changeset 15:6362d3854bb4 libtomcrypt-orig

0.96 release of LibTomCrypt
author Matt Johnston <matt@ucc.asn.au>
date Tue, 15 Jun 2004 14:07:21 +0000
parents 7faae8f46238
children 09ab3354aa21 5d99163f7e32
files PLAN aes.c aes_tab.c base64.c base64_decode.c base64_encode.c cbc_decrypt.c cbc_getiv.c cbc_setiv.c cfb_getiv.c cfb_setiv.c changes crypt.c crypt.out crypt.pdf crypt.tex crypt_hash_descriptor.c ctr_getiv.c ctr_setiv.c demos/small.c demos/test.c demos/test/base64_test.c demos/test/cipher_hash_test.c demos/test/dh_tests.c demos/test/dsa_test.c demos/test/ecc_test.c demos/test/mac_test.c demos/test/makefile demos/test/makefile.icc demos/test/makefile.msvc demos/test/modes_test.c demos/test/pkcs_1_test.c demos/test/rsa_test.c demos/test/store_test.c demos/test/test.c demos/test/test.h doc/crypt.pdf ecb_decrypt.c error_to_string.c gf.c keyring.c ltc_tommath.h makefile makefile.cygwin_dll makefile.icc makefile.msvc md2.c md4.c md5.c modes_test.c mpi.c mpi_to_ltc_error.c mycrypt.h mycrypt_cipher.h mycrypt_custom.h mycrypt_gf.h mycrypt_hash.h mycrypt_pk.h mycrypt_pkcs.h ocb_decrypt.c ofb_getiv.c ofb_setiv.c pkcs_1_oaep_decode.c pkcs_1_oaep_encode.c pkcs_1_pss_decode.c pkcs_1_pss_encode.c pkcs_1_v15_es_decode.c pkcs_1_v15_es_encode.c pkcs_1_v15_sa_decode.c pkcs_1_v15_sa_encode.c rand_prime.c rmd128.c rmd160.c rsa.c rsa_decrypt_key.c rsa_encrypt_key.c rsa_export.c rsa_exptmod.c rsa_import.c rsa_make_key.c rsa_sign_hash.c rsa_sys.c rsa_verify_hash.c sha1.c sha224.c sha256.c sha384.c sha512.c strings.c tiger.c tim_exptmod.c tommath.h whirl.c yarrow.c
diffstat 94 files changed, 4142 insertions(+), 3920 deletions(-) [+]
line wrap: on
line diff
--- a/PLAN	Mon May 31 18:25:41 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-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???
--- a/aes.c	Mon May 31 18:25:41 2004 +0000
+++ b/aes.c	Tue Jun 15 14:07:21 2004 +0000
@@ -30,16 +30,20 @@
 
 #ifdef RIJNDAEL
 
+#ifndef ENCRYPT_ONLY 
+
+#define SETUP    rijndael_setup
+#define ECB_ENC  rijndael_ecb_encrypt
+#define ECB_DEC  rijndael_ecb_decrypt
+#define ECB_TEST rijndael_test
+#define ECB_KS   rijndael_keysize
+
 const struct _cipher_descriptor rijndael_desc =
 {
     "rijndael",
     6,
     16, 32, 16, 10,
-    &rijndael_setup,
-    &rijndael_ecb_encrypt,
-    &rijndael_ecb_decrypt,
-    &rijndael_test,
-    &rijndael_keysize
+    SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_KS
 };
 
 const struct _cipher_descriptor aes_desc =
@@ -47,21 +51,63 @@
     "aes",
     6,
     16, 32, 16, 10,
-    &rijndael_setup,
-    &rijndael_ecb_encrypt,
-    &rijndael_ecb_decrypt,
-    &rijndael_test,
-    &rijndael_keysize
+    SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_KS
 };
 
+#else
+
+#define SETUP    rijndael_enc_setup
+#define ECB_ENC  rijndael_enc_ecb_encrypt
+#define ECB_KS   rijndael_enc_keysize
+
+const struct _cipher_descriptor rijndael_enc_desc =
+{
+    "rijndael",
+    6,
+    16, 32, 16, 10,
+    SETUP, ECB_ENC, NULL, NULL, ECB_KS
+};
+
+const struct _cipher_descriptor aes_enc_desc =
+{
+    "aes",
+    6,
+    16, 32, 16, 10,
+    SETUP, ECB_ENC, NULL, NULL, ECB_KS
+};
+
+#endif
+
 #include "aes_tab.c"
 
-int rijndael_setup(const unsigned char *key, int keylen, int rounds, symmetric_key *skey)
+static ulong32 setup_mix(ulong32 temp)
+{
+   return (Te4_3[byte(temp, 2)]) ^
+          (Te4_2[byte(temp, 1)]) ^
+          (Te4_1[byte(temp, 0)]) ^
+          (Te4_0[byte(temp, 3)]);
+}
+
+#ifndef ENCRYPT_ONLY
+
+static ulong32 setup_mix2(ulong32 temp)
+{
+   return Td0(255 & Te4[byte(temp, 3)]) ^
+          Td1(255 & Te4[byte(temp, 2)]) ^
+          Td2(255 & Te4[byte(temp, 1)]) ^
+          Td3(255 & Te4[byte(temp, 0)]);
+}
+
+#endif
+
+int SETUP(const unsigned char *key, int keylen, int rounds, symmetric_key *skey)
 {
     int i, j;
-    ulong32 temp, *rk, *rrk;
-    
-    _ARGCHK(key != NULL);
+    ulong32 temp, *rk;
+#ifndef ENCRYPT_ONLY
+    ulong32 *rrk;
+#endif    
+    _ARGCHK(key  != NULL);
     _ARGCHK(skey != NULL);
     
     if (keylen != 16 && keylen != 24 && keylen != 32) {
@@ -85,12 +131,7 @@
         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[4] = rk[0] ^ setup_mix(temp) ^ rcon[i];
             rk[5] = rk[1] ^ rk[4];
             rk[6] = rk[2] ^ rk[5];
             rk[7] = rk[3] ^ rk[6];
@@ -109,12 +150,7 @@
         #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[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
             rk[ 7] = rk[ 1] ^ rk[ 6];
             rk[ 8] = rk[ 2] ^ rk[ 7];
             rk[ 9] = rk[ 3] ^ rk[ 8];
@@ -137,12 +173,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[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
             rk[ 9] = rk[ 1] ^ rk[ 8];
             rk[10] = rk[ 2] ^ rk[ 9];
             rk[11] = rk[ 3] ^ rk[10];
@@ -150,11 +181,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[12] = rk[ 4] ^ setup_mix(ROR(temp, 8));
             rk[13] = rk[ 5] ^ rk[12];
             rk[14] = rk[ 6] ^ rk[13];
             rk[15] = rk[ 7] ^ rk[14];
@@ -164,7 +191,8 @@
        /* this can't happen */
        j = 4;
     }
-    
+
+#ifndef ENCRYPT_ONLY    
     /* setup the inverse key now */
     rk   = skey->rijndael.dK;
     rrk  = skey->rijndael.eK + j - 4; 
@@ -182,29 +210,13 @@
         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)]);
+        rk[0] = setup_mix2(temp);
         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)]);
+        rk[1] = setup_mix2(temp);
         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)]);
+        rk[2] = setup_mix2(temp);
         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)]);
+        rk[3] = setup_mix2(temp);
      #else
         temp = rrk[0];
         rk[0] =
@@ -241,6 +253,7 @@
     *rk++ = *rrk++;
     *rk++ = *rrk++;
     *rk   = *rrk;
+#endif /* ENCRYPT_ONLY */
 
     return CRYPT_OK;   
 }
@@ -248,7 +261,7 @@
 #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)
+void ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
 #endif
 {
     ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
@@ -270,6 +283,44 @@
     LOAD32H(s2, pt  +  8); s2 ^= rk[2];
     LOAD32H(s3, pt  + 12); s3 ^= rk[3];
 
+
+#ifdef SMALL_CODE
+
+    for (r = 0; ; r++) {
+        rk += 4;
+        t0 =
+            Te0(byte(s0, 3)) ^
+            Te1(byte(s1, 2)) ^
+            Te2(byte(s2, 1)) ^
+            Te3(byte(s3, 0)) ^
+            rk[0];
+        t1 =
+            Te0(byte(s1, 3)) ^
+            Te1(byte(s2, 2)) ^
+            Te2(byte(s3, 1)) ^
+            Te3(byte(s0, 0)) ^
+            rk[1];
+        t2 =
+            Te0(byte(s2, 3)) ^
+            Te1(byte(s3, 2)) ^
+            Te2(byte(s0, 1)) ^
+            Te3(byte(s1, 0)) ^
+            rk[2];
+        t3 =
+            Te0(byte(s3, 3)) ^
+            Te1(byte(s0, 2)) ^
+            Te2(byte(s1, 1)) ^
+            Te3(byte(s2, 0)) ^
+            rk[3];
+        if (r == Nr-2) { 
+           break;
+        }
+        s0 = t0; s1 = t1; s2 = t2; s3 = t3;
+    }
+    rk += 4;
+
+#else
+
     /*
      * Nr - 1 full rounds:
      */
@@ -330,52 +381,57 @@
             Te3(byte(t2, 0)) ^
             rk[3];
     }
+
+#endif
+
     /*
      * 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]) ^
+        (Te4_3[byte(t0, 3)]) ^
+        (Te4_2[byte(t1, 2)]) ^
+        (Te4_1[byte(t2, 1)]) ^
+        (Te4_0[byte(t3, 0)]) ^
         rk[0];
     STORE32H(s0, ct);
     s1 =
-        (Te4_3[(t1 >> 24)       ]) ^
-        (Te4_2[(t2 >> 16) & 0xff]) ^
-        (Te4_1[(t3 >>  8) & 0xff]) ^
-        (Te4_0[(t0      ) & 0xff]) ^
+        (Te4_3[byte(t1, 3)]) ^
+        (Te4_2[byte(t2, 2)]) ^
+        (Te4_1[byte(t3, 1)]) ^
+        (Te4_0[byte(t0, 0)]) ^
         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]) ^
+        (Te4_3[byte(t2, 3)]) ^
+        (Te4_2[byte(t3, 2)]) ^
+        (Te4_1[byte(t0, 1)]) ^
+        (Te4_0[byte(t1, 0)]) ^
         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]) ^ 
+        (Te4_3[byte(t3, 3)]) ^
+        (Te4_2[byte(t0, 2)]) ^
+        (Te4_1[byte(t1, 1)]) ^
+        (Te4_0[byte(t2, 0)]) ^ 
         rk[3];
     STORE32H(s3, ct+12);
 }
 
 #ifdef CLEAN_STACK
-void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) 
+void ECB_ENC(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
 
+#ifndef ENCRYPT_ONLY 
+
 #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)
+void ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
 #endif
 {
     ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
@@ -397,6 +453,42 @@
     LOAD32H(s2, ct  +  8); s2 ^= rk[2];
     LOAD32H(s3, ct  + 12); s3 ^= rk[3];
 
+#ifdef SMALL_CODE
+    for (r = 0; ; r++) {
+        rk += 4;
+        t0 =
+            Td0(byte(s0, 3)) ^
+            Td1(byte(s3, 2)) ^
+            Td2(byte(s2, 1)) ^
+            Td3(byte(s1, 0)) ^
+            rk[0];
+        t1 =
+            Td0(byte(s1, 3)) ^
+            Td1(byte(s0, 2)) ^
+            Td2(byte(s3, 1)) ^
+            Td3(byte(s2, 0)) ^
+            rk[1];
+        t2 =
+            Td0(byte(s2, 3)) ^
+            Td1(byte(s1, 2)) ^
+            Td2(byte(s0, 1)) ^
+            Td3(byte(s3, 0)) ^
+            rk[2];
+        t3 =
+            Td0(byte(s3, 3)) ^
+            Td1(byte(s2, 2)) ^
+            Td2(byte(s1, 1)) ^
+            Td3(byte(s0, 0)) ^
+            rk[3];
+        if (r == Nr-2) {
+           break; 
+        }
+        s0 = t0; s1 = t1; s2 = t2; s3 = t3;
+    }
+    rk += 4;
+
+#else       
+
     /*
      * Nr - 1 full rounds:
      */
@@ -459,51 +551,52 @@
             Td3(byte(t0, 0)) ^
             rk[3];
     }
+#endif
 
     /*
      * 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) ^
+        (Td4[byte(t0, 3)] & 0xff000000) ^
+        (Td4[byte(t3, 2)] & 0x00ff0000) ^
+        (Td4[byte(t2, 1)] & 0x0000ff00) ^
+        (Td4[byte(t1, 0)] & 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) ^
+        (Td4[byte(t1, 3)] & 0xff000000) ^
+        (Td4[byte(t0, 2)] & 0x00ff0000) ^
+        (Td4[byte(t3, 1)] & 0x0000ff00) ^
+        (Td4[byte(t2, 0)] & 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) ^
+        (Td4[byte(t2, 3)] & 0xff000000) ^
+        (Td4[byte(t1, 2)] & 0x00ff0000) ^
+        (Td4[byte(t0, 1)] & 0x0000ff00) ^
+        (Td4[byte(t3, 0)] & 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) ^
+        (Td4[byte(t3, 3)] & 0xff000000) ^
+        (Td4[byte(t2, 2)] & 0x00ff0000) ^
+        (Td4[byte(t1, 1)] & 0x0000ff00) ^
+        (Td4[byte(t0, 0)] & 0x000000ff) ^
         rk[3];
     STORE32H(s3, pt+12);
 }
 
 
 #ifdef CLEAN_STACK
-void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) 
+void ECB_DEC(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)
+int ECB_TEST(void)
 {
  #ifndef LTC_TEST
     return CRYPT_NOP;
@@ -584,7 +677,9 @@
  #endif
 }
 
-int rijndael_keysize(int *desired_keysize)
+#endif /* ENCRYPT_ONLY */
+
+int ECB_KS(int *desired_keysize)
 {
    _ARGCHK(desired_keysize != NULL);
 
--- a/aes_tab.c	Mon May 31 18:25:41 2004 +0000
+++ b/aes_tab.c	Tue Jun 15 14:07:21 2004 +0000
@@ -157,6 +157,8 @@
     0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL,
 };
 
+#ifndef ENCRYPT_ONLY
+
 static const ulong32 TD0[256] = {
     0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL,
     0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL,
@@ -291,6 +293,8 @@
     0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL,
 };
 
+#endif /* ENCRYPT_ONLY */
+
 #ifdef SMALL_CODE
 
 #define Te0(x) TE0[x]
@@ -660,6 +664,8 @@
 0x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL
 };
 
+#ifndef ENCRYPT_ONLY
+
 static const ulong32 TD1[256] = {
     0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL,
     0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL,
@@ -999,6 +1005,8 @@
 0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL
 };
 
+#endif /* ENCRYPT_ONLY */
+
 #endif /* SMALL CODE */
 
 static const ulong32 rcon[] = {
--- a/base64.c	Mon May 31 18:25:41 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/* 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/base64_decode.c	Tue Jun 15 14:07:21 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
+ */
+
+/* compliant base64 code donated by Wayne Scott ([email protected]) */
+#include "mycrypt.h"
+
+#ifdef BASE64
+
+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_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/base64_encode.c	Tue Jun 15 14:07:21 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
+ */
+/* compliant base64 code donated by Wayne Scott ([email protected]) */
+#include "mycrypt.h"
+
+#ifdef BASE64
+
+static const char *codes = 
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+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;
+}
+
+#endif
+
--- a/cbc_decrypt.c	Mon May 31 18:25:41 2004 +0000
+++ b/cbc_decrypt.c	Tue Jun 15 14:07:21 2004 +0000
@@ -25,14 +25,15 @@
    if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
        return err;
    }
-   cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key);
-   
+   _ARGCHK(cipher_descriptor[cbc->cipher].ecb_decrypt != NULL);
+      
    /* 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 */
+   /* decrypt and xor IV against the plaintext of the previous step */
+   cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key);
    for (x = 0; x < cbc->blocklen; x++) { 
        /* copy CT in case ct == pt */
        tmp2[x] = ct[x]; 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cbc_getiv.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,30 @@
+/* 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_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc)
+{
+   _ARGCHK(IV  != NULL);
+   _ARGCHK(len != NULL);
+   _ARGCHK(cbc != NULL);
+   if ((unsigned long)cbc->blocklen > *len) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+   memcpy(IV, cbc->IV, cbc->blocklen);
+   *len = cbc->blocklen;
+
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cbc_setiv.c	Tue Jun 15 14:07:21 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"
+
+#ifdef CBC
+
+int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc)
+{
+   _ARGCHK(IV  != NULL);
+   _ARGCHK(cbc != NULL);
+   if (len != (unsigned long)cbc->blocklen) {
+      return CRYPT_INVALID_ARG;
+   }
+   memcpy(cbc->IV, IV, len);
+   return CRYPT_OK;
+}
+
+#endif 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cfb_getiv.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,30 @@
+/* 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_getiv(unsigned char *IV, unsigned long *len, symmetric_CFB *cfb)
+{
+   _ARGCHK(IV  != NULL);
+   _ARGCHK(len != NULL);
+   _ARGCHK(cfb != NULL);
+   if ((unsigned long)cfb->blocklen > *len) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+   memcpy(IV, cfb->IV, cfb->blocklen);
+   *len = cfb->blocklen;
+
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cfb_setiv.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,39 @@
+/* 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_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb)
+{
+   int err;
+   
+   _ARGCHK(IV  != NULL);
+   _ARGCHK(cfb != NULL);
+
+   if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) {
+       return err;
+   }
+   
+   if (len != (unsigned long)cfb->blocklen) {
+      return CRYPT_INVALID_ARG;
+   }
+      
+   /* force next block */
+   cfb->padlen = 0;
+   cipher_descriptor[cfb->cipher].ecb_encrypt(IV, cfb->IV, &cfb->key);
+
+   return CRYPT_OK;
+}
+
+#endif 
+
--- a/changes	Mon May 31 18:25:41 2004 +0000
+++ b/changes	Tue Jun 15 14:07:21 2004 +0000
@@ -1,3 +1,28 @@
+May 30th, 2004
+v0.96  -- Removed GF and Keyring code
+       -- Extended OAEP decoder to distinguish better [and use a more uniform API]
+       -- Changed PSS/OAEP API slightly to be more consistent with other PK functions (order of arguments)
+       -- rsa_exptmod() now pads with leading zeroes as per I2OSP.
+       -- added error checking to yarrow code
+       -- Mike Frysinger pointed out that tommath.h from this distro will overwrite tommath.h
+          from libtommath.  I changed this to ltc_tommath.h to avoid any such problems.
+       -- Fixed bug in PSS encoder/decoder that didn't handle the MSB properly
+       -- refactored AES, now sports an "encrypt only" descriptor which uses half as much code space.
+       -- modded Yarrow to try and use refactored AES code and added WHIRLPOOL support (d'oh) ;-)
+       -- updated ECB, OCB and CBC decrypt functions to detect when "encrypt only" descriptor is used.
+       -- replaced old RSA code with new code that uses PKCS #1 v2.0 padding
+       -- replaced old test harness with new over-engineer'ed one in /demos/test/
+       -- updated cbc/cfb/ofb/ctr code with setiv/getiv functions to change/read the IV without re-keying.
+       -- Added PKCS #1 v1.5 RSA encryption and signature padding routines
+       -- Added DER OID's to most hash descriptors (as many as I could find) 
+       -- modded rsa_exptmod() to use timing-resilient tim_exptmod() when doing private key operations 
+          added #define RSA_TIMING which can turn on/off this feature.
+       -- No more config.pl so please just read mycrypt_custom.h for build-time tweaks
+       -- Small update to rand_prime()
+       -- Updated sha1, md5 and sha256 so they are smaller when SMALL_CODE is defined.  If you want speed though,
+          you're going to have to undefine SMALL_CODE ;-)
+       -- Worked over AES so that it's even smaller now [in both modes].
+       
 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
--- a/crypt.c	Mon May 31 18:25:41 2004 +0000
+++ b/crypt.c	Tue Jun 15 14:07:21 2004 +0000
@@ -120,6 +120,9 @@
 #if defined(RIPEMD160)
    "   RIPEMD160\n"
 #endif
+#if defined(WHIRLPOOL)
+   "   WHIRLPOOL\n"
+#endif
 
     "\nBlock Chaining Modes:\n"
 #if defined(CFB)
@@ -151,7 +154,11 @@
 
     "\nPK Algs:\n"
 #if defined(MRSA)
-    "   RSA\n"
+    "   RSA"
+#if defined(RSA_TIMING)
+    " + RSA_TIMING "
+#endif
+    "\n"
 #endif
 #if defined(MDH)
     "   DH\n"
@@ -162,9 +169,6 @@
 #if defined(MDSA)
     "   DSA\n"
 #endif
-#if defined(KR)
-    "   KR\n"
-#endif
 
     "\nCompiler:\n"
 #if defined(WIN32)
@@ -187,9 +191,6 @@
 #endif
 
     "\nVarious others: "
-#if defined(GF)
-    " GF "
-#endif
 #if defined(BASE64)
     " BASE64 "
 #endif
@@ -223,6 +224,15 @@
 #if defined(PKCS_5)
     " PKCS#5 "
 #endif
+#if defined(SMALL_CODE)
+    " SMALL_CODE "
+#endif
+#if defined(NO_FILE)
+    " NO_FILE "
+#endif
+#if defined(LTC_TEST)
+    " LTC_TEST "
+#endif
     "\n"
     "\n\n\n"
     ;
--- a/crypt.out	Mon May 31 18:25:41 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-\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
--- a/crypt.tex	Mon May 31 18:25:41 2004 +0000
+++ b/crypt.tex	Tue Jun 15 14:07:21 2004 +0000
@@ -47,7 +47,7 @@
 \def\gap{\vspace{0.5ex}}
 \makeindex
 \begin{document}
-\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.95}
+\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.96}
 \author{Tom St Denis \\
 \\
 [email protected] \\
@@ -103,7 +103,8 @@
 
 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
+These routines are fully portable but are not conformant to any known set of standards\footnote{With the exception of 
+the RSA code which is based on the PKCS \#1 standards.}.  They are all based on established
 number theory and cryptography.  
 
 \subsection{What the library IS NOT for?}
@@ -241,19 +242,20 @@
 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
 
+\index{error\_to\_string()}
 \begin{verbatim}
-const char *error_to_string(int errno);
+const char *error_to_string(int err);
 \end{verbatim}
 
 An example of handling an error is:
 \begin{verbatim}
 void somefunc(void)
 {
-   int errno;
+   int err;
    
    /* call a cryptographic function */
-   if ((errno = some_crypto_function(...)) != CRYPT_OK) {
-      printf("A crypto error occured, %s\n", error_to_string(errno));
+   if ((err = some_crypto_function(...)) != CRYPT_OK) {
+      printf("A crypto error occured, %s\n", error_to_string(err));
       /* perform error handling */
    }
    /* continue on if no error occured */
@@ -320,14 +322,14 @@
     rsa_key key;
     unsigned char buffer[1024];
     unsigned long x;
-    int errno;
+    int err;
 
     /* ... 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));
+    if ((err = rsa_export(buffer, &x, PK_PUBLIC, &key)) != CRYPT_OK) {
+       printf("Export error: %s\n", error_to_string(err));
        return -1;
     }
     
@@ -411,12 +413,12 @@
 #include <mycrypt.h>
 int main(void)
 {
-   int keysize, errno;
+   int keysize, err;
 
    /* 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));
+   if ((err = twofish_keysize(&keysize)) != CRYPT_OK) {
+      printf("Error getting key size: %s\n", error_to_string(err));
       return -1;
    }
    printf("Twofish suggested a key size of %d\n", keysize);
@@ -434,22 +436,30 @@
 { 
    unsigned char pt[8], ct[8], key[8];
    symmetric_key skey;
-   int errno;
+   int err;
 
    /* ... 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));
+   if ((err = blowfish_setup(key,     /* the key we will use */
+                               8,     /* key is 8 bytes (64-bits) long */
+                               0,     /* 0 == use default # of rounds */
+                           &skey)     /* where to put the scheduled key */
+       ) != CRYPT_OK) {
+      printf("Setup error: %s\n", error_to_string(err));
       return -1;
    }
 
    /* encrypt the block */
-   blowfish_ecb_encrypt(pt, ct, &skey);
+   blowfish_ecb_encrypt(pt,             /* encrypt this 8-byte array */
+                        ct,             /* store encrypted data here */ 
+                        &skey);         /* our previously scheduled key */
 
    /* decrypt the block */
-   blowfish_ecb_decrypt(ct, pt, &skey);
+   blowfish_ecb_decrypt(ct,             /* decrypt this 8-byte array */
+                        pt,             /* store decrypted data here */
+                        &skey);         /* our previously scheduled key */
 
    return 0;
 }
