changeset 143:5d99163f7e32 libtomcrypt-orig

import of libtomcrypt 0.99
author Matt Johnston <matt@ucc.asn.au>
date Sun, 19 Dec 2004 11:34:45 +0000
parents 6362d3854bb4
children 7ed585a2c53b 1c15b283127b
files LICENSE aes.c cast5.c cbc_getiv.c cbc_setiv.c cfb_getiv.c changes chc.c crypt.c crypt.tex crypt_cipher_descriptor.c crypt_hash_descriptor.c crypt_prng_descriptor.c crypt_register_cipher.c crypt_register_hash.c crypt_register_prng.c cscope.tmplst ctr_getiv.c ctr_setiv.c demos/hashsum.c demos/test.c demos/test/.ccmalloc demos/test/cipher_hash_test.c demos/test/der_tests.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/makefile.shared demos/test/pkcs_1_test.c demos/test/rsa_test.c demos/test/store_test.c demos/test/test.c demos/test/test.h demos/tv_gen.c demos/x86_prof.c der_decode_integer.c der_encode_integer.c der_get_multi_integer.c der_length_integer.c der_put_multi_integer.c des.c dh.c dh_sys.c doc/crypt.pdf dsa_make_key.c dsa_sign_hash.c eax_decrypt_verify_memory.c eax_done.c eax_encrypt_authenticate_memory.c eax_init.c ecc.c ecc_sys.c examples/ch1-01.c examples/ch1-02.c examples/ch1-03.c examples/ch2-01.c fortuna.c hash_filehandle.c hash_memory.c hmac_done.c hmac_file.c hmac_init.c hmac_memory.c hmac_process.c hmac_test.c ltc_tommath.h makefile makefile.cygwin_dll makefile.icc makefile.msvc makefile.shared md2.c md4.c md5.c modes_test.c mpi.c mycrypt.h mycrypt_argchk.h mycrypt_cfg.h mycrypt_cipher.h mycrypt_custom.h mycrypt_hash.h mycrypt_kr.h mycrypt_macros.h mycrypt_misc.h mycrypt_pk.h mycrypt_prng.h noekeon.c notes/hash_tv.txt notes/hmac_tv.txt notes/tech0004.txt ocb_decrypt_verify_memory.c ocb_done_decrypt.c ocb_encrypt_authenticate_memory.c ocb_init.c ofb_getiv.c omac_done.c omac_init.c omac_memory.c omac_process.c omac_test.c pkcs_1_mgf1.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_5_1.c pkcs_5_2.c pmac_init.c pmac_memory.c pmac_process.c pretty.build rc2.c rc4.c rc5.c rc6.c rmd128.c rmd160.c rsa_decrypt_key.c rsa_encrypt_key.c rsa_export.c rsa_exptmod.c rsa_free.c rsa_import.c rsa_make_key.c rsa_sign_hash.c rsa_v15_decrypt_key.c rsa_v15_encrypt_key.c rsa_v15_sign_hash.c rsa_v15_verify_hash.c rsa_verify_hash.c s_ocb_done.c sha1.c sha224.c sha256.c sha384.c sha512.c sober128.c sober128tab.c sprng.c tiger.c tim_exptmod.c tommath_class.h tommath_superclass.h whirl.c yarrow.c
diffstat 152 files changed, 10055 insertions(+), 5480 deletions(-) [+]
line wrap: on
line diff
--- a/LICENSE	Tue Jun 15 14:07:21 2004 +0000
+++ b/LICENSE	Sun Dec 19 11:34:45 2004 +0000
@@ -2,7 +2,7 @@
 
 All of the software was either written by or donated to Tom St Denis for the purposes
 of this project.  The only exception is the SAFER.C source which has no known
-license status (assumed copyrighted) which is why SAFER,C is shipped as disabled.
+license status (assumed copyrighted) which is why SAFER.C is shipped as disabled.
 
 Tom St Denis
 
--- a/aes.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/aes.c	Sun Dec 19 11:34:45 2004 +0000
@@ -89,7 +89,7 @@
 }
 
 #ifndef ENCRYPT_ONLY
-
+#ifdef SMALL_CODE
 static ulong32 setup_mix2(ulong32 temp)
 {
    return Td0(255 & Te4[byte(temp, 3)]) ^
@@ -97,7 +97,7 @@
           Td2(255 & Te4[byte(temp, 1)]) ^
           Td3(255 & Te4[byte(temp, 0)]);
 }
-
+#endif
 #endif
 
 int SETUP(const unsigned char *key, int keylen, int rounds, symmetric_key *skey)
--- a/cast5.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/cast5.c	Sun Dec 19 11:34:45 2004 +0000
@@ -418,7 +418,7 @@
 
    /* extend the key as required */
    zeromem(buf, sizeof(buf));
-   memcpy(buf, key, (size_t)keylen);
+   XMEMCPY(buf, key, (size_t)keylen);
 
    /* load and start the awful looking network */
    for (y = 0; y < 4; y++) {
--- a/cbc_getiv.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/cbc_getiv.c	Sun Dec 19 11:34:45 2004 +0000
@@ -21,7 +21,7 @@
    if ((unsigned long)cbc->blocklen > *len) {
       return CRYPT_BUFFER_OVERFLOW;
    }
-   memcpy(IV, cbc->IV, cbc->blocklen);
+   XMEMCPY(IV, cbc->IV, cbc->blocklen);
    *len = cbc->blocklen;
 
    return CRYPT_OK;
--- a/cbc_setiv.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/cbc_setiv.c	Sun Dec 19 11:34:45 2004 +0000
@@ -20,7 +20,7 @@
    if (len != (unsigned long)cbc->blocklen) {
       return CRYPT_INVALID_ARG;
    }
-   memcpy(cbc->IV, IV, len);
+   XMEMCPY(cbc->IV, IV, len);
    return CRYPT_OK;
 }
 
--- a/cfb_getiv.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/cfb_getiv.c	Sun Dec 19 11:34:45 2004 +0000
@@ -21,7 +21,7 @@
    if ((unsigned long)cfb->blocklen > *len) {
       return CRYPT_BUFFER_OVERFLOW;
    }
-   memcpy(IV, cfb->IV, cfb->blocklen);
+   XMEMCPY(IV, cfb->IV, cfb->blocklen);
    *len = cfb->blocklen;
 
    return CRYPT_OK;
--- a/changes	Tue Jun 15 14:07:21 2004 +0000
+++ b/changes	Sun Dec 19 11:34:45 2004 +0000
@@ -1,10 +1,138 @@
+October 29th, 2004
+v0.99  -- Merged in the latest version of LTM which includes all of the recent bug fixes
+       -- Deprecated LTMSSE and removed it (to be replaced with TFM later on)
+       -- Stefan Arentz pointed out that mp_s_rmap should be extern
+       -- Kristian Gj�steen pointed out that there are typos in the 
+          "test" makefile and minor issues in Yarrow and Sober [just cosmetics really]
+       -- Matthew P. Cashdollar pointed out that "export" is a C++ keyword 
+          so changed the PRNG api to use "pexport" and "pimport"
+       -- Updated "hashsum" demo so it builds ;-)
+       -- Added automatic support for x86-64 (will configure for 64-bit little endian automagically)
+       -- Zhi Chen pointed out a bug in rsa_exptmod which would leak memory on error. 
+       -- Made hash functions "init" return an int.  slight change to API ;-(
+       -- Added "CHC" mode which turns any cipher into a hash the other LTC functions can use
+       -- Added CHC mode stuff to demos such as tv_gen and hashsum
+       -- Added "makefile.shared" which builds and installs shared/static object copies
+          of the library.
+       -- Added DER for bignum support 
+       -- RSA is now fully joy.  rsa_export/rsa_import use PKCS #1 encodings and should be 
+          compatible with other crypto libs that use the format.
+       -- Added support for x86-64 for the ROL/ROR macros 
+       -- Changed the DLL and SO makefiles to optimize for speed, commented SMALL_CODE in
+          mycrypt_custom.h and added -DSMALL_CODE to the default makefile
+       -- Updated primality testing code so it does a minimum of 5 tests [of Miller-Rabin]
+          (AFAIK not a security fix, just warm fuzzies)
+       -- Minor updates to the OMAC code (additional __ARGCHK and removed printf from omac_test... oops!)
+       -- Update build and configuration info which was really really really out of date.  (Chapter 14)
+       ++ Minor update, switch RSA to use the PKCS style CRT
+
+August 6th, 2004
+v0.98  -- Update to hmac_init to free all allocated memory on error
+       -- Update to PRNG API to fix import/export functions of Fortuna and Yarrow
+       -- Added test functions to PRNG api, RC4 now conforms ;-) [was a minor issue]
+       -- Added the SOBER-128 PRNG based off of code donated by Greg Rose.
+       -- Added Tech Note #4 [notes/tech0004.txt] 
+       -- Changed RC4 back [due to request].  It will now XOR the output so you can use it like 
+          a stream cipher easily.
+       -- Update Fortuna's export() to emit a hash of each pool.  This means that the accumulated 
+          entropy that was spread over all the pools isn't entirely lost when you export/import.
+       -- Zhi Chen suggested a comment for rsa_encrypt_key() to let users know [easily] that it was
+          PKCS #1 v2.0 padding.  (updated other rsa_* functions)
+       -- Cleaned up Noekeon to remove unrolling [wasn't required, was messy and actually slower with GCC/ICC]
+       -- Updated RC4 so that when you feed it >256 bytes of entropy it quietly ignores additional
+          bytes.  Also removed the % from the key setup to speed it up a bit.
+       -- Added cipher/hash/prng tests to x86_prof to help catch bugs while testing
+       -- Made the PRNG "done" return int, fixed sprng_done to not require prng* to be non-null
+       -- Spruced up mycrypt_custom.h to trap more errors and also help prevent LTMSSE from being defined
+          on non-i386 platforms by accident.
+       -- Added RSA/ECC/DH speed tests to x86_prof and cleaned it up to build with zero warnings
+       -- Changed Fortuna to count only entropy [not the 2 byte header] added to pool[0] into the 
+          reseed mechanism.  
+       -- Added "export_size" member to prng_descriptor tables so you can know in advance the size of 
+          the exported state for any given PRNG.  
+       -- Ported over patch on LTM 0.30 [not ready to release LTM 0.31] that fixes bug in mp_mul()/mp_div()
+          that used to result in negative zeroes when you multiplied zero by a negative integer.  
+          (patch due to "Wolfgang Ehrhardt" <[email protected]>)
+       -- Fixed rsa_*decrypt_key() and rsa_*verify_hash() to default to invalid "stat" or "res".  This way
+          if any of the higher level functions fail [before you get to the padding] the result will be in
+          a known state].  Applied to both v2 and v1.5 padding helpers.
+       -- Added MACs to x86_prof
+       -- Fixed up "warnings" in x86_prof and tv_gen
+       -- Added a "profiled" target back [for GCC 3.4 and ICC v8].  Doesn't seem to help but might be worth
+          tinkering with.
+       -- Beefed up load/store test in demos/test
+
+       ++ New note, in order to use the optimized LOAD/STORE macros your platform
+          must support unaligned 32/64 bit load/stores.  The x86s support this
+          but some [ARM for instance] do not.  If your platform cannot perform
+          unaligned operations you must use the endian neutral code which is safe for 
+          any sort of platform.
+
+July 23rd, 2004
+v0.97b -- Added PKCS #1 v1.5 RSA encrypt/sign helpers (like rsa_sign_hash, etc...)
+       -- Added missing prng check to rsa_decrypt_key() [not critical as I don't use 
+          descriptors directly in that function]
+       -- Merged in LTM-SSE, define LTMSSE before you build and you will get SSE2 optimized math ;-)
+          (roughly 3x faster on a P4 Northwood).  By default it will compile as ISO C portable
+          code (when LTMSSE is undefined).
+       -- Fixed bug in ltc_tommath.h where I had the kara/toom cutoffs not marked as ``extern''
+          Thanks to "Stefan Arentz" <stefan at organicnetwork.net>
+       -- Steven Dake <[email protected]> and Richard Amacker <[email protected]> submitted patches to 
+          fix pkcs_5_2().  It now matches the output of another crypto library.  Whoops... hehehe
+       -- Updated PRNG api.  Added Fortuna PRNG to the list of supported PRNGs
+       -- Fixed up the descriptor tables since globals are automatically zero'ed on startup.
+       -- Changed RC4 to store it's output.  If you want to encrypt with RC4
+          you'll have to do the XOR yourself.
+       -- Fixed buffer overflows/overruns in the HMAC code.  
+
+       ++ API change for the PRNGs there now is a done() function per PRNG.  You
+          should call it when you are done with a prng state.  So far it's
+          not absolutely required (won't cause problems) but is a good idea to
+          start.  
+
+
+June 23rd, 2004
+v0.97a ++ Fixed several potentially crippling bugs... [read on]
+       -- Fixed bug in OAEP decoder that would incorrectly report 
+          buffer overflows. [Zhi Chen]
+       -- Fixed headers which had various C++ missing [extern "C"]'s
+       -- Added "extern" to sha384_desc descriptor which I removed by mistake
+       -- Fixed bugs in ENDIAN_BIG macros using the wrong byte order [Matt Johnston]
+       -- Updated tiger.c and des.c to not shadow "round" which is intrinsic on
+          some C compilers.
+       -- Updated demos/test/rsa_test.c to test the RSA functionality better
+       ++ This update has been tested with GCC [v3.3.3], ICC [v8] and MSVC [v6+SP6] 
+          all on a x86 P4  [GCC/ICC tested in Gentoo Linux, MSVC in WinXP]
+       ++ Outcome: The bug Zhi Chen pointed out has been fixed.  So have the bugs
+          that Matt Johnston found.  
+
+June 19th, 2004
+v0.97  -- Removed spurious unused files [arrg!]
+       -- Patched buffer overflow in tim_exptmod()
+       -- Fixed buffer overrun bug in pkcs_1_v15_es_decode()
+       -- Reduced stack usage in PKCS #1 v2.0 padding functions (by several KBs)
+       -- Removed useless extern's that were an artifact from the project start... ;-)
+       -- Replaced memcpy/memset with XMEMCPY and XMEMSET for greater flexibility
+       -- fixed bugs in hmac_done()/hmac_init()/[various others()] where I didn't trap errors 
+       -- Reduced stack usage in OMAC/PMAC/HMAC/EAX/OCB/PKCS#5 by mallocing any significant sized
+          arrays (e.g. > 100 bytes or so).  Only in non-critical functions (e.g. eax_init())
+       -- "Zhi Chen" <[email protected]> pointed out that rsa_decrypt_key() requires
+          an incorrect output size (too large).  Fixed.
+       -- Added a "pretty" target to the GCC makefile.  Requires PERL.  It is NEAT!
+       -- Minor updates to ch1 of the manual.
+       -- Cleaned up the indentation and added comments to rsa_make_key(), rsa_exptmod() and 
+          rsa_verify_hash()
+       -- Updated makefile.icc so the "install" target would work ;-)
+       -- Removed demos/test.c [deprecated from demos/test/test.c]
+       -- Changed MAXBLOCKSIZE from 128 to 64 to reflect the true size...
+
 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
+       --  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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/chc.c	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,261 @@
+/* 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 CHC_HASH
+
+#define UNDEFED_HASH  -17
+
+/* chc settings */
+static int            cipher_idx=UNDEFED_HASH,        /* which cipher */
+                      cipher_blocksize;               /* blocksize of cipher */
+
+
+const struct _hash_descriptor chc_desc = {
+   "chc_hash", 12, 0, 0, { 0 }, 0,
+   &chc_init,
+   &chc_process,
+   &chc_done,
+   &chc_test
+};
+
+/* initialize the CHC state with a given cipher */
+int chc_register(int cipher)
+{
+   int err, kl, idx;
+
+   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* will it be valid? */
+   kl = cipher_descriptor[cipher].block_length;
+
+   /* must be >64 bit block */
+   if (kl <= 8) {
+      return CRYPT_INVALID_CIPHER;
+   }
+
+   /* can we use the ideal keysize? */
+   if ((err = cipher_descriptor[cipher].keysize(&kl)) != CRYPT_OK) {
+      return err;
+   }
+   /* we require that key size == block size be a valid choice */
+   if (kl != cipher_descriptor[cipher].block_length) {
+      return CRYPT_INVALID_CIPHER;
+   }
+
+   /* determine if chc_hash has been register_hash'ed already */
+   if ((err = hash_is_valid(idx = find_hash("chc_hash"))) != CRYPT_OK) {
+      return err;
+   }
+
+   /* store into descriptor */
+   hash_descriptor[idx].hashsize  = 
+   hash_descriptor[idx].blocksize = cipher_descriptor[cipher].block_length;
+
+   /* store the idx and block size */
+   cipher_idx       = cipher;
+   cipher_blocksize = cipher_descriptor[cipher].block_length;
+   return CRYPT_OK;
+}
+
+/* "hash init" is simply encrypt 0 with the 0 key.  Simple way to make an IV */
+int chc_init(hash_state *md)
+{
+   symmetric_key *key;
+   unsigned char  buf[MAXBLOCKSIZE];
+   int            err;
+ 
+   _ARGCHK(md != NULL);
+
+   /* is the cipher valid? */
+   if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) {
+      return err;
+   }
+
+   if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) {
+      return CRYPT_INVALID_CIPHER;
+   }
+
+   if ((key = XMALLOC(sizeof(*key))) == NULL) {
+      return CRYPT_MEM;
+   }
+
+   /* zero key and what not */   
+   zeromem(buf, cipher_blocksize);
+   if ((err = cipher_descriptor[cipher_idx].setup(buf, cipher_blocksize, 0, key)) != CRYPT_OK) {
+      XFREE(key);
+      return err;
+   }
+
+   /* encrypt zero block */
+   cipher_descriptor[cipher_idx].ecb_encrypt(buf, md->chc.state, key);
+
+   /* zero other members */
+   md->chc.length = 0;
+   md->chc.curlen = 0;
+   zeromem(md->chc.buf, sizeof(md->chc.buf));
+   XFREE(key);
+   return CRYPT_OK;
+}
+
+/* 
+   key    <= state
+   T0,T1  <= block
+   T0     <= encrypt T0
+   state  <= state xor T0 xor T1
+*/
+static int chc_compress(hash_state *md, unsigned char *buf)
+{
+   unsigned char  T[2][MAXBLOCKSIZE];
+   symmetric_key *key;
+   int            err, x;
+
+   if ((key = XMALLOC(sizeof(*key))) == NULL) {
+      return CRYPT_MEM;
+   }
+   if ((err = cipher_descriptor[cipher_idx].setup(md->chc.state, cipher_blocksize, 0, key)) != CRYPT_OK) {
+      XFREE(key);
+      return err;
+   }
+   memcpy(T[1], buf, cipher_blocksize);
+   cipher_descriptor[cipher_idx].ecb_encrypt(buf, T[0], key);
+   for (x = 0; x < cipher_blocksize; x++) {
+       md->chc.state[x] ^= T[0][x] ^ T[1][x];
+   }
+   XFREE(key);
+#ifdef CLEAN_STACK
+   zeromem(T, sizeof(T));
+   zeromem(&key, sizeof(key));
+#endif
+   return CRYPT_OK;
+}
+
+HASH_PROCESS(_chc_process, chc_compress, chc, (unsigned long)cipher_blocksize)
+
+int chc_process(hash_state * md, const unsigned char *buf, unsigned long len)
+{
+   int err;
+
+   _ARGCHK(md   != NULL);
+   _ARGCHK(buf  != NULL);
+
+   /* is the cipher valid? */
+   if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) {
+      return err;
+   }
+   if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) {
+      return CRYPT_INVALID_CIPHER;
+   }
+
+   return _chc_process(md, buf, len);
+}
+
+int chc_done(hash_state *md, unsigned char *buf)
+{
+    int err;
+
+    _ARGCHK(md   != NULL);
+    _ARGCHK(buf  != NULL);
+
+    /* is the cipher valid? */
+    if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) {
+       return err;
+    }
+    if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) {
+       return CRYPT_INVALID_CIPHER;
+    }
+
+    if (md->chc.curlen >= sizeof(md->chc.buf)) {
+       return CRYPT_INVALID_ARG;
+    }
+
+    /* increase the length of the message */
+    md->chc.length += md->chc.curlen * 8;
+
+    /* append the '1' bit */
+    md->chc.buf[md->chc.curlen++] = (unsigned char)0x80;
+
+    /* if the length is currently above l-8 bytes we append zeros
+     * then compress.  Then we can fall back to padding zeros and length
+     * encoding like normal.
+     */
+    if (md->chc.curlen > (unsigned long)(cipher_blocksize - 8)) {
+        while (md->chc.curlen < (unsigned long)cipher_blocksize) {
+            md->chc.buf[md->chc.curlen++] = (unsigned char)0;
+        }
+        chc_compress(md, md->chc.buf);
+        md->chc.curlen = 0;
+    }
+
+    /* pad upto l-8 bytes of zeroes */
+    while (md->chc.curlen < (unsigned long)(cipher_blocksize - 8)) {
+        md->chc.buf[md->chc.curlen++] = (unsigned char)0;
+    }
+
+    /* store length */
+    STORE64L(md->chc.length, md->chc.buf+(cipher_blocksize-8));
+    chc_compress(md, md->chc.buf);
+
+    /* copy output */
+    XMEMCPY(buf, md->chc.state, cipher_blocksize);
+
+#ifdef CLEAN_STACK
+    zeromem(md, sizeof(hash_state));
+#endif
+    return CRYPT_OK;
+}
+
+int chc_test(void)
+{
+   static const struct {
+      unsigned char *msg,
+                    md[MAXBLOCKSIZE];
+      int            len;
+   } tests[] = {
+{
+   (unsigned char *)"hello world",
+   { 0xcf, 0x57, 0x9d, 0xc3, 0x0a, 0x0e, 0xea, 0x61, 
+     0x0d, 0x54, 0x47, 0xc4, 0x3c, 0x06, 0xf5, 0x4e },
+   16
+}
+};
+   int x, oldhashidx, idx;
+   unsigned char out[MAXBLOCKSIZE];
+   hash_state md;
+
+   /* AES can be under rijndael or aes... try to find it */
+   if ((idx = find_cipher("aes")) == -1) {
+      if ((idx = find_cipher("rijndael")) == -1) {
+         return CRYPT_NOP;
+      }
+   }
+   oldhashidx = cipher_idx;
+   chc_register(idx);
+
+   for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+       chc_init(&md);
+       chc_process(&md, tests[x].msg, strlen((char *)tests[x].msg));
+       chc_done(&md, out);
+       if (memcmp(out, tests[x].md, tests[x].len)) {
+          return CRYPT_FAIL_TESTVECTOR;
+       }
+   }
+   if (oldhashidx != UNDEFED_HASH) {
+      chc_register(oldhashidx);
+   }
+
+   return CRYPT_OK;
+}
+
+#endif
--- a/crypt.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/crypt.c	Sun Dec 19 11:34:45 2004 +0000
@@ -123,6 +123,9 @@
 #if defined(WHIRLPOOL)
    "   WHIRLPOOL\n"
 #endif
+#if defined(CHC_HASH)
+   "   CHC_HASH \n"
+#endif
 
     "\nBlock Chaining Modes:\n"
 #if defined(CFB)
@@ -141,6 +144,26 @@
     "   CTR\n"
 #endif
 
+    "\nMACs:\n"
+#if defined(HMAC)
+    "   HMAC\n"
+#endif
+#if defined(OMAC)
+    "   OMAC\n"
+#endif
+#if defined(PMAC)
+    "   PMAC\n"
+#endif
+
+    "\nENC + AUTH modes:\n"
+#if defined(EAX_MODE)
+    "   EAX_MODE\n"
+#endif
+#if defined(OCB_MODE)
+    "   OCB_MODE\n"
+#endif
+
+
     "\nPRNG:\n"
 #if defined(YARROW)
     "   Yarrow\n"
@@ -151,6 +174,12 @@
 #if defined(RC4)
     "   RC4\n"
 #endif
+#if defined(FORTUNA)
+    "   Fortuna\n"
+#endif
+#if defined(SOBER128)
+    "   SOBER128\n"
+#endif
 
     "\nPK Algs:\n"
 #if defined(MRSA)
@@ -197,21 +226,6 @@
 #if defined(MPI)
     " MPI "
 #endif
-#if defined(HMAC)
-    " HMAC "
-#endif
-#if defined(OMAC)
-    " OMAC "
-#endif
-#if defined(PMAC)
-    " PMAC "
-#endif
-#if defined(EAX_MODE)
-    " EAX_MODE "
-#endif
-#if defined(OCB_MODE)
-    " OCB_MODE "
-#endif
 #if defined(TRY_UNRANDOM_FIRST)
     " TRY_UNRANDOM_FIRST "
 #endif
@@ -230,8 +244,8 @@
 #if defined(NO_FILE)
     " NO_FILE "
 #endif
-#if defined(LTC_TEST)
-    " LTC_TEST "
+#if defined(LTMSSE)
+    " LTMSSE "
 #endif
     "\n"
     "\n\n\n"
--- a/crypt.tex	Tue Jun 15 14:07:21 2004 +0000
+++ b/crypt.tex	Sun Dec 19 11:34:45 2004 +0000
@@ -1,4 +1,4 @@
-\documentclass[b5paper]{book}
+\documentclass[a4paper]{book}
 \usepackage{hyperref}
 \usepackage{makeidx}
 \usepackage{amssymb}
@@ -47,20 +47,15 @@
 \def\gap{\vspace{0.5ex}}
 \makeindex
 \begin{document}
-\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.96}
+\title{LibTomCrypt \\ Version 0.99}
 \author{Tom St Denis \\
 \\
 [email protected] \\
-http://libtomcrypt.org \\ \\
-Phone: 1-613-836-3160\\
-111 Banning Rd \\
-Kanata, Ontario \\
-K2L 1C3 \\
-Canada
+http://libtomcrypt.org
 }
 \maketitle
 This text and source code library are both hereby placed in the public domain.  This book has been 
-formatted for B5 [176x250] paper using the \LaTeX{} {\em book} macro package.
+formatted for A4 paper using the \LaTeX{} {\em book} macro package.
 
 \vspace{10cm}
 
@@ -70,7 +65,15 @@
 
 Tom St Denis,
 
-Ontario, Canada
+Phone: 1-613-836-3160
+
+111 Banning Rd 
+
+Kanata, Ontario 
+
+K2L 1C3 
+
+Canada
 \end{flushright}
 \newpage
 \tableofcontents
@@ -182,7 +185,7 @@
 library.
 
 ``rc2.c'' is based on publicly available code that is not attributed to a person from the given source.  ``safer.c''
-was written by Richard De Moliner ([email protected]) and is public domain.
+was written by Richard De Moliner ([email protected]) and seems to be free for use.
 
 The project is hereby released as public domain.
 
@@ -190,33 +193,15 @@
 
 The author (Tom St Denis) is not a patent lawyer so this section is not to be treated as legal advice.  To the best
 of the authors knowledge the only patent related issues within the library are the RC5 and RC6 symmetric block ciphers.  
-They can be removed from a build by simply commenting out the two appropriate lines in the makefile script.  The rest
+They can be removed from a build by simply commenting out the two appropriate lines in ``mycrypt\_custom.h''.  The rest
 of the ciphers and hashes are patent free or under patents that have since expired.
 
 The RC2 and RC4 symmetric ciphers are not under patents but are under trademark regulations.  This means you can use 
 the ciphers you just can't advertise that you are doing so.  
 
-\section{Building the library}
-
-To build the library on a GCC equipped platform simply type ``make'' at your command prompt.  It will build the library
-file ``libtomcrypt.a''.  
-
-To install the library copy all of the ``.h'' files into your ``\#include'' path and the single libtomcrypt.a file into 
-your library path.
-
-With MSVC you can build the library with ``nmake -f makefile.msvc''.  This will produce a ``tomcrypt.lib'' file which
-is the core library.  Copy the header files into your MSVC include path and the library in the lib path (typically
-under where VC98 is installed).
-
-\section{Building against the library}
-
-In the recent versions the build steps have changed.  The build options are now stored in ``mycrypt\_custom.h'' and
-no longer in the makefile.  If you change a build option in that file you must re-build the library from clean to
-ensure the build is intact.  The perl script ``config.pl'' will help setup the custom header and a custom makefile
-if you want one (the provided ``makefile'' will work with custom configs).
-
 \section{Thanks}
-I would like to give thanks to the following people (in no particular order) for helping me develop this project:
+I would like to give thanks to the following people (in no particular order) for helping me develop this project from
+early on:
 \begin{enumerate}
    \item Richard van de Laarschot
    \item Richard Heathfield
@@ -233,6 +218,10 @@
    \item Christopher Imes
 \end{enumerate}
 
+There have been quite a few other people as well.  Please check the change log to see who else has contributed from
+time to time.
+
+
 \chapter{The Application Programming Interface (API)}
 \section{Introduction}
 \index{CRYPT\_ERROR} \index{CRYPT\_OK}
@@ -581,9 +570,9 @@
 \begin{tabular}{|l|l|l|}
 \hline TWOFISH\_SMALL & TWOFISH\_TABLES & Speed and Memory (per key) \\
 \hline undefined & undefined & Very fast, 4.2KB of ram. \\
-\hline undefined & defined & As above, faster keysetup, larger code (1KB more). \\
+\hline undefined & defined & Faster keysetup, larger code. \\
 \hline defined & undefined & Very slow, 0.2KB of ram. \\
-\hline defined & defined & Somewhat faster, 0.2KB of ram, larger code. \\
+\hline defined & defined & Faster, 0.2KB of ram, larger code. \\
 \hline
 \end{tabular}
 \end{center}
@@ -615,7 +604,8 @@
    }
 
    /* generic call to function (assuming the key in key[] was already setup) */
-   if ((err = cipher_descriptor[find_cipher("blowfish")].setup(key, 8, 0, &skey)) != CRYPT_OK) {
+   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;
    }
@@ -820,12 +810,13 @@
    /* somehow fill out key and IV */
 
    /* start up CTR mode */
-   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 */
+   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;
@@ -1345,7 +1336,60 @@
 int unregister_hash(const struct _hash_descriptor *hash);
 \end{verbatim}
 
-\subsection{Notice}
+\section{Cipher Hash Construction}
+\index{Cipher Hash Construction}
+An addition to the suite of hash functions is the ``Cipher Hash Construction'' or ``CHC'' mode.  In this mode
+applicable block ciphers (such as AES) can be turned into hash functions that other LTC functions can use.  In 
+particular this allows a cryptosystem to be designed using very few moving parts.
+
+In order to use the CHC system the developer will have to take a few extra steps.  First the ``chc\_desc'' hash
+descriptor must be registered with register\_hash().  At this point the CHC hash cannot be used to hash
+data.  While it is in the hash system you still have to tell the CHC code which cipher to use.  This is accomplished
+via the chc\_register() function.
+
+\index{chc\_register()}
+\begin{verbatim}
+int chc_register(int cipher);
+\end{verbatim}
+
+A cipher has to be registered with CHC (and also in the cipher descriptor tables with 
+register\_cipher()).  The chc\_register() function will bind a cipher to the CHC system.  Only one cipher can 
+be bound to the CHC hash at a time.  There are additional requirements for the system to work.
+
+\begin{enumerate}
+   \item The cipher must have a block size greater than 64--bits.  
+   \item The cipher must allow an input key the size of the block size.
+\end{enumerate}
+
+Example of using CHC with the AES block cipher.
+
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   int err; 
+
+   /* register cipher and hash */
+   if (register_cipher(&aes_enc_desc) == -1) {
+      printf("Could not register cipher\n");
+      return EXIT_FAILURE;
+   }
+   if (register_hash(&chc_desc) == -1) {
+      printf("Could not register hash\n");
+      return EXIT_FAILURE;
+   }
+
+   /* start chc with AES */
+   if ((err = chc_register(find_cipher("aes"))) != CRYPT_OK) {
+      printf("Error binding AES to CHC: %s\n", error_to_string(err));
+   }
+
+   /* now you can use chc_hash in any LTC function [aside from pkcs...] */
+   /* ... */
+\end{verbatim}
+
+
+\section{Notice}
 It is highly recommended that you \textbf{not} use the MD4 or MD5 hashes for the purposes of digital signatures or authentication codes.  
 These hashes are provided for completeness and they still can be used for the purposes of password hashing or one-way accumulators
 (e.g. Yarrow).
@@ -1678,12 +1722,15 @@
 Which returns {\bf CRYPT\_OK} if the code passes otherwise it returns an error code.
 
 
+
+
+
 \chapter{Pseudo-Random Number Generators}
 \section{Core Functions}
-
 The library provides an array of core functions for Pseudo-Random Number Generators (PRNGs) as well.  A cryptographic PRNG is
 used to expand a shorter bit string into a longer bit string.  PRNGs are used wherever random data is required such as Public Key (PK)
 key generation.  There is a universal structure called ``prng\_state''.  To initialize a PRNG call:
+\index{PRNG start}
 \begin{verbatim}
 int XXX_start(prng_state *prng);
 \end{verbatim}
@@ -1691,6 +1738,7 @@
 This will setup the PRNG for future use and not seed it.  In order 
 for the PRNG to be cryptographically useful you must give it entropy.  Ideally you'd have some OS level source to tap 
 like in UNIX (see section 5.3).  To add entropy to the PRNG call:
+\index{PRNG add\_entropy}
 \begin{verbatim}
 int XXX_add_entropy(const unsigned char *in, unsigned long len, 
                     prng_state *prng);
@@ -1698,17 +1746,77 @@
 
 Which returns {\bf CRYPTO\_OK} if the entropy was accepted.  Once you think you have enough entropy you call another
 function to put the entropy into action.
+\index{PRNG ready}
 \begin{verbatim}
 int XXX_ready(prng_state *prng);
 \end{verbatim}
 
 Which returns {\bf CRYPTO\_OK} if it is ready.  Finally to actually read bytes call:
+\index{PRNG read}
 \begin{verbatim}
 unsigned long XXX_read(unsigned char *out, unsigned long len,
                        prng_state *prng);
 \end{verbatim}
 
-Which returns the number of bytes read from the PRNG.
+Which returns the number of bytes read from the PRNG.  When you are finished with a PRNG state you call
+the following.
+
+\index{PRNG done}
+\begin{verbatim}
+void XXX_done(prng_state *prng);
+\end{verbatim}
+
+This will terminate a PRNG state and free any memory (if any) allocated.  To export a PRNG state
+so that you can later resume the PRNG call the following.
+
+\index{PRNG export}
+\begin{verbatim}
+int XXX_export(unsigned char *out, unsigned long *outlen, 
+               prng_state    *prng);
+\end{verbatim}
+
+This will write a ``PRNG state'' to the buffer ``out'' of length ``outlen'' bytes.  The idea of 
+the export is meant to be used as a ``seed file''.  That is, when the program starts up there will not likely
+be that much entropy available.   To import a state to seed a PRNG call the following function.
+
+\index{PRNG import}
+\begin{verbatim}
+int XXX_import(const unsigned char *in, unsigned long inlen, 
+                     prng_state     *prng);
+\end{verbatim}
+
+This will call the start and add\_entropy functions of the given PRNG.  It will use the state in
+``in'' of length ``inlen'' as the initial seed.  You must pass the same seed length as was exported
+by the corresponding export function.
+
+Note that importing a state will not ``resume'' the PRNG from where it left off.  That is, if you export
+a state, emit (say) 8 bytes and then import the previously exported state the next 8 bytes will not 
+specifically equal the 8 bytes you generated previously.
+
+When a program is first executed the normal course of operation is 
+
+\begin{enumerate}
+   \item Gather entropy from your sources for a given period of time or number of events.
+   \item Start, use your entropy via add\_entropy and ready the PRNG yourself.
+\end{enumerate}
+
+When your program is finished you simply call the export function and save the state to a medium (disk,
+flash memory, etc).  The next time your application starts up you can detect the state, feed it to the 
+import function and go on your way.  It is ideal that (as soon as possible) after startup you export a
+fresh state.  This helps in the case that the program aborts or the machine is powered down without
+being given a chance to exit properly.  
+
+Note that even if you have a state to import it is important to add new entropy to the state.  However,
+there is less pressure to do so.  
+
+To test a PRNG for operational conformity call the following functions.
+
+\index{PRNG test}
+\begin{verbatim}
+int XXX_test(void);
+\end{verbatim}
+
+This will return \textbf{CRYPT\_OK} if PRNG is operating properly.
 
 \subsection{Remarks}
 
@@ -1719,8 +1827,8 @@
 
 \subsection{Example}
 
-Below is a simple snippet to read 10 bytes from yarrow.  Its important to note that this snippet is {\bf NOT} secure since
-the entropy added is not random.
+Below is a simple snippet to read 10 bytes from yarrow.  Its important to note that this snippet is 
+{\bf NOT} secure since the entropy added is not random.
 
 \begin{verbatim}
 #include <mycrypt.h>
@@ -1753,10 +1861,15 @@
 \begin{verbatim}
 struct _prng_descriptor {
     char *name;
+    int  export_size;    /* size in bytes of exported state */
     int (*start)      (prng_state *);
     int (*add_entropy)(const unsigned char *, unsigned long, prng_state *);
     int (*ready)      (prng_state *);
     unsigned long (*read)(unsigned char *, unsigned long len, prng_state *);
+    void (*done)(prng_state *);
+    int (*export)(unsigned char *, unsigned long *, prng_state *);
+    int (*import)(const unsigned char *, unsigned long, prng_state *);
+    int (*test)(void);
 };
 \end{verbatim}
 
@@ -1770,16 +1883,82 @@
 int unregister_prng(const struct _prng_descriptor *prng);
 \end{verbatim}
 
-\subsubsection{PRNGs Provided}
-Currently Yarrow (yarrow\_desc), RC4 (rc4\_desc) and the secure RNG (sprng\_desc) are provided as PRNGs within the 
-library.  
-
-RC4 is provided with a PRNG interface because it is a stream cipher and not well suited for the symmetric block cipher
-interface.  You provide the key for RC4 via the rc4\_add\_entropy() function.  By calling rc4\_ready() the key will be used
-to setup the RC4 state for encryption or decryption.  The rc4\_read() function has been modified from RC4 since it will 
-XOR the output of the RC4 keystream generator against the input buffer you provide.  The following snippet will demonstrate
-how to encrypt a buffer with RC4:
-
+\subsection{PRNGs Provided}
+\begin{figure}[here]
+\begin{center}
+\begin{small}
+\begin{tabular}{|c|c|l|}
+\hline \textbf{Name} & \textbf{Descriptor} & \textbf{Usage} \\
+\hline Yarrow & yarrow\_desc & Fast short-term PRNG \\
+\hline Fortuna & fortuna\_desc & Fast long-term PRNG (recommended) \\
+\hline RC4 & rc4\_desc & Stream Cipher \\
+\hline SOBER-128 & sober128\_desc & Stream Cipher (also very fast PRNG) \\
+\hline
+\end{tabular}
+\end{small}
+\end{center}
+\caption{List of Provided PRNGs}
+\end{figure}
+
+\subsubsection{Yarrow}
+Yarrow is fast PRNG meant to collect an unspecified amount of entropy from sources 
+(keyboard, mouse, interrupts, etc) and produce an unbounded string of random bytes.  
+
+\textit{Note:} This PRNG is still secure for most taskings but is no longer recommended.  Users
+should use Fortuna instead.
+
+\subsubsection{Fortuna}
+
+Fortuna is a fast attack tolerant and more thoroughly designed PRNG suitable for long term
+usage.  It is faster than the default implementation of Yarrow\footnote{Yarrow has been implemented
+to work with most cipher and hash combos based on which you have chosen to build into the library.} while
+providing more security.  
+
+Fortuna is slightly less flexible than Yarrow in the sense that it only works with the AES block cipher 
+and SHA--256 hash function.  Technically Fortuna will work with any block cipher that accepts a 256--bit
+key and any hash that produces at least a 256--bit output.  However, to make the implementation simpler
+it has been fixed to those choices.
+
+Fortuna is more secure than Yarrow in the sense that attackers who learn parts of the entropy being 
+added to the PRNG learn far less about the state than that of Yarrow.  Without getting into to many
+details Fortuna has the ability to recover from state determination attacks where the attacker starts
+to learn information from the PRNGs output about the internal state.  Yarrow on the other hand cannot 
+recover from that problem until new entropy is added to the pool and put to use through the ready() function.
+
+\subsubsection{RC4}
+
+RC4 is an old stream cipher that can also double duty as a PRNG in a pinch.  You ``key'' it by
+calling add\_entropy() and setup the key by calling ready().  You can only add upto 256 bytes via
+add\_entropy().  
+
+When you read from RC4 the output of the RC4 algorithm is XOR'd against your buffer you provide.  In this
+manner you can use rc4\_read() as an encrypt (and decrypt) function.  
+
+You really shouldn't use RC4 anymore.  This isn't because RC4 is weak (though biases are known to exist) just
+simply that faster alternatives exist.
+
+\subsubsection{SOBER-128}
+
+SOBER-128 is a stream cipher designed by the QUALCOMM Australia team.  Like RC4 you ``key'' it by 
+calling add\_entropy().  There is no need to call ready() for this PRNG as it does not do anything.  
+
+Note that this cipher has several oddities about how it operates.  The first time you call 
+add\_entropy() that sets the cipher's key.  Every other time you call the same function it sets
+the cipher's IV variable.  The IV mechanism allows you to encrypt several messages with the same
+key and not re--use the same key material.
+
+Unlike Yarrow and Fortuna all of the entropy (and hence security) of this algorithm rests in the data
+you pass it on the first call to add\_entropy().  All buffers sent to add\_entropy() must have a length
+that is a multiple of four bytes.
+
+Like RC4 the output of SOBER--128 is XOR'ed against the buffer you provide it.  In this manner you can use
+sober128\_read() as an encrypt (and decrypt) function.
+
+Since SOBER-128 has a fixed keying scheme and is very fast (faster than RC4) the ideal usage of SOBER-128 is to 
+key it from the output of Fortuna (or Yarrow) and use it to encrypt messages.  It is also ideal for
+simulations which need a high quality (and fast) stream of bytes.  
+
+\subsubsection{Example Usage}
 \begin{small}
 \begin{verbatim}
 #include <mycrypt.h>
@@ -2116,10 +2295,11 @@
 ``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.
+\index{PK\_PRIVATE} \index{PK\_PUBLIC}
+There are two types of RSA keys.  The types are {\bf PK\_PRIVATE} and {\bf PK\_PUBLIC}.  The first type is a private 
+RSA key which includes the CRT parameters\footnote{As of v0.99 the PK\_PRIVATE\_OPTIMIZED type has been deprecated
+and has been replaced by the PK\_PRIVATE type.} in the form of a RSAPrivateKey.  The second type is a public RSA key
+which only includes the modulus and public exponent.  It takes the form of a RSAPublicKey.
 
 \subsection{RSA Exponentiation}
 
@@ -2272,79 +2452,6 @@
 }
 \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
-is made up of two algorithms, Algorithm One and Algorithm Two.  Algorithm One is the older fairly limited algorithm which has been implemented
-for completeness.  Algorithm Two is a bit more modern and more flexible to work with.
-
-\section{Algorithm One}
-Algorithm One accepts as input a password, an 8--byte salt and an iteration counter.  The iteration counter is meant to act as delay for
-people trying to brute force guess the password.  The higher the iteration counter the longer the delay.  This algorithm also requires a hash 
-algorithm and produces an output no longer than the output of the hash.  
-
-\index{pkcs\_5\_alg1()}
-\begin{alltt}
-int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, 
-                const unsigned char *salt, 
-                int iteration_count,  int hash_idx,
-                unsigned char *out,   unsigned long *outlen)
-\end{alltt}
-Where ``password'' is the users password.  Since the algorithm allows binary passwords you must also specify the length in ``password\_len''.  
-The ``salt'' is a fixed size 8--byte array which should be random for each user and session.  The ``iteration\_count'' is the delay desired
-on the password.  The ``hash\_idx'' is the index of the hash you wish to use in the descriptor table.  
-
-The output of length upto ``outlen'' is stored in ``out''.  If ``outlen'' is initially larger than the size of the hash functions output
-it is set to the number of bytes stored.  If it is smaller than not all of the hash output is stored in ``out''.
-
-\section{Algorithm Two}
-
-Algorithm Two is the recommended algorithm for this task.  It allows variable length salts and can produce outputs larger than the 
-hash functions output.  As such it can easily be used to derive session keys for ciphers and MACs as well initial vectors as required
-from a single password and invokation of this algorithm.
-
-\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,
-                int iteration_count,           int hash_idx,
-                unsigned char *out,            unsigned long *outlen)
-\end{alltt}
-Where ``password'' is the users password.  Since the algorithm allows binary passwords you must also specify the length in ``password\_len''.  
-The ``salt'' is an array of size ``salt\_len''.  It should be random for each user and session.  The ``iteration\_count'' is the delay desired
-on the password.  The ``hash\_idx'' is the index of the hash you wish to use in the descriptor table.   The output of length upto 
-``outlen'' is stored in ``out''.
-
-\begin{alltt}
-/* demo to show how to make session state material from a password */
-#include <mycrypt.h>
-int main(void)
-\{
-    unsigned char password[100], salt[100],
-                  cipher_key[16], cipher_iv[16],
-                  mac_key[16], outbuf[48];
-    int           err, hash_idx;
-    unsigned long outlen, password_len, salt_len;
-
-    /* register hash and get it's idx .... */
-
-    /* get users password and make up a salt ... */
-
-    /* create the material (100 iterations in algorithm) */
-    outlen = sizeof(outbuf);
-    if ((err = pkcs_5_alg2(password, password_len, salt, salt_len, 
-                           100, hash_idx, outbuf, &outlen)) != CRYPT_OK) \{
-       /* error handle */
-    \}
-
-    /* now extract it */
-    memcpy(cipher_key, outbuf, 16);
-    memcpy(cipher_iv,  outbuf+16, 16);
-    memcpy(mac_key,    outbuf+32, 16);
-
-    /* use material (recall to store the salt in the output) */
-\}
-\end{alltt}
 
 \chapter{Diffie-Hellman Key Exchange}
 
@@ -2774,8 +2881,6 @@
 This will test ``key'' and store the result in ``stat''.  If the result is $stat = 0$ the DSA key failed one of the tests
 and should not be used at all.  If the result is $stat = 1$ the DSA key is valid (as far as valid mathematics are concerned).
 
-
-
 \section{Signatures}
 To generate a DSA signature call the following function
 
@@ -2825,6 +2930,153 @@
 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{Standards Support}
+\section{DER Support}
+DER or ``Distinguished Encoding Rules'' is a subset of the ASN.1 encoding rules that is fully deterministic and
+ideal for cryptography.  In particular ASN.1 specifies an INTEGER type for storing arbitrary sized integers.  DER
+further limits the ASN.1 specifications to a deterministic encoding.
+
+\subsection{Storing INTEGER types}
+\index{der\_encode\_integer()}
+\begin{alltt}
+int der_encode_integer(mp_int *num, unsigned char *out, unsigned long *outlen);
+\end{alltt}
+
+This will store the integer in ``num'' to the output buffer ``out'' of length ``outlen''.  It only stores
+non--negative numbers.  It stores the number of octets used back in ``outlen''.
+
+\subsection{Reading INTEGER types}
+\index{der\_decode\_integer()}
+\begin{alltt}
+int der_decode_integer(const unsigned char *in, unsigned long *inlen, mp_int *num);
+\end{alltt}
+This will decode the DER encoded INTEGER in ``in'' of length ``inlen'' and store the resulting integer
+in ``num''.  It will store the bytes read in ``inlen'' which is handy if you have to parse multiple
+data items out of a binary packet.
+
+\subsection{INTEGER length}
+\index{der\_length\_integer()}
+\begin{alltt}
+int der_length_integer(mp_int *num, unsigned long *len);
+\end{alltt}
+This will determine the length of the DER encoding of the integer ``num'' and store it in ``len''.
+
+\subsection{Multiple INTEGER types}
+To simplify the DER encoding/decoding there are two functions two handle multple types at once.
+
+\index{der\_put\_multi\_integer()}
+\index{der\_get\_multi\_integer()}
+\begin{alltt}
+int der_put_multi_integer(unsigned char *dst, unsigned long *outlen, mp_int *num, ...);
+int der_get_multi_integer(const unsigned char *src, unsigned long *inlen,  mp_int *num, ...);
+\end{alltt}
+
+These will handle multiple encodings/decodings at once.  They work like their single operand counterparts
+except they handle a \textbf{NULL} terminated list of operands.
+
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   mp_int        a, b, c, d;
+   unsigned char buffer[1000];
+   unsigned long len;
+   int           err;
+
+   /* init a,b,c,d with some values ... */
+
+   /* ok we want to store them now... */
+   len = sizeof(buffer);
+   if ((err = der_put_multi_integer(buffer, &len, 
+                                    &a, &b, &c, &d, NULL)) != CRYPT_OK) {
+      // error
+   }
+   printf("I stored %lu bytes in buf\n", len);
+
+   /* ok say we want to get them back for fun */
+   /* len set previously...otherwise set it to the size of the packet */
+   if ((err = der_get_multi_integer(buffer, &len,
+                                    &a, &b, &c, &d, NULL)) != CRYPT_OK) {
+      // error
+   }
+   printf("I read %lu bytes from buf\n", len);
+}
+\end{verbatim}
+\section{Password Based Cryptography}
+\subsection{PKCS \#5}
+In order to securely handle user passwords for the purposes of creating session keys and chaining IVs the PKCS \#5 was drafted.   PKCS \#5
+is made up of two algorithms, Algorithm One and Algorithm Two.  Algorithm One is the older fairly limited algorithm which has been implemented
+for completeness.  Algorithm Two is a bit more modern and more flexible to work with.
+
+\subsection{Algorithm One}
+Algorithm One accepts as input a password, an 8--byte salt and an iteration counter.  The iteration counter is meant to act as delay for
+people trying to brute force guess the password.  The higher the iteration counter the longer the delay.  This algorithm also requires a hash 
+algorithm and produces an output no longer than the output of the hash.  
+
+\index{pkcs\_5\_alg1()}
+\begin{alltt}
+int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, 
+                const unsigned char *salt, 
+                int iteration_count,  int hash_idx,
+                unsigned char *out,   unsigned long *outlen)
+\end{alltt}
+Where ``password'' is the users password.  Since the algorithm allows binary passwords you must also specify the length in ``password\_len''.  
+The ``salt'' is a fixed size 8--byte array which should be random for each user and session.  The ``iteration\_count'' is the delay desired
+on the password.  The ``hash\_idx'' is the index of the hash you wish to use in the descriptor table.  
+
+The output of length upto ``outlen'' is stored in ``out''.  If ``outlen'' is initially larger than the size of the hash functions output
+it is set to the number of bytes stored.  If it is smaller than not all of the hash output is stored in ``out''.
+
+\subsection{Algorithm Two}
+
+Algorithm Two is the recommended algorithm for this task.  It allows variable length salts and can produce outputs larger than the 
+hash functions output.  As such it can easily be used to derive session keys for ciphers and MACs as well initial vectors as required
+from a single password and invokation of this algorithm.
+
+\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,
+                int iteration_count,           int hash_idx,
+                unsigned char *out,            unsigned long *outlen)
+\end{alltt}
+Where ``password'' is the users password.  Since the algorithm allows binary passwords you must also specify the length in ``password\_len''.  
+The ``salt'' is an array of size ``salt\_len''.  It should be random for each user and session.  The ``iteration\_count'' is the delay desired
+on the password.  The ``hash\_idx'' is the index of the hash you wish to use in the descriptor table.   The output of length upto 
+``outlen'' is stored in ``out''.
+
+\begin{alltt}
+/* demo to show how to make session state material from a password */
+#include <mycrypt.h>
+int main(void)
+\{
+    unsigned char password[100], salt[100],
+                  cipher_key[16], cipher_iv[16],
+                  mac_key[16], outbuf[48];
+    int           err, hash_idx;
+    unsigned long outlen, password_len, salt_len;
+
+    /* register hash and get it's idx .... */
+
+    /* get users password and make up a salt ... */
+
+    /* create the material (100 iterations in algorithm) */
+    outlen = sizeof(outbuf);
+    if ((err = pkcs_5_alg2(password, password_len, salt, salt_len, 
+                           100, hash_idx, outbuf, &outlen)) != CRYPT_OK) \{
+       /* error handle */
+    \}
+
+    /* now extract it */
+    memcpy(cipher_key, outbuf, 16);
+    memcpy(cipher_iv,  outbuf+16, 16);
+    memcpy(mac_key,    outbuf+32, 16);
+
+    /* use material (recall to store the salt in the output) */
+\}
+\end{alltt}
+
+
 \chapter{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 
@@ -3058,18 +3310,77 @@
 is modular enough putting the locks in the right place should not bloat the code significantly and will solve all thread
 safety issues within the library.
 
-\chapter{Configuring the Library}
+\chapter{Configuring and Building the Library}
 \section{Introduction}
 The library is fairly flexible about how it can be built, used and generally distributed.  Additions are being made with
-each new release that will make the library even more flexible.  Most options are placed in the makefile and others
-are in ``mycrypt\_cfg.h''.  All are used when the library is built from scratch.
-
-For GCC platforms the file ``makefile'' is the makefile to be used.  On MSVC platforms ``makefile.vc'' and on PS2 platforms
-``makefile.ps2''.
+each new release that will make the library even more flexible.  Each of the classes of functions can be disabled during
+the build process to make a smaller library.  This is particularly useful for shared libraries.
+
+\section{Building a Static Library}
+The library can be built as a static library which is generally the simplest and most portable method of 
+building the library.  With a CC or GCC equipped platform you can issue the following
+
+\begin{alltt}
+make install_lib
+\end{alltt}
+
+Which will build the library and install it in /usr/lib (as well as the headers in /usr/include).  The destination
+directory of the library and headers can be changed by editing ``makefile''.  The variable LIBNAME controls
+where the library is to be installed and INCNAME controls where the headers are to be installed.  A developer can 
+then use the library by including ``mycrypt.h'' in their program and linking against ``libtomcrypt.a''.
+
+A static library can also be built with the Intel C Compiler  (ICC) by issuing the following
+
+\begin{alltt}
+make -f makefile.icc install
+\end{alltt}
+
+This will also build ``libtomcrypt.a'' except that it will use ICC.  Additionally Microsoft's Visual C 6.00 can be used
+by issuing
+
+\begin{alltt}
+nmake -f makefile.msvc
+\end{alltt}
+
+You will have to manually copy ``tomcrypt.lib'' and the headers to your MSVC lib/inc directories.
+
+\subsection{MPI Control}
+If you already have LibTomMath installed you can safely remove it from the build.  By commenting the line
+in the appropriate makefile which starts with 
+
+\begin{alltt}
+MPIOBJECT=mpi
+\end{alltt}
+
+Simply place a \# at the start and re-build the library.  To properly link applications you will have to also
+link in LibTomMath.  Removing MPI has the benefit of cutting down the library size as well potentially have access
+to the latest mpi.
+
+\section{Building a Shared Library}
+LibTomCrypt can also be built as a shared library (.so, .dll, etc...).  With non-Windows platforms the assumption
+of the presence of gcc and ``libtool'' has been made.  These are fairly common on Unix/Linux/BSD platforms.  To
+build a .so shared library issue 
+
+\begin{alltt}
+make -f makefile.shared
+\end{alltt}
+This will use libtool and gcc to build a shared library ``libtomcrypt.la'' as well as a static library ``libtomcrypt.a''
+and install them into /usr/lib (and the headers into /usr/include).  To link your application you should use the 
+libtool program in ``--mode=link''.
+
+You can also build LibTomCrypt as a shared library (DLL) in Windows with Cygwin.  Issue the following
+
+\begin{alltt}
+make -f makefile.cygwin_dll
+\end{alltt}
+This will build ``libtomcrypt.dll.a'' which is an import library for ``libtomcrypt.dll''.  You must copy 
+``libtomcrypt.dll.a'' to your library directory, ``libtomcrypt.dll' to somewhere in your PATH and the header
+files to your include directory.  So long as ``libtomcrypt.dll'' is in your system path you can run any LibTomCrypt
+program that uses it.
 
 \section{mycrypt\_cfg.h}
-The file ``mycrypt\_cfg.h'' is what lets you control what functionality you want to remove from the library.  By default,
-everything the library has to offer it built.  
+The file ``mycrypt\_cfg.h'' is what lets you control various high level macros which control the behaviour 
+of the library. 
 
 \subsubsection{ARGTYPE}
 This lets you control how the \_ARGCHK macro will behave.  The macro is used to check pointers inside the functions against
@@ -3082,17 +3393,18 @@
 There are five macros related to endianess issues.  For little endian platforms define, ENDIAN\_LITTLE.  For big endian
 platforms define ENDIAN\_BIG.  Similarly when the default word size of an ``unsigned long'' is 32-bits define ENDIAN\_32BITWORD
 or define ENDIAN\_64BITWORD when its 64-bits.  If you do not define any of them the library will automatically use ENDIAN\_NEUTRAL
-which will work on all platforms.  Currently the system will automatically detect GCC or MSVC on a windows platform as well
-as GCC on a PS2 platform.
+which will work on all platforms.
+
+Currently LibTomCrypt will detect x86-32 and x86-64 running GCC as well as x86-32 running MSVC.  
 
 \section{The Configure Script}
-There are also options you can specify from the configure script or ``mycrypt\_config.h''.  
+There are also options you can specify from the configure script or ``mycrypt\_custom.h''.  
 
 \subsubsection{X memory routines}
-The makefiles must define three macros denoted as XMALLOC, XCALLOC and XFREE which resolve to the name of the respective
-functions.  This lets you substitute in your own memory routines.  If you substitute in your own functions they must behave
-like the standard C library functions in terms of what they expect as input and output.  By default the library uses the
-standard C routines.
+At the top of mycrypt\_custom.h are four macros denoted as XMALLOC, XCALLOC, XREALLOC and XFREE which resolve to 
+the name of the respective functions.  This lets you substitute in your own memory routines.  If you substitute in 
+your own functions they must behave like the standard C library functions in terms of what they expect as input and 
+output.  By default the library uses the standard C routines.
 
 \subsubsection{X clock routines}
 The rng\_get\_bytes() function can call a function that requires the clock() function.  These macros let you override
@@ -3100,17 +3412,22 @@
 
 \subsubsection{NO\_FILE}
 During the build if NO\_FILE is defined then any function in the library that uses file I/O will not call the file I/O 
-functions and instead simply return CRYPT\_ERROR.  This should help resolve any linker errors stemming from a lack of
+functions and instead simply return CRYPT\_NOP.  This should help resolve any linker errors stemming from a lack of
 file I/O on embedded platforms.
 
 \subsubsection{CLEAN\_STACK}
-When this functions is defined the functions that store key material on the stack will clean up afterwards.  Assumes that
-you have no memory paging with the stack.
+When this functions is defined the functions that store key material on the stack will clean up afterwards.  
+Assumes that you have no memory paging with the stack.
+
+\subsubsection{LTC\_TEST}
+When this has been defined the various self--test functions (for ciphers, hashes, prngs, etc) are included in the build.
+When this has been undefined the tests are removed and if called will return CRYPT\_NOP.
 
 \subsubsection{Symmetric Ciphers, One-way Hashes, PRNGS and Public Key Functions}
-There are a plethora of macros for the ciphers, hashes, PRNGs and public key functions which are fairly self-explanatory.  
-When they are defined the functionality is included otherwise it is not.  There are some dependency issues which are
-noted in the file.  For instance, Yarrow requires CTR chaining mode, a block cipher and a hash function.
+There are a plethora of macros for the ciphers, hashes, PRNGs and public key functions which are fairly 
+self-explanatory.  When they are defined the functionality is included otherwise it is not.  There are some 
+dependency issues which are noted in the file.  For instance, Yarrow requires CTR chaining mode, a block 
+cipher and a hash function.
 
 \subsubsection{TWOFISH\_SMALL and TWOFISH\_TABLES}
 Twofish is a 128-bit symmetric block cipher that is provided within the library.  The cipher itself is flexible enough
@@ -3128,6 +3445,20 @@
 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.
 
+\section{MPI Tweaks}
+\subsection{RSA Only Tweak}
+If you plan on only using RSA with moduli in the range of 1024 to 2560 bits you can enable a series of tweaks
+to reduce the library size.  Follow these steps
+
+\begin{enumerate}
+   \item Undefine MDSA, MECC and MDH from mycrypt\_custom.h
+   \item Undefine LTM\_ALL  from tommath\_superclass.h
+   \item Define SC\_RSA\_1 from tommath\_superclass.h
+   \item Rebuild the library.
+\end{enumerate}
+
+
+
 \input{crypt.ind}
 
 \end{document}
--- a/crypt_cipher_descriptor.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/crypt_cipher_descriptor.c	Sun Dec 19 11:34:45 2004 +0000
@@ -10,37 +10,5 @@
  */
 #include "mycrypt.h"
 
-struct _cipher_descriptor cipher_descriptor[TAB_SIZE] = {
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
-{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL } };
+struct _cipher_descriptor cipher_descriptor[TAB_SIZE];
 
--- a/crypt_hash_descriptor.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/crypt_hash_descriptor.c	Sun Dec 19 11:34:45 2004 +0000
@@ -10,36 +10,5 @@
  */
 #include "mycrypt.h"
 
-struct _hash_descriptor hash_descriptor[TAB_SIZE] = {
-{ 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 } };
+struct _hash_descriptor hash_descriptor[TAB_SIZE];
+
--- a/crypt_prng_descriptor.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/crypt_prng_descriptor.c	Sun Dec 19 11:34:45 2004 +0000
@@ -10,37 +10,4 @@
  */
 #include "mycrypt.h"
 
-struct _prng_descriptor prng_descriptor[TAB_SIZE] = {
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL },
-{ NULL, NULL, NULL, NULL, NULL } };
-
+struct _prng_descriptor prng_descriptor[TAB_SIZE];
--- a/crypt_register_cipher.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/crypt_register_cipher.c	Sun Dec 19 11:34:45 2004 +0000
@@ -26,7 +26,7 @@
    /* find a blank spot */
    for (x = 0; x < TAB_SIZE; x++) {
        if (cipher_descriptor[x].name == NULL) {
-          memcpy(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor));
+          XMEMCPY(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor));
           return x;
        }
    }
--- a/crypt_register_hash.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/crypt_register_hash.c	Sun Dec 19 11:34:45 2004 +0000
@@ -26,7 +26,7 @@
    /* find a blank spot */
    for (x = 0; x < TAB_SIZE; x++) {
        if (hash_descriptor[x].name == NULL) {
-          memcpy(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor));
+          XMEMCPY(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor));
           return x;
        }
    }
--- a/crypt_register_prng.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/crypt_register_prng.c	Sun Dec 19 11:34:45 2004 +0000
@@ -26,7 +26,7 @@
    /* find a blank spot */
    for (x = 0; x < TAB_SIZE; x++) {
        if (prng_descriptor[x].name == NULL) {
-          memcpy(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor));
+          XMEMCPY(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor));
           return x;
        }
    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cscope.tmplst	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,219 @@
+./aes.c
+./aes_tab.c
+./base64_decode.c
+./base64_encode.c
+./blowfish.c
+./burn_stack.c
+./cast5.c
+./cbc_decrypt.c
+./cbc_encrypt.c
+./cbc_getiv.c
+./cbc_setiv.c
+./cbc_start.c
+./cfb_decrypt.c
+./cfb_encrypt.c
+./cfb_getiv.c
+./cfb_setiv.c
+./cfb_start.c
+./chc.c
+./crypt.c
+./crypt_argchk.c
+./crypt_cipher_descriptor.c
+./crypt_cipher_is_valid.c
+./crypt_find_cipher.c
+./crypt_find_cipher_any.c
+./crypt_find_cipher_id.c
+./crypt_find_hash.c
+./crypt_find_hash_any.c
+./crypt_find_hash_id.c
+./crypt_find_prng.c
+./crypt_hash_descriptor.c
+./crypt_hash_is_valid.c
+./crypt_prng_descriptor.c
+./crypt_prng_is_valid.c
+./crypt_register_cipher.c
+./crypt_register_hash.c
+./crypt_register_prng.c
+./crypt_unregister_cipher.c
+./crypt_unregister_hash.c
+./crypt_unregister_prng.c
+./ctr_decrypt.c
+./ctr_encrypt.c
+./ctr_getiv.c
+./ctr_setiv.c
+./ctr_start.c
+./demos/encrypt.c
+./demos/hashsum.c
+./demos/small.c
+./demos/test/base64_test.c
+./demos/test/cipher_hash_test.c
+./demos/test/der_tests.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/makefile.shared
+./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
+./demos/tv_gen.c
+./demos/x86_prof.c
+./der_decode_integer.c
+./der_encode_integer.c
+./der_get_multi_integer.c
+./der_length_integer.c
+./der_put_multi_integer.c
+./des.c
+./dh.c
+./dh_sys.c
+./dsa_export.c
+./dsa_free.c
+./dsa_import.c
+./dsa_make_key.c
+./dsa_sign_hash.c
+./dsa_verify_hash.c
+./dsa_verify_key.c
+./eax_addheader.c
+./eax_decrypt.c
+./eax_decrypt_verify_memory.c
+./eax_done.c
+./eax_encrypt.c
+./eax_encrypt_authenticate_memory.c
+./eax_init.c
+./eax_test.c
+./ecb_decrypt.c
+./ecb_encrypt.c
+./ecb_start.c
+./ecc.c
+./ecc_sys.c
+./error_to_string.c
+./fortuna.c
+./hash_file.c
+./hash_filehandle.c
+./hash_memory.c
+./hmac_done.c
+./hmac_file.c
+./hmac_init.c
+./hmac_memory.c
+./hmac_process.c
+./hmac_test.c
+./is_prime.c
+./ltc_tommath.h
+./makefile
+./makefile.cygwin_dll
+./makefile.icc
+./makefile.msvc
+./makefile.shared
+./md2.c
+./md4.c
+./md5.c
+./mpi.c
+./mpi_to_ltc_error.c
+./mycrypt.h
+./mycrypt_argchk.h
+./mycrypt_cfg.h
+./mycrypt_cipher.h
+./mycrypt_custom.h
+./mycrypt_hash.h
+./mycrypt_macros.h
+./mycrypt_misc.h
+./mycrypt_pk.h
+./mycrypt_pkcs.h
+./mycrypt_prng.h
+./noekeon.c
+./notes/etc/whirlgen.c
+./notes/etc/whirltest.c
+./ocb_decrypt.c
+./ocb_decrypt_verify_memory.c
+./ocb_done_decrypt.c
+./ocb_done_encrypt.c
+./ocb_encrypt.c
+./ocb_encrypt_authenticate_memory.c
+./ocb_init.c
+./ocb_ntz.c
+./ocb_shift_xor.c
+./ocb_test.c
+./ofb_decrypt.c
+./ofb_encrypt.c
+./ofb_getiv.c
+./ofb_setiv.c
+./ofb_start.c
+./omac_done.c
+./omac_file.c
+./omac_init.c
+./omac_memory.c
+./omac_process.c
+./omac_test.c
+./packet_store_header.c
+./packet_valid_header.c
+./pkcs_1_i2osp.c
+./pkcs_1_mgf1.c
+./pkcs_1_oaep_decode.c
+./pkcs_1_oaep_encode.c
+./pkcs_1_os2ip.c
+./pkcs_1_pss_decode.c
+./pkcs_1_pss_encode.c
+./pkcs_1_v15_es_decode.c
+./pkcs_1_v15_es_encode.c
+./pkcs_1_v15_sa_decode.c
+./pkcs_1_v15_sa_encode.c
+./pkcs_5_1.c
+./pkcs_5_2.c
+./pmac_done.c
+./pmac_file.c
+./pmac_init.c
+./pmac_memory.c
+./pmac_ntz.c
+./pmac_process.c
+./pmac_shift_xor.c
+./pmac_test.c
+./rand_prime.c
+./rc2.c
+./rc4.c
+./rc5.c
+./rc6.c
+./rmd128.c
+./rmd160.c
+./rng_get_bytes.c
+./rng_make_prng.c
+./rsa_decrypt_key.c
+./rsa_encrypt_key.c
+./rsa_export.c
+./rsa_exptmod.c
+./rsa_free.c
+./rsa_import.c
+./rsa_make_key.c
+./rsa_sign_hash.c
+./rsa_v15_decrypt_key.c
+./rsa_v15_encrypt_key.c
+./rsa_v15_sign_hash.c
+./rsa_v15_verify_hash.c
+./rsa_verify_hash.c
+./s_ocb_done.c
+./safer.c
+./safer_tab.c
+./saferp.c
+./sha1.c
+./sha224.c
+./sha256.c
+./sha384.c
+./sha512.c
+./skipjack.c
+./sober128.c
+./sober128tab.c
+./sprng.c
+./tiger.c
+./tim_exptmod.c
+./twofish.c
+./twofish_tab.c
+./whirl.c
+./whirltab.c
+./xtea.c
+./yarrow.c
+./zeromem.c
--- a/ctr_getiv.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/ctr_getiv.c	Sun Dec 19 11:34:45 2004 +0000
@@ -21,7 +21,7 @@
    if ((unsigned long)ctr->blocklen > *len) {
       return CRYPT_BUFFER_OVERFLOW;
    }
-   memcpy(IV, ctr->ctr, ctr->blocklen);
+   XMEMCPY(IV, ctr->ctr, ctr->blocklen);
    *len = ctr->blocklen;
 
    return CRYPT_OK;
--- a/ctr_setiv.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/ctr_setiv.c	Sun Dec 19 11:34:45 2004 +0000
@@ -30,7 +30,7 @@
    }
 
    /* set IV */
-   memcpy(ctr->ctr, IV, len);
+   XMEMCPY(ctr->ctr, IV, len);
    
    /* force next block */
    ctr->padlen = 0;
--- a/demos/hashsum.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/demos/hashsum.c	Sun Dec 19 11:34:45 2004 +0000
@@ -7,7 +7,7 @@
  * more functions ;)
 */
 
-#include <mycrypt_custom.h>
+#include <mycrypt.h>
 
 int errno;
 
@@ -26,7 +26,7 @@
       printf("usage: ./hash algorithm file [file ...]\n");
       printf("Algorithms:\n");
       for (x = 0; hash_descriptor[x].name != NULL; x++) {
-         printf(" %s\n", hash_descriptor[x].name);
+         printf(" %s (%d)\n", hash_descriptor[x].name, hash_descriptor[x].ID);
       }
       exit(EXIT_SUCCESS);
    }
@@ -66,6 +66,8 @@
 
 void register_algs(void)
 {
+  int err;
+
 #ifdef TIGER
   register_hash (&tiger_desc);
 #endif
@@ -102,5 +104,12 @@
 #ifdef WHIRLPOOL
   register_hash (&whirlpool_desc);
 #endif
+#ifdef CHC_HASH
+  register_hash(&chc_desc);
+  if ((err = chc_register(register_cipher(&aes_enc_desc))) != CRYPT_OK) {
+     printf("chc_register error: %s\n", error_to_string(err));
+     exit(EXIT_FAILURE);
+  }
+#endif
 
 }
--- a/demos/test.c	Tue Jun 15 14:07:21 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1622 +0,0 @@
-/* This is the worst code you have ever seen written on purpose.... this code is just a big hack to test
-out the functionality of the library */
-
-#ifdef SONY_PS2
-#include <eetypes.h>
-#include <eeregs.h>
-#include "timer.h"
-#endif
-
-#include <mycrypt.h>
-
-int     errnum;
-
-
-int
-null_setup (const unsigned char *key, int keylen, int num_rounds,
-        symmetric_key * skey)
-{
-  return CRYPT_OK;
-}
-
-void
-null_ecb_encrypt (const unsigned char *pt, unsigned char *ct,
-          symmetric_key * key)
-{
-  memcpy (ct, pt, 8);
-}
-
-void
-null_ecb_decrypt (const unsigned char *ct, unsigned char *pt,
-          symmetric_key * key)
-{
-  memcpy (pt, ct, 8);
-}
-
-int
-null_test (void)
-{
-  return CRYPT_OK;
-}
-
-int
-null_keysize (int *desired_keysize)
-{
-  return CRYPT_OK;
-}
-
-const struct _cipher_descriptor null_desc = {
-  "memcpy()",
-  255,
-  8, 8, 8, 1,
-  &null_setup,
-  &null_ecb_encrypt,
-  &null_ecb_decrypt,
-  &null_test,
-  &null_keysize
-};
-
-
-prng_state prng;
-
-void
-store_tests (void)
-{
-  unsigned char buf[8];
-  unsigned long L;
-  ulong64 LL;
-
-  printf ("LOAD32/STORE32 tests\n");
-  L = 0x12345678UL;
-  STORE32L (L, &buf[0]);
-  L = 0;
-  LOAD32L (L, &buf[0]);
-  if (L != 0x12345678UL) {
-    printf ("LOAD/STORE32 Little don't work\n");
-    exit (-1);
-  }
-  LL = CONST64 (0x01020304050607);
-  STORE64L (LL, &buf[0]);
-  LL = 0;
-  LOAD64L (LL, &buf[0])
-    if (LL != CONST64 (0x01020304050607)) {
-    printf ("LOAD/STORE64 Little don't work\n");
-    exit (-1);
-  }
-
-  L = 0x12345678UL;
-  STORE32H (L, &buf[0]);
-  L = 0;
-  LOAD32H (L, &buf[0]);
-  if (L != 0x12345678UL) {
-    printf ("LOAD/STORE32 High don't work, %08lx\n", L);
-    exit (-1);
-  }
-  LL = CONST64 (0x01020304050607);
-  STORE64H (LL, &buf[0]);
-  LL = 0;
-  LOAD64H (LL, &buf[0])
-    if (LL != CONST64 (0x01020304050607)) {
-    printf ("LOAD/STORE64 High don't work\n");
-    exit (-1);
-  }
-}
-
-void
-cipher_tests (void)
-{
-  int     x;
-
-  printf ("Ciphers compiled in\n");
-  for (x = 0; cipher_descriptor[x].name != NULL; x++) {
-    printf
-      (" %12s (%2d) Key Size: %4d to %4d, Block Size: %3d, Default # of rounds: %2d\n",
-       cipher_descriptor[x].name, cipher_descriptor[x].ID,
-       cipher_descriptor[x].min_key_length * 8,
-       cipher_descriptor[x].max_key_length * 8,
-       cipher_descriptor[x].block_length * 8,
-       cipher_descriptor[x].default_rounds);
-  }
-
-}
-
-void
-ecb_tests (void)
-{
-  int     x;
-
-  printf ("ECB tests\n");
-  for (x = 0; cipher_descriptor[x].name != NULL; x++) {
-    printf (" %12s: ", cipher_descriptor[x].name);
-    if ((errnum = cipher_descriptor[x].test ()) != CRYPT_OK) {
-      printf (" **failed** Reason: %s\n", error_to_string (errnum));
-      exit (-1);
-    } else {
-      printf ("passed\n");
-    }
-  }
-}
-
-#ifdef CBC
-void
-cbc_tests (void)
-{
-  symmetric_CBC cbc;
-  int     x, y;
-  unsigned char blk[32], ct[32], key[32], IV[32];
-  const unsigned char test[] =
-    { 0XFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
-  printf ("CBC tests\n");
-  /* ---- CBC ENCODING ---- */
-  /* make up a block and IV */
-  for (x = 0; x < 32; x++)
-    blk[x] = IV[x] = x;
-
-  /* now lets start a cbc session */
-  if ((errnum =
-       cbc_start (find_cipher ("blowfish"), IV, key, 16, 0,
-          &cbc)) != CRYPT_OK) {
-    printf ("CBC Setup: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  /* now lets encode 32 bytes */
-  for (x = 0; x < 4; x++) {
-    if ((errnum = cbc_encrypt (blk + 8 * x, ct + 8 * x, &cbc)) != CRYPT_OK) {
-      printf ("CBC encrypt: %s\n", error_to_string (errnum));
-      exit (-1);
-    }
-  }
-
-  zeromem (blk, sizeof (blk));
-
-  /* ---- CBC DECODING ---- */
-  /* make up a IV */
-  for (x = 0; x < 32; x++)
-    IV[x] = x;
-
-  /* now lets start a cbc session */
-  if ((errnum =
-       cbc_start (find_cipher ("blowfish"), IV, key, 16, 0,
-          &cbc)) != CRYPT_OK) {
-    printf ("CBC Setup: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  /* now lets decode 32 bytes */
-  for (x = 0; x < 4; x++) {
-    if ((errnum = cbc_decrypt (ct + 8 * x, blk + 8 * x, &cbc)) != CRYPT_OK) {
-      printf ("CBC decrypt: %s\n", error_to_string (errnum));
-      exit (-1);
-    }
-  }
-
-
-  /* print output */
-  for (x = y = 0; x < 32; x++)
-    if (blk[x] != x)
-      y = 1;
-  printf ("  %s\n", y ? "failed" : "passed");
-
-  /* lets actually check the bytes */
-  memset (IV, 0, 8);
-  IV[0] = 0xFF;         /* IV  = FF 00 00 00 00 00 00 00 */
-  memset (blk, 0, 32);
-  blk[8] = 0xFF;        /* BLK = 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 */
-  cbc_start (find_cipher ("memcpy()"), IV, key, 8, 0, &cbc);
-  cbc_encrypt (blk, ct, &cbc);  /* expect: FF 00 00 00 00 00 00 00 */
-  cbc_encrypt (blk + 8, ct + 8, &cbc);  /* expect: 00 00 00 00 00 00 00 00 */
-  if (memcmp (ct, test, 16)) {
-    printf ("CBC failed logical testing.\n");
-    for (x = 0; x < 16; x++)
-      printf ("%02x ", ct[x]);
-    printf ("\n");
-    exit (-1);
-  } else {
-    printf ("CBC passed logical testing.\n");
-  }
-}
-#else
-void
-cbc_tests (void)
-{
-  printf ("CBC not compiled in\n");
-}
-#endif
-
-#ifdef OFB
-void
-ofb_tests (void)
-{
-  symmetric_OFB ofb;
-  int     x, y;
-  unsigned char blk[32], ct[32], key[32], IV[32];
-
-  printf ("OFB tests\n");
-  /* ---- ofb ENCODING ---- */
-  /* make up a block and IV */
-  for (x = 0; x < 32; x++)
-    blk[x] = IV[x] = x;
-
-  /* now lets start a ofb session */
-  if ((errnum =
-       ofb_start (find_cipher ("cast5"), IV, key, 16, 0, &ofb)) != CRYPT_OK) {
-    printf ("OFB Setup: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  /* now lets encode 32 bytes */
-  for (x = 0; x < 4; x++) {
-    if ((errnum = ofb_encrypt (blk + 8 * x, ct + 8 * x, 8, &ofb)) != CRYPT_OK) {
-      printf ("OFB encrypt: %s\n", error_to_string (errnum));
-      exit (-1);
-    }
-  }
-
-  zeromem (blk, sizeof (blk));
-
-  /* ---- ofb DECODING ---- */
-  /* make up a IV */
-  for (x = 0; x < 32; x++)
-    IV[x] = x;
-
-  /* now lets start a ofb session */
-  if ((errnum =
-       ofb_start (find_cipher ("cast5"), IV, key, 16, 0, &ofb)) != CRYPT_OK) {
-    printf ("OFB setup: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  /* now lets decode 32 bytes */
-  for (x = 0; x < 4; x++) {
-    if ((errnum = ofb_decrypt (ct + 8 * x, blk + 8 * x, 8, &ofb)) != CRYPT_OK) {
-      printf ("OFB decrypt: %s\n", error_to_string (errnum));
-      exit (-1);
-    }
-  }
-
-  /* print output */
-  for (x = y = 0; x < 32; x++)
-    if (blk[x] != x)
-      y = 1;
-  printf ("  %s\n", y ? "failed" : "passed");
-  if (y)
-    exit (-1);
-}
-#else
-void
-ofb_tests (void)
-{
-  printf ("OFB not compiled in\n");
-}
-#endif
-
-#ifdef CFB
-void
-cfb_tests (void)
-{
-  symmetric_CFB cfb;
-  int     x, y;
-  unsigned char blk[32], ct[32], key[32], IV[32];
-
-  printf ("CFB tests\n");
-  /* ---- cfb ENCODING ---- */
-  /* make up a block and IV */
-  for (x = 0; x < 32; x++)
-    blk[x] = IV[x] = x;
-
-  /* now lets start a cfb session */
-  if ((errnum =
-       cfb_start (find_cipher ("blowfish"), IV, key, 16, 0,
-          &cfb)) != CRYPT_OK) {
-    printf ("CFB setup: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  /* now lets encode 32 bytes */
-  for (x = 0; x < 4; x++) {
-    if ((errnum = cfb_encrypt (blk + 8 * x, ct + 8 * x, 8, &cfb)) != CRYPT_OK) {
-      printf ("CFB encrypt: %s\n", error_to_string (errnum));
-      exit (-1);
-    }
-  }
-
-  zeromem (blk, sizeof (blk));
-
-  /* ---- cfb DECODING ---- */
-  /* make up ahash_descriptor[prng->yarrow.hash].hashsize IV */
-  for (x = 0; x < 32; x++)
-    IV[x] = x;
-
-  /* now lets start a cfb session */
-  if ((errnum =
-       cfb_start (find_cipher ("blowfish"), IV, key, 16, 0,
-          &cfb)) != CRYPT_OK) {
-    printf ("CFB Setup: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  /* now lets decode 32 bytes */
-  for (x = 0; x < 4; x++) {
-    if ((errnum = cfb_decrypt (ct + 8 * x, blk + 8 * x, 8, &cfb)) != CRYPT_OK) {
-      printf ("CFB decrypt: %s\n", error_to_string (errnum));
-      exit (-1);
-    }
-  }
-
-  /* print output */
-  for (x = y = 0; x < 32; x++)
-    if (blk[x] != x)
-      y = 1;
-  printf ("  %s\n", y ? "failed" : "passed");
-  if (y)
-    exit (-1);
-}
-#else
-void
-cfb_tests (void)
-{
-  printf ("CFB not compiled in\n");
-}
-#endif
-
-#ifdef CTR
-void
-ctr_tests (void)
-{
-  symmetric_CTR ctr;
-  int     x, y;
-  unsigned char blk[32], ct[32], key[32], count[32];
-  const unsigned char test[] =
-    { 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0 };
-
-  printf ("CTR tests\n");
-  /* ---- CTR ENCODING ---- */
-  /* make up a block and IV */
-  for (x = 0; x < 32; x++)
-    blk[x] = count[x] = x;
-
-  /* now lets start a ctr session */
-  if ((errnum =
-       ctr_start (find_cipher ("xtea"), count, key, 16, 0,
-          &ctr)) != CRYPT_OK) {
-    printf ("CTR Setup: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  /* now lets encode 32 bytes */
-  for (x = 0; x < 4; x++) {
-    if ((errnum = ctr_encrypt (blk + 8 * x, ct + 8 * x, 8, &ctr)) != CRYPT_OK) {
-      printf ("CTR encrypt: %s\n", error_to_string (errnum));
-      exit (-1);
-    }
-  }
-
-  zeromem (blk, sizeof (blk));
-
-  /* ---- CTR DECODING ---- */
-  /* make up a IV */
-  for (x = 0; x < 32; x++)
-    count[x] = x;
-
-  /* now lets start a cbc session */
-  if ((errnum =
-       ctr_start (find_cipher ("xtea"), count, key, 16, 0,
-          &ctr)) != CRYPT_OK) {
-    printf ("CTR Setup: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  /* now lets decode 32 bytes */
-  for (x = 0; x < 4; x++) {
-    if ((errnum = ctr_decrypt (ct + 8 * x, blk + 8 * x, 8, &ctr)) != CRYPT_OK) {
-      printf ("CTR decrypt: %s\n", error_to_string (errnum));
-      exit (-1);
-    }
-  }
-
-  /* print output */
-  for (x = y = 0; x < 32; x++)
-    if (blk[x] != x)
-      y = 1;
-  printf ("  %s\n", y ? "failed" : "passed");
-  if (y)
-    exit (-1);
-
-  /* lets actually check the bytes */
-  memset (count, 0, 8);
-  count[0] = 0xFF;      /* IV  = FF 00 00 00 00 00 00 00 */
-  memset (blk, 0, 32);
-  blk[9] = 2;           /* BLK = 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 */
-  ctr_start (find_cipher ("memcpy()"), count, key, 8, 0, &ctr);
-  ctr_encrypt (blk, ct, 8, &ctr);   /* expect: FF 00 00 00 00 00 00 00 */
-  ctr_encrypt (blk + 8, ct + 8, 8, &ctr);   /* expect: 00 03 00 00 00 00 00 00 */
-  if (memcmp (ct, test, 16)) {
-    printf ("CTR failed logical testing.\n");
-    for (x = 0; x < 16; x++)
-      printf ("%02x ", ct[x]);
-    printf ("\n");
-  } else {
-    printf ("CTR passed logical testing.\n");
-  }
-
-}
-#else
-void
-ctr_tests (void)
-{
-  printf ("CTR not compiled in\n");
-}
-#endif
-
-void
-hash_tests (void)
-{
-  int     x;
-  printf ("Hash tests\n");
-  for (x = 0; hash_descriptor[x].name != NULL; x++) {
-    printf (" %10s (%2d) ", hash_descriptor[x].name, hash_descriptor[x].ID);
-    if ((errnum = hash_descriptor[x].test ()) != CRYPT_OK) {
-      printf ("**failed** Reason: %s\n", error_to_string (errnum));
-      exit(-1);
-    } else {
-      printf ("passed\n");
-    }
-  }
-}
-
-#ifdef MRSA
-void
-pad_test (void)
-{
-  unsigned char in[100], out[100];
-  unsigned long x, y;
-
-  /* make a dummy message */
-  for (x = 0; x < 16; x++)
-    in[x] = (unsigned char) x;
-
-  /* pad the message so that random filler is placed before and after it */
-  y = 100;
-  if ((errnum =
-       rsa_pad (in, 16, out, &y, find_prng ("yarrow"), &prng)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  /* depad the message to get the original content */
-  memset (in, 0, sizeof (in));
-  x = 100;
-  if ((errnum = rsa_depad (out, y, in, &x)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  /* check outcome */
-  printf ("rsa_pad: ");
-  if (x != 16) {
-    printf ("Failed.  Wrong size.\n");
-    exit (-1);
-  }
-  for (x = 0; x < 16; x++)
-    if (in[x] != x) {
-      printf ("Failed.  Expected %02lx and got %02x.\n", x, in[x]);
-      exit (-1);
-    }
-  printf ("passed.\n");
-}
-void
-rsa_test (void)
-{
-  unsigned char in[520], out[520];
-  unsigned long x, y, z, limit;
-  int     stat;
-  rsa_key key;
-  clock_t t;
-
-  /* ---- SINGLE ENCRYPT ---- */
-  /* encrypt a short 8 byte string */
-  if ((errnum =
-       rsa_make_key (&prng, find_prng ("yarrow"), 1024 / 8, 65537,
-             &key)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  for (x = 0; x < 8; x++)
-    in[x] = (unsigned char) (x + 1);
-  y = sizeof (in);
-  if ((errnum = rsa_exptmod (in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  /* decrypt it */
-  zeromem (in, sizeof (in));
-  x = sizeof (out);
-  if ((errnum = rsa_exptmod (out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  /* compare */
-  printf ("RSA    : ");
-  for (x = 0; x < 8; x++)
-    if (in[x] != (x + 1)) {
-      printf ("Failed.  x==%02lx, in[%ld]==%02x\n", x, x, in[x]);
-      exit (-1);
-    }
-  printf ("passed.\n");
-
-  /* test the rsa_encrypt_key functions */
-  for (x = 0; x < 16; x++)
-    in[x] = x;
-  y = sizeof (out);
-  if ((errnum =
-       rsa_encrypt_key (in, 16, out, &y, &prng, find_prng ("yarrow"),
-            &key)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  zeromem (in, sizeof (in));
-  x = sizeof (in);
-  if ((errnum = rsa_decrypt_key (out, y, in, &x, &key)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  printf ("RSA en/de crypt key routines: ");
-  if (x != 16) {
-    printf ("Failed (length)\n");
-    exit (-1);
-  }
-  for (x = 0; x < 16; x++)
-    if (in[x] != x) {
-      printf ("Failed (contents)\n");
-      exit (-1);
-    }
-  printf ("Passed\n");
-
-  /* test sign_hash functions */
-  for (x = 0; x < 16; x++)
-    in[x] = x;
-  x = sizeof (in);
-  if ((errnum = rsa_sign_hash (in, 16, out, &x, &key)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  printf ("RSA signed hash: %lu bytes\n", x);
-  if ((errnum = rsa_verify_hash (out, x, in, &stat, &key)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  printf ("Verify hash: %s, ", stat ? "passed" : "failed");
-  in[0] ^= 1;
-  if ((errnum = rsa_verify_hash (out, x, in, &stat, &key)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  printf ("%s\n", (!stat) ? "passed" : "failed");
-  if (stat)
-    exit (-1);
-  rsa_free (&key);
-
-  /* make a RSA key */
-#ifdef SONY_PS2_NOPE
-  limit = 1024;
-#else
-  limit = 2048;
-#endif
-
-  {
-    int     tt;
-
-    for (z = 1024; z <= limit; z += 512) {
-      t = XCLOCK ();
-      for (tt = 0; tt < 3; tt++) {
-         if ((errnum = rsa_make_key (&prng, find_prng ("yarrow"), z / 8, 65537, &key)) != CRYPT_OK) {
-            printf ("Error: %s\n", error_to_string (errnum));
-            exit (-1);
-         }
-
-         /* check modulus size */
-         if (mp_unsigned_bin_size(&key.N) != (int)(z/8)) { 
-            printf("\nRSA key supposed to be %lu bits but was %d bits\n", z, mp_count_bits(&key.N));
-            exit(EXIT_FAILURE);
-         }
-
-         if (tt < 2) {
-            rsa_free (&key);
-         }
-      }
-      t = XCLOCK () - t;
-      printf ("Took %.0f ms to make a %ld-bit RSA key.\n", 1000.0 * (((double) t / 3.0) / (double) XCLOCKS_PER_SEC), z);
-
-      /* time encryption */
-      t = XCLOCK ();
-
-      for (tt = 0; tt < 20; tt++) {
-         y = sizeof (in);
-         if ((errnum = rsa_exptmod (in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) {
-            printf ("Error: %s\n", error_to_string (errnum));
-            exit (-1);
-         }
-      }
-      t = XCLOCK () - t;
-      printf ("Took %.0f ms to encrypt with a %ld-bit RSA key.\n",
-              1000.0 * (((double) t / 20.0) / (double) XCLOCKS_PER_SEC), z);
-
-      /* time decryption */
-      t = XCLOCK ();
-      for (tt = 0; tt < 20; tt++) {
-          x = sizeof (out);
-          if ((errnum = rsa_exptmod (out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) {
-             printf ("Error: %s\n", error_to_string (errnum));
-             exit (-1);
-          }
-      }
-      t = XCLOCK () - t;
-      printf ("Took %.0f ms to decrypt with a %ld-bit RSA key.\n",
-      1000.0 * (((double) t / 20.0) / (double) XCLOCKS_PER_SEC), z);
-      rsa_free (&key);
-    }
-  }
-}
-#else
-void
-pad_test (void)
-{
-  printf ("MRSA not compiled in\n");
-}
-
-void
-rsa_test (void)
-{
-  printf ("MRSA not compiled in\n");
-}
-#endif
-
-#ifdef BASE64
-void
-base64_test (void)
-{
-  unsigned char buf[2][100];
-  unsigned long x, y;
-
-  printf ("Base64 tests\n");
-  zeromem (buf, sizeof (buf));
-  for (x = 0; x < 16; x++)
-    buf[0][x] = (unsigned char) x;
-
-  x = 100;
-  if (base64_encode (buf[0], 16, buf[1], &x) != CRYPT_OK) {
-    printf ("  error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  printf ("  encoded 16 bytes to %ld bytes...[%s]\n", x, buf[1]);
-  memset (buf[0], 0, 100);
-  y = 100;
-  if (base64_decode (buf[1], x, buf[0], &y) != CRYPT_OK) {
-    printf ("  error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  printf ("  decoded %ld bytes to %ld bytes\n", x, y);
-  for (x = 0; x < 16; x++)
-    if (buf[0][x] != x) {
-      printf (" **failed**\n");
-      exit (-1);
-    }
-  printf ("  passed\n");
-}
-#else
-void
-base64_test (void)
-{
-  printf ("Base64 not compiled in\n");
-}
-#endif
-
-void
-time_hash (void)
-{
-  clock_t t1;
-  int     x, y;
-  unsigned long z;
-  unsigned char input[4096], out[MAXBLOCKSIZE];
-  printf ("Hash Time Trials (4KB blocks):\n");
-  for (x = 0; hash_descriptor[x].name != NULL; x++) {
-    t1 = XCLOCK ();
-    z = sizeof (out);
-    y = 0;
-    while (XCLOCK () - t1 < (5 * XCLOCKS_PER_SEC)) {
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      hash_memory (x, input, 4096, out, &z);
-      y += 32;
-    }
-    t1 = XCLOCK () - t1;
-    printf ("%-20s: Hash at %5.2f Mbit/sec\n", hash_descriptor[x].name,
-        ((8.0 * 4096.0) *
-         ((double) y / ((double) t1 / (double) XCLOCKS_PER_SEC))) /
-        1000000.0);
-  }
-}
-
-void
-time_ecb (void)
-{
-  clock_t t1, t2;
-  long    x, y1, y2;
-  unsigned char pt[32], key[32];
-  symmetric_key skey;
-  void    (*func) (const unsigned char *, unsigned char *, symmetric_key *);
-
-  printf ("ECB Time Trials for the Symmetric Ciphers:\n");
-  for (x = 0; cipher_descriptor[x].name != NULL; x++) {
-    cipher_descriptor[x].setup (key, cipher_descriptor[x].min_key_length, 0,
-                &skey);
-
-#define DO1   func(pt,pt,&skey);
-#define DO2   DO1 DO1
-#define DO4   DO2 DO2
-#define DO8   DO4 DO4
-#define DO16  DO8 DO8
-#define DO32  DO16 DO16
-#define DO64  DO32 DO32
-#define DO128 DO64 DO64
-#define DO256 DO128 DO128
-
-    func = cipher_descriptor[x].ecb_encrypt;
-    y1 = 0;
-    t1 = XCLOCK ();
-    while (XCLOCK () - t1 < 3 * XCLOCKS_PER_SEC) {
-      DO256;
-      y1 += 256;
-    }
-    t1 = XCLOCK () - t1;
-
-    func = cipher_descriptor[x].ecb_decrypt;
-    y2 = 0;
-    t2 = XCLOCK ();
-    while (XCLOCK () - t2 < 3 * XCLOCKS_PER_SEC) {
-      DO256;
-      y2 += 256;
-    }
-    t2 = XCLOCK () - t2;
-    printf
-      ("%-20s: Encrypt at %5.2f Mbit/sec and Decrypt at %5.2f Mbit/sec\n",
-       cipher_descriptor[x].name,
-       ((8.0 * (double) cipher_descriptor[x].block_length) *
-    ((double) y1 / ((double) t1 / (double) XCLOCKS_PER_SEC))) / 1000000.0,
-       ((8.0 * (double) cipher_descriptor[x].block_length) *
-    ((double) y2 / ((double) t2 / (double) XCLOCKS_PER_SEC))) /
-       1000000.0);
-
-#undef DO256
-#undef DO128
-#undef DO64
-#undef DO32
-#undef DO16
-#undef DO8
-#undef DO4
-#undef DO2
-#undef DO1
-  }
-}
-
-#ifdef MDH
-void
-dh_tests (void)
-{
-  unsigned char buf[3][4096];
-  unsigned long x, y, z;
-  int     low, high, stat, stat2;
-  dh_key  usera, userb;
-  clock_t t1;
-
-  printf("Testing builting DH parameters...."); fflush(stdout);
-  if ((errnum = dh_test()) != CRYPT_OK) {
-     printf("DH Error: %s\n", error_to_string(errnum));
-     exit(-1);
-  }
-  printf("Passed.\n");
-
-  dh_sizes (&low, &high);
-  printf ("DH Keys from %d to %d supported.\n", low * 8, high * 8);
-
-  /* make up two keys */
-  if ((errnum =
-       dh_make_key (&prng, find_prng ("yarrow"), 96, &usera)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  if ((errnum =
-       dh_make_key (&prng, find_prng ("yarrow"), 96, &userb)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  /* make the shared secret */
-  x = 4096;
-  if ((errnum = dh_shared_secret (&usera, &userb, buf[0], &x)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  y = 4096;
-  if ((errnum = dh_shared_secret (&userb, &usera, buf[1], &y)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  if (y != x) {
-    printf ("DH Shared keys are not same size.\n");
-    exit (-1);
-  }
-  if (memcmp (buf[0], buf[1], x)) {
-    printf ("DH Shared keys not same contents.\n");
-    exit (-1);
-  }
-
-  /* now export userb */
-  y = 4096;
-  if ((errnum = dh_export (buf[1], &y, PK_PUBLIC, &userb)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  dh_free (&userb);
-
-  /* import and make the shared secret again */
-  if ((errnum = dh_import (buf[1], y, &userb)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  z = 4096;
-  if ((errnum = dh_shared_secret (&usera, &userb, buf[2], &z)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  printf ("DH routines: ");
-  if (z != x) {
-    printf ("failed.  Size don't match?\n");
-    exit (-1);
-  }
-  if (memcmp (buf[0], buf[2], x)) {
-    printf ("Failed.  Content didn't match.\n");
-    exit (-1);
-  }
-  printf ("Passed\n");
-  dh_free (&usera);
-  dh_free (&userb);
-
-/* time stuff */
-  {
-    static int sizes[] = { 96, 128, 160, 192, 224, 256, 320, 384, 512 };
-    int     ii, tt;
-
-    for (ii = 0; ii < (int) (sizeof (sizes) / sizeof (sizes[0])); ii++) {
-      t1 = XCLOCK ();
-      for (tt = 0; tt < 25; tt++) {
-    dh_make_key (&prng, find_prng ("yarrow"), sizes[ii], &usera);
-    dh_free (&usera);
-      }
-      t1 = XCLOCK () - t1;
-      printf ("Make dh-%d key took %f msec\n", sizes[ii] * 8,
-          1000.0 * (((double) t1 / 25.0) / (double) XCLOCKS_PER_SEC));
-    }
-  }
-
-/* test encrypt_key */
-  dh_make_key (&prng, find_prng ("yarrow"), 128, &usera);
-  for (x = 0; x < 16; x++)
-    buf[0][x] = x;
-  y = sizeof (buf[1]);
-  if ((errnum =
-       dh_encrypt_key (buf[0], 16, buf[1], &y, &prng, find_prng ("yarrow"),
-               find_hash ("md5"), &usera)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  zeromem (buf[0], sizeof (buf[0]));
-  x = sizeof (buf[0]);
-  if ((errnum = dh_decrypt_key (buf[1], y, buf[0], &x, &usera)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  printf ("DH en/de crypt key routines: ");
-  if (x != 16) {
-    printf ("Failed (length)\n");
-    exit (-1);
-  }
-  for (x = 0; x < 16; x++)
-    if (buf[0][x] != x) {
-      printf ("Failed (contents)\n");
-      exit (-1);
-    }
-  printf ("Passed (size %lu)\n", y);
-
-/* test sign_hash */
-  for (x = 0; x < 16; x++)
-    buf[0][x] = x;
-  x = sizeof (buf[1]);
-  if ((errnum =
-       dh_sign_hash (buf[0], 16, buf[1], &x, &prng, find_prng ("yarrow"),
-             &usera)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  if ((errnum = dh_verify_hash (buf[1], x, buf[0], 16, &stat, &usera)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  buf[0][0] ^= 1;
-  if ((errnum = dh_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  printf ("dh_sign/verify_hash: %s (%d,%d), %lu\n",
-      ((stat == 1)
-       && (stat2 == 0)) ? "passed" : "failed", stat, stat2, x);
-  dh_free (&usera);
-}
-#else
-void
-dh_tests (void)
-{
-  printf ("MDH not compiled in\n");
-}
-#endif
-
-int     callback_x = 0;
-void
-callback (void)
-{
-  printf ("%c\x08", "-\\|/"[++callback_x & 3]);
-#ifndef SONY_PS2
-  fflush (stdout);
-#endif
-}
-
-void
-rng_tests (void)
-{
-  unsigned char buf[16];
-  clock_t t1;
-  int     x, y;
-
-  printf ("RNG tests\n");
-  t1 = XCLOCK ();
-  x = rng_get_bytes (buf, sizeof (buf), &callback);
-  t1 = XCLOCK () - t1;
-  printf ("  %f bytes per second...",
-      (double) x / ((double) t1 / (double) XCLOCKS_PER_SEC));
-  printf ("read %d bytes.\n  ", x);
-  for (y = 0; y < x; y++)
-    printf ("%02x ", buf[y]);
-  printf ("\n");
-
-#ifdef YARROW
-  if ((errnum =
-       rng_make_prng (128, find_prng ("yarrow"), &prng,
-              &callback)) != CRYPT_OK) {
-    printf (" starting yarrow error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-#endif
-}
-
-#ifdef MECC
-void
-ecc_tests (void)
-{
-  unsigned char buf[4][4096];
-  unsigned long x, y, z;
-  int     stat, stat2, low, high;
-  ecc_key usera, userb;
-  clock_t t1;
-
-  if ((errnum = ecc_test ()) != CRYPT_OK) {
-    printf ("ecc Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  ecc_sizes (&low, &high);
-  printf ("ecc Keys from %d to %d supported.\n", low * 8, high * 8);
-
-  /* make up two keys */
-  if ((errnum =
-       ecc_make_key (&prng, find_prng ("yarrow"), 24, &usera)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  if ((errnum =
-       ecc_make_key (&prng, find_prng ("yarrow"), 24, &userb)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  /* make the shared secret */
-  x = 4096;
-  if ((errnum = ecc_shared_secret (&usera, &userb, buf[0], &x)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  y = 4096;
-  if ((errnum = ecc_shared_secret (&userb, &usera, buf[1], &y)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  if (y != x) {
-    printf ("ecc Shared keys are not same size.\n");
-    exit (-1);
-  }
-
-  if (memcmp (buf[0], buf[1], x)) {
-    printf ("ecc Shared keys not same contents.\n");
-    exit (-1);
-  }
-
-  /* now export userb */
-  y = 4096;
-  if ((errnum = ecc_export (buf[1], &y, PK_PUBLIC, &userb)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  ecc_free (&userb);
-  printf ("ECC-192 export took %ld bytes\n", y);
-
-  /* import and make the shared secret again */
-  if ((errnum = ecc_import (buf[1], y, &userb)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  z = 4096;
-  if ((errnum = ecc_shared_secret (&usera, &userb, buf[2], &z)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-
-  printf ("ecc routines: ");
-  if (z != x) {
-    printf ("failed.  Size don't match?\n");
-    exit (-1);
-  }
-  if (memcmp (buf[0], buf[2], x)) {
-    printf ("Failed.  Content didn't match.\n");
-    exit (-1);
-  }
-  printf ("Passed\n");
-  ecc_free (&usera);
-  ecc_free (&userb);
-
-/* time stuff */
-  {
-    static int sizes[] = { 20, 24, 28, 32, 48, 65 };
-    int     ii, tt;
-
-    for (ii = 0; ii < (int) (sizeof (sizes) / sizeof (sizes[0])); ii++) {
-      t1 = XCLOCK ();
-      for (tt = 0; tt < 10; tt++) {
-    if ((errnum =
-         ecc_make_key (&prng, find_prng ("yarrow"), sizes[ii],
-               &usera)) != CRYPT_OK) {
-      printf ("Error: %s\n", error_to_string (errnum));
-      exit (-1);
-    }
-    ecc_free (&usera);
-      }
-      t1 = XCLOCK () - t1;
-      printf ("Make ECC-%d key took %f msec\n", sizes[ii] * 8,
-          1000.0 * (((double) t1 / 10.0) / (double) XCLOCKS_PER_SEC));
-    }
-  }
-
-/* test encrypt_key */
-  ecc_make_key (&prng, find_prng ("yarrow"), 20, &usera);
-  for (x = 0; x < 32; x++)
-    buf[0][x] = x;
-  y = sizeof (buf[1]);
-  if ((errnum =
-       ecc_encrypt_key (buf[0], 32, buf[1], &y, &prng, find_prng ("yarrow"),
-            find_hash ("sha256"), &usera)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  zeromem (buf[0], sizeof (buf[0]));
-  x = sizeof (buf[0]);
-  if ((errnum = ecc_decrypt_key (buf[1], y, buf[0], &x, &usera)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  printf ("ECC en/de crypt key routines: ");
-  if (x != 32) {
-    printf ("Failed (length)\n");
-    exit (-1);
-  }
-  for (x = 0; x < 32; x++)
-    if (buf[0][x] != x) {
-      printf ("Failed (contents)\n");
-      exit (-1);
-    }
-  printf ("Passed (size: %lu)\n", y);
-/* test sign_hash */
-  for (x = 0; x < 16; x++)
-    buf[0][x] = x;
-  x = sizeof (buf[1]);
-  if ((errnum =
-       ecc_sign_hash (buf[0], 16, buf[1], &x, &prng, find_prng ("yarrow"),
-              &usera)) != CRYPT_OK) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  printf("Signature size: %lu\n", x);
-  if (ecc_verify_hash (buf[1], x, buf[0], 16, &stat, &usera)) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  buf[0][0] ^= 1;
-  if (ecc_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera)) {
-    printf ("Error: %s\n", error_to_string (errnum));
-    exit (-1);
-  }
-  printf ("ecc_sign/verify_hash: %s (%d,%d)\n",
-      ((stat == 1) && (stat2 == 0)) ? "passed" : "failed", stat, stat2);
-  ecc_free (&usera);
-}
-#else
-void
-ecc_tests (void)
-{
-  printf ("MECC not compiled in\n");
-}
-#endif
-
-#ifdef MPI
-void
-test_prime (void)
-{
-  char buf[1024];
-  mp_int  a;
-  int     x;
-
-  /* make a 1024 bit prime */
-  mp_init (&a);
-  rand_prime (&a, 128*8, &prng, find_prng ("yarrow"));
-
-  /* dump it */
-  mp_todecimal (&a, buf);
-  printf ("1024-bit prime:\n");
-  for (x = 0; x < (int) strlen (buf);) {
-    printf ("%c", buf[x]);
-    if (!(++x % 60))
-      printf ("\\ \n");
-  }
-  printf ("\n\n");
-
-  mp_clear (&a);
-}
-#else
-void
-test_prime (void)
-{
-  printf ("MPI not compiled in\n");
-}
-#endif
-
-void
-register_all_algs (void)
-{
-#ifdef RIJNDAEL
-  register_cipher (&aes_desc);
-#endif
-#ifdef BLOWFISH
-  register_cipher (&blowfish_desc);
-#endif
-#ifdef XTEA
-  register_cipher (&xtea_desc);
-#endif
-#ifdef RC5
-  register_cipher (&rc5_desc);
-#endif
-#ifdef RC6
-  register_cipher (&rc6_desc);
-#endif
-#ifdef SAFERP
-  register_cipher (&saferp_desc);
-#endif
-#ifdef TWOFISH
-  register_cipher (&twofish_desc);
-#endif
-#ifdef SAFER
-  register_cipher (&safer_k64_desc);
-  register_cipher (&safer_sk64_desc);
-  register_cipher (&safer_k128_desc);
-  register_cipher (&safer_sk128_desc);
-#endif
-#ifdef RC2
-  register_cipher (&rc2_desc);
-#endif
-#ifdef DES
-  register_cipher (&des_desc);
-  register_cipher (&des3_desc);
-#endif
-#ifdef CAST5
-  register_cipher (&cast5_desc);
-#endif
-#ifdef NOEKEON
-  register_cipher (&noekeon_desc);
-#endif
-#ifdef SKIPJACK
-  register_cipher (&skipjack_desc);
-#endif
-  register_cipher (&null_desc);
-
-#ifdef TIGER
-  register_hash (&tiger_desc);
-#endif
-#ifdef MD2
-  register_hash (&md2_desc);
-#endif
-#ifdef MD4
-  register_hash (&md4_desc);
-#endif
-#ifdef MD5
-  register_hash (&md5_desc);
-#endif
-#ifdef SHA1
-  register_hash (&sha1_desc);
-#endif
-#ifdef SHA256
-  register_hash (&sha256_desc);
-#endif
-#ifdef SHA224
-  register_hash (&sha224_desc);
-#endif
-#ifdef SHA384
-  register_hash (&sha384_desc);
-#endif
-#ifdef SHA512
-  register_hash (&sha512_desc);
-#endif
-#ifdef RIPEMD128
-  register_hash (&rmd128_desc);
-#endif
-#ifdef RIPEMD160
-  register_hash (&rmd160_desc);
-#endif
-#ifdef WHIRLPOOL
-  register_hash (&whirlpool_desc);
-#endif
-
-#ifdef YARROW
-  register_prng (&yarrow_desc);
-#endif
-#ifdef SPRNG
-  register_prng (&sprng_desc);
-#endif
-}
-
-void
-test_errs (void)
-{
-#define ERR(x)  printf("%25s => %s\n", #x, error_to_string(x));
-
-  ERR (CRYPT_OK);
-  ERR (CRYPT_ERROR);
-
-  ERR (CRYPT_INVALID_KEYSIZE);
-  ERR (CRYPT_INVALID_ROUNDS);
-  ERR (CRYPT_FAIL_TESTVECTOR);
-
-  ERR (CRYPT_BUFFER_OVERFLOW);
-  ERR (CRYPT_INVALID_PACKET);
-
-  ERR (CRYPT_INVALID_PRNGSIZE);
-  ERR (CRYPT_ERROR_READPRNG);
-
-  ERR (CRYPT_INVALID_CIPHER);
-  ERR (CRYPT_INVALID_HASH);
-  ERR (CRYPT_INVALID_PRNG);
-
-  ERR (CRYPT_MEM);
-
-  ERR (CRYPT_PK_TYPE_MISMATCH);
-  ERR (CRYPT_PK_NOT_PRIVATE);
-
-  ERR (CRYPT_INVALID_ARG);
-  ERR (CRYPT_FILE_NOTFOUND);
-
-  ERR (CRYPT_PK_INVALID_TYPE);
-  ERR (CRYPT_PK_INVALID_SYSTEM);
-  ERR (CRYPT_PK_DUP);
-  ERR (CRYPT_PK_NOT_FOUND);
-  ERR (CRYPT_PK_INVALID_SIZE);
-
-  ERR (CRYPT_INVALID_PRIME_SIZE);
-}
-
-
-void dsa_tests(void)
-{
-   unsigned char msg[16], out[1024], out2[1024];
-   unsigned long x, y;
-   int err, stat1, stat2;
-   dsa_key key, key2;
-
-   /* make a random key */
-   if ((err = dsa_make_key(&prng, find_prng("yarrow"), 20, 128, &key)) != CRYPT_OK) {
-      printf("Error making DSA key: %s\n", error_to_string(err));
-      exit(-1);
-   }
-   printf("DSA Key Made\n");
-
-   /* verify it */
-   if ((err = dsa_verify_key(&key, &stat1)) != CRYPT_OK) {
-      printf("Error verifying DSA key: %s\n", error_to_string(err));
-      exit(-1);
-   }
-   printf("DSA key verification: %s\n", stat1 == 1 ? "passed" : "failed");
-   if (stat1 == 0) exit(-1);     
-
-   /* sign the message */
-   x = sizeof(out);
-   if ((err = dsa_sign_hash(msg, sizeof(msg), out, &x, &prng, find_prng("yarrow"), &key)) != CRYPT_OK) {
-      printf("Error signing with DSA key: %s\n", error_to_string(err));
-      exit(-1);
-   }
-   printf("DSA 160/1024 signature is %lu bytes long\n", x);
-
-   /* verify it once */
-   if ((err = dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key)) != CRYPT_OK) {
-      printf("Error verifying with DSA key 1: %s\n", error_to_string(err));
-      exit(-1);
-   }
-
-   /* Modify and verify again */
-   msg[0] ^= 1;
-   if ((err = dsa_verify_hash(out, x, msg, sizeof(msg), &stat2, &key)) != CRYPT_OK) {
-      printf("Error verifying with DSA key 2: %s\n", error_to_string(err));
-      exit(-1);
-   }
-   msg[0] ^= 1;
-   printf("DSA Verification: %d, %d, %s\n", stat1, stat2, (stat1 == 1 && stat2 == 0) ? "passed" : "failed");
-   if (!(stat1 == 1 && stat2 == 0)) exit(-1);
-
-   /* test exporting it */
-   x = sizeof(out2);
-   if ((err = dsa_export(out2, &x, PK_PRIVATE, &key)) != CRYPT_OK) {
-      printf("Error export PK_PRIVATE DSA key: %s\n", error_to_string(err));
-      exit(-1);
-   }
-   printf("Exported PK_PRIVATE DSA key in %lu bytes\n", x);
-   if ((err = dsa_import(out2, x, &key2)) != CRYPT_OK) {
-      printf("Error importing PK_PRIVATE DSA key: %s\n", error_to_string(err));
-      exit(-1);
-   }
-   /* verify a signature with it */
-   if ((err = dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2)) != CRYPT_OK) {
-      printf("Error verifying with DSA key 3: %s\n", error_to_string(err));
-      exit(-1);
-   }
-   printf("PRIVATE Import Test: %s\n", stat1 == 1 ? "passed" : "failed");
-   if (stat1 == 0) exit(-1);
-   dsa_free(&key2);
-
-   /* export as public now */
-   x = sizeof(out2);
-   if ((err = dsa_export(out2, &x, PK_PUBLIC, &key)) != CRYPT_OK) {
-      printf("Error export PK_PUBLIC DSA key: %s\n", error_to_string(err));
-      exit(-1);
-   }
-   printf("Exported PK_PUBLIC DSA key in %lu bytes\n", x);
-   if ((err = dsa_import(out2, x, &key2)) != CRYPT_OK) {
-      printf("Error importing PK_PUBLIC DSA key: %s\n", error_to_string(err));
-      exit(-1);
-   }
-   /* verify a signature with it */
-   if ((err = dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2)) != CRYPT_OK) {
-      printf("Error verifying with DSA key 4: %s\n", error_to_string(err));
-      exit(-1);
-   }
-   printf("PUBLIC Import Test: %s\n", stat1 == 1 ? "passed" : "failed");
-   if (stat1 == 0) exit(-1);
-
-   dsa_free(&key2);
-   dsa_free(&key);
-}
-
-#ifdef PKCS_1
-void pkcs1_test(void)
-{
-   unsigned char buf[3][128];
-   int err, res1, res2, res3, prng_idx, hash_idx;
-   unsigned long x, y, l1, l2, l3, i1, i2;
-
-   /* get hash/prng  */
-   hash_idx = find_hash("sha1");
-   prng_idx = find_prng("yarrow");
-
-   /* do many tests */
-   for (x = 0; x < 10000; x++) {
-      zeromem(buf, sizeof(buf));
-
-      /* make a dummy message (of random length) */
-      l3 = (rand() & 31) + 8;
-      for (y = 0; y < l3; y++) buf[0][y] = rand() & 255;
-
-      /* encode it */
-      l1 = sizeof(buf[1]);
-      if ((err = pkcs_1_oaep_encode(buf[0], l3, NULL, 0, 1024, hash_idx, prng_idx, &prng, buf[1], &l1)) != CRYPT_OK) {
-         printf("OAEP encode: %s\n", error_to_string(err));
-         exit(-1);
-      }
-
-      /* decode it */
-      l2 = sizeof(buf[2]);
-      if ((err = pkcs_1_oaep_decode(buf[1], l1, NULL, 0, 1024, hash_idx, buf[2], &l2, &res1)) != CRYPT_OK) {
-         printf("OAEP decode: %s\n", error_to_string(err));
-         exit(-1);
-      }
-
-      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]);
-         }
-         printf("\nRESULT:\n");
-         for (x = 0; x < l2; x++) {
-             printf("%02x ", buf[2][x]);
-         }
-         printf("\n\n");
-         exit(-1);
-      }
-
-      /* test PSS */
-      l1 = sizeof(buf[1]);
-      if ((err = pkcs_1_pss_encode(buf[0], l3, l3>>2, hash_idx, prng_idx, &prng, 1024, buf[1], &l1)) != CRYPT_OK) {
-         printf("PSS encode: %s\n", error_to_string(err));
-         exit(-1); 
-      }
-      
-      if ((err = pkcs_1_pss_decode(buf[0], l3, buf[1], l1, l3>>2, hash_idx, 1024, &res1)) != CRYPT_OK) {
-         printf("PSS decode1: %s\n", error_to_string(err));
-         exit(-1); 
-      }
-      
-      buf[0][i1 = abs(rand()) % l3] ^= 1;
-      if ((err = pkcs_1_pss_decode(buf[0], l3, buf[1], l1, l3>>2, hash_idx, 1024, &res2)) != CRYPT_OK) {
-         printf("PSS decode2: %s\n", error_to_string(err));
-         exit(-1); 
-      }
-
-      buf[0][i1] ^= 1;
-      buf[1][i2 = abs(rand()) % l1] ^= 1;
-      if ((err = pkcs_1_pss_decode(buf[0], l3, buf[1], l1, l3>>2, hash_idx, 1024, &res3)) != CRYPT_OK) {
-         printf("PSS decode3: %s\n", error_to_string(err));
-         exit(-1); 
-      }
-
-      if (!(res1 == 1 && res2 == 0 && res3 == 0)) {
-         printf("PSS failed: %d, %d, %d, %lu\n", res1, res2, res3, l3);
-         exit(-1);
-      }
-   }
-   printf("PKCS #1: Passed\n");
-}
-
-#endif /* PKCS_1 */
-
-int
-main (void)
-{
-#ifdef SONY_PS2
-  TIMER_Init ();
-#endif
-  srand(time(NULL));
-
-  register_all_algs ();
-   
-  if ((errnum = yarrow_start (&prng)) != CRYPT_OK) {
-    printf ("yarrow_start: %s\n", error_to_string (errnum));
-  }
-  if ((errnum = yarrow_add_entropy ((unsigned char *)"hello", 5, &prng)) != CRYPT_OK) {
-    printf ("yarrow_add_entropy: %s\n", error_to_string (errnum));
-  }
-  if ((errnum = yarrow_ready (&prng)) != CRYPT_OK) {
-    printf ("yarrow_ready: %s\n", error_to_string (errnum));
-  }
-
-  printf (crypt_build_settings);
-  test_errs ();
-
-#ifdef HMAC
-  printf ("HMAC: %s\n", hmac_test () == CRYPT_OK ? "passed" : "failed");
-  if (hmac_test() != CRYPT_OK) exit(EXIT_FAILURE);
-#endif
-
-#ifdef OMAC
-  printf ("OMAC: %s\n", omac_test () == CRYPT_OK ? "passed" : "failed");
-  if (omac_test() != CRYPT_OK) exit(EXIT_FAILURE);
-#endif
-
-#ifdef PMAC
-  printf ("PMAC: %s\n", pmac_test () == CRYPT_OK ? "passed" : "failed");
-  if (pmac_test() != CRYPT_OK) exit(EXIT_FAILURE);
-#endif
-
-#ifdef EAX_MODE
-  printf ("EAX : %s\n", eax_test () == CRYPT_OK ? "passed" : "failed");
-  if (eax_test() != CRYPT_OK) exit(EXIT_FAILURE);
-#endif
-
-#ifdef OCB_MODE
-  printf ("OCB : %s\n", ocb_test () == CRYPT_OK ? "passed" : "failed");
-  if (ocb_test() != CRYPT_OK) exit(EXIT_FAILURE);
-#endif
-
-  store_tests ();
-  cipher_tests ();
-  hash_tests ();
-
-#ifdef PKCS_1
-  pkcs1_test();
-#endif
-
-  ecb_tests ();
-  cbc_tests ();
-  ctr_tests ();
-  ofb_tests ();
-  cfb_tests ();
-
-  rng_tests ();
-  test_prime();
-
-  dsa_tests();
-  rsa_test ();
-  pad_test ();
-  ecc_tests ();
-  dh_tests ();
-
-  base64_test ();
-
-  time_ecb ();
-  time_hash ();
-
-#ifdef SONY_PS2
-  TIMER_Shutdown ();
-#endif
-
-  return 0;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/.ccmalloc	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,356 @@
+                %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+                %%%% generic configuration file for %%%%
+                %%%%  the ccmalloc memory profiler  %%%%
+                %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    
+    %-----------------------------------------------------------------%
+    % COPY THIS FILE TO '.ccmalloc' in your project or home directory %
+    %-----------------------------------------------------------------%
+
+##############################################################################
+## (C) 1997-2003 Armin Biere, 1998 Johannes Keukelaar
+## $Id: ccmalloc.cfg,v 1.6 2003/02/03 08:03:54 biere Exp $
+##############################################################################
+
+%%% '%' and '#' are comments !!!!!!!
+
+% This file must be called '.ccmalloc' and is searched for in the
+% current directory and in the home directory of the user. If it
+% does not exist then the default values mentioned below are used.
+
+% It is also the only available user manual yet ;-) So here is a reading
+% hint. First have a look at the short one line descriptions of each option
+% ...
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% with 'file' the executable is specified [a.out]
+% ----------------------------------------------------------------------
+% This should not be necessary for Linux and Solaris because the proc
+% file system can be used to find argv[0].
+%
+% (the rest of this comment only applies to other OS)
+%
+% For other OS you should use this option unless the executable is
+% in the current directory or its name is 'a.out'.
+%
+% If you do not specify this then ccmalloc tries to find an executable
+% in the current directory that matches the running program starting
+% with 'a.out'. For this process it must call 'nm' on each executable
+% file in the directory which may be time consuming. With this option
+% you can speed up this process.
+%
+% You can also specify absolute or relative path names. This is 
+% necessary if you do not start your program from the current directory.
+% But you can also simply link or name your program to 'a.out'.
+
+%file FILE
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'log' specify the logfile [stderr]
+% ----------------------------------------------------------------------
+% The default is to use stderr. The argument to 'log' is the name of
+% the file you want to write to. It can also be 'stdout' or '-' which 
+% sets stdout as logfile. If the logfile is stdout or stderr and is
+% connected to a terminal then the output is slightly different.
+%
+% For big programs the logfile can be really big. To reduce the size
+% you can use a small chain length (see 'chain-length' below). The other
+% possibility is to use compressed logfiles. This can be done by
+% specifying a logfile name with  a '.gz' (or a '.Z') suffix. This means
+% that gnuzip (resp. compress) is used to compress the output.
+
+%log FILE
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'logpid' specify the logfile
+% ----------------------------------------------------------------------
+% Can be used alternatively to the 'log' command if you want to use
+% ccmalloc for debugging parallel applications where several copies of
+% the program you are debugging must be run simoultaneously. In this
+% case you can not use 'log' because you do not want to write to the same
+% log file. Using 'logpid' uses a file name ending with the <pid> of
+% the process which means the name is unique even if several copies of
+% your program are run simoultaneously.
+%
+% If you use the compressing suffixes then the <pid> is inserted before
+% the suffix (e.g. 'logpid ccmalloc.log.gz' uses 'ccmalloc.log.<pid>.gz'
+% as the name for the log file).
+
+%logpid FILE
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'dont-log-chain' skip info about certain chains []
+% ----------------------------------------------------------------------
+% This command may be repeated any number of times. The argument to this
+% command is a comma-separated list of function-or-file-and-line
+% specifications. Garbage allocated from a callchain that contains this
+% subchain anywhere will _not_ be logged.
+%
+% The ';'-separated list should not contain any spaces. E.g. not:
+%
+%    main ; foo ; bar
+%
+% but:
+%
+%     main;foo;bar
+%
+% A function-or-file-and-line specification is a string followed by an
+% optional colon and number, for example: main or main:14 or main.c or
+% main.c:15. Note that the string is compared with both the function and the
+% file name, if available. If main.c happens to be a function name, that
+% will cause a match (for that string at least).  Not specifying a line
+% number will match any line number. If line number information is not
+% available, anything will match!  Not specifying a name (e.g. ;;;) will
+% match an unknown function name.  Not giving any parameters at all, will
+% match a chain containing at least one unknown function.
+%
+% Note that if you say 'dont-log-chain wrapper.c' nothing will be logged.
+
+%dont-log-chain
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'only-log-chain' skip info about other chains []
+% ----------------------------------------------------------------------
+% The obvious counterpart to dont-log-chain. In this case, only matching
+% chains will be reported. Non-matching chains will not be reported.
+% Can be repeated any number of times; if the chain matches any of the
+% instances, it will be reported.
+
+%only-log-chain
+
+########################################################################
+#                                                                      #
+# This is the 'flag' section                                           #
+#                                                                      #
+#    'set FLAG' is the same as 'set FLAG 1'                            #
+#                                                                      #
+# The default values are those set below.  If 'silent' is disabled     #
+# then you will find the banner in the log file (or it is listed on    #
+# stdout or stderr). The banner describes the current settings of all  #
+# these flags.                                                         #
+#                                                                      #
+########################################################################
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% with 'only-count' ccmalloc only counts garbage - no call chains [0]
+% ----------------------------------------------------------------------
+% If only-count is set to one then only one additional pointer for
+% each allocated data is used and no call chain is generated. This is
+% the fasted and most space efficient mode ccmalloc can operate
+% in. In this mode you get at least the size of garbage produced.
+%
+% Note that 'check-free-space' does not work at all with 'only-count'
+% set and over writes ('check-overwrites') are only checked when
+% calling free.
+
+%set only-count 0
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'load-dynlibs' load dynamic linked libraries into gdb [0]
+% ----------------------------------------------------------------------
+% If your program is linked with dynamic libraries, function and file
+% name information is not available for addresses in those libraries,
+% unless you set 'load-dynlibs' to 1.
+
+%set load-dynlibs 0
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'keep-deallocated-data' does not recycle deallocated data [0]
+% ----------------------------------------------------------------------
+% If you enable keep-deallocated-data then all data deallocated with
+% 'free' (or 'delete' in C++) is not given back to the free store
+% but stays associated with the call chain of its allocation. This is
+% very useful if your program does multiple deallocation of the
+% same data.
+
+%set keep-deallocated-data 0
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'check-overwrites' detect overwrites [0]
+% ----------------------------------------------------------------------
+% If you want to detect 'off by n bytes' errors you should set
+% 'checking-overwrites' to n/4 (on 32-Bit machines).
+%
+% ccmalloc inserts a boundary above allocated data. This boundary
+% consists of 'check-overwrites' words. If your program writes to
+% this area then ccmalloc can detect this (see also check-start
+% and check-interval). 'ccmalloc' also does checking for overwrites
+% at non word boundaries (e.g. strcpy(malloc(strlen("hello")),"hello");)
+
+set check-overwrites 1
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'check-underwrites' detect underwrites [0]
+% ----------------------------------------------------------------------
+% same with writes below allocated data. You do not have to set this
+% option if you only want detect 'off (below) by one' errors because
+% ccmalloc keeps a magic value just before the user data.
+
+set check-underwrites 1
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'check-free-space' can be used to find dangling pointers. [0]
+% ----------------------------------------------------------------------
+% A very serious type of bug is to write on data that has already been
+% freed. If this happens the free space management of malloc is in
+% trouble and you will perhaps encounter non deterministic behaviour of
+% your program. To test this first enable 'keep-deallocated-data' and
+% restart your program. If the problem goes away and ccmalloc does not
+% report anything then you should *also* enable 'check-free-space'. Now
+% ccmalloc checks already deallocated data for corruption.
+%
+% Note that to perform this check 'keep-deallocated-data' also must
+% be enabled and 'only-count' disabled.
+
+set check-free-space 1
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'check-interval' can be used to speed up checks [0]
+% ----------------------------------------------------------------------
+% If check-overwrite, check-underwrites or check-free-space is set then
+% the default is to do 'write checks' when data is deallocated and
+% to do 'free space checks' when reporting together with
+% 'write checks' for garbage. When you want these checks to be
+% performed more often then you should set 'check-interval' to a
+% positive number. This number is the interval between the number of
+% calls to free or malloc without performing the checks.
+
+%set check-interval 0
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'check-start' can be used to speed up checks [0]
+% ----------------------------------------------------------------------
+% The flag 'check-start' delays the start of checks until the given
+% number of calls to free and malloc have occured. Together with
+% 'check-interval' you can use a binary search to find an aproximation
+% when a corruption occured! If you simply set check-interval to 1 and
+% check-start to 0 then this will slow done your program too much.
+
+%set check-start 0
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'silent' disables banner [0]
+% ----------------------------------------------------------------------
+% If you don't want to see the banner of ccmalloc then set
+% 'silent' to 1 (f.e. when logging to stderr)
+
+%set silent
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'file-info' en/disables file and line number information [1]
+% ----------------------------------------------------------------------
+% If your program was compiled with debugging information (-g) then
+% ccmalloc can generate line number and file info for call chains opening
+% a pipe to gdb. For very big programs this method is slow. In this case
+% you can set 'file-info' to zero and you will only get the function
+% names. For SunOS 4.3.1 'nm' does not 'demangle' C++ identifiers
+% very well. So gdb is called instead but only if 'file-info' is
+% not set to 0.
+
+%set file-info 1
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'continue' if ccmalloc aborts when something weired happened [0]
+% ----------------------------------------------------------------------
+% If the free function of ccmalloc is called with an argument that does
+% not make sense to ccmalloc or that has already been freed then you
+% probably want the program to stop at this point. This is also
+% the default behaviour. But you can force ccmalloc also to ignore
+% this if you set 'continue' to 1. This flag also controls the behaviour
+% of ccmalloc when free space is found to be corrupted or a write
+% boundary has been overwritten.
+
+%set continue 0
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'chain-length' is the length of the maximal call chain [0 = infinite]
+% ----------------------------------------------------------------------
+% You can restrict the length of call chains by setting 'chain-length'
+% to a number greater than zero. If 'chain-length' is zero (the default)
+% then chains are as long as possible (on a non x86 system only call
+% chains with a finite maximal length can be generated). For big
+% programs especially if keep-deallocated-data is enabled this can
+% reduce the size of the log file from over 100MB to several MB!
+
+%set chain-length 0
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'print-addresses' of data [0]
+% ----------------------------------------------------------------------
+% If you want to see the addresses of the allocated data (and
+% deallocated data if keep-deallocated-data is set to 1) set
+% 'print-addresses' to 1.
+
+%set print-addresses 0
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'print-on-one-line' shortens log file [0]
+% ----------------------------------------------------------------------
+% The default is to print function names and file/line number info
+% on separate lines. With 'print-on-one-line' set 1 all are printed
+% on one line.
+
+%set print-on-one-line 0
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'additional-line' enlarges readability [1]
+% ----------------------------------------------------------------------
+% When printing call chains an empty line is printed between to
+% call points. Set 'additional-line' to 0 to disable this feature.
+
+%set additional-line 1
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 'statistics' enables more accurate profiling [0] 
+% ----------------------------------------------------------------------
+% Calculate number of allocations and deallocations and bytes also on
+% a per call chain basis. This uses 4 additional pointers for each
+% call chain.
+
+set statistics 1
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% set order for sorting of call chains [1] [1]
+% ----------------------------------------------------------------------
+% When printing the report to the log file the call chains are sorted by
+% default with respect to the largest accumulated garbage produced by
+% that call chain. This can be changed with setting 'sort-by-wasted'
+% to 0. In this case they are sorted by the number of allocated bytes.
+% If you want the number of allocations (only possible if 'statistics'
+% is enabled) as sorting criteria instead then set 'sort-by-size' to 0.
+
+%set sort-by-wasted 1
+%set sort-by-size 1
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% report library chains [0]
+% ----------------------------------------------------------------------
+% Some external libraries (like libg++) have memory leaks. On some
+% systems even a call to printf produces a leak. ccmalloc tries to
+% detect this (only heuristically!) and with this flag you can control
+% if leaks produced by such library calls are reported.
+%
+% Since version 0.2.1 some similar effect can be achieved by using
+% 'dont-log-chain' with no argument.
+
+%set library-chains 0
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% print debugging information [X] (compile time dependend)
+% ----------------------------------------------------------------------
+
+%set debug X
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% align memory on 8 byte boundary [0] (no effect on SunOS or Solaris)
+% ----------------------------------------------------------------------
+
+%set align-8-byte 0
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% only report allocations which ended up being wasted (i.e don't report
+% allocations which were completely freed properly. ) [1]
+% ----------------------------------------------------------------------
+
+%set only-wasting-alloc 1
--- a/demos/test/cipher_hash_test.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/demos/test/cipher_hash_test.c	Sun Dec 19 11:34:45 2004 +0000
@@ -4,7 +4,10 @@
 
 int cipher_hash_test(void)
 {
-   int x;
+   int           x;
+   unsigned char buf[4096];
+   unsigned long n;
+   prng_state    nprng;
    
    /* test ciphers */
    for (x = 0; cipher_descriptor[x].name != NULL; x++) {
@@ -15,6 +18,24 @@
    for (x = 0; hash_descriptor[x].name != NULL; x++) {
       DO(hash_descriptor[x].test());
    }
+ 
+   /* test prngs (test, import/export */
+   for (x = 0; prng_descriptor[x].name != NULL; x++) {
+      DO(prng_descriptor[x].test());
+      DO(prng_descriptor[x].start(&nprng));
+      DO(prng_descriptor[x].add_entropy((unsigned char *)"helloworld12", 12, &nprng));
+      DO(prng_descriptor[x].ready(&nprng));
+      n = sizeof(buf);
+      DO(prng_descriptor[x].pexport(buf, &n, &nprng));
+      prng_descriptor[x].done(&nprng);
+      DO(prng_descriptor[x].pimport(buf, n, &nprng));
+      DO(prng_descriptor[x].ready(&nprng));
+      if (prng_descriptor[x].read(buf, 100, &nprng) != 100) {
+         fprintf(stderr, "Error reading from imported PRNG!\n");
+         exit(EXIT_FAILURE);
+      }
+      prng_descriptor[x].done(&nprng);
+   }
    
    return 0;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/der_tests.c	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,82 @@
+#include "test.h"
+
+int der_tests(void)
+{
+   unsigned long x, y, z, zz;
+   unsigned char buf[2][4096];
+   mp_int a, b, c, d, e, f, g;
+
+   DO(mpi_to_ltc_error(mp_init_multi(&a, &b, &c, &d, &e, &f, &g, NULL)));
+   for (zz = 0; zz < 16; zz++) {
+      for (z = 0; z < 1024; z++) {
+         if (yarrow_read(buf[0], z, &test_yarrow) != z) {
+            printf("Failed to read %lu bytes from yarrow\n", z);
+            return 1;
+         }
+         DO(mpi_to_ltc_error(mp_read_unsigned_bin(&a, buf[0], z)));
+         x = sizeof(buf[0]);
+         DO(der_encode_integer(&a, buf[0], &x));
+         y = x;
+         mp_zero(&b);
+         DO(der_decode_integer(buf[0], &y, &b));
+         if (y != x || mp_cmp(&a, &b) != MP_EQ) {
+            printf("%lu: %lu vs %lu\n", z, x, y);
+#ifdef BN_MP_TORADIX_C
+            mp_todecimal(&a, buf[0]);
+            mp_todecimal(&b, buf[1]);
+            printf("a == %s\nb == %s\n", buf[0], buf[1]);
+#endif
+            mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL);
+            return 1;
+         }
+      }
+   }
+   
+
+/* test the multi */
+   mp_set(&a, 1);
+   x = sizeof(buf[0]);
+   DO(der_put_multi_integer(buf[0], &x, &a, NULL));
+   y = x;
+   mp_zero(&a);
+   DO(der_get_multi_integer(buf[0], &y, &a, NULL));   
+   if (x != y || mp_cmp_d(&a, 1)) {
+      printf("%lu, %lu, %d\n", x, y, mp_cmp_d(&a, 1));
+      mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL);
+      return 1;
+   }   
+
+   mp_set(&a, 1);
+   mp_set(&b, 2);
+   x = sizeof(buf[0]);
+   DO(der_put_multi_integer(buf[0], &x, &a, &b, NULL));
+   y = x;
+   mp_zero(&a);
+   mp_zero(&b);
+   DO(der_get_multi_integer(buf[0], &y, &a, &b, NULL));   
+   if (x != y || mp_cmp_d(&a, 1) || mp_cmp_d(&b, 2)) {
+      printf("%lu, %lu, %d, %d\n", x, y, mp_cmp_d(&a, 1), mp_cmp_d(&b, 2));
+      mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL);
+      return 1;
+   }   
+
+   mp_set(&a, 1);
+   mp_set(&b, 2);
+   mp_set(&c, 3);
+   x = sizeof(buf[0]);
+   DO(der_put_multi_integer(buf[0], &x, &a, &b, &c, NULL));
+   y = x;
+   mp_zero(&a);
+   mp_zero(&b);
+   mp_zero(&c);
+   DO(der_get_multi_integer(buf[0], &y, &a, &b, &c, NULL));   
+   if (x != y || mp_cmp_d(&a, 1) || mp_cmp_d(&b, 2) || mp_cmp_d(&c, 3)) {
+      printf("%lu, %lu, %d, %d, %d\n", x, y, mp_cmp_d(&a, 1), mp_cmp_d(&b, 2), mp_cmp_d(&c, 3));
+      mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL);
+      return 1;
+   }   
+
+
+   mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL);
+   return 0;
+}
--- a/demos/test/dh_tests.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/demos/test/dh_tests.c	Sun Dec 19 11:34:45 2004 +0000
@@ -1,5 +1,7 @@
 #include "test.h"
 
+#ifdef MDH
+
 int dh_tests (void)
 {
   unsigned char buf[3][4096];
@@ -10,8 +12,8 @@
   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));
+  DO(dh_make_key (&test_yarrow, find_prng ("yarrow"), 512, &usera));
+  DO(dh_make_key (&test_yarrow, find_prng ("yarrow"), 512, &userb));
 
   /* make the shared secret */
   x = 4096;
@@ -50,7 +52,7 @@
   dh_free (&userb);
 
 /* test encrypt_key */
-  dh_make_key (&test_yarrow, find_prng ("yarrow"), 128, &usera);
+  dh_make_key (&test_yarrow, find_prng ("yarrow"), 512, &usera);
   for (x = 0; x < 16; x++) {
     buf[0][x] = x;
   }
@@ -85,3 +87,13 @@
   dh_free (&usera);
   return 0;
 }
+
+#else
+
+int dh_tests(void)
+{
+   printf("NOP");
+   return 0;
+}
+
+#endif
--- a/demos/test/dsa_test.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/demos/test/dsa_test.c	Sun Dec 19 11:34:45 2004 +0000
@@ -1,10 +1,12 @@
 #include "test.h"
 
+#ifdef MDSA
+
 int dsa_test(void)
 {
    unsigned char msg[16], out[1024], out2[1024];
-   unsigned long x, y;
-   int err, stat1, stat2;
+   unsigned long x;
+   int stat1, stat2;
    dsa_key key, key2;
 
    /* make a random key */
@@ -49,3 +51,13 @@
 
    return 0;
 }
+
+#else
+
+int dsa_test(void)
+{
+  printf("NOP");
+  return 0;
+}
+
+#endif
--- a/demos/test/ecc_test.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/demos/test/ecc_test.c	Sun Dec 19 11:34:45 2004 +0000
@@ -1,5 +1,7 @@
 #include "test.h"
 
+#ifdef MECC
+
 int ecc_tests (void)
 {
   unsigned char buf[4][4096];
@@ -10,8 +12,8 @@
   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));
+  DO(ecc_make_key (&test_yarrow, find_prng ("yarrow"), 65, &usera));
+  DO(ecc_make_key (&test_yarrow, find_prng ("yarrow"), 65, &userb));
 
   /* make the shared secret */
   x = 4096;
@@ -53,7 +55,7 @@
   ecc_free (&userb);
 
 /* test encrypt_key */
-  ecc_make_key (&test_yarrow, find_prng ("yarrow"), 20, &usera);
+  ecc_make_key (&test_yarrow, find_prng ("yarrow"), 65, &usera);
   for (x = 0; x < 32; x++) {
     buf[0][x] = x;
   }
@@ -87,3 +89,13 @@
   ecc_free (&usera);
   return 0;
 }
+
+#else
+
+int ecc_tests(void)
+{
+   printf("NOP");
+   return 0;
+}
+
+#endif
--- a/demos/test/mac_test.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/demos/test/mac_test.c	Sun Dec 19 11:34:45 2004 +0000
@@ -3,10 +3,10 @@
 
 int mac_test(void)
 {
-   DO(hmac_test());
-   DO(pmac_test());
-   DO(omac_test());
-   DO(eax_test());
-   DO(ocb_test());
+   DO(hmac_test()); 
+   DO(pmac_test()); 
+   DO(omac_test()); 
+   DO(eax_test());  
+   DO(ocb_test());  
    return 0;
 }
--- a/demos/test/makefile	Tue Jun 15 14:07:21 2004 +0000
+++ b/demos/test/makefile	Sun Dec 19 11:34:45 2004 +0000
@@ -1,13 +1,25 @@
 # make test harness, it is good.
 CFLAGS += -Wall -W -Os -I../../ -I./
 
+# add -g3 for ccmalloc debugging 
+#CFLAGS += -g3
+
+# if you're not debugging
+CFLAGS += -fomit-frame-pointer
+
 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 
+pkcs_1_test.o store_test.o rsa_test.o ecc_test.o dsa_test.o dh_tests.o der_tests.o 
+
+#uncomment this to get heap checking [e.g. memory leaks].  Note 
+#that you *MUST* build libtomcrypt.a with -g3 enabled [and make install it]
+#
+#
+#CCMALLOC = -lccmalloc -ldl
 
 test: $(OBJECTS)
-	$(CC) $(OBJECTS) -ltomcrypt -o test
+	$(CC) $(OBJECTS) /usr/lib/libtomcrypt.a  $(CCMALLOC) -o test
 	
 clean:
-	rm -f test *.o *.obj *.exe *~	
+	rm -rf test *.o *.obj *.exe *~	.libs
--- a/demos/test/makefile.icc	Tue Jun 15 14:07:21 2004 +0000
+++ b/demos/test/makefile.icc	Sun Dec 19 11:34:45 2004 +0000
@@ -5,7 +5,7 @@
 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 
+pkcs_1_test.o store_test.o rsa_test.o ecc_test.o dsa_test.o dh_tests.o der_tests.o
 
 test: $(OBJECTS)
 	$(CC) $(OBJECTS) -ltomcrypt -o test
--- a/demos/test/makefile.msvc	Tue Jun 15 14:07:21 2004 +0000
+++ b/demos/test/makefile.msvc	Sun Dec 19 11:34:45 2004 +0000
@@ -4,7 +4,7 @@
 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 
+pkcs_1_test.obj store_test.obj rsa_test.obj ecc_test.obj dsa_test.c dh_tests.obj der_tests.obj
 
 
 test.exe: $(OBJECTS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/test/makefile.shared	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,19 @@
+# make test harness, it is good.
+CFLAGS += -Wall -W -Os -I../../ -I./
+
+# if you're not debugging
+CFLAGS += -fomit-frame-pointer
+
+default: test
+
+#if you don't have mpi.o 
+#MPISHARED=-ltommath
+
+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.o dh_tests.o der_tests.o 
+
+test: $(OBJECTS)
+	libtool --mode=link gcc $(CFLAGS) $(OBJECTS) -o test -ltomcrypt $(MPISHARED)
+	
+clean:
+	rm -f test *.o *.obj *.exe *~	
--- a/demos/test/pkcs_1_test.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/demos/test/pkcs_1_test.c	Sun Dec 19 11:34:45 2004 +0000
@@ -1,5 +1,7 @@
 #include "test.h"
 
+#ifdef PKCS_1
+
 int pkcs_1_test(void)
 {
    unsigned char buf[3][128];
@@ -17,7 +19,7 @@
    }   
 
    /* do many tests */
-   for (x = 0; x < 10000; x++) {
+   for (x = 0; x < 100; x++) {
       zeromem(buf, sizeof(buf));
 
       /* make a dummy message (of random length) */
@@ -101,3 +103,14 @@
    }
    return 0;
 }
+
+#else
+
+int pkcs_1_test(void)
+{
+   printf("NOP");
+   return 0;
+}
+
+#endif
+
--- a/demos/test/rsa_test.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/demos/test/rsa_test.c	Sun Dec 19 11:34:45 2004 +0000
@@ -1,11 +1,15 @@
 #include "test.h"
 
+#ifdef MRSA 
+
+#define RSA_MSGSIZE 78
+
 int rsa_test(void)
 {
    unsigned char in[1024], out[1024], tmp[1024];
-   rsa_key       key;
+   rsa_key       key, privKey, pubKey;
    int           hash_idx, prng_idx, stat, stat2;
-   unsigned long len, len2;
+   unsigned long rsa_msgsize, len, len2;
    static unsigned char lparam[] = { 0x01, 0x02, 0x03, 0x04 };
       
    hash_idx = find_hash("sha1");
@@ -15,77 +19,200 @@
       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");
+   /* test PKCS #1 v1.5 */
+   for (rsa_msgsize = 1; rsa_msgsize <= 117; rsa_msgsize++) {
+      /* make a random key/msg */
+      yarrow_read(in, rsa_msgsize, &test_yarrow);
+
+      len  = sizeof(out);
+      len2 = rsa_msgsize;
+
+      /* encrypt */
+      DO(rsa_v15_encrypt_key(in, rsa_msgsize, out, &len, &test_yarrow, prng_idx, &key));
+      DO(rsa_v15_decrypt_key(out, len, tmp, rsa_msgsize, &test_yarrow, prng_idx, &stat, &key));
+      if (stat != 1 || memcmp(tmp, in, rsa_msgsize)) {
+         printf("PKCS #1 v1.5 encrypt/decrypt failure (rsa_msgsize: %lu, stat: %d)\n", rsa_msgsize, stat);
+	 return 1;
+      }
+   }
+   
+   /* signature */
+   len = sizeof(out);
+   DO(rsa_v15_sign_hash(in, 20, out, &len, &test_yarrow, prng_idx, hash_idx, &key));
+   in[1] ^= 1;
+   DO(rsa_v15_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, &stat, &key));
+   in[1] ^= 1;
+   DO(rsa_v15_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, &stat2, &key));
+   if (!(stat == 0 && stat2 == 1)) {
+      printf("PKCS #1 v1.5 sign/verify failure (stat %d, stat2 %d)\n", stat, stat2);
       return 1;
    }
-   if (len2 != 20 || memcmp(tmp, in, 20)) {
-      printf("rsa_decrypt_key mismatch len %lu", len2);
-      return 1;
+   
+   /* encrypt the key (without lparam) */
+   for (rsa_msgsize = 1; rsa_msgsize <= 86; rsa_msgsize++) {
+      /* make a random key/msg */
+      yarrow_read(in, rsa_msgsize, &test_yarrow);
+
+      len  = sizeof(out);
+      len2 = rsa_msgsize;
+   
+      DO(rsa_encrypt_key(in, rsa_msgsize, out, &len, NULL, 0, &test_yarrow, prng_idx, hash_idx, &key));
+      /* change a byte */
+      out[8] ^= 1;
+      DO(rsa_decrypt_key(out, len, tmp, &len2, NULL, 0, &test_yarrow, prng_idx, hash_idx, &stat2, &key));
+      /* change a byte back */
+      out[8] ^= 1;
+      if (len2 != rsa_msgsize) {
+         printf("\nrsa_decrypt_key mismatch len %lu (first decrypt)", len2);
+         return 1;
+      }
+
+      len2 = rsa_msgsize;
+      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 != rsa_msgsize || memcmp(tmp, in, rsa_msgsize)) {
+         unsigned long x;
+         printf("\nrsa_decrypt_key mismatch, len %lu (second decrypt)\n", len2);
+         printf("Original contents: \n"); 
+         for (x = 0; x < rsa_msgsize; ) {
+             printf("%02x ", in[x]);
+             if (!(++x % 16)) {
+                printf("\n");
+             }
+         }
+         printf("\n");
+         printf("Output contents: \n"); 
+         for (x = 0; x < rsa_msgsize; ) {
+             printf("%02x ", out[x]);
+             if (!(++x % 16)) {
+                printf("\n");
+             }
+         }     
+         printf("\n");
+         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;
+   for (rsa_msgsize = 1; rsa_msgsize <= 86; rsa_msgsize++) {
+      len  = sizeof(out);
+      len2 = rsa_msgsize;
+      DO(rsa_encrypt_key(in, rsa_msgsize, out, &len, lparam, sizeof(lparam), &test_yarrow, prng_idx, hash_idx, &key));
+      /* change a byte */
+      out[8] ^= 1;
+      DO(rsa_decrypt_key(out, len, tmp, &len2, lparam, sizeof(lparam), &test_yarrow, prng_idx, hash_idx, &stat2, &key));
+      if (len2 != rsa_msgsize) {
+         printf("\nrsa_decrypt_key mismatch len %lu (first decrypt)", len2);
+         return 1;
+      }
+      /* change a byte back */
+      out[8] ^= 1;
+
+      len2 = rsa_msgsize;
+      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 != rsa_msgsize || memcmp(tmp, in, rsa_msgsize)) {
+         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));
+
+/* export key and import as both private and public */
+   len2 = sizeof(tmp);
+   DO(rsa_export(tmp, &len2, PK_PRIVATE, &key)); 
+   DO(rsa_import(tmp, len2, &privKey)); 
+   len2 = sizeof(tmp);
+   DO(rsa_export(tmp, &len2, PK_PUBLIC, &key));
+   DO(rsa_import(tmp, len2, &pubKey));
+
+   /* verify with original */
    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);
+      printf("rsa_verify_hash (unsalted, origKey) failed, %d, %d", stat, stat2);
+      rsa_free(&key);
+      rsa_free(&pubKey);
+      rsa_free(&privKey);
+      return 1;
+   }
+
+   /* verify with privKey */
+   /* change a byte */
+   in[0] ^= 1;
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 0, &stat, &privKey));
+   /* change a byte */
+   in[0] ^= 1;
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 0, &stat2, &privKey));
+   
+   if (!(stat == 1 && stat2 == 0)) {
+      printf("rsa_verify_hash (unsalted, privKey) failed, %d, %d", stat, stat2);
+      rsa_free(&key);
+      rsa_free(&pubKey);
+      rsa_free(&privKey);
       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));
+   /* verify with pubKey */
+   /* change a byte */
+   in[0] ^= 1;
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 0, &stat, &pubKey));
    /* change a byte */
    in[0] ^= 1;
-   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 8, &stat2, &key));
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 0, &stat2, &pubKey));
+   
+   if (!(stat == 1 && stat2 == 0)) {
+      printf("rsa_verify_hash (unsalted, pubkey) failed, %d, %d", stat, stat2);
+      rsa_free(&key);
+      rsa_free(&pubKey);
+      rsa_free(&privKey);
+      return 1;
+   }
+
+   /* sign a message (salted) now (use privKey to make, pubKey to verify) */
+   len = sizeof(out);
+   DO(rsa_sign_hash(in, 20, out, &len, &test_yarrow, prng_idx, hash_idx, 8, &privKey));
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 8, &stat, &pubKey));
+   /* change a byte */
+   in[0] ^= 1;
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 8, &stat2, &pubKey));
    
    if (!(stat == 1 && stat2 == 0)) {
       printf("rsa_verify_hash (salted) failed, %d, %d", stat, stat2);
+      rsa_free(&key);
+      rsa_free(&pubKey);
+      rsa_free(&privKey);
       return 1;
    }
    
    /* free the key and return */
    rsa_free(&key);
+   rsa_free(&pubKey);
+   rsa_free(&privKey);
    return 0;
 }
+
+#else
+
+int rsa_test(void)
+{
+   printf("NOP");
+   return 0;
+}
+
+#endif
--- a/demos/test/store_test.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/demos/test/store_test.c	Sun Dec 19 11:34:45 2004 +0000
@@ -1,43 +1,44 @@
 #include "test.h"
 
+/* Test store/load macros with offsets */
 int store_test(void)
 {
-  unsigned char buf[8];
-  unsigned long L;
-  ulong64 LL;
+  unsigned char buf[24];
+  unsigned long L, L1;
+  int y;
+  ulong64 LL, LL1;
 
   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;
+  for (y = 0; y < 4; y++) {
+      STORE32L(L, buf + y);
+      LOAD32L(L1, buf + y);
+      if (L1 != L) {
+         fprintf(stderr, "\n32L failed at offset %d\n", y);
+         return 1;
+      }
+      STORE32H(L, buf + y);
+      LOAD32H(L1, buf + y);
+      if (L1 != L) {
+         fprintf(stderr, "\n32H failed at offset %d\n", y);
+         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);
+  for (y = 0; y < 8; y++) {
+      STORE64L(LL, buf + y);
+      LOAD64L(LL1, buf + y);
+      if (LL1 != LL) {
+         fprintf(stderr, "\n64L failed at offset %d\n", y);
+         return 1;
+      }
+      STORE64H(LL, buf + y);
+      LOAD64H(LL1, buf + y);
+      if (LL1 != LL) {
+         fprintf(stderr, "\n64H failed at offset %d\n", y);
+         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;
 }
--- a/demos/test/test.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/demos/test/test.c	Sun Dec 19 11:34:45 2004 +0000
@@ -9,11 +9,13 @@
 {"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             },
+{"der_test",               "e",         "",          der_tests            },
+
+{"pkcs_1_test",            "f",        "e",          pkcs_1_test          },
+{"rsa_test",               "g",        "e",          rsa_test             },
+{"ecc_test",               "h",        "a",          ecc_tests            },
+{"dsa_test",               "i",        "a",          dsa_test             },
+{"dh_test",                "j",        "a",          dh_tests             },
 
 {NULL, NULL, NULL, NULL} 
 };
@@ -31,6 +33,8 @@
 
 void register_algs(void)
 {
+  int err;
+
 #ifdef RIJNDAEL
   register_cipher (&aes_desc);
 #endif
@@ -110,16 +114,30 @@
 #ifdef WHIRLPOOL
   register_hash (&whirlpool_desc);
 #endif
+#ifdef CHC_HASH
+  register_hash(&chc_desc);
+  if ((err = chc_register(register_cipher(&aes_enc_desc))) != CRYPT_OK) {
+     printf("chc_register error: %s\n", error_to_string(err));
+     exit(EXIT_FAILURE);
+  }
+#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);
-   }
+#ifdef YARROW
+   register_prng(&yarrow_desc);
+#endif
+#ifdef FORTUNA
+   register_prng(&fortuna_desc);
+#endif
+#ifdef RC4
+   register_prng(&rc4_desc);
+#endif
+#ifdef SPRNG
+   register_prng(&sprng_desc);
+#endif
+#ifdef SOBER128
+   register_prng(&sober128_desc);
+#endif
 }
 
 /* sort tests based on their requirement/services.  Helps make sure dependencies are tested first */
@@ -153,20 +171,87 @@
       }
    } while (y == 1);
 }
-   
+
+#define STACKBLOCK       8
+#define STACK_EST_USAGE  32768
+
+unsigned char stack_mask[STACKBLOCK];
+unsigned long stack_cur=0;
+
+void stack_masker(void)
+{
+#ifdef STACK_TEST
+   volatile unsigned char M[STACK_EST_USAGE];
+   stack_cur   = 0;
+   for (stack_cur = 0; stack_cur < STACK_EST_USAGE/STACKBLOCK; stack_cur++) {
+       memcpy(M+(stack_cur*STACKBLOCK), stack_mask, STACKBLOCK);
+   }
+#endif
+}
+
+void stack_check(void)
+{
+#ifdef STACK_TEST
+   unsigned char M[STACK_EST_USAGE];
+   stack_cur   = 0;
+#ifdef STACK_DOWN
+   while (memcmp(M+(STACK_EST_USAGE-STACKBLOCK-stack_cur), stack_mask, STACKBLOCK) && 
+#else
+   while (memcmp(M+stack_cur, stack_mask, STACKBLOCK) &&
+#endif
+          stack_cur < (STACK_EST_USAGE - STACKBLOCK)) {
+      ++stack_cur;
+   }
+#endif
+}
+
 int main(void)
 {
+   int x;
+   unsigned char buf[16];
+
+   /* setup stack checker */
+   srand(time(NULL));
+   for (x = 0; x < STACKBLOCK; x++) {
+       stack_mask[x] = rand() & 255;
+   }
+   stack_masker();
+
    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));
+   sprng_read(buf, 16, NULL);
+   DO(yarrow_add_entropy(buf, 16, &test_yarrow));
    DO(yarrow_ready(&test_yarrow));
 
+   // output sizes 
+   printf("Sizes of objects (in bytes)\n");
+   printf("\tsymmetric_key\t=\t%5lu\n", sizeof(symmetric_key));
+   printf("\thash_state\t=\t%5lu\n", sizeof(hash_state));
+   printf("\thmac_state\t=\t%5lu\n", sizeof(hmac_state));
+   printf("\tomac_state\t=\t%5lu\n", sizeof(omac_state));
+   printf("\tpmac_state\t=\t%5lu\n", sizeof(pmac_state));
+   printf("\tocb_state\t=\t%5lu\n", sizeof(ocb_state));
+   printf("\teax_state\t=\t%5lu\n", sizeof(eax_state));
+   printf("\tmp_int\t\t=\t%5lu\n", sizeof(mp_int));
+#ifdef MRSA
+   printf("\trsa_key\t\t=\t%5lu\n", sizeof(rsa_key));
+#endif
+#ifdef MDSA
+   printf("\tdsa_key\t\t=\t%5lu\n", sizeof(dsa_key));
+#endif
+#ifdef MDH
+   printf("\tdh_key\t\t=\t%5lu\n", sizeof(dh_key));
+#endif
+#ifdef MECC
+   printf("\tecc_key\t\t=\t%5lu\n", sizeof(ecc_key));
+#endif
+
+   printf("\n\n");
    // do tests
    for (current_test = 0; tests[current_test].name != NULL; current_test++) {
        printf("[%-20s]: ", tests[current_test].name); fflush(stdout);
--- a/demos/test/test.h	Tue Jun 15 14:07:21 2004 +0000
+++ b/demos/test/test.h	Sun Dec 19 11:34:45 2004 +0000
@@ -3,6 +3,12 @@
 
 #include "mycrypt.h"
 
+/* enable stack testing */
+// #define STACK_TEST
+
+/* stack testing, define this if stack usage goes downwards [e.g. x86] */
+#define STACK_DOWN
+
 typedef struct {
     char *name, *prov, *req;
     int  (*entry)(void);
@@ -10,10 +16,14 @@
 
 extern prng_state test_yarrow;
 
+
+void stack_masker(void);
+void stack_check(void);
+extern unsigned long stack_cur;
+#define stack_chk(x) { stack_check(); if (stack_cur >= 1024) { fprintf(stderr, " Warning: Stack usage of %lu in %s, %s:%d\n", stack_cur, x, __FILE__, __LINE__); } }
+
 void run_cmd(int res, int line, char *file, char *cmd);
-#define DO(x) run_cmd((x), __LINE__, __FILE__, #x)
-
-
+#define DO(x) { stack_masker(); run_cmd((x), __LINE__, __FILE__, #x); stack_chk(#x); }
 
 /* TESTS */
 int cipher_hash_test(void);
@@ -25,5 +35,6 @@
 int ecc_tests(void);
 int dsa_test(void);
 int dh_tests(void);
+int der_tests(void);
 
 #endif
--- a/demos/tv_gen.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/demos/tv_gen.c	Sun Dec 19 11:34:45 2004 +0000
@@ -2,6 +2,8 @@
 
 void reg_algs(void)
 {
+  int err;
+
 #ifdef RIJNDAEL
   register_cipher (&aes_desc);
 #endif
@@ -82,26 +84,45 @@
 #ifdef WHIRLPOOL
   register_hash (&whirlpool_desc);
 #endif
+#ifdef CHC_HASH
+  register_hash(&chc_desc);
+  if ((err = chc_register(register_cipher(&aes_desc))) != CRYPT_OK) {
+     printf("chc_register error: %s\n", error_to_string(err));
+     exit(EXIT_FAILURE);
+  }
+#endif
+
 }
 
 void hash_gen(void)
 {
-   unsigned char md[MAXBLOCKSIZE], buf[MAXBLOCKSIZE*2+2];
+   unsigned char md[MAXBLOCKSIZE], *buf;
    unsigned long outlen, x, y, z;
    FILE *out;
+   int   err;
    
    out = fopen("hash_tv.txt", "w");
+   if (out == NULL) {
+      perror("can't open hash_tv");
+   }
    
    fprintf(out, "Hash Test Vectors:\n\nThese are the hashes of nn bytes '00 01 02 03 .. (nn-1)'\n\n");
    for (x = 0; hash_descriptor[x].name != NULL; x++) {
+      buf = XMALLOC(2 * hash_descriptor[x].blocksize + 1);
+      if (buf == NULL) {
+         perror("can't alloc mem");
+         exit(EXIT_FAILURE);
+      }
       fprintf(out, "Hash: %s\n", hash_descriptor[x].name);
-      
       for (y = 0; y <= (hash_descriptor[x].blocksize * 2); y++) {
          for (z = 0; z < y; z++) {
             buf[z] = (unsigned char)(z & 255);
          }
          outlen = sizeof(md);
-         hash_memory(x, buf, y, md, &outlen);
+         if ((err = hash_memory(x, buf, y, md, &outlen)) != CRYPT_OK) {
+            printf("hash_memory error: %s\n", error_to_string(err));
+            exit(EXIT_FAILURE);
+         }
          fprintf(out, "%3lu: ", y);
          for (z = 0; z < outlen; z++) {
             fprintf(out, "%02X", md[z]);
@@ -109,15 +130,16 @@
          fprintf(out, "\n");
       }
       fprintf(out, "\n");
+      XFREE(buf);
    }
    fclose(out);
 }
 
 void cipher_gen(void)
 {
-   unsigned char key[MAXBLOCKSIZE], pt[MAXBLOCKSIZE];
+   unsigned char *key, pt[MAXBLOCKSIZE];
    unsigned long x, y, z, w;
-   int kl, lastkl;
+   int err, kl, lastkl;
    FILE *out;
    symmetric_key skey;
    
@@ -138,15 +160,27 @@
             case 1: kl = (cipher_descriptor[x].min_key_length + cipher_descriptor[x].max_key_length)/2; break;
             case 2: kl = cipher_descriptor[x].max_key_length; break;
          }
-         cipher_descriptor[x].keysize(&kl);
+         if ((err = cipher_descriptor[x].keysize(&kl)) != CRYPT_OK) {
+            printf("keysize error: %s\n", error_to_string(err));
+            exit(EXIT_FAILURE);
+         }
          if (kl == lastkl) break;
          lastkl = kl;
          fprintf(out, "Key Size: %d bytes\n", kl);
 
+         key = XMALLOC(kl);
+         if (key == NULL) {
+            perror("can't malloc memory");
+            exit(EXIT_FAILURE);
+         }
+
          for (z = 0; (int)z < kl; z++) {
              key[z] = (unsigned char)z;
          }
-         cipher_descriptor[x].setup(key, kl, 0, &skey);
+         if ((err = cipher_descriptor[x].setup(key, kl, 0, &skey)) != CRYPT_OK) {
+            printf("setup error: %s\n", error_to_string(err));
+            exit(EXIT_FAILURE);
+         }
          
          for (z = 0; (int)z < cipher_descriptor[x].block_length; z++) {
             pt[z] = (unsigned char)z;
@@ -163,9 +197,13 @@
              for (z = 0; z < (unsigned long)kl; z++) {
                  key[z] = pt[z % cipher_descriptor[x].block_length];
              }
-             cipher_descriptor[x].setup(key, kl, 0, &skey);
+             if ((err = cipher_descriptor[x].setup(key, kl, 0, &skey)) != CRYPT_OK) {
+                printf("cipher setup2 error: %s\n", error_to_string(err));
+                exit(EXIT_FAILURE);
+             }
          }
          fprintf(out, "\n");
+         XFREE(key);
      }
      fprintf(out, "\n");
   }
@@ -174,8 +212,8 @@
 
 void hmac_gen(void)
 {
-   unsigned char key[MAXBLOCKSIZE], output[MAXBLOCKSIZE], input[MAXBLOCKSIZE*2+2];
-   int x, y, z, kl, err;
+   unsigned char key[MAXBLOCKSIZE], output[MAXBLOCKSIZE], *input;
+   int x, y, z, err;
    FILE *out;
    unsigned long len;
   
@@ -193,6 +231,12 @@
       for (y = 0; y < (int)hash_descriptor[x].hashsize; y++) {
           key[y] = (y&255);
       }
+
+      input = XMALLOC(hash_descriptor[x].blocksize * 2 + 1);
+      if (input == NULL) {
+         perror("Can't malloc memory");
+         exit(EXIT_FAILURE);
+      }
       
       for (y = 0; y <= (int)(hash_descriptor[x].blocksize * 2); y++) {
          for (z = 0; z < y; z++) {
@@ -212,6 +256,7 @@
          /* forward the key */
          memcpy(key, output, hash_descriptor[x].hashsize);
       }
+      XFREE(input);
       fprintf(out, "\n");
    }
    fclose(out);
--- a/demos/x86_prof.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/demos/x86_prof.c	Sun Dec 19 11:34:45 2004 +0000
@@ -45,16 +45,13 @@
    }
 }
 
-
-
-
 /* RDTSC from Scott Duplichan */
 static ulong64 rdtsc (void)
    {
    #if defined __GNUC__
-      #ifdef __i386__
-         ulong64 a;
-         __asm__ __volatile__ ("rdtsc ":"=A" (a));
+      #if defined(__i386__) || defined(__x86_64__)
+         unsigned long long a;
+         __asm__ __volatile__ ("rdtsc\nmovl %%eax,%0\nmovl %%edx,4+%0\n"::"m"(a):"%eax","%edx");
          return a;
       #else /* gcc-IA64 version */
          unsigned long result;
@@ -113,6 +110,7 @@
 
 void reg_algs(void)
 {
+  int err;
 #ifdef RIJNDAEL
   register_cipher (&aes_desc);
 #endif
@@ -193,14 +191,35 @@
 #ifdef WHIRLPOOL
   register_hash (&whirlpool_desc);
 #endif
+#ifdef CHC_HASH
+  register_hash(&chc_desc);
+  if ((err = chc_register(register_cipher(&aes_desc))) != CRYPT_OK) {
+     printf("chc_register error: %s\n", error_to_string(err));
+     exit(EXIT_FAILURE);
+  }
+#endif
 
+
+#ifndef YARROW 
+   #error This demo requires Yarrow.
+#endif
 register_prng(&yarrow_desc);
+#ifdef FORTUNA
+register_prng(&fortuna_desc);
+#endif
+#ifdef RC4
+register_prng(&rc4_desc);
+#endif
+#ifdef SOBER128
+register_prng(&sober128_desc);
+#endif
+
 rng_make_prng(128, find_prng("yarrow"), &prng, NULL);
 }
 
 int time_keysched(void)
 {
-  unsigned long x, i, y1;
+  unsigned long x, y1;
   ulong64 t1, c1;
   symmetric_key skey;
   int kl;
@@ -241,7 +260,7 @@
   symmetric_key skey;
   void    (*func) (const unsigned char *, unsigned char *, symmetric_key *);
   unsigned char key[MAXBLOCKSIZE], pt[MAXBLOCKSIZE];
-
+  int err;
 
   printf ("\n\nECB Time Trials for the Symmetric Ciphers:\n");
   no_results = 0;
@@ -249,6 +268,12 @@
     cipher_descriptor[x].setup (key, cipher_descriptor[x].min_key_length, 0,
                 &skey);
 
+    /* sanity check on cipher */
+    if ((err = cipher_descriptor[x].test()) != CRYPT_OK) {
+       fprintf(stderr, "\n\nERROR: Cipher %s failed self-test %s\n", cipher_descriptor[x].name, error_to_string(err));
+       exit(EXIT_FAILURE);
+    }
+
 #define DO1   func(pt,pt,&skey);
 #define DO2   DO1 DO1
 
@@ -303,13 +328,20 @@
   unsigned long x, y1, len;
   ulong64 t1, t2, c1, c2;
   hash_state md;
-  int    (*func)(hash_state *, const unsigned char *, unsigned long);
+  int    (*func)(hash_state *, const unsigned char *, unsigned long), err;
   unsigned char pt[MAXBLOCKSIZE];
 
 
   printf ("\n\nHASH Time Trials for:\n");
   no_results = 0;
   for (x = 0; hash_descriptor[x].name != NULL; x++) {
+
+    /* sanity check on hash */
+    if ((err = hash_descriptor[x].test()) != CRYPT_OK) {
+       fprintf(stderr, "\n\nERROR: Hash %s failed self-test %s\n", hash_descriptor[x].name, error_to_string(err));
+       exit(EXIT_FAILURE);
+    }
+
     hash_descriptor[x].init(&md);
 
 #define DO1   func(&md,pt,len);
@@ -342,6 +374,349 @@
    return 0;
 }
 
+void time_mult(void)
+{
+   ulong64 t1, t2;
+   unsigned long x, y;
+   mp_int  a, b, c;
+
+   printf("Timing Multiplying:\n");
+   mp_init_multi(&a,&b,&c,NULL);
+   for (x = 128/DIGIT_BIT; x <= 1024/DIGIT_BIT; x += 128/DIGIT_BIT) {
+       mp_rand(&a, x);
+       mp_rand(&b, x);
+
+#define DO1 mp_mul(&a, &b, &c);
+#define DO2 DO1; DO1;
+
+       t2 = -1;
+       for (y = 0; y < TIMES; y++) {
+           t_start();
+           t1 = t_read();
+           DO2;
+           t1 = (t_read() - t1)>>1;
+           if (t1 < t2) t2 = t1;
+       }
+       printf("%3lu digits: %9llu cycles\n", x, t2);
+   }
+   mp_clear_multi(&a,&b,&c,NULL);
+
+#undef DO1
+#undef DO2
+}      
+
+void time_sqr(void)
+{
+   ulong64 t1, t2;
+   unsigned long x, y;
+   mp_int  a, b;
+
+   printf("Timing Squaring:\n");
+   mp_init_multi(&a,&b,NULL);
+   for (x = 128/DIGIT_BIT; x <= 1024/DIGIT_BIT; x += 128/DIGIT_BIT) {
+       mp_rand(&a, x);
+
+#define DO1 mp_sqr(&a, &b);
+#define DO2 DO1; DO1;
+
+       t2 = -1;
+       for (y = 0; y < TIMES; y++) {
+           t_start();
+           t1 = t_read();
+           DO2;
+           t1 = (t_read() - t1)>>1;
+           if (t1 < t2) t2 = t1;
+       }
+       printf("%3lu digits: %9llu cycles\n", x, t2);
+   }
+   mp_clear_multi(&a,&b,NULL);
+
+#undef DO1
+#undef DO2
+}    
+   
+void time_prng(void)
+{
+   ulong64 t1, t2;
+   unsigned char buf[4096];
+   prng_state tprng;
+   unsigned long x, y;
+   int           err;
+
+   printf("Timing PRNGs (cycles/byte output, cycles add_entropy (32 bytes) :\n");
+   for (x = 0; prng_descriptor[x].name != NULL; x++) {
+
+      /* sanity check on prng */
+      if ((err = prng_descriptor[x].test()) != CRYPT_OK) {
+         fprintf(stderr, "\n\nERROR: PRNG %s failed self-test %s\n", prng_descriptor[x].name, error_to_string(err));
+         exit(EXIT_FAILURE);
+      }
+
+      prng_descriptor[x].start(&tprng);
+      zeromem(buf, 256);
+      prng_descriptor[x].add_entropy(buf, 256, &tprng);
+      prng_descriptor[x].ready(&tprng);
+      t2 = -1;
+
+#define DO1 if (prng_descriptor[x].read(buf, 4096, &tprng) != 4096) { printf("\n\nERROR READ != 4096\n\n"); exit(EXIT_FAILURE); }
+#define DO2 DO1 DO1
+      for (y = 0; y < 10000; y++) {
+         t_start();
+         t1 = t_read();
+         DO2;
+         t1 = (t_read() - t1)>>1;
+         if (t1 < t2) t2 = t1;
+      }
+      printf("%20s: %5llu ", prng_descriptor[x].name, t2>>12);
+#undef DO2
+#undef DO1
+
+#define DO1 prng_descriptor[x].start(&tprng); prng_descriptor[x].add_entropy(buf, 32, &tprng); prng_descriptor[x].ready(&tprng); prng_descriptor[x].done(&tprng);
+#define DO2 DO1 DO1
+      for (y = 0; y < 10000; y++) {
+         t_start();
+         t1 = t_read();
+         DO2;
+         t1 = (t_read() - t1)>>1;
+         if (t1 < t2) t2 = t1;
+      }
+      printf("%5llu\n", t2);
+#undef DO2
+#undef DO1
+
+   }
+}
+      
+/* time various RSA operations */
+void time_rsa(void)
+{
+   rsa_key key;
+   ulong64 t1, t2;
+   unsigned char buf[2][4096];
+   unsigned long x, y, z, zzz;
+   int           err, zz;
+
+   for (x = 1024; x <= 2048; x += 512) {
+       t2 = 0;
+       for (y = 0; y < 16; y++) {
+           t_start();
+           t1 = t_read();
+           if ((err = rsa_make_key(&prng, find_prng("yarrow"), x/8, 65537, &key)) != CRYPT_OK) {
+              fprintf(stderr, "\n\nrsa_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
+              exit(EXIT_FAILURE);
+           }
+           t1 = t_read() - t1;
+           t2 += t1;
+
+           if (y < 15) {
+              rsa_free(&key);
+           }
+       }
+       t2 >>= 4;
+       printf("RSA-%lu make_key    took %15llu cycles\n", x, t2);
+
+       t2 = 0;
+       for (y = 0; y < 16; y++) {
+           t_start();
+           t1 = t_read();
+           z = sizeof(buf[1]);
+           if ((err = rsa_encrypt_key(buf[0], 32, buf[1], &z, "testprog", 8, &prng,
+                                      find_prng("yarrow"), find_hash("sha1"),
+                                      &key)) != CRYPT_OK) {
+              fprintf(stderr, "\n\nrsa_encrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
+              exit(EXIT_FAILURE);
+           }
+           t1 = t_read() - t1;
+           t2 += t1;
+       }
+       t2 >>= 4;
+       printf("RSA-%lu encrypt_key took %15llu cycles\n", x, t2);
+
+       t2 = 0;
+       for (y = 0; y < 16; y++) {
+           t_start();
+           t1 = t_read();
+           zzz = sizeof(buf[0]);
+           if ((err = rsa_decrypt_key(buf[1], z, buf[0], &zzz, "testprog", 8, &prng,
+                                      find_prng("yarrow"), find_hash("sha1"), 
+                                      &zz, &key)) != CRYPT_OK) {
+              fprintf(stderr, "\n\nrsa_decrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
+              exit(EXIT_FAILURE);
+           }
+           t1 = t_read() - t1;
+           t2 += t1;
+       }
+       t2 >>= 4;
+       printf("RSA-%lu decrypt_key took %15llu cycles\n", x, t2);
+
+
+       rsa_free(&key);
+  }
+}
+
+/* time various ECC operations */
+void time_ecc(void)
+{
+   ecc_key key;
+   ulong64 t1, t2;
+   unsigned char buf[2][4096];
+   unsigned long i, x, y, z;
+   int           err;
+   static unsigned long sizes[] = {160/8, 256/8, 521/8, 100000};
+
+   for (x = sizes[i=0]; x < 100000; x = sizes[++i]) {
+       t2 = 0;
+       for (y = 0; y < 16; y++) {
+           t_start();
+           t1 = t_read();
+           if ((err = ecc_make_key(&prng, find_prng("yarrow"), x, &key)) != CRYPT_OK) {
+              fprintf(stderr, "\n\necc_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
+              exit(EXIT_FAILURE);
+           }
+           t1 = t_read() - t1;
+           t2 += t1;
+
+           if (y < 15) {
+              ecc_free(&key);
+           }
+       }
+       t2 >>= 4;
+       printf("ECC-%lu make_key    took %15llu cycles\n", x*8, t2);
+
+       t2 = 0;
+       for (y = 0; y < 16; y++) {
+           t_start();
+           t1 = t_read();
+           z = sizeof(buf[1]);
+           if ((err = ecc_encrypt_key(buf[0], 20, buf[1], &z, &prng, find_prng("yarrow"), find_hash("sha1"),
+                                      &key)) != CRYPT_OK) {
+              fprintf(stderr, "\n\necc_encrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
+              exit(EXIT_FAILURE);
+           }
+           t1 = t_read() - t1;
+           t2 += t1;
+       }
+       t2 >>= 4;
+       printf("ECC-%lu encrypt_key took %15llu cycles\n", x*8, t2);
+       ecc_free(&key);
+  }
+}
+
+/* time various DH operations */
+void time_dh(void)
+{
+   dh_key key;
+   ulong64 t1, t2;
+   unsigned char buf[2][4096];
+   unsigned long i, x, y, z;
+   int           err;
+   static unsigned long sizes[] = {768/8, 1024/8, 1536/8, 2048/8, 3072/8, 4096/8, 100000};
+
+   for (x = sizes[i=0]; x < 100000; x = sizes[++i]) {
+       t2 = 0;
+       for (y = 0; y < 16; y++) {
+           t_start();
+           t1 = t_read();
+           if ((err = dh_make_key(&prng, find_prng("yarrow"), x, &key)) != CRYPT_OK) {
+              fprintf(stderr, "\n\ndh_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
+              exit(EXIT_FAILURE);
+           }
+           t1 = t_read() - t1;
+           t2 += t1;
+
+           if (y < 15) {
+              dh_free(&key);
+           }
+       }
+       t2 >>= 4;
+       printf("DH-%4lu make_key    took %15llu cycles\n", x*8, t2);
+
+       t2 = 0;
+       for (y = 0; y < 16; y++) {
+           t_start();
+           t1 = t_read();
+           z = sizeof(buf[1]);
+           if ((err = dh_encrypt_key(buf[0], 20, buf[1], &z, &prng, find_prng("yarrow"), find_hash("sha1"),
+                                      &key)) != CRYPT_OK) {
+              fprintf(stderr, "\n\ndh_encrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
+              exit(EXIT_FAILURE);
+           }
+           t1 = t_read() - t1;
+           t2 += t1;
+       }
+       t2 >>= 4;
+       printf("DH-%4lu encrypt_key took %15llu cycles\n", x*8, t2);
+       dh_free(&key);
+  }
+}
+
+#define MAC_SIZE 32
+void time_macs(void)
+{
+   unsigned char *buf, key[16], tag[16];
+   ulong64 t1, t2;
+   unsigned long x, z;
+   int err, cipher_idx, hash_idx;
+
+   printf("\nMAC Timings (cycles/byte on %dKB blocks):\n", MAC_SIZE);
+
+   buf = XMALLOC(MAC_SIZE*1024);
+   if (buf == NULL) {
+      fprintf(stderr, "\n\nout of heap yo\n\n");
+      exit(EXIT_FAILURE);
+   }
+
+   cipher_idx = find_cipher("aes");
+   hash_idx   = find_hash("md5");
+
+   yarrow_read(buf, MAC_SIZE*1024, &prng);
+   yarrow_read(key, 16, &prng);
+
+   t2 = -1;
+   for (x = 0; x < 10000; x++) {
+        t_start();
+        t1 = t_read();
+        z = 16;
+        if ((err = omac_memory(cipher_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) {
+           fprintf(stderr, "\n\nomac error... %s\n", error_to_string(err));
+           exit(EXIT_FAILURE);
+        }
+        t1 = t_read() - t1;
+        if (t1 < t2) t2 = t1;
+   }
+   printf("OMAC-AES\t\t%9llu\n", t2/(MAC_SIZE*1024));
+
+   t2 = -1;
+   for (x = 0; x < 10000; x++) {
+        t_start();
+        t1 = t_read();
+        z = 16;
+        if ((err = pmac_memory(cipher_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) {
+           fprintf(stderr, "\n\npmac error... %s\n", error_to_string(err));
+           exit(EXIT_FAILURE);
+        }
+        t1 = t_read() - t1;
+        if (t1 < t2) t2 = t1;
+   }
+   printf("PMAC-AES\t\t%9llu\n", t2/(MAC_SIZE*1024));
+
+   t2 = -1;
+   for (x = 0; x < 10000; x++) {
+        t_start();
+        t1 = t_read();
+        z = 16;
+        if ((err = hmac_memory(hash_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) {
+           fprintf(stderr, "\n\nhmac error... %s\n", error_to_string(err));
+           exit(EXIT_FAILURE);
+        }
+        t1 = t_read() - t1;
+        if (t1 < t2) t2 = t1;
+   }
+   printf("HMAC-MD5\t\t%9llu\n", t2/(MAC_SIZE*1024));
+
+   XFREE(buf);
+}
+
 int main(void)
 {
   reg_algs();
@@ -349,9 +724,16 @@
   printf("Timings for ciphers and hashes.  Times are listed as cycles per byte processed.\n\n");
 
 //  init_timer();
+  time_mult();
+  time_sqr();
+  time_rsa();
+  time_dh();
+  time_ecc();
+  time_prng();
   time_cipher();
   time_keysched();
   time_hash();
+  time_macs();
 
   return EXIT_SUCCESS;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/der_decode_integer.c	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,83 @@
+/* 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"
+
+
+/* decodes a DER INTEGER in [in].  You have to tell this function
+ * how many bytes are available [inlen].  It will then attempt to 
+ * read the INTEGER.  If all goes well it stores the number of bytes
+ * read in [inlen] and the number in [num].
+ */
+int der_decode_integer(const unsigned char *in, unsigned long *inlen, mp_int *num)
+{
+   unsigned long tmplen, y, z;
+
+   _ARGCHK(num    != NULL);
+   _ARGCHK(in     != NULL);
+   _ARGCHK(inlen  != NULL);
+
+   /* save copy of max output size */
+   tmplen = *inlen;
+   *inlen = 0;
+
+   /* min DER INTEGER is 0x02 01 00 == 0 */
+   if (tmplen < (1 + 1 + 1)) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* ok expect 0x02 when we AND with 0011 1111 [3F] */
+   if ((*in++ & 0x3F) != 0x02) {
+      return CRYPT_INVALID_PACKET;
+   }
+   ++(*inlen);
+
+   /* now decode the len stuff */
+   z = *in++;
+   ++(*inlen);
+
+   if ((z & 0x80) == 0x00) {
+      /* short form */
+
+      /* will it overflow? */
+      if (*inlen + z > tmplen) {
+         return CRYPT_INVALID_PACKET;
+      }
+     
+      /* no so read it */
+      (*inlen) += z;
+      return mpi_to_ltc_error(mp_read_unsigned_bin(num, (unsigned char *)in, z));
+   } else {
+      /* long form */
+      z &= 0x7F;
+      
+      /* will number of length bytes overflow? (or > 4) */
+      if (((*inlen + z) > tmplen) || (z > 4)) {
+         return CRYPT_INVALID_PACKET;
+      }
+
+      /* now read it in */
+      y = 0;
+      while (z--) {
+         y = ((unsigned long)(*in++)) | (y << 8);
+         ++(*inlen);
+      }
+
+      /* now will reading y bytes overrun? */
+      if ((*inlen + y) > tmplen) {
+         return CRYPT_INVALID_PACKET;
+      }
+
+      /* no so read it */
+      (*inlen) += y;
+      return mpi_to_ltc_error(mp_read_unsigned_bin(num, (unsigned char *)in, y));
+   }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/der_encode_integer.c	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,93 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+/* Exports a positive bignum as DER format (upto 2^32 bytes in size) */
+int der_encode_integer(mp_int *num, unsigned char *out, unsigned long *outlen)
+{  
+   unsigned long tmplen, x, y, z;
+   int           err, leading_zero;
+
+   _ARGCHK(num    != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* find out how big this will be */
+   if ((err = der_length_integer(num, &tmplen)) != CRYPT_OK) {
+      return err;
+   }
+
+   if (*outlen < tmplen) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* we only need a leading zero if the msb of the first byte is one */
+   if ((mp_count_bits(num) & 7) == 7 || mp_iszero(num) == MP_YES) {
+      leading_zero = 1;
+   } else {
+      leading_zero = 0;
+   }
+
+   /* get length of num in bytes (plus 1 since we force the msbyte to zero) */
+   y = mp_unsigned_bin_size(num) + leading_zero;
+
+   /* now store initial data */
+   *out++ = 0x02;
+   if (y < 128) {
+      /* short form */
+      *out++ = (unsigned char)y;
+   } else {
+      /* long form (relies on y != 0) */
+
+      /* get length of length... ;-) */
+      x = y;
+      z = 0;
+      while (x) {
+         ++z;
+         x >>= 8;
+      }
+      
+      /* store length of length */
+      *out++ = 0x80 | ((unsigned char)z);
+
+      /* now store length */
+      
+      /* first shift length up so msbyte != 0 */
+      x = y;
+      while ((x & 0xFF000000) == 0) {
+          x <<= 8;
+      }
+
+      /* now store length */
+      while (z--) {
+         *out++ = (unsigned char)((x >> 24) & 0xFF);
+         x <<= 8;
+      }
+   }
+
+   /* now store msbyte of zero if num is non-zero */
+   if (leading_zero) {
+      *out++ = 0x00;
+   }
+
+   /* if it's not zero store it as big endian */
+   if (mp_iszero(num) == MP_NO) {
+      /* now store the mpint */
+      if ((err = mp_to_unsigned_bin(num, out)) != MP_OKAY) {
+          return mpi_to_ltc_error(err);
+      }
+   }
+
+   /* we good */
+   *outlen = tmplen; 
+   return CRYPT_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/der_get_multi_integer.c	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,50 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include <stdarg.h>
+#include "mycrypt.h"
+
+/* will read multiple DER INTEGER encoded mp_ints from src
+ * of upto [inlen] bytes.  It will store the number of bytes
+ * read back into [inlen].
+ */
+int der_get_multi_integer(const unsigned char *src, unsigned long *inlen, 
+                  mp_int *num, ...)
+{
+   va_list        args;
+   mp_int        *next;
+   unsigned long  wrote, len;
+   int            err;
+
+   _ARGCHK(src    != NULL);
+   _ARGCHK(inlen  != NULL);
+
+   /* setup va list */
+   next  = num;
+   len   = *inlen;
+   wrote = 0;
+   va_start(args, num);
+
+   while (next != NULL) {
+       if ((err = der_decode_integer(src, inlen, next)) != CRYPT_OK) {
+          va_end(args);
+          return err;
+       }
+       wrote += *inlen;
+       src   += *inlen;
+       len   -= *inlen;
+       *inlen = len;
+        next     = va_arg(args, mp_int*);
+   }
+   va_end(args);
+   *inlen = wrote;
+   return CRYPT_OK;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/der_length_integer.c	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,54 @@
+/* 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"
+
+/* Gets length of DER encoding of num */
+
+int der_length_integer(mp_int *num, unsigned long *outlen)
+{
+   unsigned long z, len;
+   int           leading_zero;
+
+   _ARGCHK(num     != NULL);
+   _ARGCHK(outlen  != NULL);
+
+   /* we only need a leading zero if the msb of the first byte is one */
+   if ((mp_count_bits(num) & 7) == 7 || mp_iszero(num) == MP_YES) {
+      leading_zero = 1;
+   } else {
+      leading_zero = 0;
+   }
+
+   /* size for bignum */
+   z = len = leading_zero + mp_unsigned_bin_size(num);
+
+   /* we need a 0x02 */
+   ++len;
+
+   /* now we need a length */
+   if (z < 128) {
+      /* short form */
+      ++len;
+   } else {
+      /* long form (relies on z != 0) */
+      ++len;
+
+      while (z) {
+         ++len;
+         z >>= 8;
+      }
+   }
+
+   *outlen = len; 
+   return CRYPT_OK;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/der_put_multi_integer.c	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,49 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include <stdarg.h>
+#include "mycrypt.h"
+
+/* store multiple mp_ints in DER INTEGER format to the dst, will not
+ * overflow the length you give it [outlen] and store the number of 
+ * bytes used in [outlen] 
+ */
+int der_put_multi_integer(unsigned char *dst, unsigned long *outlen, 
+                  mp_int *num, ...)
+{
+   va_list        args;
+   mp_int        *next;
+   unsigned long  wrote, len;
+   int            err;
+
+   _ARGCHK(dst    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* setup va list */
+   next  = num;
+   len   = *outlen;
+   wrote = 0;
+   va_start(args, num);
+
+   while (next != NULL) {
+        if ((err = der_encode_integer(next, dst, outlen)) != CRYPT_OK) {
+           va_end(args);
+           return err;
+        }
+        wrote   += *outlen;
+        dst     += *outlen;
+        len     -= *outlen;
+        *outlen  = len;
+        next     = va_arg(args, mp_int*);
+   }
+   va_end(args);
+   *outlen = wrote;
+   return CRYPT_OK;
+}
--- a/des.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/des.c	Sun Dec 19 11:34:45 2004 +0000
@@ -1377,7 +1377,7 @@
         *cook++ |= (*raw1 & 0x0000003fL);
     }
 
-    memcpy(keyout, dough, sizeof dough);
+    XMEMCPY(keyout, dough, sizeof dough);
 }
 
 #ifdef CLEAN_STACK
@@ -1395,7 +1395,7 @@
 #endif
 {
     ulong32 work, right, leftt;
-    int round;
+    int cur_round;
 
     leftt = block[0];
     right = block[1];
@@ -1439,7 +1439,7 @@
    }
 #endif
 
-    for (round = 0; round < 8; round++) {
+    for (cur_round = 0; cur_round < 8; cur_round++) {
         work  = ROR(right, 4) ^ *keys++;
         leftt ^= SP7[work        & 0x3fL]
               ^ SP5[(work >>  8) & 0x3fL]
@@ -1534,7 +1534,7 @@
     _ARGCHK(key != NULL);
     _ARGCHK(skey != NULL);
 
-    if( num_rounds != 0 && num_rounds != 16) {
+    if(num_rounds != 0 && num_rounds != 16) {
         return CRYPT_INVALID_ROUNDS;
     }
 
--- a/dh.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/dh.c	Sun Dec 19 11:34:45 2004 +0000
@@ -12,6 +12,9 @@
 
 #ifdef MDH
 
+/* max export size we'll encounter (smaller than this but lets round up a bit */
+#define DH_BUF_SIZE 1200
+
 /* This holds the key settings.  ***MUST*** be organized by size from smallest to largest. */
 static const struct {
     int size;
@@ -226,7 +229,7 @@
 
 int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key)
 {
-   unsigned char buf[512];
+   unsigned char *buf;
    unsigned long x;
    mp_int p, g;
    int err;
@@ -251,14 +254,21 @@
    }
    key->idx = x;
 
+   /* allocate buffer */
+   buf = XMALLOC(keysize);
+   if (buf == NULL) {
+      return CRYPT_MEM;
+   }
+
    /* make up random string */
    if (prng_descriptor[wprng].read(buf, keysize, prng) != (unsigned long)keysize) {
-      return CRYPT_ERROR_READPRNG;
+      err = CRYPT_ERROR_READPRNG; 
+      goto error2;
    }
 
    /* init parameters */
    if ((err = mp_init_multi(&g, &p, &key->x, &key->y, NULL)) != MP_OKAY) {
-      return mpi_to_ltc_error(err);
+      goto error;
    }
    if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY)      { goto error; }
    if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY)     { goto error; }
@@ -276,10 +286,14 @@
    goto done;
 error:
    err = mpi_to_ltc_error(err);
+error2:
    mp_clear_multi(&key->x, &key->y, NULL);
 done:
+#ifdef CLEAN_STACK
+   zeromem(buf, keysize);
+#endif
    mp_clear_multi(&p, &g, NULL);
-   zeromem(buf, sizeof(buf));
+   XFREE(buf);
    return err;
 }
 
--- a/dh_sys.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/dh_sys.c	Sun Dec 19 11:34:45 2004 +0000
@@ -13,7 +13,7 @@
                          prng_state *prng, int wprng, int hash,
                          dh_key *key)
 {
-    unsigned char pub_expt[768], dh_shared[768], skey[MAXBLOCKSIZE];
+    unsigned char *pub_expt, *dh_shared, *skey;
     dh_key pubkey;
     unsigned long x, y, z, hashsize, pubkeysize;
     int err;
@@ -36,36 +36,54 @@
         return CRYPT_INVALID_HASH;
     }
 
-    /* make a random key and export the public copy */
-    if ((err = dh_make_key(prng, wprng, dh_get_size(key), &pubkey)) != CRYPT_OK) {
-       return err;
+    /* allocate memory */
+    pub_expt  = XMALLOC(DH_BUF_SIZE);
+    dh_shared = XMALLOC(DH_BUF_SIZE);
+    skey      = XMALLOC(MAXBLOCKSIZE);
+    if (pub_expt == NULL || dh_shared == NULL || skey == NULL) {
+       if (pub_expt != NULL) {
+          XFREE(pub_expt);
+       }
+       if (dh_shared != NULL) {
+          XFREE(dh_shared);
+       }
+       if (skey != NULL) {
+          XFREE(skey);
+       }
+       return CRYPT_MEM;
     }
 
-    pubkeysize = sizeof(pub_expt);
+    /* make a random key and export the public copy */
+    if ((err = dh_make_key(prng, wprng, dh_get_size(key), &pubkey)) != CRYPT_OK) {
+       goto __ERR;
+    }
+
+    pubkeysize = DH_BUF_SIZE;
     if ((err = dh_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
        dh_free(&pubkey);
-       return err;
+       goto __ERR;
     }
 
     /* now check if the out buffer is big enough */
     if (*len < (1 + 4 + 4 + PACKET_SIZE + pubkeysize + keylen)) {
        dh_free(&pubkey);
-       return CRYPT_BUFFER_OVERFLOW;
+       err = CRYPT_BUFFER_OVERFLOW;
+       goto __ERR;
     }
 
     /* make random key */
     hashsize  = hash_descriptor[hash].hashsize;
 
-    x = (unsigned long)sizeof(dh_shared);
+    x = DH_BUF_SIZE;
     if ((err = dh_shared_secret(&pubkey, key, dh_shared, &x)) != CRYPT_OK) {
        dh_free(&pubkey);
-       return err;
+       goto __ERR;
     }
     dh_free(&pubkey);
 
-    z = sizeof(skey);
+    z = MAXBLOCKSIZE;
     if ((err = hash_memory(hash, dh_shared, x, skey, &z)) != CRYPT_OK) {
-       return err;
+       goto __ERR;
     }
 
     /* store header */
@@ -93,21 +111,26 @@
     }
     *len = y;
 
+    err = CRYPT_OK;
+__ERR:
 #ifdef CLEAN_STACK
     /* clean up */
-    zeromem(pub_expt, sizeof(pub_expt));
-    zeromem(dh_shared, sizeof(dh_shared));
-    zeromem(skey, sizeof(skey));
+    zeromem(pub_expt,  DH_BUF_SIZE);
+    zeromem(dh_shared, DH_BUF_SIZE);
+    zeromem(skey,      MAXBLOCKSIZE);
 #endif
+    XFREE(skey);
+    XFREE(dh_shared);
+    XFREE(pub_expt);
 
-    return CRYPT_OK;
+    return err;
 }
 
 int dh_decrypt_key(const unsigned char *in, unsigned long inlen,
                          unsigned char *outkey, unsigned long *keylen, 
                          dh_key *key)
 {
-   unsigned char shared_secret[768], skey[MAXBLOCKSIZE];
+   unsigned char *shared_secret, *skey;
    unsigned long x, y, z,hashsize, keysize;
    int  hash, err;
    dh_key pubkey;
@@ -122,23 +145,38 @@
       return CRYPT_PK_NOT_PRIVATE;
    }
 
+   /* allocate ram */
+   shared_secret = XMALLOC(DH_BUF_SIZE);
+   skey          = XMALLOC(MAXBLOCKSIZE);
+   if (shared_secret == NULL || skey == NULL) {
+      if (shared_secret != NULL) {
+         XFREE(shared_secret);
+      }
+      if (skey != NULL) {
+         XFREE(skey);
+      }
+      return CRYPT_MEM;
+   }
+
    /* check if initial header should fit */
    if (inlen < PACKET_SIZE+1+4+4) {
-      return CRYPT_INVALID_PACKET;
+      err =  CRYPT_INVALID_PACKET;
+      goto __ERR;
    } else {
       inlen -= PACKET_SIZE+1+4+4;
    }
 
    /* is header correct? */
    if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_ENC_KEY)) != CRYPT_OK)  {
-      return err;
+      goto __ERR;
    }
 
    /* now lets get the hash name */
    y = PACKET_SIZE;
    hash = find_hash_id(in[y++]);
    if (hash == -1) {
-      return CRYPT_INVALID_HASH;
+      err = CRYPT_INVALID_HASH;
+      goto __ERR;
    }
 
    /* common values */
@@ -149,28 +187,29 @@
    
    /* now check if the imported key will fit */
    if (inlen < x) {
-      return CRYPT_INVALID_PACKET;
+      err = CRYPT_INVALID_PACKET;
+      goto __ERR;
    } else {
       inlen -= x;
    }
    
    y += 4;
    if ((err = dh_import(in+y, x, &pubkey)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
    y += x;
 
    /* make shared key */
-   x = (unsigned long)sizeof(shared_secret);
+   x = DH_BUF_SIZE;
    if ((err = dh_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) {
       dh_free(&pubkey);
-      return err;
+      goto __ERR;
    }
    dh_free(&pubkey);
 
-   z = sizeof(skey);
+   z = MAXBLOCKSIZE;
    if ((err = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
 
    /* load in the encrypted key */
@@ -178,14 +217,15 @@
    
    /* will the outkey fit as part of the input */
    if (inlen < keysize) {
-      return CRYPT_INVALID_PACKET;
+      err = CRYPT_INVALID_PACKET;
+      goto __ERR;
    } else {
       inlen -= keysize;
    }
    
    if (keysize > *keylen) {
        err = CRYPT_BUFFER_OVERFLOW;
-       goto done;
+       goto __ERR;
    }
    y += 4;
 
@@ -196,11 +236,15 @@
    }
 
    err = CRYPT_OK;
-done:
+__ERR:
 #ifdef CLEAN_STACK
-   zeromem(shared_secret, sizeof(shared_secret));
-   zeromem(skey, sizeof(skey));
+   zeromem(shared_secret, DH_BUF_SIZE);
+   zeromem(skey,          MAXBLOCKSIZE);
 #endif
+
+   XFREE(skey);
+   XFREE(shared_secret);
+
    return err;
 }
 
@@ -227,7 +271,7 @@
                        prng_state *prng, int wprng, dh_key *key)
 {
    mp_int a, b, k, m, g, p, p1, tmp;
-   unsigned char buf[520];
+   unsigned char *buf;
    unsigned long x, y;
    int err;
 
@@ -250,18 +294,23 @@
       return CRYPT_PK_INVALID_TYPE;
    }
 
+   /* allocate ram for buf */
+   buf = XMALLOC(520);
+
    /* make up a random value k,
     * since the order of the group is prime
     * we need not check if gcd(k, r) is 1 
     */
    if (prng_descriptor[wprng].read(buf, sets[key->idx].size, prng) != 
        (unsigned long)(sets[key->idx].size)) {
-      return CRYPT_ERROR_READPRNG;
+      err = CRYPT_ERROR_READPRNG;
+      goto __ERR;
    }
 
    /* init bignums */
    if ((err = mp_init_multi(&a, &b, &k, &m, &p, &g, &p1, &tmp, NULL)) != MP_OKAY) { 
-      return mpi_to_ltc_error(err);
+      err = mpi_to_ltc_error(err);
+      goto __ERR;
    }
 
    /* load k and m */
@@ -290,7 +339,7 @@
    /* check for overflow */
    if ((unsigned long)(PACKET_SIZE + 4 + 4 + mp_unsigned_bin_size(&a) + mp_unsigned_bin_size(&b)) > *outlen) {
       err = CRYPT_BUFFER_OVERFLOW;
-      goto done;
+      goto __ERR;
    }
    
    /* store header  */
@@ -310,7 +359,7 @@
    /* check if size too big */
    if (*outlen < y) {
       err = CRYPT_BUFFER_OVERFLOW;
-      goto done;
+      goto __ERR;
    }
 
    /* store header */
@@ -318,11 +367,14 @@
    *outlen = y;
 
    err = CRYPT_OK;
-   goto done;
+   goto __ERR;
 error:
    err = mpi_to_ltc_error(err);
-done:
+__ERR:
    mp_clear_multi(&tmp, &p1, &g, &p, &m, &k, &b, &a, NULL);
+
+   XFREE(buf);
+
    return err;
 }
 
Binary file doc/crypt.pdf has changed
--- a/dsa_make_key.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/dsa_make_key.c	Sun Dec 19 11:34:45 2004 +0000
@@ -14,9 +14,9 @@
 
 int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key)
 {
-   mp_int tmp, tmp2;
-   int err, res;
-   unsigned char buf[512];
+   mp_int         tmp, tmp2;
+   int            err, res;
+   unsigned char *buf;
 
    _ARGCHK(key  != NULL);
 
@@ -26,26 +26,33 @@
    }
 
    /* check size */
-   if (group_size >= 1024 || group_size <= 15 || 
-       group_size >= modulus_size || (modulus_size - group_size) >= (int)sizeof(buf)) {
+   if (group_size >= MDSA_MAX_GROUP || group_size <= 15 || 
+       group_size >= modulus_size || (modulus_size - group_size) >= MDSA_DELTA) {
       return CRYPT_INVALID_ARG;
    }
 
+   /* allocate ram */
+   buf = XMALLOC(MDSA_DELTA);
+   if (buf == NULL) {
+      return CRYPT_MEM;
+   }
+
    /* init mp_ints  */
    if ((err = mp_init_multi(&tmp, &tmp2, &key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != MP_OKAY) {
-      return mpi_to_ltc_error(err);
+      err = mpi_to_ltc_error(err);
+      goto __ERR;
    }
 
    /* make our prime q */
-   if ((err = rand_prime(&key->q, group_size*8, prng, wprng)) != CRYPT_OK)             { goto error2; }
+   if ((err = rand_prime(&key->q, group_size*8, prng, wprng)) != CRYPT_OK)             { goto __ERR; }
 
    /* double q  */
-   if ((err = mp_mul_2(&key->q, &tmp)) != MP_OKAY)                                   { goto error; }
+   if ((err = mp_mul_2(&key->q, &tmp)) != MP_OKAY)                                     { goto error; }
 
    /* now make a random string and multply it against q */
    if (prng_descriptor[wprng].read(buf+1, modulus_size - group_size, prng) != (unsigned long)(modulus_size - group_size)) {
       err = CRYPT_ERROR_READPRNG;
-      goto error2;
+      goto __ERR;
    }
 
    /* force magnitude */
@@ -60,7 +67,7 @@
    
    /* now loop until p is prime */
    for (;;) {
-       if ((err = is_prime(&key->p, &res)) != CRYPT_OK)                                { goto error2; }
+       if ((err = is_prime(&key->p, &res)) != CRYPT_OK)                                { goto __ERR; }
        if (res == MP_YES) break;
 
        /* add 2q to p and 2 to tmp2 */
@@ -85,7 +92,7 @@
    do {
       if (prng_descriptor[wprng].read(buf, group_size, prng) != (unsigned long)group_size) {
          err = CRYPT_ERROR_READPRNG;
-         goto error2;
+         goto __ERR;
       }
       if ((err = mp_read_unsigned_bin(&key->x, buf, group_size)) != MP_OKAY)           { goto error; }
    } while (mp_cmp_d(&key->x, 1) != MP_GT);
@@ -101,17 +108,21 @@
    if ((err = mp_shrink(&key->x)) != MP_OKAY)                                          { goto error; }
    if ((err = mp_shrink(&key->y)) != MP_OKAY)                                          { goto error; }
 
-   err = CRYPT_OK;
-
 #ifdef CLEAN_STACK
-   zeromem(buf, sizeof(buf));
+   zeromem(buf, MDSA_DELTA);
 #endif
 
+   err = CRYPT_OK;
    goto done;
-error : err = mpi_to_ltc_error(err);
-error2: mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL);
-done  : mp_clear_multi(&tmp, &tmp2, NULL);
-   return err;
+error: 
+    err = mpi_to_ltc_error(err);
+__ERR: 
+    mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL);
+done: 
+    mp_clear_multi(&tmp, &tmp2, NULL);
+
+    XFREE(buf);
+    return err;
 }
 
 #endif
--- a/dsa_sign_hash.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/dsa_sign_hash.c	Sun Dec 19 11:34:45 2004 +0000
@@ -16,11 +16,10 @@
                         unsigned char *out, unsigned long *outlen,
                         prng_state *prng, int wprng, dsa_key *key)
 {
-   mp_int k, kinv, tmp, r, s;
-   unsigned char buf[512];
-   int err, y;
-   unsigned long len;
-
+   mp_int         k, kinv, tmp, r, s;
+   unsigned char *buf;
+   int            err, y;
+   unsigned long  len;
 
    _ARGCHK(in     != NULL);
    _ARGCHK(out    != NULL);
@@ -35,10 +34,15 @@
    }
 
    /* check group order size  */
-   if (key->qord >= (int)sizeof(buf)) {
+   if (key->qord >= MDSA_MAX_GROUP) {
       return CRYPT_INVALID_ARG;
    }
 
+   buf = XMALLOC(MDSA_MAX_GROUP);
+   if (buf == NULL) {
+      return CRYPT_MEM;
+   }
+
    /* Init our temps */
    if ((err = mp_init_multi(&k, &kinv, &r, &s, &tmp, NULL)) != MP_OKAY)               { goto error; }
 
@@ -48,7 +52,7 @@
       /* gen random k */
       if (prng_descriptor[wprng].read(buf, key->qord, prng) != (unsigned long)key->qord) {
          err = CRYPT_ERROR_READPRNG;
-         goto done;
+         goto __ERR;
       }
 
       /* read k */
@@ -83,7 +87,7 @@
    /* first check that we have enough room */
    if (*outlen < (unsigned long)(PACKET_SIZE + 4 + mp_unsigned_bin_size(&s) + mp_unsigned_bin_size(&r))) {
       err = CRYPT_BUFFER_OVERFLOW;
-      goto done;
+      goto __ERR;
    }
 
    /* packet header */
@@ -112,13 +116,16 @@
    *outlen = y;
 
    err = CRYPT_OK;
-   goto done;
+   goto __ERR;
 
-error : err = mpi_to_ltc_error(err);
-done  : mp_clear_multi(&k, &kinv, &r, &s, &tmp, NULL);
+error: 
+   err = mpi_to_ltc_error(err);
+__ERR: 
+   mp_clear_multi(&k, &kinv, &r, &s, &tmp, NULL);
 #ifdef CLEAN_STACK
-   zeromem(buf, sizeof(buf));
+   zeromem(buf, MDSA_MAX_GROUP);
 #endif
+   XFREE(buf);
    return err;
 }
 
--- a/eax_decrypt_verify_memory.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/eax_decrypt_verify_memory.c	Sun Dec 19 11:34:45 2004 +0000
@@ -23,38 +23,58 @@
           unsigned char *tag,    unsigned long taglen,
           int           *res)
 {
-   int err;
-   eax_state eax;
-   unsigned char buf[MAXBLOCKSIZE];
-   unsigned long buflen;
+   int            err;
+   eax_state     *eax;
+   unsigned char *buf;
+   unsigned long  buflen;
 
    _ARGCHK(res != NULL);
 
    /* default to zero */
    *res = 0;
 
-   if ((err = eax_init(&eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) {
-      return err;
+   /* allocate ram */
+   buf = XMALLOC(taglen);
+   eax = XMALLOC(sizeof(eax_state));
+   if (eax == NULL || buf == NULL) {
+      if (eax != NULL) {
+         XFREE(eax);
+      }
+      if (buf != NULL) {
+         XFREE(buf);
+      }
+      return CRYPT_MEM;
    }
 
-   if ((err = eax_decrypt(&eax, ct, pt, ctlen)) != CRYPT_OK) {
-      return err;
+   if ((err = eax_init(eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) {
+      goto __ERR;
+   }
+
+   if ((err = eax_decrypt(eax, ct, pt, ctlen)) != CRYPT_OK) {
+      goto __ERR;
    }
  
-   buflen = MIN(sizeof(buf), taglen);
-   if ((err = eax_done(&eax, buf, &buflen)) != CRYPT_OK) {
-      return err;
+   buflen = taglen;
+   if ((err = eax_done(eax, buf, &buflen)) != CRYPT_OK) {
+      goto __ERR;
    }
 
    /* compare tags */
    if (buflen >= taglen && memcmp(buf, tag, taglen) == 0) {
       *res = 1;
    }
-
+   
+   err = CRYPT_OK;
+__ERR:
 #ifdef CLEAN_STACK
-   zeromem(buf, sizeof(buf));
+   zeromem(buf, taglen);
+   zeromem(eax, sizeof(eax_state));
 #endif
-   return CRYPT_OK;
+
+   XFREE(eax);
+   XFREE(buf);
+
+   return err;
 }
 
 #endif
--- a/eax_done.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/eax_done.c	Sun Dec 19 11:34:45 2004 +0000
@@ -17,17 +17,31 @@
 int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen)
 {
    int           err;
-   unsigned char headermac[MAXBLOCKSIZE], ctmac[MAXBLOCKSIZE];
+   unsigned char *headermac, *ctmac;
    unsigned long x, len;
 
    _ARGCHK(eax    != NULL);
    _ARGCHK(tag    != NULL);
    _ARGCHK(taglen != NULL);
 
+   /* allocate ram */
+   headermac = XMALLOC(MAXBLOCKSIZE);
+   ctmac     = XMALLOC(MAXBLOCKSIZE);
+
+   if (headermac == NULL || ctmac == NULL) {
+      if (headermac != NULL) {
+         XFREE(headermac);
+      }
+      if (ctmac != NULL) {
+         XFREE(ctmac);
+      }
+      return CRYPT_MEM;
+   }
+
    /* finish ctomac */
-   len = sizeof(ctmac);
+   len = MAXBLOCKSIZE;
    if ((err = omac_done(&eax->ctomac, ctmac, &len)) != CRYPT_OK) {
-      return err;
+      goto __ERR; 
    }
 
    /* finish headeromac */
@@ -35,7 +49,7 @@
    /* note we specifically don't reset len so the two lens are minimal */
 
    if ((err = omac_done(&eax->headeromac, headermac, &len)) != CRYPT_OK) {
-      return err;
+      goto __ERR; 
    }
 
    /* compute N xor H xor C */
@@ -44,13 +58,18 @@
    }
    *taglen = x;
 
+   err = CRYPT_OK;
+__ERR:
 #ifdef CLEAN_STACK
-   zeromem(ctmac, sizeof(ctmac));
-   zeromem(headermac, sizeof(headermac));
-   zeromem(eax, sizeof(*eax));
+   zeromem(ctmac,     MAXBLOCKSIZE);
+   zeromem(headermac, MAXBLOCKSIZE);
+   zeromem(eax,       sizeof(*eax));
 #endif
 
-   return CRYPT_OK;
+   XFREE(ctmac);
+   XFREE(headermac);
+
+   return err;
 }
 
 #endif
--- a/eax_encrypt_authenticate_memory.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/eax_encrypt_authenticate_memory.c	Sun Dec 19 11:34:45 2004 +0000
@@ -23,21 +23,31 @@
           unsigned char *tag,    unsigned long *taglen)
 {
    int err;
-   eax_state eax;
+   eax_state *eax;
 
-   if ((err = eax_init(&eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) {
-      return err;
+   eax = XMALLOC(sizeof(eax_state));
+
+   if ((err = eax_init(eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) {
+      goto __ERR; 
    }
 
-   if ((err = eax_encrypt(&eax, pt, ct, ptlen)) != CRYPT_OK) {
-      return err;
+   if ((err = eax_encrypt(eax, pt, ct, ptlen)) != CRYPT_OK) {
+      goto __ERR; 
    }
  
-   if ((err = eax_done(&eax, tag, taglen)) != CRYPT_OK) {
-      return err;
+   if ((err = eax_done(eax, tag, taglen)) != CRYPT_OK) {
+      goto __ERR; 
    }
 
-   return CRYPT_OK;
+   err = CRYPT_OK;
+__ERR:
+#ifdef CLEAN_STACK
+   zeromem(eax, sizeof(eax_state));
+#endif
+
+   XFREE(eax);
+
+   return err;   
 }
 
 #endif
--- a/eax_init.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/eax_init.c	Sun Dec 19 11:34:45 2004 +0000
@@ -18,9 +18,9 @@
              const unsigned char *nonce, unsigned long noncelen,
              const unsigned char *header, unsigned long headerlen)
 {
-   unsigned char buf[MAXBLOCKSIZE];
+   unsigned char *buf;
    int           err, blklen;
-   omac_state    omac;
+   omac_state    *omac;
    unsigned long len;
 
 
@@ -36,42 +36,56 @@
    }
    blklen = cipher_descriptor[cipher].block_length;
 
+   /* allocate ram */
+   buf  = XMALLOC(MAXBLOCKSIZE);
+   omac = XMALLOC(sizeof(omac_state));
+
+   if (buf == NULL || omac == NULL) {
+      if (buf != NULL) {
+         XFREE(buf);
+      }
+      if (omac != NULL) {
+         XFREE(omac);
+      }
+      return CRYPT_MEM;
+   }
+
    /* N = OMAC_0K(nonce) */
-   zeromem(buf, sizeof(buf));
-   if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) {
-      return err;
+   zeromem(buf, MAXBLOCKSIZE);
+   if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) {
+      goto __ERR; 
    }
 
    /* omac the [0]_n */
-   if ((err = omac_process(&omac, buf, blklen)) != CRYPT_OK) {
-      return err;
+   if ((err = omac_process(omac, buf, blklen)) != CRYPT_OK) {
+      goto __ERR; 
    }
    /* omac the nonce */
-   if ((err = omac_process(&omac, nonce, noncelen)) != CRYPT_OK) {
-      return err;
+   if ((err = omac_process(omac, nonce, noncelen)) != CRYPT_OK) {
+      goto __ERR; 
    }
    /* store result */
    len = sizeof(eax->N);
-   if ((err = omac_done(&omac, eax->N, &len)) != CRYPT_OK) {
-      return err;
+   if ((err = omac_done(omac, eax->N, &len)) != CRYPT_OK) {
+      goto __ERR; 
    }
 
    /* H = OMAC_1K(header) */
-   zeromem(buf, sizeof(buf));
+   zeromem(buf, MAXBLOCKSIZE);
    buf[blklen - 1] = 1;
 
    if ((err = omac_init(&eax->headeromac, cipher, key, keylen)) != CRYPT_OK) {
-      return err;
+      goto __ERR; 
    }
 
    /* omac the [1]_n */
    if ((err = omac_process(&eax->headeromac, buf, blklen)) != CRYPT_OK) {
-      return err;
+      goto __ERR; 
    }
    /* omac the header */
    if (headerlen != 0) {
       if ((err = omac_process(&eax->headeromac, header, headerlen)) != CRYPT_OK) {
-         return err;
+          goto __ERR; 
       }
    }
 
@@ -79,28 +93,34 @@
 
    /* setup the CTR mode */
    if ((err = ctr_start(cipher, eax->N, key, keylen, 0, &eax->ctr)) != CRYPT_OK) {
-      return err;
+      goto __ERR; 
    }
    /* use big-endian counter */
    eax->ctr.mode = 1;
 
    /* setup the OMAC for the ciphertext */
    if ((err = omac_init(&eax->ctomac, cipher, key, keylen)) != CRYPT_OK) { 
-      return err;
+      goto __ERR; 
    }
 
    /* omac [2]_n */
-   zeromem(buf, sizeof(buf));
+   zeromem(buf, MAXBLOCKSIZE);
    buf[blklen-1] = 2;
    if ((err = omac_process(&eax->ctomac, buf, blklen)) != CRYPT_OK) {
-      return err;
+      goto __ERR; 
    }
 
+   err = CRYPT_OK;
+__ERR:
 #ifdef CLEAN_STACK
-   zeromem(buf, sizeof(buf));
-   zeromem(&omac, sizeof(omac));
+   zeromem(buf,  MAXBLOCKSIZE);
+   zeromem(omac, sizeof(omac_state));
 #endif
-   return CRYPT_OK;
+
+   XFREE(omac);
+   XFREE(buf);
+
+   return err;
 }
 
 #endif 
--- a/ecc.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/ecc.c	Sun Dec 19 11:34:45 2004 +0000
@@ -19,6 +19,12 @@
 
 #ifdef MECC
 
+/* size of our temp buffers for exported keys */
+#define ECC_BUF_SIZE 160
+
+/* max private key size */
+#define ECC_MAXSIZE  66
+
 /* This holds the key settings.  ***MUST*** be organized by size from smallest to largest. */
 static const struct {
    int size;
@@ -219,9 +225,6 @@
  
 #endif
 
-
-
-
 static int is_valid_idx(int n)
 {
    int x;
@@ -368,10 +371,10 @@
 static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus)
 {
    ecc_point *tG, *M[8];
-   int i, j, err;
-   mp_int mu;
-   mp_digit buf;
-   int     first, bitbuf, bitcpy, bitcnt, mode, digidx;
+   int        i, j, err;
+   mp_int     mu;
+   mp_digit   buf;
+   int        first, bitbuf, bitcpy, bitcnt, mode, digidx;
 
   /* init barrett reduction */
   if ((err = mp_init(&mu)) != MP_OKAY) {
@@ -595,10 +598,10 @@
 
 int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
 {
-   int x, err;
-   ecc_point *base;
-   mp_int prime;
-   unsigned char buf[128];
+   int            x, err;
+   ecc_point     *base;
+   mp_int         prime;
+   unsigned char *buf;
 
    _ARGCHK(key != NULL);
 
@@ -610,25 +613,36 @@
    /* find key size */
    for (x = 0; (keysize > sets[x].size) && (sets[x].size != 0); x++);
    keysize = sets[x].size;
+   _ARGCHK(keysize <= ECC_MAXSIZE);
 
    if (sets[x].size == 0) {
       return CRYPT_INVALID_KEYSIZE;
    }
    key->idx = x;
 
+   /* allocate ram */
+   base = NULL;
+   buf  = XMALLOC(ECC_MAXSIZE);
+   if (buf == NULL) {
+      return CRYPT_MEM;
+   }
+
    /* make up random string */
    if (prng_descriptor[wprng].read(buf, (unsigned long)keysize, prng) != (unsigned long)keysize) {
-      return CRYPT_ERROR_READPRNG;
+      err = CRYPT_ERROR_READPRNG;
+      goto __ERR2;
    }
 
    /* setup the key variables */
    if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->k, &prime, NULL)) != MP_OKAY) {
-      return mpi_to_ltc_error(err);
+      err = mpi_to_ltc_error(err);
+      goto __ERR;
    }
    base = new_point();
    if (base == NULL) {
       mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, &prime, NULL);
-      return CRYPT_MEM;
+      err = CRYPT_MEM;
+      goto __ERR;
    }
 
    /* read in the specs for this key */
@@ -638,7 +652,7 @@
    if ((err = mp_read_unsigned_bin(&key->k, (unsigned char *)buf, keysize)) != MP_OKAY) { goto error; }
 
    /* make the public key */
-   if ((err = ecc_mulmod(&key->k, base, &key->pubkey, &prime)) != CRYPT_OK)             { goto done; }
+   if ((err = ecc_mulmod(&key->k, base, &key->pubkey, &prime)) != CRYPT_OK)             { goto __ERR; }
    key->type = PK_PRIVATE;
 
    /* shrink key */
@@ -648,15 +662,19 @@
 
    /* free up ram */
    err = CRYPT_OK;
-   goto done;
+   goto __ERR;
 error:
    err = mpi_to_ltc_error(err);
-done:
+__ERR:
    del_point(base);
    mp_clear(&prime);
+__ERR2:
 #ifdef CLEAN_STACK
-   zeromem(buf, sizeof(buf));
+   zeromem(buf, ECC_MAXSIZE);
 #endif
+
+   XFREE(buf);
+
    return err;
 }
 
--- a/ecc_sys.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/ecc_sys.c	Sun Dec 19 11:34:45 2004 +0000
@@ -13,10 +13,10 @@
                           prng_state *prng, int wprng, int hash, 
                           ecc_key *key)
 {
-    unsigned char pub_expt[256], ecc_shared[256], skey[MAXBLOCKSIZE];
-    ecc_key pubkey;
-    unsigned long x, y, z, hashsize, pubkeysize;
-    int err;
+    unsigned char *pub_expt, *ecc_shared, *skey;
+    ecc_key        pubkey;
+    unsigned long  x, y, z, hashsize, pubkeysize;
+    int            err;
 
     _ARGCHK(inkey != NULL);
     _ARGCHK(out   != NULL);
@@ -41,29 +41,47 @@
        return err;
     }
 
-    pubkeysize = (unsigned long)sizeof(pub_expt);
+    pub_expt   = XMALLOC(ECC_BUF_SIZE);
+    ecc_shared = XMALLOC(ECC_BUF_SIZE);
+    skey       = XMALLOC(MAXBLOCKSIZE);
+    if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) {
+       if (pub_expt != NULL) {
+          XFREE(pub_expt);
+       }
+       if (ecc_shared != NULL) {
+          XFREE(ecc_shared);
+       }
+       if (skey != NULL) {
+          XFREE(skey);
+       }
+       ecc_free(&pubkey);
+       return CRYPT_MEM;
+    }
+
+    pubkeysize = ECC_BUF_SIZE;
     if ((err = ecc_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
        ecc_free(&pubkey);
-       return err;
+       goto __ERR;
     }
     
     /* now check if the out buffer is big enough */
     if (*len < (9 + PACKET_SIZE + pubkeysize + hash_descriptor[hash].hashsize)) {
        ecc_free(&pubkey);
-       return CRYPT_BUFFER_OVERFLOW;
+       err = CRYPT_BUFFER_OVERFLOW;
+       goto __ERR;
     }
 
     /* make random key */
     hashsize  = hash_descriptor[hash].hashsize;
-    x = (unsigned long)sizeof(ecc_shared);
+    x = ECC_BUF_SIZE;
     if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) {
        ecc_free(&pubkey);
-       return err;
+       goto __ERR;
     }
     ecc_free(&pubkey);
-    z = (unsigned long)sizeof(skey);
+    z = MAXBLOCKSIZE;
     if ((err = hash_memory(hash, ecc_shared, x, skey, &z)) != CRYPT_OK) {
-       return err;
+       goto __ERR;
     }
     
     /* store header */
@@ -92,23 +110,30 @@
     }
     *len = y;
 
+    err = CRYPT_OK;
+__ERR:
 #ifdef CLEAN_STACK
     /* clean up */
-    zeromem(pub_expt, sizeof(pub_expt));
-    zeromem(ecc_shared, sizeof(ecc_shared));
-    zeromem(skey, sizeof(skey));
+    zeromem(pub_expt,   ECC_BUF_SIZE);
+    zeromem(ecc_shared, ECC_BUF_SIZE);
+    zeromem(skey,       MAXBLOCKSIZE);
 #endif
-    return CRYPT_OK;
+
+    XFREE(skey);
+    XFREE(ecc_shared);
+    XFREE(pub_expt);
+
+    return err;
 }
 
 int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
                           unsigned char *outkey, unsigned long *keylen, 
                           ecc_key *key)
 {
-   unsigned char shared_secret[256], skey[MAXBLOCKSIZE];
-   unsigned long x, y, z, hashsize, keysize;
-   int hash, err;
-   ecc_key pubkey;
+   unsigned char *shared_secret, *skey;
+   unsigned long  x, y, z, hashsize, keysize;
+   int            hash, err;
+   ecc_key        pubkey;
 
    _ARGCHK(in     != NULL);
    _ARGCHK(outkey != NULL);
@@ -155,22 +180,37 @@
    }
    y += x;
 
+   /* allocate memory */
+   shared_secret = XMALLOC(ECC_BUF_SIZE);
+   skey          = XMALLOC(MAXBLOCKSIZE);
+   if (shared_secret == NULL || skey == NULL) {
+      if (shared_secret != NULL) {
+         XFREE(shared_secret);
+      }
+      if (skey != NULL) {
+         XFREE(skey);
+      }
+      ecc_free(&pubkey);
+      return CRYPT_MEM;
+   }
+
    /* make shared key */
-   x = (unsigned long)sizeof(shared_secret);
+   x = ECC_BUF_SIZE;
    if ((err = ecc_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) {
       ecc_free(&pubkey);
-      return err;
+      goto __ERR;
    }
    ecc_free(&pubkey);
 
-   z = (unsigned long)sizeof(skey);
+   z = MAXBLOCKSIZE;
    if ((err = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
 
    LOAD32L(keysize, in+y);
    if (inlen < keysize) {
-      return CRYPT_INVALID_PACKET;
+      err = CRYPT_INVALID_PACKET;
+      goto __ERR;
    } else {
       inlen -= keysize;
    }
@@ -178,7 +218,7 @@
 
    if (*keylen < keysize) {
        err = CRYPT_BUFFER_OVERFLOW;
-       goto done;
+       goto __ERR;
    }
 
    /* Decrypt the key */
@@ -189,11 +229,15 @@
    *keylen = keysize;
 
    err = CRYPT_OK;
-done:
+__ERR:
 #ifdef CLEAN_STACK
-   zeromem(shared_secret, sizeof(shared_secret));
-   zeromem(skey, sizeof(skey));
+   zeromem(shared_secret, ECC_BUF_SIZE);
+   zeromem(skey,          MAXBLOCKSIZE);
 #endif
+
+   XFREE(skey);
+   XFREE(shared_secret);
+
    return err;
 }
 
@@ -201,11 +245,11 @@
                         unsigned char *out, unsigned long *outlen, 
                         prng_state *prng, int wprng, ecc_key *key)
 {
-   ecc_key pubkey;
-   mp_int b, p;
-   unsigned char epubkey[256], er[256];
+   ecc_key       pubkey;
+   mp_int        b, p;
+   unsigned char *epubkey, *er;
    unsigned long x, y, pubkeysize, rsize;
-   int  err;
+   int           err;
 
    _ARGCHK(in     != NULL);
    _ARGCHK(out    != NULL);
@@ -231,17 +275,32 @@
       return err;
    }
 
-   pubkeysize = (unsigned long)sizeof(epubkey);
+   /* allocate ram */
+   epubkey = XMALLOC(ECC_BUF_SIZE);
+   er      = XMALLOC(ECC_BUF_SIZE);
+   if (epubkey == NULL || er == NULL) {
+      if (epubkey != NULL) {
+         XFREE(epubkey);
+      }
+      if (er != NULL) {
+         XFREE(er);
+      }
+      ecc_free(&pubkey);
+      return CRYPT_MEM;
+   }
+
+   pubkeysize = ECC_BUF_SIZE;
    if ((err = ecc_export(epubkey, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
       ecc_free(&pubkey);
-      return err;
+      goto __ERR;
    }
 
    /* get the hash and load it as a bignum into 'b' */
    /* init the bignums */
    if ((err = mp_init_multi(&b, &p, NULL)) != MP_OKAY) { 
       ecc_free(&pubkey);
-      return mpi_to_ltc_error(err);
+      err = mpi_to_ltc_error(err);
+      goto __ERR;
    }
    if ((err = mp_read_radix(&p, (char *)sets[key->idx].order, 64)) != MP_OKAY)        { goto error; }
    if ((err = mp_read_unsigned_bin(&b, (unsigned char *)in, (int)inlen)) != MP_OKAY)  { goto error; }
@@ -253,7 +312,7 @@
 
    /* export it */
    rsize = (unsigned long)mp_unsigned_bin_size(&b);
-   if (rsize > (unsigned long)sizeof(er)) { 
+   if (rsize > ECC_BUF_SIZE) { 
       err = CRYPT_BUFFER_OVERFLOW;
       goto error; 
    }
@@ -262,7 +321,7 @@
    /* now lets check the outlen before we write */
    if (*outlen < (12 + rsize + pubkeysize)) {
       err = CRYPT_BUFFER_OVERFLOW;
-      goto done;
+      goto __ERR;
    }
 
    /* lets output */
@@ -288,20 +347,24 @@
 
    /* store header */
    packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_SIGNED);
+   *outlen = y;
 
-   /* clear memory */
-   *outlen = y;
+   /* all ok */
    err = CRYPT_OK;
-   goto done;
+   goto __ERR;
 error:
    err = mpi_to_ltc_error(err);
-done:
+__ERR:
    mp_clear_multi(&b, &p, NULL);
    ecc_free(&pubkey);
 #ifdef CLEAN_STACK
-   zeromem(er, sizeof(er));
-   zeromem(epubkey, sizeof(epubkey));
+   zeromem(er,      ECC_BUF_SIZE);
+   zeromem(epubkey, ECC_BUF_SIZE);
 #endif
+
+   XFREE(epubkey);
+   XFREE(er);
+
    return err;   
 }
 
@@ -322,11 +385,11 @@
                     const unsigned char *hash, unsigned long inlen, 
                     int *stat, ecc_key *key)
 {
-   ecc_point *mG;
-   ecc_key   pubkey;
-   mp_int b, p, m, mu;
+   ecc_point    *mG;
+   ecc_key       pubkey;
+   mp_int        b, p, m, mu;
    unsigned long x, y;
-   int err;
+   int           err;
 
    _ARGCHK(sig  != NULL);
    _ARGCHK(hash != NULL);
--- a/examples/ch1-01.c	Tue Jun 15 14:07:21 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-/* 
- * Name      : ch1-01.c
- * Purpose   : Demonstration of a basic libtomcrypt program
- * Author    : Tom St Denis
- *
- * History   : v0.79 Initial release
- */
- 
-/* ch1-01-1  */
-/* Include the default headers and libtomcrypt headers */
-#include <mycrypt.h>
-
-int main(void)
-{
-   return 0;
-}
-/* ch1-01-1  */
-
--- a/examples/ch1-02.c	Tue Jun 15 14:07:21 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/* 
- * Name      : ch1-02.c
- * Purpose   : Demonstration of error handling
- * Author    : Tom St Denis
- *
- * History   : v0.79 Initial release
- */
- 
-/* ch1-01-1 */
-#include <mycrypt.h>
-
-int main(void)
-{
-   int errno;
-   
-   if ((errno = some_func(...)) != CRYPT_OK) {
-      printf("Error: %s\n", error_to_string(errno));
-      return EXIT_FAILURE;
-   }
-   
-   return 0;
-}
-/*ch1-01-1 */
-
-
--- a/examples/ch1-03.c	Tue Jun 15 14:07:21 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/* 
- * Name      : ch1-03.c
- * Purpose   : Demonstration of variable length outputs
- * Author    : Tom St Denis
- *
- * History   : v0.79 Initial release
- */
- 
- /* ch1-01-1 */
- #include <mycrypt.h>
- 
- int main(void)
- {
-    unsigned long length;
-    unsigned char buffer[512];
-    int errno;
-    
-    length = sizeof(buffer);
-    if ((errno = some_func(..., buffer, &length)) != CRYPT_OK) {
-       printf("Error: %s\n", error_to_string(errno));
-       return EXIT_FAILURE;
-    }
-    printf("Size of output is %lu bytes\n", length);
-    return 0;
-}
-/* ch1-01-1 */
-
-
-    
\ No newline at end of file
--- a/examples/ch2-01.c	Tue Jun 15 14:07:21 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/* 
- * Name      : ch2-01.c
- * Purpose   : Demonstration of reading the RNG
- * Author    : Tom St Denis
- *
- * History   : v0.81 Initial release
- */
- 
- /* ch2-02-2 */
- #include <mycrypt.h>
- 
- int main(void) 
- {
-    unsigned char buf[16];
-    unsigned long len;
-    int           ix;
-    
-    /* read the RNG */
-    len = rng_get_bytes(buf, sizeof(buf), NULL);
-    
-    /* verify return */
-    if (len != sizeof(buf)) {
-       printf("Error: Only read %lu bytes.\n", len);
-    } else {
-       printf("Read %lu bytes\n", len);
-       for (ix = 0; ix < sizeof(buf); ix++) {
-           printf("%02x ", buf[ix]);
-       }
-       printf("\n");
-    }
-    
-    return EXIT_SUCCESS;
-}
-/* ch2-02-2 */
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fortuna.c	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,335 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+
+/* Implementation of Fortuna by Tom St Denis 
+
+We deviate slightly here for reasons of simplicity [and to fit in the API].  First all "sources"
+in the AddEntropy function are fixed to 0.  Second since no reliable timer is provided 
+we reseed automatically when len(pool0) >= 64 or every FORTUNA_WD calls to the read function */
+
+#include "mycrypt.h"
+
+#ifdef FORTUNA 
+
+/* requries SHA256 and AES  */
+#if !(defined(RIJNDAEL) && defined(SHA256))
+   #error FORTUNA requires SHA256 and RIJNDAEL (AES)
+#endif
+
+#ifndef FORTUNA_POOLS
+   #warning FORTUNA_POOLS was not previously defined (old headers?)
+   #define FORTUNA_POOLS 32
+#endif
+
+#if FORTUNA_POOLS < 4 || FORTUNA_POOLS > 32
+   #error FORTUNA_POOLS must be in [4..32]
+#endif
+
+const struct _prng_descriptor fortuna_desc = {
+    "fortuna", 1024,
+    &fortuna_start,
+    &fortuna_add_entropy,
+    &fortuna_ready,
+    &fortuna_read,
+    &fortuna_done,
+    &fortuna_export,
+    &fortuna_import,
+    &fortuna_test
+};
+
+/* update the IV */
+static void fortuna_update_iv(prng_state *prng)
+{
+   int            x;
+   unsigned char *IV;
+   /* update IV */
+   IV = prng->fortuna.IV;
+   for (x = 0; x < 16; x++) {
+      IV[x] = (IV[x] + 1) & 255;
+      if (IV[x] != 0) break;
+   }
+}
+
+/* reseed the PRNG */
+static int fortuna_reseed(prng_state *prng)
+{
+   unsigned char tmp[MAXBLOCKSIZE];
+   hash_state    md;
+   int           err, x;
+
+   ++prng->fortuna.reset_cnt;
+
+   /* new K == SHA256(K || s) where s == SHA256(P0) || SHA256(P1) ... */
+   sha256_init(&md);
+   if ((err = sha256_process(&md, prng->fortuna.K, 32)) != CRYPT_OK) {
+      return err;
+   }
+
+   for (x = 0; x < FORTUNA_POOLS; x++) {
+       if (x == 0 || ((prng->fortuna.reset_cnt >> (x-1)) & 1) == 0) { 
+          /* terminate this hash */
+          if ((err = sha256_done(&prng->fortuna.pool[x], tmp)) != CRYPT_OK) {
+             return err; 
+          }
+          /* add it to the string */
+          if ((err = sha256_process(&md, tmp, 32)) != CRYPT_OK) {
+             return err;
+          }
+          /* reset this pool */
+          sha256_init(&prng->fortuna.pool[x]);
+       } else {
+          break;
+       }
+   }
+
+   /* finish key */
+   if ((err = sha256_done(&md, prng->fortuna.K)) != CRYPT_OK) {
+      return err; 
+   }
+   if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) {
+      return err;
+   }
+   fortuna_update_iv(prng);
+
+   /* reset pool len */
+   prng->fortuna.pool0_len = 0;
+   prng->fortuna.wd        = 0;
+
+
+#ifdef CLEAN_STACK
+   zeromem(&md, sizeof(md));
+   zeromem(tmp, sizeof(tmp));
+#endif
+
+   return CRYPT_OK;
+}
+
+int fortuna_start(prng_state *prng)
+{
+   int err, x;
+
+   _ARGCHK(prng != NULL);
+   
+   /* initialize the pools */
+   for (x = 0; x < FORTUNA_POOLS; x++) {
+       sha256_init(&prng->fortuna.pool[x]);
+   }
+   prng->fortuna.pool_idx = prng->fortuna.pool0_len = prng->fortuna.reset_cnt = 
+   prng->fortuna.wd = 0;
+
+   /* reset bufs */
+   zeromem(prng->fortuna.K, 32);
+   if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) {
+      return err;
+   }
+   zeromem(prng->fortuna.IV, 16);
+
+   return CRYPT_OK;
+}
+
+int fortuna_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
+{
+   unsigned char tmp[2];
+   int           err;
+
+   _ARGCHK(buf  != NULL);
+   _ARGCHK(prng != NULL);
+
+   /* ensure len <= 32 */
+   if (len > 32) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* add s || length(buf) || buf to pool[pool_idx] */
+   tmp[0] = 0;
+   tmp[1] = len;
+   if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], tmp, 2)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], buf, len)) != CRYPT_OK) {
+      return err;
+   }
+   if (prng->fortuna.pool_idx == 0) {
+      prng->fortuna.pool0_len += len;
+   }
+   if (++(prng->fortuna.pool_idx) == FORTUNA_POOLS) {
+      prng->fortuna.pool_idx = 0;
+   }
+
+   return CRYPT_OK;
+}
+
+int fortuna_ready(prng_state *prng)
+{
+   return fortuna_reseed(prng);
+}
+
+unsigned long fortuna_read(unsigned char *dst, unsigned long len, prng_state *prng)
+{
+   unsigned char tmp[16];
+   int           err;
+   unsigned long tlen;
+
+   _ARGCHK(dst  != NULL);
+   _ARGCHK(prng != NULL);
+
+   /* do we have to reseed? */
+   if (++prng->fortuna.wd == FORTUNA_WD || prng->fortuna.pool0_len >= 64) {
+      if ((err = fortuna_reseed(prng)) != CRYPT_OK) {
+         return 0;
+      }
+   }
+
+   /* now generate the blocks required */
+   tlen = len;
+
+   /* handle whole blocks without the extra memcpy */
+   while (len >= 16) {
+      /* encrypt the IV and store it */
+      rijndael_ecb_encrypt(prng->fortuna.IV, dst, &prng->fortuna.skey);
+      dst += 16;
+      len -= 16;
+      fortuna_update_iv(prng);
+   }
+
+   /* left over bytes? */
+   if (len > 0) {
+      rijndael_ecb_encrypt(prng->fortuna.IV, tmp, &prng->fortuna.skey);
+      XMEMCPY(dst, tmp, len);
+      fortuna_update_iv(prng);
+   }
+       
+   /* generate new key */
+   rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K   , &prng->fortuna.skey); fortuna_update_iv(prng);
+   rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K+16, &prng->fortuna.skey); fortuna_update_iv(prng);
+   if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) {
+      return 0;
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(tmp, sizeof(tmp));
+#endif
+   return tlen;
+}   
+
+int fortuna_done(prng_state *prng)
+{
+   int           err, x;
+   unsigned char tmp[32];
+
+   _ARGCHK(prng != NULL);
+
+   /* terminate all the hashes */
+   for (x = 0; x < FORTUNA_POOLS; x++) {
+       if ((err = sha256_done(&(prng->fortuna.pool[x]), tmp)) != CRYPT_OK) {
+          return err; 
+       }
+   }
+   /* call cipher done when we invent one ;-) */
+
+#ifdef CLEAN_STACK
+   zeromem(tmp, sizeof(tmp));
+#endif
+
+   return CRYPT_OK;
+}
+
+int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
+{
+   int         x, err;
+   hash_state *md;
+
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(prng   != NULL);
+
+   /* we'll write bytes for s&g's */
+   if (*outlen < 32*FORTUNA_POOLS) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   md = XMALLOC(sizeof(hash_state));
+   if (md == NULL) {
+      return CRYPT_MEM;
+   }
+
+   /* to emit the state we copy each pool, terminate it then hash it again so 
+    * an attacker who sees the state can't determine the current state of the PRNG 
+    */   
+   for (x = 0; x < FORTUNA_POOLS; x++) {
+      /* copy the PRNG */
+      XMEMCPY(md, &(prng->fortuna.pool[x]), sizeof(*md));
+
+      /* terminate it */
+      if ((err = sha256_done(md, out+x*32)) != CRYPT_OK) {
+         goto __ERR;
+      }
+
+      /* now hash it */
+      if ((err = sha256_init(md)) != CRYPT_OK) {
+         goto __ERR;
+      }
+      if ((err = sha256_process(md, out+x*32, 32)) != CRYPT_OK) {
+         goto __ERR;
+      }
+      if ((err = sha256_done(md, out+x*32)) != CRYPT_OK) {
+         goto __ERR;
+      }
+   }
+   *outlen = 32*FORTUNA_POOLS;
+   err = CRYPT_OK;
+
+__ERR:
+#ifdef CLEAN_STACK
+   zeromem(md, sizeof(*md));
+#endif
+   XFREE(md);
+   return err;
+}
+ 
+int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+   int err, x;
+
+   _ARGCHK(in   != NULL);
+   _ARGCHK(prng != NULL);
+
+   if (inlen != 32*FORTUNA_POOLS) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   if ((err = fortuna_start(prng)) != CRYPT_OK) {
+      return err;
+   }
+   for (x = 0; x < FORTUNA_POOLS; x++) {
+      if ((err = fortuna_add_entropy(in+x*32, 32, prng)) != CRYPT_OK) {
+         return err;
+      }
+   }
+   return err;
+}
+
+int fortuna_test(void)
+{
+#ifndef LTC_TEST
+   return CRYPT_NOP;
+#else
+   int err;
+
+   if ((err = sha256_test()) != CRYPT_OK) {
+      return err;
+   }
+   return rijndael_test();
+#endif
+}
+
+#endif
+
--- a/hash_filehandle.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/hash_filehandle.c	Sun Dec 19 11:34:45 2004 +0000
@@ -31,19 +31,23 @@
     if (*outlen < hash_descriptor[hash].hashsize) {
        return CRYPT_BUFFER_OVERFLOW;
     }
-    *outlen = hash_descriptor[hash].hashsize;
+    if ((err = hash_descriptor[hash].init(&md)) != CRYPT_OK) {
+       return err;
+    }
 
-    hash_descriptor[hash].init(&md);
+    *outlen = hash_descriptor[hash].hashsize;
     do {
         x = fread(buf, 1, sizeof(buf), in);
-        hash_descriptor[hash].process(&md, buf, x);
+        if ((err = hash_descriptor[hash].process(&md, buf, x)) != CRYPT_OK) {
+           return err;
+        }
     } while (x == sizeof(buf));
-    hash_descriptor[hash].done(&md, dst);
+    err = hash_descriptor[hash].done(&md, dst);
 
 #ifdef CLEAN_STACK
     zeromem(buf, sizeof(buf));
 #endif
-    return CRYPT_OK;
+    return err;
 #endif
 }
 
--- a/hash_memory.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/hash_memory.c	Sun Dec 19 11:34:45 2004 +0000
@@ -12,7 +12,7 @@
 
 int hash_memory(int hash, const unsigned char *data, unsigned long len, unsigned char *dst, unsigned long *outlen)
 {
-    hash_state md;
+    hash_state *md;
     int err;
 
     _ARGCHK(data   != NULL);
@@ -26,10 +26,25 @@
     if (*outlen < hash_descriptor[hash].hashsize) {
        return CRYPT_BUFFER_OVERFLOW;
     }
-    *outlen = hash_descriptor[hash].hashsize;
+
+    md = XMALLOC(sizeof(hash_state));
+    if (md == NULL) {
+       return CRYPT_MEM;
+    }
 
-    hash_descriptor[hash].init(&md);
-    hash_descriptor[hash].process(&md, data, len);
-    hash_descriptor[hash].done(&md, dst);
-    return CRYPT_OK;
+    if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) {
+       goto __ERR;
+    }
+    if ((err = hash_descriptor[hash].process(md, data, len)) != CRYPT_OK) {
+       goto __ERR;
+    }
+    err = hash_descriptor[hash].done(md, dst);
+    *outlen = hash_descriptor[hash].hashsize;
+__ERR:
+#ifdef CLEAN_STACK
+    zeromem(md, sizeof(hash_state));
+#endif
+    XFREE(md);
+
+    return err;
 }
--- a/hmac_done.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/hmac_done.c	Sun Dec 19 11:34:45 2004 +0000
@@ -35,14 +35,14 @@
 
 int hmac_done(hmac_state *hmac, unsigned char *hashOut, unsigned long *outlen)
 {
-    unsigned char buf[MAXBLOCKSIZE];
-    unsigned char isha[MAXBLOCKSIZE];
+    unsigned char *buf, *isha;
     unsigned long hashsize, i;
     int hash, err;
 
-    _ARGCHK(hmac != NULL);
+    _ARGCHK(hmac    != NULL);
     _ARGCHK(hashOut != NULL);
 
+    /* test hash */
     hash = hmac->hash;
     if((err = hash_is_valid(hash)) != CRYPT_OK) {
         return err;
@@ -51,34 +51,62 @@
     /* get the hash message digest size */
     hashsize = hash_descriptor[hash].hashsize;
 
-    // Get the hash of the first HMAC vector plus the data
-    if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) {
-       return err;
+    /* allocate buffers */
+    buf  = XMALLOC(HMAC_BLOCKSIZE);
+    isha = XMALLOC(hashsize);
+    if (buf == NULL || isha == NULL) { 
+       if (buf != NULL) {
+          XFREE(buf);
+       } 
+       if (isha != NULL) {
+          XFREE(isha);
+       }  
+       return CRYPT_MEM;
     }
 
-    // Create the second HMAC vector vector for step (3)
+    /* Get the hash of the first HMAC vector plus the data */
+    if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) {
+       goto __ERR;
+    }
+
+    /* Create the second HMAC vector vector for step (3) */
     for(i=0; i < HMAC_BLOCKSIZE; i++) {
         buf[i] = hmac->key[i] ^ 0x5C;
     }
 
-    // Now calculate the "outer" hash for step (5), (6), and (7)
-    hash_descriptor[hash].init(&hmac->md);
-    hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE);
-    hash_descriptor[hash].process(&hmac->md, isha, hashsize);
-    hash_descriptor[hash].done(&hmac->md, buf);
+    /* Now calculate the "outer" hash for step (5), (6), and (7) */
+    if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) {
+       goto __ERR;
+    }
+    if ((err = hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE)) != CRYPT_OK) {
+       goto __ERR;
+    }
+    if ((err = hash_descriptor[hash].process(&hmac->md, isha, hashsize)) != CRYPT_OK) {
+       goto __ERR;
+    }
+    if ((err = hash_descriptor[hash].done(&hmac->md, buf)) != CRYPT_OK) {
+       goto __ERR;
+    }
 
-    // copy to output 
+    /* copy to output  */
     for (i = 0; i < hashsize && i < *outlen; i++) {
         hashOut[i] = buf[i];
     }
     *outlen = i;
 
+    err = CRYPT_OK;
+__ERR:
+    XFREE(hmac->key);
 #ifdef CLEAN_STACK
-    zeromem(isha, sizeof(buf));
-    zeromem(buf,  sizeof(isha));
+    zeromem(isha, hashsize);
+    zeromem(buf,  hashsize);
     zeromem(hmac, sizeof(*hmac));
 #endif
-    return CRYPT_OK;
+
+    XFREE(isha);
+    XFREE(buf);
+
+    return err;
 }
 
 #endif
--- a/hmac_file.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/hmac_file.c	Sun Dec 19 11:34:45 2004 +0000
@@ -12,27 +12,8 @@
 
 #include "mycrypt.h"
 
-/*
-    (1) append zeros to the end of K to create a B byte string
-        (e.g., if K is of length 20 bytes and B=64, then K will be
-         appended with 44 zero bytes 0x00)
-    (2) XOR (bitwise exclusive-OR) the B byte string computed in step
-        (1) with ipad (ipad = the byte 0x36 repeated B times)
-    (3) append the stream of data 'text' to the B byte string resulting
-        from step (2)
-    (4) apply H to the stream generated in step (3)
-    (5) XOR (bitwise exclusive-OR) the B byte string computed in
-        step (1) with opad (opad = the byte 0x5C repeated B times.)
-    (6) append the H result from step (4) to the B byte string
-        resulting from step (5)
-    (7) apply H to the stream generated in step (6) and output
-        the result
-*/
-
 #ifdef HMAC
 
-#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
-
 /* hmac_file added by Tom St Denis */
 int hmac_file(int hash, const char *fname, 
               const unsigned char *key, unsigned long keylen, 
--- a/hmac_init.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/hmac_init.c	Sun Dec 19 11:34:45 2004 +0000
@@ -35,53 +35,80 @@
 
 int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen)
 {
-    unsigned char buf[MAXBLOCKSIZE];
+    unsigned char *buf;
     unsigned long hashsize;
     unsigned long i, z;
     int err;
 
     _ARGCHK(hmac != NULL);
-    _ARGCHK(key != NULL);
+    _ARGCHK(key  != NULL);
 
+    /* valid hash? */
     if ((err = hash_is_valid(hash)) != CRYPT_OK) {
         return err;
     }
+    hmac->hash = hash;
+    hashsize   = hash_descriptor[hash].hashsize;
 
     /* valid key length? */
     if (keylen == 0) {
         return CRYPT_INVALID_KEYSIZE;
     }
 
-    hmac->hash = hash;
+    /* allocate ram for buf */
+    buf = XMALLOC(HMAC_BLOCKSIZE);
+    if (buf == NULL) {
+       return CRYPT_MEM;
+    }
 
-    // (1) make sure we have a large enough key
-    hashsize = hash_descriptor[hash].hashsize;
+    /* allocate memory for key */
+    hmac->key = XMALLOC(HMAC_BLOCKSIZE);
+    if (hmac->key == NULL) {
+       XFREE(buf);
+       return CRYPT_MEM;
+    }
+
+    /* (1) make sure we have a large enough key */
     if(keylen > HMAC_BLOCKSIZE) {
-        z = (unsigned long)sizeof(hmac->key);
+        z = HMAC_BLOCKSIZE;
         if ((err = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) {
-           return err;
+           goto __ERR;
         }
         if(hashsize < HMAC_BLOCKSIZE) {
             zeromem((hmac->key) + hashsize, (size_t)(HMAC_BLOCKSIZE - hashsize));
         }
         keylen = hashsize;
     } else {
-        memcpy(hmac->key, key, (size_t)keylen);
+        XMEMCPY(hmac->key, key, (size_t)keylen);
         if(keylen < HMAC_BLOCKSIZE) {
             zeromem((hmac->key) + keylen, (size_t)(HMAC_BLOCKSIZE - keylen));
         }
     }
 
-    // Create the initial vector for step (3)
+    /* Create the initial vector for step (3) */
     for(i=0; i < HMAC_BLOCKSIZE;   i++) {
        buf[i] = hmac->key[i] ^ 0x36;
     }
 
-    // Pre-pend that to the hash data
-    hash_descriptor[hash].init(&hmac->md);
-    hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE);
+    /* Pre-pend that to the hash data */
+    if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) {
+       goto __ERR;
+    }
 
-    return CRYPT_OK;
+    if ((err = hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE)) != CRYPT_OK) {
+       goto __ERR;
+    }
+    goto done;
+__ERR:
+    /* free the key since we failed */
+    XFREE(hmac->key);
+done:
+#ifdef CLEAN_STACK
+   zeromem(buf, HMAC_BLOCKSIZE);
+#endif
+ 
+   XFREE(buf);
+   return err;    
 }
 
 #endif
--- a/hmac_memory.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/hmac_memory.c	Sun Dec 19 11:34:45 2004 +0000
@@ -12,55 +12,46 @@
 
 #include "mycrypt.h"
 
-/*
-    (1) append zeros to the end of K to create a B byte string
-        (e.g., if K is of length 20 bytes and B=64, then K will be
-         appended with 44 zero bytes 0x00)
-    (2) XOR (bitwise exclusive-OR) the B byte string computed in step
-        (1) with ipad (ipad = the byte 0x36 repeated B times)
-    (3) append the stream of data 'text' to the B byte string resulting
-        from step (2)
-    (4) apply H to the stream generated in step (3)
-    (5) XOR (bitwise exclusive-OR) the B byte string computed in
-        step (1) with opad (opad = the byte 0x5C repeated B times.)
-    (6) append the H result from step (4) to the B byte string
-        resulting from step (5)
-    (7) apply H to the stream generated in step (6) and output
-        the result
-*/
-
 #ifdef HMAC
 
-#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
-
 int hmac_memory(int hash, const unsigned char *key, unsigned long keylen,
                 const unsigned char *data, unsigned long len, 
                 unsigned char *dst, unsigned long *dstlen)
 {
-    hmac_state hmac;
+    hmac_state *hmac;
     int err;
 
     _ARGCHK(key    != NULL);
     _ARGCHK(data   != NULL);
     _ARGCHK(dst    != NULL); 
     _ARGCHK(dstlen != NULL);
-    
-    if((err = hash_is_valid(hash)) != CRYPT_OK) {
-        return err;
+
+    /* allocate ram for hmac state */
+    hmac = XMALLOC(sizeof(hmac_state));
+    if (hmac == NULL) {
+       return CRYPT_MEM;
     }
 
-    if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) {
-        return err;
+    if ((err = hmac_init(hmac, hash, key, keylen)) != CRYPT_OK) {
+       goto __ERR;
     }
 
-    if ((err = hmac_process(&hmac, data, len)) != CRYPT_OK) {
-       return err;
+    if ((err = hmac_process(hmac, data, len)) != CRYPT_OK) {
+       goto __ERR;
+    }
+
+    if ((err = hmac_done(hmac, dst, dstlen)) != CRYPT_OK) {
+       goto __ERR;
     }
 
-    if ((err = hmac_done(&hmac, dst, dstlen)) != CRYPT_OK) {
-       return err;
-    }
-    return CRYPT_OK;
+   err = CRYPT_OK;
+__ERR:
+#ifdef CLEAN_STACK
+   zeromem(hmac, sizeof(hmac_state));
+#endif
+
+   XFREE(hmac);
+   return err;   
 }
 
 #endif
--- a/hmac_process.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/hmac_process.c	Sun Dec 19 11:34:45 2004 +0000
@@ -12,27 +12,8 @@
 
 #include "mycrypt.h"
 
-/*
-    (1) append zeros to the end of K to create a B byte string
-        (e.g., if K is of length 20 bytes and B=64, then K will be
-         appended with 44 zero bytes 0x00)
-    (2) XOR (bitwise exclusive-OR) the B byte string computed in step
-        (1) with ipad (ipad = the byte 0x36 repeated B times)
-    (3) append the stream of data 'text' to the B byte string resulting
-        from step (2)
-    (4) apply H to the stream generated in step (3)
-    (5) XOR (bitwise exclusive-OR) the B byte string computed in
-        step (1) with opad (opad = the byte 0x5C repeated B times.)
-    (6) append the H result from step (4) to the B byte string
-        resulting from step (5)
-    (7) apply H to the stream generated in step (6) and output
-        the result
-*/
-
 #ifdef HMAC
 
-#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
-
 int hmac_process(hmac_state *hmac, const unsigned char *buf, unsigned long len)
 {
     int err;
--- a/hmac_test.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/hmac_test.c	Sun Dec 19 11:34:45 2004 +0000
@@ -285,12 +285,13 @@
         outlen = sizeof(digest);
         if((err = hmac_memory(hash, cases[i].key, cases[i].keylen, cases[i].data, cases[i].datalen, digest, &outlen)) != CRYPT_OK) {
 #if 0
-            printf("HMAC-%s test #%d\n", cases[i].algo, cases[i].num);
+            printf("HMAC-%s test #%d, %s\n", cases[i].algo, cases[i].num, error_to_string(err));
 #endif
             return err;
         }
 
         if(memcmp(digest, cases[i].digest, (size_t)hash_descriptor[hash].hashsize) != 0)  {
+            failed++;
 #if 0
             unsigned int j;
             printf("\nHMAC-%s test #%d:\n", cases[i].algo, cases[i].num);
@@ -303,9 +304,8 @@
                printf("%2x ", cases[i].digest[j]);
             }
             printf("\n");
+            return CRYPT_ERROR;
 #endif
-            failed++;
-            //return CRYPT_ERROR;
         } else {
             /* printf("HMAC-%s test #%d: Passed\n", cases[i].algo, cases[i].num); */
         }
--- a/ltc_tommath.h	Tue Jun 15 14:07:21 2004 +0000
+++ b/ltc_tommath.h	Sun Dec 19 11:34:45 2004 +0000
@@ -21,6 +21,8 @@
 #include <ctype.h>
 #include <limits.h>
 
+#include <tommath_class.h>
+
 #undef MIN
 #define MIN(x,y) ((x)<(y)?(x):(y))
 #undef MAX
@@ -39,6 +41,14 @@
 
 #endif
 
+
+/* detect 64-bit mode if possible */
+#if defined(__x86_64__) 
+   #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT))
+      #define MP_64BIT
+   #endif
+#endif
+
 /* some default configurations.
  *
  * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
@@ -60,7 +70,7 @@
    typedef signed long long   long64;
 #endif
 
-   typedef ulong64            mp_digit;
+   typedef unsigned long      mp_digit;
    typedef unsigned long      mp_word __attribute__ ((mode(TI)));
 
    #define DIGIT_BIT          60
@@ -153,7 +163,7 @@
 
 /* default precision */
 #ifndef MP_PREC
-   #ifdef MP_LOW_MEM
+   #ifndef MP_LOW_MEM
       #define MP_PREC                 64     /* default digits of precision */
    #else
       #define MP_PREC                 8      /* default digits of precision */
@@ -541,6 +551,7 @@
 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 mp_invmod_slow (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);
--- a/makefile	Tue Jun 15 14:07:21 2004 +0000
+++ b/makefile	Sun Dec 19 11:34:45 2004 +0000
@@ -2,14 +2,9 @@
 #
 # Tom St Denis
 # Modified by Clay Culver
-#
-# NOTE: This should later be replaced by autoconf/automake scripts, but for
-# the time being this is actually pretty clean. The only ugly part is
-# handling CFLAGS so that the x86 specific optimizations don't break
-# a build. This is easy to remedy though, for those that have problems.
 
 # The version
-VERSION=0.96
+VERSION=0.99
 
 # Compiler and Linker Names
 #CC=gcc
@@ -24,17 +19,16 @@
 # -Werror
 
 # optimize for SPEED
-#CFLAGS += -O3 -funroll-loops
+#CFLAGS += -O3 -funroll-all-loops
 
-#add -fomit-frame-pointer.  GCC v3.2 is buggy for certain platforms!
-CFLAGS += -fomit-frame-pointer
+#add -fomit-frame-pointer.  hinders debugging!
+#CFLAGS += -fomit-frame-pointer
 
 # optimize for SIZE
-CFLAGS += -Os
+CFLAGS += -Os -DSMALL_CODE
 
-# compile for DEBUGING
+# compile for DEBUGING (required for ccmalloc checking!!!)
 #CFLAGS += -g3
-#ch1-01-3
 
 #These flags control how the library gets built.
 
@@ -69,7 +63,7 @@
 crypt_unregister_cipher.o  crypt_cipher_is_valid.o  crypt_find_hash.o          \
 crypt_hash_descriptor.o    crypt_register_cipher.o  crypt_unregister_hash.o    \
 \
-sprng.o yarrow.o rc4.o rng_get_bytes.o  rng_make_prng.o \
+sober128.o fortuna.o sprng.o yarrow.o rc4.o rng_get_bytes.o  rng_make_prng.o \
 \
 rand_prime.o is_prime.o \
 \
@@ -77,6 +71,7 @@
 \
 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 \
+rsa_v15_encrypt_key.o rsa_v15_decrypt_key.o rsa_v15_sign_hash.o rsa_v15_verify_hash.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 \
@@ -87,7 +82,7 @@
 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 \
+rmd128.o rmd160.o chc.o \
 \
 packet_store_header.o  packet_valid_header.o \
 \
@@ -119,7 +114,11 @@
 \
 pkcs_5_1.o pkcs_5_2.o \
 \
+der_encode_integer.o der_decode_integer.o der_length_integer.o \
+der_put_multi_integer.o der_get_multi_integer.o \
+\
 burn_stack.o zeromem.o \
+\
 $(MPIOBJECT)
 
 TESTOBJECTS=demos/test.o
@@ -139,7 +138,7 @@
 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
+mycrypt_custom.h mycrypt_pkcs.h tommath_class.h tommath_superclass.h
 
 #The default rule for make builds the libtomcrypt library.
 default:library
@@ -147,8 +146,11 @@
 #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.
+aes.o: aes.c aes_tab.c
+twofish.o: twofish.c twofish_tab.c
+whirl.o: whirl.c whirltab.c
 ecc.o: ecc.c ecc_sys.c
 dh.o: dh.c dh_sys.c
 sha512.o: sha512.c sha384.c
@@ -173,10 +175,10 @@
 	$(CC) $(SMALLOBJECTS) $(LIBNAME) -o $(SMALL) $(WARN)
 	
 x86_prof: library $(PROFS)
-	$(CC) $(PROFS) $(LIBNAME) -o $(PROF)
+	$(CC) $(PROFS) $(LIBNAME) $(EXTRALIBS) -o $(PROF)
 
 tv_gen: library $(TVS)
-	$(CC) $(TVS) $(LIBNAME) -o $(TV)
+	$(CC) $(TVS) $(LIBNAME) $(EXTRALIBS) -o $(TV)
 
 #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
@@ -189,15 +191,22 @@
 	install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH)
 	install -g root -o root doc/crypt.pdf $(DESTDIR)$(DATAPATH)
 
+install_lib: library
+	install -d -g root -o root $(DESTDIR)$(LIBPATH)
+	install -d -g root -o root $(DESTDIR)$(INCPATH)
+	install -g root -o root $(LIBNAME) $(DESTDIR)$(LIBPATH)
+	install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH)
+
 #This rule cleans the source tree of all compiled code, not including the pdf
 #documentation.
 clean:
 	rm -f $(OBJECTS) $(TESTOBJECTS) $(HASHOBJECTS) $(CRYPTOBJECTS) $(SMALLOBJECTS) $(LEFTOVERS) $(LIBNAME)
 	rm -f $(TEST) $(HASH) $(COMPRESSED) $(PROFS) $(PROF) $(TVS) $(TV)
-	rm -f *.a *.dll *stackdump *.lib *.exe *.obj demos/*.obj demos/*.o *.bat *.txt *.il *.da demos/*.il demos/*.da *.dyn *.dpi \
-         *.gcda *.gcno demos/*.gcno demos/*.gcda *~ doc/*
+	rm -f *.la *.lo *.o *.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 *~ doc/*
 	cd demos/test ; make clean   
-
+	rm -rf .libs demos/.libs demos/test/.libs
+	
 #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
@@ -206,8 +215,8 @@
 	rm -f doc/crypt.pdf $(LEFTOVERS)
 	echo "hello" > crypt.ind
 	latex crypt > /dev/null
-	makeindex crypt > /dev/null
 	latex crypt > /dev/null
+	makeindex crypt.idx > /dev/null
 	latex crypt > /dev/null
 	dvipdf crypt
 	mv -ivf crypt.pdf doc/crypt.pdf
@@ -217,19 +226,24 @@
 	echo hello > crypt.ind
 	latex crypt > /dev/null
 	latex crypt > /dev/null
-	makeindex crypt
+	makeindex crypt.idx
 	latex crypt > /dev/null
 
-#beta
-beta: clean
-	cd .. ; rm -rf crypt* libtomcrypt-$(VERSION)-beta ; mkdir libtomcrypt-$(VERSION)-beta ; \
-	cp -R ./libtomcrypt/* ./libtomcrypt-$(VERSION)-beta/ ; tar -c libtomcrypt-$(VERSION)-beta/* > crypt-$(VERSION)-beta.tar ; \
-	bzip2 -9vv crypt-$(VERSION)-beta.tar ; zip -9 -r crypt-$(VERSION)-beta.zip libtomcrypt-$(VERSION)-beta/*
+#pretty build
+pretty:
+	perl pretty.build
+
+#for GCC 3.4+
+profiled:
+	make clean
+	make CFLAGS="$(CFLAGS) -fprofile-generate" EXTRALIBS=-lgcov x86_prof
+	./x86_prof
+	rm *.o *.a x86_prof
+	make CFLAGS="$(CFLAGS) -fprofile-use" EXTRALIBS=-lgcov x86_prof
 
 #zipup the project (take that!)
 zipup: clean docs
 	cd .. ; rm -rf crypt* libtomcrypt-$(VERSION) ; mkdir libtomcrypt-$(VERSION) ; \
 	cp -R ./libtomcrypt/* ./libtomcrypt-$(VERSION)/ ; tar -c libtomcrypt-$(VERSION)/* > crypt-$(VERSION).tar ; \
 	bzip2 -9vv crypt-$(VERSION).tar ; zip -9 -r crypt-$(VERSION).zip libtomcrypt-$(VERSION)/* ; \
-	gpg -b -a crypt-$(VERSION).tar.bz2 ; \
-   gpg -b -a crypt-$(VERSION).zip
+	gpg -b -a crypt-$(VERSION).tar.bz2 ; gpg -b -a crypt-$(VERSION).zip
--- a/makefile.cygwin_dll	Tue Jun 15 14:07:21 2004 +0000
+++ b/makefile.cygwin_dll	Sun Dec 19 11:34:45 2004 +0000
@@ -7,13 +7,13 @@
 CFLAGS += -I./ -Wall -Wsign-compare -W -Wno-unused -Wshadow -mno-cygwin -DWIN32
 
 # optimize for SPEED
-#CFLAGS += -O3 -funroll-loops
+CFLAGS += -O3 -funroll-all-loops
 
 #add -fomit-frame-pointer.  v3.2 is buggy for certain platforms!
-#CFLAGS += -fomit-frame-pointer
+CFLAGS += -fomit-frame-pointer
 
 # optimize for SIZE
-CFLAGS += -Os
+#CFLAGS += -Os
 
 #Leave MPI built-in or force developer to link against libtommath?
 MPIOBJECT=mpi.o
@@ -28,7 +28,7 @@
 crypt_unregister_cipher.o  crypt_cipher_is_valid.o  crypt_find_hash.o          \
 crypt_hash_descriptor.o    crypt_register_cipher.o  crypt_unregister_hash.o    \
 \
-sprng.o yarrow.o rc4.o rng_get_bytes.o  rng_make_prng.o \
+sober128.o fortuna.o sprng.o yarrow.o rc4.o rng_get_bytes.o  rng_make_prng.o \
 \
 rand_prime.o is_prime.o \
 \
@@ -36,6 +36,7 @@
 \
 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 \
+rsa_v15_encrypt_key.o rsa_v15_decrypt_key.o rsa_v15_sign_hash.o rsa_v15_verify_hash.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 \
@@ -46,7 +47,7 @@
 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 \
+rmd128.o rmd160.o chc.o \
 \
 packet_store_header.o  packet_valid_header.o \
 \
@@ -78,7 +79,11 @@
 \
 pkcs_5_1.o pkcs_5_2.o \
 \
+der_encode_integer.o der_decode_integer.o der_length_integer.o \
+der_put_multi_integer.o der_get_multi_integer.o \
+\
 burn_stack.o zeromem.o \
+\
 $(MPIOBJECT)
 
 #ciphers come in two flavours... enc+dec and enc 
--- a/makefile.icc	Tue Jun 15 14:07:21 2004 +0000
+++ b/makefile.icc	Sun Dec 19 11:34:45 2004 +0000
@@ -41,7 +41,7 @@
 #   B - Blend of P4 and PM [mobile]
 #
 # Default to just generic max opts
-CFLAGS += -O3 -xN -ip
+CFLAGS += -O3 -xN -ip 
 
 # want to see stuff?
 #CFLAGS += -opt_report
@@ -79,7 +79,7 @@
 crypt_unregister_cipher.o  crypt_cipher_is_valid.o  crypt_find_hash.o          \
 crypt_hash_descriptor.o    crypt_register_cipher.o  crypt_unregister_hash.o    \
 \
-sprng.o yarrow.o rc4.o rng_get_bytes.o  rng_make_prng.o \
+sober128.o fortuna.o sprng.o yarrow.o rc4.o rng_get_bytes.o  rng_make_prng.o \
 \
 rand_prime.o is_prime.o \
 \
@@ -87,6 +87,7 @@
 \
 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 \
+rsa_v15_encrypt_key.o rsa_v15_decrypt_key.o rsa_v15_sign_hash.o rsa_v15_verify_hash.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 \
@@ -97,7 +98,7 @@
 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 \
+rmd128.o rmd160.o chc.o \
 \
 packet_store_header.o  packet_valid_header.o \
 \
@@ -129,7 +130,11 @@
 \
 pkcs_5_1.o pkcs_5_2.o \
 \
+der_encode_integer.o der_decode_integer.o der_length_integer.o \
+der_put_multi_integer.o der_get_multi_integer.o \
+\
 burn_stack.o zeromem.o \
+\
 $(MPIOBJECT)
 
 
@@ -150,7 +155,7 @@
 COMPRESSED=crypt.tar.bz2 crypt.zip crypt.tar.gz
 
 #Header files used by libtomcrypt.
-HEADERS=tommath.h mycrypt_cfg.h mycrypt_gf.h mycrypt_kr.h \
+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
 
@@ -187,6 +192,13 @@
 tv_gen: library $(TVS)
 	$(CC) $(TVS) $(LIBNAME) -o $(TV)
 
+profiled:
+	make clean
+	make CFLAGS="$(CFLAGS) -prof_gen" x86_prof
+	./x86_prof
+	rm *.o *.a x86_prof
+	make CFLAGS="$(CFLAGS) -prof_use" x86_prof
+
   
 #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
--- a/makefile.msvc	Tue Jun 15 14:07:21 2004 +0000
+++ b/makefile.msvc	Sun Dec 19 11:34:45 2004 +0000
@@ -18,7 +18,7 @@
 crypt_unregister_cipher.obj  crypt_cipher_is_valid.obj  crypt_find_hash.obj          \
 crypt_hash_descriptor.obj    crypt_register_cipher.obj  crypt_unregister_hash.obj    \
 \
-sprng.obj yarrow.obj rc4.obj rng_get_bytes.obj  rng_make_prng.obj \
+sober128.obj fortuna.obj sprng.obj yarrow.obj rc4.obj rng_get_bytes.obj  rng_make_prng.obj \
 \
 rand_prime.obj is_prime.obj \
 \
@@ -26,6 +26,7 @@
 \
 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 \
+rsa_v15_encrypt_key.obj rsa_v15_decrypt_key.obj rsa_v15_sign_hash.obj rsa_v15_verify_hash.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 \
@@ -36,7 +37,7 @@
 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 \
+rmd128.obj rmd160.obj chc.obj \
 \
 packet_store_header.obj  packet_valid_header.obj \
 \
@@ -68,7 +69,11 @@
 \
 pkcs_5_1.obj pkcs_5_2.obj \
 \
+der_encode_integer.obj der_decode_integer.obj der_length_integer.obj \
+der_put_multi_integer.obj der_get_multi_integer.obj \
+\
 burn_stack.obj zeromem.obj \
+\
 $(MPIOBJECT)
 
 #ciphers come in two flavours... enc+dec and enc 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/makefile.shared	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,186 @@
+# MAKEFILE for linux GCC
+#
+# Tom St Denis
+# Modified by Clay Culver
+
+# The version
+VERSION=0:99
+
+# Compiler and Linker Names
+CC=libtool --mode=compile gcc
+
+# Archiver [makes .a files]
+AR=libtool --mode=link 
+
+# Compilation flags. Note the += does not write over the user's CFLAGS!
+CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wshadow 
+# -Werror
+
+# optimize for SPEED
+CFLAGS += -O3 -funroll-all-loops
+
+#add -fomit-frame-pointer.  hinders debugging!
+CFLAGS += -fomit-frame-pointer
+
+# optimize for SIZE
+#CFLAGS += -Os
+
+# compile for DEBUGING (required for ccmalloc checking!!!)
+#CFLAGS += -g3
+
+#These flags control how the library gets built.
+
+#Output filenames for various targets.
+LIBNAME=libtomcrypt.la
+HASH=hashsum
+CRYPT=encrypt
+SMALL=small
+PROF=x86_prof
+TV=tv_gen
+
+#LIBPATH-The directory for libtomcrypt to be installed to.
+#INCPATH-The directory to install the header files for libtomcrypt.
+#DATAPATH-The directory to install the pdf docs.
+DESTDIR=
+LIBPATH=/usr/lib
+INCPATH=/usr/include
+DATAPATH=/usr/share/doc/libtomcrypt/pdf
+
+#List of objects to compile.
+
+#Leave MPI built-in or force developer to link against libtommath?
+MPIOBJECT=mpi.o
+
+#If you don't want mpi.o then add this
+#MPISHARED=$(LIBPATH)/libtommath.la
+
+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    \
+crypt_argchk.o             crypt_find_cipher_any.o  crypt_find_hash_id.o       \
+crypt_prng_descriptor.o    crypt_register_prng.o    crypt_cipher_descriptor.o  \
+crypt_find_cipher_id.o     crypt_find_prng.o        crypt_prng_is_valid.o      \
+crypt_unregister_cipher.o  crypt_cipher_is_valid.o  crypt_find_hash.o          \
+crypt_hash_descriptor.o    crypt_register_cipher.o  crypt_unregister_hash.o    \
+\
+sober128.o fortuna.o sprng.o yarrow.o rc4.o rng_get_bytes.o  rng_make_prng.o \
+\
+rand_prime.o is_prime.o \
+\
+ecc.o  dh.o \
+\
+rsa_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 \
+rsa_v15_encrypt_key.o rsa_v15_decrypt_key.o rsa_v15_sign_hash.o rsa_v15_verify_hash.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 \
+\
+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 chc.o \
+\
+packet_store_header.o  packet_valid_header.o \
+\
+eax_addheader.o  eax_decrypt.o  eax_decrypt_verify_memory.o  eax_done.o  eax_encrypt.o  \
+eax_encrypt_authenticate_memory.o  eax_init.o  eax_test.o \
+\
+ocb_decrypt.o  ocb_decrypt_verify_memory.o  ocb_done_decrypt.o  ocb_done_encrypt.o  \
+ocb_encrypt.o  ocb_encrypt_authenticate_memory.o  ocb_init.o  ocb_ntz.o  \
+ocb_shift_xor.o  ocb_test.o s_ocb_done.o \
+\
+omac_done.o  omac_file.o  omac_init.o  omac_memory.o  omac_process.o  omac_test.o \
+\
+pmac_done.o  pmac_file.o  pmac_init.o  pmac_memory.o  pmac_ntz.o  pmac_process.o  \
+pmac_shift_xor.o  pmac_test.o \
+\
+cbc_start.o cbc_encrypt.o cbc_decrypt.o 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 \
+\
+hmac_done.o  hmac_file.o  hmac_init.o  hmac_memory.o  hmac_process.o  hmac_test.o \
+\
+pkcs_1_mgf1.o pkcs_1_oaep_encode.o pkcs_1_oaep_decode.o  \
+pkcs_1_pss_encode.o pkcs_1_pss_decode.o pkcs_1_i2osp.o pkcs_1_os2ip.o \
+pkcs_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 \
+\
+der_encode_integer.o der_decode_integer.o der_length_integer.o \
+der_put_multi_integer.o der_get_multi_integer.o \
+\
+burn_stack.o zeromem.o \
+\
+$(MPIOBJECT)
+
+TESTOBJECTS=demos/test.o
+HASHOBJECTS=demos/hashsum.o
+CRYPTOBJECTS=demos/encrypt.o
+SMALLOBJECTS=demos/small.o
+PROFS=demos/x86_prof.o
+TVS=demos/tv_gen.o
+
+#Files left over from making the crypt.pdf.
+LEFTOVERS=*.dvi *.log *.aux *.toc *.idx *.ilg *.ind *.out
+
+#Compressed filenames
+COMPRESSED=crypt-$(VERSION).tar.bz2 crypt-$(VERSION).zip
+
+#Header files used by libtomcrypt.
+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 tommath_class.h tommath_superclass.h
+
+#The default rule for make builds the libtomcrypt library.
+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.
+aes.o: aes.c aes_tab.c
+twofish.o: twofish.c twofish_tab.c
+whirl.o: whirl.c whirltab.c
+ecc.o: ecc.c ecc_sys.c
+dh.o: dh.c dh_sys.c
+sha512.o: sha512.c sha384.c
+sha256.o: sha256.c sha224.c
+
+#This rule makes the libtomcrypt library.
+library: $(LIBNAME)
+
+$(LIBNAME): $(OBJECTS)
+	libtool --mode=link gcc $(CFLAGS) *.lo -o libtomcrypt.la -rpath $(LIBPATH) -version-info $(VERSION)
+	libtool --mode=link gcc $(CFLAGS) *.o  -o libtomcrypt.a
+	libtool --mode=install install -c libtomcrypt.la $(LIBPATH)/libtomcrypt.la
+	install -d -g root -o root $(DESTDIR)$(INCPATH)
+	install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH)
+
+#This rule makes the hash program included with libtomcrypt
+hashsum: library
+	gcc $(CFLAGS) demos/hashsum.c -o hashsum.o
+	libtool --mode=link gcc -o hashsum hashsum.o -ltomcrypt $(MPISHARED)
+
+#makes the crypt program
+crypt: library 
+	gcc $(CFLAGS) demos/encrypt.c -o encrypt.o
+	libtool --mode=link gcc -o crypt encrypt.o -ltomcrypt $(MPISHARED)
+
+x86_prof: library
+	gcc $(CFLAGS) demos/x86_prof.c -o x86_prof.o
+	libtool --mode=link gcc -o x86_prof x86_prof.o -ltomcrypt $(MPISHARED) $(EXTRALIBS)
+
+tv_gen: library $(TVS)
+	gcc $(CFLAGS) demos/tv_gen.c -o tv_gen.o
+	libtool --mode=link gcc -o tv_gen tv_gen.o -ltomcrypt $(MPISHARED)
--- a/md2.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/md2.c	Sun Dec 19 11:34:45 2004 +0000
@@ -90,7 +90,7 @@
    }
 }
 
-void md2_init(hash_state *md)
+int md2_init(hash_state *md)
 {
    _ARGCHK(md != NULL);
 
@@ -99,6 +99,7 @@
    zeromem(md->md2.chksum, sizeof(md->md2.chksum));
    zeromem(md->md2.buf, sizeof(md->md2.buf));
    md->md2.curlen = 0;
+   return CRYPT_OK;
 }
 
 int md2_process(hash_state *md, const unsigned char *buf, unsigned long len)
@@ -111,7 +112,7 @@
     }                                                                                       
     while (len > 0) {
         n = MIN(len, (16 - md->md2.curlen));
-        memcpy(md->md2.buf + md->md2.curlen, buf, (size_t)n);
+        XMEMCPY(md->md2.buf + md->md2.curlen, buf, (size_t)n);
         md->md2.curlen += n;
         buf            += n;
         len            -= n;
@@ -149,11 +150,11 @@
     md2_update_chksum(md);
 
     /* hash checksum */
-    memcpy(md->md2.buf, md->md2.chksum, 16);
+    XMEMCPY(md->md2.buf, md->md2.chksum, 16);
     md2_compress(md);
 
     /* output is lower 16 bytes of X */
-    memcpy(hash, md->md2.X, 16);
+    XMEMCPY(hash, md->md2.X, 16);
 
 #ifdef CLEAN_STACK
     zeromem(md, sizeof(hash_state));
--- a/md4.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/md4.c	Sun Dec 19 11:34:45 2004 +0000
@@ -68,9 +68,9 @@
   }
 
 #ifdef CLEAN_STACK
-static void _md4_compress(hash_state *md, unsigned char *buf)
+static int _md4_compress(hash_state *md, unsigned char *buf)
 #else
-static void md4_compress(hash_state *md, unsigned char *buf)
+static int  md4_compress(hash_state *md, unsigned char *buf)
 #endif
 {
     ulong32 x[16], a, b, c, d;
@@ -147,17 +147,21 @@
     md->md4.state[1] = md->md4.state[1] + b;
     md->md4.state[2] = md->md4.state[2] + c;
     md->md4.state[3] = md->md4.state[3] + d;
+
+    return CRYPT_OK;
 }
 
 #ifdef CLEAN_STACK
-static void md4_compress(hash_state *md, unsigned char *buf)
+static int md4_compress(hash_state *md, unsigned char *buf)
 {
-   _md4_compress(md, buf);
+   int err;
+   err = _md4_compress(md, buf);
    burn_stack(sizeof(ulong32) * 20 + sizeof(int));
+   return err;
 }
 #endif
 
-void md4_init(hash_state * md)
+int md4_init(hash_state * md)
 {
    _ARGCHK(md != NULL);
    md->md4.state[0] = 0x67452301UL;
@@ -166,6 +170,7 @@
    md->md4.state[3] = 0x10325476UL;
    md->md4.length  = 0;
    md->md4.curlen  = 0;
+   return CRYPT_OK;
 }
 
 HASH_PROCESS(md4_process, md4_compress, md4, 64)
--- a/md5.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/md5.c	Sun Dec 19 11:34:45 2004 +0000
@@ -81,9 +81,9 @@
 #endif   
 
 #ifdef CLEAN_STACK
-static void _md5_compress(hash_state *md, unsigned char *buf)
+static int _md5_compress(hash_state *md, unsigned char *buf)
 #else
-static void md5_compress(hash_state *md, unsigned char *buf)
+static int  md5_compress(hash_state *md, unsigned char *buf)
 #endif
 {
     ulong32 i, W[16], a, b, c, d;
@@ -194,17 +194,21 @@
     md->md5.state[1] = md->md5.state[1] + b;
     md->md5.state[2] = md->md5.state[2] + c;
     md->md5.state[3] = md->md5.state[3] + d;
+
+    return CRYPT_OK;
 }
 
 #ifdef CLEAN_STACK
-static void md5_compress(hash_state *md, unsigned char *buf)
+static int md5_compress(hash_state *md, unsigned char *buf)
 {
-   _md5_compress(md, buf);
+   int err;
+   err = _md5_compress(md, buf);
    burn_stack(sizeof(ulong32) * 21);
+   return err;
 }
 #endif
 
-void md5_init(hash_state * md)
+int md5_init(hash_state * md)
 {
    _ARGCHK(md != NULL);
    md->md5.state[0] = 0x67452301UL;
@@ -213,6 +217,7 @@
    md->md5.state[3] = 0x10325476UL;
    md->md5.curlen = 0;
    md->md5.length = 0;
+   return CRYPT_OK;
 }
 
 HASH_PROCESS(md5_process, md5_compress, md5, 64)
--- a/modes_test.c	Tue Jun 15 14:07:21 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/* 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	Tue Jun 15 14:07:21 2004 +0000
+++ b/mpi.c	Sun Dec 19 11:34:45 2004 +0000
@@ -1,19 +1,20 @@
 /* Start: bn_error.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_ERROR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 static const struct {
      int code;
@@ -40,30 +41,32 @@
    return "Invalid error code";
 }
 
+#endif
 
 /* End: bn_error.c */
 
 /* Start: bn_fast_mp_invmod.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_FAST_MP_INVMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* computes the modular inverse via binary extended euclidean algorithm, 
  * that is c = 1/a mod b 
  *
- * Based on mp_invmod except this is optimized for the case where b is 
+ * Based on slow invmod except this is optimized for the case where b is 
  * odd as per HAC Note 14.64 on pp. 610
  */
 int
@@ -187,29 +190,31 @@
 __ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL);
   return res;
 }
+#endif
 
 /* End: bn_fast_mp_invmod.c */
 
 /* Start: bn_fast_mp_montgomery_reduce.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* computes xR**-1 == x (mod N) via Montgomery Reduction
  *
- * This is an optimized implementation of mp_montgomery_reduce
+ * This is an optimized implementation of montgomery_reduce
  * which uses the comba method to quickly calculate the columns of the
  * reduction.
  *
@@ -358,25 +363,27 @@
   }
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_fast_mp_montgomery_reduce.c */
 
 /* Start: bn_fast_s_mp_mul_digs.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* Fast (comba) multiplier
  *
@@ -397,8 +404,9 @@
 int
 fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
 {
-  int     olduse, res, pa, ix;
-  mp_word W[MP_WARRAY];
+  int     olduse, res, pa, ix, iz;
+  mp_digit W[MP_WARRAY];
+  register mp_word  _W;
 
   /* grow the destination as required */
   if (c->alloc < digs) {
@@ -407,48 +415,39 @@
     }
   }
 
-  /* clear temp buf (the columns) */
-  memset (W, 0, sizeof (mp_word) * digs);
-
-  /* calculate the columns */
-  pa = a->used;
-  for (ix = 0; ix < pa; ix++) {
-    /* this multiplier has been modified to allow you to 
-     * control how many digits of output are produced.  
-     * So at most we want to make upto "digs" digits of output.
-     *
-     * this adds products to distinct columns (at ix+iy) of W
-     * note that each step through the loop is not dependent on
-     * the previous which means the compiler can easily unroll
-     * the loop without scheduling problems
-     */
-    {
-      register mp_digit tmpx, *tmpy;
-      register mp_word *_W;
-      register int iy, pb;
-
-      /* alias for the the word on the left e.g. A[ix] * A[iy] */
-      tmpx = a->dp[ix];
-
-      /* alias for the right side */
-      tmpy = b->dp;
-
-      /* alias for the columns, each step through the loop adds a new
-         term to each column
+  /* number of output digits to produce */
+  pa = MIN(digs, a->used + b->used);
+
+  /* clear the carry */
+  _W = 0;
+  for (ix = 0; ix <= pa; ix++) { 
+      int      tx, ty;
+      int      iy;
+      mp_digit *tmpx, *tmpy;
+
+      /* get offsets into the two bignums */
+      ty = MIN(b->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = b->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially its 
+         while (tx++ < a->used && ty-- >= 0) { ... }
        */
-      _W = W + ix;
-
-      /* the number of digits is limited by their placement.  E.g.
-         we avoid multiplying digits that will end up above the # of
-         digits of precision requested
-       */
-      pb = MIN (b->used, digs - ix);
-
-      for (iy = 0; iy < pb; iy++) {
-        *_W++ += ((mp_word)tmpx) * ((mp_word)*tmpy++);
+      iy = MIN(a->used-tx, ty+1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; ++iz) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
       }
-    }
-
+
+      /* store term */
+      W[ix] = ((mp_digit)_W) & MP_MASK;
+
+      /* make next carry */
+      _W = _W >> ((mp_word)DIGIT_BIT);
   }
 
   /* setup dest */
@@ -457,32 +456,11 @@
 
   {
     register mp_digit *tmpc;
-
-    /* At this point W[] contains the sums of each column.  To get the
-     * correct result we must take the extra bits from each column and
-     * carry them down
-     *
-     * Note that while this adds extra code to the multiplier it 
-     * saves time since the carry propagation is removed from the 
-     * above nested loop.This has the effect of reducing the work 
-     * from N*(N+N*c)==N**2 + c*N**2 to N**2 + N*c where c is the 
-     * cost of the shifting.  On very small numbers this is slower 
-     * but on most cryptographic size numbers it is faster.
-     *
-     * In this particular implementation we feed the carries from
-     * behind which means when the loop terminates we still have one
-     * last digit to copy
-     */
     tmpc = c->dp;
-    for (ix = 1; ix < digs; ix++) {
-      /* forward the carry from the previous temp */
-      W[ix] += (W[ix - 1] >> ((mp_word) DIGIT_BIT));
-
+    for (ix = 0; ix < digs; ix++) {
       /* now extract the previous digit [below the carry] */
-      *tmpc++ = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK));
-    }
-    /* fetch the last digit */
-    *tmpc++ = (mp_digit) (W[digs - 1] & ((mp_word) MP_MASK));
+      *tmpc++ = W[ix];
+    }
 
     /* clear unused digits [that existed in the old copy of c] */
     for (; ix < olduse; ix++) {
@@ -492,28 +470,30 @@
   mp_clamp (c);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_fast_s_mp_mul_digs.c */
 
 /* Start: bn_fast_s_mp_mul_high_digs.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
- #include <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
+#include <ltc_tommath.h>
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+
+/* this is a modified version of fast_s_mul_digs that only produces
+ * output digits *above* digs.  See the comments for fast_s_mul_digs
  * to see how it works.
  *
  * This is used in the Barrett reduction since for one of the multiplications
@@ -524,95 +504,92 @@
 int
 fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
 {
-  int     oldused, newused, res, pa, pb, ix;
-  mp_word W[MP_WARRAY];
-
-  /* calculate size of product and allocate more space if required */
-  newused = a->used + b->used + 1;
-  if (c->alloc < newused) {
-    if ((res = mp_grow (c, newused)) != MP_OKAY) {
+  int     olduse, res, pa, ix, iz;
+  mp_digit W[MP_WARRAY];
+  mp_word  _W;
+
+  /* grow the destination as required */
+  pa = a->used + b->used;
+  if (c->alloc < pa) {
+    if ((res = mp_grow (c, pa)) != MP_OKAY) {
       return res;
     }
   }
 
-  /* like the other comba method we compute the columns first */
-  pa = a->used;
-  pb = b->used;
-  memset (W + digs, 0, (pa + pb + 1 - digs) * sizeof (mp_word));
-  for (ix = 0; ix < pa; ix++) {
-    {
-      register mp_digit tmpx, *tmpy;
-      register int iy;
-      register mp_word *_W;
-
-      /* work todo, that is we only calculate digits that are at "digs" or above  */
-      iy = digs - ix;
-
-      /* copy of word on the left of A[ix] * B[iy] */
-      tmpx = a->dp[ix];
-
-      /* alias for right side */
-      tmpy = b->dp + iy;
-     
-      /* alias for the columns of output.  Offset to be equal to or above the 
-       * smallest digit place requested 
+  /* number of output digits to produce */
+  pa = a->used + b->used;
+  _W = 0;
+  for (ix = digs; ix <= pa; ix++) { 
+      int      tx, ty, iy;
+      mp_digit *tmpx, *tmpy;
+
+      /* get offsets into the two bignums */
+      ty = MIN(b->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = b->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially its 
+         while (tx++ < a->used && ty-- >= 0) { ... }
        */
-      _W = W + digs;     
-      
-      /* skip cases below zero where ix > digs */
-      if (iy < 0) {
-         iy    = abs(iy);
-         tmpy += iy;
-         _W   += iy;
-         iy    = 0;
+      iy = MIN(a->used-tx, ty+1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; iz++) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
       }
 
-      /* compute column products for digits above the minimum */
-      for (; iy < pb; iy++) {
-         *_W++ += ((mp_word) tmpx) * ((mp_word)*tmpy++);
-      }
-    }
+      /* store term */
+      W[ix] = ((mp_digit)_W) & MP_MASK;
+
+      /* make next carry */
+      _W = _W >> ((mp_word)DIGIT_BIT);
   }
 
   /* setup dest */
-  oldused = c->used;
-  c->used = newused;
-
-  /* now convert the array W downto what we need
-   *
-   * See comments in bn_fast_s_mp_mul_digs.c
-   */
-  for (ix = digs + 1; ix < newused; ix++) {
-    W[ix] += (W[ix - 1] >> ((mp_word) DIGIT_BIT));
-    c->dp[ix - 1] = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK));
-  }
-  c->dp[newused - 1] = (mp_digit) (W[newused - 1] & ((mp_word) MP_MASK));
-
-  for (; ix < oldused; ix++) {
-    c->dp[ix] = 0;
+  olduse  = c->used;
+  c->used = pa;
+
+  {
+    register mp_digit *tmpc;
+
+    tmpc = c->dp + digs;
+    for (ix = digs; ix <= pa; ix++) {
+      /* now extract the previous digit [below the carry] */
+      *tmpc++ = W[ix];
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpc++ = 0;
+    }
   }
   mp_clamp (c);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_fast_s_mp_mul_high_digs.c */
 
 /* Start: bn_fast_s_mp_sqr.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_FAST_S_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* fast squaring
  *
@@ -631,131 +608,121 @@
  * Based on Algorithm 14.16 on pp.597 of HAC.
  *
  */
+/* the jist of squaring...
+
+you do like mult except the offset of the tmpx [one that starts closer to zero]
+can't equal the offset of tmpy.  So basically you set up iy like before then you min it with
+(ty-tx) so that it never happens.  You double all those you add in the inner loop
+
+After that loop you do the squares and add them in.
+
+Remove W2 and don't memset W
+
+*/
+
 int fast_s_mp_sqr (mp_int * a, mp_int * b)
 {
-  int     olduse, newused, res, ix, pa;
-  mp_word W2[MP_WARRAY], W[MP_WARRAY];
-
-  /* calculate size of product and allocate as required */
-  pa = a->used;
-  newused = pa + pa + 1;
-  if (b->alloc < newused) {
-    if ((res = mp_grow (b, newused)) != MP_OKAY) {
+  int       olduse, res, pa, ix, iz;
+  mp_digit   W[MP_WARRAY], *tmpx;
+  mp_word   W1;
+
+  /* grow the destination as required */
+  pa = a->used + a->used;
+  if (b->alloc < pa) {
+    if ((res = mp_grow (b, pa)) != MP_OKAY) {
       return res;
     }
   }
 
-  /* zero temp buffer (columns)
-   * Note that there are two buffers.  Since squaring requires
-   * a outer and inner product and the inner product requires
-   * computing a product and doubling it (a relatively expensive
-   * op to perform n**2 times if you don't have to) the inner and
-   * outer products are computed in different buffers.  This way
-   * the inner product can be doubled using n doublings instead of
-   * n**2
-   */
-  memset (W,  0, newused * sizeof (mp_word));
-  memset (W2, 0, newused * sizeof (mp_word));
-
-  /* This computes the inner product.  To simplify the inner N**2 loop
-   * the multiplication by two is done afterwards in the N loop.
-   */
-  for (ix = 0; ix < pa; ix++) {
-    /* compute the outer product
-     *
-     * Note that every outer product is computed
-     * for a particular column only once which means that
-     * there is no need todo a double precision addition
-     * into the W2[] array.
-     */
-    W2[ix + ix] = ((mp_word)a->dp[ix]) * ((mp_word)a->dp[ix]);
-
-    {
-      register mp_digit tmpx, *tmpy;
-      register mp_word *_W;
-      register int iy;
-
-      /* copy of left side */
-      tmpx = a->dp[ix];
-
-      /* alias for right side */
-      tmpy = a->dp + (ix + 1);
-
-      /* the column to store the result in */
-      _W = W + (ix + ix + 1);
-
-      /* inner products */
-      for (iy = ix + 1; iy < pa; iy++) {
-          *_W++ += ((mp_word)tmpx) * ((mp_word)*tmpy++);
+  /* number of output digits to produce */
+  W1 = 0;
+  for (ix = 0; ix <= pa; ix++) { 
+      int      tx, ty, iy;
+      mp_word  _W;
+      mp_digit *tmpy;
+
+      /* clear counter */
+      _W = 0;
+
+      /* get offsets into the two bignums */
+      ty = MIN(a->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = a->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially its 
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* now for squaring tx can never equal ty 
+       * we halve the distance since they approach at a rate of 2x
+       * and we have to round because odd cases need to be executed
+       */
+      iy = MIN(iy, (ty-tx+1)>>1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; iz++) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
       }
-    }
+
+      /* double the inner product and add carry */
+      _W = _W + _W + W1;
+
+      /* even columns have the square term in them */
+      if ((ix&1) == 0) {
+         _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
+      }
+
+      /* store it */
+      W[ix] = _W;
+
+      /* make next carry */
+      W1 = _W >> ((mp_word)DIGIT_BIT);
   }
 
   /* setup dest */
   olduse  = b->used;
-  b->used = newused;
-
-  /* now compute digits
-   *
-   * We have to double the inner product sums, add in the
-   * outer product sums, propagate carries and convert
-   * to single precision.
-   */
+  b->used = a->used+a->used;
+
   {
-    register mp_digit *tmpb;
-
-    /* double first value, since the inner products are
-     * half of what they should be
-     */
-    W[0] += W[0] + W2[0];
-
+    mp_digit *tmpb;
     tmpb = b->dp;
-    for (ix = 1; ix < newused; ix++) {
-      /* double/add next digit */
-      W[ix] += W[ix] + W2[ix];
-
-      /* propagate carry forwards [from the previous digit] */
-      W[ix] = W[ix] + (W[ix - 1] >> ((mp_word) DIGIT_BIT));
-
-      /* store the current digit now that the carry isn't
-       * needed
-       */
-      *tmpb++ = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK));
-    }
-    /* set the last value.  Note even if the carry is zero
-     * this is required since the next step will not zero
-     * it if b originally had a value at b->dp[2*a.used]
-     */
-    *tmpb++ = (mp_digit) (W[(newused) - 1] & ((mp_word) MP_MASK));
-
-    /* clear high digits of b if there were any originally */
+    for (ix = 0; ix < pa; ix++) {
+      *tmpb++ = W[ix] & MP_MASK;
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
     for (; ix < olduse; ix++) {
       *tmpb++ = 0;
     }
   }
-
   mp_clamp (b);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_fast_s_mp_sqr.c */
 
 /* Start: bn_mp_2expt.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_2EXPT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* computes a = 2**b 
  *
@@ -779,29 +746,31 @@
   a->used = b / DIGIT_BIT + 1;
 
   /* put the single bit in its place */
-  a->dp[b / DIGIT_BIT] = 1 << (b % DIGIT_BIT);
+  a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
 
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_2expt.c */
 
 /* Start: bn_mp_abs.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_ABS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* b = |a| 
  *
@@ -824,25 +793,27 @@
 
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_abs.c */
 
 /* Start: bn_mp_add.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_ADD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* high level addition (handles signs) */
 int mp_add (mp_int * a, mp_int * b, mp_int * c)
@@ -875,25 +846,27 @@
   return res;
 }
 
+#endif
 
 /* End: bn_mp_add.c */
 
 /* Start: bn_mp_add_d.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_ADD_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* single digit addition */
 int
@@ -982,25 +955,27 @@
   return MP_OKAY;
 }
 
+#endif
 
 /* End: bn_mp_add_d.c */
 
 /* Start: bn_mp_addmod.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_ADDMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* d = a + b (mod c) */
 int
@@ -1021,25 +996,27 @@
   mp_clear (&t);
   return res;
 }
+#endif
 
 /* End: bn_mp_addmod.c */
 
 /* Start: bn_mp_and.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_AND_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* AND two ints together */
 int
@@ -1076,25 +1053,27 @@
   mp_clear (&t);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_and.c */
 
 /* Start: bn_mp_clamp.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_CLAMP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* trim unused digits 
  *
@@ -1118,34 +1097,40 @@
     a->sign = MP_ZPOS;
   }
 }
+#endif
 
 /* End: bn_mp_clamp.c */
 
 /* Start: bn_mp_clear.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_CLEAR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* clear one (frees)  */
 void
 mp_clear (mp_int * a)
 {
+  int i;
+
   /* only do anything if a hasn't been freed previously */
   if (a->dp != NULL) {
     /* first zero the digits */
-    memset (a->dp, 0, sizeof (mp_digit) * a->used);
+    for (i = 0; i < a->used; i++) {
+        a->dp[i] = 0;
+    }
 
     /* free ram */
     XFREE(a->dp);
@@ -1156,25 +1141,27 @@
     a->sign  = MP_ZPOS;
   }
 }
+#endif
 
 /* End: bn_mp_clear.c */
 
 /* Start: bn_mp_clear_multi.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_CLEAR_MULTI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 #include <stdarg.h>
 
 void mp_clear_multi(mp_int *mp, ...) 
@@ -1188,25 +1175,27 @@
     }
     va_end(args);
 }
+#endif
 
 /* End: bn_mp_clear_multi.c */
 
 /* Start: bn_mp_cmp.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_CMP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* compare two ints (signed)*/
 int
@@ -1229,25 +1218,27 @@
      return mp_cmp_mag(a, b);
   }
 }
+#endif
 
 /* End: bn_mp_cmp.c */
 
 /* Start: bn_mp_cmp_d.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_CMP_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* compare a digit */
 int mp_cmp_d(mp_int * a, mp_digit b)
@@ -1271,25 +1262,27 @@
     return MP_EQ;
   }
 }
+#endif
 
 /* End: bn_mp_cmp_d.c */
 
 /* Start: bn_mp_cmp_mag.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_CMP_MAG_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* compare maginitude of two ints (unsigned) */
 int mp_cmp_mag (mp_int * a, mp_int * b)
@@ -1324,25 +1317,27 @@
   }
   return MP_EQ;
 }
+#endif
 
 /* End: bn_mp_cmp_mag.c */
 
 /* Start: bn_mp_cnt_lsb.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_CNT_LSB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 static const int lnz[16] = { 
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
@@ -1375,25 +1370,27 @@
    return x;
 }
 
+#endif
 
 /* End: bn_mp_cnt_lsb.c */
 
 /* Start: bn_mp_copy.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_COPY_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* copy, b = a */
 int
@@ -1441,25 +1438,27 @@
   b->sign = a->sign;
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_copy.c */
 
 /* Start: bn_mp_count_bits.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_COUNT_BITS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* returns the number of bits in an int */
 int
@@ -1484,25 +1483,99 @@
   }
   return r;
 }
+#endif
 
 /* End: bn_mp_count_bits.c */
 
 /* Start: bn_mp_div.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_DIV_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+
+#ifdef BN_MP_DIV_SMALL
+
+/* slower bit-bang division... also smaller */
+int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+   mp_int ta, tb, tq, q;
+   int    res, n, n2;
+
+  /* is divisor zero ? */
+  if (mp_iszero (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (mp_cmp_mag (a, b) == MP_LT) {
+    if (d != NULL) {
+      res = mp_copy (a, d);
+    } else {
+      res = MP_OKAY;
+    }
+    if (c != NULL) {
+      mp_zero (c);
+    }
+    return res;
+  }
+	
+  /* init our temps */
+  if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) {
+     return res;
+  }
+
+
+  mp_set(&tq, 1);
+  n = mp_count_bits(a) - mp_count_bits(b);
+  if (((res = mp_copy(a, &ta)) != MP_OKAY) ||
+      ((res = mp_copy(b, &tb)) != MP_OKAY) || 
+      ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
+      ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
+      goto __ERR;
+  }
+
+  while (n-- >= 0) {
+     if (mp_cmp(&tb, &ta) != MP_GT) {
+        if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
+            ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
+           goto __ERR;
+        }
+     }
+     if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
+         ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
+           goto __ERR;
+     }
+  }
+
+  /* now q == quotient and ta == remainder */
+  n  = a->sign;
+  n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
+  if (c != NULL) {
+     mp_exch(c, &q);
+     c->sign  = n2;
+  }
+  if (d != NULL) {
+     mp_exch(d, &ta);
+     d->sign = n;
+  }
+__ERR:
+   mp_clear_multi(&ta, &tb, &tq, &q, NULL);
+   return res;
+}
+
+#else
 
 /* integer signed division. 
  * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
@@ -1677,7 +1750,7 @@
    */
   
   /* get sign before writing to c */
-  x.sign = a->sign;
+  x.sign = x.used == 0 ? MP_ZPOS : a->sign;
 
   if (c != NULL) {
     mp_clamp (&q);
@@ -1700,24 +1773,29 @@
   return res;
 }
 
+#endif
+
+#endif
+
 /* End: bn_mp_div.c */
 
 /* Start: bn_mp_div_2.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_DIV_2_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* b = a/2 */
 int mp_div_2(mp_int * a, mp_int * b)
@@ -1765,25 +1843,27 @@
   mp_clamp (b);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_div_2.c */
 
 /* Start: bn_mp_div_2d.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_DIV_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* 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)
@@ -1860,25 +1940,27 @@
   mp_clear (&t);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_div_2d.c */
 
 /* Start: bn_mp_div_3.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_DIV_3_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* divide by three (based on routine from MPI and the GMP manual) */
 int
@@ -1937,25 +2019,27 @@
   return res;
 }
 
+#endif
 
 /* End: bn_mp_div_3.c */
 
 /* Start: bn_mp_div_d.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_DIV_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 static int s_is_power_of_two(mp_digit b, int *p)
 {
@@ -1997,7 +2081,7 @@
   /* power of two ? */
   if (s_is_power_of_two(b, &ix) == 1) {
      if (d != NULL) {
-        *d = a->dp[0] & ((1<<ix) - 1);
+        *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
      }
      if (c != NULL) {
         return mp_div_2d(a, ix, c, NULL);
@@ -2005,10 +2089,12 @@
      return MP_OKAY;
   }
 
+#ifdef BN_MP_DIV_3_C
   /* three? */
   if (b == 3) {
      return mp_div_3(a, c, d);
   }
+#endif
 
   /* no easy answer [c'est la vie].  Just division */
   if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
@@ -2043,25 +2129,27 @@
   return res;
 }
 
+#endif
 
 /* End: bn_mp_div_d.c */
 
 /* Start: bn_mp_dr_is_modulus.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_DR_IS_MODULUS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* determines if a number is a valid DR modulus */
 int mp_dr_is_modulus(mp_int *a)
@@ -2084,25 +2172,27 @@
    return 1;
 }
 
+#endif
 
 /* End: bn_mp_dr_is_modulus.c */
 
 /* Start: bn_mp_dr_reduce.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_DR_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
  *
@@ -2176,25 +2266,27 @@
   }
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_dr_reduce.c */
 
 /* Start: bn_mp_dr_setup.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_DR_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* determines the setup value */
 void mp_dr_setup(mp_int *a, mp_digit *d)
@@ -2206,25 +2298,27 @@
         ((mp_word)a->dp[0]));
 }
 
+#endif
 
 /* End: bn_mp_dr_setup.c */
 
 /* Start: bn_mp_exch.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_EXCH_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* swap the elements of two integers, for cases where you can't simply swap the 
  * mp_int pointers around
@@ -2238,25 +2332,27 @@
   *a = *b;
   *b = t;
 }
+#endif
 
 /* End: bn_mp_exch.c */
 
 /* Start: bn_mp_expt_d.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_EXPT_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* calculate c = a**b  using a square-multiply algorithm */
 int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
@@ -2293,25 +2389,27 @@
   mp_clear (&g);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_expt_d.c */
 
 /* Start: bn_mp_exptmod.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_EXPTMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 
 /* this is a shell function that calls either the normal or Montgomery
@@ -2330,6 +2428,7 @@
 
   /* if exponent X is negative we have to recurse */
   if (X->sign == MP_NEG) {
+#ifdef BN_MP_INVMOD_C
      mp_int tmpG, tmpX;
      int err;
 
@@ -2356,44 +2455,65 @@
      err = mp_exptmod(&tmpG, &tmpX, P, Y);
      mp_clear_multi(&tmpG, &tmpX, NULL);
      return err;
-  }
-
+#else 
+     /* no invmod */
+     return MP_VAL
+#endif
+  }
+
+#ifdef BN_MP_DR_IS_MODULUS_C
   /* is it a DR modulus? */
   dr = mp_dr_is_modulus(P);
-
+#else
+  dr = 0;
+#endif
+
+#ifdef BN_MP_REDUCE_IS_2K_C
   /* if not, is it a uDR modulus? */
   if (dr == 0) {
      dr = mp_reduce_is_2k(P) << 1;
   }
+#endif
     
   /* if the modulus is odd or dr != 0 use the fast method */
+#ifdef BN_MP_EXPTMOD_FAST_C
   if (mp_isodd (P) == 1 || dr !=  0) {
     return mp_exptmod_fast (G, X, P, Y, dr);
   } else {
+#endif
+#ifdef BN_S_MP_EXPTMOD_C
     /* otherwise use the generic Barrett reduction technique */
     return s_mp_exptmod (G, X, P, Y);
-  }
+#else
+    /* no exptmod for evens */
+    return MP_VAL;
+#endif
+#ifdef BN_MP_EXPTMOD_FAST_C
+  }
+#endif
 }
 
+#endif
 
 /* End: bn_mp_exptmod.c */
 
 /* Start: bn_mp_exptmod_fast.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_EXPTMOD_FAST_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
  *
@@ -2465,29 +2585,52 @@
 
   /* determine and setup reduction code */
   if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_SETUP_C     
      /* now setup montgomery  */
      if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
         goto __M;
      }
+#else
+     err = MP_VAL;
+     goto __M;
+#endif
 
      /* automatically pick the comba one if available (saves quite a few calls/ifs) */
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
      if (((P->used * 2 + 1) < MP_WARRAY) &&
           P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
         redux = fast_mp_montgomery_reduce;
-     } else {
+     } else 
+#endif
+     {
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
         /* use slower baseline Montgomery method */
         redux = mp_montgomery_reduce;
+#else
+        err = MP_VAL;
+        goto __M;
+#endif
      }
   } else if (redmode == 1) {
+#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
      /* setup DR reduction for moduli of the form B**k - b */
      mp_dr_setup(P, &mp);
      redux = mp_dr_reduce;
+#else
+     err = MP_VAL;
+     goto __M;
+#endif
   } else {
+#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
      /* setup DR reduction for moduli of the form 2**k - b */
      if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
         goto __M;
      }
      redux = mp_reduce_2k;
+#else
+     err = MP_VAL;
+     goto __M;
+#endif
   }
 
   /* setup result */
@@ -2497,16 +2640,21 @@
 
   /* create M table
    *
-   * The M table contains powers of the input base, e.g. M[x] = G^x mod P
+
    *
    * The first half of the table is not computed though accept for M[0] and M[1]
    */
 
   if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
      /* now we need R mod m */
      if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
        goto __RES;
      }
+#else 
+     err = MP_VAL;
+     goto __RES;
+#endif
 
      /* now set M[1] to G * R mod m */
      if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
@@ -2650,7 +2798,7 @@
       * to reduce one more time to cancel out the factor
       * of R.
       */
-     if ((err = mp_montgomery_reduce (&res, P, mp)) != MP_OKAY) {
+     if ((err = redux(&res, P, mp)) != MP_OKAY) {
        goto __RES;
      }
   }
@@ -2666,25 +2814,28 @@
   }
   return err;
 }
+#endif
+
 
 /* End: bn_mp_exptmod_fast.c */
 
 /* Start: bn_mp_exteuclid.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_EXTEUCLID_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* Extended euclidean algorithm of (a, b) produces 
    a*u1 + b*u2 = u3
@@ -2739,25 +2890,27 @@
 _ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
    return err;
 }
+#endif
 
 /* End: bn_mp_exteuclid.c */
 
 /* Start: bn_mp_fread.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_FREAD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* read a bigint from a file stream in ASCII */
 int mp_fread(mp_int *a, int radix, FILE *stream)
@@ -2804,25 +2957,27 @@
    return MP_OKAY;
 }
 
+#endif
 
 /* End: bn_mp_fread.c */
 
 /* Start: bn_mp_fwrite.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_FWRITE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 int mp_fwrite(mp_int *a, int radix, FILE *stream)
 {
@@ -2854,25 +3009,27 @@
    return MP_OKAY;
 }
 
+#endif
 
 /* End: bn_mp_fwrite.c */
 
 /* Start: bn_mp_gcd.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_GCD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* Greatest Common Divisor using the binary method */
 int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
@@ -2965,25 +3122,27 @@
 __U:mp_clear (&v);
   return res;
 }
+#endif
 
 /* End: bn_mp_gcd.c */
 
 /* Start: bn_mp_get_int.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_GET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* get the lower 32-bits of an mp_int */
 unsigned long mp_get_int(mp_int * a) 
@@ -3008,25 +3167,27 @@
   /* force result to 32-bits always so it is consistent on non 32-bit platforms */
   return res & 0xFFFFFFFFUL;
 }
+#endif
 
 /* End: bn_mp_get_int.c */
 
 /* Start: bn_mp_grow.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_GROW_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* grow as required */
 int mp_grow (mp_int * a, int size)
@@ -3063,35 +3224,44 @@
   }
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_grow.c */
 
 /* Start: bn_mp_init.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
-
-/* init a new bigint */
+#include <ltc_tommath.h>
+#ifdef BN_MP_INIT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+
+/* init a new mp_int */
 int mp_init (mp_int * a)
 {
+  int i;
+
   /* allocate memory required and clear it */
-  a->dp = OPT_CAST(mp_digit) XCALLOC (sizeof (mp_digit), MP_PREC);
+  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC);
   if (a->dp == NULL) {
     return MP_MEM;
   }
 
+  /* set the digits to zero */
+  for (i = 0; i < MP_PREC; i++) {
+      a->dp[i] = 0;
+  }
+
   /* set the used to zero, allocated digits to the default precision
    * and sign to positive */
   a->used  = 0;
@@ -3100,25 +3270,27 @@
 
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_init.c */
 
 /* Start: bn_mp_init_copy.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_INIT_COPY_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* creates "a" then copies b into it */
 int mp_init_copy (mp_int * a, mp_int * b)
@@ -3130,25 +3302,27 @@
   }
   return mp_copy (b, a);
 }
+#endif
 
 /* End: bn_mp_init_copy.c */
 
 /* Start: bn_mp_init_multi.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_INIT_MULTI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 #include <stdarg.h>
 
 int mp_init_multi(mp_int *mp, ...) 
@@ -3187,25 +3361,27 @@
     return res;                /* Assumed ok, if error flagged above. */
 }
 
+#endif
 
 /* End: bn_mp_init_multi.c */
 
 /* Start: bn_mp_init_set.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_INIT_SET_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* initialize and set a digit */
 int mp_init_set (mp_int * a, mp_digit b)
@@ -3217,25 +3393,27 @@
   mp_set(a, b);
   return err;
 }
+#endif
 
 /* End: bn_mp_init_set.c */
 
 /* Start: bn_mp_init_set_int.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_INIT_SET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* initialize and set a digit */
 int mp_init_set_int (mp_int * a, unsigned long b)
@@ -3246,66 +3424,122 @@
   }
   return mp_set_int(a, b);
 }
+#endif
 
 /* End: bn_mp_init_set_int.c */
 
 /* Start: bn_mp_init_size.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_INIT_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* init an mp_init for a given size */
 int mp_init_size (mp_int * a, int size)
 {
+  int x;
+
   /* pad size so there are always extra digits */
   size += (MP_PREC * 2) - (size % MP_PREC);	
   
   /* alloc mem */
-  a->dp = OPT_CAST(mp_digit) XCALLOC (sizeof (mp_digit), size);
+  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size);
   if (a->dp == NULL) {
     return MP_MEM;
   }
+
+  /* set the members */
   a->used  = 0;
   a->alloc = size;
   a->sign  = MP_ZPOS;
 
+  /* zero the digits */
+  for (x = 0; x < size; x++) {
+      a->dp[x] = 0;
+  }
+
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_init_size.c */
 
 /* Start: bn_mp_invmod.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_INVMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* hac 14.61, pp608 */
 int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
 {
+  /* b cannot be negative */
+  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+    return MP_VAL;
+  }
+
+#ifdef BN_FAST_MP_INVMOD_C
+  /* if the modulus is odd we can use a faster routine instead */
+  if (mp_isodd (b) == 1) {
+    return fast_mp_invmod (a, b, c);
+  }
+#endif
+
+#ifdef BN_MP_INVMOD_SLOW_C
+  return mp_invmod_slow(a, b, c);
+#endif
+
+  return MP_VAL;
+}
+#endif
+
+/* End: bn_mp_invmod.c */
+
+/* Start: bn_mp_invmod_slow.c */
+#include <ltc_tommath.h>
+#ifdef BN_MP_INVMOD_SLOW_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+
+/* hac 14.61, pp608 */
+int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
+{
   mp_int  x, y, u, v, A, B, C, D;
   int     res;
 
@@ -3314,11 +3548,6 @@
     return MP_VAL;
   }
 
-  /* if the modulus is odd we can use a faster routine instead */
-  if (mp_isodd (b) == 1) {
-    return fast_mp_invmod (a, b, c);
-  }
-  
   /* init temps */
   if ((res = mp_init_multi(&x, &y, &u, &v, 
                            &A, &B, &C, &D, NULL)) != MP_OKAY) {
@@ -3461,25 +3690,27 @@
 __ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
   return res;
 }
-
-/* End: bn_mp_invmod.c */
+#endif
+
+/* End: bn_mp_invmod_slow.c */
 
 /* Start: bn_mp_is_square.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_IS_SQUARE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* Check if remainders are possible squares - fast exclude non-squares */
 static const char rem_128[128] = {
@@ -3536,7 +3767,7 @@
      return MP_OKAY;
   }
 
-  /* product of primes less than 2^31 */
+
   if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) {
      return res;
   }
@@ -3568,25 +3799,27 @@
 ERR:mp_clear(&t);
   return res;
 }
+#endif
 
 /* End: bn_mp_is_square.c */
 
 /* Start: bn_mp_jacobi.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_JACOBI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* computes the jacobi c = (a | n) (or Legendre if n is prime)
  * HAC pp. 73 Algorithm 2.149
@@ -3671,25 +3904,27 @@
 __A1:mp_clear (&a1);
   return res;
 }
+#endif
 
 /* End: bn_mp_jacobi.c */
 
 /* Start: bn_mp_karatsuba_mul.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_KARATSUBA_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* c = |a| * |b| using Karatsuba Multiplication using 
  * three half size multiplications
@@ -3753,9 +3988,6 @@
     goto X0Y0;
 
   /* now shift the digits */
-  x0.sign = x1.sign = a->sign;
-  y0.sign = y1.sign = b->sign;
-
   x0.used = y0.used = B;
   x1.used = a->used - B;
   y1.used = b->used - B;
@@ -3839,30 +4071,32 @@
 ERR:
   return err;
 }
+#endif
 
 /* End: bn_mp_karatsuba_mul.c */
 
 /* Start: bn_mp_karatsuba_sqr.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_KARATSUBA_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* Karatsuba squaring, computes b = a*a using three 
  * half size squarings
  *
- * See comments of mp_karatsuba_mul for details.  It 
+ * See comments of karatsuba_mul for details.  It 
  * is essentially the same algorithm but merely 
  * tuned to perform recursive squarings.
  */
@@ -3958,25 +4192,27 @@
 ERR:
   return err;
 }
+#endif
 
 /* End: bn_mp_karatsuba_sqr.c */
 
 /* Start: bn_mp_lcm.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_LCM_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* computes least common multiple as |a*b|/(a, b) */
 int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
@@ -4016,25 +4252,27 @@
   mp_clear_multi (&t1, &t2, NULL);
   return res;
 }
+#endif
 
 /* End: bn_mp_lcm.c */
 
 /* Start: bn_mp_lshd.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_LSHD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* shift left a certain amount of digits */
 int mp_lshd (mp_int * a, int b)
@@ -4081,25 +4319,27 @@
   }
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_lshd.c */
 
 /* Start: bn_mp_mod.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_MOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* c = a mod b, 0 <= c < b */
 int
@@ -4127,25 +4367,27 @@
   mp_clear (&t);
   return res;
 }
+#endif
 
 /* End: bn_mp_mod.c */
 
 /* Start: bn_mp_mod_2d.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_MOD_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* calc a value mod 2**b */
 int
@@ -4180,73 +4422,78 @@
   mp_clamp (c);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_mod_2d.c */
 
 /* Start: bn_mp_mod_d.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_MOD_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 int
 mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
 {
   return mp_div_d(a, b, NULL, c);
 }
+#endif
 
 /* End: bn_mp_mod_d.c */
 
 /* Start: bn_mp_montgomery_calc_normalization.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
-
-/* calculates a = B^n mod b for Montgomery reduction
- * Where B is the base [e.g. 2^DIGIT_BIT].
- * B^n mod b is computed by first computing
- * A = B^(n-1) which doesn't require a reduction but a simple OR.
- * then C = A * B = B^n is computed by performing upto DIGIT_BIT
+#include <ltc_tommath.h>
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+
+/*
  * shifts with subtractions when the result is greater than b.
  *
  * The method is slightly modified to shift B unconditionally upto just under
  * the leading bit of b.  This saves alot of multiple precision shifting.
  */
-int
-mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
+int mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
 {
   int     x, bits, res;
 
   /* how many bits of last digit does b use */
   bits = mp_count_bits (b) % DIGIT_BIT;
 
-  /* compute A = B^(n-1) * 2^(bits-1) */
-  if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
-    return res;
-  }
+
+  if (b->used > 1) {
+     if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
+        return res;
+     }
+  } else {
+     mp_set(a, 1);
+     bits = 1;
+  }
+
 
   /* now compute C = A * B mod b */
   for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
@@ -4262,25 +4509,27 @@
 
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_montgomery_calc_normalization.c */
 
 /* Start: bn_mp_montgomery_reduce.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* computes xR**-1 == x (mod N) via Montgomery Reduction */
 int
@@ -4291,7 +4540,7 @@
 
   /* can the fast reduction [comba] method be used?
    *
-   * Note that unlike in mp_mul you're safely allowed *less*
+   * Note that unlike in mul you're safely allowed *less*
    * than the available columns [255 per default] since carries
    * are fixed up in the inner loop.
    */
@@ -4314,7 +4563,7 @@
     /* mu = ai * rho mod b
      *
      * The value of rho must be precalculated via
-     * bn_mp_montgomery_setup() such that
+     * montgomery_setup() such that
      * it equals -1/n0 mod b this allows the
      * following inner loop to reduce the
      * input one digit at a time
@@ -4378,25 +4627,27 @@
 
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_montgomery_reduce.c */
 
 /* Start: bn_mp_montgomery_setup.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_MONTGOMERY_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* setups the montgomery reduction stuff */
 int
@@ -4431,29 +4682,31 @@
 #endif
 
   /* rho = -1/m mod b */
-  *rho = (((mp_digit) 1 << ((mp_digit) DIGIT_BIT)) - x) & MP_MASK;
+  *rho = (((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;
 
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_montgomery_setup.c */
 
 /* Start: bn_mp_mul.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* high level multiplication (handles sign) */
 int mp_mul (mp_int * a, mp_int * b, mp_int * c)
@@ -4462,12 +4715,18 @@
   neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
 
   /* use Toom-Cook? */
+#ifdef BN_MP_TOOM_MUL_C
   if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) {
     res = mp_toom_mul(a, b, c);
+  } else 
+#endif
+#ifdef BN_MP_KARATSUBA_MUL_C
   /* use Karatsuba? */
-  } else if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
+  if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
     res = mp_karatsuba_mul (a, b, c);
-  } else {
+  } else 
+#endif
+  {
     /* can we use the fast multiplier?
      *
      * The fast multiplier can be used if the output will 
@@ -4476,36 +4735,44 @@
      */
     int     digs = a->used + b->used + 1;
 
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
     if ((digs < MP_WARRAY) &&
         MIN(a->used, b->used) <= 
         (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
       res = fast_s_mp_mul_digs (a, b, c, digs);
-    } else {
-      res = s_mp_mul (a, b, c);
-    }
-  }
-  c->sign = neg;
+    } else 
+#endif
+#ifdef BN_S_MP_MUL_DIGS_C
+      res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
+#else
+      res = MP_VAL;
+#endif
+
+  }
+  c->sign = (c->used > 0) ? neg : MP_ZPOS;
   return res;
 }
+#endif
 
 /* End: bn_mp_mul.c */
 
 /* Start: bn_mp_mul_2.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_MUL_2_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* b = a*2 */
 int mp_mul_2(mp_int * a, mp_int * b)
@@ -4567,25 +4834,27 @@
   b->sign = a->sign;
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_mul_2.c */
 
 /* Start: bn_mp_mul_2d.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_MUL_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* shift left by a certain bit count */
 int mp_mul_2d (mp_int * a, int b, mp_int * c)
@@ -4650,25 +4919,27 @@
   mp_clamp (c);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_mul_2d.c */
 
 /* Start: bn_mp_mul_d.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_MUL_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* multiply by a digit */
 int
@@ -4726,25 +4997,27 @@
 
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_mul_d.c */
 
 /* Start: bn_mp_mulmod.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_MULMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* d = a * b (mod c) */
 int
@@ -4765,25 +5038,27 @@
   mp_clear (&t);
   return res;
 }
+#endif
 
 /* End: bn_mp_mulmod.c */
 
 /* Start: bn_mp_n_root.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_N_ROOT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* find the n'th root of an integer 
  *
@@ -4895,25 +5170,27 @@
 __T1:mp_clear (&t1);
   return res;
 }
+#endif
 
 /* End: bn_mp_n_root.c */
 
 /* Start: bn_mp_neg.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_NEG_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* b = -a */
 int mp_neg (mp_int * a, mp_int * b)
@@ -4927,25 +5204,27 @@
   }
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_neg.c */
 
 /* Start: bn_mp_or.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_OR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* OR two ints together */
 int mp_or (mp_int * a, mp_int * b, mp_int * c)
@@ -4975,25 +5254,27 @@
   mp_clear (&t);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_or.c */
 
 /* Start: bn_mp_prime_fermat.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_PRIME_FERMAT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* performs one Fermat test.
  * 
@@ -5035,25 +5316,27 @@
 __T:mp_clear (&t);
   return err;
 }
+#endif
 
 /* End: bn_mp_prime_fermat.c */
 
 /* Start: bn_mp_prime_is_divisible.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_PRIME_IS_DIVISIBLE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* determines if an integers is divisible by one 
  * of the first PRIME_SIZE primes or not
@@ -5083,30 +5366,32 @@
 
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_prime_is_divisible.c */
 
 /* Start: bn_mp_prime_is_prime.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_PRIME_IS_PRIME_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* performs a variable number of rounds of Miller-Rabin
  *
  * Probability of error after t rounds is no more than
- * (1/4)^t when 1 <= t <= PRIME_SIZE
+
  *
  * Sets result to 1 if probably prime, 0 otherwise
  */
@@ -5164,25 +5449,27 @@
 __B:mp_clear (&b);
   return err;
 }
+#endif
 
 /* End: bn_mp_prime_is_prime.c */
 
 /* Start: bn_mp_prime_miller_rabin.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_PRIME_MILLER_RABIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* Miller-Rabin test of "a" to the base of "b" as described in 
  * HAC pp. 139 Algorithm 4.24
@@ -5265,25 +5552,27 @@
 __N1:mp_clear (&n1);
   return err;
 }
+#endif
 
 /* End: bn_mp_prime_miller_rabin.c */
 
 /* Start: bn_mp_prime_next_prime.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_PRIME_NEXT_PRIME_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* finds the next prime after the number "a" using "t" trials
  * of Miller-Rabin.
@@ -5433,25 +5722,79 @@
    return err;
 }
 
+#endif
 
 /* End: bn_mp_prime_next_prime.c */
 
+/* Start: bn_mp_prime_rabin_miller_trials.c */
+#include <ltc_tommath.h>
+#ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+
+
+static const struct {
+   int k, t;
+} sizes[] = {
+{   128,    28 },
+{   256,    16 },
+{   384,    10 },
+{   512,     7 },
+{   640,     6 },
+{   768,     5 },
+{   896,     4 },
+{  1024,     4 }
+};
+
+/* returns # of RM trials required for a given bit size */
+int mp_prime_rabin_miller_trials(int size)
+{
+   int x;
+
+   for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) {
+       if (sizes[x].k == size) {
+          return sizes[x].t;
+       } else if (sizes[x].k > size) {
+          return (x == 0) ? sizes[0].t : sizes[x - 1].t;
+       }
+   }
+   return sizes[x-1].t + 1;
+}
+
+
+#endif
+
+/* End: bn_mp_prime_rabin_miller_trials.c */
+
 /* Start: bn_mp_prime_random_ex.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_PRIME_RANDOM_EX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* makes a truly random prime of a given size (bits),
  *
@@ -5531,6 +5874,9 @@
 
       /* is it prime? */
       if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY)           { goto error; }
+      if (res == MP_NO) {  
+         continue;
+      }
 
       if (flags & LTM_PRIME_SAFE) {
          /* see if (a-1)/2 is prime */
@@ -5555,25 +5901,27 @@
 }
 
 
+#endif
 
 /* End: bn_mp_prime_random_ex.c */
 
 /* Start: bn_mp_radix_size.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_RADIX_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* returns size of ASCII reprensentation */
 int mp_radix_size (mp_int * a, int radix, int *size)
@@ -5624,47 +5972,51 @@
   return MP_OKAY;
 }
 
+#endif
 
 /* End: bn_mp_radix_size.c */
 
 /* Start: bn_mp_radix_smap.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_RADIX_SMAP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* chars used in radix conversions */
 const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+#endif
 
 /* End: bn_mp_radix_smap.c */
 
 /* Start: bn_mp_rand.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_RAND_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* makes a pseudo-random int of a given size */
 int
@@ -5699,25 +6051,27 @@
 
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_rand.c */
 
 /* Start: bn_mp_read_radix.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_READ_RADIX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* read a string [ASCII] in a given radix */
 int mp_read_radix (mp_int * a, char *str, int radix)
@@ -5779,25 +6133,27 @@
   }
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_read_radix.c */
 
 /* Start: bn_mp_read_signed_bin.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_READ_SIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* read signed bin, big endian, first byte is 0==positive or 1==negative */
 int
@@ -5819,25 +6175,27 @@
 
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_read_signed_bin.c */
 
 /* Start: bn_mp_read_unsigned_bin.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_READ_UNSIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* reads a unsigned char array, assumes the msb is stored first [big endian] */
 int
@@ -5873,25 +6231,27 @@
   mp_clamp (a);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_read_unsigned_bin.c */
 
 /* Start: bn_mp_reduce.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* reduces x mod m, assumes 0 < x < m**2, mu is 
  * precomputed via mp_reduce_setup.
@@ -5917,9 +6277,20 @@
       goto CLEANUP;
     }
   } else {
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
     if ((res = s_mp_mul_high_digs (&q, mu, &q, um - 1)) != MP_OKAY) {
       goto CLEANUP;
     }
+#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+    if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um - 1)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+#else 
+    { 
+      res = MP_VAL;
+      goto CLEANUP;
+    }
+#endif
   }
 
   /* q3 = q2 / b**(k+1) */
@@ -5961,25 +6332,27 @@
 
   return res;
 }
+#endif
 
 /* End: bn_mp_reduce.c */
 
 /* Start: bn_mp_reduce_2k.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_REDUCE_2K_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* reduces a modulo n where n is of the form 2**p - d */
 int
@@ -6021,25 +6394,27 @@
    return res;
 }
 
+#endif
 
 /* End: bn_mp_reduce_2k.c */
 
 /* Start: bn_mp_reduce_2k_setup.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_REDUCE_2K_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* determines the setup value */
 int 
@@ -6067,30 +6442,33 @@
    mp_clear(&tmp);
    return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_reduce_2k_setup.c */
 
 /* Start: bn_mp_reduce_is_2k.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_REDUCE_IS_2K_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* determines if mp_reduce_2k can be used */
 int mp_reduce_is_2k(mp_int *a)
 {
-   int ix, iy, iz, iw;
+   int ix, iy, iw;
+   mp_digit iz;
    
    if (a->used == 0) {
       return 0;
@@ -6107,7 +6485,7 @@
              return 0;
           }
           iz <<= 1;
-          if (iz > (int)MP_MASK) {
+          if (iz > (mp_digit)MP_MASK) {
              ++iw;
              iz = 1;
           }
@@ -6116,31 +6494,32 @@
    return 1;
 }
 
+#endif
 
 /* End: bn_mp_reduce_is_2k.c */
 
 /* Start: bn_mp_reduce_setup.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_REDUCE_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* pre-calculate the value required for Barrett reduction
  * For a given modulus "b" it calulates the value required in "a"
  */
-int
-mp_reduce_setup (mp_int * a, mp_int * b)
+int mp_reduce_setup (mp_int * a, mp_int * b)
 {
   int     res;
   
@@ -6149,25 +6528,27 @@
   }
   return mp_div (a, b, a, NULL);
 }
+#endif
 
 /* End: bn_mp_reduce_setup.c */
 
 /* Start: bn_mp_rshd.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_RSHD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* shift right a certain amount of digits */
 void mp_rshd (mp_int * a, int b)
@@ -6219,25 +6600,27 @@
   /* remove excess digits */
   a->used -= b;
 }
+#endif
 
 /* End: bn_mp_rshd.c */
 
 /* Start: bn_mp_set.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_SET_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* set to a digit */
 void mp_set (mp_int * a, mp_digit b)
@@ -6246,25 +6629,27 @@
   a->dp[0] = b & MP_MASK;
   a->used  = (a->dp[0] != 0) ? 1 : 0;
 }
+#endif
 
 /* End: bn_mp_set.c */
 
 /* Start: bn_mp_set_int.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_SET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* set a 32-bit const */
 int mp_set_int (mp_int * a, unsigned long b)
@@ -6292,25 +6677,27 @@
   mp_clamp (a);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_set_int.c */
 
 /* Start: bn_mp_shrink.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_SHRINK_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* shrink a bignum */
 int mp_shrink (mp_int * a)
@@ -6325,50 +6712,54 @@
   }
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_shrink.c */
 
 /* Start: bn_mp_signed_bin_size.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_SIGNED_BIN_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* get the size for an signed equivalent */
 int mp_signed_bin_size (mp_int * a)
 {
   return 1 + mp_unsigned_bin_size (a);
 }
+#endif
 
 /* End: bn_mp_signed_bin_size.c */
 
 /* Start: bn_mp_sqr.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* computes b = a*a */
 int
@@ -6376,44 +6767,57 @@
 {
   int     res;
 
+#ifdef BN_MP_TOOM_SQR_C
   /* use Toom-Cook? */
   if (a->used >= TOOM_SQR_CUTOFF) {
     res = mp_toom_sqr(a, b);
   /* Karatsuba? */
-  } else if (a->used >= KARATSUBA_SQR_CUTOFF) {
+  } else 
+#endif
+#ifdef BN_MP_KARATSUBA_SQR_C
+if (a->used >= KARATSUBA_SQR_CUTOFF) {
     res = mp_karatsuba_sqr (a, b);
-  } else {
+  } else 
+#endif
+  {
+#ifdef BN_FAST_S_MP_SQR_C
     /* can we use the fast comba multiplier? */
     if ((a->used * 2 + 1) < MP_WARRAY && 
          a->used < 
          (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
       res = fast_s_mp_sqr (a, b);
-    } else {
+    } else
+#endif
+#ifdef BN_S_MP_SQR_C
       res = s_mp_sqr (a, b);
-    }
+#else
+      res = MP_VAL;
+#endif
   }
   b->sign = MP_ZPOS;
   return res;
 }
+#endif
 
 /* End: bn_mp_sqr.c */
 
 /* Start: bn_mp_sqrmod.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_SQRMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* c = a * a (mod b) */
 int
@@ -6434,25 +6838,27 @@
   mp_clear (&t);
   return res;
 }
+#endif
 
 /* End: bn_mp_sqrmod.c */
 
 /* Start: bn_mp_sqrt.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_SQRT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* this function is less generic than mp_n_root, simpler and faster */
 int mp_sqrt(mp_int *arg, mp_int *ret) 
@@ -6513,25 +6919,27 @@
   return res;
 }
 
+#endif
 
 /* End: bn_mp_sqrt.c */
 
 /* Start: bn_mp_sub.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_SUB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* high level subtraction (handles signs) */
 int
@@ -6570,25 +6978,27 @@
   return res;
 }
 
+#endif
 
 /* End: bn_mp_sub.c */
 
 /* Start: bn_mp_sub_d.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_SUB_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* single digit subtraction */
 int
@@ -6657,25 +7067,27 @@
   return MP_OKAY;
 }
 
+#endif
 
 /* End: bn_mp_sub_d.c */
 
 /* Start: bn_mp_submod.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_SUBMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* d = a - b (mod c) */
 int
@@ -6697,25 +7109,27 @@
   mp_clear (&t);
   return res;
 }
+#endif
 
 /* End: bn_mp_submod.c */
 
 /* Start: bn_mp_to_signed_bin.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_TO_SIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* store in signed [big endian] format */
 int
@@ -6729,25 +7143,27 @@
   b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_to_signed_bin.c */
 
 /* Start: bn_mp_to_unsigned_bin.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_TO_UNSIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* store in unsigned [big endian] format */
 int
@@ -6776,27 +7192,34 @@
   mp_clear (&t);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_to_unsigned_bin.c */
 
 /* Start: bn_mp_toom_mul.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
-
-/* multiplication using the Toom-Cook 3-way algorithm */
+#include <ltc_tommath.h>
+#ifdef BN_MP_TOOM_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+
+/* multiplication using the Toom-Cook 3-way algorithm 
+ *
+ * Much more complicated than Karatsuba but has a lower asymptotic running time of 
+ * O(N**1.464).  This algorithm is only particularly useful on VERY large
+ * inputs (we're talking 1000s of digits here...).
+*/
 int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
 {
     mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
@@ -7052,25 +7475,27 @@
      return res;
 }     
      
+#endif
 
 /* End: bn_mp_toom_mul.c */
 
 /* Start: bn_mp_toom_sqr.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_TOOM_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* squaring using Toom-Cook 3-way algorithm */
 int
@@ -7276,25 +7701,27 @@
      return res;
 }
 
+#endif
 
 /* End: bn_mp_toom_sqr.c */
 
 /* Start: bn_mp_toradix.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_TORADIX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* stores a bignum as a ASCII string in a given radix (2..64) */
 int mp_toradix (mp_int * a, char *str, int radix)
@@ -7349,25 +7776,27 @@
   return MP_OKAY;
 }
 
+#endif
 
 /* End: bn_mp_toradix.c */
 
 /* Start: bn_mp_toradix_n.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_TORADIX_N_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* stores a bignum as a ASCII string in a given radix (2..64) 
  *
@@ -7436,25 +7865,27 @@
   return MP_OKAY;
 }
 
+#endif
 
 /* End: bn_mp_toradix_n.c */
 
 /* Start: bn_mp_unsigned_bin_size.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_UNSIGNED_BIN_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* get the size for an unsigned equivalent */
 int
@@ -7463,25 +7894,27 @@
   int     size = mp_count_bits (a);
   return (size / 8 + ((size & 7) != 0 ? 1 : 0));
 }
+#endif
 
 /* End: bn_mp_unsigned_bin_size.c */
 
 /* Start: bn_mp_xor.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_XOR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* XOR two ints together */
 int
@@ -7505,32 +7938,34 @@
   }
 
   for (ix = 0; ix < px; ix++) {
-    t.dp[ix] ^= x->dp[ix];
+
   }
   mp_clamp (&t);
   mp_exch (c, &t);
   mp_clear (&t);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_mp_xor.c */
 
 /* Start: bn_mp_zero.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_MP_ZERO_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* set to zero */
 void
@@ -7540,80 +7975,27 @@
   a->used = 0;
   memset (a->dp, 0, sizeof (mp_digit) * a->alloc);
 }
+#endif
 
 /* End: bn_mp_zero.c */
 
-/* Start: bn_prime_sizes_tab.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
-
-/* this table gives the # of rabin miller trials for a prob of failure lower than 2^-96 */
-static const struct {
-   int k, t;
-} sizes[] = {
-{   128,    28 },
-{   256,    16 },
-{   384,    10 },
-{   512,     7 },
-{   640,     6 },
-{   768,     5 },
-{   896,     4 },
-{  1024,     4 },
-{  1152,     3 },
-{  1280,     3 },
-{  1408,     3 },
-{  1536,     3 },
-{  1664,     3 },
-{  1792,     2 } };
-
-/* returns # of RM trials required for a given bit size */
-int mp_prime_rabin_miller_trials(int size)
-{
-   int x;
-
-   for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) {
-       if (sizes[x].k == size) {
-          return sizes[x].t;
-       } else if (sizes[x].k > size) {
-          return (x == 0) ? sizes[0].t : sizes[x - 1].t;
-       }
-   }
-   return 1;
-}
-
-
-
-/* End: bn_prime_sizes_tab.c */
-
 /* Start: bn_prime_tab.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_PRIME_TAB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 const mp_digit __prime_tab[] = {
   0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
   0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
@@ -7654,25 +8036,27 @@
   0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
 #endif
 };
+#endif
 
 /* End: bn_prime_tab.c */
 
 /* Start: bn_reverse.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_REVERSE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* reverse an array, used for radix code */
 void
@@ -7691,25 +8075,27 @@
     --iy;
   }
 }
+#endif
 
 /* End: bn_reverse.c */
 
 /* Start: bn_s_mp_add.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_S_MP_ADD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* low level addition, based on HAC pp.594, Algorithm 14.7 */
 int
@@ -7798,25 +8184,27 @@
   mp_clamp (c);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_s_mp_add.c */
 
 /* Start: bn_s_mp_exptmod.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_S_MP_EXPTMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 #ifdef MP_LOW_MEM
    #define TAB_SIZE 32
@@ -8036,25 +8424,27 @@
   }
   return err;
 }
+#endif
 
 /* End: bn_s_mp_exptmod.c */
 
 /* Start: bn_s_mp_mul_digs.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_S_MP_MUL_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* multiplies |a| * |b| and only computes upto digs digits of result
  * HAC pp. 595, Algorithm 14.12  Modified so you can control how 
@@ -8125,25 +8515,27 @@
   mp_clear (&t);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_s_mp_mul_digs.c */
 
 /* Start: bn_s_mp_mul_high_digs.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* multiplies |a| * |b| and does not compute the lower digs digits
  * [meant to get the higher part of the product]
@@ -8158,10 +8550,12 @@
   mp_digit tmpx, *tmpt, *tmpy;
 
   /* can we use the fast multiplier? */
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
   if (((a->used + b->used + 1) < MP_WARRAY)
       && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
     return fast_s_mp_mul_high_digs (a, b, c, digs);
   }
+#endif
 
   if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
     return res;
@@ -8202,25 +8596,27 @@
   mp_clear (&t);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_s_mp_mul_high_digs.c */
 
 /* Start: bn_s_mp_sqr.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_S_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
 int
@@ -8285,25 +8681,27 @@
   mp_clear (&t);
   return MP_OKAY;
 }
+#endif
 
 /* End: bn_s_mp_sqr.c */
 
 /* Start: bn_s_mp_sub.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BN_S_MP_SUB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
 int
@@ -8372,43 +8770,42 @@
   return MP_OKAY;
 }
 
+#endif
 
 /* End: bn_s_mp_sub.c */
 
 /* Start: bncore.c */
-/* LibTomMath, multiple-precision integer library -- Tom St Denis
- *
- * LibTomMath is a library that provides multiple-precision
- * integer arithmetic as well as number theoretic functionality.
- *
- * The library was designed directly after the MPI library by
- * Michael Fromberger but has been written from scratch with
- * additional optimizations in place.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, [email protected], http://math.libtomcrypt.org
- */
-#include <ltc_tommath.h>
+#include <ltc_tommath.h>
+#ifdef BNCORE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
 
 /* Known optimal configurations
 
  CPU                    /Compiler     /MUL CUTOFF/SQR CUTOFF
 -------------------------------------------------------------
- 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/
+ Intel P4 Northwood     /GCC v3.4.1   /        88/       128/LTM 0.32 ;-)
  
 */
 
-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. */
+int     KARATSUBA_MUL_CUTOFF = 88,      /* Min. number of digits before Karatsuba multiplication is used. */
+        KARATSUBA_SQR_CUTOFF = 128,     /* 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; 
+#endif
 
 /* End: bncore.c */
 
--- a/mycrypt.h	Tue Jun 15 14:07:21 2004 +0000
+++ b/mycrypt.h	Sun Dec 19 11:34:45 2004 +0000
@@ -16,14 +16,14 @@
 #endif
 
 /* version */
-#define CRYPT   0x0096
-#define SCRYPT  "0.96"
+#define CRYPT   0x0099
+#define SCRYPT  "0.99"
 
 /* max size of either a cipher/hash block or symmetric key [largest of the two] */
-#define MAXBLOCKSIZE           128
+#define MAXBLOCKSIZE  64
 
 /* descriptor table size */
-#define TAB_SIZE    32
+#define TAB_SIZE      32
 
 /* error codes [will be expanded in future releases] */
 enum {
--- a/mycrypt_argchk.h	Tue Jun 15 14:07:21 2004 +0000
+++ b/mycrypt_argchk.h	Sun Dec 19 11:34:45 2004 +0000
@@ -1,13 +1,11 @@
 /* Defines the _ARGCHK macro used within the library */
-
-/* ch1-01-1 */
 /* ARGTYPE is defined in mycrypt_cfg.h */
 #if ARGTYPE == 0
 
 #include <signal.h>
 
 /* this is the default LibTomCrypt macro  */
-extern void crypt_argchk(char *v, char *s, int d);
+void crypt_argchk(char *v, char *s, int d);
 #define _ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); }
 
 #elif ARGTYPE == 1
@@ -20,5 +18,4 @@
 #define _ARGCHK(x) 
 
 #endif
-/* ch1-01-1 */
 
--- a/mycrypt_cfg.h	Tue Jun 15 14:07:21 2004 +0000
+++ b/mycrypt_cfg.h	Sun Dec 19 11:34:45 2004 +0000
@@ -8,20 +8,28 @@
 #define MYCRYPT_CFG_H
 
 /* you can change how memory allocation works ... */
-extern void *XMALLOC(size_t n);
-extern void *REALLOC(void *p, size_t n);
-extern void *XCALLOC(size_t n, size_t s);
-extern void XFREE(void *p);
+void *XMALLOC(size_t n);
+void *REALLOC(void *p, size_t n);
+void *XCALLOC(size_t n, size_t s);
+void XFREE(void *p);
 
 /* change the clock function too */
-extern clock_t XCLOCK(void);
+ clock_t XCLOCK(void);
 
-/* ch1-01-1 */
+/* various other functions */
+void *XMEMCPY(void *dest, const void *src, size_t n);
+int   XMEMCMP(const void *s1, const void *s2, size_t n);
+
 /* type of argument checking, 0=default, 1=fatal and 2=none */
 #define ARGTYPE  0
-/* ch1-01-1 */
 
-/* Controls endianess and size of registers.  Leave uncommented to get platform neutral [slower] code */
+/* Controls endianess and size of registers.  Leave uncommented to get platform neutral [slower] code 
+ * 
+ * Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes.
+ * The x86 platforms allow this but some others [ARM for instance] do not.  On those platforms you **MUST**
+ * use the portable [slower] macros.
+ */
+
 /* detect x86-32 machines somewhat */
 #if defined(INTEL_CC) || (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__)))
    #define ENDIAN_LITTLE
@@ -34,6 +42,12 @@
    #define ENDIAN_64BITWORD
 #endif
 
+/* detect amd64 */
+#if defined(__x86_64__)
+   #define ENDIAN_LITTLE
+   #define ENDIAN_64BITWORD
+#endif
+
 /* #define ENDIAN_LITTLE */
 /* #define ENDIAN_BIG */
 
@@ -48,12 +62,6 @@
    #define ENDIAN_NEUTRAL
 #endif
 
-#ifdef YARROW
-   #ifndef CTR
-      #error YARROW requires CTR chaining mode to be defined!
-   #endif
-#endif
-
 /* packet code */
 #if defined(MRSA) || defined(MDH) || defined(MECC)
     #define PACKET
--- a/mycrypt_cipher.h	Tue Jun 15 14:07:21 2004 +0000
+++ b/mycrypt_cipher.h	Sun Dec 19 11:34:45 2004 +0000
@@ -179,7 +179,7 @@
 } symmetric_CTR;
 
 /* cipher descriptor table, last entry has "name == NULL" to mark the end of table */
-extern  struct _cipher_descriptor {
+extern struct _cipher_descriptor {
    char *name;
    unsigned char ID;
    int  min_key_length, max_key_length, block_length, default_rounds;
@@ -191,65 +191,65 @@
 } cipher_descriptor[];
 
 #ifdef BLOWFISH
-extern int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
-extern void blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
-extern void blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
-extern int blowfish_test(void);
-extern int blowfish_keysize(int *desired_keysize);
-extern const struct _cipher_descriptor blowfish_desc;
+ int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ void blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+ void blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+ int blowfish_test(void);
+ int blowfish_keysize(int *desired_keysize);
+ extern const struct _cipher_descriptor blowfish_desc;
 #endif
 
 #ifdef RC5
-extern int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
-extern void rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
-extern void rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
-extern int rc5_test(void);
-extern int rc5_keysize(int *desired_keysize);
-extern const struct _cipher_descriptor rc5_desc;
+ int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ void rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+ void rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+ int rc5_test(void);
+ int rc5_keysize(int *desired_keysize);
+ extern const struct _cipher_descriptor rc5_desc;
 #endif
 
 #ifdef RC6
-extern int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
-extern void rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
-extern void rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
-extern int rc6_test(void);
-extern int rc6_keysize(int *desired_keysize);
-extern const struct _cipher_descriptor rc6_desc;
+ int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ void rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+ void rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+ int rc6_test(void);
+ int rc6_keysize(int *desired_keysize);
+ extern const struct _cipher_descriptor rc6_desc;
 #endif
 
 #ifdef RC2
-extern int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
-extern void rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
-extern void rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
-extern int rc2_test(void);
-extern int rc2_keysize(int *desired_keysize);
-extern const struct _cipher_descriptor rc2_desc;
+ int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ void rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+ void rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+ int rc2_test(void);
+ int rc2_keysize(int *desired_keysize);
+ extern const struct _cipher_descriptor rc2_desc;
 #endif
 
 #ifdef SAFERP
-extern int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
-extern void saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
-extern void saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
-extern int saferp_test(void);
-extern int saferp_keysize(int *desired_keysize);
-extern const struct _cipher_descriptor saferp_desc;
+ int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ void saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+ void saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+ int saferp_test(void);
+ int saferp_keysize(int *desired_keysize);
+ extern const struct _cipher_descriptor saferp_desc;
 #endif
 
 #ifdef SAFER
-extern int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
-extern int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
-extern int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
-extern int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
-extern void safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
-extern void safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+ int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ void safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+ void safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
 
-extern int safer_k64_test(void);
-extern int safer_sk64_test(void);
-extern int safer_sk128_test(void);
+ int safer_k64_test(void);
+ int safer_sk64_test(void);
+ int safer_sk128_test(void);
 
-extern int safer_64_keysize(int *desired_keysize);
-extern int safer_128_keysize(int *desired_keysize);
-extern const struct _cipher_descriptor safer_k64_desc, safer_k128_desc, safer_sk64_desc, safer_sk128_desc;
+ int safer_64_keysize(int *desired_keysize);
+ int safer_128_keysize(int *desired_keysize);
+ extern const struct _cipher_descriptor safer_k64_desc, safer_k128_desc, safer_sk64_desc, safer_sk128_desc;
 #endif
 
 #ifdef RIJNDAEL
@@ -265,132 +265,132 @@
 #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);
+ int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+ void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+ int rijndael_test(void);
+ 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);
+ int rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ void rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+ 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;
+ extern const struct _cipher_descriptor rijndael_desc, aes_desc;
+ extern const struct _cipher_descriptor rijndael_enc_desc, aes_enc_desc;
 #endif
 
 #ifdef XTEA
-extern int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
-extern void xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
-extern void xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
-extern int xtea_test(void);
-extern int xtea_keysize(int *desired_keysize);
-extern const struct _cipher_descriptor xtea_desc;
+ int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ void xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+ void xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+ int xtea_test(void);
+ int xtea_keysize(int *desired_keysize);
+ extern const struct _cipher_descriptor xtea_desc;
 #endif
 
 #ifdef TWOFISH
-extern int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
-extern void twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
-extern void twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
-extern int twofish_test(void);
-extern int twofish_keysize(int *desired_keysize);
-extern const struct _cipher_descriptor twofish_desc;
+ int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ void twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+ void twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+ int twofish_test(void);
+ int twofish_keysize(int *desired_keysize);
+ extern const struct _cipher_descriptor twofish_desc;
 #endif
 
 #ifdef DES
-extern int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
-extern void des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
-extern void des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
-extern int des_test(void);
-extern int des_keysize(int *desired_keysize);
+ int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ void des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+ void des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+ int des_test(void);
+ int des_keysize(int *desired_keysize);
 
-extern int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
-extern void des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
-extern void des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
-extern int des3_test(void);
-extern int des3_keysize(int *desired_keysize);
+ int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ void des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+ void des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+ int des3_test(void);
+ int des3_keysize(int *desired_keysize);
 
-extern const struct _cipher_descriptor des_desc, des3_desc;
+ extern const struct _cipher_descriptor des_desc, des3_desc;
 #endif
 
 #ifdef CAST5
-extern int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
-extern void cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
-extern void cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
-extern int cast5_test(void);
-extern int cast5_keysize(int *desired_keysize);
-extern const struct _cipher_descriptor cast5_desc;
+ int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ void cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+ void cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+ int cast5_test(void);
+ int cast5_keysize(int *desired_keysize);
+ extern const struct _cipher_descriptor cast5_desc;
 #endif
 
 #ifdef NOEKEON
-extern int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
-extern void noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
-extern void noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
-extern int noekeon_test(void);
-extern int noekeon_keysize(int *desired_keysize);
-extern const struct _cipher_descriptor noekeon_desc;
+ int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ void noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+ void noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+ int noekeon_test(void);
+ int noekeon_keysize(int *desired_keysize);
+ extern const struct _cipher_descriptor noekeon_desc;
 #endif
 
 #ifdef SKIPJACK
-extern int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
-extern void skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
-extern void skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
-extern int skipjack_test(void);
-extern int skipjack_keysize(int *desired_keysize);
-extern const struct _cipher_descriptor skipjack_desc;
+ int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+ void skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
+ void skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
+ int skipjack_test(void);
+ int skipjack_keysize(int *desired_keysize);
+ extern const struct _cipher_descriptor skipjack_desc;
 #endif
 
 #ifdef ECB
-extern int ecb_start(int cipher, const unsigned char *key, 
+ int ecb_start(int cipher, const unsigned char *key, 
                      int keylen, int num_rounds, symmetric_ECB *ecb);
-extern int ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_ECB *ecb);
-extern int ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_ECB *ecb);
+ int ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_ECB *ecb);
+ int ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_ECB *ecb);
 #endif
 
 #ifdef CFB
-extern int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, 
+ int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, 
                      int keylen, int num_rounds, symmetric_CFB *cfb);
-extern int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb);
-extern int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb);
-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);
+ int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb);
+ int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb);
+ int cfb_getiv(unsigned char *IV, unsigned long *len, symmetric_CFB *cfb);
+ int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb);
 #endif
 
 #ifdef OFB
-extern int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, 
+ int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, 
                      int keylen, int num_rounds, symmetric_OFB *ofb);
-extern int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb);
-extern int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb);
-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);
+ int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb);
+ int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb);
+ int ofb_getiv(unsigned char *IV, unsigned long *len, symmetric_OFB *ofb);
+ int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb);
 #endif
 
 #ifdef CBC
-extern int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
+ 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);
-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);
+ int cbc_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_CBC *cbc);
+ int cbc_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_CBC *cbc);
+ int cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc);
+ int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc);
 #endif
 
 #ifdef CTR
-extern int ctr_start(int cipher, const unsigned char *IV, const unsigned char *key, 
+ int ctr_start(int cipher, const unsigned char *IV, const unsigned char *key, 
                      int keylen, int num_rounds, symmetric_CTR *ctr);
-extern int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr);
-extern int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr);
-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);
+ int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr);
+ int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr);
+ int ctr_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr);
+ int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr);
 #endif
 
 
     
-extern int find_cipher(const char *name);
-extern int find_cipher_any(const char *name, int blocklen, int keylen);
-extern int find_cipher_id(unsigned char ID);
+ int find_cipher(const char *name);
+ int find_cipher_any(const char *name, int blocklen, int keylen);
+ int find_cipher_id(unsigned char ID);
 
-extern int register_cipher(const struct _cipher_descriptor *cipher);
-extern int unregister_cipher(const struct _cipher_descriptor *cipher);
+ int register_cipher(const struct _cipher_descriptor *cipher);
+ int unregister_cipher(const struct _cipher_descriptor *cipher);
 
-extern int cipher_is_valid(int idx);
+ int cipher_is_valid(int idx);
 
--- a/mycrypt_custom.h	Tue Jun 15 14:07:21 2004 +0000
+++ b/mycrypt_custom.h	Sun Dec 19 11:34:45 2004 +0000
@@ -5,29 +5,29 @@
 #ifndef MYCRYPT_CUSTOM_H_
 #define MYCRYPT_CUSTOM_H_
 
-#ifdef CRYPT
-	#error mycrypt_custom.h should be included before mycrypt.h
-#endif
+/* macros for various libc functions you can change for embedded targets */
+#define XMALLOC  malloc
+#define XREALLOC realloc
+#define XCALLOC  calloc
+#define XFREE    free
 
-/* macros for various libc functions */
-#define XMALLOC malloc
-#define XREALLOC realloc
-#define XCALLOC calloc
-#define XFREE free
-#define XCLOCK clock
+#define XMEMSET  memset
+#define XMEMCPY  memcpy
+
+#define XCLOCK   clock
 #define XCLOCKS_PER_SEC CLOCKS_PER_SEC
 
 /* Use small code where possible */
-#define SMALL_CODE
+// #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
+// #define CLEAN_STACK
 
 /* disable all file related functions */
-//#define NO_FILE
+// #define NO_FILE
 
 /* various ciphers */
 #define BLOWFISH
@@ -37,16 +37,23 @@
 #define SAFERP
 #define RIJNDAEL
 #define XTEA
+/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format
+ * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */
 #define TWOFISH
 #define TWOFISH_TABLES
-//#define TWOFISH_ALL_TABLES
-//#define TWOFISH_SMALL
+// #define TWOFISH_ALL_TABLES
+// #define TWOFISH_SMALL
+/* DES includes EDE triple-DES */
 #define DES
 #define CAST5
 #define NOEKEON
 #define SKIPJACK
+/* SAFER code isn't public domain.  It appears to be free to use 
+ * but has been disabled by default to avoid any such problems 
+ */
+//#define SAFER
 
-/* modes of operation */
+/* block cipher modes of operation */
 #define CFB
 #define OFB
 #define ECB
@@ -54,6 +61,7 @@
 #define CTR
 
 /* hash functions */
+#define CHC_HASH
 #define WHIRLPOOL
 #define SHA512
 #define SHA384
@@ -78,21 +86,48 @@
 
 /* Various tidbits of modern neatoness */
 #define BASE64
+
+/* Yarrow */
 #define YARROW
 // which descriptor of AES to use? 
 // 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full]
 #define YARROW_AES 0
+
+#if defined(YARROW) && !defined(CTR)
+   #error YARROW requires CTR chaining mode to be defined!
+#endif
+
 #define SPRNG
 #define RC4
+
+/* Fortuna PRNG */
+#define FORTUNA
+/* reseed every N calls to the read function */
+#define FORTUNA_WD    10
+/* number of pools (4..32) can save a bit of ram by lowering the count */
+#define FORTUNA_POOLS 32
+
+/* Greg's SOBER128 PRNG ;-0 */
+#define SOBER128
+
 #define DEVRANDOM
 #define TRY_URANDOM_FIRST
 
 /* Public Key Neatoness */
 #define MRSA
-#define RSA_TIMING                   // enable RSA side channel timing prevention 
+/* enable RSA side channel timing prevention */
+#define RSA_TIMING
+
+/* Digital Signature Algorithm */
 #define MDSA
+/* Max diff between group and modulus size in bytes */
+#define MDSA_DELTA     512
+/* Max DSA group size in bytes (default allows 4k-bit groups) */
+#define MDSA_MAX_GROUP 512
+
+/* Diffie-Hellman */
 #define MDH
-#define MECC
+/* Supported Key Sizes */
 #define DH768
 #define DH1024
 #define DH1280
@@ -102,19 +137,23 @@
 #define DH2560
 #define DH3072
 #define DH4096
+
+/* ECC */
+#define MECC
+/* Supported Key Sizes */
 #define ECC160
 #define ECC192
 #define ECC224
 #define ECC256
 #define ECC384
 #define ECC521
+
+/* Include the MPI functionality?  (required by the PK algorithms) */
 #define MPI
 
-/* PKCS #1 and 5 stuff */
+/* PKCS #1 (RSA) and #5 (Password Handling) stuff */
 #define PKCS_1
 #define PKCS_5
 
-#include <mycrypt.h>
-
 #endif
 
--- a/mycrypt_hash.h	Tue Jun 15 14:07:21 2004 +0000
+++ b/mycrypt_hash.h	Sun Dec 19 11:34:45 2004 +0000
@@ -78,7 +78,18 @@
 };
 #endif
 
+#ifdef CHC_HASH
+struct chc_state {
+    ulong64 length;
+    unsigned char state[MAXBLOCKSIZE], buf[MAXBLOCKSIZE];
+    ulong32 curlen;
+};
+#endif
+
 typedef union Hash_state {
+#ifdef CHC_HASH
+    struct chc_state chc;
+#endif
 #ifdef WHIRLPOOL
     struct whirlpool_state whirlpool;
 #endif
@@ -111,139 +122,147 @@
 #endif
 } hash_state;
 
-extern struct _hash_descriptor {
+extern  struct _hash_descriptor {
     char *name;
     unsigned char ID;
     unsigned long hashsize;       /* digest output size in bytes  */
     unsigned long blocksize;      /* the block size the hash uses */
     unsigned char DER[64];        /* DER encoded identifier */
     unsigned long DERlen;         /* length of DER encoding */
-    void (*init)(hash_state *);
+    int (*init)(hash_state *);
     int (*process)(hash_state *, const unsigned char *, unsigned long);
     int (*done)(hash_state *, unsigned char *);
-    int  (*test)(void);
+    int (*test)(void);
 } hash_descriptor[];
 
+#ifdef CHC_HASH
+ int chc_register(int cipher);
+ int chc_init(hash_state * md);
+ int chc_process(hash_state * md, const unsigned char *buf, unsigned long len);
+ int chc_done(hash_state * md, unsigned char *hash);
+ int chc_test(void);
+ extern const struct _hash_descriptor chc_desc;
+#endif
 
 #ifdef WHIRLPOOL
-extern void whirlpool_init(hash_state * md);
-extern int whirlpool_process(hash_state * md, const unsigned char *buf, unsigned long len);
-extern int whirlpool_done(hash_state * md, unsigned char *hash);
-extern int  whirlpool_test(void);
-extern const struct _hash_descriptor whirlpool_desc;
+ int whirlpool_init(hash_state * md);
+ int whirlpool_process(hash_state * md, const unsigned char *buf, unsigned long len);
+ int whirlpool_done(hash_state * md, unsigned char *hash);
+ int whirlpool_test(void);
+ extern const struct _hash_descriptor whirlpool_desc;
 #endif
 
 #ifdef SHA512
-extern void sha512_init(hash_state * md);
-extern int sha512_process(hash_state * md, const unsigned char *buf, unsigned long len);
-extern int sha512_done(hash_state * md, unsigned char *hash);
-extern int  sha512_test(void);
-extern const struct _hash_descriptor sha512_desc;
+ int sha512_init(hash_state * md);
+ int sha512_process(hash_state * md, const unsigned char *buf, unsigned long len);
+ int sha512_done(hash_state * md, unsigned char *hash);
+ int sha512_test(void);
+ extern const struct _hash_descriptor sha512_desc;
 #endif
 
 #ifdef SHA384
 #ifndef SHA512
    #error SHA512 is required for SHA384
 #endif
-extern void sha384_init(hash_state * md);
+ int sha384_init(hash_state * md);
 #define sha384_process sha512_process
-extern int sha384_done(hash_state * md, unsigned char *hash);
-extern int  sha384_test(void);
-extern const struct _hash_descriptor sha384_desc;
+ int sha384_done(hash_state * md, unsigned char *hash);
+ int sha384_test(void);
+ extern const struct _hash_descriptor sha384_desc;
 #endif
 
 #ifdef SHA256
-extern void sha256_init(hash_state * md);
-extern int sha256_process(hash_state * md, const unsigned char *buf, unsigned long len);
-extern int sha256_done(hash_state * md, unsigned char *hash);
-extern int  sha256_test(void);
-extern const struct _hash_descriptor sha256_desc;
+ int sha256_init(hash_state * md);
+ int sha256_process(hash_state * md, const unsigned char *buf, unsigned long len);
+ int sha256_done(hash_state * md, unsigned char *hash);
+ int sha256_test(void);
+ extern const struct _hash_descriptor sha256_desc;
 
 #ifdef SHA224
 #ifndef SHA256
    #error SHA256 is required for SHA224
 #endif
-extern void sha224_init(hash_state * md);
+ int sha224_init(hash_state * md);
 #define sha224_process sha256_process
-extern int sha224_done(hash_state * md, unsigned char *hash);
-extern int  sha224_test(void);
-extern const struct _hash_descriptor sha224_desc;
+ int sha224_done(hash_state * md, unsigned char *hash);
+ int sha224_test(void);
+ extern const struct _hash_descriptor sha224_desc;
 #endif
 #endif
 
 #ifdef SHA1
-extern void sha1_init(hash_state * md);
-extern int sha1_process(hash_state * md, const unsigned char *buf, unsigned long len);
-extern int sha1_done(hash_state * md, unsigned char *hash);
-extern int  sha1_test(void);
-extern const struct _hash_descriptor sha1_desc;
+ int sha1_init(hash_state * md);
+ int sha1_process(hash_state * md, const unsigned char *buf, unsigned long len);
+ int sha1_done(hash_state * md, unsigned char *hash);
+ int sha1_test(void);
+ extern const struct _hash_descriptor sha1_desc;
 #endif
 
 #ifdef MD5
-extern void md5_init(hash_state * md);
-extern int md5_process(hash_state * md, const unsigned char *buf, unsigned long len);
-extern int md5_done(hash_state * md, unsigned char *hash);
-extern int  md5_test(void);
-extern const struct _hash_descriptor md5_desc;
+ int md5_init(hash_state * md);
+ int md5_process(hash_state * md, const unsigned char *buf, unsigned long len);
+ int md5_done(hash_state * md, unsigned char *hash);
+ int md5_test(void);
+ extern const struct _hash_descriptor md5_desc;
 #endif
 
 #ifdef MD4
-extern void md4_init(hash_state * md);
-extern int md4_process(hash_state * md, const unsigned char *buf, unsigned long len);
-extern int md4_done(hash_state * md, unsigned char *hash);
-extern int  md4_test(void);
-extern const struct _hash_descriptor md4_desc;
+ int md4_init(hash_state * md);
+ int md4_process(hash_state * md, const unsigned char *buf, unsigned long len);
+ int md4_done(hash_state * md, unsigned char *hash);
+ int md4_test(void);
+ extern const struct _hash_descriptor md4_desc;
 #endif
 
 #ifdef MD2
-extern void md2_init(hash_state * md);
-extern int md2_process(hash_state * md, const unsigned char *buf, unsigned long len);
-extern int md2_done(hash_state * md, unsigned char *hash);
-extern int  md2_test(void);
-extern const struct _hash_descriptor md2_desc;
+ int md2_init(hash_state * md);
+ int md2_process(hash_state * md, const unsigned char *buf, unsigned long len);
+ int md2_done(hash_state * md, unsigned char *hash);
+ int md2_test(void);
+ extern const struct _hash_descriptor md2_desc;
 #endif
 
 #ifdef TIGER
-extern void tiger_init(hash_state * md);
-extern int tiger_process(hash_state * md, const unsigned char *buf, unsigned long len);
-extern int tiger_done(hash_state * md, unsigned char *hash);
-extern int  tiger_test(void);
-extern const struct _hash_descriptor tiger_desc;
+ int tiger_init(hash_state * md);
+ int tiger_process(hash_state * md, const unsigned char *buf, unsigned long len);
+ int tiger_done(hash_state * md, unsigned char *hash);
+ int tiger_test(void);
+ extern const struct _hash_descriptor tiger_desc;
 #endif
 
 #ifdef RIPEMD128
-extern void rmd128_init(hash_state * md);
-extern int rmd128_process(hash_state * md, const unsigned char *buf, unsigned long len);
-extern int rmd128_done(hash_state * md, unsigned char *hash);
-extern int  rmd128_test(void);
-extern const struct _hash_descriptor rmd128_desc;
+ int rmd128_init(hash_state * md);
+ int rmd128_process(hash_state * md, const unsigned char *buf, unsigned long len);
+ int rmd128_done(hash_state * md, unsigned char *hash);
+ int rmd128_test(void);
+ extern const struct _hash_descriptor rmd128_desc;
 #endif
 
 #ifdef RIPEMD160
-extern void rmd160_init(hash_state * md);
-extern int rmd160_process(hash_state * md, const unsigned char *buf, unsigned long len);
-extern int rmd160_done(hash_state * md, unsigned char *hash);
-extern int  rmd160_test(void);
-extern const struct _hash_descriptor rmd160_desc;
+ int rmd160_init(hash_state * md);
+ int rmd160_process(hash_state * md, const unsigned char *buf, unsigned long len);
+ int rmd160_done(hash_state * md, unsigned char *hash);
+ int rmd160_test(void);
+ extern const struct _hash_descriptor rmd160_desc;
 #endif
 
+ int find_hash(const char *name);
+ int find_hash_id(unsigned char ID);
+ int find_hash_any(const char *name, int digestlen);
+ int register_hash(const struct _hash_descriptor *hash);
+ int unregister_hash(const struct _hash_descriptor *hash);
+ int hash_is_valid(int idx);
 
-extern int find_hash(const char *name);
-extern int find_hash_id(unsigned char ID);
-extern int find_hash_any(const char *name, int digestlen);
-extern int register_hash(const struct _hash_descriptor *hash);
-extern int unregister_hash(const struct _hash_descriptor *hash);
-extern int hash_is_valid(int idx);
-
-extern int hash_memory(int hash, const unsigned char *data, unsigned long len, unsigned char *dst, unsigned long *outlen);
-extern int hash_filehandle(int hash, FILE *in, unsigned char *dst, unsigned long *outlen);
-extern int hash_file(int hash, const char *fname, unsigned char *dst, unsigned long *outlen);
+ int hash_memory(int hash, const unsigned char *data, unsigned long len, unsigned char *dst, unsigned long *outlen);
+ int hash_filehandle(int hash, FILE *in, unsigned char *dst, unsigned long *outlen);
+ int hash_file(int hash, const char *fname, unsigned char *dst, unsigned long *outlen);
 
 /* a simple macro for making hash "process" functions */
 #define HASH_PROCESS(func_name, compress_name, state_var, block_size)                       \
 int func_name (hash_state * md, const unsigned char *buf, unsigned long len)               \
 {                                                                                           \
     unsigned long n;                                                                        \
+    int           err;                                                                      \
     _ARGCHK(md != NULL);                                                                    \
     _ARGCHK(buf != NULL);                                                                   \
     if (md-> state_var .curlen > sizeof(md-> state_var .buf)) {                             \
@@ -251,7 +270,9 @@
     }                                                                                       \
     while (len > 0) {                                                                       \
         if (md-> state_var .curlen == 0 && len >= block_size) {                             \
-           compress_name (md, (unsigned char *)buf);                                        \
+           if ((err = compress_name (md, (unsigned char *)buf)) != CRYPT_OK) { \
+              return err;         \
+           }                                        \
            md-> state_var .length += block_size * 8;                                        \
            buf             += block_size;                                                   \
            len             -= block_size;                                                   \
@@ -262,7 +283,9 @@
            buf             += n;                                                            \
            len             -= n;                                                            \
            if (md-> state_var .curlen == block_size) {                                      \
-              compress_name (md, md-> state_var .buf);                                      \
+              if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) {\
+                 return err;                                      \
+              } \
               md-> state_var .length += 8*block_size;                                       \
               md-> state_var .curlen = 0;                                                   \
            }                                                                                \
@@ -276,17 +299,17 @@
      hash_state     md;
      int            hash;
      hash_state     hashstate;
-     unsigned char  key[MAXBLOCKSIZE];
+     unsigned char  *key;
 } hmac_state;
 
-extern int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen);
-extern int hmac_process(hmac_state *hmac, const unsigned char *buf, unsigned long len);
-extern int hmac_done(hmac_state *hmac, unsigned char *hashOut, unsigned long *outlen);
-extern int hmac_test(void);
-extern int hmac_memory(int hash, const unsigned char *key, unsigned long keylen,
+ int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen);
+ int hmac_process(hmac_state *hmac, const unsigned char *buf, unsigned long len);
+ int hmac_done(hmac_state *hmac, unsigned char *hashOut, unsigned long *outlen);
+ int hmac_test(void);
+ int hmac_memory(int hash, const unsigned char *key, unsigned long keylen,
                        const unsigned char *data, unsigned long len, 
                        unsigned char *dst, unsigned long *dstlen);
-extern int hmac_file(int hash, const char *fname, const unsigned char *key,
+ int hmac_file(int hash, const char *fname, const unsigned char *key,
                      unsigned long keylen, 
                      unsigned char *dst, unsigned long *dstlen);
 #endif
@@ -303,15 +326,15 @@
    symmetric_key   key;
 } omac_state;
 
-extern int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen);
-extern int omac_process(omac_state *state, const unsigned char *buf, unsigned long len);
-extern int omac_done(omac_state *state, unsigned char *out, unsigned long *outlen);
-extern int omac_memory(int cipher, const unsigned char *key, unsigned long keylen,
+ int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen);
+ int omac_process(omac_state *state, const unsigned char *buf, unsigned long len);
+ int omac_done(omac_state *state, unsigned char *out, unsigned long *outlen);
+ int omac_memory(int cipher, const unsigned char *key, unsigned long keylen,
                 const unsigned char *msg, unsigned long msglen,
                 unsigned char *out, unsigned long *outlen);
-extern int omac_file(int cipher, const unsigned char *key, unsigned long keylen,
+ int omac_file(int cipher, const unsigned char *key, unsigned long keylen,
               const char *filename, unsigned char *out, unsigned long *outlen);
-extern int omac_test(void);
+ int omac_test(void);
 #endif /* OMAC */
 
 #ifdef PMAC
@@ -330,22 +353,22 @@
                      buflen;                  /* number of bytes in the buffer */
 } pmac_state;
 
-extern int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen);
-extern int pmac_process(pmac_state *state, const unsigned char *buf, unsigned long len);
-extern int pmac_done(pmac_state *state, unsigned char *out, unsigned long *outlen);
+ int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen);
+ int pmac_process(pmac_state *state, const unsigned char *buf, unsigned long len);
+ int pmac_done(pmac_state *state, unsigned char *out, unsigned long *outlen);
 
-extern int pmac_memory(int cipher, const unsigned char *key, unsigned long keylen,
+ int pmac_memory(int cipher, const unsigned char *key, unsigned long keylen,
                 const unsigned char *msg, unsigned long msglen,
                 unsigned char *out, unsigned long *outlen);
 
-extern int pmac_file(int cipher, const unsigned char *key, unsigned long keylen,
+ int pmac_file(int cipher, const unsigned char *key, unsigned long keylen,
               const char *filename, unsigned char *out, unsigned long *outlen);
 
-extern int pmac_test(void);
+ int pmac_test(void);
 
 /* internal functions */
-extern int pmac_ntz(unsigned long x);
-extern void pmac_shift_xor(pmac_state *pmac);
+ int pmac_ntz(unsigned long x);
+ void pmac_shift_xor(pmac_state *pmac);
 
 #endif /* PMAC */
 
@@ -361,16 +384,16 @@
    omac_state    headeromac, ctomac;
 } eax_state;
 
-extern int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen,
+ int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen,
                     const unsigned char *nonce, unsigned long noncelen,
                     const unsigned char *header, unsigned long headerlen);
 
-extern int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length);
-extern int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length);
-extern int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length);
-extern int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen);
+ int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length);
+ int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length);
+ int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length);
+ int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen);
 
-extern int eax_encrypt_authenticate_memory(int cipher,
+ 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,
@@ -378,7 +401,7 @@
           unsigned char *ct,
           unsigned char *tag,    unsigned long *taglen);
 
-extern int eax_decrypt_verify_memory(int cipher,
+ 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,
@@ -387,7 +410,7 @@
           unsigned char *tag,    unsigned long taglen,
           int           *res);
 
-extern int eax_test(void);
+ int eax_test(void);
 #endif /* EAX MODE */
 
 #ifdef OCB_MODE
@@ -405,30 +428,30 @@
                      block_len;               /* length of block */
 } ocb_state;
 
-extern int ocb_init(ocb_state *ocb, int cipher, 
+ int ocb_init(ocb_state *ocb, int cipher, 
              const unsigned char *key, unsigned long keylen, const unsigned char *nonce);
 
-extern int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct);
-extern int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt);
+ 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);
 
-extern int ocb_done_encrypt(ocb_state *ocb, 
+ int ocb_done_encrypt(ocb_state *ocb, 
                      const unsigned char *pt,  unsigned long ptlen,
                            unsigned char *ct, 
                            unsigned char *tag, unsigned long *taglen);
 
-extern int ocb_done_decrypt(ocb_state *ocb, 
+ int ocb_done_decrypt(ocb_state *ocb, 
                      const unsigned char *ct,  unsigned long ctlen,
                            unsigned char *pt, 
                      const unsigned char *tag, unsigned long taglen, int *res);
 
-extern int ocb_encrypt_authenticate_memory(int cipher,
+ int ocb_encrypt_authenticate_memory(int cipher,
     const unsigned char *key,    unsigned long keylen,
     const unsigned char *nonce,  
     const unsigned char *pt,     unsigned long ptlen,
           unsigned char *ct,
           unsigned char *tag,    unsigned long *taglen);
 
-extern int ocb_decrypt_verify_memory(int cipher,
+ int ocb_decrypt_verify_memory(int cipher,
     const unsigned char *key,    unsigned long keylen,
     const unsigned char *nonce,  
     const unsigned char *ct,     unsigned long ctlen,
@@ -436,12 +459,12 @@
     const unsigned char *tag,    unsigned long taglen,
           int           *res);
 
-extern int ocb_test(void);
+ int ocb_test(void);
 
 /* internal functions */
-extern void ocb_shift_xor(ocb_state *ocb, unsigned char *Z);
-extern int ocb_ntz(unsigned long x);
-extern int __ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen,
+ void ocb_shift_xor(ocb_state *ocb, unsigned char *Z);
+ int ocb_ntz(unsigned long x);
+ int __ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen,
                      unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode);
 
 #endif /* OCB_MODE */
--- a/mycrypt_kr.h	Tue Jun 15 14:07:21 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-#ifdef KR
-
-#if !defined(MRSA) || !defined(MDH) || !defined(MECC)
-    #error "Keyring code requires all three public key algorithms."
-#endif
-
-#define MAXLEN    256
-
-enum {
-   NON_KEY=0,
-   RSA_KEY,
-   DH_KEY,
-   ECC_KEY
-};
-
-typedef union {
-    rsa_key rsa;
-    dh_key  dh;
-    ecc_key ecc;
-} _pk_key;
-
-typedef struct Pk_key {
-    int     key_type,             /* PUBLIC, PRIVATE, PRIVATE_OPTIMIZED */
-            system;               /* RSA, ECC or DH ?   */
-
-    unsigned char 
-            name[MAXLEN],         /* various info's about this key */
-            email[MAXLEN],
-            description[MAXLEN];
-
-    unsigned long ID;             /* CRC32 of the name/email/description together */
-
-    _pk_key key;
-
-    struct Pk_key  *next;         /* linked list chain */
-} pk_key;
-
-extern int kr_init(pk_key **pk);
-
-extern unsigned long kr_crc(const unsigned char *name, const unsigned char *email, const unsigned char *description);
-
-extern pk_key *kr_find(pk_key *pk, unsigned long ID);
-extern pk_key *kr_find_name(pk_key *pk, const char *name);
-
-extern int kr_add(pk_key *pk, int key_type, int sys, const unsigned char *name, 
-                  const unsigned char *email, const unsigned char *description, const _pk_key *key);
-                  
-extern int kr_del(pk_key **_pk, unsigned long ID);
-extern int kr_clear(pk_key **pk);
-extern int kr_make_key(pk_key *pk, prng_state *prng, int wprng, 
-                       int sys, int keysize, const unsigned char *name,
-                       const unsigned char *email, const unsigned char *description);
-
-extern int kr_export(pk_key *pk, unsigned long ID, int key_type, unsigned char *out, unsigned long *outlen);
-extern int kr_import(pk_key *pk, const unsigned char *in, unsigned long inlen);
-
-extern int kr_load(pk_key **pk, FILE *in, symmetric_CTR *ctr);
-extern int kr_save(pk_key *pk, FILE *out, symmetric_CTR *ctr);
-
-extern int kr_encrypt_key(pk_key *pk, unsigned long ID, 
-                          const unsigned char *in, unsigned long inlen,
-                          unsigned char *out, unsigned long *outlen,
-                          prng_state *prng, int wprng, int hash);
-
-extern int kr_decrypt_key(pk_key *pk, const unsigned char *in,
-                          unsigned char *out, unsigned long *outlen);
-
-extern int kr_sign_hash(pk_key *pk, unsigned long ID, 
-                        const unsigned char *in, unsigned long inlen,
-                        unsigned char *out, unsigned long *outlen,
-                        prng_state *prng, int wprng);
-
-extern int kr_verify_hash(pk_key *pk, const unsigned char *in, 
-                          const unsigned char *hash, unsigned long hashlen,
-                          int *stat);
-
-extern int kr_fingerprint(pk_key *pk, unsigned long ID, int hash,
-                          unsigned char *out, unsigned long *outlen);
-
-#endif
-
--- a/mycrypt_macros.h	Tue Jun 15 14:07:21 2004 +0000
+++ b/mycrypt_macros.h	Sun Dec 19 11:34:45 2004 +0000
@@ -10,7 +10,11 @@
 /* this is the "32-bit at least" data type 
  * Re-define it to suit your platform but it must be at least 32-bits 
  */
-typedef unsigned long ulong32;
+#if defined(__x86_64__)
+   typedef unsigned ulong32;
+#else
+   typedef unsigned long ulong32;
+#endif
 
 /* ---- HELPER MACROS ---- */
 #ifdef ENDIAN_NEUTRAL
@@ -125,26 +129,26 @@
 
 #ifdef ENDIAN_BIG
 #define STORE32L(x, y)                                                                     \
-     { (y)[z0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255);   \
-       (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
+     { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255);   \
+       (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
 
 #define LOAD32L(x, y)                            \
-     { x = ((unsigned long)((y)[0] & 255)<<24) | \
-           ((unsigned long)((y)[1] & 255)<<16) | \
-           ((unsigned long)((y)[2] & 255)<<8)  | \
-           ((unsigned long)((y)[3] & 255)); }
+     { x = ((unsigned long)((y)[3] & 255)<<24) | \
+           ((unsigned long)((y)[2] & 255)<<16) | \
+           ((unsigned long)((y)[1] & 255)<<8)  | \
+           ((unsigned long)((y)[0] & 255)); }
 
 #define STORE64L(x, y)                                                                     \
-   { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255);     \
-     (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255);     \
-     (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255);     \
-     (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
+   { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255);     \
+     (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255);     \
+     (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255);     \
+     (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
 
 #define LOAD64L(x, y)                                                      \
-   { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
-         (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
-         (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
-         (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
+   { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \
+         (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \
+         (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \
+         (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
 
 #ifdef ENDIAN_32BITWORD 
 
@@ -155,16 +159,16 @@
      memcpy(&(x), y, 4);
 
 #define STORE64H(x, y)                                                                     \
-     { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255);   \
-       (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255);   \
-       (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255);   \
-       (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
+     { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255);   \
+       (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255);   \
+       (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255);   \
+       (y)[6] = (unsigned char)(((x)>>8)&255);  (y)[7] = (unsigned char)((x)&255); }
 
 #define LOAD64H(x, y)                                                       \
-     { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
-           (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
-           (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
-           (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
+     { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \
+           (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \
+           (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \
+           (((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); }
 
 #else /* 64-bit words then  */
 
@@ -194,9 +198,9 @@
 #define ROR(x,n) _lrotr(x,n)
 #define ROL(x,n) _lrotl(x,n)
 
-#elif defined(__GNUC__) && defined(__i386__) && !defined(INTEL_CC)
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC)
 
-static inline unsigned long ROL(unsigned long word, int i)
+static inline unsigned ROL(unsigned word, int i)
 {
    __asm__("roll %%cl,%0"
       :"=r" (word)
@@ -204,7 +208,7 @@
    return word;
 }
 
-static inline unsigned long ROR(unsigned long word, int i)
+static inline unsigned ROR(unsigned word, int i)
 {
    __asm__("rorl %%cl,%0"
       :"=r" (word)
@@ -220,6 +224,26 @@
 
 #endif
 
+#if defined(__GNUCC__) && defined(__x86_64__)
+
+static inline unsigned long ROL64(unsigned long word, int i)
+{
+   __asm__("rolq %%cl,%0"
+      :"=r" (word)
+      :"0" (word),"c" (i));
+   return word;
+}
+
+static inline unsigned long ROR64(unsigned long word, int i)
+{
+   __asm__("rorq %%cl,%0"
+      :"=r" (word)
+      :"0" (word),"c" (i));
+   return word;
+}
+
+#else
+
 #define ROL64(x, y) \
     ( (((x)<<((ulong64)(y)&63)) | \
       (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
@@ -228,6 +252,8 @@
     ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
       ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
 
+#endif
+
 #undef MAX
 #undef MIN
 #define MAX(x, y) ( ((x)>(y))?(x):(y) )
--- a/mycrypt_misc.h	Tue Jun 15 14:07:21 2004 +0000
+++ b/mycrypt_misc.h	Sun Dec 19 11:34:45 2004 +0000
@@ -1,17 +1,17 @@
 /* ---- BASE64 Routines ---- */
 #ifdef BASE64
-extern int base64_encode(const unsigned char *in,  unsigned long len, 
+ int base64_encode(const unsigned char *in,  unsigned long len, 
                                unsigned char *out, unsigned long *outlen);
 
-extern int base64_decode(const unsigned char *in,  unsigned long len, 
+ int base64_decode(const unsigned char *in,  unsigned long len, 
                                unsigned char *out, unsigned long *outlen);
 #endif
 
 /* ---- MEM routines ---- */
-extern void zeromem(void *dst, size_t len);
-extern void burn_stack(unsigned long len);
+ void zeromem(void *dst, size_t len);
+ void burn_stack(unsigned long len);
 
-extern const char *error_to_string(int err);
-extern int mpi_to_ltc_error(int err);
+ const char *error_to_string(int err);
+ int mpi_to_ltc_error(int err);
 
-extern const char *crypt_build_settings;
+ extern const char *crypt_build_settings;
--- a/mycrypt_pk.h	Tue Jun 15 14:07:21 2004 +0000
+++ b/mycrypt_pk.h	Sun Dec 19 11:34:45 2004 +0000
@@ -44,8 +44,8 @@
      }                                                           \
 }
 
-extern int is_prime(mp_int *, int *);
-extern int rand_prime(mp_int *N, long len, prng_state *prng, int wprng);
+ int is_prime(mp_int *, int *);
+ int rand_prime(mp_int *N, long len, prng_state *prng, int wprng);
 
 #else
    #ifdef MRSA
@@ -67,13 +67,12 @@
 
 #define PK_PRIVATE            0        /* PK private keys */
 #define PK_PUBLIC             1        /* PK public keys */
-#define PK_PRIVATE_OPTIMIZED  2        /* PK private key [rsa optimized] */
 
 /* ---- PACKET ---- */
 #ifdef PACKET
 
-extern void packet_store_header(unsigned char *dst, int section, int subsection);
-extern int packet_valid_header(unsigned char *src, int section, int subsection);
+ void packet_store_header(unsigned char *dst, int section, int subsection);
+ int packet_valid_header(unsigned char *src, int section, int subsection);
 
 #endif
 
@@ -90,19 +89,19 @@
 
 typedef struct Rsa_key {
     int type;
-    mp_int e, d, N, qP, pQ, dP, dQ, p, q;
+    mp_int e, d, N, p, q, qP, dP, dQ;
 } rsa_key;
 
-extern int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key);
+ 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,
+ 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);
 
 #ifdef RSA_TIMING
 
-extern int tim_exptmod(prng_state *prng, int prng_idx, 
+ int tim_exptmod(prng_state *prng, int prng_idx, 
                        mp_int *c, mp_int *e, mp_int *d, mp_int *n, mp_int *m);
 
 #else
@@ -111,8 +110,9 @@
 
 #endif
 
-extern void rsa_free(rsa_key *key);
+ void rsa_free(rsa_key *key);
 
+/* These use PKCS #1 v2.0 padding */
 int rsa_encrypt_key(const unsigned char *inkey,  unsigned long inlen,
                           unsigned char *outkey, unsigned long *outlen,
                     const unsigned char *lparam, unsigned long lparamlen,
@@ -137,6 +137,30 @@
                           int            hash_idx, unsigned long saltlen,
                           int           *stat,     rsa_key      *key);
 
+/* these use PKCS #1 v1.5 padding */
+int rsa_v15_encrypt_key(const unsigned char *inkey,    unsigned long  inlen,
+                              unsigned char *outkey,   unsigned long *outlen,
+                              prng_state    *prng,     int            prng_idx, 
+                              rsa_key       *key);
+			      
+int rsa_v15_decrypt_key(const unsigned char *in,     unsigned long  inlen,
+                              unsigned char *outkey, unsigned long keylen, 
+                              prng_state    *prng,   int            prng_idx,
+                              int           *res,    rsa_key       *key);
+
+int rsa_v15_sign_hash(const unsigned char *msghash,  unsigned long  msghashlen, 
+                            unsigned char *sig,      unsigned long *siglen, 
+                            prng_state    *prng,     int            prng_idx,
+                            int            hash_idx, rsa_key       *key);
+
+int rsa_v15_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, int          *stat,     
+                              rsa_key       *key);
+
+
+/* PKCS #1 import/export */
 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);
                         
@@ -150,33 +174,33 @@
     mp_int x, y;
 } dh_key;
 
-extern int dh_test(void);
-extern void dh_sizes(int *low, int *high);
-extern int dh_get_size(dh_key *key);
+ int dh_test(void);
+ void dh_sizes(int *low, int *high);
+ int dh_get_size(dh_key *key);
 
-extern int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key);
-extern void dh_free(dh_key *key);
+ int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key);
+ void dh_free(dh_key *key);
 
-extern int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key);
-extern int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key);
+ int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key);
+ int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key);
 
-extern int dh_shared_secret(dh_key *private_key, dh_key *public_key,
+ int dh_shared_secret(dh_key *private_key, dh_key *public_key,
                             unsigned char *out, unsigned long *outlen);
 
-extern int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen,
+ int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen,
                                 unsigned char *out,  unsigned long *len, 
                                 prng_state *prng, int wprng, int hash, 
                                 dh_key *key);
 
-extern int dh_decrypt_key(const unsigned char *in,  unsigned long inlen, 
+ int dh_decrypt_key(const unsigned char *in,  unsigned long inlen, 
                                 unsigned char *outkey, unsigned long *keylen, 
                                 dh_key *key);
 
-extern int dh_sign_hash(const unsigned char *in,  unsigned long inlen,
+ int dh_sign_hash(const unsigned char *in,  unsigned long inlen,
                               unsigned char *out, unsigned long *outlen,
                               prng_state *prng, int wprng, dh_key *key);
 
-extern int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
+ int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
                           const unsigned char *hash, unsigned long hashlen, 
                                 int *stat, dh_key *key);
 
@@ -195,33 +219,33 @@
     mp_int k;
 } ecc_key;
 
-extern int ecc_test(void);
-extern void ecc_sizes(int *low, int *high);
-extern int ecc_get_size(ecc_key *key);
+ int ecc_test(void);
+ void ecc_sizes(int *low, int *high);
+ int ecc_get_size(ecc_key *key);
 
-extern int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key);
-extern void ecc_free(ecc_key *key);
+ int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key);
+ void ecc_free(ecc_key *key);
 
-extern int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key);
-extern int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
+ int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key);
+ int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
 
-extern int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, 
+ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, 
                              unsigned char *out, unsigned long *outlen);
 
-extern int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
+ int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
                                  unsigned char *out,  unsigned long *len, 
                                  prng_state *prng, int wprng, int hash, 
                                  ecc_key *key);
 
-extern int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
+ int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
                                  unsigned char *outkey, unsigned long *keylen, 
                                  ecc_key *key);
 
-extern int ecc_sign_hash(const unsigned char *in,  unsigned long inlen,
+ int ecc_sign_hash(const unsigned char *in,  unsigned long inlen,
                                unsigned char *out, unsigned long *outlen,
                                prng_state *prng, int wprng, ecc_key *key);
 
-extern int ecc_verify_hash(const unsigned char *sig,  unsigned long siglen,
+ int ecc_verify_hash(const unsigned char *sig,  unsigned long siglen,
                            const unsigned char *hash, unsigned long hashlen, 
                                  int *stat, ecc_key *key);
 #endif
@@ -233,21 +257,29 @@
    mp_int g, q, p, x, y;
 } dsa_key;
 
-extern int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key);
-extern void dsa_free(dsa_key *key);
+ int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key);
+ void dsa_free(dsa_key *key);
 
-extern int dsa_sign_hash(const unsigned char *in,  unsigned long inlen,
+ int dsa_sign_hash(const unsigned char *in,  unsigned long inlen,
                         unsigned char *out, unsigned long *outlen,
                         prng_state *prng, int wprng, dsa_key *key);
 
-extern int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+ int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
                            const unsigned char *hash, unsigned long inlen, 
                            int *stat, dsa_key *key);
 
-extern int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key);
+ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key);
 
-extern int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key);
+ int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key);
 
-extern int dsa_verify_key(dsa_key *key, int *stat);
+ int dsa_verify_key(dsa_key *key, int *stat);
 
 #endif
+
+/* DER handling */
+int der_encode_integer(mp_int *num, unsigned char *out, unsigned long *outlen);
+int der_decode_integer(const unsigned char *in, unsigned long *inlen, mp_int *num);
+int der_length_integer(mp_int *num, unsigned long *len);
+int der_put_multi_integer(unsigned char *dst, unsigned long *outlen, mp_int *num, ...);
+int der_get_multi_integer(const unsigned char *src, unsigned long *inlen,  mp_int *num, ...);
+
--- a/mycrypt_prng.h	Tue Jun 15 14:07:21 2004 +0000
+++ b/mycrypt_prng.h	Sun Dec 19 11:34:45 2004 +0000
@@ -10,57 +10,132 @@
     unsigned char buf[256];
 };
 
+struct fortuna_prng {
+    hash_state pool[FORTUNA_POOLS];     /* the  pools */
+
+    symmetric_key skey;
+
+    unsigned char K[32],      /* the current key */
+                  IV[16];     /* IV for CTR mode */
+    
+    unsigned long pool_idx,   /* current pool we will add to */
+                  pool0_len,  /* length of 0'th pool */
+                  wd;            
+
+    ulong64       reset_cnt;  /* number of times we have reset */
+};
+
+struct sober128_prng {
+    ulong32      R[17],          /* Working storage for the shift register */
+                 initR[17],      /* saved register contents */ 
+                 konst,          /* key dependent constant */
+                 sbuf;           /* partial word encryption buffer */
+
+    int          nbuf,           /* number of part-word stream bits buffered */
+                 flag,           /* first add_entropy call or not? */
+                 set;            /* did we call add_entropy to set key? */
+    
+};
+
 typedef union Prng_state {
+#ifdef YARROW
     struct yarrow_prng    yarrow;
+#endif
+#ifdef RC4
     struct rc4_prng       rc4;
+#endif
+#ifdef FORTUNA
+    struct fortuna_prng   fortuna;
+#endif
+#ifdef SOBER128
+    struct sober128_prng  sober128;
+#endif
 } prng_state;
 
 extern struct _prng_descriptor {
     char *name;
+    int  export_size;    /* size in bytes of exported state */
     int (*start)(prng_state *);
     int (*add_entropy)(const unsigned char *, unsigned long, prng_state *);
     int (*ready)(prng_state *);
-    unsigned long (*read)(unsigned char *, unsigned long len, prng_state *);
+    unsigned long (*read)(unsigned char *, unsigned long, prng_state *);
+    int (*done)(prng_state *);
+    int (*pexport)(unsigned char *, unsigned long *, prng_state *);
+    int (*pimport)(const unsigned char *, unsigned long, prng_state *);
+    int (*test)(void);
 } prng_descriptor[];
 
 #ifdef YARROW
-extern int yarrow_start(prng_state *prng);
-extern int yarrow_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng);
-extern int yarrow_ready(prng_state *prng);
-extern unsigned long yarrow_read(unsigned char *buf, unsigned long len, prng_state *prng);
-extern const struct _prng_descriptor yarrow_desc;
+ int yarrow_start(prng_state *prng);
+ int yarrow_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng);
+ int yarrow_ready(prng_state *prng);
+ unsigned long yarrow_read(unsigned char *buf, unsigned long len, prng_state *prng);
+ int yarrow_done(prng_state *prng);
+ int  yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+ int  yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+ int  yarrow_test(void);
+ extern const struct _prng_descriptor yarrow_desc;
+#endif
+
+#ifdef FORTUNA
+ int fortuna_start(prng_state *prng);
+ int fortuna_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng);
+ int fortuna_ready(prng_state *prng);
+ unsigned long fortuna_read(unsigned char *buf, unsigned long len, prng_state *prng);
+ int fortuna_done(prng_state *prng);
+ int  fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+ int  fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+ int  fortuna_test(void);
+ extern const struct _prng_descriptor fortuna_desc;
 #endif
 
 #ifdef RC4
-extern int rc4_start(prng_state *prng);
-extern int rc4_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng);
-extern int rc4_ready(prng_state *prng);
-extern unsigned long rc4_read(unsigned char *buf, unsigned long len, prng_state *prng);
-extern const struct _prng_descriptor rc4_desc;
+ int rc4_start(prng_state *prng);
+ int rc4_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng);
+ int rc4_ready(prng_state *prng);
+ unsigned long rc4_read(unsigned char *buf, unsigned long len, prng_state *prng);
+ int  rc4_done(prng_state *prng);
+ int  rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+ int  rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+ int  rc4_test(void);
+ extern const struct _prng_descriptor rc4_desc;
 #endif
 
 #ifdef SPRNG
-extern int sprng_start(prng_state *prng);
-extern int sprng_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng);
-extern int sprng_ready(prng_state *prng);
-extern unsigned long sprng_read(unsigned char *buf, unsigned long len, prng_state *prng);
-extern const struct _prng_descriptor sprng_desc;
+ int sprng_start(prng_state *prng);
+ int sprng_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng);
+ int sprng_ready(prng_state *prng);
+ unsigned long sprng_read(unsigned char *buf, unsigned long len, prng_state *prng);
+ int sprng_done(prng_state *prng);
+ int  sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+ int  sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+ int  sprng_test(void);
+ extern const struct _prng_descriptor sprng_desc;
 #endif
 
-extern int find_prng(const char *name);
-extern int register_prng(const struct _prng_descriptor *prng);
-extern int unregister_prng(const struct _prng_descriptor *prng);
-extern int prng_is_valid(int idx);
+#ifdef SOBER128
+ int sober128_start(prng_state *prng);
+ int sober128_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng);
+ int sober128_ready(prng_state *prng);
+ unsigned long sober128_read(unsigned char *buf, unsigned long len, prng_state *prng);
+ int sober128_done(prng_state *prng);
+ int  sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+ int  sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+ int  sober128_test(void);
+ extern const struct _prng_descriptor sober128_desc;
+#endif
 
+ int find_prng(const char *name);
+ int register_prng(const struct _prng_descriptor *prng);
+ int unregister_prng(const struct _prng_descriptor *prng);
+ int prng_is_valid(int idx);
 
 /* Slow RNG you **might** be able to use to seed a PRNG with.  Be careful as this
  * might not work on all platforms as planned
  */
-/* ch2-02-1 */ 
-extern unsigned long rng_get_bytes(unsigned char *buf, 
+unsigned long rng_get_bytes(unsigned char *buf, 
                                    unsigned long len, 
                                    void (*callback)(void));
-/* ch2-02-1 */
 
-extern int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void));
+int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void));
 
--- a/noekeon.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/noekeon.c	Sun Dec 19 11:34:45 2004 +0000
@@ -33,7 +33,6 @@
    0x000000d4UL 
 };
 
-
 #define kTHETA(a, b, c, d)                                 \
     temp = a^c; temp = temp ^ ROL(temp, 8) ^ ROR(temp, 8); \
     b ^= temp; d ^= temp;                                  \
@@ -97,9 +96,7 @@
 #endif
 {
    ulong32 a,b,c,d,temp;
-#ifdef SMALL_CODE
    int r;
-#endif
 
    _ARGCHK(key != NULL);
    _ARGCHK(pt != NULL);
@@ -115,16 +112,9 @@
        GAMMA(a,b,c,d); \
        PI2(a,b,c,d);
 
-#ifdef SMALL_CODE
    for (r = 0; r < 16; ++r) {
        ROUND(r);
    }
-#else 
-   ROUND( 0); ROUND( 1); ROUND( 2); ROUND( 3);
-   ROUND( 4); ROUND( 5); ROUND( 6); ROUND( 7);
-   ROUND( 8); ROUND( 9); ROUND(10); ROUND(11);
-   ROUND(12); ROUND(13); ROUND(14); ROUND(15);
-#endif
 
 #undef ROUND
 
@@ -150,9 +140,7 @@
 #endif
 {
    ulong32 a,b,c,d, temp;
-#ifdef SMALL_CODE
    int r;
-#endif
 
    _ARGCHK(key != NULL);
    _ARGCHK(pt != NULL);
@@ -169,17 +157,10 @@
        GAMMA(a,b,c,d); \
        PI2(a,b,c,d); 
 
-#ifdef SMALL_CODE
    for (r = 16; r > 0; --r) {
        ROUND(r);
    }
-#else
-   ROUND(16); ROUND(15); ROUND(14); ROUND(13);
-   ROUND(12); ROUND(11); ROUND(10); ROUND( 9);
-   ROUND( 8); ROUND( 7); ROUND( 6); ROUND( 5);
-   ROUND( 4); ROUND( 3); ROUND( 2); ROUND( 1);
-#endif
-   
+
 #undef ROUND
 
    THETA(key->noekeon.dK, a,b,c,d);
--- a/notes/hash_tv.txt	Tue Jun 15 14:07:21 2004 +0000
+++ b/notes/hash_tv.txt	Sun Dec 19 11:34:45 2004 +0000
@@ -1734,3 +1734,38 @@
 127: 3C9A7F387B7104DF19CF264B0B5821B2E46E44ADC79262546E98FFA113EB3D45799EAC78CCA4643C937FCC3C1D249A212FACB34C63D45EEC81069095D7CDCE7B
 128: 803A3B37C89E84FBBEC75BEE3D00DD728FFC4246B5A5E989DC8DC2CD0F7937966AB78C79E1D4648EE6EB40F3D70491CB46B8AB42E155672E2AB8374FCF70DD79
 
+Hash: chc_hash
+  0: 4047929F1F572643B55F829EB3291D11
+  1: 8898FD04F810507740E7A8DBF44C18E8
+  2: 1445928BB912A6D3C5111923B6C5D48D
+  3: D85B2E8854D16A440CF32DDDA741DA52
+  4: 5F3082124472598098B03649EA409CDC
+  5: 604A19622A06D0486D559A07C95B297A
+  6: A16F89E4DACA6C8174C9D66AA23B15AF
+  7: FC6893F79A2D28315FBBEFCAF0280793
+  8: 6A80F04CB93B1CFB947DED28141E877A
+  9: D036D0B4DEF1FA138C3181367143D1A9
+ 10: F031A2DC2A196B268046F73728EE7831
+ 11: 2E05C9B5A43CFB01AD026ABA8AE8201F
+ 12: 8B49EF0BC936792F905E61AE621E63C3
+ 13: 485CF5E83BC66843D446D9922547E43B
+ 14: 704767A75D1FD6639CE72291AE1F6CD8
+ 15: 19F6228C2531747CB20F644F9EC65691
+ 16: B78FEC0628D7F47B042A3C15C57750FB
+ 17: 3EF9AFAAFAE9C80D09CD078E1CC0BD8A
+ 18: 5E4501C8DD0D49589F4FFA20F278D316
+ 19: 00D2D0FDD0E0476C9D40DE5A04508849
+ 20: CC7382E78D8DF07F0BAB66203F191745
+ 21: 85B841BCCCB4AD2420BCABCFD06A0757
+ 22: 7159E38F4D7E4CEBEBF86A65A984BA2A
+ 23: C8949A9D92601726F77E1AEF0E5F1E0F
+ 24: 8CE35EF6EC7DDA294134077420159F68
+ 25: A0F4E4522832676B49E7CD393E6D9761
+ 26: F55C27D180948585819833322D7BC4CA
+ 27: 0A3975A0113E1FE6A66F8C7D529715B5
+ 28: F77135C5D04096181305C0906BAEE789
+ 29: 31FF81B49B9003D73F878F810D49C851
+ 30: BE1E12BF021D0DB2FC5CE7D5348A1DE7
+ 31: CB4AF60D7340EC6849574DF1E5BAA24E
+ 32: 7C5ABDBA19396D7BE48C2A84F8CC747B
+
--- a/notes/hmac_tv.txt	Tue Jun 15 14:07:21 2004 +0000
+++ b/notes/hmac_tv.txt	Sun Dec 19 11:34:45 2004 +0000
@@ -1734,3 +1734,38 @@
 127: 1D8B2525E519A3FF8BDAAF31E80EE695F5914B78E7DAB801729B5D84C3A7A2B36A33803F5E0723981CF8A9586EC1BEABC58154EFD919AFF08935FBD756327AAB
 128: 4AABF1C3F24C20FFAA61D6106E32EF1BB7CDEB607354BD4B6251893941730054244E198EECD4943C77082CC9B406A2E12271BCA455DF15D3613336615C36B22E
 
+HMAC-chc_hash
+  0: 0607F24D43AA98A86FCC45B53DA04F9D
+  1: BE4FB5E0BC4BD8132DB14BCBD7E4CD10
+  2: A3246C609FE39D7C9F7CFCF16185FB48
+  3: 3C7EA951205937240F0756BC0F2F4D1B
+  4: 7F69A5DD411DFE6BB99D1B8391B31272
+  5: DCB4D4D7F3B9AF6F51F30DCF733068CC
+  6: 1363B27E6B28BCD8AE3DCD0F55B387D7
+  7: BB525342845B1253CFE98F00237A85F3
+  8: 89FB247A36A9926FDA10F2013119151B
+  9: 54EB023EF9CE37EDC986373E23A9ED16
+ 10: 2358D8884471CB1D9E233107C7A7A4A0
+ 11: 94BAB092B00574C5FBEB1D7E54B684C4
+ 12: DF1819707621B8A66D9709397E92DC2F
+ 13: 3044DFFC7947787FDB12F62141B9E4FB
+ 14: 9EA9943FC2635AD852D1C5699234915D
+ 15: 1CC75C985BE6EDD3AD5907ED72ECE05E
+ 16: 1A826C4817FF59E686A59B0B96C9A619
+ 17: 44DB2A64264B125DE535A182CB7B2B2C
+ 18: 4741D46F73F2A860F95751E7E14CC244
+ 19: 13FDD4463084FEEB24F713DD9858E7F4
+ 20: D3308382E65E588D576D970A792BAC61
+ 21: 38E04BD5885FEA9E140F065F37DD09FC
+ 22: 5C309499657F24C1812FD8B926A419E2
+ 23: D1FDB9E8AC245737DA836D68FA507736
+ 24: F6924085988770FCC3BC9EEA8F72604E
+ 25: C72B261A79411F74D707C6B6F45823BD
+ 26: 2ED2333EBAC77F291FC6E844F2A7E42D
+ 27: CE0D3EF674917CEA5171F1A52EA62AAE
+ 28: 55EDEAC9F935ABEAF2956C8E83F3E447
+ 29: 820B799CB66DC9763FFD9AB634D971EC
+ 30: E14B18AB25025BF5DF2C1A73C235AD8B
+ 31: DE9F394575B9F525A734F302F0DB0A42
+ 32: 625ED3B09144ADFF57B6659BB2044FBE
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/notes/tech0004.txt	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,91 @@
+Tech Note 0004
+Using Yarrow, Fortuna and SOBER-128
+Tom St Denis
+
+Introduction
+------------
+
+This tech note explains how to use three of the more useful pseudo random number generators and their 
+own little "issues".  While all of the PRNGs have the same API and are roughly used in the same 
+manner their effectiveness really depends on the user knowing how they work.
+
+
+Yarrow
+------
+
+Yarrow is by far the simplest of the PRNGs.  It gathers bits of entropy by hashing the pool state
+plus the additional bits storing the message digest back in the pool.  E.g.
+
+pool = hash(pool || newbits)
+
+Simply dump bits into the PRNG via yarrow_add_entropy() and call yarrow_ready() when you want to 
+put them to use.  This PRNG while simple is not entirely safe.  An attacker who learns the state
+of the pool and can control future events can control the PRNG.  This requires an active attacker but 
+isn't entire impossible.
+
+The pool is then used as a key for a cipher that is used in CTR mode.  
+
+Yarrow is mostly meant for short-term programs [e.g. like file utils].  This particular implementation
+is not meant for long-term usage.
+
+Fortuna
+-------
+
+Fortuna was designed by Niels Fergusson and Bruce Schneier [Bruce is also the guy who invented Yarrow].  It
+operates on a more defensive level than Yarrow.  Instead of 1 entropy pool it has 32 and the new entropy 
+is spread [round robin] in all of the pools. 
+
+That is, each call to fortuna_add_entropy() puts the bits in the next [in the sequenece] pool of entropy.  
+Effective bits are added to the pool by sending them through a hash [but not terminating the hash].  
+
+Here's the main catch though.  When the PRNG must be reseeded [so that you can extract bits from it] only
+certain pools are used.  More precisely the i'th pool is used every 2**i'th reseeding.  For example, pool[0]
+is always used.  pool[1] is used every second reseeding, pool[2] every fourth.
+
+The pools are hashed together along with the current key and the result is the new key for a cipher which
+operates in CTR mode [more about that in a sec].
+
+Now this may seem odd at first however there is a good reason behind it.  An attacker who learns pool[0] won't
+strictly know the other pools.  So the recovery rate of is not 0.  In fact pool[0] can be completely 
+compromised and the PRNG will still eventually recover.  The value FORTUNA_WD is the "WatchDog" counter.
+Every FORTUNA_WD calls to fortuna_read will invoke the reseed operation.  By default this is set to 10 which 
+means after 10 calls the PRNG will reseed itself.  
+
+The pools are combined with the running cipher key [256 bits] so that a cipher in CTR mode can produce 
+the stream.  Unlike Yarrow the cipher is re-keyed after every call to fortuna_read() [so one big call 
+would be faster than many smaller calls].  This prevents too much data being encrypted under the same
+key [and mitigates a flaw in CTR mode that the same block can't be emitted twice under the same key].
+
+Fortuna is really meant for a kernel-level PRNG.  The more sources [and often] you feed into it the 
+healthier it will be.  It's also meant to be used for long term purposes.  Since it can recover from
+compromises it is harder to control it.  
+
+SOBER-128
+------
+
+SOBER-128 is actually a stream cipher but like most ciphers can easily be modelled in the context of a PRNG.
+This PRNG is extremely fast [4 cycles/byte on a P4] and was designed by a well known cryptographer [Greg Rose].
+
+SOBER-128 doesn't really "act" like the other two PRNGs.  It's meant to be seeded once and then read as 
+required.  In such a sense it isn't a "system PRNG" but useful short term purposes.  In particular
+the sober128_read() function actually XORs against the input buffer you specify.  This allows the 
+read() function to be used as an "encrypt" function as well.  
+
+You can only key SOBER-128 once [by calling sober128_add_entropy()].  Once it it is keyed subsequent
+calls to add_entropy() will be considered a "re-IV" operation.  Changing the IV allows you to use same
+initial key and not produce the same output stream.  It also lets you differentiate packets.  E.g. each
+packet has it's own IV.
+
+All inputs to sober128_add_entropy() must have a length that is a multiple of four.
+
+Overall
+-------
+
+Since SOBER-128 is *much* faster than the other two PRNGs a good setup would be to use Fortuna as your 
+system-wide PRNG and use SOBER-128 [key'ed from Fortuna] for encrypting streams or as a PRNG for 
+simulations.
+
+Yarrow is still a good candidate but only for "short lived" programs.  However, since Fortuna is faster
+[by about 10 cycles/byte on a P4] I'd use Fortuna anyways...
+
+Tom
\ No newline at end of file
--- a/ocb_decrypt_verify_memory.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/ocb_decrypt_verify_memory.c	Sun Dec 19 11:34:45 2004 +0000
@@ -23,8 +23,7 @@
           int           *res)
 {
    int err;
-   ocb_state ocb;
-
+   ocb_state *ocb;
 
    _ARGCHK(key    != NULL);
    _ARGCHK(nonce  != NULL);
@@ -33,20 +32,34 @@
    _ARGCHK(tag    != NULL);
    _ARGCHK(res    != NULL);
 
-   if ((err = ocb_init(&ocb, cipher, key, keylen, nonce)) != CRYPT_OK) {
-      return err;
+   /* allocate memory */
+   ocb = XMALLOC(sizeof(ocb_state));
+   if (ocb == NULL) {
+      return CRYPT_MEM;
+   }
+
+   if ((err = ocb_init(ocb, cipher, key, keylen, nonce)) != CRYPT_OK) {
+      goto __ERR; 
    }
 
-   while (ctlen > (unsigned long)ocb.block_len) {
-        if ((err = ocb_decrypt(&ocb, ct, pt)) != CRYPT_OK) {
-           return err;
+   while (ctlen > (unsigned long)ocb->block_len) {
+        if ((err = ocb_decrypt(ocb, ct, pt)) != CRYPT_OK) {
+            goto __ERR; 
         }
-        ctlen   -= ocb.block_len;
-        pt      += ocb.block_len;
-        ct      += ocb.block_len;
+        ctlen   -= ocb->block_len;
+        pt      += ocb->block_len;
+        ct      += ocb->block_len;
    }
 
-   return ocb_done_decrypt(&ocb, ct, ctlen, pt, tag, taglen, res);
+   err = ocb_done_decrypt(ocb, ct, ctlen, pt, tag, taglen, res);
+__ERR:
+#ifdef CLEAN_STACK
+   zeromem(ocb, sizeof(ocb_state));
+#endif
+ 
+   XFREE(ocb);
+
+   return err;
 }
 
 #endif
--- a/ocb_done_decrypt.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/ocb_done_decrypt.c	Sun Dec 19 11:34:45 2004 +0000
@@ -20,7 +20,7 @@
                      const unsigned char *tag, unsigned long taglen, int *res)
 {
    int err;
-   unsigned char tagbuf[MAXBLOCKSIZE];
+   unsigned char *tagbuf;
    unsigned long tagbuflen;
 
    _ARGCHK(ocb != NULL);
@@ -29,22 +29,33 @@
    _ARGCHK(tag != NULL);
    _ARGCHK(res != NULL);
 
+   /* default to failed */
    *res = 0;
 
-   tagbuflen = sizeof(tagbuf);
+   /* allocate memory */
+   tagbuf = XMALLOC(MAXBLOCKSIZE);
+   if (tagbuf == NULL) {
+      return CRYPT_MEM;
+   }
+
+   tagbuflen = MAXBLOCKSIZE;
    if ((err = __ocb_done(ocb, ct, ctlen, pt, tagbuf, &tagbuflen, 1)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
 
    if (taglen <= tagbuflen && memcmp(tagbuf, tag, taglen) == 0) {
       *res = 1;
    }
 
+   err = CRYPT_OK;
+__ERR:
 #ifdef CLEAN_STACK
-   zeromem(tagbuf, sizeof(tagbuf));
+   zeromem(tagbuf, MAXBLOCKSIZE);
 #endif
 
-   return CRYPT_OK;
+   XFREE(tagbuf);
+
+   return err;
 }
 
 #endif
--- a/ocb_encrypt_authenticate_memory.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/ocb_encrypt_authenticate_memory.c	Sun Dec 19 11:34:45 2004 +0000
@@ -22,7 +22,7 @@
           unsigned char *tag,    unsigned long *taglen)
 {
    int err;
-   ocb_state ocb;
+   ocb_state *ocb;
 
    _ARGCHK(key    != NULL);
    _ARGCHK(nonce  != NULL);
@@ -31,20 +31,34 @@
    _ARGCHK(tag    != NULL);
    _ARGCHK(taglen != NULL);
 
-   if ((err = ocb_init(&ocb, cipher, key, keylen, nonce)) != CRYPT_OK) {
-      return err;
+   /* allocate ram */
+   ocb = XMALLOC(sizeof(ocb_state));
+   if (ocb == NULL) {
+      return CRYPT_MEM;
+   }
+
+   if ((err = ocb_init(ocb, cipher, key, keylen, nonce)) != CRYPT_OK) {
+      goto __ERR;
    }
 
-   while (ptlen > (unsigned long)ocb.block_len) {
-        if ((err = ocb_encrypt(&ocb, pt, ct)) != CRYPT_OK) {
-           return err;
+   while (ptlen > (unsigned long)ocb->block_len) {
+        if ((err = ocb_encrypt(ocb, pt, ct)) != CRYPT_OK) {
+           goto __ERR;
         }
-        ptlen   -= ocb.block_len;
-        pt      += ocb.block_len;
-        ct      += ocb.block_len;
+        ptlen   -= ocb->block_len;
+        pt      += ocb->block_len;
+        ct      += ocb->block_len;
    }
 
-   return ocb_done_encrypt(&ocb, pt, ptlen, ct, tag, taglen);
+   err = ocb_done_encrypt(ocb, pt, ptlen, ct, tag, taglen);
+__ERR:
+#ifdef CLEAN_STACK
+   zeromem(ocb, sizeof(ocb_state));
+#endif
+
+   XFREE(ocb);
+
+   return err;
 }
 
 #endif
--- a/ocb_init.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/ocb_init.c	Sun Dec 19 11:34:45 2004 +0000
@@ -73,7 +73,7 @@
    cipher_descriptor[cipher].ecb_encrypt(ocb->R, ocb->R, &ocb->key);
 
    /* find Ls[i] = L << i for i == 0..31 */
-   memcpy(ocb->Ls[0], ocb->L, ocb->block_len);
+   XMEMCPY(ocb->Ls[0], ocb->L, ocb->block_len);
    for (x = 1; x < 32; x++) {
        m = ocb->Ls[x-1][0] >> 7;
        for (y = 0; y < ocb->block_len-1; y++) {
@@ -104,7 +104,7 @@
     }
 
     /* set Li, checksum */
-    zeromem(ocb->Li, ocb->block_len);
+    zeromem(ocb->Li,       ocb->block_len);
     zeromem(ocb->checksum, ocb->block_len);
 
     /* set other params */
--- a/ofb_getiv.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/ofb_getiv.c	Sun Dec 19 11:34:45 2004 +0000
@@ -21,7 +21,7 @@
    if ((unsigned long)ofb->blocklen > *len) {
       return CRYPT_BUFFER_OVERFLOW;
    }
-   memcpy(IV, ofb->IV, ofb->blocklen);
+   XMEMCPY(IV, ofb->IV, ofb->blocklen);
    *len = ofb->blocklen;
 
    return CRYPT_OK;
--- a/omac_done.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/omac_done.c	Sun Dec 19 11:34:45 2004 +0000
@@ -15,10 +15,12 @@
 
 int omac_done(omac_state *state, unsigned char *out, unsigned long *outlen)
 {
-   int err, mode, x;
+   int       err, mode;
+   unsigned  x;
 
-   _ARGCHK(state != NULL);
-   _ARGCHK(out   != NULL);
+   _ARGCHK(state  != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
    if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) {
       return err;
    }
@@ -43,7 +45,7 @@
    }
 
    /* now xor prev + Lu[mode] */
-   for (x = 0; x < state->blklen; x++) {
+   for (x = 0; x < (unsigned)state->blklen; x++) {
        state->block[x] ^= state->prev[x] ^ state->Lu[mode][x];
    }
 
@@ -51,7 +53,7 @@
    cipher_descriptor[state->cipher_idx].ecb_encrypt(state->block, state->block, &state->key);
  
    /* output it */
-   for (x = 0; x < state->blklen && (unsigned long)x < *outlen; x++) {
+   for (x = 0; x < (unsigned)state->blklen && x < *outlen; x++) {
        out[x] = state->block[x];
    }
    *outlen = x;
--- a/omac_init.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/omac_init.c	Sun Dec 19 11:34:45 2004 +0000
@@ -59,7 +59,7 @@
  
        /* copy up as require */
        if (x == 0) {
-          memcpy(omac->Lu[1], omac->Lu[0], sizeof(omac->Lu[0]));
+          XMEMCPY(omac->Lu[1], omac->Lu[0], sizeof(omac->Lu[0]));
        }
    }
 
--- a/omac_memory.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/omac_memory.c	Sun Dec 19 11:34:45 2004 +0000
@@ -19,24 +19,38 @@
                       unsigned char *out, unsigned long *outlen)
 {
    int err;
-   omac_state omac;
+   omac_state *omac;
 
-   _ARGCHK(key != NULL);
-   _ARGCHK(msg != NULL);
-   _ARGCHK(out != NULL);
+   _ARGCHK(key    != NULL);
+   _ARGCHK(msg    != NULL);
+   _ARGCHK(out    != NULL);
    _ARGCHK(outlen != NULL);
 
-   if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) {
-      return err;
-   }
-   if ((err = omac_process(&omac, msg, msglen)) != CRYPT_OK) {
-      return err;
-   }
-   if ((err = omac_done(&omac, out, outlen)) != CRYPT_OK) {
-      return err;
+   /* allocate ram for omac state */
+   omac = XMALLOC(sizeof(omac_state));
+   if (omac == NULL) {
+      return CRYPT_MEM;
    }
 
-   return CRYPT_OK;
+   /* omac process the message */
+   if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) {
+      goto __ERR;
+   }
+   if ((err = omac_process(omac, msg, msglen)) != CRYPT_OK) {
+      goto __ERR;
+   }
+   if ((err = omac_done(omac, out, outlen)) != CRYPT_OK) {
+      goto __ERR;
+   }
+
+   err = CRYPT_OK;
+__ERR:
+#ifdef CLEAN_STACK
+   zeromem(omac, sizeof(omac_state));
+#endif
+
+   XFREE(omac);
+   return err;   
 }
 
 #endif
--- a/omac_process.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/omac_process.c	Sun Dec 19 11:34:45 2004 +0000
@@ -40,7 +40,7 @@
 
        /* add bytes */
        n = MIN(len, (unsigned long)(state->blklen - state->buflen));
-       memcpy(state->block + state->buflen, buf, n);
+       XMEMCPY(state->block + state->buflen, buf, n);
        state->buflen += n;
        len           -= n;
        buf           += n;
--- a/omac_test.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/omac_test.c	Sun Dec 19 11:34:45 2004 +0000
@@ -65,7 +65,7 @@
 
     };
     unsigned char out[16];
-    int x, y, err, idx;
+    int x, err, idx;
     unsigned long len;
 
 
@@ -83,8 +83,11 @@
        }
 
        if (memcmp(out, tests[x].tag, 16) != 0) {
+#if 0
+          int y;
           printf("\n\nTag: ");
           for (y = 0; y < 16; y++) printf("%02x", out[y]); printf("\n\n");
+#endif
           return CRYPT_FAIL_TESTVECTOR;
        }
     }
--- a/pkcs_1_mgf1.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/pkcs_1_mgf1.c	Sun Dec 19 11:34:45 2004 +0000
@@ -20,8 +20,8 @@
 {
    unsigned long hLen, counter, x;
    int           err;
-   hash_state    md;
-   unsigned char buf[MAXBLOCKSIZE];
+   hash_state    *md;
+   unsigned char *buf;
  
    _ARGCHK(seed != NULL);
    _ARGCHK(mask != NULL);
@@ -34,6 +34,19 @@
    /* get hash output size */
    hLen = hash_descriptor[hash_idx].hashsize;
 
+   /* allocate memory */
+   md  = XMALLOC(sizeof(hash_state));
+   buf = XMALLOC(hLen);
+   if (md == NULL || buf == NULL) {
+      if (md != NULL) {
+         XFREE(md);
+      }
+      if (buf != NULL) {
+         XFREE(buf);
+      }
+      return CRYPT_MEM;
+   }
+
    /* start counter */
    counter = 0;
 
@@ -43,15 +56,17 @@
        ++counter;
 
        /* get hash of seed || counter */
-       hash_descriptor[hash_idx].init(&md);
-       if ((err = hash_descriptor[hash_idx].process(&md, seed, seedlen)) != CRYPT_OK) {
-          return err;
+       if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) {
+          goto __ERR;
+       }
+       if ((err = hash_descriptor[hash_idx].process(md, seed, seedlen)) != CRYPT_OK) {
+          goto __ERR;
        }
-       if ((err = hash_descriptor[hash_idx].process(&md, buf, 4)) != CRYPT_OK) {
-          return err;
+       if ((err = hash_descriptor[hash_idx].process(md, buf, 4)) != CRYPT_OK) {
+          goto __ERR;
        }
-       if ((err = hash_descriptor[hash_idx].done(&md, buf)) != CRYPT_OK) {
-          return err;
+       if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) {
+          goto __ERR;
        }
 
        /* store it */
@@ -60,7 +75,17 @@
        }
    }
 
-   return CRYPT_OK;
+   err = CRYPT_OK;
+__ERR:
+#ifdef CLEAN_STACK
+   zeromem(buf, hLen);
+   zeromem(md,  sizeof(hash_state));
+#endif
+
+   XFREE(buf);
+   XFREE(md);
+
+   return err;
 }
 
 #endif /* PKCS_1 */
--- a/pkcs_1_oaep_decode.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/pkcs_1_oaep_decode.c	Sun Dec 19 11:34:45 2004 +0000
@@ -20,7 +20,7 @@
                              unsigned char *out,    unsigned long *outlen,
                              int           *res)
 {
-   unsigned char DB[1024], seed[MAXBLOCKSIZE], mask[sizeof(DB)];
+   unsigned char *DB, *seed, *mask;
    unsigned long hLen, x, y, modulus_len;
    int           err;
 
@@ -39,9 +39,28 @@
    hLen        = hash_descriptor[hash_idx].hashsize;
    modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
 
+   /* allocate ram for DB/mask/salt of size modulus_len */
+   DB   = XMALLOC(modulus_len);
+   mask = XMALLOC(modulus_len);
+   seed = XMALLOC(modulus_len);
+   if (DB == NULL || mask == NULL || seed == NULL) {
+      if (DB != NULL) {
+         XFREE(DB);
+      }
+      if (mask != NULL) {
+         XFREE(mask);
+      }
+      if (seed != NULL) {
+         XFREE(seed);
+      }
+      return CRYPT_MEM;
+   }
+
+
    /* test message size */
-   if (modulus_len >= sizeof(DB) || msglen != modulus_len) {
-      return CRYPT_PK_INVALID_SIZE;
+   if (msglen != modulus_len) {
+      err = CRYPT_PK_INVALID_SIZE;
+      goto __ERR;
    }
 
    /* ok so it's now in the form
@@ -54,7 +73,8 @@
 
    /* must have leading 0x00 byte */
    if (msg[0] != 0x00) {
-      return CRYPT_OK;
+      err = CRYPT_OK;
+      goto __ERR;
    }
 
    /* now read the masked seed */
@@ -69,7 +89,7 @@
 
    /* compute MGF1 of maskedDB (hLen) */ 
    if ((err = pkcs_1_mgf1(DB, modulus_len - hLen - 1, hash_idx, mask, hLen)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
 
    /* XOR against seed */
@@ -79,7 +99,7 @@
 
    /* compute MGF1 of seed (k - hlen - 1) */
    if ((err = pkcs_1_mgf1(seed, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
 
    /* xor against DB */
@@ -90,21 +110,22 @@
    /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */
 
    /* compute lhash and store it in seed [reuse temps!] */
-   x = sizeof(seed);
+   x = modulus_len;
    if (lparam != NULL) {
       if ((err = hash_memory(hash_idx, lparam, lparamlen, seed, &x)) != CRYPT_OK) {
-         return err;
+         goto __ERR;
       }
    } else {
       /* can't pass hash_memory a NULL so use DB with zero length */
       if ((err = hash_memory(hash_idx, DB, 0, seed, &x)) != CRYPT_OK) {
-         return err;
+         goto __ERR;
       }
    }
 
    /* compare the lhash'es */
    if (memcmp(seed, DB, hLen) != 0) {
-      return CRYPT_OK;
+      err = CRYPT_OK;
+      goto __ERR;
    }
 
    /* now zeroes before a 0x01 */
@@ -114,12 +135,14 @@
 
    /* error out if wasn't 0x01 */
    if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) {
-      return CRYPT_OK;
+      err = CRYPT_OK;
+      goto __ERR;
    }
 
    /* rest is the message (and skip 0x01) */
-   if (msglen - ++x > *outlen) {
-      return CRYPT_BUFFER_OVERFLOW;
+   if ((modulus_len - hLen - 1) - ++x > *outlen) {
+      err = CRYPT_BUFFER_OVERFLOW;
+      goto __ERR;
    }
 
    /* copy message */
@@ -128,16 +151,22 @@
        out[y++] = DB[x++];
    }
 
-#ifdef CLEAN_STACK
-   zeromem(DB,   sizeof(DB));
-   zeromem(seed, sizeof(seed));
-   zeromem(mask, sizeof(mask));
-#endif
-
    /* valid packet */
    *res = 1;
 
-   return CRYPT_OK;
+   err = CRYPT_OK;
+__ERR:
+#ifdef CLEAN_STACK
+   zeromem(DB,   modulus_len);
+   zeromem(seed, modulus_len);
+   zeromem(mask, modulus_len);
+#endif
+
+   XFREE(seed);
+   XFREE(mask);
+   XFREE(DB);
+
+   return err;
 }
 
 #endif /* PKCS_1 */
--- a/pkcs_1_oaep_encode.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/pkcs_1_oaep_encode.c	Sun Dec 19 11:34:45 2004 +0000
@@ -20,7 +20,7 @@
                              int           prng_idx,         int  hash_idx,
                              unsigned char *out,    unsigned long *outlen)
 {
-   unsigned char DB[1024], seed[MAXBLOCKSIZE], mask[sizeof(DB)];
+   unsigned char *DB, *seed, *mask;
    unsigned long hLen, x, y, modulus_len;
    int           err;
 
@@ -41,22 +41,40 @@
    hLen        = hash_descriptor[hash_idx].hashsize;
    modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
 
+   /* allocate ram for DB/mask/salt of size modulus_len */
+   DB   = XMALLOC(modulus_len);
+   mask = XMALLOC(modulus_len);
+   seed = XMALLOC(modulus_len);
+   if (DB == NULL || mask == NULL || seed == NULL) {
+      if (DB != NULL) {
+         XFREE(DB);
+      }
+      if (mask != NULL) {
+         XFREE(mask);
+      }
+      if (seed != NULL) {
+         XFREE(seed);
+      }
+      return CRYPT_MEM;
+   }
+
    /* test message size */
-   if (modulus_len >= sizeof(DB) || msglen > (modulus_len - 2*hLen - 2)) {
-      return CRYPT_PK_INVALID_SIZE;
+   if (msglen > (modulus_len - 2*hLen - 2)) {
+      err = CRYPT_PK_INVALID_SIZE;
+      goto __ERR;
    }
 
    /* get lhash */
-// DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes
-   x = sizeof(DB);
+   /* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */
+   x = modulus_len;
    if (lparam != NULL) {
       if ((err = hash_memory(hash_idx, lparam, lparamlen, DB, &x)) != CRYPT_OK) {
-         return err;
+         goto __ERR;
       }
    } else {
       /* can't pass hash_memory a NULL so use DB with zero length */
       if ((err = hash_memory(hash_idx, DB, 0, DB, &x)) != CRYPT_OK) {
-         return err;
+         goto __ERR;
       }
    }
 
@@ -76,12 +94,13 @@
 
    /* now choose a random seed */
    if (prng_descriptor[prng_idx].read(seed, hLen, prng) != hLen) {
-      return CRYPT_ERROR_READPRNG;
+      err = CRYPT_ERROR_READPRNG;
+      goto __ERR;
    }
 
    /* compute MGF1 of seed (k - hlen - 1) */
    if ((err = pkcs_1_mgf1(seed, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
 
    /* xor against DB */
@@ -91,7 +110,7 @@
 
    /* compute MGF1 of maskedDB (hLen) */ 
    if ((err = pkcs_1_mgf1(DB, modulus_len - hLen - 1, hash_idx, mask, hLen)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
 
    /* XOR against seed */
@@ -101,7 +120,8 @@
 
    /* create string of length modulus_len */
    if (*outlen < modulus_len) {
-      return CRYPT_BUFFER_OVERFLOW;
+      err = CRYPT_BUFFER_OVERFLOW;
+      goto __ERR;
    }
 
    /* start output which is 0x00 || maskedSeed || maskedDB */
@@ -114,14 +134,20 @@
       out[x++] = DB[y];
    }
    *outlen = x;
-
+    
+   err = CRYPT_OK;
+__ERR:
 #ifdef CLEAN_STACK
-   zeromem(DB,   sizeof(DB));
-   zeromem(seed, sizeof(seed));
-   zeromem(mask, sizeof(mask));
+   zeromem(DB,   modulus_len);
+   zeromem(seed, modulus_len);
+   zeromem(mask, modulus_len);
 #endif
 
-   return CRYPT_OK;
+   XFREE(seed);
+   XFREE(mask);
+   XFREE(DB);
+
+   return err;
 }
 
 #endif /* PKCS_1 */
--- a/pkcs_1_pss_decode.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/pkcs_1_pss_decode.c	Sun Dec 19 11:34:45 2004 +0000
@@ -19,7 +19,7 @@
                             unsigned long saltlen,  int           hash_idx,
                             unsigned long modulus_bitlen, int    *res)
 {
-   unsigned char DB[1024], mask[sizeof(DB)], salt[sizeof(DB)], hash[sizeof(DB)];
+   unsigned char *DB, *mask, *salt, *hash;
    unsigned long x, y, hLen, modulus_len;
    int           err;
    hash_state    md;
@@ -38,15 +38,38 @@
    hLen        = hash_descriptor[hash_idx].hashsize;
    modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
 
+   /* allocate ram for DB/mask/salt/hash of size modulus_len */
+   DB   = XMALLOC(modulus_len);
+   mask = XMALLOC(modulus_len);
+   salt = XMALLOC(modulus_len);
+   hash = XMALLOC(modulus_len);
+   if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) {
+      if (DB != NULL) {
+         XFREE(DB);
+      }
+      if (mask != NULL) {
+         XFREE(mask);
+      }
+      if (salt != NULL) {
+         XFREE(salt);
+      }
+      if (hash != NULL) {
+         XFREE(hash);
+      }
+      return CRYPT_MEM;
+   }
+
    /* check sizes */
-   if ((saltlen > sizeof(salt)) || (modulus_len > sizeof(DB)) || 
+   if ((saltlen > modulus_len) || 
        (modulus_len < hLen + saltlen + 2) || (siglen != modulus_len)) {
-      return CRYPT_INVALID_ARG;
+      err = CRYPT_INVALID_ARG;
+      goto __ERR;
    }
 
    /* ensure the 0xBC byte */
    if (sig[siglen-1] != 0xBC) {
-      return CRYPT_OK;
+      err = CRYPT_OK;
+      goto __ERR;
    }
 
    /* copy out the DB */
@@ -61,12 +84,13 @@
 
    /* check the MSB */
    if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)))) != 0) {
-      return CRYPT_OK;
+      err = CRYPT_OK;
+      goto __ERR;
    }
 
    /* generate mask of length modulus_len - hLen - 1 from hash */
    if ((err = pkcs_1_mgf1(hash, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
 
    /* xor against DB */
@@ -82,28 +106,33 @@
    /* check for zeroes and 0x01 */
    for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) {
        if (DB[x] != 0x00) {
-          return CRYPT_OK;
+          err = CRYPT_OK;
+          goto __ERR;
        }
    }
 
+   /* check for the 0x01 */
    if (DB[x++] != 0x01) {
-      return CRYPT_OK;
+      err = CRYPT_OK;
+      goto __ERR;
    }
 
    /* M = (eight) 0x00 || msghash || salt, mask = H(M) */
-   hash_descriptor[hash_idx].init(&md);
+   if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) {
+      goto __ERR;
+   }
    zeromem(mask, 8);
    if ((err = hash_descriptor[hash_idx].process(&md, mask, 8)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
    if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
    if ((err = hash_descriptor[hash_idx].process(&md, DB+x, saltlen)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
    if ((err = hash_descriptor[hash_idx].done(&md, mask)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
 
    /* mask == hash means valid signature */
@@ -111,14 +140,21 @@
       *res = 1;
    }
 
+   err = CRYPT_OK;
+__ERR:
 #ifdef CLEAN_STACK
-   zeromem(DB,   sizeof(DB));   
-   zeromem(mask, sizeof(mask));   
-   zeromem(salt, sizeof(salt));   
-   zeromem(hash, sizeof(hash));   
+   zeromem(DB,   modulus_len);   
+   zeromem(mask, modulus_len);   
+   zeromem(salt, modulus_len);   
+   zeromem(hash, modulus_len);   
 #endif
 
-   return CRYPT_OK;
+   XFREE(hash);
+   XFREE(salt);
+   XFREE(mask);
+   XFREE(DB);
+
+   return err;
 }
 
 #endif /* PKCS_1 */
--- a/pkcs_1_pss_encode.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/pkcs_1_pss_encode.c	Sun Dec 19 11:34:45 2004 +0000
@@ -20,7 +20,7 @@
                             unsigned long modulus_bitlen,
                             unsigned char *out,     unsigned long *outlen)
 {
-   unsigned char DB[1024], mask[sizeof(DB)], salt[sizeof(DB)], hash[sizeof(DB)];
+   unsigned char *DB, *mask, *salt, *hash;
    unsigned long x, y, hLen, modulus_len;
    int           err;
    hash_state    md;
@@ -40,32 +40,58 @@
    hLen        = hash_descriptor[hash_idx].hashsize;
    modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
 
+   /* allocate ram for DB/mask/salt/hash of size modulus_len */
+   DB   = XMALLOC(modulus_len);
+   mask = XMALLOC(modulus_len);
+   salt = XMALLOC(modulus_len);
+   hash = XMALLOC(modulus_len);
+   if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) {
+      if (DB != NULL) {
+         XFREE(DB);
+      }
+      if (mask != NULL) {
+         XFREE(mask);
+      }
+      if (salt != NULL) {
+         XFREE(salt);
+      }
+      if (hash != NULL) {
+         XFREE(hash);
+      }
+      return CRYPT_MEM;
+   }
+
+
    /* check sizes */
-   if ((saltlen > sizeof(salt)) || (modulus_len > sizeof(DB)) || (modulus_len < hLen + saltlen + 2)) {
-      return CRYPT_INVALID_ARG;
+   if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2)) {
+      err = CRYPT_INVALID_ARG;
+      goto __ERR;
    }
 
    /* generate random salt */
    if (saltlen > 0) {
       if (prng_descriptor[prng_idx].read(salt, saltlen, prng) != saltlen) {
-         return CRYPT_ERROR_READPRNG;
+         err = CRYPT_ERROR_READPRNG;
+         goto __ERR;
       }
    }
 
    /* M = (eight) 0x00 || msghash || salt, hash = H(M) */
-   hash_descriptor[hash_idx].init(&md);
+   if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) {
+      goto __ERR;
+   }
    zeromem(DB, 8);
    if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
    if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
    if ((err = hash_descriptor[hash_idx].process(&md, salt, saltlen)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
    if ((err = hash_descriptor[hash_idx].done(&md, hash)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
 
    /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */
@@ -79,7 +105,7 @@
 
    /* generate mask of length modulus_len - hLen - 1 from hash */
    if ((err = pkcs_1_mgf1(hash, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
-      return err;
+      goto __ERR;
    }
 
    /* xor against DB */
@@ -89,7 +115,8 @@
 
    /* output is DB || hash || 0xBC */
    if (*outlen < modulus_len) {
-      return CRYPT_BUFFER_OVERFLOW;
+      err = CRYPT_BUFFER_OVERFLOW;
+      goto __ERR;
    }
 
    /* DB */
@@ -108,15 +135,21 @@
 
    /* store output size */
    *outlen = modulus_len;
-
+   err = CRYPT_OK;
+__ERR:
 #ifdef CLEAN_STACK
-   zeromem(DB,   sizeof(DB));   
-   zeromem(mask, sizeof(mask));   
-   zeromem(salt, sizeof(salt));   
-   zeromem(hash, sizeof(hash));   
+   zeromem(DB,   modulus_len);   
+   zeromem(mask, modulus_len);   
+   zeromem(salt, modulus_len);   
+   zeromem(hash, modulus_len);   
 #endif
 
-   return CRYPT_OK;
+   XFREE(hash);
+   XFREE(salt);
+   XFREE(mask);
+   XFREE(DB);
+
+   return err;
 }
 
 #endif /* PKCS_1 */
--- a/pkcs_1_v15_es_decode.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/pkcs_1_v15_es_decode.c	Sun Dec 19 11:34:45 2004 +0000
@@ -28,13 +28,13 @@
    /* default to failed */
    *res = 0;
 
-   /* must be at least 12 bytes long */
-   if (msglen < 12) {
+   modulus_bytelen = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+   /* must be at least modulus_bytelen bytes long */
+   if (msglen != modulus_bytelen) {
       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;
@@ -52,7 +52,7 @@
    if (x + outlen > modulus_bytelen) {
       return CRYPT_PK_INVALID_SIZE;
    }
-   memcpy(out, msg + x, outlen);
+   XMEMCPY(out, msg + x, outlen);
    *res = 1;
    return CRYPT_OK;
 }
--- a/pkcs_1_v15_es_encode.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/pkcs_1_v15_es_encode.c	Sun Dec 19 11:34:45 2004 +0000
@@ -46,7 +46,7 @@
    }
    x += y;
    out[x++] = 0x00;
-   memcpy(out+x, msg, msglen);
+   XMEMCPY(out+x, msg, msglen);
    *outlen = modulus_bytelen;
 
    return CRYPT_OK;
--- a/pkcs_5_1.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/pkcs_5_1.c	Sun Dec 19 11:34:45 2004 +0000
@@ -20,8 +20,8 @@
 {
    int err;
    unsigned long x;
-   hash_state md;
-   unsigned char buf[MAXBLOCKSIZE];
+   hash_state    *md;
+   unsigned char *buf;
 
    _ARGCHK(password != NULL);
    _ARGCHK(salt     != NULL);
@@ -33,17 +33,38 @@
       return err;
    }
 
+   /* allocate memory */
+   md  = XMALLOC(sizeof(hash_state));
+   buf = XMALLOC(MAXBLOCKSIZE);
+   if (md == NULL || buf == NULL) {
+      if (md != NULL) {
+         XFREE(md);
+      }
+      if (buf != NULL) { 
+         XFREE(buf);
+      }
+      return CRYPT_MEM;
+   }        
+
    /* hash initial password + salt */
-   hash_descriptor[hash_idx].init(&md);
-   hash_descriptor[hash_idx].process(&md, password, password_len);
-   hash_descriptor[hash_idx].process(&md, salt, 8);
-   hash_descriptor[hash_idx].done(&md, buf);
+   if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) {
+       goto __ERR;
+   }
+   if ((err = hash_descriptor[hash_idx].process(md, password, password_len)) != CRYPT_OK) {
+       goto __ERR;
+   }
+   if ((err = hash_descriptor[hash_idx].process(md, salt, 8)) != CRYPT_OK) {
+       goto __ERR;
+   }
+   if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) {
+       goto __ERR;
+   }
 
    while (--iteration_count) {
       // code goes here.
-      x = sizeof(buf);
+      x = MAXBLOCKSIZE;
       if ((err = hash_memory(hash_idx, buf, hash_descriptor[hash_idx].hashsize, buf, &x)) != CRYPT_OK) {
-         return err;
+         goto __ERR;
       }
    }
 
@@ -52,12 +73,17 @@
        out[x] = buf[x];
    }
    *outlen = x;
-
+   err = CRYPT_OK;
+__ERR:
 #ifdef CLEAN_STACK 
-   zeromem(buf, sizeof(buf));
+   zeromem(buf, MAXBLOCKSIZE);
+   zeromem(md, sizeof(hash_state));
 #endif
 
-   return CRYPT_OK;
+   XFREE(buf);
+   XFREE(md);
+
+   return err;
 }
 
 #endif
--- a/pkcs_5_2.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/pkcs_5_2.c	Sun Dec 19 11:34:45 2004 +0000
@@ -20,8 +20,8 @@
 {
    int err, itts;
    unsigned long stored, left, x, y, blkno;
-   unsigned char buf[2][MAXBLOCKSIZE];
-   hmac_state    hmac;
+   unsigned char *buf[2];
+   hmac_state    *hmac;
 
    _ARGCHK(password != NULL);
    _ARGCHK(salt     != NULL);
@@ -33,37 +33,51 @@
       return err;
    }
 
+   buf[0] = XMALLOC(MAXBLOCKSIZE * 2);
+   hmac   = XMALLOC(sizeof(hmac_state));
+   if (hmac == NULL || buf[0] == NULL) {
+      if (hmac != NULL) {
+         XFREE(hmac);
+      }
+      if (buf[0] != NULL) {
+         XFREE(buf[0]);
+      }
+      return CRYPT_MEM;
+   }
+   /* buf[1] points to the second block of MAXBLOCKSIZE bytes */
+   buf[1] = buf[0] + MAXBLOCKSIZE;
+
    left   = *outlen;
    blkno  = 1;
    stored = 0;
    while (left != 0) {
        /* process block number blkno */
-       zeromem(buf, sizeof(buf));
+       zeromem(buf[0], MAXBLOCKSIZE*2);
        
        /* store current block number and increment for next pass */
        STORE32H(blkno, buf[1]);
        ++blkno;
 
        /* get PRF(P, S||int(blkno)) */
-       if ((err = hmac_init(&hmac, hash_idx, password, password_len)) != CRYPT_OK) { 
-          return err; 
+       if ((err = hmac_init(hmac, hash_idx, password, password_len)) != CRYPT_OK) { 
+          goto __ERR;
        }
-       if ((err = hmac_process(&hmac, salt, salt_len)) != CRYPT_OK) {
-          return err;
+       if ((err = hmac_process(hmac, salt, salt_len)) != CRYPT_OK) {
+          goto __ERR;
        }
-       if ((err = hmac_process(&hmac, buf[1], 4)) != CRYPT_OK) {
-          return err;
+       if ((err = hmac_process(hmac, buf[1], 4)) != CRYPT_OK) {
+          goto __ERR;
        }
-       x = sizeof(buf[0]);
-       if ((err = hmac_done(&hmac, buf[0], &x)) != CRYPT_OK) {
-          return err;
+       x = MAXBLOCKSIZE;
+       if ((err = hmac_done(hmac, buf[0], &x)) != CRYPT_OK) {
+          goto __ERR;
        }
 
        /* now compute repeated and XOR it in buf[1] */
-       memcpy(buf[1], buf[0], x);
-       for (itts = 2; itts < iteration_count; ++itts) {
+       XMEMCPY(buf[1], buf[0], x);
+       for (itts = 1; itts < iteration_count; ++itts) {
            if ((err = hmac_memory(hash_idx, password, password_len, buf[0], x, buf[0], &x)) != CRYPT_OK) {
-              return err;
+              goto __ERR;
            }
            for (y = 0; y < x; y++) {
                buf[1][y] ^= buf[0][y];
@@ -78,10 +92,17 @@
    }
    *outlen = stored;
 
+   err = CRYPT_OK;
+__ERR:
 #ifdef CLEAN_STACK
-   zeromem(buf, sizeof(buf));
+   zeromem(buf[0], MAXBLOCKSIZE*2);
+   zeromem(hmac, sizeof(hmac_state));
 #endif
-   return CRYPT_OK;
+
+   XFREE(hmac);
+   XFREE(buf[0]);
+
+   return err;
 }
 
 #endif
--- a/pmac_init.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/pmac_init.c	Sun Dec 19 11:34:45 2004 +0000
@@ -35,7 +35,7 @@
 int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen)
 {
    int poly, x, y, m, err;
-   unsigned char L[MAXBLOCKSIZE];
+   unsigned char *L;
 
    _ARGCHK(pmac  != NULL);
    _ARGCHK(key   != NULL);
@@ -61,12 +61,18 @@
       return err;
    }
  
+   /* allocate L */
+   L = XMALLOC(pmac->block_len);
+   if (L == NULL) {
+      return CRYPT_MEM;
+   }
+
    /* find L = E[0] */
    zeromem(L, pmac->block_len);
    cipher_descriptor[cipher].ecb_encrypt(L, L, &pmac->key);
 
    /* find Ls[i] = L << i for i == 0..31 */
-   memcpy(pmac->Ls[0], L, pmac->block_len);
+   XMEMCPY(pmac->Ls[0], L, pmac->block_len);
    for (x = 1; x < 32; x++) {
        m = pmac->Ls[x-1][0] >> 7;
        for (y = 0; y < pmac->block_len-1; y++) {
@@ -105,9 +111,11 @@
     zeromem(pmac->checksum, sizeof(pmac->checksum));
 
 #ifdef CLEAN_STACK
-    zeromem(L, sizeof(L));
+    zeromem(L, pmac->block_len);
 #endif
 
+    XFREE(L);
+
     return CRYPT_OK;
 }
 
--- a/pmac_memory.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/pmac_memory.c	Sun Dec 19 11:34:45 2004 +0000
@@ -20,25 +20,37 @@
                       unsigned char *out, unsigned long *outlen)
 {
    int err;
-   pmac_state pmac;
+   pmac_state *pmac;
 
    _ARGCHK(key    != NULL);
    _ARGCHK(msg    != NULL);
    _ARGCHK(out    != NULL);
    _ARGCHK(outlen != NULL);
 
-
-   if ((err = pmac_init(&pmac, cipher, key, keylen)) != CRYPT_OK) {
-      return err;
+   /* allocate ram for pmac state */
+   pmac = XMALLOC(sizeof(pmac_state));
+   if (pmac == NULL) {
+      return CRYPT_MEM;
    }
-   if ((err = pmac_process(&pmac, msg, msglen)) != CRYPT_OK) {
-      return err;
+   
+   if ((err = pmac_init(pmac, cipher, key, keylen)) != CRYPT_OK) {
+      goto __ERR;
    }
-   if ((err = pmac_done(&pmac, out, outlen)) != CRYPT_OK) {
-      return err;
+   if ((err = pmac_process(pmac, msg, msglen)) != CRYPT_OK) {
+      goto __ERR;
+   }
+   if ((err = pmac_done(pmac, out, outlen)) != CRYPT_OK) {
+      goto __ERR;
    }
 
-   return CRYPT_OK;
+   err = CRYPT_OK;
+__ERR:
+#ifdef CLEAN_STACK
+   zeromem(pmac, sizeof(pmac_state));
+#endif
+
+   XFREE(pmac);
+   return err;   
 }
 
 #endif
--- a/pmac_process.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/pmac_process.c	Sun Dec 19 11:34:45 2004 +0000
@@ -46,7 +46,7 @@
 
        /* add bytes */
        n = MIN(len, (unsigned long)(state->block_len - state->buflen));
-       memcpy(state->block + state->buflen, buf, n);
+       XMEMCPY(state->block + state->buflen, buf, n);
        state->buflen += n;
        len           -= n;
        buf           += n;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pretty.build	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,84 @@
+#!/bin/perl -w
+#
+# Cute little builder for perl 
+# Total waste of development time...
+#
+# This will build all the object files and then the archive .a file
+# requires GCC, GNU make and a sense of humour.
+#
+# Tom St Denis
+use strict;
+
+my $count = 0;
+my $starttime = time;
+my $rate  = 0;
+print "Scanning for source files...\n";
+foreach my $filename (glob "*.c") {
+    if (!($filename =~ "aes_tab.c")) {
+    if (!($filename =~ "twofish_tab.c")) {
+    if (!($filename =~ "whirltab.c")) {
+    if (!($filename =~ "sha224.c")) {
+    if (!($filename =~ "sha384.c")) {
+    if (!($filename =~ "dh_sys.c")) {
+    if (!($filename =~ "ecc_sys.c")) {
+    if (!($filename =~ "sober128tab.c")) {
+       ++$count;
+    }}}}}}}}
+}
+print "Source files to build: $count\nBuilding...\n";
+my $i = 0;
+my $lines = 0;
+my $filesbuilt = 0;
+foreach my $filename (glob "*.c") {
+    if (!($filename =~ "aes_tab.c")) {
+    if (!($filename =~ "twofish_tab.c")) {
+    if (!($filename =~ "whirltab.c")) {
+    if (!($filename =~ "sha224.c")) {
+    if (!($filename =~ "sha384.c")) {
+    if (!($filename =~ "dh_sys.c")) {
+    if (!($filename =~ "ecc_sys.c")) {
+    if (!($filename =~ "sober128tab.c")) {
+       printf("Building %3.2f%%, ", (++$i/$count)*100.0);
+       if ($i % 4 == 0) { print "/, "; }
+       if ($i % 4 == 1) { print "-, "; }
+       if ($i % 4 == 2) { print "\\, "; }
+       if ($i % 4 == 3) { print "|, "; }
+       if ($rate > 0) {
+           my $tleft = ($count - $i) / $rate;
+           my $tsec  = $tleft%60;
+           my $tmin  = ($tleft/60)%60;
+           my $thour = ($tleft/3600)%60;
+           printf("%2d:%02d:%02d left, ", $thour, $tmin, $tsec);
+       }
+       my $cnt = ($i/$count)*30.0;
+       my $x   = 0;
+       print "[";
+       for (; $x < $cnt; $x++) { print "#"; }
+       for (; $x < 30; $x++)   { print " "; }
+       print "]\r";
+       my $tmp = $filename;
+       $tmp =~ s/\.c/".o"/ge;
+       if (open(SRC, "<$tmp")) {
+          close SRC;
+       } else {
+          !system("make $tmp > /dev/null 2>/dev/null") or die "\nERROR: Failed to make $tmp!!!\n";
+          open( SRC, "<$filename" ) or die "Couldn't open $filename for reading: $!";
+          ++$lines while (<SRC>);
+          close SRC or die "Error closing $filename after reading: $!";
+          ++$filesbuilt;
+       }      
+
+       # update timer 
+       if (time != $starttime) {
+          my $delay = time - $starttime;
+          $rate = $i/$delay;
+       }
+    }}}}}}}}
+}
+
+# finish building the library 
+printf("\nFinished building source (%d seconds, %3.2f files per second).\n", time - $starttime, $rate);
+print "Compiled approximately $filesbuilt files and $lines lines of code.\n";
+print "Doing final make (building archive...)\n";
+!system("make > /dev/null 2>/dev/null") or die "\nERROR: Failed to perform last make command!!!\n";
+print "done.\n";
\ No newline at end of file
--- a/rc2.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/rc2.c	Sun Dec 19 11:34:45 2004 +0000
@@ -33,17 +33,8 @@
    &rc2_keysize
 };
 
-
-/**********************************************************************\
-* Expand a variable-length user key (between 1 and 128 bytes) to a     *
-* 64-short working rc2 key, of at most "bits" effective key bits.      *
-* The effective key bits parameter looks like an export control hack.  *
-* For normal use, it should always be set to 1024.  For convenience,   *
-* zero is accepted as an alias for 1024.                               *
-\**********************************************************************/
-
-   /* 256-entry permutation table, probably derived somehow from pi */
-    static const unsigned char permute[256] = {
+/* 256-entry permutation table, probably derived somehow from pi */
+static const unsigned char permute[256] = {
         217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157,
         198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162,
          23,154, 89,245,135,179, 79, 19, 97, 69,109,141,  9,129,125, 50,
@@ -60,7 +51,7 @@
         211,  0,230,207,225,158,168, 44, 99, 22,  1, 63, 88,226,137,169,
          13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46,
         197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173
-    };
+};
 
 int rc2_setup(const unsigned char *key, int keylen, int rounds, symmetric_key *skey)
 {
@@ -87,24 +78,23 @@
     /* Phase 1: Expand input key to 128 bytes */
     if (keylen < 128) {
         for (i = keylen; i < 128; i++) {
-            tmp[i] = permute[(int)((tmp[i - 1] + tmp[i - keylen]) & 255)];
+            tmp[i] = permute[(tmp[i - 1] + tmp[i - keylen]) & 255];
         }
     }
     
     /* Phase 2 - reduce effective key size to "bits" */
-    bits = keylen*8;
+    bits = keylen<<3;
     T8   = (unsigned)(bits+7)>>3;
     TM   = (255 >> (unsigned)(7 & -bits));
-    tmp[128 - T8] = permute[(int)(tmp[128 - T8] & TM)];
+    tmp[128 - T8] = permute[tmp[128 - T8] & TM];
     for (i = 127 - T8; i >= 0; i--) {
-        tmp[i] = permute[(int)(tmp[i + 1] ^ tmp[i + T8])];
+        tmp[i] = permute[tmp[i + 1] ^ tmp[i + T8]];
     }
 
     /* Phase 3 - copy to xkey in little-endian order */
-    i = 63;
-    do {
+    for (i = 0; i < 64; i++) {
         xkey[i] =  (unsigned)tmp[2*i] + ((unsigned)tmp[2*i+1] << 8);
-    } while (i-- > 0);
+    }        
 
 #ifdef CLEAN_STACK
     zeromem(tmp, sizeof(tmp));
@@ -129,9 +119,9 @@
     unsigned *xkey;
     unsigned x76, x54, x32, x10, i;
 
-    _ARGCHK(plain != NULL);
+    _ARGCHK(plain  != NULL);
     _ARGCHK(cipher != NULL);
-    _ARGCHK(skey != NULL);
+    _ARGCHK(skey   != NULL);
 
     xkey = skey->rc2.xkey;
 
@@ -142,16 +132,16 @@
 
     for (i = 0; i < 16; i++) {
         x10 = (x10 + (x32 & ~x76) + (x54 & x76) + xkey[4*i+0]) & 0xFFFF;
-        x10 = ((x10 << 1) | (x10 >> 15)) & 0xFFFF;
+        x10 = ((x10 << 1) | (x10 >> 15));
 
         x32 = (x32 + (x54 & ~x10) + (x76 & x10) + xkey[4*i+1]) & 0xFFFF;
-        x32 = ((x32 << 2) | (x32 >> 14)) & 0xFFFF;
+        x32 = ((x32 << 2) | (x32 >> 14));
 
         x54 = (x54 + (x76 & ~x32) + (x10 & x32) + xkey[4*i+2]) & 0xFFFF;
-        x54 = ((x54 << 3) | (x54 >> 13)) & 0xFFFF;
+        x54 = ((x54 << 3) | (x54 >> 13));
 
         x76 = (x76 + (x10 & ~x54) + (x32 & x54) + xkey[4*i+3]) & 0xFFFF;
-        x76 = ((x76 << 5) | (x76 >> 11)) & 0xFFFF;
+        x76 = ((x76 << 5) | (x76 >> 11));
 
         if (i == 4 || i == 10) {
             x10 = (x10 + xkey[x76 & 63]) & 0xFFFF;
@@ -199,9 +189,9 @@
     unsigned *xkey;
     int i;
 
-    _ARGCHK(plain != NULL);
+    _ARGCHK(plain  != NULL);
     _ARGCHK(cipher != NULL);
-    _ARGCHK(skey != NULL);
+    _ARGCHK(skey   != NULL);
 
     xkey = skey->rc2.xkey;
 
@@ -218,16 +208,16 @@
             x10 = (x10 - xkey[x76 & 63]) & 0xFFFF;
         }
 
-        x76 = ((x76 << 11) | (x76 >> 5)) & 0xFFFF;
+        x76 = ((x76 << 11) | (x76 >> 5));
         x76 = (x76 - ((x10 & ~x54) + (x32 & x54) + xkey[4*i+3])) & 0xFFFF;
 
-        x54 = ((x54 << 13) | (x54 >> 3)) & 0xFFFF;
+        x54 = ((x54 << 13) | (x54 >> 3));
         x54 = (x54 - ((x76 & ~x32) + (x10 & x32) + xkey[4*i+2])) & 0xFFFF;
 
-        x32 = ((x32 << 14) | (x32 >> 2)) & 0xFFFF;
+        x32 = ((x32 << 14) | (x32 >> 2));
         x32 = (x32 - ((x54 & ~x10) + (x76 & x10) + xkey[4*i+1])) & 0xFFFF;
 
-        x10 = ((x10 << 15) | (x10 >> 1)) & 0xFFFF;
+        x10 = ((x10 << 15) | (x10 >> 1));
         x10 = (x10 - ((x32 & ~x76) + (x54 & x76) + xkey[4*i+0])) & 0xFFFF;
     }
 
--- a/rc4.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/rc4.c	Sun Dec 19 11:34:45 2004 +0000
@@ -14,11 +14,15 @@
 
 const struct _prng_descriptor rc4_desc = 
 {
-   "rc4",
+   "rc4", 32,
     &rc4_start,
     &rc4_add_entropy,
     &rc4_ready,
-    &rc4_read
+    &rc4_read,
+    &rc4_done,
+    &rc4_export,
+    &rc4_import,
+    &rc4_test
 };
 
 int rc4_start(prng_state *prng)
@@ -33,11 +37,18 @@
 
 int rc4_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
 {
-    _ARGCHK(buf != NULL);
+    _ARGCHK(buf  != NULL);
     _ARGCHK(prng != NULL);
-
+ 
+    /* trim as required */
     if (prng->rc4.x + len > 256) {
-       return CRYPT_INVALID_KEYSIZE;
+       if (prng->rc4.x == 256) {
+          /* I can't possibly accept another byte, ok maybe a mint wafer... */
+          return CRYPT_OK;
+       } else {
+          /* only accept part of it */
+          len = 256 - prng->rc4.x;
+       }       
     }
 
     while (len--) {
@@ -50,26 +61,30 @@
 
 int rc4_ready(prng_state *prng)
 {
-    unsigned char key[256], tmp;
-    int keylen, x, y;
+    unsigned char key[256], tmp, *s;
+    int keylen, x, y, j;
 
     _ARGCHK(prng != NULL);
 
     /* extract the key */
-    memcpy(key, prng->rc4.buf, 256);
+    s = prng->rc4.buf;
+    XMEMCPY(key, s, 256);
     keylen = prng->rc4.x;
 
     /* make RC4 perm and shuffle */
     for (x = 0; x < 256; x++) {
-        prng->rc4.buf[x] = x;
+        s[x] = x;
     }
 
-    for (x = y = 0; x < 256; x++) {
-        y = (y + prng->rc4.buf[x] + key[x % keylen]) & 255;
-        tmp = prng->rc4.buf[x]; prng->rc4.buf[x] = prng->rc4.buf[y]; prng->rc4.buf[y] = tmp;
+    for (j = x = y = 0; x < 256; x++) {
+        y = (y + prng->rc4.buf[x] + key[j++]) & 255;
+        if (j == keylen) {
+           j = 0; 
+        }
+        tmp = s[x]; s[x] = s[y]; s[y] = tmp;
     }
-    prng->rc4.x = x;
-    prng->rc4.y = y;
+    prng->rc4.x = 0;
+    prng->rc4.y = 0;
 
 #ifdef CLEAN_STACK
     zeromem(key, sizeof(key));
@@ -80,8 +95,7 @@
 
 unsigned long rc4_read(unsigned char *buf, unsigned long len, prng_state *prng)
 {
-   int x, y; 
-   unsigned char *s, tmp;
+   unsigned char x, y, *s, tmp;
    unsigned long n;
 
    _ARGCHK(buf != NULL);
@@ -103,5 +117,92 @@
    return n;
 }
 
+int rc4_done(prng_state *prng)
+{
+   _ARGCHK(prng != NULL);
+   return CRYPT_OK;
+}
+
+int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
+{
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(prng   != NULL);
+
+   if (*outlen < 32) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   if (rc4_read(out, 32, prng) != 32) {
+      return CRYPT_ERROR_READPRNG;
+   }
+   *outlen = 32;
+
+   return CRYPT_OK;
+}
+ 
+int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+   int err;
+   _ARGCHK(in   != NULL);
+   _ARGCHK(prng != NULL);
+
+   if (inlen != 32) {
+      return CRYPT_INVALID_ARG;
+   }
+   
+   if ((err = rc4_start(prng)) != CRYPT_OK) {
+      return err;
+   }
+   return rc4_add_entropy(in, 32, prng);
+}
+
+int rc4_test(void)
+{
+#ifndef LTC_TEST
+   return CRYPT_NOP;
+#else
+   static const struct {
+      unsigned char key[8], pt[8], ct[8];
+   } tests[] = {
+{
+   { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+   { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+   { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 }
+}
+};
+   prng_state prng;
+   unsigned char dst[8];
+   int err, x;
+
+   for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+       if ((err = rc4_start(&prng)) != CRYPT_OK) {
+          return err;
+       }
+       if ((err = rc4_add_entropy(tests[x].key, 8, &prng)) != CRYPT_OK) {
+          return err;
+       }
+       if ((err = rc4_ready(&prng)) != CRYPT_OK) {
+          return err;
+       }
+       XMEMCPY(dst, tests[x].pt, 8);
+       if (rc4_read(dst, 8, &prng) != 8) {
+          return CRYPT_ERROR_READPRNG;
+       }
+       rc4_done(&prng);
+       if (memcmp(dst, tests[x].ct, 8)) {
+#if 0
+          int y;
+          printf("\n\nRC4 failed, I got:\n"); 
+          for (y = 0; y < 8; y++) printf("%02x ", dst[y]);
+          printf("\n");
+#endif
+          return CRYPT_FAIL_TESTVECTOR;
+       }
+   }
+   return CRYPT_OK;
+#endif
+}
+
 #endif
 
--- a/rc5.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/rc5.c	Sun Dec 19 11:34:45 2004 +0000
@@ -81,7 +81,7 @@
 
     /* setup the S array */
     t = (ulong32)(2 * (num_rounds + 1));
-    memcpy(S, stab, t * sizeof(*S));
+    XMEMCPY(S, stab, t * sizeof(*S));
 
     /* mix buffer */
     s = 3 * MAX(t, j);
--- a/rc6.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/rc6.c	Sun Dec 19 11:34:45 2004 +0000
@@ -71,7 +71,7 @@
     }
 
     /* setup the S array */
-    memcpy(S, stab, 44 * sizeof(stab[0]));
+    XMEMCPY(S, stab, 44 * sizeof(stab[0]));
 
     /* mix buffer */
     s = 3 * MAX(44, j);
--- a/rmd128.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/rmd128.c	Sun Dec 19 11:34:45 2004 +0000
@@ -75,9 +75,9 @@
       (a) = ROL((a), (s));
 
 #ifdef CLEAN_STACK
-static void _rmd128_compress(hash_state *md, unsigned char *buf)
+static int _rmd128_compress(hash_state *md, unsigned char *buf)
 #else
-static void rmd128_compress(hash_state *md, unsigned char *buf)
+static int  rmd128_compress(hash_state *md, unsigned char *buf)
 #endif
 {
    ulong32 aa,bb,cc,dd,aaa,bbb,ccc,ddd,X[16];
@@ -244,17 +244,21 @@
    md->rmd128.state[2] = md->rmd128.state[3] + aa + bbb;
    md->rmd128.state[3] = md->rmd128.state[0] + bb + ccc;
    md->rmd128.state[0] = ddd;
+
+   return CRYPT_OK;
 }
 
 #ifdef CLEAN_STACK
-static void rmd128_compress(hash_state *md, unsigned char *buf)
+static int rmd128_compress(hash_state *md, unsigned char *buf)
 {
-   _rmd128_compress(md, buf);
+   int err;
+   err = _rmd128_compress(md, buf);
    burn_stack(sizeof(ulong32) * 24 + sizeof(int));
+   return err;
 }
 #endif
 
-void rmd128_init(hash_state * md)
+int rmd128_init(hash_state * md)
 {
    _ARGCHK(md != NULL);
    md->rmd128.state[0] = 0x67452301UL;
@@ -263,6 +267,7 @@
    md->rmd128.state[3] = 0x10325476UL;
    md->rmd128.curlen   = 0;
    md->rmd128.length   = 0;
+   return CRYPT_OK;
 }
 
 HASH_PROCESS(rmd128_process, rmd128_compress, rmd128, 64)
--- a/rmd160.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/rmd160.c	Sun Dec 19 11:34:45 2004 +0000
@@ -96,9 +96,9 @@
 
 
 #ifdef CLEAN_STACK
-static void _rmd160_compress(hash_state *md, unsigned char *buf)
+static int _rmd160_compress(hash_state *md, unsigned char *buf)
 #else
-static void rmd160_compress(hash_state *md, unsigned char *buf)
+static int  rmd160_compress(hash_state *md, unsigned char *buf)
 #endif
 {
    ulong32 aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16];
@@ -303,17 +303,21 @@
    md->rmd160.state[3] = md->rmd160.state[4] + aa + bbb;
    md->rmd160.state[4] = md->rmd160.state[0] + bb + ccc;
    md->rmd160.state[0] = ddd;
+
+   return CRYPT_OK;
 }
 
 #ifdef CLEAN_STACK
-static void rmd160_compress(hash_state *md, unsigned char *buf)
+static int rmd160_compress(hash_state *md, unsigned char *buf)
 {
-   _rmd160_compress(md, buf);
+   int err;
+   err = _rmd160_compress(md, buf);
    burn_stack(sizeof(ulong32) * 26 + sizeof(int));
+   return err;
 }
 #endif
 
-void rmd160_init(hash_state * md)
+int rmd160_init(hash_state * md)
 {
    _ARGCHK(md != NULL);
    md->rmd160.state[0] = 0x67452301UL;
@@ -323,6 +327,7 @@
    md->rmd160.state[4] = 0xc3d2e1f0UL;
    md->rmd160.curlen   = 0;
    md->rmd160.length   = 0;
+   return CRYPT_OK;
 }
 
 HASH_PROCESS(rmd160_process, rmd160_compress, rmd160, 64)
--- a/rsa_decrypt_key.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/rsa_decrypt_key.c	Sun Dec 19 11:34:45 2004 +0000
@@ -13,7 +13,7 @@
 
 #ifdef MRSA
 
-/* decrypt then OAEP depad  */
+/* (PKCS #1 v2.0) 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,
@@ -23,13 +23,20 @@
 {
   unsigned long modulus_bitlen, modulus_bytelen, x;
   int           err;
+  unsigned char *tmp;
   
   _ARGCHK(outkey != NULL);
   _ARGCHK(keylen != NULL);
   _ARGCHK(key    != NULL);
   _ARGCHK(res    != NULL);
-  
-  /* valid hash ? */
+
+  /* default to invalid */
+  *res = 0;
+
+  /* valid hash/prng ? */
+  if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+     return err;
+  }
   if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
      return err;
   }
@@ -43,15 +50,24 @@
      return CRYPT_INVALID_PACKET;
   }
 
+  /* allocate ram */
+  tmp = XMALLOC(inlen);
+  if (tmp == NULL) {
+     return CRYPT_MEM;
+  }
+
   /* rsa decode the packet */
-  x = *keylen;
-  if ((err = rsa_exptmod(in, inlen, outkey, &x, PK_PRIVATE, prng, prng_idx, key)) != CRYPT_OK) {
+  x = inlen;
+  if ((err = rsa_exptmod(in, inlen, tmp, &x, PK_PRIVATE, prng, prng_idx, key)) != CRYPT_OK) {
+     XFREE(tmp);
      return err;
   }
 
   /* now OAEP decode the packet */
-  return pkcs_1_oaep_decode(outkey, x, lparam, lparamlen, modulus_bitlen, hash_idx,
-                            outkey, keylen, res);
+  err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, hash_idx,
+                           outkey, keylen, res);
+  XFREE(tmp);
+  return err;
 }
 
 #endif /* MRSA */
--- a/rsa_encrypt_key.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/rsa_encrypt_key.c	Sun Dec 19 11:34:45 2004 +0000
@@ -13,7 +13,7 @@
 
 #ifdef MRSA
 
-/* OAEP pad then encrypt */
+/* (PKCS #1 v2.0) 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,
--- a/rsa_export.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/rsa_export.c	Sun Dec 19 11:34:45 2004 +0000
@@ -13,59 +13,43 @@
 
 #ifdef MRSA
 
+/* This will export either an RSAPublicKey or RSAPrivateKey [defined in PKCS #1 v2.1] */
 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)) {
+   if (!(key->type == PK_PRIVATE) && (type == PK_PRIVATE)) {
       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) {
+      /* private key */
+      mp_int zero;
 
-   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);
+      /* first INTEGER == 0 to signify two-prime RSA */
+      if ((err = mp_init(&zero)) != MP_OKAY) {
+         return mpi_to_ltc_error(err);
+      }
+ 
+      /* output is 
+            Version, n, e, d, p, q, d mod (p-1), d mod (q - 1), 1/q mod p
+       */
+      err = der_put_multi_integer(out, outlen, &zero, &key->N, &key->e,
+                          &key->d, &key->p, &key->q, &key->dP,
+                          &key->dQ, &key->qP, NULL);
+ 
+      /* clear zero and return */
+      mp_clear(&zero);
+      return err;
+   } else {
+      /* public key */
+      return der_put_multi_integer(out, outlen, &key->N, &key->e, NULL);
    }
-
-   /* 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	Tue Jun 15 14:07:21 2004 +0000
+++ b/rsa_exptmod.c	Sun Dec 19 11:34:45 2004 +0000
@@ -14,6 +14,7 @@
 
 #ifdef MRSA
 
+/* compute an RSA modular exponentiation */
 int rsa_exptmod(const unsigned char *in,   unsigned long inlen,
                       unsigned char *out,  unsigned long *outlen, int which,
                       prng_state    *prng, int           prng_idx,
@@ -28,11 +29,13 @@
    _ARGCHK(outlen != NULL);
    _ARGCHK(key    != NULL);
    
+   /* valid prng? */
    if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
       return err;
    }
 
-   if (which == PK_PRIVATE && (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED)) {
+   /* is the key of the right type for the operation? */
+   if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) {
       return CRYPT_PK_NOT_PRIVATE;
    }
 
@@ -42,7 +45,7 @@
    }
 
    /* init and copy into tmp */
-   if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != MP_OKAY)                     { goto error; }
+   if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != MP_OKAY)                     { return mpi_to_ltc_error(err); }
    if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, (int)inlen)) != MP_OKAY) { goto error; }
 
    /* sanity check on the input */
@@ -52,24 +55,23 @@
    }
 
    /* are we using the private exponent and is the key optimized? */
-   if (which == PK_PRIVATE && key->type == PK_PRIVATE_OPTIMIZED) {
+   if (which == PK_PRIVATE) {
       /* tmpa = tmp^dP mod p */
       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 = 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; }
-      if ((err = mp_mul(&tmpb, &key->pQ, &tmpb)) != MP_OKAY)                { goto error; }
-      if ((err = mp_addmod(&tmpa, &tmpb, &key->N, &tmp)) != MP_OKAY)        { goto error; }
+      /* tmp = (tmpa - tmpb) * qInv (mod p) */
+      if ((err = mp_sub(&tmpa, &tmpb, &tmp)) != MP_OKAY)                    { goto error; }
+      if ((err = mp_mulmod(&tmp, &key->qP, &key->p, &tmp)) != MP_OKAY)      { goto error; }
+
+      /* tmp = tmpb + q * tmp */
+      if ((err = mp_mul(&tmp, &key->q, &tmp)) != MP_OKAY)                   { goto error; }
+      if ((err = mp_add(&tmp, &tmpb, &tmp)) != MP_OKAY)                     { goto error; }
    } else {
       /* exptmod it */
-      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; }
-      }
+      if ((err = mp_exptmod(&tmp, &key->e, &key->N, &tmp)) != MP_OKAY) { goto error; }
    }
 
    /* read it back */
--- a/rsa_free.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/rsa_free.c	Sun Dec 19 11:34:45 2004 +0000
@@ -18,7 +18,7 @@
 {
    _ARGCHK(key != NULL);
    mp_clear_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP,
-                  &key->qP, &key->pQ, &key->p, &key->q, NULL);
+                  &key->qP, &key->p, &key->q, NULL);
 }
 
 #endif
--- a/rsa_import.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/rsa_import.c	Sun Dec 19 11:34:45 2004 +0000
@@ -13,67 +13,55 @@
 
 #ifdef MRSA
 
+/* import an RSAPublicKey or RSAPrivateKey [two-prime only, defined in PKCS #1 v2.1] */
 int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
 {
-   unsigned long x, y;
+   unsigned long x;
    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) {
+                     &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);
+   /* read first number, it's either N or 0 [0 == private key] */
+   x = inlen;
+   if ((err = der_get_multi_integer(in, &x, &key->N, NULL)) != CRYPT_OK) {
+      goto __ERR;
    }
 
-   /* 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);
-   }
+   /* advance */
+   inlen -= x;
+   in    += x;
+
+   if (mp_cmp_d(&key->N, 0) == MP_EQ) {
+      /* it's a private key */
+      if ((err = der_get_multi_integer(in, &inlen, &key->N, &key->e,
+                          &key->d, &key->p, &key->q, &key->dP,
+                          &key->dQ, &key->qP, NULL)) != CRYPT_OK) {
+         goto __ERR;
+      }
 
-   /* 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);
+      key->type = PK_PRIVATE;
+   } else {
+      /* it's a public key and we lack e */
+      if ((err = der_get_multi_integer(in, &inlen, &key->e, NULL)) != CRYPT_OK) {
+         goto __ERR;
+      }
+
+      /* free up some ram */
+      mp_clear_multi(&key->p, &key->q, &key->qP, &key->dP, &key->dQ, NULL);
+
+      key->type = PK_PUBLIC;
    }
-   if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) {
-      mp_clear(&key->d);
-   }
-
    return CRYPT_OK;
-error:
+__ERR:
    mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,
-                  &key->pQ, &key->qP, &key->p, &key->q, NULL);
+                  &key->qP, &key->p, &key->q, NULL);
    return err;
 }
 
--- a/rsa_make_key.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/rsa_make_key.c	Sun Dec 19 11:34:45 2004 +0000
@@ -61,48 +61,44 @@
 
    /* make key */
    if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP,
-                     &key->qP, &key->pQ, &key->p, &key->q, NULL)) != MP_OKAY) {
+                     &key->qP, &key->p, &key->q, NULL)) != MP_OKAY) {
       goto error;
    }
 
-   if ((err = mp_set_int(&key->e, e)) != MP_OKAY)                  { goto error2; } /* key->e =  e */
-   if ((err = mp_invmod(&key->e, &tmp1, &key->d)) != MP_OKAY)      { goto error2; } /* key->d = 1/e mod lcm(p-1,q-1) */
-   if ((err = mp_mul(&p, &q, &key->N)) != MP_OKAY)                 { goto error2; } /* key->N = pq */
-
-/* optimize for CRT now */
-   /* find d mod q-1 and d mod p-1 */
-   if ((err = mp_sub_d(&p, 1, &tmp1)) != MP_OKAY)                  { goto error2; } /* tmp1 = q-1 */
-   if ((err = mp_sub_d(&q, 1, &tmp2)) != MP_OKAY)                  { goto error2; } /* tmp2 = p-1 */
+   if ((err = mp_set_int(&key->e, e)) != MP_OKAY)                     { goto error2; } /* key->e =  e */
+   if ((err = mp_invmod(&key->e, &tmp1, &key->d)) != MP_OKAY)         { goto error2; } /* key->d = 1/e mod lcm(p-1,q-1) */
+   if ((err = mp_mul(&p, &q, &key->N)) != MP_OKAY)                    { goto error2; } /* key->N = pq */
 
-   if ((err = mp_mod(&key->d, &tmp1, &key->dP)) != MP_OKAY)        { goto error2; } /* dP = d mod p-1 */
-   if ((err = mp_mod(&key->d, &tmp2, &key->dQ)) != MP_OKAY)        { goto error2; } /* dQ = d mod q-1 */
-
-   if ((err = mp_invmod(&q, &p, &key->qP)) != MP_OKAY)             { goto error2; } /* qP = 1/q mod p */
-   if ((err = mp_mulmod(&key->qP, &q, &key->N, &key->qP)) != MP_OKAY)         { goto error2; } /* qP = q * (1/q mod p) mod N */
+   /* optimize for CRT now */
+   /* find d mod q-1 and d mod p-1 */
+   if ((err = mp_sub_d(&p, 1, &tmp1)) != MP_OKAY)                     { goto error2; } /* tmp1 = q-1 */
+   if ((err = mp_sub_d(&q, 1, &tmp2)) != MP_OKAY)                     { goto error2; } /* tmp2 = p-1 */
+   if ((err = mp_mod(&key->d, &tmp1, &key->dP)) != MP_OKAY)           { goto error2; } /* dP = d mod p-1 */
+   if ((err = mp_mod(&key->d, &tmp2, &key->dQ)) != MP_OKAY)           { goto error2; } /* dQ = d mod q-1 */
+   if ((err = mp_invmod(&q, &p, &key->qP)) != MP_OKAY)                { goto error2; } /* qP = 1/q mod p */
 
-   if ((err = mp_invmod(&p, &q, &key->pQ)) != MP_OKAY)             { goto error2; } /* pQ = 1/p mod q */
-   if ((err = mp_mulmod(&key->pQ, &p, &key->N, &key->pQ)) != MP_OKAY)         { goto error2; } /* pQ = p * (1/p mod q) mod N */
-
-   if ((err = mp_copy(&p, &key->p)) != MP_OKAY)                    { goto error2; }
-   if ((err = mp_copy(&q, &key->q)) != MP_OKAY)                    { goto error2; }
+   if ((err = mp_copy(&p, &key->p)) != MP_OKAY)                       { goto error2; }
+   if ((err = mp_copy(&q, &key->q)) != MP_OKAY)                       { goto error2; }
 
    /* shrink ram required  */
-   if ((err = mp_shrink(&key->e)) != MP_OKAY)                      { goto error2; }
-   if ((err = mp_shrink(&key->d)) != MP_OKAY)                      { goto error2; }
-   if ((err = mp_shrink(&key->N)) != MP_OKAY)                      { goto error2; }
-   if ((err = mp_shrink(&key->dQ)) != MP_OKAY)                     { goto error2; }
-   if ((err = mp_shrink(&key->dP)) != MP_OKAY)                     { goto error2; }
-   if ((err = mp_shrink(&key->qP)) != MP_OKAY)                     { goto error2; }
-   if ((err = mp_shrink(&key->pQ)) != MP_OKAY)                     { goto error2; }
-   if ((err = mp_shrink(&key->p)) != MP_OKAY)                      { goto error2; }
-   if ((err = mp_shrink(&key->q)) != MP_OKAY)                      { goto error2; }
+   if ((err = mp_shrink(&key->e)) != MP_OKAY)                         { goto error2; }
+   if ((err = mp_shrink(&key->d)) != MP_OKAY)                         { goto error2; }
+   if ((err = mp_shrink(&key->N)) != MP_OKAY)                         { goto error2; }
+   if ((err = mp_shrink(&key->dQ)) != MP_OKAY)                        { goto error2; }
+   if ((err = mp_shrink(&key->dP)) != MP_OKAY)                        { goto error2; }
+   if ((err = mp_shrink(&key->qP)) != MP_OKAY)                        { goto error2; }
+   if ((err = mp_shrink(&key->p)) != MP_OKAY)                         { goto error2; }
+   if ((err = mp_shrink(&key->q)) != MP_OKAY)                         { goto error2; }
 
-   err = CRYPT_OK;
-   key->type = PK_PRIVATE_OPTIMIZED;
+   /* set key type (in this case it's CRT optimized) */
+   key->type = PK_PRIVATE;
+
+   /* return ok and free temps */
+   err       = CRYPT_OK;
    goto done;
 error2:
    mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,
-                  &key->qP, &key->pQ, &key->p, &key->q, NULL);
+                  &key->qP, &key->p, &key->q, NULL);
 error:
    err = mpi_to_ltc_error(err);
 done:
--- a/rsa_sign_hash.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/rsa_sign_hash.c	Sun Dec 19 11:34:45 2004 +0000
@@ -13,7 +13,7 @@
 
 #ifdef MRSA
 
-/* PSS pad then sign */
+/* (PKCS #1, v2.0) 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,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rsa_v15_decrypt_key.c	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,66 @@
+	/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+/* decrypt then PKCS #1 v1.5 depad  */
+int rsa_v15_decrypt_key(const unsigned char *in,     unsigned long  inlen,
+                              unsigned char *outkey, unsigned long keylen, 
+                              prng_state    *prng,   int            prng_idx,
+                              int           *res,    rsa_key       *key)
+{
+  unsigned long modulus_bitlen, modulus_bytelen, x;
+  int           err;
+  unsigned char *tmp;
+  
+  _ARGCHK(outkey != NULL);
+  _ARGCHK(key    != NULL);
+  _ARGCHK(res    != NULL);
+ 
+  /* default to invalid */
+  *res = 0;
+
+  /* valid prng ? */
+  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 != inlen) {
+     return CRYPT_INVALID_PACKET;
+  }
+
+  /* allocate ram */
+  tmp = XMALLOC(inlen);
+  if (tmp == NULL) {
+     return CRYPT_MEM;
+  }
+
+  /* rsa decode the packet */
+  x = inlen;
+  if ((err = rsa_exptmod(in, inlen, tmp, &x, PK_PRIVATE, prng, prng_idx, key)) != CRYPT_OK) {
+     XFREE(tmp);
+     return err;
+  }
+
+  /* PKCS #1 v1.5 depad */
+  err = pkcs_1_v15_es_decode(tmp, x, modulus_bitlen, outkey, keylen, res);
+  XFREE(tmp);
+  return err;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rsa_v15_encrypt_key.c	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,54 @@
+/* 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
+
+/* PKCS #1 v1.5 pad then encrypt */
+int rsa_v15_encrypt_key(const unsigned char *inkey,    unsigned long  inlen,
+                              unsigned char *outkey,   unsigned long *outlen,
+                              prng_state    *prng,     int            prng_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? */
+  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 > *outlen) {
+     return CRYPT_BUFFER_OVERFLOW;
+  }
+  
+  /* pad it */
+  x = *outlen;
+  if ((err = pkcs_1_v15_es_encode(inkey, inlen, modulus_bitlen, prng, prng_idx, outkey, &x)) != CRYPT_OK) {
+     return err;
+  }
+  
+  /* encrypt it */
+  return rsa_exptmod(outkey, x, outkey, outlen, PK_PUBLIC, prng, prng_idx, key);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rsa_v15_sign_hash.c	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,57 @@
+/* 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
+
+/* PKCS #1 v1.5 pad then sign */
+int rsa_v15_sign_hash(const unsigned char *msghash,  unsigned long  msghashlen, 
+                            unsigned char *sig,      unsigned long *siglen, 
+                            prng_state    *prng,     int            prng_idx,
+                            int            hash_idx, 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;
+  }
+      
+  /* PKCS #1 v1.5 pad the key */
+  x = *siglen;
+  if ((err = pkcs_1_v15_sa_encode(msghash, msghashlen, 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rsa_v15_verify_hash.c	Sun Dec 19 11:34:45 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
+
+/* de-sign then PKCS v1.5 depad */
+int rsa_v15_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, 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);
+
+  /* default to invalid */
+  *stat = 0;
+  
+  /* 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 = XMALLOC(siglen);
+  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_v15_sa_decode(msghash, msghashlen, tmpbuf, x, hash_idx, modulus_bitlen, stat);
+  XFREE(tmpbuf);
+  return err;
+}
+
+#endif
--- a/rsa_verify_hash.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/rsa_verify_hash.c	Sun Dec 19 11:34:45 2004 +0000
@@ -13,7 +13,7 @@
 
 #ifdef MRSA
 
-/* design then PSS depad */
+/* (PKCS #1, v2.0) de-sign 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,
@@ -28,6 +28,9 @@
   _ARGCHK(sig      != NULL);
   _ARGCHK(stat     != NULL);
   _ARGCHK(key      != NULL);
+
+  /* default to invalid */
+  *stat = 0;
   
   /* valid hash ? */
   if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
@@ -48,7 +51,7 @@
   }
   
   /* allocate temp buffer for decoded sig */
-  tmpbuf = XCALLOC(1, modulus_bytelen + 1);
+  tmpbuf = XMALLOC(siglen);
   if (tmpbuf == NULL) {
      return CRYPT_MEM;
   }
--- a/s_ocb_done.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/s_ocb_done.c	Sun Dec 19 11:34:45 2004 +0000
@@ -25,7 +25,7 @@
                      unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode)
 
 {
-   unsigned char Z[MAXBLOCKSIZE], Y[MAXBLOCKSIZE], X[MAXBLOCKSIZE];
+   unsigned char *Z, *Y, *X;
    int err, x;
 
    _ARGCHK(ocb    != NULL);
@@ -41,9 +41,26 @@
       return CRYPT_INVALID_ARG;
    }
 
+   /* allocate ram */
+   Z = XMALLOC(MAXBLOCKSIZE);
+   Y = XMALLOC(MAXBLOCKSIZE);
+   X = XMALLOC(MAXBLOCKSIZE);
+   if (X == NULL || Y == NULL || Z == NULL) {
+      if (X != NULL) {
+         XFREE(X);
+      }
+      if (Y != NULL) {
+         XFREE(Y);
+      }
+      if (Z != NULL) {
+         XFREE(Z);
+      }
+      return CRYPT_MEM;
+   }
+
    /* compute X[m] = len(pt[m]) XOR Lr XOR Z[m] */
    ocb_shift_xor(ocb, X); 
-   memcpy(Z, X, ocb->block_len);
+   XMEMCPY(Z, X, ocb->block_len);
 
    X[ocb->block_len-1] ^= (ptlen*8)&255;
    X[ocb->block_len-2] ^= ((ptlen*8)>>8)&255;
@@ -90,11 +107,16 @@
    *taglen = x;
 
 #ifdef CLEAN_STACK
-   zeromem(X, sizeof(X));
-   zeromem(Y, sizeof(Y));
-   zeromem(Z, sizeof(Z));
+   zeromem(X, MAXBLOCKSIZE);
+   zeromem(Y, MAXBLOCKSIZE);
+   zeromem(Z, MAXBLOCKSIZE);
    zeromem(ocb, sizeof(*ocb));
 #endif
+   
+   XFREE(X);
+   XFREE(Y);
+   XFREE(Z);
+
    return CRYPT_OK;
 }
 
--- a/sha1.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/sha1.c	Sun Dec 19 11:34:45 2004 +0000
@@ -38,9 +38,9 @@
 #define F3(x,y,z)  (x ^ y ^ z)
 
 #ifdef CLEAN_STACK
-static void _sha1_compress(hash_state *md, unsigned char *buf)
+static int _sha1_compress(hash_state *md, unsigned char *buf)
 #else
-static void sha1_compress(hash_state *md, unsigned char *buf)
+static int  sha1_compress(hash_state *md, unsigned char *buf)
 #endif
 {
     ulong32 a,b,c,d,e,W[80],i;
@@ -139,17 +139,21 @@
     md->sha1.state[2] = md->sha1.state[2] + c;
     md->sha1.state[3] = md->sha1.state[3] + d;
     md->sha1.state[4] = md->sha1.state[4] + e;
+
+    return CRYPT_OK;
 }
 
 #ifdef CLEAN_STACK
-static void sha1_compress(hash_state *md, unsigned char *buf)
+static int sha1_compress(hash_state *md, unsigned char *buf)
 {
-   _sha1_compress(md, buf);
+   int err;
+   err = _sha1_compress(md, buf);
    burn_stack(sizeof(ulong32) * 87);
+   return err;
 }
 #endif
 
-void sha1_init(hash_state * md)
+int sha1_init(hash_state * md)
 {
    _ARGCHK(md != NULL);
    md->sha1.state[0] = 0x67452301UL;
@@ -159,6 +163,7 @@
    md->sha1.state[4] = 0xc3d2e1f0UL;
    md->sha1.curlen = 0;
    md->sha1.length = 0;
+   return CRYPT_OK;
 }
 
 HASH_PROCESS(sha1_process, sha1_compress, sha1, 64)
--- a/sha224.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/sha224.c	Sun Dec 19 11:34:45 2004 +0000
@@ -28,7 +28,7 @@
 };
 
 /* init the sha256 er... sha224 state ;-) */
-void sha224_init(hash_state * md)
+int sha224_init(hash_state * md)
 {
     _ARGCHK(md != NULL);
 
@@ -42,6 +42,7 @@
     md->sha256.state[5] = 0x68581511UL;
     md->sha256.state[6] = 0x64f98fa7UL;
     md->sha256.state[7] = 0xbefa4fa4UL;
+    return CRYPT_OK;
 }
 
 int sha224_done(hash_state * md, unsigned char *hash)
@@ -50,7 +51,7 @@
     int err;
 
     err = sha256_done(md, buf);
-    memcpy(hash, buf, 28);
+    XMEMCPY(hash, buf, 28);
 #ifdef CLEAN_STACK
     zeromem(buf, sizeof(buf));
 #endif 
--- a/sha256.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/sha256.c	Sun Dec 19 11:34:45 2004 +0000
@@ -66,9 +66,9 @@
 
 /* compress 512-bits */
 #ifdef CLEAN_STACK
-static void _sha256_compress(hash_state * md, unsigned char *buf)
+static int _sha256_compress(hash_state * md, unsigned char *buf)
 #else
-static void sha256_compress(hash_state * md, unsigned char *buf)
+static int  sha256_compress(hash_state * md, unsigned char *buf)
 #endif
 {
     ulong32 S[8], W[64], t0, t1;
@@ -104,7 +104,7 @@
          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];   \
@@ -185,19 +185,21 @@
     for (i = 0; i < 8; i++) {
         md->sha256.state[i] = md->sha256.state[i] + S[i];
     }
-
+    return CRYPT_OK;
 }
 
 #ifdef CLEAN_STACK
-static void sha256_compress(hash_state * md, unsigned char *buf)
+static int sha256_compress(hash_state * md, unsigned char *buf)
 {
-    _sha256_compress(md, buf);
+    int err;
+    err = _sha256_compress(md, buf);
     burn_stack(sizeof(ulong32) * 74);
+    return err;
 }
 #endif
 
 /* init the sha256 state */
-void sha256_init(hash_state * md)
+int sha256_init(hash_state * md)
 {
     _ARGCHK(md != NULL);
 
@@ -211,6 +213,7 @@
     md->sha256.state[5] = 0x9B05688CUL;
     md->sha256.state[6] = 0x1F83D9ABUL;
     md->sha256.state[7] = 0x5BE0CD19UL;
+    return CRYPT_OK;
 }
 
 HASH_PROCESS(sha256_process, sha256_compress, sha256, 64)
--- a/sha384.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/sha384.c	Sun Dec 19 11:34:45 2004 +0000
@@ -30,7 +30,7 @@
     &sha384_test
 };
 
-void sha384_init(hash_state * md)
+int sha384_init(hash_state * md)
 {
     _ARGCHK(md != NULL);
 
@@ -44,6 +44,7 @@
     md->sha512.state[5] = CONST64(0x8eb44a8768581511);
     md->sha512.state[6] = CONST64(0xdb0c2e0d64f98fa7);
     md->sha512.state[7] = CONST64(0x47b5481dbefa4fa4);
+    return CRYPT_OK;
 }
 
 int sha384_done(hash_state * md, unsigned char *hash)
@@ -58,7 +59,7 @@
     }
 
    sha512_done(md, buf);
-   memcpy(hash, buf, 48);
+   XMEMCPY(hash, buf, 48);
 #ifdef CLEAN_STACK
    zeromem(buf, sizeof(buf));
 #endif
--- a/sha512.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/sha512.c	Sun Dec 19 11:34:45 2004 +0000
@@ -90,9 +90,9 @@
 
 /* compress 1024-bits */
 #ifdef CLEAN_STACK
-static void _sha512_compress(hash_state * md, unsigned char *buf)
+static int _sha512_compress(hash_state * md, unsigned char *buf)
 #else
-static void sha512_compress(hash_state * md, unsigned char *buf)
+static int  sha512_compress(hash_state * md, unsigned char *buf)
 #endif
 {
     ulong64 S[8], W[80], t0, t1;
@@ -151,22 +151,25 @@
     for (i = 0; i < 8; i++) {
         md->sha512.state[i] = md->sha512.state[i] + S[i];
     }
+
+    return CRYPT_OK;
 }
 
 /* compress 1024-bits */
 #ifdef CLEAN_STACK
-static void sha512_compress(hash_state * md, unsigned char *buf)
+static int sha512_compress(hash_state * md, unsigned char *buf)
 {
-    _sha512_compress(md, buf);
+    int err;
+    err = _sha512_compress(md, buf);
     burn_stack(sizeof(ulong64) * 90 + sizeof(int));
+    return err;
 }
 #endif
 
 /* init the sha512 state */
-void sha512_init(hash_state * md)
+int sha512_init(hash_state * md)
 {
     _ARGCHK(md != NULL);
-
     md->sha512.curlen = 0;
     md->sha512.length = 0;
     md->sha512.state[0] = CONST64(0x6a09e667f3bcc908);
@@ -177,6 +180,7 @@
     md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f);
     md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b);
     md->sha512.state[7] = CONST64(0x5be0cd19137e2179);
+    return CRYPT_OK;
 }
 
 HASH_PROCESS(sha512_process, sha512_compress, sha512, 128)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sober128.c	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,444 @@
+/* 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"
+
+/* Implementation of SOBER-128 by Tom St Denis.
+ * Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM.
+ */
+
+#ifdef SOBER128
+
+#include "sober128tab.c"
+
+const struct _prng_descriptor sober128_desc = 
+{
+   "sober128", 64,
+    &sober128_start,
+    &sober128_add_entropy,
+    &sober128_ready,
+    &sober128_read,
+    &sober128_done,
+    &sober128_export,
+    &sober128_import,
+    &sober128_test
+};
+
+/* don't change these... */
+#define N                        17
+#define FOLD                      N /* how many iterations of folding to do */
+#define INITKONST        0x6996c53a /* value of KONST to use during key loading */
+#define KEYP                     15 /* where to insert key words */
+#define FOLDP                     4 /* where to insert non-linear feedback */
+
+#define B(x,i) ((unsigned char)(((x) >> (8*i)) & 0xFF))
+
+static ulong32 BYTE2WORD(unsigned char *b)
+{
+   ulong32 t;
+   LOAD32L(t, b);
+   return t;
+}
+
+#define WORD2BYTE(w, b) STORE32L(b, w)
+
+static void XORWORD(ulong32 w, unsigned char *b)
+{
+   ulong32 t;
+   LOAD32L(t, b);
+   t ^= w;
+   STORE32L(t, b);
+}
+
+/* give correct offset for the current position of the register,
+ * where logically R[0] is at position "zero".
+ */
+#define OFF(zero, i) (((zero)+(i)) % N)
+
+/* step the LFSR */
+/* After stepping, "zero" moves right one place */
+#define STEP(R,z) \
+    R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF];
+
+static void cycle(ulong32 *R)
+{
+    ulong32 t;
+    int     i;
+
+    STEP(R,0);
+    t = R[0];
+    for (i = 1; i < N; ++i) {
+        R[i-1] = R[i];
+    }
+    R[N-1] = t;
+}
+
+/* Return a non-linear function of some parts of the register.
+ */
+#define NLFUNC(c,z) \
+{ \
+    t = c->R[OFF(z,0)] + c->R[OFF(z,16)]; \
+    t ^= Sbox[(t >> 24) & 0xFF]; \
+    t = ROR(t, 8); \
+    t = ((t + c->R[OFF(z,1)]) ^ c->konst) + c->R[OFF(z,6)]; \
+    t ^= Sbox[(t >> 24) & 0xFF]; \
+    t = t + c->R[OFF(z,13)]; \
+}
+
+static ulong32 nltap(struct sober128_prng *c)
+{
+    ulong32 t;
+    NLFUNC(c, 0);
+    return t;
+}
+
+/* initialise to known state
+ */
+int sober128_start(prng_state *prng)
+{
+    int                   i;
+    struct sober128_prng *c;
+
+    _ARGCHK(prng != NULL);
+
+    c = &(prng->sober128);
+    
+    /* Register initialised to Fibonacci numbers */
+    c->R[0] = 1;
+    c->R[1] = 1;
+    for (i = 2; i < N; ++i) {
+       c->R[i] = c->R[i-1] + c->R[i-2];
+    }
+    c->konst = INITKONST;
+
+    /* next add_entropy will be the key */
+    c->flag  = 1;
+    c->set   = 0;
+
+    return CRYPT_OK;
+}
+
+/* Save the current register state
+ */
+static void s128_savestate(struct sober128_prng *c)
+{
+    int i;
+    for (i = 0; i < N; ++i) {
+        c->initR[i] = c->R[i];
+    }
+}
+
+/* initialise to previously saved register state
+ */
+static void s128_reloadstate(struct sober128_prng *c)
+{
+    int i;
+
+    for (i = 0; i < N; ++i) {
+        c->R[i] = c->initR[i];
+    }
+}
+
+/* Initialise "konst"
+ */
+static void s128_genkonst(struct sober128_prng *c)
+{
+    ulong32 newkonst;
+
+    do {
+       cycle(c->R);
+       newkonst = nltap(c);
+    } while ((newkonst & 0xFF000000) == 0);
+    c->konst = newkonst;
+}
+
+/* Load key material into the register
+ */
+#define ADDKEY(k) \
+   c->R[KEYP] += (k);
+
+#define XORNL(nl) \
+   c->R[FOLDP] ^= (nl);
+
+/* nonlinear diffusion of register for key */
+#define DROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); c->R[OFF((z+1),FOLDP)] ^= t; 
+static void s128_diffuse(struct sober128_prng *c)
+{
+    ulong32 t;
+    /* relies on FOLD == N == 17! */
+    DROUND(0);
+    DROUND(1);
+    DROUND(2);
+    DROUND(3);
+    DROUND(4);
+    DROUND(5);
+    DROUND(6);
+    DROUND(7);
+    DROUND(8);
+    DROUND(9);
+    DROUND(10);
+    DROUND(11);
+    DROUND(12);
+    DROUND(13);
+    DROUND(14);
+    DROUND(15);
+    DROUND(16);
+}
+
+int sober128_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
+{
+    struct sober128_prng *c;
+    ulong32               i, k;
+
+    _ARGCHK(buf != NULL);
+    _ARGCHK(prng != NULL);
+    c = &(prng->sober128);
+
+    if (c->flag == 1) {
+       /* this is the first call to the add_entropy so this input is the key */
+       /* len must be multiple of 4 bytes */
+       if ((len & 3) != 0) {
+          return CRYPT_INVALID_KEYSIZE;
+       }
+    
+       for (i = 0; i < len; i += 4) {
+           k = BYTE2WORD((unsigned char *)&buf[i]);
+          ADDKEY(k);
+          cycle(c->R);
+          XORNL(nltap(c));
+       }
+
+       /* also fold in the length of the key */
+       ADDKEY(len);
+
+       /* now diffuse */
+       s128_diffuse(c);
+
+       s128_genkonst(c);
+       s128_savestate(c);
+       c->nbuf = 0;
+       c->flag = 0;       
+       c->set  = 1;
+    } else {
+       /* ok we are adding an IV then... */
+       s128_reloadstate(c);
+
+       /* len must be multiple of 4 bytes */
+       if ((len & 3) != 0) {
+          return CRYPT_INVALID_KEYSIZE;
+       }
+    
+       for (i = 0; i < len; i += 4) {
+           k = BYTE2WORD((unsigned char *)&buf[i]);
+          ADDKEY(k);
+          cycle(c->R);
+          XORNL(nltap(c));
+       }
+
+       /* also fold in the length of the key */
+       ADDKEY(len);
+
+       /* now diffuse */
+       s128_diffuse(c);
+       c->nbuf = 0;
+    }
+
+    return CRYPT_OK;
+}
+
+int sober128_ready(prng_state *prng)
+{
+   return prng->sober128.set == 1 ? CRYPT_OK : CRYPT_ERROR;
+}
+
+/* XOR pseudo-random bytes into buffer
+ */
+#define SROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); XORWORD(t, buf+(z*4));
+
+unsigned long sober128_read(unsigned char *buf, unsigned long nbytes, prng_state *prng)
+{
+   struct sober128_prng *c;
+   ulong32               t, tlen;
+
+   _ARGCHK(buf  != NULL);
+   _ARGCHK(prng != NULL);
+
+   c = &(prng->sober128);
+   t = 0;
+   tlen = nbytes;
+   
+   /* handle any previously buffered bytes */
+   while (c->nbuf != 0 && nbytes != 0) {
+      *buf++ ^= c->sbuf & 0xFF;
+       c->sbuf >>= 8;
+       c->nbuf -= 8;
+       --nbytes;
+   }
+
+#ifndef SMALL_CODE
+    /* do lots at a time, if there's enough to do */
+    while (nbytes >= N*4) {
+      SROUND(0);
+      SROUND(1);
+      SROUND(2);
+      SROUND(3);
+      SROUND(4);
+      SROUND(5);
+      SROUND(6);
+      SROUND(7);
+      SROUND(8);
+      SROUND(9);
+      SROUND(10);
+      SROUND(11);
+      SROUND(12);
+      SROUND(13);
+      SROUND(14);
+      SROUND(15);
+      SROUND(16);
+      buf    += 4*N;
+      nbytes -= 4*N;
+    }
+#endif
+
+    /* do small or odd size buffers the slow way */
+    while (4 <= nbytes) {
+      cycle(c->R);
+      t = nltap(c);
+      XORWORD(t, buf);
+      buf    += 4;
+      nbytes -= 4;
+    }
+
+    /* handle any trailing bytes */
+    if (nbytes != 0) {
+      cycle(c->R);
+      c->sbuf = nltap(c);
+      c->nbuf = 32;
+      while (c->nbuf != 0 && nbytes != 0) {
+          *buf++ ^= c->sbuf & 0xFF;
+          c->sbuf >>= 8;
+          c->nbuf -= 8;
+          --nbytes;
+      }
+    }
+
+    return tlen;
+}
+
+int sober128_done(prng_state *prng)
+{
+   _ARGCHK(prng != NULL);
+   return CRYPT_OK;
+}
+
+int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
+{
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(prng   != NULL);
+
+   if (*outlen < 64) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   if (sober128_read(out, 64, prng) != 64) {
+      return CRYPT_ERROR_READPRNG;
+   }
+   *outlen = 64;
+
+   return CRYPT_OK;
+}
+ 
+int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+   int err;
+   _ARGCHK(in   != NULL);
+   _ARGCHK(prng != NULL);
+
+   if (inlen != 64) {
+      return CRYPT_INVALID_ARG;
+   }
+   
+   if ((err = sober128_start(prng)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = sober128_add_entropy(in, 64, prng)) != CRYPT_OK) {
+      return err;
+   }
+   return sober128_ready(prng);
+}
+
+int sober128_test(void)
+{
+#ifndef LTC_TEST
+   return CRYPT_NOP;
+#else
+   static const struct { 
+     int keylen, ivlen, len;
+     unsigned char key[16], iv[4], out[20];
+   } tests[] = {
+
+{
+   16, 4, 20,
+
+   /* key */
+   { 't', 'e', 's', 't', ' ', 'k', 'e', 'y', 
+     ' ', '1', '2', '8', 'b', 'i', 't', 's' },
+
+   /* IV */
+   { 0x00, 0x00, 0x00, 0x0 },
+
+   /* expected output */
+   { 0x43, 0x50, 0x0c, 0xcf, 0x89, 0x91, 0x9f, 0x1d,
+     0xaa, 0x37, 0x74, 0x95, 0xf4, 0xb4, 0x58, 0xc2, 
+     0x40, 0x37, 0x8b, 0xbb }
+}
+
+};
+   prng_state    prng;
+   unsigned char dst[20];
+   int           err, x;
+
+   for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+       if ((err = sober128_start(&prng)) != CRYPT_OK) {
+          return err;
+       }
+       if ((err = sober128_add_entropy(tests[x].key, tests[x].keylen, &prng)) != CRYPT_OK) {
+          return err;
+       }
+       /* add IV */
+       if ((err = sober128_add_entropy(tests[x].iv, tests[x].ivlen, &prng)) != CRYPT_OK) {
+          return err;
+       }
+
+       /* ready up */
+       if ((err = sober128_ready(&prng)) != CRYPT_OK) {
+          return err;
+       }
+       memset(dst, 0, tests[x].len);
+       if (sober128_read(dst, tests[x].len, &prng) != (unsigned long)tests[x].len) {
+          return CRYPT_ERROR_READPRNG;
+       }
+       sober128_done(&prng);
+       if (memcmp(dst, tests[x].out, tests[x].len)) {
+#if 0
+          printf("\n\nSOBER128 failed, I got:\n"); 
+          for (y = 0; y < tests[x].len; y++) printf("%02x ", dst[y]);
+          printf("\n");
+#endif
+          return CRYPT_FAIL_TESTVECTOR;
+       }
+   }
+   return CRYPT_OK;
+#endif
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sober128tab.c	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,154 @@
+/* $Id: s128multab.h 213 2003-12-16 04:27:12Z ggr $ */
+/* @(#)TuringMultab.h	1.3 (QUALCOMM) 02/09/03 */
+/* Multiplication table for Turing using 0xD02B4367 */
+static const ulong32 Multab[256] = {
+    0x00000000, 0xD02B4367, 0xED5686CE, 0x3D7DC5A9,
+    0x97AC41D1, 0x478702B6, 0x7AFAC71F, 0xAAD18478,
+    0x631582EF, 0xB33EC188, 0x8E430421, 0x5E684746,
+    0xF4B9C33E, 0x24928059, 0x19EF45F0, 0xC9C40697,
+    0xC62A4993, 0x16010AF4, 0x2B7CCF5D, 0xFB578C3A,
+    0x51860842, 0x81AD4B25, 0xBCD08E8C, 0x6CFBCDEB,
+    0xA53FCB7C, 0x7514881B, 0x48694DB2, 0x98420ED5,
+    0x32938AAD, 0xE2B8C9CA, 0xDFC50C63, 0x0FEE4F04,
+    0xC154926B, 0x117FD10C, 0x2C0214A5, 0xFC2957C2,
+    0x56F8D3BA, 0x86D390DD, 0xBBAE5574, 0x6B851613,
+    0xA2411084, 0x726A53E3, 0x4F17964A, 0x9F3CD52D,
+    0x35ED5155, 0xE5C61232, 0xD8BBD79B, 0x089094FC,
+    0x077EDBF8, 0xD755989F, 0xEA285D36, 0x3A031E51,
+    0x90D29A29, 0x40F9D94E, 0x7D841CE7, 0xADAF5F80,
+    0x646B5917, 0xB4401A70, 0x893DDFD9, 0x59169CBE,
+    0xF3C718C6, 0x23EC5BA1, 0x1E919E08, 0xCEBADD6F,
+    0xCFA869D6, 0x1F832AB1, 0x22FEEF18, 0xF2D5AC7F,
+    0x58042807, 0x882F6B60, 0xB552AEC9, 0x6579EDAE,
+    0xACBDEB39, 0x7C96A85E, 0x41EB6DF7, 0x91C02E90,
+    0x3B11AAE8, 0xEB3AE98F, 0xD6472C26, 0x066C6F41,
+    0x09822045, 0xD9A96322, 0xE4D4A68B, 0x34FFE5EC,
+    0x9E2E6194, 0x4E0522F3, 0x7378E75A, 0xA353A43D,
+    0x6A97A2AA, 0xBABCE1CD, 0x87C12464, 0x57EA6703,
+    0xFD3BE37B, 0x2D10A01C, 0x106D65B5, 0xC04626D2,
+    0x0EFCFBBD, 0xDED7B8DA, 0xE3AA7D73, 0x33813E14,
+    0x9950BA6C, 0x497BF90B, 0x74063CA2, 0xA42D7FC5,
+    0x6DE97952, 0xBDC23A35, 0x80BFFF9C, 0x5094BCFB,
+    0xFA453883, 0x2A6E7BE4, 0x1713BE4D, 0xC738FD2A,
+    0xC8D6B22E, 0x18FDF149, 0x258034E0, 0xF5AB7787,
+    0x5F7AF3FF, 0x8F51B098, 0xB22C7531, 0x62073656,
+    0xABC330C1, 0x7BE873A6, 0x4695B60F, 0x96BEF568,
+    0x3C6F7110, 0xEC443277, 0xD139F7DE, 0x0112B4B9,
+    0xD31DD2E1, 0x03369186, 0x3E4B542F, 0xEE601748,
+    0x44B19330, 0x949AD057, 0xA9E715FE, 0x79CC5699,
+    0xB008500E, 0x60231369, 0x5D5ED6C0, 0x8D7595A7,
+    0x27A411DF, 0xF78F52B8, 0xCAF29711, 0x1AD9D476,
+    0x15379B72, 0xC51CD815, 0xF8611DBC, 0x284A5EDB,
+    0x829BDAA3, 0x52B099C4, 0x6FCD5C6D, 0xBFE61F0A,
+    0x7622199D, 0xA6095AFA, 0x9B749F53, 0x4B5FDC34,
+    0xE18E584C, 0x31A51B2B, 0x0CD8DE82, 0xDCF39DE5,
+    0x1249408A, 0xC26203ED, 0xFF1FC644, 0x2F348523,
+    0x85E5015B, 0x55CE423C, 0x68B38795, 0xB898C4F2,
+    0x715CC265, 0xA1778102, 0x9C0A44AB, 0x4C2107CC,
+    0xE6F083B4, 0x36DBC0D3, 0x0BA6057A, 0xDB8D461D,
+    0xD4630919, 0x04484A7E, 0x39358FD7, 0xE91ECCB0,
+    0x43CF48C8, 0x93E40BAF, 0xAE99CE06, 0x7EB28D61,
+    0xB7768BF6, 0x675DC891, 0x5A200D38, 0x8A0B4E5F,
+    0x20DACA27, 0xF0F18940, 0xCD8C4CE9, 0x1DA70F8E,
+    0x1CB5BB37, 0xCC9EF850, 0xF1E33DF9, 0x21C87E9E,
+    0x8B19FAE6, 0x5B32B981, 0x664F7C28, 0xB6643F4F,
+    0x7FA039D8, 0xAF8B7ABF, 0x92F6BF16, 0x42DDFC71,
+    0xE80C7809, 0x38273B6E, 0x055AFEC7, 0xD571BDA0,
+    0xDA9FF2A4, 0x0AB4B1C3, 0x37C9746A, 0xE7E2370D,
+    0x4D33B375, 0x9D18F012, 0xA06535BB, 0x704E76DC,
+    0xB98A704B, 0x69A1332C, 0x54DCF685, 0x84F7B5E2,
+    0x2E26319A, 0xFE0D72FD, 0xC370B754, 0x135BF433,
+    0xDDE1295C, 0x0DCA6A3B, 0x30B7AF92, 0xE09CECF5,
+    0x4A4D688D, 0x9A662BEA, 0xA71BEE43, 0x7730AD24,
+    0xBEF4ABB3, 0x6EDFE8D4, 0x53A22D7D, 0x83896E1A,
+    0x2958EA62, 0xF973A905, 0xC40E6CAC, 0x14252FCB,
+    0x1BCB60CF, 0xCBE023A8, 0xF69DE601, 0x26B6A566,
+    0x8C67211E, 0x5C4C6279, 0x6131A7D0, 0xB11AE4B7,
+    0x78DEE220, 0xA8F5A147, 0x958864EE, 0x45A32789,
+    0xEF72A3F1, 0x3F59E096, 0x0224253F, 0xD20F6658,
+};
+
+/* $Id: s128sbox.h 213 2003-12-16 04:27:12Z ggr $ */
+/* Sbox for SOBER-128 */
+/*
+ * This is really the combination of two SBoxes; the least significant
+ * 24 bits comes from:
+ * 8->32 Sbox generated by Millan et. al. at Queensland University of
+ * Technology. See: E. Dawson, W. Millan, L. Burnett, G. Carter,
+ * "On the Design of 8*32 S-boxes". Unpublished report, by the
+ * Information Systems Research Centre,
+ * Queensland University of Technology, 1999.
+ * 
+ * The most significant 8 bits are the Skipjack "F table", which can be
+ * found at http://csrc.nist.gov/CryptoToolkit/skipjack/skipjack.pdf .
+ * In this optimised table, though, the intent is to XOR the word from
+ * the table selected by the high byte with the input word. Thus, the
+ * high byte is actually the Skipjack F-table entry XORED with its
+ * table index.
+ */
+static const ulong32 Sbox[256] = {
+    0xa3aa1887, 0xd65e435c, 0x0b65c042, 0x800e6ef4,
+    0xfc57ee20, 0x4d84fed3, 0xf066c502, 0xf354e8ae,
+    0xbb2ee9d9, 0x281f38d4, 0x1f829b5d, 0x735cdf3c,
+    0x95864249, 0xbc2e3963, 0xa1f4429f, 0xf6432c35,
+    0xf7f40325, 0x3cc0dd70, 0x5f973ded, 0x9902dc5e,
+    0xda175b42, 0x590012bf, 0xdc94d78c, 0x39aab26b,
+    0x4ac11b9a, 0x8c168146, 0xc3ea8ec5, 0x058ac28f,
+    0x52ed5c0f, 0x25b4101c, 0x5a2db082, 0x370929e1,
+    0x2a1843de, 0xfe8299fc, 0x202fbc4b, 0x833915dd,
+    0x33a803fa, 0xd446b2de, 0x46233342, 0x4fcee7c3,
+    0x3ad607ef, 0x9e97ebab, 0x507f859b, 0xe81f2e2f,
+    0xc55b71da, 0xd7e2269a, 0x1339c3d1, 0x7ca56b36,
+    0xa6c9def2, 0xb5c9fc5f, 0x5927b3a3, 0x89a56ddf,
+    0xc625b510, 0x560f85a7, 0xace82e71, 0x2ecb8816,
+    0x44951e2a, 0x97f5f6af, 0xdfcbc2b3, 0xce4ff55d,
+    0xcb6b6214, 0x2b0b83e3, 0x549ea6f5, 0x9de041af,
+    0x792f1f17, 0xf73b99ee, 0x39a65ec0, 0x4c7016c6,
+    0x857709a4, 0xd6326e01, 0xc7b280d9, 0x5cfb1418,
+    0xa6aff227, 0xfd548203, 0x506b9d96, 0xa117a8c0,
+    0x9cd5bf6e, 0xdcee7888, 0x61fcfe64, 0xf7a193cd,
+    0x050d0184, 0xe8ae4930, 0x88014f36, 0xd6a87088,
+    0x6bad6c2a, 0x1422c678, 0xe9204de7, 0xb7c2e759,
+    0x0200248e, 0x013b446b, 0xda0d9fc2, 0x0414a895,
+    0x3a6cc3a1, 0x56fef170, 0x86c19155, 0xcf7b8a66,
+    0x551b5e69, 0xb4a8623e, 0xa2bdfa35, 0xc4f068cc,
+    0x573a6acd, 0x6355e936, 0x03602db9, 0x0edf13c1,
+    0x2d0bb16d, 0x6980b83c, 0xfeb23763, 0x3dd8a911,
+    0x01b6bc13, 0xf55579d7, 0xf55c2fa8, 0x19f4196e,
+    0xe7db5476, 0x8d64a866, 0xc06e16ad, 0xb17fc515,
+    0xc46feb3c, 0x8bc8a306, 0xad6799d9, 0x571a9133,
+    0x992466dd, 0x92eb5dcd, 0xac118f50, 0x9fafb226,
+    0xa1b9cef3, 0x3ab36189, 0x347a19b1, 0x62c73084,
+    0xc27ded5c, 0x6c8bc58f, 0x1cdde421, 0xed1e47fb,
+    0xcdcc715e, 0xb9c0ff99, 0x4b122f0f, 0xc4d25184,
+    0xaf7a5e6c, 0x5bbf18bc, 0x8dd7c6e0, 0x5fb7e420,
+    0x521f523f, 0x4ad9b8a2, 0xe9da1a6b, 0x97888c02,
+    0x19d1e354, 0x5aba7d79, 0xa2cc7753, 0x8c2d9655,
+    0x19829da1, 0x531590a7, 0x19c1c149, 0x3d537f1c,
+    0x50779b69, 0xed71f2b7, 0x463c58fa, 0x52dc4418,
+    0xc18c8c76, 0xc120d9f0, 0xafa80d4d, 0x3b74c473,
+    0xd09410e9, 0x290e4211, 0xc3c8082b, 0x8f6b334a,
+    0x3bf68ed2, 0xa843cc1b, 0x8d3c0ff3, 0x20e564a0,
+    0xf8f55a4f, 0x2b40f8e7, 0xfea7f15f, 0xcf00fe21,
+    0x8a6d37d6, 0xd0d506f1, 0xade00973, 0xefbbde36,
+    0x84670fa8, 0xfa31ab9e, 0xaedab618, 0xc01f52f5,
+    0x6558eb4f, 0x71b9e343, 0x4b8d77dd, 0x8cb93da6,
+    0x740fd52d, 0x425412f8, 0xc5a63360, 0x10e53ad0,
+    0x5a700f1c, 0x8324ed0b, 0xe53dc1ec, 0x1a366795,
+    0x6d549d15, 0xc5ce46d7, 0xe17abe76, 0x5f48e0a0,
+    0xd0f07c02, 0x941249b7, 0xe49ed6ba, 0x37a47f78,
+    0xe1cfffbd, 0xb007ca84, 0xbb65f4da, 0xb59f35da,
+    0x33d2aa44, 0x417452ac, 0xc0d674a7, 0x2d61a46a,
+    0xdc63152a, 0x3e12b7aa, 0x6e615927, 0xa14fb118,
+    0xa151758d, 0xba81687b, 0xe152f0b3, 0x764254ed,
+    0x34c77271, 0x0a31acab, 0x54f94aec, 0xb9e994cd,
+    0x574d9e81, 0x5b623730, 0xce8a21e8, 0x37917f0b,
+    0xe8a9b5d6, 0x9697adf8, 0xf3d30431, 0x5dcac921,
+    0x76b35d46, 0xaa430a36, 0xc2194022, 0x22bca65e,
+    0xdaec70ba, 0xdfaea8cc, 0x777bae8b, 0x242924d5,
+    0x1f098a5a, 0x4b396b81, 0x55de2522, 0x435c1cb8,
+    0xaeb8fe1d, 0x9db3c697, 0x5b164f83, 0xe0c16376,
+    0xa319224c, 0xd0203b35, 0x433ac0fe, 0x1466a19a,
+    0x45f0b24f, 0x51fda998, 0xc0d52d71, 0xfa0896a8,
+    0xf9e6053f, 0xa4b0d300, 0xd499cbcc, 0xb95e3d40,
+};
--- a/sprng.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/sprng.c	Sun Dec 19 11:34:45 2004 +0000
@@ -19,11 +19,15 @@
 
 const struct _prng_descriptor sprng_desc =
 {
-    "sprng",
+    "sprng", 0,
     &sprng_start,
     &sprng_add_entropy,
     &sprng_ready,
-    &sprng_read
+    &sprng_read,
+    &sprng_done,
+    &sprng_export,
+    &sprng_import,
+    &sprng_test
 };
 
 int sprng_start(prng_state *prng)
@@ -47,6 +51,29 @@
    return rng_get_bytes(buf, len, NULL);
 }
 
+int sprng_done(prng_state *prng)
+{
+   return CRYPT_OK;
+}
+
+int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
+{
+   _ARGCHK(outlen != NULL);
+
+   *outlen = 0;
+   return CRYPT_OK;
+}
+ 
+int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+   return CRYPT_OK;
+}
+
+int sprng_test(void)
+{
+   return CRYPT_OK;
+}
+
 #endif
 
 
--- a/tiger.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/tiger.c	Sun Dec 19 11:34:45 2004 +0000
@@ -558,7 +558,7 @@
 #endif   
 
 /* one round of the hash function */
-INLINE static void round(ulong64 *a, ulong64 *b, ulong64 *c, ulong64 x, int mul)
+INLINE static void tiger_round(ulong64 *a, ulong64 *b, ulong64 *c, ulong64 x, int mul)
 {
     ulong64 tmp;
     tmp = (*c ^= x); 
@@ -574,14 +574,14 @@
 /* one complete pass */
 static void pass(ulong64 *a, ulong64 *b, ulong64 *c, ulong64 *x, int mul)
 {
-   round(a,b,c,x[0],mul); 
-   round(b,c,a,x[1],mul); 
-   round(c,a,b,x[2],mul); 
-   round(a,b,c,x[3],mul); 
-   round(b,c,a,x[4],mul); 
-   round(c,a,b,x[5],mul); 
-   round(a,b,c,x[6],mul); 
-   round(b,c,a,x[7],mul);          
+   tiger_round(a,b,c,x[0],mul); 
+   tiger_round(b,c,a,x[1],mul); 
+   tiger_round(c,a,b,x[2],mul); 
+   tiger_round(a,b,c,x[3],mul); 
+   tiger_round(b,c,a,x[4],mul); 
+   tiger_round(c,a,b,x[5],mul); 
+   tiger_round(a,b,c,x[6],mul); 
+   tiger_round(b,c,a,x[7],mul);          
 }   
 
 /* The key mixing schedule */
@@ -606,9 +606,9 @@
 }    
 
 #ifdef CLEAN_STACK
-static void _tiger_compress(hash_state *md, unsigned char *buf)
+static int _tiger_compress(hash_state *md, unsigned char *buf)
 #else
-static void tiger_compress(hash_state *md, unsigned char *buf)
+static int  tiger_compress(hash_state *md, unsigned char *buf)
 #endif
 {
     ulong64 a, b, c, x[8];
@@ -632,17 +632,21 @@
     md->tiger.state[0] = a ^ md->tiger.state[0];
     md->tiger.state[1] = b - md->tiger.state[1];
     md->tiger.state[2] = c + md->tiger.state[2];
+
+    return CRYPT_OK;
 }
 
 #ifdef CLEAN_STACK
-static void tiger_compress(hash_state *md, unsigned char *buf)
+static int tiger_compress(hash_state *md, unsigned char *buf)
 {
-   _tiger_compress(md, buf);
+   int err;
+   err = _tiger_compress(md, buf);
    burn_stack(sizeof(ulong64) * 11 + sizeof(unsigned long));
+   return err;
 }
 #endif
 
-void tiger_init(hash_state *md)
+int tiger_init(hash_state *md)
 {
     _ARGCHK(md != NULL);
     md->tiger.state[0] = CONST64(0x0123456789ABCDEF);
@@ -650,6 +654,7 @@
     md->tiger.state[2] = CONST64(0xF096A5B4C3B2E187);
     md->tiger.curlen = 0;
     md->tiger.length = 0;
+    return CRYPT_OK;
 }
 
 HASH_PROCESS(tiger_process, tiger_compress, tiger, 64)
--- a/tim_exptmod.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/tim_exptmod.c	Sun Dec 19 11:34:45 2004 +0000
@@ -34,13 +34,13 @@
    }
 
    /* pick random r */ 
-   rtmp = XMALLOC(MAX_RSA_SIZE/8);
+   rlen = mp_unsigned_bin_size(n);
+   rtmp = XMALLOC(rlen);
    if (rtmp == NULL) {
       return CRYPT_MEM;
    }
 
-
-   rlen = mp_unsigned_bin_size(n);
+   /* read in random value "r" */
    if (prng_descriptor[prng_idx].read(rtmp, rlen, prng) != rlen) {
       XFREE(rtmp);
       return CRYPT_ERROR_READPRNG;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tommath_class.h	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,955 @@
+#if !(defined(LTM1) && defined(LTM2) && defined(LTM3))
+#if defined(LTM2)
+#define LTM3
+#endif
+#if defined(LTM1)
+#define LTM2
+#endif
+#define LTM1
+
+#if defined(LTM_ALL)
+#define BN_ERROR_C
+#define BN_FAST_MP_INVMOD_C
+#define BN_FAST_MP_MONTGOMERY_REDUCE_C
+#define BN_FAST_S_MP_MUL_DIGS_C
+#define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+#define BN_FAST_S_MP_SQR_C
+#define BN_MP_2EXPT_C
+#define BN_MP_ABS_C
+#define BN_MP_ADD_C
+#define BN_MP_ADD_D_C
+#define BN_MP_ADDMOD_C
+#define BN_MP_AND_C
+#define BN_MP_CLAMP_C
+#define BN_MP_CLEAR_C
+#define BN_MP_CLEAR_MULTI_C
+#define BN_MP_CMP_C
+#define BN_MP_CMP_D_C
+#define BN_MP_CMP_MAG_C
+#define BN_MP_CNT_LSB_C
+#define BN_MP_COPY_C
+#define BN_MP_COUNT_BITS_C
+#define BN_MP_DIV_C
+#define BN_MP_DIV_2_C
+#define BN_MP_DIV_2D_C
+#define BN_MP_DIV_3_C
+#define BN_MP_DIV_D_C
+#define BN_MP_DR_IS_MODULUS_C
+#define BN_MP_DR_REDUCE_C
+#define BN_MP_DR_SETUP_C
+#define BN_MP_EXCH_C
+#define BN_MP_EXPT_D_C
+#define BN_MP_EXPTMOD_C
+#define BN_MP_EXPTMOD_FAST_C
+#define BN_MP_EXTEUCLID_C
+#define BN_MP_FREAD_C
+#define BN_MP_FWRITE_C
+#define BN_MP_GCD_C
+#define BN_MP_GET_INT_C
+#define BN_MP_GROW_C
+#define BN_MP_INIT_C
+#define BN_MP_INIT_COPY_C
+#define BN_MP_INIT_MULTI_C
+#define BN_MP_INIT_SET_C
+#define BN_MP_INIT_SET_INT_C
+#define BN_MP_INIT_SIZE_C
+#define BN_MP_INVMOD_C
+#define BN_MP_INVMOD_SLOW_C
+#define BN_MP_IS_SQUARE_C
+#define BN_MP_JACOBI_C
+#define BN_MP_KARATSUBA_MUL_C
+#define BN_MP_KARATSUBA_SQR_C
+#define BN_MP_LCM_C
+#define BN_MP_LSHD_C
+#define BN_MP_MOD_C
+#define BN_MP_MOD_2D_C
+#define BN_MP_MOD_D_C
+#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+#define BN_MP_MONTGOMERY_REDUCE_C
+#define BN_MP_MONTGOMERY_SETUP_C
+#define BN_MP_MUL_C
+#define BN_MP_MUL_2_C
+#define BN_MP_MUL_2D_C
+#define BN_MP_MUL_D_C
+#define BN_MP_MULMOD_C
+#define BN_MP_N_ROOT_C
+#define BN_MP_NEG_C
+#define BN_MP_OR_C
+#define BN_MP_PRIME_FERMAT_C
+#define BN_MP_PRIME_IS_DIVISIBLE_C
+#define BN_MP_PRIME_IS_PRIME_C
+#define BN_MP_PRIME_MILLER_RABIN_C
+#define BN_MP_PRIME_NEXT_PRIME_C
+#define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+#define BN_MP_PRIME_RANDOM_EX_C
+#define BN_MP_RADIX_SIZE_C
+#define BN_MP_RADIX_SMAP_C
+#define BN_MP_RAND_C
+#define BN_MP_READ_RADIX_C
+#define BN_MP_READ_SIGNED_BIN_C
+#define BN_MP_READ_UNSIGNED_BIN_C
+#define BN_MP_REDUCE_C
+#define BN_MP_REDUCE_2K_C
+#define BN_MP_REDUCE_2K_SETUP_C
+#define BN_MP_REDUCE_IS_2K_C
+#define BN_MP_REDUCE_SETUP_C
+#define BN_MP_RSHD_C
+#define BN_MP_SET_C
+#define BN_MP_SET_INT_C
+#define BN_MP_SHRINK_C
+#define BN_MP_SIGNED_BIN_SIZE_C
+#define BN_MP_SQR_C
+#define BN_MP_SQRMOD_C
+#define BN_MP_SQRT_C
+#define BN_MP_SUB_C
+#define BN_MP_SUB_D_C
+#define BN_MP_SUBMOD_C
+#define BN_MP_TO_SIGNED_BIN_C
+#define BN_MP_TO_UNSIGNED_BIN_C
+#define BN_MP_TOOM_MUL_C
+#define BN_MP_TOOM_SQR_C
+#define BN_MP_TORADIX_C
+#define BN_MP_TORADIX_N_C
+#define BN_MP_UNSIGNED_BIN_SIZE_C
+#define BN_MP_XOR_C
+#define BN_MP_ZERO_C
+#define BN_PRIME_TAB_C
+#define BN_REVERSE_C
+#define BN_S_MP_ADD_C
+#define BN_S_MP_EXPTMOD_C
+#define BN_S_MP_MUL_DIGS_C
+#define BN_S_MP_MUL_HIGH_DIGS_C
+#define BN_S_MP_SQR_C
+#define BN_S_MP_SUB_C
+#define BNCORE_C
+#endif
+
+#if defined(BN_ERROR_C)
+   #define BN_MP_ERROR_TO_STRING_C
+#endif
+
+#if defined(BN_FAST_MP_INVMOD_C)
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ABS_C
+   #define BN_MP_SET_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_ADD_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C)
+   #define BN_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_GROW_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_FAST_S_MP_MUL_DIGS_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+   #define BN_FAST_S_MP_MUL_DIGS_C
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_FAST_S_MP_SQR_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_2EXPT_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_ABS_C)
+   #define BN_MP_COPY_C
+#endif
+
+#if defined(BN_MP_ADD_C)
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_ADD_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_ADDMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_AND_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_CLAMP_C)
+#endif
+
+#if defined(BN_MP_CLEAR_C)
+#endif
+
+#if defined(BN_MP_CLEAR_MULTI_C)
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_CMP_C)
+   #define BN_MP_CMP_MAG_C
+#endif
+
+#if defined(BN_MP_CMP_D_C)
+#endif
+
+#if defined(BN_MP_CMP_MAG_C)
+#endif
+
+#if defined(BN_MP_CNT_LSB_C)
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_COPY_C)
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_COUNT_BITS_C)
+#endif
+
+#if defined(BN_MP_DIV_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_SET_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SUB_C
+   #define BN_MP_ADD_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_INIT_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DIV_2_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_DIV_2D_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_DIV_3_C)
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DIV_D_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_COPY_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DR_IS_MODULUS_C)
+#endif
+
+#if defined(BN_MP_DR_REDUCE_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_DR_SETUP_C)
+#endif
+
+#if defined(BN_MP_EXCH_C)
+#endif
+
+#if defined(BN_MP_EXPT_D_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_SET_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MUL_C
+#endif
+
+#if defined(BN_MP_EXPTMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_INVMOD_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_ABS_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_DR_IS_MODULUS_C
+   #define BN_MP_REDUCE_IS_2K_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_EXPTMOD_FAST_C
+   #define BN_S_MP_EXPTMOD_C
+#endif
+
+#if defined(BN_MP_EXPTMOD_FAST_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MONTGOMERY_SETUP_C
+   #define BN_FAST_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_DR_SETUP_C
+   #define BN_MP_DR_REDUCE_C
+   #define BN_MP_REDUCE_2K_SETUP_C
+   #define BN_MP_REDUCE_2K_C
+   #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+   #define BN_MP_MULMOD_C
+   #define BN_MP_SET_C
+   #define BN_MP_MOD_C
+   #define BN_MP_COPY_C
+   #define BN_MP_SQR_C
+   #define BN_MP_MUL_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_EXTEUCLID_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_SET_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SUB_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_FREAD_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_S_RMAP_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_CMP_D_C
+#endif
+
+#if defined(BN_MP_FWRITE_C)
+   #define BN_MP_RADIX_SIZE_C
+   #define BN_MP_TORADIX_C
+#endif
+
+#if defined(BN_MP_GCD_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ABS_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_GET_INT_C)
+#endif
+
+#if defined(BN_MP_GROW_C)
+#endif
+
+#if defined(BN_MP_INIT_C)
+#endif
+
+#if defined(BN_MP_INIT_COPY_C)
+   #define BN_MP_COPY_C
+#endif
+
+#if defined(BN_MP_INIT_MULTI_C)
+   #define BN_MP_ERR_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_INIT_SET_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+#endif
+
+#if defined(BN_MP_INIT_SET_INT_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_INT_C
+#endif
+
+#if defined(BN_MP_INIT_SIZE_C)
+   #define BN_MP_INIT_C
+#endif
+
+#if defined(BN_MP_INVMOD_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ISODD_C
+   #define BN_FAST_MP_INVMOD_C
+   #define BN_MP_INVMOD_SLOW_C
+#endif
+
+#if defined(BN_MP_INVMOD_SLOW_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_SET_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_IS_SQUARE_C)
+   #define BN_MP_MOD_D_C
+   #define BN_MP_INIT_SET_INT_C
+   #define BN_MP_MOD_C
+   #define BN_MP_GET_INT_C
+   #define BN_MP_SQRT_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_JACOBI_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_MOD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_KARATSUBA_MUL_C)
+   #define BN_MP_MUL_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_SUB_C
+   #define BN_MP_ADD_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_KARATSUBA_SQR_C)
+   #define BN_MP_KARATSUBA_MUL_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_SQR_C
+   #define BN_MP_SUB_C
+   #define BN_S_MP_ADD_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_LCM_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_GCD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_DIV_C
+   #define BN_MP_MUL_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_LSHD_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_RSHD_C
+#endif
+
+#if defined(BN_MP_MOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_DIV_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_ADD_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_MOD_2D_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_COPY_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MOD_D_C)
+   #define BN_MP_DIV_D_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_2EXPT_C
+   #define BN_MP_SET_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_REDUCE_C)
+   #define BN_MP_MUL_C
+   #define BN_FAST_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_GROW_C
+   #define BN_MP_MONTGOMERY_SETUP_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_SETUP_C)
+#endif
+
+#if defined(BN_MP_MUL_C)
+   #define BN_MP_TOOM_MUL_C
+   #define BN_MP_KARATSUBA_MUL_C
+   #define BN_FAST_S_MP_MUL_DIGS_C
+   #define BN_S_MP_MUL_C
+   #define BN_S_MP_MUL_DIGS_C
+#endif
+
+#if defined(BN_MP_MUL_2_C)
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_MUL_2D_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_GROW_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MUL_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MULMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_MUL_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_N_ROOT_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+   #define BN_MP_COPY_C
+   #define BN_MP_EXPT_D_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SUB_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_NEG_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_OR_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_FERMAT_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_INIT_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_CMP_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_IS_DIVISIBLE_C)
+   #define BN_MP_MOD_D_C
+#endif
+
+#if defined(BN_MP_PRIME_IS_PRIME_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_PRIME_IS_DIVISIBLE_C
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+   #define BN_MP_PRIME_MILLER_RABIN_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_MILLER_RABIN_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SQRMOD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_NEXT_PRIME_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_SET_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_MOD_D_C
+   #define BN_MP_INIT_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_PRIME_MILLER_RABIN_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C)
+#endif
+
+#if defined(BN_MP_PRIME_RANDOM_EX_C)
+   #define BN_MP_READ_UNSIGNED_BIN_C
+   #define BN_MP_PRIME_IS_PRIME_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_D_C
+#endif
+
+#if defined(BN_MP_RADIX_SIZE_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_RADIX_SMAP_C)
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_RAND_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_LSHD_C
+#endif
+
+#if defined(BN_MP_READ_RADIX_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_S_RMAP_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_READ_SIGNED_BIN_C)
+   #define BN_MP_READ_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_READ_UNSIGNED_BIN_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_REDUCE_C)
+   #define BN_MP_REDUCE_SETUP_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_C
+   #define BN_S_MP_MUL_HIGH_DIGS_C
+   #define BN_MP_MOD_2D_C
+   #define BN_S_MP_MUL_DIGS_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_SET_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CMP_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_SETUP_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_2EXPT_C
+   #define BN_MP_CLEAR_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_REDUCE_IS_2K_C)
+   #define BN_MP_REDUCE_2K_C
+   #define BN_MP_COUNT_BITS_C
+#endif
+
+#if defined(BN_MP_REDUCE_SETUP_C)
+   #define BN_MP_2EXPT_C
+   #define BN_MP_DIV_C
+#endif
+
+#if defined(BN_MP_RSHD_C)
+   #define BN_MP_ZERO_C
+#endif
+
+#if defined(BN_MP_SET_C)
+   #define BN_MP_ZERO_C
+#endif
+
+#if defined(BN_MP_SET_INT_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_SHRINK_C)
+#endif
+
+#if defined(BN_MP_SIGNED_BIN_SIZE_C)
+   #define BN_MP_UNSIGNED_BIN_SIZE_C
+#endif
+
+#if defined(BN_MP_SQR_C)
+   #define BN_MP_TOOM_SQR_C
+   #define BN_MP_KARATSUBA_SQR_C
+   #define BN_FAST_S_MP_SQR_C
+   #define BN_S_MP_SQR_C
+#endif
+
+#if defined(BN_MP_SQRMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_SQRT_C)
+   #define BN_MP_N_ROOT_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_DIV_C
+   #define BN_MP_ADD_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_SUB_C)
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_SUB_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_SUBMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_TO_SIGNED_BIN_C)
+   #define BN_MP_TO_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TO_UNSIGNED_BIN_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_TOOM_MUL_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_TOOM_SQR_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_SQR_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_TORADIX_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_TORADIX_N_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_UNSIGNED_BIN_SIZE_C)
+   #define BN_MP_COUNT_BITS_C
+#endif
+
+#if defined(BN_MP_XOR_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_ZERO_C)
+#endif
+
+#if defined(BN_PRIME_TAB_C)
+#endif
+
+#if defined(BN_REVERSE_C)
+#endif
+
+#if defined(BN_S_MP_ADD_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_S_MP_EXPTMOD_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_REDUCE_SETUP_C
+   #define BN_MP_MOD_C
+   #define BN_MP_COPY_C
+   #define BN_MP_SQR_C
+   #define BN_MP_REDUCE_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SET_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_S_MP_MUL_DIGS_C)
+   #define BN_FAST_S_MP_MUL_DIGS_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_MUL_HIGH_DIGS_C)
+   #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_SQR_C)
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_SUB_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BNCORE_C)
+#endif
+
+#ifdef LTM3
+#define LTM_LAST
+#endif
+#include <tommath_superclass.h>
+#include <tommath_class.h>
+#else
+#define LTM_LAST
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tommath_superclass.h	Sun Dec 19 11:34:45 2004 +0000
@@ -0,0 +1,70 @@
+/* super class file for PK algos */
+
+/* default ... include all MPI */
+#define LTM_ALL
+
+/* RSA only (does not support DH/DSA/ECC) */
+// #define SC_RSA_1
+
+/* For reference.... On an Athlon64 optimizing for speed...
+   LTM's mpi.o with all functions [striped] is 142KiB in size.
+*/
+
+/* Works for RSA only, mpi.o is 68KiB */
+#ifdef SC_RSA_1
+   #define BN_MP_SHRINK_C
+   #define BN_MP_LCM_C
+   #define BN_MP_PRIME_RANDOM_EX_C
+   #define BN_MP_INVMOD_C
+   #define BN_MP_GCD_C
+   #define BN_MP_MOD_C
+   #define BN_MP_MULMOD_C
+   #define BN_MP_ADDMOD_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_SET_INT_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_UNSIGNED_BIN_SIZE_C
+   #define BN_MP_TO_UNSIGNED_BIN_C
+   #define BN_MP_MOD_D_C
+   #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+   #define BN_REVERSE_C
+   #define BN_PRIME_TAB_C
+
+   /* other modifiers */
+//   #define BN_MP_DIV_SMALL                    /* Slower division, not critical (currently buggy?) */
+
+   /* here we are on the last pass so we turn things off.  The functions classes are still there
+    * but we remove them specifically from the build.  This also invokes tweaks in functions
+    * like removing support for even moduli, etc...
+    */
+#ifdef LTM_LAST
+   #undef  BN_MP_TOOM_MUL_C
+   #undef  BN_MP_TOOM_SQR_C
+   #undef  BN_MP_KARATSUBA_MUL_C
+   #undef  BN_MP_KARATSUBA_SQR_C
+   #undef  BN_MP_REDUCE_C
+   #undef  BN_MP_REDUCE_SETUP_C
+   #undef  BN_MP_DR_IS_MODULUS_C
+   #undef  BN_MP_DR_SETUP_C
+   #undef  BN_MP_DR_REDUCE_C
+   #undef  BN_MP_REDUCE_IS_2K_C
+   #undef  BN_MP_REDUCE_2K_SETUP_C
+   #undef  BN_MP_REDUCE_2K_C
+   #undef  BN_S_MP_EXPTMOD_C
+   #undef  BN_MP_DIV_3_C
+   #undef  BN_S_MP_MUL_HIGH_DIGS_C
+   #undef  BN_FAST_S_MP_MUL_HIGH_DIGS_C
+   #undef  BN_FAST_MP_INVMOD_C
+
+   /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold
+    * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] 
+    * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without
+    * trouble.  
+    */
+   #undef  BN_S_MP_MUL_DIGS_C
+   #undef  BN_S_MP_SQR_C
+   #undef  BN_MP_MONTGOMERY_REDUCE_C
+#endif
+
+#endif
--- a/whirl.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/whirl.c	Sun Dec 19 11:34:45 2004 +0000
@@ -50,9 +50,9 @@
     SB7(GB(a, i-7, 0))
 
 #ifdef CLEAN_STACK
-static void _whirlpool_compress(hash_state *md, unsigned char *buf)
+static int _whirlpool_compress(hash_state *md, unsigned char *buf)
 #else
-static void whirlpool_compress(hash_state *md, unsigned char *buf)
+static int whirlpool_compress(hash_state *md, unsigned char *buf)
 #endif
 {
    ulong64 K[2][8], T[3][8];
@@ -90,7 +90,7 @@
        /* xor the constant */
        K[0][0] ^= cont[x+1];
        
-       /* apply main transform to T[0] into T[1] */
+       /* apply main transform to T[1] into T[0] */
        for (y = 0; y < 8; y++) {
            T[0][y] = theta_pi_gamma(T[1], y) ^ K[0][y];
        }
@@ -100,22 +100,27 @@
    for (x = 0; x < 8; x++) {
       md->whirlpool.state[x] ^= T[0][x] ^ T[2][x];
    }
+
+   return CRYPT_OK;
 }
 
 
 #ifdef CLEAN_STACK
-static void whirlpool_compress(hash_state *md, unsigned char *buf)
+static int whirlpool_compress(hash_state *md, unsigned char *buf)
 {
-   _whirlpool_compress(md, buf);
+   int err;
+   err = _whirlpool_compress(md, buf);
    burn_stack((5 * 8 * sizeof(ulong64)) + (2 * sizeof(int)));
+   return err;
 }
 #endif
 
 
-void whirlpool_init(hash_state * md)
+int whirlpool_init(hash_state * md)
 {
    _ARGCHK(md != NULL);
    zeromem(&md->whirlpool, sizeof(md->whirlpool));
+   return CRYPT_OK;
 }
 
 HASH_PROCESS(whirlpool_process, whirlpool_compress, whirlpool, 64)
--- a/yarrow.c	Tue Jun 15 14:07:21 2004 +0000
+++ b/yarrow.c	Sun Dec 19 11:34:45 2004 +0000
@@ -15,11 +15,15 @@
 
 const struct _prng_descriptor yarrow_desc =
 {
-    "yarrow",
+    "yarrow", 64,
     &yarrow_start,
     &yarrow_add_entropy,
     &yarrow_ready,
-    &yarrow_read
+    &yarrow_read,
+    &yarrow_done,
+    &yarrow_export,
+    &yarrow_import,
+    &yarrow_test
 };
 
 int yarrow_start(prng_state *prng)
@@ -61,7 +65,7 @@
    prng->yarrow.cipher = register_cipher(&safer_sk128_desc);
 #elif defined(DES)
    prng->yarrow.cipher = register_cipher(&des3_desc);
-#elif
+#else
    #error YARROW needs at least one CIPHER
 #endif
    if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) {
@@ -114,7 +118,9 @@
    }
 
    /* start the hash */
-   hash_descriptor[prng->yarrow.hash].init(&md);
+   if ((err = hash_descriptor[prng->yarrow.hash].init(&md)) != CRYPT_OK) {
+      return err; 
+   }
 
    /* hash the current pool */
    if ((err = hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool, 
@@ -180,5 +186,74 @@
    return len;
 }
 
+int yarrow_done(prng_state *prng)
+{
+   _ARGCHK(prng != NULL);
+   /* call cipher done when we invent one ;-) */
+
+   return CRYPT_OK;
+}
+
+int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
+{
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(prng   != NULL);
+
+   /* we'll write 64 bytes for s&g's */
+   if (*outlen < 64) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   if (yarrow_read(out, 64, prng) != 64) {
+      return CRYPT_ERROR_READPRNG;
+   }
+   *outlen = 64;
+
+   return CRYPT_OK;
+}
+ 
+int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+   int err;
+
+   _ARGCHK(in   != NULL);
+   _ARGCHK(prng != NULL);
+
+   if (inlen != 64) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   if ((err = yarrow_start(prng)) != CRYPT_OK) {
+      return err;
+   }
+   return yarrow_add_entropy(in, 64, prng);
+}
+
+int yarrow_test(void)
+{
+#ifndef LTC_TEST
+   return CRYPT_NOP;
+#else
+   int err;
+   prng_state prng;
+
+   if ((err = yarrow_start(&prng)) != CRYPT_OK) {
+      return err;
+   }
+   
+   /* now let's test the hash/cipher that was chosen */
+   if ((err = cipher_descriptor[prng.yarrow.cipher].test()) != CRYPT_OK) {
+      return err; 
+   }
+   if ((err = hash_descriptor[prng.yarrow.hash].test()) != CRYPT_OK) {
+      return err; 
+   }
+
+   yarrow_done(&prng);
+   return CRYPT_OK;
+#endif
+}
+
 #endif