@@ -501,6 +511,7 @@
 
 As of this release the current cipher\_descriptors elements are
 
+\index{Cipher descriptor table}
 \begin{small}
 \begin{center}
 \begin{tabular}{|c|c|c|c|c|c|}
@@ -516,6 +527,7 @@
      \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 \\
+                & aes\_enc\_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 \\
@@ -528,14 +540,32 @@
 \end{small}
 
 \subsection{Notes}
+\begin{small}
+\begin{enumerate}
+\item
+For AES (also known as Rijndael) there are four descriptors which complicate issues a little.  The descriptors 
+rijndael\_desc and rijndael\_enc\_desc provide the cipher named ``rijndael''.  The descriptors aes\_desc and 
+aes\_enc\_desc provide the cipher name ``aes''.  Functionally both ``rijndael'' and ``aes'' are the same cipher.  The
+only difference is when you call find\_cipher() you have to pass the correct name.  The cipher descriptors with ``enc'' 
+in the middle (e.g. rijndael\_enc\_desc) are related to an implementation of Rijndael with only the encryption routine
+and tables.  The decryption and self--test function pointers of both ``encrypt only'' descriptors are set to \textbf{NULL} and 
+should not be called.
+
+The ``encrypt only'' descriptors are useful for applications that only use the encryption function of the cipher.  Algorithms such
+as EAX, PMAC and OMAC only require the encryption function.  So far this ``encrypt only'' functionality has only been implemented for
+Rijndael as it makes the most sense for this cipher.
+
+\item
 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.
 
+\item
 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.
 
+\item
 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
@@ -545,6 +575,7 @@
 speed increase is useful when ``TWOFISH\_SMALL'' is defined since the s-boxes and MDS multiply form the heart of the
 Twofish round function.
 
+\index{Twofish build options}
 \begin{small}
 \begin{center}
 \begin{tabular}{|l|l|l|}
@@ -558,7 +589,11 @@
 \end{center}
 \end{small}
 
+\end{enumerate}
+\end{small}
+
 To work with the cipher\_descriptor array there is a function:
+\index{find\_cipher()}
 \begin{verbatim}
 int find_cipher(char *name)
 \end{verbatim}
@@ -571,7 +606,7 @@
 {
    unsigned char key[8];
    symmetric_key skey;
-   int errno;
+   int err;
 
    /* you must register a cipher before you use it */
    if (register_cipher(&blowfish_desc)) == -1) {
@@ -580,8 +615,8 @@
    }
 
    /* 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));
+   if ((err = cipher_descriptor[find_cipher("blowfish")].setup(key, 8, 0, &skey)) != CRYPT_OK) {
+      printf("Error setting up Blowfish: %s\n", error_to_string(err));
       return -1;
    }
 
@@ -592,12 +627,14 @@
 
 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:
+\index{register\_cipher()}
 \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:
+\index{unregister\_cipher()}
 \begin{verbatim}
 int unregister_cipher(const struct _cipher_descriptor *cipher);
 \end{verbatim}
@@ -607,7 +644,7 @@
 #include <mycrypt.h>
 int main(void)
 {
-   int errno;
+   int err;
    
    /* register the cipher */
    if (register_cipher(&rijndael_desc) == -1) {
@@ -618,8 +655,8 @@
    /* use Rijndael */
 
    /* remove it */
-   if ((errno = unregister_cipher(&rijndael_desc)) != CRYPT_OK) {
-      printf("Error removing Rijndael: %s\n", error_to_string(errno));
+   if ((err = unregister_cipher(&rijndael_desc)) != CRYPT_OK) {
+      printf("Error removing Rijndael: %s\n", error_to_string(err));
       return -1;
    }
 
@@ -636,6 +673,7 @@
 $P$ under the key $k$ as $E_k(P)$.  In some modes there exists an initial vector denoted as $C_{-1}$.
 
 \subsubsection{ECB Mode}
+\index{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)
@@ -644,6 +682,7 @@
 than once.
 
 \subsubsection{CBC Mode}
+\index{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}
@@ -652,6 +691,7 @@
 It is important that the initial vector be unique and preferably random for each message encrypted under the same key.
 
 \subsubsection{CTR Mode}
+\index{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}
@@ -663,6 +703,7 @@
 as the block cipher is under a chosen plaintext attack (provided the initial vector is unique).
 
 \subsubsection{CFB Mode}
+\index{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 \\
@@ -673,6 +714,7 @@
 blocks without a delay.  When this mode is first setup it will initially encrypt the initial vector as required.
 
 \subsubsection{OFB Mode}
+\index{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 \\
@@ -703,6 +745,7 @@
 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):
+\index{ecb\_start()} \index{cfb\_start()} \index{cbc\_start()} \index{ofb\_start()} \index{ctr\_start()}
 \begin{verbatim}
 int XXX_start(int cipher, const unsigned char *IV, 
               const unsigned char *key, int keylen, 
@@ -721,6 +764,8 @@
 
 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:
+\index{ecb\_encrypt()} \index{ecb\_decrypt()} \index{cfb\_encrypt()} \index{cfb\_decrypt()} 
+\index{cbc\_encrypt()} \index{cbc\_decrypt()} \index{ofb\_encrypt()} \index{ofb\_decrypt()} \index{ctr\_encrypt()} \index{ctr\_decrypt()}
 \begin{verbatim}
 int XXX_encrypt(const unsigned char *pt, unsigned char *ct, 
                 symmetric_XXX *XXX);
@@ -739,8 +784,23 @@
 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:
+and use the decrypt routine on all of the blocks.
+
+To change or read the IV of a previously initialized chaining mode use the following two functions.
+
+\index{cbc\_setiv()} \index{cbc\_getiv()} \index{ofb\_setiv()} \index{ofb\_getiv()} \index{cfb\_setiv()} \index{cfb\_getiv()}
+\index{ctr\_setiv()} \index{ctr\_getiv()}
+\begin{verbatim}
+int XXX_getiv(unsigned char *IV, unsigned long *len, symmetric_XXX *XXX);
+int XXX_setiv(const unsigned char *IV, unsigned long len, symmetric_XXX *XXX);
+\end{verbatim}
+
+The XXX\_getiv function will read the IV out of the chaining mode and store it into ``IV'' along with the length of the IV 
+stored in ``len''.  The XXX\_setiv will initialize the chaining mode state as if the original IV were the new IV specified.  The length
+of the IV passed in must be the size of the ciphers block size.
+
+The XXX\_setiv functions are handy if you wish to change the IV without re--keying the cipher.  
+
 \newpage
 \begin{small}
 \begin{verbatim}
@@ -749,7 +809,7 @@
 {
    unsigned char key[16], IV[16], buffer[512];
    symmetric_CTR ctr;
-   int x, errno;
+   int x, err;
 
    /* register twofish first */
    if (register_cipher(&twofish_desc) == -1) {
@@ -760,19 +820,47 @@
    /* 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));
+   if ((err = ctr_start(find_cipher("twofish"), /* index of desired cipher */
+                                            IV, /* the initial vector */
+                                           key, /* the secret key */
+                                            16, /* length of secret key (16 bytes, 128 bits) */
+                                             0, /* 0 == default # of rounds */
+                                         &ctr)  /* where to store initialized CTR state */
+      ) != CRYPT_OK) {
+      printf("ctr_start error: %s\n", error_to_string(err));
       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));
+   if ((err = ctr_encrypt(        buffer, /* plaintext */
+                                  buffer, /* ciphertext */
+                          sizeof(buffer), /* length of data to encrypt */
+                                   &ctr)  /* previously initialized CTR state */
+      ) != CRYPT_OK) {
+      printf("ctr_encrypt error: %s\n", error_to_string(err));
       return -1;
    }
 
    /* make use of ciphertext... */
 
+   /* now we want to decrypt so let's use ctr_setiv */
+   if ((err = ctr_setiv(  IV, /* the initial IV we gave to ctr_start */
+                          16, /* the IV is 16 bytes long */
+                        &ctr) /* the ctr state we wish to modify */
+       ) != CRYPT_OK) {
+      printf("ctr_setiv error: %s\n", error_to_string(err));
+      return -1;
+   }
+
+   if ((err = ctr_decrypt(        buffer, /* ciphertext */
+                                  buffer, /* plaintext */
+                          sizeof(buffer), /* length of data to encrypt */
+                                   &ctr)  /* previously initialized CTR state */
+      ) != CRYPT_OK) {
+      printf("ctr_decrypt error: %s\n", error_to_string(err));
+      return -1;
+   }
+
    /* clear up and return */
    zeromem(key, sizeof(key));
    zeromem(&ctr, sizeof(ctr));
@@ -787,15 +875,14 @@
 \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.
+way it was intended to be used by the designers.  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\footnote{Note that since EAX only requires OMAC and CTR you may use ``encrypt only'' cipher descriptors with this mode.}.  
+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.
+be detected by changes in the 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
@@ -803,6 +890,7 @@
 of operation.
 
 The mode is initialized with the following function.
+\index{eax\_init()}
 \begin{verbatim}
 int eax_init(eax_state *eax, int cipher, 
              const unsigned char *key, unsigned long keylen,
@@ -816,10 +904,11 @@
 ``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.  
+encrypted in EAX mode.  Note that if ``headerlen'' is zero you may pass ``header'' as \textbf{NULL} to indicate
+there is no initial header data.
 
 To encrypt or decrypt data in a streaming mode use the following.
+\index{eax\_encrypt()} \index{eax\_decrypt()}
 \begin{verbatim}
 int eax_encrypt(eax_state *eax, const unsigned char *pt, 
                 unsigned char *ct, unsigned long length);
@@ -832,13 +921,14 @@
 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.  
 
+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).  
+
 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).  
-
+\index{eax\_addheader()}
 \begin{verbatim}
 int eax_addheader(eax_state *eax, 
                   const unsigned char *header, unsigned long length);
@@ -847,6 +937,7 @@
 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.
 
+\index{eax\_done()}
 \begin{verbatim}
 int eax_done(eax_state *eax, 
              unsigned char *tag, unsigned long *taglen);
@@ -855,19 +946,102 @@
 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.
+\index{eax\_test()}
 \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.
 
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   int           err;
+   eax_state     eax;
+   unsigned char pt[64], ct[64], nonce[16], key[16], tag[16];
+   unsigned long taglen;
+
+   if (register_cipher(&rijndael_desc) == -1) {
+      printf("Error registering Rijndael");
+      return EXIT_FAILURE;
+   }
+
+   /* ... make up random nonce and key ... */
+
+   /* initialize context */
+   if ((err = eax_init(            &eax,  /* the context */
+                find_cipher("rijndael"),  /* cipher we want to use */
+                                  nonce,  /* our state nonce */
+                                     16,  /* none is 16 bytes */
+                              "TestApp",  /* example header, identifies this program */
+                                      7)  /* length of the header */
+       ) != CRYPT_OK) {
+      printf("Error eax_init: %s", error_to_string(err));
+      return EXIT_FAILURE;
+   }
+
+   /* now encrypt data, say in a loop or whatever */
+   if ((err = eax_encrypt(     &eax,      /* eax context */
+                                 pt,      /* plaintext  (source) */
+                                 ct,      /* ciphertext (destination) */
+                          sizeof(pt)      /* size of plaintext */
+      ) != CRYPT_OK) {
+      printf("Error eax_encrypt: %s", error_to_string(err));
+      return EXIT_FAILURE;
+   }
+
+   /* finish message and get authentication tag */
+   taglen = sizeof(tag);
+   if ((err = eax_done(   &eax,           /* eax context */
+                           tag,           /* where to put tag */
+                       &taglen            /* length of tag space */
+      ) != CRYPT_OK) {
+      printf("Error eax_done: %s", error_to_string(err));
+      return EXIT_FAILURE;
+   }
+
+   /* now we have the authentication tag in "tag" and it's taglen bytes long */
+
+}
+\end{verbatim}
+                       
+You can also perform an entire EAX state on a block of memory in a single function call with the 
+following functions.
+
+
+\index{eax\_encrypt\_authenticate\_memory} \index{eax\_decrypt\_verify\_memory}
+\begin{verbatim}
+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 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);
+\end{verbatim}
+
+Both essentially just call eax\_init() followed by eax\_encrypt() (or eax\_decrypt() respectively) and eax\_done().  The parameters
+have the same meaning as with those respective functions.  
+
+The only difference is eax\_decrypt\_verify\_memory() does not emit a tag.  Instead you pass it a tag as input and it compares it against
+the tag it computed while decrypting the message.  If the tags match then it stores a $1$ in ``res'', otherwise it stores a $0$.
+
 \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
+.  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.
 
+\index{ocb\_init()}
 \begin{verbatim}
 int ocb_init(ocb_state *ocb, int cipher, 
              const unsigned char *key, unsigned long keylen, 
@@ -876,11 +1050,12 @@
 
 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).
+block size (e.g. 16 bytes 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.
 
+\index{ocb\_encrypt()} \index{ocb\_decrypt()}
 \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);
@@ -893,6 +1068,7 @@
 
 When you are finished encrypting the message you call the following function to compute the tag.
 
+\index{ocb\_done\_encrypt()}
 \begin{verbatim}
 int ocb_done_encrypt(ocb_state *ocb, 
                      const unsigned char *pt, unsigned long ptlen,
@@ -909,6 +1085,7 @@
 
 To terminate a decrypt stream and compared the tag you call the following.
 
+\index{ocb\_done\_decrypt()}
 \begin{verbatim}
 int ocb_done_decrypt(ocb_state *ocb, 
                      const unsigned char *ct,  unsigned long ctlen,
@@ -924,6 +1101,7 @@
 
 To make life simpler the following two functions are provided for memory bound OCB.
 
+\index{ocb\_encrypt\_authenticate\_memory()}
 \begin{verbatim}
 int ocb_encrypt_authenticate_memory(int cipher,
     const unsigned char *key,    unsigned long keylen,
@@ -936,6 +1114,7 @@
 This will OCB encrypt the message ``pt'' of length ``ptlen'' and store the ciphertext in ``ct''.  The length ``ptlen''
 can be any arbitrary length.  
 
+\index{ocb\_decrypt\_verify\_memory()}
 \begin{verbatim}
 int ocb_decrypt_verify_memory(int cipher,
     const unsigned char *key,    unsigned long keylen,
@@ -949,8 +1128,6 @@
 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}
 
@@ -1020,7 +1197,6 @@
 \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}
@@ -1116,7 +1292,7 @@
 #include <mycrypt.h>
 int main(void)
 {
-   int idx, errno;
+   int idx, err;
    unsigned long len;
    unsigned char out[MAXBLOCKSIZE];
 
@@ -1131,8 +1307,8 @@
 
    /* 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));
+   if ((err = hash_memory(idx, "hello world", 11, out, &len)) != CRYPT_OK) {
+      printf("Error hashing data: %s\n", error_to_string(err));
       return -1;
    }
    return 0;
@@ -1141,6 +1317,7 @@
 \end{small}
 
 The following hashes are provided as of this release:
+\index{Hash descriptor table}
 \begin{center}
 \begin{tabular}{|c|c|c|}
       \hline Name & Descriptor Name & Size of Message Digest (bytes) \\
@@ -1162,6 +1339,7 @@
 
 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:
+\index{register\_hash()} \index{unregister\_hash()}
 \begin{verbatim}
 int register_hash(const struct _hash_descriptor *hash);
 int unregister_hash(const struct _hash_descriptor *hash);
@@ -1185,6 +1363,7 @@
 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:
+\index{hmac\_init()}
 \begin{verbatim}
 int hmac_init(hmac_state *hmac, int hash, 
               const unsigned char *key, unsigned long keylen);
@@ -1192,6 +1371,7 @@
 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:
+\index{hmac\_process()}
 \begin{verbatim}
 int hmac_process(hmac_state *hmac, const unsigned char *buf,
                   unsigned long len);
@@ -1199,6 +1379,7 @@
 ``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:
+\index{hmac\_done()}
 \begin{verbatim}
 int hmac_done(hmac_state *hmac, unsigned char *hashOut,
               unsigned long *outlen);
@@ -1212,6 +1393,7 @@
 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.
 
+\index{hmac\_memory()}
 \begin{verbatim}
 int hmac_memory(int hash, const unsigned char *key, unsigned long keylen,
                 const unsigned char *data, unsigned long len, 
@@ -1221,6 +1403,7 @@
 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:
+\index{hmac\_file()}
 \begin{verbatim}
 int hmac_file(int hash, const char *fname, const unsigned char *key,
               unsigned long keylen, 
@@ -1231,6 +1414,7 @@
 result should be stored.
 
 To test if the HMAC code is working there is the following function:
+\index{hmac\_test()}
 \begin{verbatim}
 int hmac_test(void);
 \end{verbatim}
@@ -1242,7 +1426,7 @@
 #include <mycrypt.h>
 int main(void)
 {
-   int idx, errno;
+   int idx, err;
    hmac_state hmac;
    unsigned char key[16], dst[MAXBLOCKSIZE];
    unsigned long dstlen;
@@ -1259,21 +1443,21 @@
    /* 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));
+   if ((err = hmac_init(&hmac, idx, key, 16)) != CRYPT_OK) {
+      printf("Error setting up hmac: %s\n", error_to_string(err));
       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));
+   if((err = hmac_process(&hmac, "hello", 5) != CRYPT_OK) {
+      printf("Error processing hmac: %s\n", error_to_string(err));
       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));
+   if ((err = hmac_done(&hmac, dst, &dstlen)) != CRYPT_OK) {
+      printf("Error finishing hmac: %s\n", error_to_string(err));
       return -1;
    }
    printf("The hmac is %lu bytes long\n", dstlen);
@@ -1290,7 +1474,7 @@
 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
-
+\index{omac\_init()}
 \begin{verbatim}
 int omac_init(omac_state *omac, int cipher, 
               const unsigned char *key, unsigned long keylen);
@@ -1300,6 +1484,7 @@
 wish to use.  ``key'' and ``keylen'' are the keys used to authenticate the data.
 
 To send data through the algorithm call
+\index{omac\_process()}
 \begin{verbatim}
 int omac_process(omac_state *state, 
                  const unsigned char *buf, unsigned long len);
@@ -1320,6 +1505,7 @@
 
 When you are done processing the message you can call the following to compute the message tag.
 
+\index{omac\_done()}
 \begin{verbatim}
 int omac_done(omac_state *state, 
               unsigned char *out, unsigned long *outlen);
@@ -1333,6 +1519,7 @@
 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.
 
+\index{omac\_memory()}
 \begin{verbatim}
 int omac_memory(int cipher, 
                 const unsigned char *key, unsigned long keylen,
@@ -1344,6 +1531,7 @@
 rules as omac\_done.
 
 To OMAC a file use
+\index{omac\_file()}
 \begin{verbatim}
 int omac_file(int cipher, 
               const unsigned char *key, unsigned long keylen,
@@ -1356,6 +1544,7 @@
 the same rules as omac\_done.
 
 To test if the OMAC code is working there is the following function:
+\index{omac\_test()}
 \begin{verbatim}
 int omac_test(void);
 \end{verbatim}
@@ -1416,6 +1605,7 @@
 
 A PMAC state is initialized with the following.
 
+\index{pmac\_init()}
 \begin{verbatim}
 int pmac_init(pmac_state *pmac, int cipher, 
               const unsigned char *key, unsigned long keylen);
@@ -1425,6 +1615,7 @@
 
 To MAC data simply send it through the process function.
 
+\index{pmac\_process()}
 \begin{verbatim}
 int pmac_process(pmac_state *state, 
                  const unsigned char *buf, unsigned long len);
@@ -1445,6 +1636,7 @@
 
 When a complete message has been processed the following function can be called to compute the message tag.
 
+\index{pmac\_done()}
 \begin{verbatim}
 int pmac_done(pmac_state *state, 
               unsigned char *out, unsigned long *outlen);
@@ -1455,6 +1647,7 @@
 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.
 
+\index{pmac\_memory()}
 \begin{verbatim}
 int pmac_memory(int cipher, 
                 const unsigned char *key, unsigned long keylen,
@@ -1466,6 +1659,7 @@
 rules as omac\_done.
 
 To PMAC a file use
+\index{pmac\_file()}
 \begin{verbatim}
 int pmac_file(int cipher, 
               const unsigned char *key, unsigned long keylen,
@@ -1716,8 +1910,12 @@
 \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{Introduction}
+RSA wrote the PKCS \#1 specifications which detail RSA Public Key Cryptography.  In the specifications are
+padding algorithms for encryption and signatures.  The standard includes ``v1.5'' and ``v2.0'' algorithms.
+To simplify matters a little the v2.0 encryption and signature padding algorithms are called OAEP and PSS 
+respectively.  
 
 \section{PKCS \#1 Encryption}
 
@@ -1726,11 +1924,12 @@
 
 \subsection{OAEP Encoding}
 
+\index{pkcs\_1\_oaep\_encode()}
 \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 long modulus_bitlen, prng_state *prng,
+                             int           prng_idx,         int  hash_idx,
                              unsigned char *out,    unsigned long *outlen);
 \end{alltt}
 
@@ -1752,11 +1951,13 @@
 
 \subsection{OAEP Decoding}
 
+\index{pkcs\_1\_oaep\_decode()}
 \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);
+                             unsigned char *out,    unsigned long *outlen,
+                             int           *res);
 \end{alltt}
 
 This function decodes an OAEP encoded message and outputs the original message that was passed to the OAEP encoder.  ``msg'' is the 
@@ -1765,17 +1966,47 @@
 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''.  
+If the function succeeds it decodes the OAEP encoded message into ``out'' of length ``outlen'' and stores a 
+$1$ in ``res''.  If the packet is invalid it stores $0$ in ``res'' and if the function fails for another reason
+it returns an error code.  
+
+\subsection{PKCS \#1 v1.5 Encoding}
+
+\index{pkcs\_1\_v15\_es\_encode()}
+\begin{verbatim}
+int pkcs_1_v15_es_encode(const unsigned char *msg,    unsigned long msglen,
+                               unsigned long  modulus_bitlen, 
+                               prng_state    *prng,   int           prng_idx,
+                               unsigned char *out,    unsigned long *outlen);
+\end{verbatim}
+
+This will PKCS v1.5 encode the data in ``msg'' of length ``msglen''.  Pass the length (in bits) of your
+RSA modulus in ``modulus\_bitlen''.  The encoded data will be stored in ``out'' of length ``outlen''.
+
+\subsection{PKCS \#1 v1.5 Decoding}
+\index{pkcs\_1\_v15\_es\_decode()}
+\begin{verbatim}
+int pkcs_1_v15_es_decode(const unsigned char *msg,  unsigned long msglen,
+                               unsigned long modulus_bitlen,
+                               unsigned char *out,  unsigned long outlen,
+                               int           *res);
+\end{verbatim}
+
+This will PKCS v1.5 decode the message in ``msg'' of length ``msglen''.  It will store the output in ``out''. Note
+that the length of the output ``outlen'' is a constant.  This decoder cannot determine the original message 
+length.  If the data in ``msg'' is a valid packet then a $1$ is stored in ``res'', otherwise a $0$ is 
+stored.
 
 \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.  
 
+\index{pkcs\_1\_pss\_encode()}
 \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 saltlen,  prng_state   *prng,     
+                            int           prng_idx, int           hash_idx,
                             unsigned long modulus_bitlen,
                             unsigned char *out,     unsigned long *outlen);
 \end{alltt}
@@ -1785,7 +2016,7 @@
 ``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
+Similar to OAEP encoding ``modulus\_bitlen'' is the size of the RSA modulus (in bits).  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().
@@ -1794,6 +2025,7 @@
 
 To decode a PSS encoded signature block you have to use the following.
 
+\index{pkcs\_1\_pss\_decode()}
 \begin{alltt}
 int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
                       const unsigned char *sig,     unsigned long siglen,
@@ -1806,6 +2038,240 @@
 
 It's important to use the same ``saltlen'' and hash for both encoding and decoding as otherwise the procedure will not work.
 
+\subsection{PKCS \#1 v1.5 Encoding}
+
+\index{pkcs\_1\_v15\_sa\_encode()}
+\begin{verbatim}
+int pkcs_1_v15_sa_encode(const unsigned char *msghash,  unsigned long msghashlen,
+                               int            hash_idx, unsigned long modulus_bitlen,
+                               unsigned char *out,      unsigned long *outlen);
+\end{verbatim}
+
+This will PKCS \#1 v1.5 signature encode the message hash ``msghash''  of length ``msghashlen''.  You have
+to tell this routine which hash produced the message hash in ``hash\_idx''.  The encoded hash is stored
+in ``out'' of length ``outlen''.
+
+\subsection{PKCS \#1 v1.5 Decoding}
+
+\index{pkcs\_1\_v15\_sa\_decode()}
+\begin{verbatim}
+int pkcs_1_v15_sa_decode(const unsigned char *msghash, unsigned long msghashlen,
+                         const unsigned char *sig,     unsigned long siglen,
+                               int           hash_idx, unsigned long modulus_bitlen, 
+                               int          *res);
+\end{verbatim}
+
+This will PKCS \#1 v1.5 signature decode the data in ``sig'' of length ``siglen'' and compare the extracted
+hash against ``msghash'' of length ``msghashlen''.  You have to tell this routine which hash produced the
+message digest in ``hash\_idx''.  If the packet is valid and the hashes match ``res'' is set to $1$.  Otherwise,
+it is set to $0$.
+
+\section{RSA Operations}
+\subsection{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.  
+
+\subsection{RSA Key Generation}
+
+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.
+
+\subsection{RSA Exponentiation}
+
+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,
+                      prng_state    *prng, int           prng_idx,
+                      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 the output of his function is zero-padded as per PKCS \#1 specifications.  This allows this routine to 
+interoprate with PKCS \#1 padding functions properly.
+
+\subsection{RSA Key Encryption}
+Normally RSA is used to encrypt short symmetric keys which are then used in block ciphers to encrypt a message.
+To facilitate encrypting short keys the following functions have been provided.
+
+\index{rsa\_encrypt\_key()}
+\begin{verbatim}
+int rsa_encrypt_key(const unsigned char *inkey,  unsigned long inlen,
+                          unsigned char *outkey, unsigned long *outlen,
+                    const unsigned char *lparam, unsigned long lparamlen,
+                    prng_state *prng, int prng_idx, int hash_idx, rsa_key *key);
+\end{verbatim}
+This function will OAEP pad ``inkey'' of length inlen bytes then RSA encrypt it and store the ciphertext
+in ``outkey'' of length ``outlen''.  The ``lparam'' and ``lparamlen'' are the same parameters you would pass
+to pkcs\_1\_oaep\_encode().
+
+\index{rsa\_decrypt\_key()}
+\begin{verbatim}
+int rsa_decrypt_key(const unsigned char *in,     unsigned long inlen,
+                          unsigned char *outkey, unsigned long *keylen, 
+                    const unsigned char *lparam, unsigned long lparamlen,
+                          prng_state    *prng,   int           prng_idx,
+                          int            hash_idx, int *res,
+                          rsa_key       *key);
+\end{verbatim}
+This function will RSA decrypt ``in'' of length ``inlen'' then OAEP depad the resulting data and store it in
+``outkey'' of length ``outlen''.  The ``lparam'' and ``lparamlen'' are the same parameters you would pass
+to pkcs\_1\_oaep\_decode().
+
+If the RSA decrypted data isn't a valid OAEP packet then ``res'' is set to $0$.  Otherwise, it is set to $1$.
+
+\subsection{RSA Hash Signatures}
+Similar to RSA key encryption RSA is also used to ``digitally sign'' message digests (hashes).  To facilitate this
+process the following functions have been provided.
+
+\index{rsa\_sign\_hash()}
+\begin{verbatim}
+int rsa_sign_hash(const unsigned char *msghash,  unsigned long  msghashlen, 
+                        unsigned char *sig,      unsigned long *siglen, 
+                        prng_state    *prng,     int            prng_idx,
+                        int            hash_idx, unsigned long  saltlen,
+                        rsa_key *key);
+\end{verbatim}
+
+This will PSS encode the message hash ``msghash'' of length ``msghashlen''.  Next the PSS encoded message is
+RSA ``signed'' and the output is stored in ``sig'' of length ``siglen''.  
+
+
+\index{rsa\_verify\_hash()}
+\begin{verbatim}
+int rsa_verify_hash(const unsigned char *sig,      unsigned long siglen,
+                    const unsigned char *msghash,  unsigned long msghashlen,
+                          prng_state    *prng,     int           prng_idx,
+                          int            hash_idx, unsigned long saltlen,
+                          int           *stat,     rsa_key      *key);
+\end{verbatim}
+
+This will RSA ``verify'' the signature in ``sig'' of length ``siglen''.  Next the RSA decoded data is PSS decoded
+and the extracted hash is compared against the message hash ``msghash'' of length ``msghashlen''.
+
+If the RSA decoded data is not a valid PSS message or if the PSS decoded hash does not match the ``msghash'' 
+the value ``res'' is set to $0$.  Otherwise, if the function succeeds and signature is valid ``res'' is set
+to $1$.
+
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   int           err, hash_idx, prng_idx, res;
+   unsigned long l1, l2;
+   unsigned char pt[16], pt2[16], out[1024];
+   rsa_key       key;
+
+   /* register prng/hash */
+   if (register_prng(&sprng_desc) == -1) {
+      printf("Error registering sprng");
+      return EXIT_FAILURE;
+   }
+
+   if (register_hash(&sha1_desc) == -1) {
+      printf("Error registering sha1");
+      return EXIT_FAILURE;
+   }
+   hash_idx = find_hash("sha1");
+   prng_idx = find_prng("sprng");
+
+   /* make an RSA-1024 key */
+   if ((err = rsa_make_key(NULL,     /* PRNG state */
+                           prng_idx, /* PRNG idx */
+                           1024/8,   /* 1024-bit key */
+                           65537,    /* we like e=65537 */
+                           &key)     /* where to store the key */
+       ) != CRYPT_OK) {
+       printf("rsa_make_key %s", error_to_string(err));
+       return EXIT_FAILURE;
+   }
+
+   /* fill in pt[] with a key we want to send ... */
+   l1 = sizeof(out);
+   if ((err = rsa_encrypt_key(pt,    /* data we wish to encrypt */
+                              16,    /* data is 16 bytes long */
+                             out,    /* where to store ciphertext */
+                             &l1,    /* length of ciphertext */
+                       "TestApp",    /* our lparam for this program */
+                               7,    /* lparam is 7 bytes long */
+                            NULL,    /* PRNG state */
+                        prng_idx,    /* prng idx */
+                        hash_idx,    /* hash idx */
+                            &key)    /* our RSA key */
+       ) != CRYPT_OK) {
+       printf("rsa_encrypt_key %s", error_to_string(err));
+       return EXIT_FAILURE;
+   }
+
+   /* now let's decrypt the encrypted key */
+   l2 = sizeof(pt2);
+   if ((err = rsa_decrypt_key(out, /* encrypted data */
+                               l1, /* length of ciphertext */
+                              pt2, /* where to put plaintext */
+                              &l2, /* plaintext length */
+                        "TestApp", /* lparam for this program */
+                                7, /* lparam is 7 bytes long */
+                             NULL, /* PRNG state */
+                         prng_idx, /* prng idx */
+                         hash_idx, /* hash idx */
+                             &res, /* validity of data */
+                             &key) /* our RSA key */ 
+        ) != CRYPT_OK) {
+       printf("rsa_decrypt_key %s", error_to_string(err));
+       return EXIT_FAILURE;
+   }
+   /* if all went well pt == pt2, l2 == 16, res == 1 */
+}
+\end{verbatim}
+
 \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
@@ -1817,6 +2283,7 @@
 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.  
 
+\index{pkcs\_5\_alg1()}
 \begin{alltt}
 int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, 
                 const unsigned char *salt, 
@@ -1836,6 +2303,7 @@
 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.
 
+\index{pkcs\_5\_alg2()}
 \begin{alltt}
 int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, 
                 const unsigned char *salt,     unsigned long salt_len,
@@ -1878,161 +2346,6 @@
 \}
 \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}
@@ -2224,6 +2537,7 @@
 \section{DH Packet}
 Similar to the RSA related functions there are functions to encrypt or decrypt symmetric keys using the DH public key
 algorithms.  
+\index{dh\_encrypt\_key()} \index{dh\_decrypt\_key()}
 \begin{verbatim}
 int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen,
                          unsigned char *out,  unsigned long *len, 
@@ -2240,6 +2554,7 @@
 as the symmetric key you are trying to share.
 
 Similar to the RSA system you can sign and verify a hash of a message.
+\index{dh\_sign\_hash()} \index{dh\_verify\_hash()}
 \begin{verbatim}
 int dh_sign_hash(const unsigned char *in,  unsigned long inlen,
                        unsigned char *out, unsigned long *outlen,
@@ -2334,6 +2649,8 @@
 \section{ECC Packet}
 Similar to the RSA API there are two functions which encrypt and decrypt symmetric keys using the ECC public key
 algorithms.
+
+\index{ecc\_encrypt\_key()} \index{ecc\_decrypt\_key()}
 \begin{verbatim}
 int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
                           unsigned char *out,  unsigned long *len, 
@@ -2351,6 +2668,7 @@
 as the symmetric key you are trying to share.
 
 There are also functions to sign and verify the hash of a message.
+\index{ecc\_sign\_hash()} \index{ecc\_verify\_hash()}
 \begin{verbatim}
 int ecc_sign_hash(const unsigned char *in,  unsigned long inlen,
                         unsigned char *out, unsigned long *outlen,
@@ -2409,6 +2727,7 @@
 \end{center}
 
 When you are finished with a DSA key you can call the following function to free the memory used.
+\index{dsa\_free()}
 \begin{verbatim}
 void dsa_free(dsa_key *key);
 \end{verbatim}
@@ -2447,6 +2766,7 @@
 
 The following function will perform these tests.
 
+\index{dsa\_verify\_key()}
 \begin{verbatim}
 int dsa_verify_key(dsa_key *key, int *stat);
 \end{verbatim}
@@ -2459,6 +2779,7 @@
 \section{Signatures}
 To generate a DSA signature call the following function
 
+\index{dsa\_sign\_hash()}
 \begin{verbatim}
 int dsa_sign_hash(const unsigned char *in,  unsigned long inlen,
                         unsigned char *out, unsigned long *outlen,
@@ -2471,6 +2792,7 @@
 
 To verify a hash created with that function use the following function
 
+\index{dsa\_verify\_hash()} 
 \begin{verbatim}
 int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
                     const unsigned char *hash, unsigned long inlen, 
@@ -2482,6 +2804,7 @@
 \section{Import and Export}
 
 To export a DSA key so that it can be transported use the following function
+\index{dsa\_export()}
 \begin{verbatim}
 int dsa_export(unsigned char *out, unsigned long *outlen, 
                int type, 
@@ -2493,6 +2816,7 @@
 
 To import an exported DSA key use the following function
 
+\index{dsa\_import()}
 \begin{verbatim}
 int dsa_import(const unsigned char *in, unsigned long inlen, 
                dsa_key *key);
@@ -2501,239 +2825,6 @@
 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 
@@ -3037,4 +3128,6 @@
 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.
 
+\input{crypt.ind}
+
 \end{document}
--- a/crypt_hash_descriptor.c	Mon May 31 18:25:41 2004 +0000
+++ b/crypt_hash_descriptor.c	Tue Jun 15 14:07:21 2004 +0000
@@ -11,35 +11,35 @@
 #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 } };
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL },
+{ NULL, 0, 0, 0, { 0x00 }, 0, NULL, NULL, NULL, NULL } };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ctr_getiv.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,30 @@
+/* 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_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr)
+{
+   _ARGCHK(IV  != NULL);
+   _ARGCHK(len != NULL);
+   _ARGCHK(ctr != NULL);
+   if ((unsigned long)ctr->blocklen > *len) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+   memcpy(IV, ctr->ctr, ctr->blocklen);
+   *len = ctr->blocklen;
+
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ctr_setiv.c	Tue Jun 15 14:07:21 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 CTR
+
+int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr)
+{
+   int err;
+   
+   _ARGCHK(IV  != NULL);
+   _ARGCHK(ctr != NULL);
+
+   /* bad param? */
+   if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {
+      return err;
+   }
+   
+   if (len != (unsigned long)ctr->blocklen) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* set IV */
+   memcpy(ctr->ctr, IV, len);
+   
+   /* force next block */
+   ctr->padlen = 0;
+   cipher_descriptor[ctr->cipher].ecb_encrypt(IV, ctr->pad, &ctr->key);
+   
+   return CRYPT_OK;
+}
+
+#endif 
+
--- a/demos/small.c	Mon May 31 18:25:41 2004 +0000
+++ b/demos/small.c	Tue Jun 15 14:07:21 2004 +0000
@@ -4,7 +4,7 @@
 
 int main(void)
 {
-   register_cipher(&rijndael_desc);
+   register_cipher(&rijndael_enc_desc);
    register_prng(&yarrow_desc);
    register_hash(&sha256_desc);
    return 0;
--- a/demos/test.c	Mon May 31 18:25:41 2004 +0000
+++ b/demos/test.c	Tue Jun 15 14:07:21 2004 +0000
@@ -1202,69 +1202,6 @@
 }
 #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)
@@ -1390,299 +1327,6 @@
 #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)
 {
@@ -1840,13 +1484,13 @@
 
       /* 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) {
+      if ((err = pkcs_1_oaep_decode(buf[1], l1, NULL, 0, 1024, hash_idx, buf[2], &l2, &res1)) != 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);
+      if (res1 != 1 || l2 != l3 || memcmp(buf[2], buf[0], l3) != 0) {
+         printf("res == %d, Outsize == %lu, should have been %lu, msg contents follow.\n", res1, l2, l3);
          printf("ORIGINAL:\n");
          for (x = 0; x < l3; x++) {
              printf("%02x ", buf[0][x]);
@@ -1959,16 +1603,12 @@
   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 ();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/base64_test.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,20 @@
+#include  "test.h"
+
+int base64_test(void)
+{
+   unsigned char in[64], out[256], tmp[64];
+   unsigned long x, l1, l2;
+   
+   for  (x = 0; x < 64; x++) {
+       yarrow_read(in, x, &test_yarrow);
+       l1 = sizeof(out);
+       DO(base64_encode(in, x, out, &l1));
+       l2 = sizeof(tmp);
+       DO(base64_decode(out, l1, tmp, &l2));
+       if (l2 != x || memcmp(tmp, in, x)) {
+           printf("base64  failed %lu %lu %lu", x, l1, l2);
+           return 1;
+       }
+   }
+   return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/cipher_hash_test.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,20 @@
+/* test the ciphers and hashes using their built-in self-tests */
+
+#include "test.h"
+
+int cipher_hash_test(void)
+{
+   int x;
+   
+   /* test ciphers */
+   for (x = 0; cipher_descriptor[x].name != NULL; x++) {
+      DO(cipher_descriptor[x].test());
+   }
+   
+   /* test hashes */
+   for (x = 0; hash_descriptor[x].name != NULL; x++) {
+      DO(hash_descriptor[x].test());
+   }
+   
+   return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/dh_tests.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,87 @@
+#include "test.h"
+
+int dh_tests (void)
+{
+  unsigned char buf[3][4096];
+  unsigned long x, y, z;
+  int           stat, stat2;
+  dh_key        usera, userb;
+
+  DO(dh_test());
+
+  /* make up two keys */
+  DO(dh_make_key (&test_yarrow, find_prng ("yarrow"), 96, &usera));
+  DO(dh_make_key (&test_yarrow, find_prng ("yarrow"), 96, &userb));
+
+  /* make the shared secret */
+  x = 4096;
+  DO(dh_shared_secret (&usera, &userb, buf[0], &x));
+
+  y = 4096;
+  DO(dh_shared_secret (&userb, &usera, buf[1], &y));
+  if (y != x) {
+    printf ("DH Shared keys are not same size.\n");
+    return 1;
+  }
+  if (memcmp (buf[0], buf[1], x)) {
+    printf ("DH Shared keys not same contents.\n");
+    return 1;
+  }
+
+  /* now export userb */
+  y = 4096;
+  DO(dh_export (buf[1], &y, PK_PUBLIC, &userb));
+	  dh_free (&userb);
+
+  /* import and make the shared secret again */
+  DO(dh_import (buf[1], y, &userb));
+  z = 4096;
+  DO(dh_shared_secret (&usera, &userb, buf[2], &z));
+
+  if (z != x) {
+    printf ("failed.  Size don't match?\n");
+    return 1;
+  }
+  if (memcmp (buf[0], buf[2], x)) {
+    printf ("Failed.  Content didn't match.\n");
+    return 1;
+  }
+  dh_free (&usera);
+  dh_free (&userb);
+
+/* test encrypt_key */
+  dh_make_key (&test_yarrow, find_prng ("yarrow"), 128, &usera);
+  for (x = 0; x < 16; x++) {
+    buf[0][x] = x;
+  }
+  y = sizeof (buf[1]);
+  DO(dh_encrypt_key (buf[0], 16, buf[1], &y, &test_yarrow, find_prng ("yarrow"), find_hash ("md5"), &usera));
+  zeromem (buf[0], sizeof (buf[0]));
+  x = sizeof (buf[0]);
+  DO(dh_decrypt_key (buf[1], y, buf[0], &x, &usera));
+  if (x != 16) {
+    printf ("Failed (length)\n");
+    return 1;
+  }
+  for (x = 0; x < 16; x++)
+    if (buf[0][x] != x) {
+      printf ("Failed (contents)\n");
+      return 1;
+    }
+
+/* test sign_hash */
+  for (x = 0; x < 16; x++) {
+     buf[0][x] = x;
+  }
+  x = sizeof (buf[1]);
+  DO(dh_sign_hash (buf[0], 16, buf[1], &x, &test_yarrow		, find_prng ("yarrow"), &usera));
+  DO(dh_verify_hash (buf[1], x, buf[0], 16, &stat, &usera));
+  buf[0][0] ^= 1;
+  DO(dh_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera));
+  if (!(stat == 1 && stat2 == 0)) { 
+     printf("dh_sign/verify_hash %d %d", stat, stat2);
+     return 1;
+  }
+  dh_free (&usera);
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/dsa_test.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,51 @@
+#include "test.h"
+
+int dsa_test(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 */
+   DO(dsa_make_key(&test_yarrow, find_prng("yarrow"), 20, 128, &key));
+
+   /* verify it */
+   DO(dsa_verify_key(&key, &stat1));
+   if (stat1 == 0) { printf("dsa_verify_key "); return 1; }
+
+   /* sign the message */
+   x = sizeof(out);
+   DO(dsa_sign_hash(msg, sizeof(msg), out, &x, &test_yarrow, find_prng("yarrow"), &key));
+
+   /* verify it once */
+   DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key));
+
+   /* Modify and verify again */
+   msg[0] ^= 1;
+   DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat2, &key));
+   msg[0] ^= 1;
+   if (!(stat1 == 1 && stat2 == 0)) { printf("dsa_verify %d %d", stat1, stat2); return 1; }
+
+   /* test exporting it */
+   x = sizeof(out2);
+   DO(dsa_export(out2, &x, PK_PRIVATE, &key));
+   DO(dsa_import(out2, x, &key2));
+
+   /* verify a signature with it */
+   DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2));
+   if (stat1 == 0) { printf("dsa_verify (import private) %d ", stat1); return 1; }
+   dsa_free(&key2);
+
+   /* export as public now */
+   x = sizeof(out2);
+   DO(dsa_export(out2, &x, PK_PUBLIC, &key));
+   DO(dsa_import(out2, x, &key2));
+   /* verify a signature with it */
+   DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2));
+   if (stat1 == 0) { printf("dsa_verify (import public) %d ", stat1); return 1; }
+   dsa_free(&key2);
+   dsa_free(&key);
+
+   return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/ecc_test.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,89 @@
+#include "test.h"
+
+int ecc_tests (void)
+{
+  unsigned char buf[4][4096];
+  unsigned long x, y, z;
+  int           stat, stat2;
+  ecc_key usera, userb;
+	
+  DO(ecc_test ());
+
+  /* make up two keys */
+  DO(ecc_make_key (&test_yarrow, find_prng ("yarrow"), 24, &usera));
+  DO(ecc_make_key (&test_yarrow, find_prng ("yarrow"), 24, &userb));
+
+  /* make the shared secret */
+  x = 4096;
+  DO(ecc_shared_secret (&usera, &userb, buf[0], &x));
+
+  y = 4096;
+  DO(ecc_shared_secret (&userb, &usera, buf[1], &y));
+
+  if (y != x) {
+    printf ("ecc Shared keys are not same size.");
+    return 1;
+  }
+
+  if (memcmp (buf[0], buf[1], x)) {
+    printf ("ecc Shared keys not same contents.");
+    return 1;
+  }
+
+  /* now export userb */
+  y = 4096;
+  DO(ecc_export (buf[1], &y, PK_PUBLIC, &userb));
+  ecc_free (&userb);
+
+  /* import and make the shared secret again */
+  DO(ecc_import (buf[1], y, &userb));
+
+  z = 4096;
+  DO(ecc_shared_secret (&usera, &userb, buf[2], &z));
+
+  if (z != x) {
+    printf ("failed.  Size don't match?");
+    return 1;
+  }
+  if (memcmp (buf[0], buf[2], x)) {
+    printf ("Failed.  Content didn't match.");
+    return 1;
+  }
+  ecc_free (&usera);
+  ecc_free (&userb);
+
+/* test encrypt_key */
+  ecc_make_key (&test_yarrow, find_prng ("yarrow"), 20, &usera);
+  for (x = 0; x < 32; x++) {
+    buf[0][x] = x;
+  }
+  y = sizeof (buf[1]);
+  DO(ecc_encrypt_key (buf[0], 32, buf[1], &y, &test_yarrow, find_prng ("yarrow"), find_hash ("sha256"), &usera));
+  zeromem (buf[0], sizeof (buf[0]));
+  x = sizeof (buf[0]);
+  DO(ecc_decrypt_key (buf[1], y, buf[0], &x, &usera));
+  if (x != 32) {
+    printf ("Failed (length)");
+    return 1;
+  }
+  for (x = 0; x < 32; x++)
+    if (buf[0][x] != x) {
+      printf ("Failed (contents)");
+      return 1;
+    }
+/* test sign_hash */
+  for (x = 0; x < 16; x++) {
+    buf[0][x] = x;
+  }
+  x = sizeof (buf[1]);
+  DO(ecc_sign_hash (buf[0], 16, buf[1], &x, &test_yarrow, find_prng ("yarrow"), &usera));
+  DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat, &usera));
+  buf[0][0] ^= 1;
+  DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera));
+  if (!(stat == 1 && stat2 == 0)) { 
+    printf("ecc_verify_hash failed");
+    return 1;
+  }
+  ecc_free (&usera);
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/mac_test.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,12 @@
+/* test pmac/omac/hmac */
+#include "test.h"
+
+int mac_test(void)
+{
+   DO(hmac_test());
+   DO(pmac_test());
+   DO(omac_test());
+   DO(eax_test());
+   DO(ocb_test());
+   return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/makefile	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,13 @@
+# make test harness, it is good.
+CFLAGS += -Wall -W -Os -I../../ -I./
+
+default: test
+
+OBJECTS=test.o cipher_hash_test.o mac_test.o modes_test.o \
+pkcs_1_test.o store_test.o rsa_test.o ecc_test.o dsa_test.c dh_tests.o 
+
+test: $(OBJECTS)
+	$(CC) $(OBJECTS) -ltomcrypt -o test
+	
+clean:
+	rm -f test *.o *.obj *.exe *~	
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/makefile.icc	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,14 @@
+# make test harness, it is good.
+CFLAGS += -O3 -xN -ip -I../../ -I./
+CC=icc
+
+default: test
+
+OBJECTS=test.o cipher_hash_test.o mac_test.o modes_test.o \
+pkcs_1_test.o store_test.o rsa_test.o ecc_test.o dsa_test.c dh_tests.o 
+
+test: $(OBJECTS)
+	$(CC) $(OBJECTS) -ltomcrypt -o test
+	
+clean:
+	rm -f test *.o *~	
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/makefile.msvc	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,14 @@
+# make test harness, it is good.
+CFLAGS = $(CFLAGS) /W3 /Ox -I../../ -I./
+
+default: test.exe
+
+OBJECTS = test.obj cipher_hash_test.obj mac_test.obj modes_test.obj \
+pkcs_1_test.obj store_test.obj rsa_test.obj ecc_test.obj dsa_test.c dh_tests.obj 
+
+
+test.exe: $(OBJECTS)
+	cl $(OBJECTS) tomcrypt.lib advapi32.lib 
+	
+clean:
+	rm -f test.exe *.obj *~	
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/modes_test.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,112 @@
+/* test CFB/OFB/CBC modes */
+#include "test.h"
+
+int modes_test(void)
+{
+   unsigned char pt[64], ct[64], tmp[64], key[16], iv[16], iv2[16];
+   int x, cipher_idx;
+   symmetric_CBC cbc;
+   symmetric_CFB cfb;
+   symmetric_OFB ofb;
+   symmetric_CTR ctr;
+   unsigned long l;
+   
+   /* make a random pt, key and iv */
+   yarrow_read(pt,  64, &test_yarrow);
+   yarrow_read(key, 16, &test_yarrow);
+   yarrow_read(iv,  16, &test_yarrow);
+   
+   /* get idx of AES handy */
+   cipher_idx = find_cipher("aes");
+   if (cipher_idx == -1) {
+      printf("test requires AES");
+      return 1;
+   }
+   
+   /* test CBC mode */
+   /* encode the block */
+   DO(cbc_start(cipher_idx, iv, key, 16, 0, &cbc));
+   l = sizeof(iv2);
+   DO(cbc_getiv(iv2, &l, &cbc));
+   if (l != 16 || memcmp(iv2, iv, 16)) {
+      printf("cbc_getiv failed");
+      return 1;
+   }
+   for (x = 0; x < 4; x++) {
+      DO(cbc_encrypt(pt+x*16, ct+x*16, &cbc));
+   }
+   
+   /* decode the block */
+   DO(cbc_setiv(iv2, l, &cbc));
+   zeromem(tmp, sizeof(tmp));
+   for (x = 0; x < 4; x++) {
+      DO(cbc_decrypt(ct+x*16, tmp+x*16, &cbc));
+   }
+   if (memcmp(tmp, pt, 64) != 0) {
+      printf("CBC failed");
+      return 1;
+   }
+   
+   /* test CFB mode */
+   /* encode the block */
+   DO(cfb_start(cipher_idx, iv, key, 16, 0, &cfb));
+   l = sizeof(iv2);
+   DO(cfb_getiv(iv2, &l, &cfb));
+   /* note we don't memcmp iv2/iv since cfb_start processes the IV for the first block */
+   if (l != 16) {
+      printf("cfb_getiv failed");
+      return 1;
+   }
+   DO(cfb_encrypt(pt, ct, 64, &cfb));
+   
+   /* decode the block */
+   DO(cfb_setiv(iv, l, &cfb));
+   zeromem(tmp, sizeof(tmp));
+   DO(cfb_decrypt(ct, tmp, 64, &cfb));
+   if (memcmp(tmp, pt, 64) != 0) {
+      printf("CFB failed");
+      return 1;
+   }
+   
+   /* test OFB mode */
+   /* encode the block */
+   DO(ofb_start(cipher_idx, iv, key, 16, 0, &ofb));
+   l = sizeof(iv2);
+   DO(ofb_getiv(iv2, &l, &ofb));
+   if (l != 16 || memcmp(iv2, iv, 16)) {
+      printf("ofb_getiv failed");
+      return 1;
+   }
+   DO(ofb_encrypt(pt, ct, 64, &ofb));
+   
+   /* decode the block */
+   DO(ofb_setiv(iv2, l, &ofb));
+   zeromem(tmp, sizeof(tmp));
+   DO(ofb_decrypt(ct, tmp, 64, &ofb));
+   if (memcmp(tmp, pt, 64) != 0) {
+      printf("OFB failed");
+      return 1;
+   }
+   
+   /* test CTR mode */
+   /* encode the block */
+   DO(ctr_start(cipher_idx, iv, key, 16, 0, &ctr));
+   l = sizeof(iv2);
+   DO(ctr_getiv(iv2, &l, &ctr));
+   if (l != 16 || memcmp(iv2, iv, 16)) {
+      printf("ctr_getiv failed");
+      return 1;
+   }
+   DO(ctr_encrypt(pt, ct, 64, &ctr));
+   
+   /* decode the block */
+   DO(ctr_setiv(iv2, l, &ctr));
+   zeromem(tmp, sizeof(tmp));
+   DO(ctr_decrypt(ct, tmp, 64, &ctr));
+   if (memcmp(tmp, pt, 64) != 0) {
+      printf("CTR failed");
+      return 1;
+   }
+         
+   return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/pkcs_1_test.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,103 @@
+#include "test.h"
+
+int pkcs_1_test(void)
+{
+   unsigned char buf[3][128];
+   int res1, res2, res3, prng_idx, hash_idx;
+   unsigned long x, y, l1, l2, l3, i1, i2, lparamlen, saltlen, modlen;
+   static const unsigned char lparam[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 };
+
+   /* get hash/prng  */
+   hash_idx = find_hash("sha1");
+   prng_idx = find_prng("yarrow");
+   
+   if (hash_idx == -1 || prng_idx == -1) {
+      printf("pkcs_1 tests require sha1/yarrow");
+      return 1;
+   }   
+
+   /* 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;
+
+      /* random modulus len (v1.5 must be multiple of 8 though arbitrary sizes seem to work) */
+      modlen = 800 + 8 * (abs(rand()) % 28);
+
+      /* PKCS v1.5 testing (encryption) */
+      l1 = sizeof(buf[1]);
+      DO(pkcs_1_v15_es_encode(buf[0], l3, modlen, &test_yarrow, prng_idx, buf[1], &l1));
+      DO(pkcs_1_v15_es_decode(buf[1], l1, modlen, buf[2], l3, &res1));
+      if (res1 != 1 || memcmp(buf[0], buf[2], l3)) {
+         printf("pkcs v1.5 encrypt failed %d, %lu, %lu ", res1, l1, l3);
+         return 1;
+      }
+
+      /* PKCS v1.5 testing (signatures) */
+      l1 = sizeof(buf[1]);
+      DO(pkcs_1_v15_sa_encode(buf[0], l3, hash_idx, modlen, buf[1], &l1));
+      DO(pkcs_1_v15_sa_decode(buf[0], l3, buf[1], l1, hash_idx, modlen, &res1));
+      buf[0][i1 = abs(rand()) % l3] ^= 1;
+      DO(pkcs_1_v15_sa_decode(buf[0], l3, buf[1], l1, hash_idx, modlen, &res2));
+      buf[0][i1] ^= 1;
+      buf[1][i2 = abs(rand()) % l1] ^= 1;
+      DO(pkcs_1_v15_sa_decode(buf[0], l3, buf[1], l1, hash_idx, modlen, &res3));
+
+      if (!(res1 == 1 && res2 == 0 && res3 == 0)) {
+         printf("pkcs v1.5 sign failed %d %d %d ", res1, res2, res3);
+         return 1;
+      }
+
+      /* pick a random lparam len [0..16] */
+      lparamlen = abs(rand()) % 17;
+
+      /* pick a random saltlen 0..16 */
+      saltlen   = abs(rand()) % 17;
+
+      /* PKCS #1 v2.0 supports modlens not multiple of 8 */
+      modlen = 800 + (abs(rand()) % 224);
+
+      /* encode it */
+      l1 = sizeof(buf[1]);
+      DO(pkcs_1_oaep_encode(buf[0], l3, lparam, lparamlen, modlen, &test_yarrow, prng_idx, hash_idx, buf[1], &l1));
+
+      /* decode it */
+      l2 = sizeof(buf[2]);
+      DO(pkcs_1_oaep_decode(buf[1], l1, lparam, lparamlen, modlen, hash_idx, buf[2], &l2, &res1));
+
+      if (res1 != 1 || l2 != l3 || memcmp(buf[2], buf[0], l3) != 0) {
+         printf("Outsize == %lu, should have been %lu, res1 = %d, lparamlen = %lu, msg contents follow.\n", l2, l3, res1, lparamlen);
+         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");
+         return 1;
+      }
+
+      /* test PSS */
+      l1 = sizeof(buf[1]);
+      DO(pkcs_1_pss_encode(buf[0], l3, saltlen, &test_yarrow, prng_idx, hash_idx, modlen, buf[1], &l1));
+      DO(pkcs_1_pss_decode(buf[0], l3, buf[1], l1, saltlen, hash_idx, modlen, &res1));
+      
+      buf[0][i1 = abs(rand()) % l3] ^= 1;
+      DO(pkcs_1_pss_decode(buf[0], l3, buf[1], l1, saltlen, hash_idx, modlen, &res2));
+
+      buf[0][i1] ^= 1;
+      buf[1][i2 = abs(rand()) % l1] ^= 1;
+      DO(pkcs_1_pss_decode(buf[0], l3, buf[1], l1, saltlen, hash_idx, modlen, &res3));
+
+      if (!(res1 == 1 && res2 == 0 && res3 == 0)) {
+         printf("PSS failed: %d, %d, %d, %lu, %lu\n", res1, res2, res3, l3, saltlen);
+         return 1;
+      }
+   }
+   return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/rsa_test.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,91 @@
+#include "test.h"
+
+int rsa_test(void)
+{
+   unsigned char in[1024], out[1024], tmp[1024];
+   rsa_key       key;
+   int           hash_idx, prng_idx, stat, stat2;
+   unsigned long len, len2;
+   static unsigned char lparam[] = { 0x01, 0x02, 0x03, 0x04 };
+      
+   hash_idx = find_hash("sha1");
+   prng_idx = find_prng("yarrow");
+   if (hash_idx == -1 || prng_idx == -1) {
+      printf("rsa_test requires SHA1 and yarrow");
+      return 1;
+   }
+   
+   /* make a random key/msg */
+   yarrow_read(in, 20, &test_yarrow);
+   
+   /* make a random key */
+   DO(rsa_make_key(&test_yarrow, prng_idx, 1024/8, 65537, &key));
+   
+   /* encrypt the key (without lparam) */
+   len  = sizeof(out);
+   len2 = sizeof(tmp);
+   DO(rsa_encrypt_key(in, 20, out, &len, NULL, 0, &test_yarrow, prng_idx, hash_idx, &key));
+   /* change a byte */
+   out[0] ^= 1;
+   DO(rsa_decrypt_key(out, len, tmp, &len2, NULL, 0, &test_yarrow, prng_idx, hash_idx, &stat2, &key));
+   /* change a byte back */
+   out[0] ^= 1;
+   DO(rsa_decrypt_key(out, len, tmp, &len2, NULL, 0, &test_yarrow, prng_idx, hash_idx, &stat, &key));
+   if (!(stat == 1 && stat2 == 0)) {
+      printf("rsa_decrypt_key failed");
+      return 1;
+   }
+   if (len2 != 20 || memcmp(tmp, in, 20)) {
+      printf("rsa_decrypt_key mismatch len %lu", len2);
+      return 1;
+   }
+
+   /* encrypt the key (with lparam) */
+   len  = sizeof(out);
+   len2 = sizeof(tmp);
+   DO(rsa_encrypt_key(in, 20, out, &len, lparam, sizeof(lparam), &test_yarrow, prng_idx, hash_idx, &key));
+   /* change a byte */
+   out[0] ^= 1;
+   DO(rsa_decrypt_key(out, len, tmp, &len2, lparam, sizeof(lparam), &test_yarrow, prng_idx, hash_idx, &stat2, &key));
+   /* change a byte back */
+   out[0] ^= 1;
+   DO(rsa_decrypt_key(out, len, tmp, &len2, lparam, sizeof(lparam), &test_yarrow, prng_idx, hash_idx, &stat, &key));
+   if (!(stat == 1 && stat2 == 0)) {
+      printf("rsa_decrypt_key failed");
+      return 1;
+   }
+   if (len2 != 20 || memcmp(tmp, in, 20)) {
+      printf("rsa_decrypt_key mismatch len %lu", len2);
+      return 1;
+   }
+
+   /* sign a message (unsalted, lower cholestorol and Atkins approved) now */
+   len = sizeof(out);
+   DO(rsa_sign_hash(in, 20, out, &len, &test_yarrow, prng_idx, hash_idx, 0, &key));
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 0, &stat, &key));
+   /* change a byte */
+   in[0] ^= 1;
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 0, &stat2, &key));
+   
+   if (!(stat == 1 && stat2 == 0)) {
+      printf("rsa_verify_hash (unsalted) failed, %d, %d", stat, stat2);
+      return 1;
+   }
+
+   /* sign a message (salted) now */
+   len = sizeof(out);
+   DO(rsa_sign_hash(in, 20, out, &len, &test_yarrow, prng_idx, hash_idx, 8, &key));
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 8, &stat, &key));
+   /* change a byte */
+   in[0] ^= 1;
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 8, &stat2, &key));
+   
+   if (!(stat == 1 && stat2 == 0)) {
+      printf("rsa_verify_hash (salted) failed, %d, %d", stat, stat2);
+      return 1;
+   }
+   
+   /* free the key and return */
+   rsa_free(&key);
+   return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/store_test.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,43 @@
+#include "test.h"
+
+int store_test(void)
+{
+  unsigned char buf[8];
+  unsigned long L;
+  ulong64 LL;
+
+  L = 0x12345678UL;
+  STORE32L (L, &buf[0]);
+  L = 0;
+  LOAD32L (L, &buf[0]);
+  if (L != 0x12345678UL) {
+    printf ("LOAD/STORE32 Little don't work");
+    return 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");
+    return 1;
+  }
+
+  L = 0x12345678UL;
+  STORE32H (L, &buf[0]);
+  L = 0;
+  LOAD32H (L, &buf[0]);
+  if (L != 0x12345678UL) {
+    printf ("LOAD/STORE32 High don't work, %08lx", L);
+    return 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");
+    return 1;
+  }
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/test.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,177 @@
+#include "test.h"
+
+test_entry tests[26];
+
+test_entry test_list[26] = { 
+
+/* test name          provides    requires             entry */
+{"store_test",             "a",         "",          store_test           },
+{"cipher_hash_test",       "b",        "a",          cipher_hash_test     },
+{"modes_test",             "c",        "b",          modes_test           },
+{"mac_test",               "d",        "c",          mac_test             },
+{"pkcs_1_test",            "e",        "b",          pkcs_1_test          },
+{"rsa_test",               "f",        "e",          rsa_test             },
+{"ecc_test",               "g",        "a",          ecc_tests            },
+{"dsa_test",               "h",        "a",          dsa_test             },
+{"dh_test",                "i",        "a",          dh_tests             },
+
+{NULL, NULL, NULL, NULL} 
+};
+
+prng_state test_yarrow;
+static int current_test;
+
+void run_cmd(int res, int line, char *file, char *cmd)
+{
+   if (res != CRYPT_OK) {
+      fprintf(stderr, "[%s]: %s (%d)\n%s:%d:%s\n", tests[current_test].name, error_to_string(res), res, file, line, cmd);
+      exit(EXIT_FAILURE);
+   }
+}
+
+void register_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 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
+
+   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);
+   }
+}
+
+/* sort tests based on their requirement/services.  Helps make sure dependencies are tested first */
+void sort(void)
+{
+   unsigned x, y, z, a, pidx[26];
+      
+   /* find out where things are provided */
+   zeromem(pidx, sizeof(pidx));   
+   z = 0;
+   do { 
+      y = 0;
+      for (x = 0; test_list[x].name != NULL; x++) {
+        if (test_list[x].entry == NULL) continue;
+        if (strlen(test_list[x].prov) == 0) {
+           y = 1;
+           tests[z++] = test_list[x]; test_list[x].entry = NULL;
+           pidx[test_list[x].prov[0]-'a'] = 1;
+           break;
+        } else {
+           for (a = 0; a < strlen(test_list[x].req); a++) {
+               if (pidx[test_list[x].req[a]-'a'] == 0) break;
+           }
+           if (a == strlen(test_list[x].req)) {
+              y = 1;
+              tests[z++] = test_list[x]; test_list[x].entry = NULL;
+              pidx[test_list[x].prov[0]-'a'] = 1;
+              break;
+           }
+        }
+      }
+   } while (y == 1);
+}
+   
+int main(void)
+{
+   printf("Built with\n%s\n", crypt_build_settings);
+
+   srand(time(NULL));
+   sort();
+   register_algs();
+      
+   // start dummy yarrow for internal use 
+   DO(yarrow_start(&test_yarrow));
+   DO(yarrow_add_entropy("test", 4, &test_yarrow));
+   DO(yarrow_ready(&test_yarrow));
+
+   // do tests
+   for (current_test = 0; tests[current_test].name != NULL; current_test++) {
+       printf("[%-20s]: ", tests[current_test].name); fflush(stdout);
+       printf("\t%s\n", tests[current_test].entry()==0?"passed":"failed"); 
+   }
+   
+   return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/test.h	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,29 @@
+#ifndef __TEST_H_
+#define __TEST_H_
+
+#include "mycrypt.h"
+
+typedef struct {
+    char *name, *prov, *req;
+    int  (*entry)(void);
+} test_entry;
+
+extern prng_state test_yarrow;
+
+void run_cmd(int res, int line, char *file, char *cmd);
+#define DO(x) run_cmd((x), __LINE__, __FILE__, #x)
+
+
+
+/* TESTS */
+int cipher_hash_test(void);
+int modes_test(void);
+int mac_test(void);
+int pkcs_1_test(void);
+int store_test(void);
+int rsa_test(void);
+int ecc_tests(void);
+int dsa_test(void);
+int dh_tests(void);
+
+#endif
Binary file doc/crypt.pdf has changed
--- a/ecb_decrypt.c	Mon May 31 18:25:41 2004 +0000
+++ b/ecb_decrypt.c	Tue Jun 15 14:07:21 2004 +0000
@@ -19,9 +19,12 @@
    _ARGCHK(ct != NULL);
    _ARGCHK(ecb != NULL);
 
+   /* valid cipher? */
    if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
        return err;
    }
+   _ARGCHK(cipher_descriptor[ecb->cipher].ecb_decrypt != NULL);
+   
    cipher_descriptor[ecb->cipher].ecb_decrypt(ct, pt, &ecb->key);
    return CRYPT_OK;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/error_to_string.c	Tue Jun 15 14:07:21 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
+ */
+
+#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.",
+
+};
+
+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];
+   }   
+}
+
--- a/gf.c	Mon May 31 18:25:41 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,305 +0,0 @@
-/* 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
-
-
--- a/keyring.c	Mon May 31 18:25:41 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,862 +0,0 @@
-/* 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/ltc_tommath.h	Tue Jun 15 14:07:21 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
+
--- a/makefile	Mon May 31 18:25:41 2004 +0000
+++ b/makefile	Tue Jun 15 14:07:21 2004 +0000
@@ -9,9 +9,8 @@
 # a build. This is easy to remedy though, for those that have problems.
 
 # The version
-VERSION=0.95
+VERSION=0.96
 
-#ch1-01-1
 # Compiler and Linker Names
 #CC=gcc
 #LD=ld
@@ -19,9 +18,7 @@
 # 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
@@ -29,8 +26,8 @@
 # optimize for SPEED
 #CFLAGS += -O3 -funroll-loops
 
-#add -fomit-frame-pointer.  v3.2 is buggy for certain platforms!
-#CFLAGS += -fomit-frame-pointer
+#add -fomit-frame-pointer.  GCC v3.2 is buggy for certain platforms!
+CFLAGS += -fomit-frame-pointer
 
 # optimize for SIZE
 CFLAGS += -Os
@@ -43,7 +40,6 @@
 
 #Output filenames for various targets.
 LIBNAME=libtomcrypt.a
-TEST=test
 HASH=hashsum
 CRYPT=encrypt
 SMALL=small
@@ -63,7 +59,7 @@
 #Leave MPI built-in or force developer to link against libtommath?
 MPIOBJECT=mpi.o
 
-OBJECTS=keyring.o gf.o strings.o base64.o \
+OBJECTS=error_to_string.o mpi_to_ltc_error.o base64_encode.o base64_decode.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    \
@@ -79,12 +75,16 @@
 \
 ecc.o  dh.o \
 \
-rsa.o rsa_exptmod.o  rsa_free.o  rsa_make_key.o \
+rsa_decrypt_key.o  rsa_encrypt_key.o  rsa_exptmod.o  rsa_free.o  rsa_make_key.o  \
+rsa_sign_hash.o  rsa_verify_hash.o rsa_export.o rsa_import.o tim_exptmod.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 \
+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 \
+aes.o aes_enc.o \
+\
+blowfish.o des.o safer_tab.o safer.o saferp.o rc2.o xtea.o \
+rc6.o rc5.o cast5.o noekeon.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 \
@@ -103,10 +103,10 @@
 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 \
+cbc_start.o cbc_encrypt.o cbc_decrypt.o cbc_getiv.o cbc_setiv.o \
+cfb_start.o cfb_encrypt.o cfb_decrypt.o cfb_getiv.o cfb_setiv.o \
+ofb_start.o ofb_encrypt.o ofb_decrypt.o ofb_getiv.o ofb_setiv.o \
+ctr_start.o ctr_encrypt.o ctr_decrypt.o ctr_getiv.o ctr_setiv.o \
 ecb_start.o ecb_encrypt.o ecb_decrypt.o \
 \
 hash_file.o  hash_filehandle.o  hash_memory.o \
@@ -115,6 +115,7 @@
 \
 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_1_v15_es_encode.o pkcs_1_v15_es_decode.o pkcs_1_v15_sa_encode.o pkcs_1_v15_sa_decode.o \
 \
 pkcs_5_1.o pkcs_5_2.o \
 \
@@ -129,26 +130,27 @@
 TVS=demos/tv_gen.o
 
 #Files left over from making the crypt.pdf.
-LEFTOVERS=*.dvi *.log *.aux *.toc *.idx *.ilg *.ind
+LEFTOVERS=*.dvi *.log *.aux *.toc *.idx *.ilg *.ind *.out
 
 #Compressed filenames
-COMPRESSED=crypt.tar.bz2 crypt.zip crypt.tar.gz
+COMPRESSED=crypt-$(VERSION).tar.bz2 crypt-$(VERSION).zip
 
 #Header files used by libtomcrypt.
-HEADERS=tommath.h mycrypt_cfg.h mycrypt_gf.h mycrypt_kr.h \
+HEADERS=ltc_tommath.h mycrypt_cfg.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
+default:library
 
+#ciphers come in two flavours... enc+dec and enc 
+aes_enc.o: aes.c aes_tab.c
+	$(CC) $(CFLAGS) -DENCRYPT_ONLY -c aes.c -o aes_enc.o
+		
 #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
 
@@ -158,10 +160,6 @@
 $(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)
@@ -180,34 +178,6 @@
 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.
@@ -217,7 +187,7 @@
 	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)
+	install -g root -o root doc/crypt.pdf $(DESTDIR)$(DATAPATH)
 
 #This rule cleans the source tree of all compiled code, not including the pdf
 #documentation.
@@ -225,21 +195,31 @@
 	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 *~
+         *.gcda *.gcno demos/*.gcno demos/*.gcda *~ doc/*
+	cd demos/test ; make clean   
 
 #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)
+	rm -f doc/crypt.pdf $(LEFTOVERS)
+	echo "hello" > crypt.ind
 	latex crypt > /dev/null
 	makeindex crypt > /dev/null
 	latex crypt > /dev/null
 	latex crypt > /dev/null
 	dvipdf crypt
+	mv -ivf crypt.pdf doc/crypt.pdf
 	rm -f $(LEFTOVERS)
-       
+
+docdvi: crypt.tex
+	echo hello > crypt.ind
+	latex crypt > /dev/null
+	latex crypt > /dev/null
+	makeindex crypt
+	latex crypt > /dev/null
+
 #beta
 beta: clean
 	cd .. ; rm -rf crypt* libtomcrypt-$(VERSION)-beta ; mkdir libtomcrypt-$(VERSION)-beta ; \
@@ -250,4 +230,6 @@
 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)/*
+	bzip2 -9vv crypt-$(VERSION).tar ; zip -9 -r crypt-$(VERSION).zip libtomcrypt-$(VERSION)/* ; \
+	gpg -b -a crypt-$(VERSION).tar.bz2 ; \
+   gpg -b -a crypt-$(VERSION).zip
--- a/makefile.cygwin_dll	Mon May 31 18:25:41 2004 +0000
+++ b/makefile.cygwin_dll	Tue Jun 15 14:07:21 2004 +0000
@@ -1,4 +1,4 @@
-
+#makefile for Cygwin [makes a .dll]
 
 default: ltc_dll
 
@@ -18,7 +18,7 @@
 #Leave MPI built-in or force developer to link against libtommath?
 MPIOBJECT=mpi.o
 
-OBJECTS=keyring.o gf.o strings.o base64.o \
+OBJECTS=error_to_string.o mpi_to_ltc_error.o base64_encode.o base64_decode.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    \
@@ -34,12 +34,16 @@
 \
 ecc.o  dh.o \
 \
-rsa.o rsa_exptmod.o  rsa_free.o  rsa_make_key.o \
+rsa_decrypt_key.o  rsa_encrypt_key.o  rsa_exptmod.o  rsa_free.o  rsa_make_key.o  \
+rsa_sign_hash.o  rsa_verify_hash.o rsa_export.o rsa_import.o tim_exptmod.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 \
+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 \
+aes.o aes_enc.o \
+\
+blowfish.o des.o safer_tab.o safer.o saferp.o rc2.o xtea.o \
+rc6.o rc5.o cast5.o noekeon.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 \
@@ -58,10 +62,10 @@
 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 \
+cbc_start.o cbc_encrypt.o cbc_decrypt.o cbc_getiv.o cbc_setiv.o \
+cfb_start.o cfb_encrypt.o cfb_decrypt.o cfb_getiv.o cfb_setiv.o \
+ofb_start.o ofb_encrypt.o ofb_decrypt.o ofb_getiv.o ofb_setiv.o \
+ctr_start.o ctr_encrypt.o ctr_decrypt.o ctr_getiv.o ctr_setiv.o \
 ecb_start.o ecb_encrypt.o ecb_decrypt.o \
 \
 hash_file.o  hash_filehandle.o  hash_memory.o \
@@ -70,15 +74,17 @@
 \
 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_1_v15_es_encode.o pkcs_1_v15_es_decode.o pkcs_1_v15_sa_encode.o pkcs_1_v15_sa_decode.o \
 \
 pkcs_5_1.o pkcs_5_2.o \
 \
 burn_stack.o zeromem.o \
 $(MPIOBJECT)
 
+#ciphers come in two flavours... enc+dec and enc 
+aes_enc.o: aes.c aes_tab.c
+	$(CC) $(CFLAGS) -DENCRYPT_ONLY -c aes.c -o aes_enc.o
+
 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
--- a/makefile.icc	Mon May 31 18:25:41 2004 +0000
+++ b/makefile.icc	Tue Jun 15 14:07:21 2004 +0000
@@ -24,6 +24,9 @@
 # Compilation flags. Note the += does not write over the user's CFLAGS!
 CFLAGS += -c -I./ -DINTEL_CC
 
+#The default rule for make builds the libtomcrypt library.
+default:library
+
 # optimize for SPEED
 #
 # -mcpu= can be pentium, pentiumpro (covers PII through PIII) or pentium4
@@ -47,7 +50,6 @@
 
 #Output filenames for various targets.
 LIBNAME=libtomcrypt.a
-TEST=test
 HASH=hashsum
 CRYPT=encrypt
 SMALL=small
@@ -67,7 +69,7 @@
 #Leave MPI built-in or force developer to link against libtommath?
 MPIOBJECT=mpi.o
 
-OBJECTS=keyring.o gf.o strings.o base64.o \
+OBJECTS=error_to_string.o mpi_to_ltc_error.o base64_encode.o base64_decode.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    \
@@ -83,12 +85,16 @@
 \
 ecc.o  dh.o \
 \
-rsa.o rsa_exptmod.o  rsa_free.o  rsa_make_key.o \
+rsa_decrypt_key.o  rsa_encrypt_key.o  rsa_exptmod.o  rsa_free.o  rsa_make_key.o  \
+rsa_sign_hash.o  rsa_verify_hash.o rsa_export.o rsa_import.o tim_exptmod.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 \
+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 \
+aes.o aes_enc.o \
+\
+blowfish.o des.o safer_tab.o safer.o saferp.o rc2.o xtea.o \
+rc6.o rc5.o cast5.o noekeon.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 \
@@ -107,10 +113,10 @@
 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 \
+cbc_start.o cbc_encrypt.o cbc_decrypt.o cbc_getiv.o cbc_setiv.o \
+cfb_start.o cfb_encrypt.o cfb_decrypt.o cfb_getiv.o cfb_setiv.o \
+ofb_start.o ofb_encrypt.o ofb_decrypt.o ofb_getiv.o ofb_setiv.o \
+ctr_start.o ctr_encrypt.o ctr_decrypt.o ctr_getiv.o ctr_setiv.o \
 ecb_start.o ecb_encrypt.o ecb_decrypt.o \
 \
 hash_file.o  hash_filehandle.o  hash_memory.o \
@@ -119,13 +125,18 @@
 \
 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_1_v15_es_encode.o pkcs_1_v15_es_decode.o pkcs_1_v15_sa_encode.o pkcs_1_v15_sa_decode.o \
 \
 pkcs_5_1.o pkcs_5_2.o \
 \
 burn_stack.o zeromem.o \
 $(MPIOBJECT)
 
-TESTOBJECTS=demos/test.o
+
+#ciphers come in two flavours... enc+dec and enc 
+aes_enc.o: aes.c aes_tab.c
+	$(CC) $(CFLAGS) -DENCRYPT_ONLY -c aes.c -o aes_enc.o
+
 HASHOBJECTS=demos/hashsum.o
 CRYPTOBJECTS=demos/encrypt.o
 SMALLOBJECTS=demos/small.o
@@ -143,9 +154,6 @@
 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
@@ -161,10 +169,6 @@
 $(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)
@@ -183,19 +187,7 @@
 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.
--- a/makefile.msvc	Mon May 31 18:25:41 2004 +0000
+++ b/makefile.msvc	Tue Jun 15 14:07:21 2004 +0000
@@ -8,8 +8,7 @@
 # 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 \
+OBJECTS=error_to_string.obj mpi_to_ltc_error.obj base64_encode.obj base64_decode.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    \
@@ -25,12 +24,16 @@
 \
 ecc.obj  dh.obj \
 \
-rsa.obj rsa_exptmod.obj  rsa_free.obj  rsa_make_key.obj \
+rsa_decrypt_key.obj  rsa_encrypt_key.obj  rsa_exptmod.obj  rsa_free.obj  rsa_make_key.obj  \
+rsa_sign_hash.obj  rsa_verify_hash.obj rsa_export.obj rsa_import.obj tim_exptmod.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 \
+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 \
+aes.obj aes_enc.obj \
+\
+blowfish.obj des.obj safer_tab.obj safer.obj saferp.obj rc2.obj xtea.obj \
+rc6.obj rc5.obj cast5.obj noekeon.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 \
@@ -49,10 +52,10 @@
 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 \
+cbc_start.obj cbc_encrypt.obj cbc_decrypt.obj cbc_getiv.obj cbc_setiv.obj \
+cfb_start.obj cfb_encrypt.obj cfb_decrypt.obj cfb_getiv.obj cfb_setiv.obj \
+ofb_start.obj ofb_encrypt.obj ofb_decrypt.obj ofb_getiv.obj ofb_setiv.obj \
+ctr_start.obj ctr_encrypt.obj ctr_decrypt.obj ctr_getiv.obj ctr_setiv.obj \
 ecb_start.obj ecb_encrypt.obj ecb_decrypt.obj \
 \
 hash_file.obj  hash_filehandle.obj  hash_memory.obj \
@@ -61,21 +64,20 @@
 \
 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_1_v15_es_encode.obj pkcs_1_v15_es_decode.obj pkcs_1_v15_sa_encode.obj pkcs_1_v15_sa_decode.obj \
 \
 pkcs_5_1.obj pkcs_5_2.obj \
 \
-burn_stack.obj zeromem.obj 	\
+burn_stack.obj zeromem.obj \
 $(MPIOBJECT)
 
+#ciphers come in two flavours... enc+dec and enc 
+aes_enc.obj: aes.c aes_tab.c
+	$(CC) $(CFLAGS) /DENCRYPT_ONLY /c aes.c /Foaes_enc.obj
+
 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 
 
--- a/md2.c	Mon May 31 18:25:41 2004 +0000
+++ b/md2.c	Tue Jun 15 14:07:21 2004 +0000
@@ -19,6 +19,13 @@
     7,
     16,
     16,
+
+    /* DER encoding */
+    { 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 
+      0x48, 0x86, 0xF7, 0x0D, 0x02, 0x02, 0x05, 0x00, 
+      0x04, 0x10 },
+    18,
+
     &md2_init,
     &md2_process,
     &md2_done,
--- a/md4.c	Mon May 31 18:25:41 2004 +0000
+++ b/md4.c	Tue Jun 15 14:07:21 2004 +0000
@@ -19,6 +19,11 @@
     6,
     16,
     64,
+ 
+    /* DER encoding (not yet supported) */
+    { 0x00 },
+    0,    
+
     &md4_init,
     &md4_process,
     &md4_done,
--- a/md5.c	Mon May 31 18:25:41 2004 +0000
+++ b/md5.c	Tue Jun 15 14:07:21 2004 +0000
@@ -21,6 +21,13 @@
     3,
     16,
     64,
+
+    /* DER identifier */
+    { 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 
+      0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 
+      0x04, 0x10 },
+    18,
+
     &md5_init,
     &md5_process,
     &md5_done,
@@ -44,6 +51,35 @@
 #define II(a,b,c,d,M,s,t) \
     a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b;
 
+#ifdef SMALL_CODE
+
+static const unsigned char Worder[64] = {
+   0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
+   1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,
+   5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,
+   0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9
+};
+
+static const unsigned char Rorder[64] = {
+   7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,
+   5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
+   4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,
+   6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21
+};
+
+static const ulong32 Korder[64] = {
+0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL,
+0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL,
+0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL,
+0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL,
+0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL,
+0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL,
+0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL,
+0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL
+};
+
+#endif   
+
 #ifdef CLEAN_STACK
 static void _md5_compress(hash_state *md, unsigned char *buf)
 #else
@@ -51,6 +87,9 @@
 #endif
 {
     ulong32 i, W[16], a, b, c, d;
+#ifdef SMALL_CODE
+    ulong32 t;
+#endif
 
     /* copy the state into 512-bits into W[0..15] */
     for (i = 0; i < 16; i++) {
@@ -63,6 +102,28 @@
     c = md->md5.state[2];
     d = md->md5.state[3];
 
+#ifdef SMALL_CODE
+    for (i = 0; i < 16; ++i) {
+        FF(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
+        t = d; d = c; c = b; b = a; a = t;
+    }
+
+    for (; i < 32; ++i) {
+        GG(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
+        t = d; d = c; c = b; b = a; a = t;
+    }
+
+    for (; i < 48; ++i) {
+        HH(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
+        t = d; d = c; c = b; b = a; a = t;
+    }
+
+    for (; i < 64; ++i) {
+        II(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]);
+        t = d; d = c; c = b; b = a; a = t;
+    }
+
+#else
     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)
@@ -127,6 +188,7 @@
     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)
+#endif
 
     md->md5.state[0] = md->md5.state[0] + a;
     md->md5.state[1] = md->md5.state[1] + b;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modes_test.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,46 @@
+/* test CFB/OFB/CBC modes */
+#include "test.h"
+
+int modes_test(void)
+{
+   unsigned char pt[64], ct[64], tmp[64], key[16], iv[16];
+   int x, cipher_idx;
+   symmetric_CBC cbc;
+   
+   /* make a random pt, key and iv */
+   yarrow_read(pt, 64,  &test_yarrow);
+   yarrow_read(key, 16, &test_yarrow);
+   yarrow_read(iv, 16,  &test_yarrow);
+   
+/* test CBC mode */
+   cipher_idx = find_cipher("aes");
+   if (cipher_idx == -1) {
+      printf("test requires AES");
+      return 1;
+   }
+   
+   
+   /* encode the block */
+   DO(cbc_start(cipher_idx, iv, key, 16, 0, &cbc));
+   for (x = 0; x < 4; x++) {
+      DO(cbc_encrypt(pt+x*16, ct+x*16, &cbc));
+   }
+   
+   /* decode the block */
+   DO(cbc_start(cipher_idx, iv, key, 16, 0, &cbc));
+   for (x = 0; x < 4; x++) {
+      DO(cbc_decrypt(ct+x*16, tmp+x*16, &cbc));
+   }
+   if (memcmp(tmp, pt, 64) != 0) {
+      printf("CBC failed");
+      return 1;
+   }
+   
+/*   
+   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);
+*/
+
+}
--- a/mpi.c	Mon May 31 18:25:41 2004 +0000
+++ b/mpi.c	Tue Jun 15 14:07:21 2004 +0000
@@ -13,7 +13,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 static const struct {
      int code;
@@ -58,7 +58,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* computes the modular inverse via binary extended euclidean algorithm, 
  * that is c = 1/a mod b 
@@ -205,7 +205,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* computes xR**-1 == x (mod N) via Montgomery Reduction
  *
@@ -376,7 +376,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* Fast (comba) multiplier
  *
@@ -452,7 +452,7 @@
   }
 
   /* setup dest */
-  olduse = c->used;
+  olduse  = c->used;
   c->used = digs;
 
   {
@@ -510,7 +510,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
- #include <tommath.h>
+ #include <ltc_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
@@ -612,7 +612,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* fast squaring
  *
@@ -755,7 +755,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* computes a = 2**b 
  *
@@ -801,7 +801,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* b = |a| 
  *
@@ -842,7 +842,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* high level addition (handles signs) */
 int mp_add (mp_int * a, mp_int * b, mp_int * c)
@@ -893,7 +893,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* single digit addition */
 int
@@ -1000,7 +1000,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* d = a + b (mod c) */
 int
@@ -1039,7 +1039,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* AND two ints together */
 int
@@ -1094,7 +1094,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* trim unused digits 
  *
@@ -1136,7 +1136,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* clear one (frees)  */
 void
@@ -1174,7 +1174,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 #include <stdarg.h>
 
 void mp_clear_multi(mp_int *mp, ...) 
@@ -1206,7 +1206,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* compare two ints (signed)*/
 int
@@ -1247,7 +1247,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* compare a digit */
 int mp_cmp_d(mp_int * a, mp_digit b)
@@ -1289,7 +1289,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* compare maginitude of two ints (unsigned) */
 int mp_cmp_mag (mp_int * a, mp_int * b)
@@ -1342,7 +1342,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 static const int lnz[16] = { 
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
@@ -1393,7 +1393,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* copy, b = a */
 int
@@ -1459,7 +1459,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* returns the number of bits in an int */
 int
@@ -1502,7 +1502,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* integer signed division. 
  * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
@@ -1717,7 +1717,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* b = a/2 */
 int mp_div_2(mp_int * a, mp_int * b)
@@ -1783,7 +1783,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_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)
@@ -1878,7 +1878,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* divide by three (based on routine from MPI and the GMP manual) */
 int
@@ -1955,7 +1955,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 static int s_is_power_of_two(mp_digit b, int *p)
 {
@@ -2061,7 +2061,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* determines if a number is a valid DR modulus */
 int mp_dr_is_modulus(mp_int *a)
@@ -2102,7 +2102,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
  *
@@ -2194,7 +2194,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* determines the setup value */
 void mp_dr_setup(mp_int *a, mp_digit *d)
@@ -2224,7 +2224,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* swap the elements of two integers, for cases where you can't simply swap the 
  * mp_int pointers around
@@ -2256,7 +2256,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* calculate c = a**b  using a square-multiply algorithm */
 int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
@@ -2311,7 +2311,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 
 /* this is a shell function that calls either the normal or Montgomery
@@ -2393,7 +2393,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
  *
@@ -2684,7 +2684,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* Extended euclidean algorithm of (a, b) produces 
    a*u1 + b*u2 = u3
@@ -2757,7 +2757,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* read a bigint from a file stream in ASCII */
 int mp_fread(mp_int *a, int radix, FILE *stream)
@@ -2822,7 +2822,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 int mp_fwrite(mp_int *a, int radix, FILE *stream)
 {
@@ -2872,7 +2872,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* Greatest Common Divisor using the binary method */
 int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
@@ -2983,7 +2983,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* get the lower 32-bits of an mp_int */
 unsigned long mp_get_int(mp_int * a) 
@@ -3026,7 +3026,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* grow as required */
 int mp_grow (mp_int * a, int size)
@@ -3081,7 +3081,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* init a new bigint */
 int mp_init (mp_int * a)
@@ -3118,7 +3118,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* creates "a" then copies b into it */
 int mp_init_copy (mp_int * a, mp_int * b)
@@ -3148,7 +3148,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 #include <stdarg.h>
 
 int mp_init_multi(mp_int *mp, ...) 
@@ -3205,7 +3205,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* initialize and set a digit */
 int mp_init_set (mp_int * a, mp_digit b)
@@ -3235,7 +3235,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* initialize and set a digit */
 int mp_init_set_int (mp_int * a, unsigned long b)
@@ -3264,7 +3264,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* init an mp_init for a given size */
 int mp_init_size (mp_int * a, int size)
@@ -3301,7 +3301,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* hac 14.61, pp608 */
 int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
@@ -3479,7 +3479,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* Check if remainders are possible squares - fast exclude non-squares */
 static const char rem_128[128] = {
@@ -3586,7 +3586,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* computes the jacobi c = (a | n) (or Legendre if n is prime)
  * HAC pp. 73 Algorithm 2.149
@@ -3689,7 +3689,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* c = |a| * |b| using Karatsuba Multiplication using 
  * three half size multiplications
@@ -3857,7 +3857,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* Karatsuba squaring, computes b = a*a using three 
  * half size squarings
@@ -3976,7 +3976,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* computes least common multiple as |a*b|/(a, b) */
 int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
@@ -4034,7 +4034,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* shift left a certain amount of digits */
 int mp_lshd (mp_int * a, int b)
@@ -4099,7 +4099,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* c = a mod b, 0 <= c < b */
 int
@@ -4145,7 +4145,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* calc a value mod 2**b */
 int
@@ -4198,7 +4198,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 int
 mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
@@ -4223,7 +4223,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* calculates a = B^n mod b for Montgomery reduction
  * Where B is the base [e.g. 2^DIGIT_BIT].
@@ -4280,7 +4280,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* computes xR**-1 == x (mod N) via Montgomery Reduction */
 int
@@ -4396,7 +4396,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* setups the montgomery reduction stuff */
 int
@@ -4453,7 +4453,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* high level multiplication (handles sign) */
 int mp_mul (mp_int * a, mp_int * b, mp_int * c)
@@ -4505,7 +4505,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* b = a*2 */
 int mp_mul_2(mp_int * a, mp_int * b)
@@ -4585,7 +4585,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* shift left by a certain bit count */
 int mp_mul_2d (mp_int * a, int b, mp_int * c)
@@ -4668,7 +4668,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* multiply by a digit */
 int
@@ -4744,7 +4744,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* d = a * b (mod c) */
 int
@@ -4783,7 +4783,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* find the n'th root of an integer 
  *
@@ -4913,7 +4913,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* b = -a */
 int mp_neg (mp_int * a, mp_int * b)
@@ -4945,7 +4945,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* OR two ints together */
 int mp_or (mp_int * a, mp_int * b, mp_int * c)
@@ -4993,7 +4993,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* performs one Fermat test.
  * 
@@ -5053,7 +5053,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* determines if an integers is divisible by one 
  * of the first PRIME_SIZE primes or not
@@ -5101,7 +5101,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* performs a variable number of rounds of Miller-Rabin
  *
@@ -5182,7 +5182,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* Miller-Rabin test of "a" to the base of "b" as described in 
  * HAC pp. 139 Algorithm 4.24
@@ -5283,7 +5283,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* finds the next prime after the number "a" using "t" trials
  * of Miller-Rabin.
@@ -5451,7 +5451,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* makes a truly random prime of a given size (bits),
  *
@@ -5573,7 +5573,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* returns size of ASCII reprensentation */
 int mp_radix_size (mp_int * a, int radix, int *size)
@@ -5642,7 +5642,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* chars used in radix conversions */
 const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
@@ -5664,7 +5664,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* makes a pseudo-random int of a given size */
 int
@@ -5717,7 +5717,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* read a string [ASCII] in a given radix */
 int mp_read_radix (mp_int * a, char *str, int radix)
@@ -5797,7 +5797,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* read signed bin, big endian, first byte is 0==positive or 1==negative */
 int
@@ -5837,7 +5837,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* reads a unsigned char array, assumes the msb is stored first [big endian] */
 int
@@ -5891,7 +5891,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* reduces x mod m, assumes 0 < x < m**2, mu is 
  * precomputed via mp_reduce_setup.
@@ -5979,7 +5979,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* reduces a modulo n where n is of the form 2**p - d */
 int
@@ -6039,7 +6039,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* determines the setup value */
 int 
@@ -6085,7 +6085,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* determines if mp_reduce_2k can be used */
 int mp_reduce_is_2k(mp_int *a)
@@ -6134,7 +6134,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* pre-calculate the value required for Barrett reduction
  * For a given modulus "b" it calulates the value required in "a"
@@ -6167,7 +6167,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* shift right a certain amount of digits */
 void mp_rshd (mp_int * a, int b)
@@ -6237,7 +6237,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* set to a digit */
 void mp_set (mp_int * a, mp_digit b)
@@ -6264,7 +6264,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* set a 32-bit const */
 int mp_set_int (mp_int * a, unsigned long b)
@@ -6310,7 +6310,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* shrink a bignum */
 int mp_shrink (mp_int * a)
@@ -6343,7 +6343,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* get the size for an signed equivalent */
 int mp_signed_bin_size (mp_int * a)
@@ -6368,7 +6368,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* computes b = a*a */
 int
@@ -6413,7 +6413,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* c = a * a (mod b) */
 int
@@ -6452,7 +6452,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* this function is less generic than mp_n_root, simpler and faster */
 int mp_sqrt(mp_int *arg, mp_int *ret) 
@@ -6531,7 +6531,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* high level subtraction (handles signs) */
 int
@@ -6588,7 +6588,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* single digit subtraction */
 int
@@ -6675,7 +6675,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* d = a - b (mod c) */
 int
@@ -6715,7 +6715,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* store in signed [big endian] format */
 int
@@ -6747,7 +6747,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* store in unsigned [big endian] format */
 int
@@ -6794,7 +6794,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* multiplication using the Toom-Cook 3-way algorithm */
 int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
@@ -7070,7 +7070,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* squaring using Toom-Cook 3-way algorithm */
 int
@@ -7294,7 +7294,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_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)
@@ -7367,7 +7367,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* stores a bignum as a ASCII string in a given radix (2..64) 
  *
@@ -7454,7 +7454,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* get the size for an unsigned equivalent */
 int
@@ -7481,7 +7481,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* XOR two ints together */
 int
@@ -7530,7 +7530,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* set to zero */
 void
@@ -7558,7 +7558,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* this table gives the # of rabin miller trials for a prob of failure lower than 2^-96 */
 static const struct {
@@ -7613,7 +7613,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 const mp_digit __prime_tab[] = {
   0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
   0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
@@ -7672,7 +7672,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* reverse an array, used for radix code */
 void
@@ -7709,7 +7709,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* low level addition, based on HAC pp.594, Algorithm 14.7 */
 int
@@ -7816,7 +7816,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 #ifdef MP_LOW_MEM
    #define TAB_SIZE 32
@@ -8054,7 +8054,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_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 
@@ -8143,7 +8143,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* multiplies |a| * |b| and does not compute the lower digs digits
  * [meant to get the higher part of the product]
@@ -8220,7 +8220,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
 int
@@ -8303,7 +8303,7 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_tommath.h>
 
 /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
 int
@@ -8390,20 +8390,22 @@
  *
  * Tom St Denis, [email protected], http://math.libtomcrypt.org
  */
-#include <tommath.h>
+#include <ltc_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
-
+ Intel P4 Northwood     /GCC v3.3.3   /        59/        81/profiled build
+ Intel P4 Northwood     /GCC v3.3.3   /        59/        80/profiled_single build
+ Intel P4 Northwood     /ICC v8.0     /        57/        70/profiled build
+ Intel P4 Northwood     /ICC v8.0     /        54/        76/profiled_single build
+ 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. */
+int     KARATSUBA_MUL_CUTOFF = 57,      /* Min. number of digits before Karatsuba multiplication is used. */
+        KARATSUBA_SQR_CUTOFF = 70,      /* 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; 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpi_to_ltc_error.c	Tue Jun 15 14:07:21 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"
+
+#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},
+};
+
+/* 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
+
--- a/mycrypt.h	Mon May 31 18:25:41 2004 +0000
+++ b/mycrypt.h	Tue Jun 15 14:07:21 2004 +0000
@@ -16,8 +16,8 @@
 #endif
 
 /* version */
-#define CRYPT   0x0095
-#define SCRYPT  "0.95"
+#define CRYPT   0x0096
+#define SCRYPT  "0.96"
 
 /* max size of either a cipher/hash block or symmetric key [largest of the two] */
 #define MAXBLOCKSIZE           128
@@ -68,9 +68,7 @@
 #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>
 
--- a/mycrypt_cipher.h	Mon May 31 18:25:41 2004 +0000
+++ b/mycrypt_cipher.h	Tue Jun 15 14:07:21 2004 +0000
@@ -261,12 +261,22 @@
 #define aes_test            rijndael_test
 #define aes_keysize         rijndael_keysize
 
+#define aes_enc_setup           rijndael_enc_setup
+#define aes_enc_ecb_encrypt     rijndael_enc_ecb_encrypt
+#define aes_enc_keysize         rijndael_enc_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 int rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+extern void rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+extern int rijndael_enc_keysize(int *desired_keysize);
+
 extern const struct _cipher_descriptor rijndael_desc, aes_desc;
+extern const struct _cipher_descriptor rijndael_enc_desc, aes_enc_desc;
 #endif
 
 #ifdef XTEA
@@ -342,6 +352,8 @@
                      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);
+extern int cfb_getiv(unsigned char *IV, unsigned long *len, symmetric_CFB *cfb);
+extern int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb);
 #endif
 
 #ifdef OFB
@@ -349,6 +361,8 @@
                      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);
+extern int ofb_getiv(unsigned char *IV, unsigned long *len, symmetric_OFB *ofb);
+extern int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb);
 #endif
 
 #ifdef CBC
@@ -356,6 +370,8 @@
                      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);
+extern int cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc);
+extern int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc);
 #endif
 
 #ifdef CTR
@@ -363,6 +379,8 @@
                      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);
+extern int ctr_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr);
+extern int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr);
 #endif
 
 
--- a/mycrypt_custom.h	Mon May 31 18:25:41 2004 +0000
+++ b/mycrypt_custom.h	Tue Jun 15 14:07:21 2004 +0000
@@ -9,14 +9,27 @@
 	#error mycrypt_custom.h should be included before mycrypt.h
 #endif
 
+/* macros for various libc functions */
 #define XMALLOC malloc
 #define XREALLOC realloc
 #define XCALLOC calloc
 #define XFREE free
 #define XCLOCK clock
 #define XCLOCKS_PER_SEC CLOCKS_PER_SEC
+
+/* Use small code where possible */
 #define SMALL_CODE
+
+/* Enable self-test test vector checking */
 #define LTC_TEST
+
+/* clean the stack of functions which put private information on stack */
+//#define CLEAN_STACK
+
+/* disable all file related functions */
+//#define NO_FILE
+
+/* various ciphers */
 #define BLOWFISH
 #define RC2
 #define RC5
@@ -26,15 +39,21 @@
 #define XTEA
 #define TWOFISH
 #define TWOFISH_TABLES
+//#define TWOFISH_ALL_TABLES
+//#define TWOFISH_SMALL
 #define DES
 #define CAST5
 #define NOEKEON
 #define SKIPJACK
+
+/* modes of operation */
 #define CFB
 #define OFB
 #define ECB
 #define CBC
 #define CTR
+
+/* hash functions */
 #define WHIRLPOOL
 #define SHA512
 #define SHA384
@@ -47,18 +66,30 @@
 #define MD2
 #define RIPEMD128
 #define RIPEMD160
+
+/* MAC functions */
 #define HMAC
 #define OMAC
 #define PMAC
+
+/* Encrypt + Authenticate Modes */
 #define EAX_MODE
 #define OCB_MODE
+
+/* Various tidbits of modern neatoness */
 #define BASE64
 #define YARROW
+// which descriptor of AES to use? 
+// 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full]
+#define YARROW_AES 0
 #define SPRNG
 #define RC4
 #define DEVRANDOM
 #define TRY_URANDOM_FIRST
+
+/* Public Key Neatoness */
 #define MRSA
+#define RSA_TIMING                   // enable RSA side channel timing prevention 
 #define MDSA
 #define MDH
 #define MECC
@@ -79,10 +110,10 @@
 #define ECC521
 #define MPI
 
+/* PKCS #1 and 5 stuff */
 #define PKCS_1
 #define PKCS_5
 
-
 #include <mycrypt.h>
 
 #endif
--- a/mycrypt_gf.h	Mon May 31 18:25:41 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-
-/* ---- 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
--- a/mycrypt_hash.h	Mon May 31 18:25:41 2004 +0000
+++ b/mycrypt_hash.h	Tue Jun 15 14:07:21 2004 +0000
@@ -116,6 +116,8 @@
     unsigned char ID;
     unsigned long hashsize;       /* digest output size in bytes  */
     unsigned long blocksize;      /* the block size the hash uses */
+    unsigned char DER[64];        /* DER encoded identifier */
+    unsigned long DERlen;         /* length of DER encoding */
     void (*init)(hash_state *);
     int (*process)(hash_state *, const unsigned char *, unsigned long);
     int (*done)(hash_state *, unsigned char *);
--- a/mycrypt_pk.h	Mon May 31 18:25:41 2004 +0000
+++ b/mycrypt_pk.h	Tue Jun 15 14:07:21 2004 +0000
@@ -1,7 +1,7 @@
 /* ---- NUMBER THEORY ---- */
 #ifdef MPI
 
-#include "tommath.h"
+#include "ltc_tommath.h"
 
 /* in/out macros */
 #define OUTPUT_BIGNUM(num, out, y, z)                                                             \
@@ -86,7 +86,7 @@
 #define MAX_RSA_SIZE 4096
 
 /* Stack required for temps (plus padding) */
-#define RSA_STACK    (8 + (MAX_RSA_SIZE/8))
+// #define RSA_STACK    (8 + (MAX_RSA_SIZE/8))
 
 typedef struct Rsa_key {
     int type;
@@ -95,43 +95,51 @@
 
 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_exptmod(const unsigned char *in,   unsigned long inlen,
+                      unsigned char *out,  unsigned long *outlen, int which,
+                      prng_state    *prng, int           prng_idx,
+                      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);
+#ifdef RSA_TIMING
 
-extern int rsa_signpad(const unsigned char *in,  unsigned long inlen, 
-                             unsigned char *out, unsigned long *outlen);
+extern int tim_exptmod(prng_state *prng, int prng_idx, 
+                       mp_int *c, mp_int *e, mp_int *d, mp_int *n, mp_int *m);
 
-extern int rsa_depad(const unsigned char *in,  unsigned long inlen, 
-                           unsigned char *out, unsigned long *outlen);
+#else
 
-extern int rsa_signdepad(const unsigned char *in,  unsigned long inlen,
-                               unsigned char *out, unsigned long *outlen);
+#define tim_exptmod(prng, prng_idx, c, e, d, n, m) mpi_to_ltc_error(mp_exptmod(c, d, n, m))
 
+#endif
 
 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);
+int rsa_encrypt_key(const unsigned char *inkey,  unsigned long inlen,
+                          unsigned char *outkey, unsigned long *outlen,
+                    const unsigned char *lparam, unsigned long lparamlen,
+                    prng_state *prng, int prng_idx, int hash_idx, rsa_key *key);
+                                        
+int rsa_decrypt_key(const unsigned char *in,     unsigned long inlen,
+                          unsigned char *outkey, unsigned long *keylen, 
+                    const unsigned char *lparam, unsigned long lparamlen,
+                          prng_state    *prng,   int           prng_idx,
+                          int            hash_idx, int *res,
+                          rsa_key       *key);
 
-extern int rsa_sign_hash(const unsigned char *in,  unsigned long inlen, 
-                               unsigned char *out, unsigned long *outlen, 
-                               rsa_key *key);
+int rsa_sign_hash(const unsigned char *msghash,  unsigned long  msghashlen, 
+                        unsigned char *sig,      unsigned long *siglen, 
+                        prng_state    *prng,     int            prng_idx,
+                        int            hash_idx, unsigned long  saltlen,
+                        rsa_key *key);
 
-extern int rsa_verify_hash(const unsigned char *sig, unsigned long siglen,
-                           const unsigned char *hash, int *stat, rsa_key *key);
+int rsa_verify_hash(const unsigned char *sig,      unsigned long siglen,
+                    const unsigned char *msghash,  unsigned long msghashlen,
+                          prng_state    *prng,     int           prng_idx,
+                          int            hash_idx, unsigned long saltlen,
+                          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);
+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);
+                        
 #endif
 
 /* ---- DH Routines ---- */
--- a/mycrypt_pkcs.h	Mon May 31 18:25:41 2004 +0000
+++ b/mycrypt_pkcs.h	Tue Jun 15 14:07:21 2004 +0000
@@ -7,20 +7,25 @@
                       int            hash_idx,
                       unsigned char *mask, unsigned long masklen);
 
+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);
+
+/* *** v2.0 padding */
 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 long modulus_bitlen, prng_state *prng,
+                             int           prng_idx,         int  hash_idx,
                              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);
+                             unsigned char *out,    unsigned long *outlen,
+                             int           *res);
 
 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 saltlen,  prng_state   *prng,     
+                            int           prng_idx, int           hash_idx,
                             unsigned long modulus_bitlen,
                             unsigned char *out,     unsigned long *outlen);
 
@@ -29,8 +34,30 @@
                             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);
+/* *** v1.5 padding */
+/* encryption padding */
+int pkcs_1_v15_es_encode(const unsigned char *msg,    unsigned long msglen,
+                               unsigned long  modulus_bitlen, 
+                               prng_state    *prng,   int           prng_idx,
+                               unsigned char *out,    unsigned long *outlen);
+
+/* note "outlen" is fixed, you have to tell this decoder how big
+ * the original message was.  Unlike the OAEP decoder it cannot auto-detect it.
+ */
+int pkcs_1_v15_es_decode(const unsigned char *msg,  unsigned long msglen,
+                               unsigned long modulus_bitlen,
+                               unsigned char *out,  unsigned long outlen,
+                               int           *res);
+
+/* signature padding */
+int pkcs_1_v15_sa_encode(const unsigned char *msghash,  unsigned long msghashlen,
+                               int            hash_idx, unsigned long modulus_bitlen,
+                               unsigned char *out,      unsigned long *outlen);
+
+int pkcs_1_v15_sa_decode(const unsigned char *msghash, unsigned long msghashlen,
+                         const unsigned char *sig,     unsigned long siglen,
+                               int           hash_idx, unsigned long modulus_bitlen, 
+                               int          *res);
 
 
 #endif /* PKCS_1 */
--- a/ocb_decrypt.c	Mon May 31 18:25:41 2004 +0000
+++ b/ocb_decrypt.c	Tue Jun 15 14:07:21 2004 +0000
@@ -22,9 +22,14 @@
    _ARGCHK(ocb != NULL);
    _ARGCHK(pt  != NULL);
    _ARGCHK(ct  != NULL);
+
+   /* check if valid cipher */
    if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) {
       return err;
    }
+   _ARGCHK(cipher_descriptor[ocb->cipher].ecb_decrypt != NULL);
+   
+   /* check length */
    if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) {
       return CRYPT_INVALID_ARG;
    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ofb_getiv.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,30 @@
+/* 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_getiv(unsigned char *IV, unsigned long *len, symmetric_OFB *ofb)
+{
+   _ARGCHK(IV  != NULL);
+   _ARGCHK(len != NULL);
+   _ARGCHK(ofb != NULL);
+   if ((unsigned long)ofb->blocklen > *len) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+   memcpy(IV, ofb->IV, ofb->blocklen);
+   *len = ofb->blocklen;
+
+   return CRYPT_OK;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ofb_setiv.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,38 @@
+/* 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_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb)
+{
+   int err;
+
+   _ARGCHK(IV  != NULL);
+   _ARGCHK(ofb != NULL);
+
+   if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) {
+       return err;
+   }
+
+   if (len != (unsigned long)ofb->blocklen) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* force next block */
+   ofb->padlen = 0;
+   cipher_descriptor[ofb->cipher].ecb_encrypt(IV, ofb->IV, &ofb->key);
+   return CRYPT_OK;
+}
+
+#endif 
+
--- a/pkcs_1_oaep_decode.c	Mon May 31 18:25:41 2004 +0000
+++ b/pkcs_1_oaep_decode.c	Tue Jun 15 14:07:21 2004 +0000
@@ -15,9 +15,10 @@
 #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)
+                       const unsigned char *lparam, unsigned long lparamlen,
+                             unsigned long modulus_bitlen, int hash_idx,
+                             unsigned char *out,    unsigned long *outlen,
+                             int           *res)
 {
    unsigned char DB[1024], seed[MAXBLOCKSIZE], mask[sizeof(DB)];
    unsigned long hLen, x, y, modulus_len;
@@ -26,6 +27,10 @@
    _ARGCHK(msg    != NULL);
    _ARGCHK(out    != NULL);
    _ARGCHK(outlen != NULL);
+   _ARGCHK(res    != NULL);
+
+   /* default to invalid packet */
+   *res = 0;
    
    /* test valid hash */
    if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { 
@@ -49,7 +54,7 @@
 
    /* must have leading 0x00 byte */
    if (msg[0] != 0x00) {
-      return CRYPT_INVALID_PACKET;
+      return CRYPT_OK;
    }
 
    /* now read the masked seed */
@@ -99,7 +104,7 @@
 
    /* compare the lhash'es */
    if (memcmp(seed, DB, hLen) != 0) {
-      return CRYPT_INVALID_PACKET;
+      return CRYPT_OK;
    }
 
    /* now zeroes before a 0x01 */
@@ -109,7 +114,7 @@
 
    /* error out if wasn't 0x01 */
    if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) {
-      return CRYPT_INVALID_PACKET;
+      return CRYPT_OK;
    }
 
    /* rest is the message (and skip 0x01) */
@@ -129,6 +134,9 @@
    zeromem(mask, sizeof(mask));
 #endif
 
+   /* valid packet */
+   *res = 1;
+
    return CRYPT_OK;
 }
 
--- a/pkcs_1_oaep_encode.c	Mon May 31 18:25:41 2004 +0000
+++ b/pkcs_1_oaep_encode.c	Tue Jun 15 14:07:21 2004 +0000
@@ -15,10 +15,10 @@
 #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)
+                       const unsigned char *lparam, unsigned long lparamlen,
+                             unsigned long modulus_bitlen, prng_state *prng,
+                             int           prng_idx,         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;
--- a/pkcs_1_pss_decode.c	Mon May 31 18:25:41 2004 +0000
+++ b/pkcs_1_pss_decode.c	Tue Jun 15 14:07:21 2004 +0000
@@ -60,7 +60,7 @@
    }
 
    /* check the MSB */
-   if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - modulus_bitlen))) != 0) {
+   if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)))) != 0) {
       return CRYPT_OK;
    }
 
@@ -73,6 +73,9 @@
    for (y = 0; y < (modulus_len - hLen - 1); y++) {
       DB[y] ^= mask[y];
    }
+   
+   /* now clear the first byte [make sure smaller than modulus] */
+   DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1));
 
    /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */
 
--- a/pkcs_1_pss_encode.c	Mon May 31 18:25:41 2004 +0000
+++ b/pkcs_1_pss_encode.c	Tue Jun 15 14:07:21 2004 +0000
@@ -15,8 +15,8 @@
 #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 saltlen,  prng_state   *prng,     
+                            int           prng_idx, int           hash_idx,
                             unsigned long modulus_bitlen,
                             unsigned char *out,     unsigned long *outlen)
 {
@@ -104,7 +104,7 @@
    out[y] = 0xBC;
 
    /* now clear the 8*modulus_len - modulus_bitlen most significant bits */
-   out[0] &= 0xFF >> ((modulus_len<<3) - modulus_bitlen);
+   out[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1));
 
    /* store output size */
    *outlen = modulus_len;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkcs_1_v15_es_decode.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,61 @@
+/* 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 v1.5 Encryption Padding -- Tom St Denis */
+
+#ifdef PKCS_1
+
+int pkcs_1_v15_es_decode(const unsigned char *msg,  unsigned long msglen,
+                               unsigned long modulus_bitlen,
+                               unsigned char *out,  unsigned long outlen,
+                               int           *res)
+{
+   unsigned long x, modulus_bytelen;
+
+   _ARGCHK(msg != NULL);
+   _ARGCHK(out != NULL);
+   _ARGCHK(res != NULL);
+   
+   /* default to failed */
+   *res = 0;
+
+   /* must be at least 12 bytes long */
+   if (msglen < 12) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   modulus_bytelen = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+   /* should start with 0x00 0x02 */
+   if (msg[0] != 0x00 || msg[1] != 0x02) {
+      return CRYPT_OK;
+   }
+   
+   /* skip over PS */
+   x = 2 + (modulus_bytelen - outlen - 3);
+
+   /* should be 0x00 */
+   if (msg[x++] != 0x00) {
+      return CRYPT_OK;
+   }
+
+   /* the message is left */
+   if (x + outlen > modulus_bytelen) {
+      return CRYPT_PK_INVALID_SIZE;
+   }
+   memcpy(out, msg + x, outlen);
+   *res = 1;
+   return CRYPT_OK;
+}
+
+#endif 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkcs_1_v15_es_encode.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,55 @@
+/* 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"
+
+/* v1.5 Encryption Padding for PKCS #1 -- Tom St Denis */
+
+#ifdef PKCS_1
+
+int pkcs_1_v15_es_encode(const unsigned char *msg,    unsigned long msglen,
+                               unsigned long  modulus_bitlen, 
+                               prng_state    *prng,   int           prng_idx,
+                               unsigned char *out,    unsigned long *outlen)
+{ 
+   unsigned long modulus_bytelen, x, y;
+
+   _ARGCHK(msg    != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* get modulus len */
+   modulus_bytelen = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+   if (modulus_bytelen < 12) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* verify length */
+   if (msglen > (modulus_bytelen - 11) || *outlen < modulus_bytelen) {
+      return CRYPT_PK_INVALID_SIZE;
+   }
+
+   /* 0x00 0x02 PS 0x00 M */
+   x = 0;
+   out[x++] = 0x00;
+   out[x++] = 0x02;
+   y = modulus_bytelen - msglen - 3;
+   if (prng_descriptor[prng_idx].read(out+x, y, prng) != y) {
+      return CRYPT_ERROR_READPRNG;
+   }
+   x += y;
+   out[x++] = 0x00;
+   memcpy(out+x, msg, msglen);
+   *outlen = modulus_bytelen;
+
+   return CRYPT_OK;
+}
+
+#endif /* PKCS_1 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkcs_1_v15_sa_decode.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,77 @@
+/* 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 v1.5 Signature Padding -- Tom St Denis */
+
+#ifdef PKCS_1
+
+int pkcs_1_v15_sa_decode(const unsigned char *msghash, unsigned long msghashlen,
+                         const unsigned char *sig,     unsigned long siglen,
+                               int           hash_idx, unsigned long modulus_bitlen, 
+                               int          *res)
+{
+   unsigned long x, y, modulus_bytelen, derlen;
+   int err;
+   
+   _ARGCHK(msghash != NULL);
+   _ARGCHK(sig     != NULL);
+   _ARGCHK(res     != NULL);
+
+   /* default to invalid */
+   *res = 0;
+
+   /* valid hash ? */
+   if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* get derlen */
+   derlen = hash_descriptor[hash_idx].DERlen;
+
+   /* get modulus len */
+   modulus_bytelen = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+   /* valid sizes? */
+   if ((msghashlen + 3 + derlen > modulus_bytelen) || (siglen != modulus_bytelen)) {
+      return CRYPT_PK_INVALID_SIZE;
+   }
+
+   /* packet is 0x00 0x01 PS 0x00 T, where PS == 0xFF repeated modulus_bytelen - 3 - derlen - msghashlen times, T == DER || hash */
+   x = 0;
+   if (sig[x++] != 0x00 || sig[x++] != 0x01) {
+      return CRYPT_OK;
+   }
+
+   /* now follows (modulus_bytelen - 3 - derlen - msghashlen) 0xFF bytes */
+   for (y = 0; y < (modulus_bytelen - 3 - derlen - msghashlen); y++) {
+     if (sig[x++] != 0xFF) {
+        return CRYPT_OK;
+     }
+   }
+
+   if (sig[x++] != 0x00) {
+      return CRYPT_OK;
+   }
+
+   for (y = 0; y < derlen; y++) {
+      if (sig[x++] != hash_descriptor[hash_idx].DER[y]) {
+         return CRYPT_OK;
+      }
+   }
+
+   if (memcmp(msghash, sig+x, msghashlen) == 0) {
+      *res = 1;
+   }
+   return CRYPT_OK;
+}
+
+#endif 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkcs_1_v15_sa_encode.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,71 @@
+/* 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 v1.5 Signature Padding -- Tom St Denis */
+
+#ifdef PKCS_1
+
+int pkcs_1_v15_sa_encode(const unsigned char *msghash,  unsigned long msghashlen,
+                               int            hash_idx, unsigned long modulus_bitlen,
+                               unsigned char *out,      unsigned long *outlen)
+{
+  unsigned long derlen, modulus_bytelen, x, y;
+  int err;
+
+  _ARGCHK(msghash != NULL)
+  _ARGCHK(out     != NULL);
+  _ARGCHK(outlen  != NULL);
+
+  if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+     return err;
+  }
+
+  /* hack, to detect any hash without a DER OID */
+  if (hash_descriptor[hash_idx].DERlen == 0) {
+     return CRYPT_INVALID_ARG; 
+  }
+
+  /* get modulus len */
+  modulus_bytelen = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+  /* get der len ok?  Forgive my lame German accent.... */
+  derlen = hash_descriptor[hash_idx].DERlen;
+
+  /* valid sizes? */
+  if (msghashlen + 3 + derlen > modulus_bytelen) {
+     return CRYPT_PK_INVALID_SIZE;
+  }
+
+  if (*outlen < modulus_bytelen) {
+     return CRYPT_BUFFER_OVERFLOW;
+  }
+
+  /* packet is 0x00 0x01 PS 0x00 T, where PS == 0xFF repeated modulus_bytelen - 3 - derlen - msghashlen times, T == DER || hash */
+  x = 0;
+  out[x++] = 0x00;
+  out[x++] = 0x01;
+  for (y = 0; y < (modulus_bytelen - 3 - derlen - msghashlen); y++) {
+     out[x++] = 0xFF;
+  }
+  out[x++] = 0x00;
+  for (y = 0; y < derlen; y++) {
+     out[x++] = hash_descriptor[hash_idx].DER[y];
+  }
+  for (y = 0; y < msghashlen; y++) {
+     out[x++] = msghash[y];
+  }
+
+  *outlen = modulus_bytelen;
+  return CRYPT_OK;
+}
+
+#endif /* PKCS_1 */
--- a/rand_prime.c	Mon May 31 18:25:41 2004 +0000
+++ b/rand_prime.c	Tue Jun 15 14:07:21 2004 +0000
@@ -54,11 +54,7 @@
    /* 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;
+   return mpi_to_ltc_error(mp_prime_random_ex(N, mp_prime_rabin_miller_trials(len), len, type, rand_prime_helper, &rng));
 }
       
 #endif
--- a/rmd128.c	Mon May 31 18:25:41 2004 +0000
+++ b/rmd128.c	Tue Jun 15 14:07:21 2004 +0000
@@ -24,6 +24,11 @@
     8,
     16,
     64,
+
+    /* DER identifier (not supported) */
+    { 0x00 },
+    0,
+
     &rmd128_init,
     &rmd128_process,
     &rmd128_done,
--- a/rmd160.c	Mon May 31 18:25:41 2004 +0000
+++ b/rmd160.c	Tue Jun 15 14:07:21 2004 +0000
@@ -24,6 +24,12 @@
     9,
     20,
     64,
+
+    /* DER identifier */
+    { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 
+      0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 },
+    15,
+
     &rmd160_init,
     &rmd160_process,
     &rmd160_done,
--- a/rsa.c	Mon May 31 18:25:41 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,273 +0,0 @@
-/* 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_decrypt_key.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,61 @@
+/* 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 MRSA
+
+/* decrypt then OAEP depad  */
+int rsa_decrypt_key(const unsigned char *in,     unsigned long inlen,
+                          unsigned char *outkey, unsigned long *keylen, 
+                    const unsigned char *lparam, unsigned long lparamlen,
+                          prng_state    *prng,   int           prng_idx,
+                          int            hash_idx, int *res,
+                          rsa_key       *key)
+{
+  unsigned long modulus_bitlen, modulus_bytelen, x;
+  int           err;
+  
+  _ARGCHK(outkey != NULL);
+  _ARGCHK(keylen != NULL);
+  _ARGCHK(key    != NULL);
+  _ARGCHK(res    != NULL);
+  
+  /* valid hash ? */
+  if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+     return err;
+  }
+  
+  /* get modulus len in bits */
+  modulus_bitlen = mp_count_bits(&(key->N));
+
+  /* outlen must be at least the size of the modulus */
+  modulus_bytelen = mp_unsigned_bin_size(&(key->N));
+  if (modulus_bytelen != inlen) {
+     return CRYPT_INVALID_PACKET;
+  }
+
+  /* rsa decode the packet */
+  x = *keylen;
+  if ((err = rsa_exptmod(in, inlen, outkey, &x, PK_PRIVATE, prng, prng_idx, key)) != CRYPT_OK) {
+     return err;
+  }
+
+  /* now OAEP decode the packet */
+  return pkcs_1_oaep_decode(outkey, x, lparam, lparamlen, modulus_bitlen, hash_idx,
+                            outkey, keylen, res);
+}
+
+#endif /* MRSA */
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rsa_encrypt_key.c	Tue Jun 15 14:07:21 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 MRSA
+
+/* OAEP pad then encrypt */
+int rsa_encrypt_key(const unsigned char *inkey,  unsigned long inlen,
+                          unsigned char *outkey, unsigned long *outlen,
+                    const unsigned char *lparam, unsigned long lparamlen,
+                    prng_state *prng, int prng_idx, int hash_idx, rsa_key *key)
+{
+  unsigned long modulus_bitlen, modulus_bytelen, x;
+  int           err;
+  
+  _ARGCHK(inkey  != NULL);
+  _ARGCHK(outkey != NULL);
+  _ARGCHK(outlen != NULL);
+  _ARGCHK(key    != NULL);
+  
+  /* valid prng and hash ? */
+  if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+     return err;
+  }
+  if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+     return err;
+  }
+  
+  /* get modulus len in bits */
+  modulus_bitlen = mp_count_bits(&(key->N));
+
+  /* outlen must be at least the size of the modulus */
+  modulus_bytelen = mp_unsigned_bin_size(&(key->N));
+  if (modulus_bytelen > *outlen) {
+     return CRYPT_BUFFER_OVERFLOW;
+  }
+      
+  /* OAEP pad the key */
+  x = *outlen;
+  if ((err = pkcs_1_oaep_encode(inkey, inlen, lparam, 
+                                lparamlen, modulus_bitlen, prng, prng_idx, hash_idx, 
+                                outkey, &x)) != CRYPT_OK) {
+     return err;
+  }                                
+
+  /* rsa exptmod the OAEP pad */
+  return rsa_exptmod(outkey, x, outkey, outlen, PK_PUBLIC, prng, prng_idx, key);
+}
+
+#endif /* MRSA */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rsa_export.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,72 @@
+/* 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 MRSA
+
+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;
+}
+
+#endif /* MRSA */
+
--- a/rsa_exptmod.c	Mon May 31 18:25:41 2004 +0000
+++ b/rsa_exptmod.c	Tue Jun 15 14:07:21 2004 +0000
@@ -14,18 +14,23 @@
 
 #ifdef MRSA
 
-int rsa_exptmod(const unsigned char *in,  unsigned long inlen,
-                      unsigned char *out, unsigned long *outlen, int which,
+int rsa_exptmod(const unsigned char *in,   unsigned long inlen,
+                      unsigned char *out,  unsigned long *outlen, int which,
+                      prng_state    *prng, int           prng_idx,
                       rsa_key *key)
 {
-   mp_int tmp, tmpa, tmpb;
+   mp_int        tmp, tmpa, tmpb;
    unsigned long x;
-   int err;
+   int           err;
 
    _ARGCHK(in     != NULL);
    _ARGCHK(out    != NULL);
    _ARGCHK(outlen != NULL);
    _ARGCHK(key    != NULL);
+   
+   if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+      return err;
+   }
 
    if (which == PK_PRIVATE && (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED)) {
       return CRYPT_PK_NOT_PRIVATE;
@@ -49,10 +54,10 @@
    /* 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; }
+      if ((err = tim_exptmod(prng, prng_idx, &tmp, &key->e, &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; }
+      if ((err = tim_exptmod(prng, prng_idx, &tmp, &key->e,  &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; }
@@ -60,11 +65,15 @@
       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; }
+      if (which == PK_PRIVATE) {
+         if ((err = tim_exptmod(prng, prng_idx, &tmp, &key->e, &key->d, &key->N, &tmp)) != MP_OKAY) { goto error; }
+      } else {
+         if ((err = mp_exptmod(&tmp, &key->e, &key->N, &tmp)) != MP_OKAY) { goto error; }
+      }
    }
 
    /* read it back */
-   x = (unsigned long)mp_unsigned_bin_size(&tmp);
+   x = (unsigned long)mp_unsigned_bin_size(&key->N);
    if (x > *outlen) {
       err = CRYPT_BUFFER_OVERFLOW;
       goto done;
@@ -72,7 +81,8 @@
    *outlen = x;
 
    /* convert it */
-   if ((err = mp_to_unsigned_bin(&tmp, out)) != MP_OKAY)                    { goto error; }
+   zeromem(out, x);
+   if ((err = mp_to_unsigned_bin(&tmp, out+(x-mp_unsigned_bin_size(&tmp)))) != MP_OKAY) { goto error; }
 
    /* clean up and return */
    err = CRYPT_OK;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rsa_import.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,81 @@
+/* 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 MRSA
+
+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;
+}
+
+#endif /* MRSA */
+
--- a/rsa_make_key.c	Mon May 31 18:25:41 2004 +0000
+++ b/rsa_make_key.c	Tue Jun 15 14:07:21 2004 +0000
@@ -17,7 +17,7 @@
 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;
+   int    err;
 
    _ARGCHK(key != NULL);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rsa_sign_hash.c	Tue Jun 15 14:07:21 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 MRSA
+
+/* PSS pad then sign */
+int rsa_sign_hash(const unsigned char *msghash,  unsigned long  msghashlen, 
+                        unsigned char *sig,      unsigned long *siglen, 
+                        prng_state    *prng,     int            prng_idx,
+                        int            hash_idx, unsigned long  saltlen,
+                        rsa_key *key)
+{
+   unsigned long modulus_bitlen, modulus_bytelen, x;
+   int           err;
+   
+  _ARGCHK(msghash  != NULL);
+  _ARGCHK(sig      != NULL);
+  _ARGCHK(siglen   != NULL);
+  _ARGCHK(key      != NULL);
+  
+  /* valid prng and hash ? */
+  if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+     return err;
+  }
+  if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+     return err;
+  }
+  
+  /* get modulus len in bits */
+  modulus_bitlen = mp_count_bits(&(key->N));
+
+  /* outlen must be at least the size of the modulus */
+  modulus_bytelen = mp_unsigned_bin_size(&(key->N));
+  if (modulus_bytelen > *siglen) {
+     return CRYPT_BUFFER_OVERFLOW;
+  }
+      
+  /* PSS pad the key */
+  x = *siglen;
+  if ((err = pkcs_1_pss_encode(msghash, msghashlen, saltlen, prng, prng_idx,
+                               hash_idx, modulus_bitlen, sig, &x)) != CRYPT_OK) {
+     return err;
+  }
+
+  /* RSA encode it */
+  return rsa_exptmod(sig, x, sig, siglen, PK_PRIVATE, prng, prng_idx, key);
+}
+
+#endif /* MRSA */
--- a/rsa_sys.c	Mon May 31 18:25:41 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,274 +0,0 @@
-/* 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/rsa_verify_hash.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,69 @@
+/* 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 MRSA
+
+/* design then PSS depad */
+int rsa_verify_hash(const unsigned char *sig,      unsigned long siglen,
+                    const unsigned char *msghash,  unsigned long msghashlen,
+                          prng_state    *prng,     int           prng_idx,
+                          int            hash_idx, unsigned long saltlen,
+                          int           *stat,     rsa_key      *key)
+{
+   unsigned long modulus_bitlen, modulus_bytelen, x;
+   int           err;
+   unsigned char *tmpbuf;
+   
+  _ARGCHK(msghash  != NULL);
+  _ARGCHK(sig      != NULL);
+  _ARGCHK(stat     != NULL);
+  _ARGCHK(key      != NULL);
+  
+  /* valid hash ? */
+  if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+     return err;
+  }
+
+  if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+     return err;
+  }
+  
+  /* get modulus len in bits */
+  modulus_bitlen = mp_count_bits(&(key->N));
+
+  /* outlen must be at least the size of the modulus */
+  modulus_bytelen = mp_unsigned_bin_size(&(key->N));
+  if (modulus_bytelen != siglen) {
+     return CRYPT_INVALID_PACKET;
+  }
+  
+  /* allocate temp buffer for decoded sig */
+  tmpbuf = XCALLOC(1, modulus_bytelen + 1);
+  if (tmpbuf == NULL) {
+     return CRYPT_MEM;
+  }
+      
+  /* RSA decode it  */
+  x = siglen;
+  if ((err = rsa_exptmod(sig, siglen, tmpbuf, &x, PK_PUBLIC, prng, prng_idx, key)) != CRYPT_OK) {
+     XFREE(tmpbuf);
+     return err;
+  }
+  
+  /* PSS decode it */
+  err = pkcs_1_pss_decode(msghash, msghashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat);
+  XFREE(tmpbuf);
+  return err;
+}
+
+#endif /* MRSA */
--- a/sha1.c	Mon May 31 18:25:41 2004 +0000
+++ b/sha1.c	Tue Jun 15 14:07:21 2004 +0000
@@ -20,6 +20,12 @@
     2,
     20,
     64,
+
+    /* DER identifier */
+    { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 
+      0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 },
+    15,
+
     &sha1_init,
     &sha1_process,
     &sha1_done,
@@ -38,6 +44,9 @@
 #endif
 {
     ulong32 a,b,c,d,e,W[80],i;
+#ifdef SMALL_CODE
+    ulong32 t;
+#endif
 
     /* copy the state into 512-bits into W[0..15] */
     for (i = 0; i < 16; i++) {
@@ -63,6 +72,26 @@
     #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);
  
+#ifdef SMALL_CODE
+ 
+    for (i = 0; i < 20; ) {
+       FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
+    }
+
+    for (; i < 40; ) {
+       FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
+    }
+
+    for (; i < 60; ) {
+       FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
+    }
+
+    for (; i < 80; ) {
+       FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
+    }
+
+#else
+
     for (i = 0; i < 20; ) {
        FF0(a,b,c,d,e,i++);
        FF0(e,a,b,c,d,i++);
@@ -97,6 +126,7 @@
        FF3(c,d,e,a,b,i++);
        FF3(b,c,d,e,a,i++);
     }
+#endif
 
     #undef FF0
     #undef FF1
--- a/sha224.c	Mon May 31 18:25:41 2004 +0000
+++ b/sha224.c	Tue Jun 15 14:07:21 2004 +0000
@@ -16,6 +16,11 @@
     10,
     28,
     64,
+
+    /* DER identifier (not supported) */
+    { 0x00 },
+    0,
+
     &sha224_init,
     &sha256_process,
     &sha224_done,
--- a/sha256.c	Mon May 31 18:25:41 2004 +0000
+++ b/sha256.c	Tue Jun 15 14:07:21 2004 +0000
@@ -22,12 +22,20 @@
     0,
     32,
     64,
+
+    /* DER identifier */
+    { 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 
+      0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 
+      0x00, 0x04, 0x20 },
+    19,
+    
     &sha256_init,
     &sha256_process,
     &sha256_done,
     &sha256_test
 };
 
+#ifdef SMALL_CODE
 /* the K array */
 static const unsigned long K[64] = {
     0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
@@ -44,6 +52,7 @@
     0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
     0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
 };
+#endif
 
 /* Various logical functions */
 #define Ch(x,y,z)       (z ^ (x & (y ^ z)))
@@ -63,6 +72,9 @@
 #endif
 {
     ulong32 S[8], W[64], t0, t1;
+#ifdef SMALL_CODE
+    ulong32 t;
+#endif
     int i;
 
     /* copy state into S */
@@ -82,22 +94,17 @@
 
     /* Compress */
 #ifdef SMALL_CODE   
-#define RND(a,b,c,d,e,f,g,h,i)                    \
+#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;                                        \
+     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);
-     }  
+     for (i = 0; i < 64; ++i) {
+         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i);
+         t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; 
+         S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
+	  }  
 #else 
 #define RND(a,b,c,d,e,f,g,h,i,ki)                    \
      t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i];   \
--- a/sha384.c	Mon May 31 18:25:41 2004 +0000
+++ b/sha384.c	Tue Jun 15 14:07:21 2004 +0000
@@ -17,6 +17,13 @@
     4,
     48,
     128,
+
+    /* DER identifier */
+    { 0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 
+      0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 
+      0x00, 0x04, 0x30 },
+    19,
+
     &sha384_init,
     &sha512_process,
     &sha384_done,
--- a/sha512.c	Mon May 31 18:25:41 2004 +0000
+++ b/sha512.c	Tue Jun 15 14:07:21 2004 +0000
@@ -21,6 +21,13 @@
     5,
     64,
     128,
+
+    /* DER identifier */
+    { 0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 
+      0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 
+      0x00, 0x04, 0x40 },
+    19,
+
     &sha512_init,
     &sha512_process,
     &sha512_done,
--- a/strings.c	Mon May 31 18:25:41 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/* 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
-
--- a/tiger.c	Mon May 31 18:25:41 2004 +0000
+++ b/tiger.c	Tue Jun 15 14:07:21 2004 +0000
@@ -19,6 +19,13 @@
     1,
     24,
     64,
+
+    /* DER identifier */
+    { 0x30, 0x29, 0x30, 0x0D, 0x06, 0x09, 0x2B, 0x06, 
+      0x01, 0x04, 0x01, 0xDA, 0x47, 0x0C, 0x02, 0x05, 
+      0x00, 0x04, 0x18 },
+    19,
+
     &tiger_init,
     &tiger_process,
     &tiger_done,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tim_exptmod.c	Tue Jun 15 14:07:21 2004 +0000
@@ -0,0 +1,77 @@
+/* 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 RSA_TIMING
+
+/* decrypts c into m */
+int tim_exptmod(prng_state *prng, int prng_idx, 
+                mp_int *c, mp_int *e, mp_int *d, mp_int *n, mp_int *m)
+{
+   int           err;
+   mp_int        r, tmp, tmp2;
+   unsigned char *rtmp;
+   unsigned long rlen;
+
+   _ARGCHK(c != NULL);
+   _ARGCHK(e != NULL);
+   _ARGCHK(d != NULL);
+   _ARGCHK(n != NULL);
+   _ARGCHK(m != NULL);
+
+   if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* pick random r */ 
+   rtmp = XMALLOC(MAX_RSA_SIZE/8);
+   if (rtmp == NULL) {
+      return CRYPT_MEM;
+   }
+
+
+   rlen = mp_unsigned_bin_size(n);
+   if (prng_descriptor[prng_idx].read(rtmp, rlen, prng) != rlen) {
+      XFREE(rtmp);
+      return CRYPT_ERROR_READPRNG;
+   }
+
+   if ((err = mp_init_multi(&r, &tmp, &tmp2, NULL)) != MP_OKAY) {
+      XFREE(rtmp);
+      return mpi_to_ltc_error(err);
+   }
+
+   /* read in r */
+   if ((err = mp_read_unsigned_bin(&r, rtmp, rlen)) != MP_OKAY)              { goto __ERR; }
+
+   /* compute tmp = r^e */
+   if ((err = mp_exptmod(&r, e, n, &tmp)) != MP_OKAY)                        { goto __ERR; }
+
+   /* multiply C into the mix */
+   if ((err = mp_mulmod(c, &tmp, n, &tmp)) != MP_OKAY)                       { goto __ERR; }
+
+   /* raise to d */
+   if ((err = mp_exptmod(&tmp, d, n, &tmp)) != MP_OKAY)                      { goto __ERR; }
+   
+   /* invert r and multiply */
+   if ((err = mp_invmod(&r, n, &tmp2)) != MP_OKAY)                           { goto __ERR; }
+
+   /* multiply and we are totally set */
+   if ((err = mp_mulmod(&tmp, &tmp2, n, m)) != MP_OKAY)                      { goto __ERR; }
+
+__ERR:  mp_clear_multi(&r, &tmp, &tmp2, NULL);
+   XFREE(rtmp);
+   return mpi_to_ltc_error(err);
+}
+
+#endif 
--- a/tommath.h	Mon May 31 18:25:41 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,556 +0,0 @@
-/* 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
-
--- a/whirl.c	Mon May 31 18:25:41 2004 +0000
+++ b/whirl.c	Tue Jun 15 14:07:21 2004 +0000
@@ -21,6 +21,11 @@
     11,
     64,
     64,
+
+    /* DER encoding (not yet supported) */
+    { 0x00 },
+    0,
+
     &whirlpool_init,
     &whirlpool_process,
     &whirlpool_done,
@@ -34,7 +39,7 @@
 #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)               \
+#define theta_pi_gamma(a, i)             \
     SB0(GB(a, i-0, 7)) ^                 \
     SB1(GB(a, i-1, 6)) ^                 \
     SB2(GB(a, i-2, 5)) ^                 \
--- a/yarrow.c	Mon May 31 18:25:41 2004 +0000
+++ b/yarrow.c	Tue Jun 15 14:07:21 2004 +0000
@@ -30,7 +30,15 @@
 
    /* these are the default hash/cipher combo used */
 #ifdef RIJNDAEL
+#if    YARROW_AES==0
+   prng->yarrow.cipher = register_cipher(&rijndael_enc_desc);
+#elif  YARROW_AES==1
+   prng->yarrow.cipher = register_cipher(&aes_enc_desc);
+#elif  YARROW_AES==2
    prng->yarrow.cipher = register_cipher(&rijndael_desc);
+#elif  YARROW_AES==3
+   prng->yarrow.cipher = register_cipher(&aes_desc);
+#endif
 #elif defined(BLOWFISH)
    prng->yarrow.cipher = register_cipher(&blowfish_desc);
 #elif defined(TWOFISH)
@@ -78,6 +86,8 @@
    prng->yarrow.hash   = register_hash(&md4_desc);
 #elif defined(MD2)
    prng->yarrow.hash   = register_hash(&md2_desc);
+#elif defined(WHIRLPOOL)
+   prng->yarrow.hash   = register_hash(&whirlpool_desc);
 #else
    #error YARROW needs at least one HASH
 #endif
@@ -107,13 +117,20 @@
    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);
+   if ((err = hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool, 
+                                                        hash_descriptor[prng->yarrow.hash].hashsize)) != CRYPT_OK) {
+      return err;
+   }
 
    /* add the new entropy */
-   hash_descriptor[prng->yarrow.hash].process(&md, buf, len);
+   if ((err = hash_descriptor[prng->yarrow.hash].process(&md, buf, len)) != CRYPT_OK) {
+      return err;
+   }
 
    /* store result */
-   hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool);
+   if ((err = hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool)) != CRYPT_OK) {
+      return err;
+   }
 
    return CRYPT_OK;
 }