The unified diff between revisions [1626dca9..] and [a1c3f430..] is displayed below. It can also be downloaded as a raw diff.

#
#
# delete "PLAN"
#
# delete "base64.c"
#
# delete "crypt.out"
#
# delete "crypt.pdf"
#
# delete "gf.c"
#
# delete "keyring.c"
#
# delete "mycrypt_gf.h"
#
# delete "rsa.c"
#
# delete "rsa_sys.c"
#
# delete "strings.c"
#
# delete "tommath.h"
#
# add_dir "demos/test"
#
# add_dir "doc"
#
# add_file "base64_decode.c"
#  content [49ccbccfc3b994abf9539af29b18d0d37991e060]
#
# add_file "base64_encode.c"
#  content [41306437f35d6fd1a1462446b9b9967237a4572d]
#
# add_file "cbc_getiv.c"
#  content [e988ddd3049ba757b3fd6597cf7668edfb00f5a6]
#
# add_file "cbc_setiv.c"
#  content [8e48c5f46e2363cd36e0d27081f7d52c0ea571df]
#
# add_file "cfb_getiv.c"
#  content [59ac5e237c81e1f436a0b8da54bcc5c353506fe1]
#
# add_file "cfb_setiv.c"
#  content [639e29970bb27da0715e6c70eb528e3b6f6aa749]
#
# add_file "ctr_getiv.c"
#  content [6bd784631074f758a426149338a9c276034bc3e1]
#
# add_file "ctr_setiv.c"
#  content [6ba792cb56a6d9298a143de79da714c2c99b82e5]
#
# add_file "demos/test/base64_test.c"
#  content [8563403c95aa7f401d28e079a11ae1546f53a819]
#
# add_file "demos/test/cipher_hash_test.c"
#  content [5583bea1f573708f68ac52da3c4852e9708b94ed]
#
# add_file "demos/test/dh_tests.c"
#  content [db5836adc0a960ff208b529cc1a8060ddf3840b8]
#
# add_file "demos/test/dsa_test.c"
#  content [dda7a8784e843636c1b201a616989e7deadda832]
#
# add_file "demos/test/ecc_test.c"
#  content [c6f856ccd26a648520e74dfc3671db2423887755]
#
# add_file "demos/test/mac_test.c"
#  content [b146fe51848f5a83eca8b0d3019a18e51e35eed1]
#
# add_file "demos/test/makefile"
#  content [41cb74e27182085077426a8a65ce689d74631997]
#
# add_file "demos/test/makefile.icc"
#  content [ba1e3cae1c73187489c4366a45bc0333b0138be3]
#
# add_file "demos/test/makefile.msvc"
#  content [e1dce5e5ec45d9d7d54f6de85c86bb9077e214a4]
#
# add_file "demos/test/modes_test.c"
#  content [82f5d5a22220c23604ef85c0b6365a9dd044b165]
#
# add_file "demos/test/pkcs_1_test.c"
#  content [5cd09f8b0ebd98bb507bbd83b1ea22a31e4bfa9b]
#
# add_file "demos/test/rsa_test.c"
#  content [5c282302d927e2683f17ff312cf50d7afbfd9080]
#
# add_file "demos/test/store_test.c"
#  content [d202711443c1aee0e06d8fcc691883ea5f8e56c5]
#
# add_file "demos/test/test.c"
#  content [671f2b2af594fcf024cf2c7819d3bb11b520372b]
#
# add_file "demos/test/test.h"
#  content [ca8227f354a804ca3d084fae803b0993c37dbf5d]
#
# add_file "doc/crypt.pdf"
#  content [f4d9846f37129b03cdf8969976365a05bd4be09b]
#
# add_file "error_to_string.c"
#  content [4b53223659cd11cfedabf2dbd1ac1f00064ec812]
#
# add_file "ltc_tommath.h"
#  content [c8e202d5b2b69feb8a255872514685eccf82bb03]
#
# add_file "modes_test.c"
#  content [5fb32a2a1cdc4311654b80d027a10dbdcf09fc4b]
#
# add_file "mpi_to_ltc_error.c"
#  content [7d237900c806bdaf1b45494089d37020aa4051f9]
#
# add_file "ofb_getiv.c"
#  content [78815a65ad0934db29c875cf19333887ad1d46e5]
#
# add_file "ofb_setiv.c"
#  content [45017eac234d24e2f2f6c766f36ec6d7ff72788a]
#
# add_file "pkcs_1_v15_es_decode.c"
#  content [21f620c947db684ab3bc11e051edc1d0176086f4]
#
# add_file "pkcs_1_v15_es_encode.c"
#  content [fb6d3ddfe5810de3c92b46edb0f4c8a7b6de615b]
#
# add_file "pkcs_1_v15_sa_decode.c"
#  content [4f6aeaa76927807827ad5a472b8e84d600f9f6cd]
#
# add_file "pkcs_1_v15_sa_encode.c"
#  content [0f05185ad6c209d813573788e5cf5057e9dbaf66]
#
# add_file "rsa_decrypt_key.c"
#  content [471c35e6305e3e3a7819d08525526b0019248723]
#
# add_file "rsa_encrypt_key.c"
#  content [1ca9226d54ce36a9e700000145db98a22b3753d5]
#
# add_file "rsa_export.c"
#  content [520f23951ac1fd1e28ab14a9283ef84abacc8baa]
#
# add_file "rsa_import.c"
#  content [4a7e1456f13ac5313a999164c2f7e41022c3419b]
#
# add_file "rsa_sign_hash.c"
#  content [d3856ae248e093d7f73f48dee96911f2293cd4a5]
#
# add_file "rsa_verify_hash.c"
#  content [a1667bf6fa35453ae0b69bfec574ab3c39525935]
#
# add_file "tim_exptmod.c"
#  content [80dfac51cb0dd33e4d80702187313fc7d96d52d4]
#
# patch "aes.c"
#  from [decb06209890d202bdaa2b2095344580bb9d4b13]
#    to [34c70069a1c05c3e8d6e42f1ef10495b271f425d]
#
# patch "aes_tab.c"
#  from [026d6575ce571ca3ca33e828c9c7c75dc787c696]
#    to [8d84d7ccee23e01c4a8f876735478b5a44d4bd42]
#
# patch "cbc_decrypt.c"
#  from [f6a28de38f7e35337bc38c2f5a81e60cdc104a05]
#    to [290fb8f65b1037f8479d118dd94340458eeaed8d]
#
# patch "changes"
#  from [1dfeb3f2aedcb7f984297fb7d4a7afdbff1cb674]
#    to [b68f47aa1ca092c730b59b38f794c822f473902e]
#
# patch "crypt.c"
#  from [c1c89e3e4d520f3674362686f4b2eb652350c71f]
#    to [14fd6a0ac48eea8e092891cc828a900b55682689]
#
# patch "crypt.tex"
#  from [8e63225b182ba100c6698dcea5381fb0debcb46e]
#    to [f230cd06ff9351b7e4a36fa9a6932a55cedc295f]
#
# patch "crypt_hash_descriptor.c"
#  from [d0386cb2ec1370c57309cb15e08e95c5ca627cd5]
#    to [b5a017b295b4284cddcd27e504148811b52b3405]
#
# patch "demos/small.c"
#  from [1a4e2dca6b16d1474e29005fa8451ddfae81abf8]
#    to [440bca5f72e64be156dbc6485f6068ce0fe8b794]
#
# patch "demos/test.c"
#  from [8548c615d06874b5dae9c3959db9855c499863e0]
#    to [8cc348c95e2631175ebf374edfd3df934607b5f8]
#
# patch "ecb_decrypt.c"
#  from [53780e706a225c2f685332a70fb98a20a462c625]
#    to [92321c1426f8be007eac0df4caf7635cbb5e216f]
#
# patch "makefile"
#  from [b4e997bd6c027d59e2a60ce4b079a9256967bb4b]
#    to [f34bcc5442faad26bb98cd87a2eafd6c788f5184]
#
# patch "makefile.cygwin_dll"
#  from [803e293fbcdeadc6bdb7229739e61b83791e31cc]
#    to [4eee01a79b76b8ba00eccd58b686305d6ff84462]
#
# patch "makefile.icc"
#  from [a82a0d6536f7f69b62b0a15d5ba385ccb5ca2879]
#    to [e951e45a38738fb5a3d61ac43bc039140d34c535]
#
# patch "makefile.msvc"
#  from [b820f04a1e6db4ebeead72049de0b0d93f93e238]
#    to [79b8467715506130a3f3cb20525399f225e623b1]
#
# patch "md2.c"
#  from [b4db9406ea825037a46546994b7f9fb0e5bd21e1]
#    to [446a9d5577967f794c594cfb724dcf1dc48f94fb]
#
# patch "md4.c"
#  from [850599f3a17573e4a2e9c3c69122df74b1d8515f]
#    to [834f4fe24b63861b8787897b033d4f124c064dd4]
#
# patch "md5.c"
#  from [9f6e0c2df3f95e20f91c5c346d6ce3110b160591]
#    to [146b63b358a6d9e087ff5921e29b5a530ec2e7cd]
#
# patch "mpi.c"
#  from [b7d2e380f9a57fad2340798f43f3fc652df5067f]
#    to [95d17e02a09052c7d53ac093066d971f828fe9d7]
#
# patch "mycrypt.h"
#  from [47a3216a12b8ce2f4d6efeb0f78b5d39a823ee64]
#    to [67d2c66396a3d3b332f8ebfb3610ee752c55474e]
#
# patch "mycrypt_cipher.h"
#  from [9deee5e42419a480952beac21c104be76423b6c7]
#    to [c3ce8966f910ff29ec719b9af7d87b70686a02c4]
#
# patch "mycrypt_custom.h"
#  from [aa735b140b9925a32fc521e2ba92b4f0a3079110]
#    to [71c0e7f5d117e5dbbddd77ba1e75d962f49af33f]
#
# patch "mycrypt_hash.h"
#  from [c0e65e241aad97d124741afcc296c4c823034081]
#    to [93c98acbf5e1bf8a08ee1e9934bfa55881986c47]
#
# patch "mycrypt_pk.h"
#  from [b9e347a708e04c332933960fd95ac17f4a20568d]
#    to [ec5fb7007b02c76f82ff0f24fc340d95396cdefa]
#
# patch "mycrypt_pkcs.h"
#  from [315b6018cad585c9c9d5a854bd25e2a8d0cf915a]
#    to [9f28361cb5f5126bc309575ca33b0e30e884ff2e]
#
# patch "ocb_decrypt.c"
#  from [9092f4c0199562e9bf3e9f28774ceb9038373c1c]
#    to [d36abea76b375107933ed6e71564de088a203682]
#
# patch "pkcs_1_oaep_decode.c"
#  from [729397dd6a0a98faff0b8df3b3db64f7355084ee]
#    to [ff3eb43d282de73d129242a35ad6ee9fbff0209c]
#
# patch "pkcs_1_oaep_encode.c"
#  from [eb6e0a6299b6464d9f26286cd00d84671adfc87b]
#    to [4e2fad693071f6eab8883542033a88320709b883]
#
# patch "pkcs_1_pss_decode.c"
#  from [5165a09c5d765df08c24aa67068bfc20b07d0d3a]
#    to [4098b3b99c9f32ac78ca7aa7d9fe4154e14dd23f]
#
# patch "pkcs_1_pss_encode.c"
#  from [b2f328321d233df002192b465777bba6dd6ae3e7]
#    to [a0c15b111517e97a0f55182ad9f8ccf9a6167c4e]
#
# patch "rand_prime.c"
#  from [ec5e7efda34d965eae1cbb0a52473db479da8e35]
#    to [716723552a2ccc6a70d253135151d4595825359a]
#
# patch "rmd128.c"
#  from [7b52ad77825ff94107226edb710d014068a2d3f7]
#    to [749732011d84577bed3c9366ea090b9b6a5c2441]
#
# patch "rmd160.c"
#  from [a0f49ecdfe69fc098a299235f93520507cabcd5c]
#    to [b8595a8ed7d693ee5c60c5e8e71f722eb6c41092]
#
# patch "rsa_exptmod.c"
#  from [6361b239258c3ee1a169a04e01c147080dade30e]
#    to [c23f2543a33b6fe7b8d0bab375336352c85ee739]
#
# patch "rsa_make_key.c"
#  from [8c7c819a278a233cdb9dec1f7eac36a593955059]
#    to [59612917f688ba173a370b6e6cb5274c151047dd]
#
# patch "sha1.c"
#  from [c219f8d01e686c965739cf4c1157d6faf63568c5]
#    to [82ab6899fadd59a69f080fcedea62a128c60acc7]
#
# patch "sha224.c"
#  from [1dbca996c51893963ecfa5a76ce3a0a00e0cf664]
#    to [7a2466729d8dbe51079d1ea89b42a1e422e0ab98]
#
# patch "sha256.c"
#  from [76ba884bf17db0300ef57bd04970b814bec0c634]
#    to [2087aaa8b96b7f63cb7025e6abb3f812aaf354bd]
#
# patch "sha384.c"
#  from [1c06293daaa40114f78aa9b2aa8f38a2b271866e]
#    to [4f1a92e2a188be6eb754d19b718a2450a921e2c6]
#
# patch "sha512.c"
#  from [f679021c238038f2e8c8b8a15416563d6a2833bc]
#    to [a656eaab1f2dd2fbbeb63b88967cad0c11fa1f7d]
#
# patch "tiger.c"
#  from [893ab0b0444497740dc3458fdc9532c3897e98f8]
#    to [7250776761a9c629f1a2ff94764f0ba57f830726]
#
# patch "whirl.c"
#  from [1b15f087805d4d22edfce19f9edf987d87b1081f]
#    to [4036d1c6ad3f1421be81c3e928483f40ae3334c8]
#
# patch "yarrow.c"
#  from [438250d987fc8762d3329b2364d8b737d49de06a]
#    to [443c387d2a917a521ba0a203e674bc6781155296]
#
============================================================
--- base64_decode.c	49ccbccfc3b994abf9539af29b18d0d37991e060
+++ base64_decode.c	49ccbccfc3b994abf9539af29b18d0d37991e060
@@ -0,0 +1,76 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+/* compliant base64 code donated by Wayne Scott (wscott@bitmover.com) */
+#include "mycrypt.h"
+
+#ifdef BASE64
+
+static const unsigned char map[256] = {
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63,
+ 52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255,
+255, 254, 255, 255, 255,   0,   1,   2,   3,   4,   5,   6,
+  7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,
+ 19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255,
+255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
+ 37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
+ 49,  50,  51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255 };
+
+int base64_decode(const unsigned char *in,  unsigned long len,
+                        unsigned char *out, unsigned long *outlen)
+{
+   unsigned long t, x, y, z;
+   unsigned char c;
+   int           g;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   g = 3;
+   for (x = y = z = t = 0; x < len; x++) {
+       c = map[in[x]&0xFF];
+       if (c == 255) continue;
+       if (c == 254) { c = 0; g--; }
+       t = (t<<6)|c;
+       if (++y == 4) {
+          if (z + g > *outlen) {
+             return CRYPT_BUFFER_OVERFLOW;
+          }
+          out[z++] = (unsigned char)((t>>16)&255);
+          if (g > 1) out[z++] = (unsigned char)((t>>8)&255);
+          if (g > 2) out[z++] = (unsigned char)(t&255);
+          y = t = 0;
+       }
+   }
+   if (y != 0) {
+       return CRYPT_INVALID_PACKET;
+   }
+   *outlen = z;
+   return CRYPT_OK;
+}
+
+#endif
+
============================================================
--- base64_encode.c	41306437f35d6fd1a1462446b9b9967237a4572d
+++ base64_encode.c	41306437f35d6fd1a1462446b9b9967237a4572d
@@ -0,0 +1,63 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+/* compliant base64 code donated by Wayne Scott (wscott@bitmover.com) */
+#include "mycrypt.h"
+
+#ifdef BASE64
+
+static const char *codes =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+int base64_encode(const unsigned char *in,  unsigned long len,
+                        unsigned char *out, unsigned long *outlen)
+{
+   unsigned long i, len2, leven;
+   unsigned char *p;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* valid output size ? */
+   len2 = 4 * ((len + 2) / 3);
+   if (*outlen < len2 + 1) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+   p = out;
+   leven = 3*(len / 3);
+   for (i = 0; i < leven; i += 3) {
+       *p++ = codes[(in[0] >> 2) & 0x3F];
+       *p++ = codes[(((in[0] & 3) << 4) + (in[1] >> 4)) & 0x3F];
+       *p++ = codes[(((in[1] & 0xf) << 2) + (in[2] >> 6)) & 0x3F];
+       *p++ = codes[in[2] & 0x3F];
+       in += 3;
+   }
+   /* Pad it if necessary...  */
+   if (i < len) {
+       unsigned a = in[0];
+       unsigned b = (i+1 < len) ? in[1] : 0;
+
+       *p++ = codes[(a >> 2) & 0x3F];
+       *p++ = codes[(((a & 3) << 4) + (b >> 4)) & 0x3F];
+       *p++ = (i+1 < len) ? codes[(((b & 0xf) << 2)) & 0x3F] : '=';
+       *p++ = '=';
+   }
+
+   /* append a NULL byte */
+   *p = '\0';
+
+   /* return ok */
+   *outlen = p - out;
+   return CRYPT_OK;
+}
+
+#endif
+
============================================================
--- cbc_getiv.c	e988ddd3049ba757b3fd6597cf7668edfb00f5a6
+++ cbc_getiv.c	e988ddd3049ba757b3fd6597cf7668edfb00f5a6
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef CBC
+
+int cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc)
+{
+   _ARGCHK(IV  != NULL);
+   _ARGCHK(len != NULL);
+   _ARGCHK(cbc != NULL);
+   if ((unsigned long)cbc->blocklen > *len) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+   memcpy(IV, cbc->IV, cbc->blocklen);
+   *len = cbc->blocklen;
+
+   return CRYPT_OK;
+}
+
+#endif
============================================================
--- cbc_setiv.c	8e48c5f46e2363cd36e0d27081f7d52c0ea571df
+++ cbc_setiv.c	8e48c5f46e2363cd36e0d27081f7d52c0ea571df
@@ -0,0 +1,28 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef CBC
+
+int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc)
+{
+   _ARGCHK(IV  != NULL);
+   _ARGCHK(cbc != NULL);
+   if (len != (unsigned long)cbc->blocklen) {
+      return CRYPT_INVALID_ARG;
+   }
+   memcpy(cbc->IV, IV, len);
+   return CRYPT_OK;
+}
+
+#endif
+
============================================================
--- cfb_getiv.c	59ac5e237c81e1f436a0b8da54bcc5c353506fe1
+++ cfb_getiv.c	59ac5e237c81e1f436a0b8da54bcc5c353506fe1
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef CFB
+
+int cfb_getiv(unsigned char *IV, unsigned long *len, symmetric_CFB *cfb)
+{
+   _ARGCHK(IV  != NULL);
+   _ARGCHK(len != NULL);
+   _ARGCHK(cfb != NULL);
+   if ((unsigned long)cfb->blocklen > *len) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+   memcpy(IV, cfb->IV, cfb->blocklen);
+   *len = cfb->blocklen;
+
+   return CRYPT_OK;
+}
+
+#endif
============================================================
--- cfb_setiv.c	639e29970bb27da0715e6c70eb528e3b6f6aa749
+++ cfb_setiv.c	639e29970bb27da0715e6c70eb528e3b6f6aa749
@@ -0,0 +1,39 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef CFB
+
+int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb)
+{
+   int err;
+
+   _ARGCHK(IV  != NULL);
+   _ARGCHK(cfb != NULL);
+
+   if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) {
+       return err;
+   }
+
+   if (len != (unsigned long)cfb->blocklen) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* force next block */
+   cfb->padlen = 0;
+   cipher_descriptor[cfb->cipher].ecb_encrypt(IV, cfb->IV, &cfb->key);
+
+   return CRYPT_OK;
+}
+
+#endif
+
============================================================
--- ctr_getiv.c	6bd784631074f758a426149338a9c276034bc3e1
+++ ctr_getiv.c	6bd784631074f758a426149338a9c276034bc3e1
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef CTR
+
+int ctr_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr)
+{
+   _ARGCHK(IV  != NULL);
+   _ARGCHK(len != NULL);
+   _ARGCHK(ctr != NULL);
+   if ((unsigned long)ctr->blocklen > *len) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+   memcpy(IV, ctr->ctr, ctr->blocklen);
+   *len = ctr->blocklen;
+
+   return CRYPT_OK;
+}
+
+#endif
============================================================
--- ctr_setiv.c	6ba792cb56a6d9298a143de79da714c2c99b82e5
+++ ctr_setiv.c	6ba792cb56a6d9298a143de79da714c2c99b82e5
@@ -0,0 +1,43 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef CTR
+
+int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr)
+{
+   int err;
+
+   _ARGCHK(IV  != NULL);
+   _ARGCHK(ctr != NULL);
+
+   /* bad param? */
+   if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {
+      return err;
+   }
+
+   if (len != (unsigned long)ctr->blocklen) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* set IV */
+   memcpy(ctr->ctr, IV, len);
+
+   /* force next block */
+   ctr->padlen = 0;
+   cipher_descriptor[ctr->cipher].ecb_encrypt(IV, ctr->pad, &ctr->key);
+
+   return CRYPT_OK;
+}
+
+#endif
+
============================================================
--- demos/test/base64_test.c	8563403c95aa7f401d28e079a11ae1546f53a819
+++ demos/test/base64_test.c	8563403c95aa7f401d28e079a11ae1546f53a819
@@ -0,0 +1,20 @@
+#include  "test.h"
+
+int base64_test(void)
+{
+   unsigned char in[64], out[256], tmp[64];
+   unsigned long x, l1, l2;
+
+   for  (x = 0; x < 64; x++) {
+       yarrow_read(in, x, &test_yarrow);
+       l1 = sizeof(out);
+       DO(base64_encode(in, x, out, &l1));
+       l2 = sizeof(tmp);
+       DO(base64_decode(out, l1, tmp, &l2));
+       if (l2 != x || memcmp(tmp, in, x)) {
+           printf("base64  failed %lu %lu %lu", x, l1, l2);
+           return 1;
+       }
+   }
+   return 0;
+}
============================================================
--- demos/test/cipher_hash_test.c	5583bea1f573708f68ac52da3c4852e9708b94ed
+++ demos/test/cipher_hash_test.c	5583bea1f573708f68ac52da3c4852e9708b94ed
@@ -0,0 +1,20 @@
+/* test the ciphers and hashes using their built-in self-tests */
+
+#include "test.h"
+
+int cipher_hash_test(void)
+{
+   int x;
+
+   /* test ciphers */
+   for (x = 0; cipher_descriptor[x].name != NULL; x++) {
+      DO(cipher_descriptor[x].test());
+   }
+
+   /* test hashes */
+   for (x = 0; hash_descriptor[x].name != NULL; x++) {
+      DO(hash_descriptor[x].test());
+   }
+
+   return 0;
+}
============================================================
--- demos/test/dh_tests.c	db5836adc0a960ff208b529cc1a8060ddf3840b8
+++ demos/test/dh_tests.c	db5836adc0a960ff208b529cc1a8060ddf3840b8
@@ -0,0 +1,87 @@
+#include "test.h"
+
+int dh_tests (void)
+{
+  unsigned char buf[3][4096];
+  unsigned long x, y, z;
+  int           stat, stat2;
+  dh_key        usera, userb;
+
+  DO(dh_test());
+
+  /* make up two keys */
+  DO(dh_make_key (&test_yarrow, find_prng ("yarrow"), 96, &usera));
+  DO(dh_make_key (&test_yarrow, find_prng ("yarrow"), 96, &userb));
+
+  /* make the shared secret */
+  x = 4096;
+  DO(dh_shared_secret (&usera, &userb, buf[0], &x));
+
+  y = 4096;
+  DO(dh_shared_secret (&userb, &usera, buf[1], &y));
+  if (y != x) {
+    printf ("DH Shared keys are not same size.\n");
+    return 1;
+  }
+  if (memcmp (buf[0], buf[1], x)) {
+    printf ("DH Shared keys not same contents.\n");
+    return 1;
+  }
+
+  /* now export userb */
+  y = 4096;
+  DO(dh_export (buf[1], &y, PK_PUBLIC, &userb));
+	  dh_free (&userb);
+
+  /* import and make the shared secret again */
+  DO(dh_import (buf[1], y, &userb));
+  z = 4096;
+  DO(dh_shared_secret (&usera, &userb, buf[2], &z));
+
+  if (z != x) {
+    printf ("failed.  Size don't match?\n");
+    return 1;
+  }
+  if (memcmp (buf[0], buf[2], x)) {
+    printf ("Failed.  Content didn't match.\n");
+    return 1;
+  }
+  dh_free (&usera);
+  dh_free (&userb);
+
+/* test encrypt_key */
+  dh_make_key (&test_yarrow, find_prng ("yarrow"), 128, &usera);
+  for (x = 0; x < 16; x++) {
+    buf[0][x] = x;
+  }
+  y = sizeof (buf[1]);
+  DO(dh_encrypt_key (buf[0], 16, buf[1], &y, &test_yarrow, find_prng ("yarrow"), find_hash ("md5"), &usera));
+  zeromem (buf[0], sizeof (buf[0]));
+  x = sizeof (buf[0]);
+  DO(dh_decrypt_key (buf[1], y, buf[0], &x, &usera));
+  if (x != 16) {
+    printf ("Failed (length)\n");
+    return 1;
+  }
+  for (x = 0; x < 16; x++)
+    if (buf[0][x] != x) {
+      printf ("Failed (contents)\n");
+      return 1;
+    }
+
+/* test sign_hash */
+  for (x = 0; x < 16; x++) {
+     buf[0][x] = x;
+  }
+  x = sizeof (buf[1]);
+  DO(dh_sign_hash (buf[0], 16, buf[1], &x, &test_yarrow		, find_prng ("yarrow"), &usera));
+  DO(dh_verify_hash (buf[1], x, buf[0], 16, &stat, &usera));
+  buf[0][0] ^= 1;
+  DO(dh_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera));
+  if (!(stat == 1 && stat2 == 0)) {
+     printf("dh_sign/verify_hash %d %d", stat, stat2);
+     return 1;
+  }
+  dh_free (&usera);
+  return 0;
+}
============================================================
--- demos/test/dsa_test.c	dda7a8784e843636c1b201a616989e7deadda832
+++ demos/test/dsa_test.c	dda7a8784e843636c1b201a616989e7deadda832
@@ -0,0 +1,51 @@
+#include "test.h"
+
+int dsa_test(void)
+{
+   unsigned char msg[16], out[1024], out2[1024];
+   unsigned long x, y;
+   int err, stat1, stat2;
+   dsa_key key, key2;
+
+   /* make a random key */
+   DO(dsa_make_key(&test_yarrow, find_prng("yarrow"), 20, 128, &key));
+
+   /* verify it */
+   DO(dsa_verify_key(&key, &stat1));
+   if (stat1 == 0) { printf("dsa_verify_key "); return 1; }
+
+   /* sign the message */
+   x = sizeof(out);
+   DO(dsa_sign_hash(msg, sizeof(msg), out, &x, &test_yarrow, find_prng("yarrow"), &key));
+
+   /* verify it once */
+   DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key));
+
+   /* Modify and verify again */
+   msg[0] ^= 1;
+   DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat2, &key));
+   msg[0] ^= 1;
+   if (!(stat1 == 1 && stat2 == 0)) { printf("dsa_verify %d %d", stat1, stat2); return 1; }
+
+   /* test exporting it */
+   x = sizeof(out2);
+   DO(dsa_export(out2, &x, PK_PRIVATE, &key));
+   DO(dsa_import(out2, x, &key2));
+
+   /* verify a signature with it */
+   DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2));
+   if (stat1 == 0) { printf("dsa_verify (import private) %d ", stat1); return 1; }
+   dsa_free(&key2);
+
+   /* export as public now */
+   x = sizeof(out2);
+   DO(dsa_export(out2, &x, PK_PUBLIC, &key));
+   DO(dsa_import(out2, x, &key2));
+   /* verify a signature with it */
+   DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2));
+   if (stat1 == 0) { printf("dsa_verify (import public) %d ", stat1); return 1; }
+   dsa_free(&key2);
+   dsa_free(&key);
+
+   return 0;
+}
============================================================
--- demos/test/ecc_test.c	c6f856ccd26a648520e74dfc3671db2423887755
+++ demos/test/ecc_test.c	c6f856ccd26a648520e74dfc3671db2423887755
@@ -0,0 +1,89 @@
+#include "test.h"
+
+int ecc_tests (void)
+{
+  unsigned char buf[4][4096];
+  unsigned long x, y, z;
+  int           stat, stat2;
+  ecc_key usera, userb;
+
+  DO(ecc_test ());
+
+  /* make up two keys */
+  DO(ecc_make_key (&test_yarrow, find_prng ("yarrow"), 24, &usera));
+  DO(ecc_make_key (&test_yarrow, find_prng ("yarrow"), 24, &userb));
+
+  /* make the shared secret */
+  x = 4096;
+  DO(ecc_shared_secret (&usera, &userb, buf[0], &x));
+
+  y = 4096;
+  DO(ecc_shared_secret (&userb, &usera, buf[1], &y));
+
+  if (y != x) {
+    printf ("ecc Shared keys are not same size.");
+    return 1;
+  }
+
+  if (memcmp (buf[0], buf[1], x)) {
+    printf ("ecc Shared keys not same contents.");
+    return 1;
+  }
+
+  /* now export userb */
+  y = 4096;
+  DO(ecc_export (buf[1], &y, PK_PUBLIC, &userb));
+  ecc_free (&userb);
+
+  /* import and make the shared secret again */
+  DO(ecc_import (buf[1], y, &userb));
+
+  z = 4096;
+  DO(ecc_shared_secret (&usera, &userb, buf[2], &z));
+
+  if (z != x) {
+    printf ("failed.  Size don't match?");
+    return 1;
+  }
+  if (memcmp (buf[0], buf[2], x)) {
+    printf ("Failed.  Content didn't match.");
+    return 1;
+  }
+  ecc_free (&usera);
+  ecc_free (&userb);
+
+/* test encrypt_key */
+  ecc_make_key (&test_yarrow, find_prng ("yarrow"), 20, &usera);
+  for (x = 0; x < 32; x++) {
+    buf[0][x] = x;
+  }
+  y = sizeof (buf[1]);
+  DO(ecc_encrypt_key (buf[0], 32, buf[1], &y, &test_yarrow, find_prng ("yarrow"), find_hash ("sha256"), &usera));
+  zeromem (buf[0], sizeof (buf[0]));
+  x = sizeof (buf[0]);
+  DO(ecc_decrypt_key (buf[1], y, buf[0], &x, &usera));
+  if (x != 32) {
+    printf ("Failed (length)");
+    return 1;
+  }
+  for (x = 0; x < 32; x++)
+    if (buf[0][x] != x) {
+      printf ("Failed (contents)");
+      return 1;
+    }
+/* test sign_hash */
+  for (x = 0; x < 16; x++) {
+    buf[0][x] = x;
+  }
+  x = sizeof (buf[1]);
+  DO(ecc_sign_hash (buf[0], 16, buf[1], &x, &test_yarrow, find_prng ("yarrow"), &usera));
+  DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat, &usera));
+  buf[0][0] ^= 1;
+  DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera));
+  if (!(stat == 1 && stat2 == 0)) {
+    printf("ecc_verify_hash failed");
+    return 1;
+  }
+  ecc_free (&usera);
+  return 0;
+}
============================================================
--- demos/test/mac_test.c	b146fe51848f5a83eca8b0d3019a18e51e35eed1
+++ demos/test/mac_test.c	b146fe51848f5a83eca8b0d3019a18e51e35eed1
@@ -0,0 +1,12 @@
+/* test pmac/omac/hmac */
+#include "test.h"
+
+int mac_test(void)
+{
+   DO(hmac_test());
+   DO(pmac_test());
+   DO(omac_test());
+   DO(eax_test());
+   DO(ocb_test());
+   return 0;
+}
============================================================
--- demos/test/makefile	41cb74e27182085077426a8a65ce689d74631997
+++ demos/test/makefile	41cb74e27182085077426a8a65ce689d74631997
@@ -0,0 +1,13 @@
+# make test harness, it is good.
+CFLAGS += -Wall -W -Os -I../../ -I./
+
+default: test
+
+OBJECTS=test.o cipher_hash_test.o mac_test.o modes_test.o \
+pkcs_1_test.o store_test.o rsa_test.o ecc_test.o dsa_test.c dh_tests.o
+
+test: $(OBJECTS)
+	$(CC) $(OBJECTS) -ltomcrypt -o test
+
+clean:
+	rm -f test *.o *.obj *.exe *~
============================================================
--- demos/test/makefile.icc	ba1e3cae1c73187489c4366a45bc0333b0138be3
+++ demos/test/makefile.icc	ba1e3cae1c73187489c4366a45bc0333b0138be3
@@ -0,0 +1,14 @@
+# make test harness, it is good.
+CFLAGS += -O3 -xN -ip -I../../ -I./
+CC=icc
+
+default: test
+
+OBJECTS=test.o cipher_hash_test.o mac_test.o modes_test.o \
+pkcs_1_test.o store_test.o rsa_test.o ecc_test.o dsa_test.c dh_tests.o
+
+test: $(OBJECTS)
+	$(CC) $(OBJECTS) -ltomcrypt -o test
+
+clean:
+	rm -f test *.o *~
============================================================
--- demos/test/makefile.msvc	e1dce5e5ec45d9d7d54f6de85c86bb9077e214a4
+++ demos/test/makefile.msvc	e1dce5e5ec45d9d7d54f6de85c86bb9077e214a4
@@ -0,0 +1,14 @@
+# make test harness, it is good.
+CFLAGS = $(CFLAGS) /W3 /Ox -I../../ -I./
+
+default: test.exe
+
+OBJECTS = test.obj cipher_hash_test.obj mac_test.obj modes_test.obj \
+pkcs_1_test.obj store_test.obj rsa_test.obj ecc_test.obj dsa_test.c dh_tests.obj
+
+
+test.exe: $(OBJECTS)
+	cl $(OBJECTS) tomcrypt.lib advapi32.lib
+
+clean:
+	rm -f test.exe *.obj *~
============================================================
--- demos/test/modes_test.c	82f5d5a22220c23604ef85c0b6365a9dd044b165
+++ demos/test/modes_test.c	82f5d5a22220c23604ef85c0b6365a9dd044b165
@@ -0,0 +1,112 @@
+/* test CFB/OFB/CBC modes */
+#include "test.h"
+
+int modes_test(void)
+{
+   unsigned char pt[64], ct[64], tmp[64], key[16], iv[16], iv2[16];
+   int x, cipher_idx;
+   symmetric_CBC cbc;
+   symmetric_CFB cfb;
+   symmetric_OFB ofb;
+   symmetric_CTR ctr;
+   unsigned long l;
+
+   /* make a random pt, key and iv */
+   yarrow_read(pt,  64, &test_yarrow);
+   yarrow_read(key, 16, &test_yarrow);
+   yarrow_read(iv,  16, &test_yarrow);
+
+   /* get idx of AES handy */
+   cipher_idx = find_cipher("aes");
+   if (cipher_idx == -1) {
+      printf("test requires AES");
+      return 1;
+   }
+
+   /* test CBC mode */
+   /* encode the block */
+   DO(cbc_start(cipher_idx, iv, key, 16, 0, &cbc));
+   l = sizeof(iv2);
+   DO(cbc_getiv(iv2, &l, &cbc));
+   if (l != 16 || memcmp(iv2, iv, 16)) {
+      printf("cbc_getiv failed");
+      return 1;
+   }
+   for (x = 0; x < 4; x++) {
+      DO(cbc_encrypt(pt+x*16, ct+x*16, &cbc));
+   }
+
+   /* decode the block */
+   DO(cbc_setiv(iv2, l, &cbc));
+   zeromem(tmp, sizeof(tmp));
+   for (x = 0; x < 4; x++) {
+      DO(cbc_decrypt(ct+x*16, tmp+x*16, &cbc));
+   }
+   if (memcmp(tmp, pt, 64) != 0) {
+      printf("CBC failed");
+      return 1;
+   }
+
+   /* test CFB mode */
+   /* encode the block */
+   DO(cfb_start(cipher_idx, iv, key, 16, 0, &cfb));
+   l = sizeof(iv2);
+   DO(cfb_getiv(iv2, &l, &cfb));
+   /* note we don't memcmp iv2/iv since cfb_start processes the IV for the first block */
+   if (l != 16) {
+      printf("cfb_getiv failed");
+      return 1;
+   }
+   DO(cfb_encrypt(pt, ct, 64, &cfb));
+
+   /* decode the block */
+   DO(cfb_setiv(iv, l, &cfb));
+   zeromem(tmp, sizeof(tmp));
+   DO(cfb_decrypt(ct, tmp, 64, &cfb));
+   if (memcmp(tmp, pt, 64) != 0) {
+      printf("CFB failed");
+      return 1;
+   }
+
+   /* test OFB mode */
+   /* encode the block */
+   DO(ofb_start(cipher_idx, iv, key, 16, 0, &ofb));
+   l = sizeof(iv2);
+   DO(ofb_getiv(iv2, &l, &ofb));
+   if (l != 16 || memcmp(iv2, iv, 16)) {
+      printf("ofb_getiv failed");
+      return 1;
+   }
+   DO(ofb_encrypt(pt, ct, 64, &ofb));
+
+   /* decode the block */
+   DO(ofb_setiv(iv2, l, &ofb));
+   zeromem(tmp, sizeof(tmp));
+   DO(ofb_decrypt(ct, tmp, 64, &ofb));
+   if (memcmp(tmp, pt, 64) != 0) {
+      printf("OFB failed");
+      return 1;
+   }
+
+   /* test CTR mode */
+   /* encode the block */
+   DO(ctr_start(cipher_idx, iv, key, 16, 0, &ctr));
+   l = sizeof(iv2);
+   DO(ctr_getiv(iv2, &l, &ctr));
+   if (l != 16 || memcmp(iv2, iv, 16)) {
+      printf("ctr_getiv failed");
+      return 1;
+   }
+   DO(ctr_encrypt(pt, ct, 64, &ctr));
+
+   /* decode the block */
+   DO(ctr_setiv(iv2, l, &ctr));
+   zeromem(tmp, sizeof(tmp));
+   DO(ctr_decrypt(ct, tmp, 64, &ctr));
+   if (memcmp(tmp, pt, 64) != 0) {
+      printf("CTR failed");
+      return 1;
+   }
+
+   return 0;
+}
============================================================
--- demos/test/pkcs_1_test.c	5cd09f8b0ebd98bb507bbd83b1ea22a31e4bfa9b
+++ demos/test/pkcs_1_test.c	5cd09f8b0ebd98bb507bbd83b1ea22a31e4bfa9b
@@ -0,0 +1,103 @@
+#include "test.h"
+
+int pkcs_1_test(void)
+{
+   unsigned char buf[3][128];
+   int res1, res2, res3, prng_idx, hash_idx;
+   unsigned long x, y, l1, l2, l3, i1, i2, lparamlen, saltlen, modlen;
+   static const unsigned char lparam[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 };
+
+   /* get hash/prng  */
+   hash_idx = find_hash("sha1");
+   prng_idx = find_prng("yarrow");
+
+   if (hash_idx == -1 || prng_idx == -1) {
+      printf("pkcs_1 tests require sha1/yarrow");
+      return 1;
+   }
+
+   /* do many tests */
+   for (x = 0; x < 10000; x++) {
+      zeromem(buf, sizeof(buf));
+
+      /* make a dummy message (of random length) */
+      l3 = (rand() & 31) + 8;
+      for (y = 0; y < l3; y++) buf[0][y] = rand() & 255;
+
+      /* random modulus len (v1.5 must be multiple of 8 though arbitrary sizes seem to work) */
+      modlen = 800 + 8 * (abs(rand()) % 28);
+
+      /* PKCS v1.5 testing (encryption) */
+      l1 = sizeof(buf[1]);
+      DO(pkcs_1_v15_es_encode(buf[0], l3, modlen, &test_yarrow, prng_idx, buf[1], &l1));
+      DO(pkcs_1_v15_es_decode(buf[1], l1, modlen, buf[2], l3, &res1));
+      if (res1 != 1 || memcmp(buf[0], buf[2], l3)) {
+         printf("pkcs v1.5 encrypt failed %d, %lu, %lu ", res1, l1, l3);
+         return 1;
+      }
+
+      /* PKCS v1.5 testing (signatures) */
+      l1 = sizeof(buf[1]);
+      DO(pkcs_1_v15_sa_encode(buf[0], l3, hash_idx, modlen, buf[1], &l1));
+      DO(pkcs_1_v15_sa_decode(buf[0], l3, buf[1], l1, hash_idx, modlen, &res1));
+      buf[0][i1 = abs(rand()) % l3] ^= 1;
+      DO(pkcs_1_v15_sa_decode(buf[0], l3, buf[1], l1, hash_idx, modlen, &res2));
+      buf[0][i1] ^= 1;
+      buf[1][i2 = abs(rand()) % l1] ^= 1;
+      DO(pkcs_1_v15_sa_decode(buf[0], l3, buf[1], l1, hash_idx, modlen, &res3));
+
+      if (!(res1 == 1 && res2 == 0 && res3 == 0)) {
+         printf("pkcs v1.5 sign failed %d %d %d ", res1, res2, res3);
+         return 1;
+      }
+
+      /* pick a random lparam len [0..16] */
+      lparamlen = abs(rand()) % 17;
+
+      /* pick a random saltlen 0..16 */
+      saltlen   = abs(rand()) % 17;
+
+      /* PKCS #1 v2.0 supports modlens not multiple of 8 */
+      modlen = 800 + (abs(rand()) % 224);
+
+      /* encode it */
+      l1 = sizeof(buf[1]);
+      DO(pkcs_1_oaep_encode(buf[0], l3, lparam, lparamlen, modlen, &test_yarrow, prng_idx, hash_idx, buf[1], &l1));
+
+      /* decode it */
+      l2 = sizeof(buf[2]);
+      DO(pkcs_1_oaep_decode(buf[1], l1, lparam, lparamlen, modlen, hash_idx, buf[2], &l2, &res1));
+
+      if (res1 != 1 || l2 != l3 || memcmp(buf[2], buf[0], l3) != 0) {
+         printf("Outsize == %lu, should have been %lu, res1 = %d, lparamlen = %lu, msg contents follow.\n", l2, l3, res1, lparamlen);
+         printf("ORIGINAL:\n");
+         for (x = 0; x < l3; x++) {
+             printf("%02x ", buf[0][x]);
+         }
+         printf("\nRESULT:\n");
+         for (x = 0; x < l2; x++) {
+             printf("%02x ", buf[2][x]);
+         }
+         printf("\n\n");
+         return 1;
+      }
+
+      /* test PSS */
+      l1 = sizeof(buf[1]);
+      DO(pkcs_1_pss_encode(buf[0], l3, saltlen, &test_yarrow, prng_idx, hash_idx, modlen, buf[1], &l1));
+      DO(pkcs_1_pss_decode(buf[0], l3, buf[1], l1, saltlen, hash_idx, modlen, &res1));
+
+      buf[0][i1 = abs(rand()) % l3] ^= 1;
+      DO(pkcs_1_pss_decode(buf[0], l3, buf[1], l1, saltlen, hash_idx, modlen, &res2));
+
+      buf[0][i1] ^= 1;
+      buf[1][i2 = abs(rand()) % l1] ^= 1;
+      DO(pkcs_1_pss_decode(buf[0], l3, buf[1], l1, saltlen, hash_idx, modlen, &res3));
+
+      if (!(res1 == 1 && res2 == 0 && res3 == 0)) {
+         printf("PSS failed: %d, %d, %d, %lu, %lu\n", res1, res2, res3, l3, saltlen);
+         return 1;
+      }
+   }
+   return 0;
+}
============================================================
--- demos/test/rsa_test.c	5c282302d927e2683f17ff312cf50d7afbfd9080
+++ demos/test/rsa_test.c	5c282302d927e2683f17ff312cf50d7afbfd9080
@@ -0,0 +1,91 @@
+#include "test.h"
+
+int rsa_test(void)
+{
+   unsigned char in[1024], out[1024], tmp[1024];
+   rsa_key       key;
+   int           hash_idx, prng_idx, stat, stat2;
+   unsigned long len, len2;
+   static unsigned char lparam[] = { 0x01, 0x02, 0x03, 0x04 };
+
+   hash_idx = find_hash("sha1");
+   prng_idx = find_prng("yarrow");
+   if (hash_idx == -1 || prng_idx == -1) {
+      printf("rsa_test requires SHA1 and yarrow");
+      return 1;
+   }
+
+   /* make a random key/msg */
+   yarrow_read(in, 20, &test_yarrow);
+
+   /* make a random key */
+   DO(rsa_make_key(&test_yarrow, prng_idx, 1024/8, 65537, &key));
+
+   /* encrypt the key (without lparam) */
+   len  = sizeof(out);
+   len2 = sizeof(tmp);
+   DO(rsa_encrypt_key(in, 20, out, &len, NULL, 0, &test_yarrow, prng_idx, hash_idx, &key));
+   /* change a byte */
+   out[0] ^= 1;
+   DO(rsa_decrypt_key(out, len, tmp, &len2, NULL, 0, &test_yarrow, prng_idx, hash_idx, &stat2, &key));
+   /* change a byte back */
+   out[0] ^= 1;
+   DO(rsa_decrypt_key(out, len, tmp, &len2, NULL, 0, &test_yarrow, prng_idx, hash_idx, &stat, &key));
+   if (!(stat == 1 && stat2 == 0)) {
+      printf("rsa_decrypt_key failed");
+      return 1;
+   }
+   if (len2 != 20 || memcmp(tmp, in, 20)) {
+      printf("rsa_decrypt_key mismatch len %lu", len2);
+      return 1;
+   }
+
+   /* encrypt the key (with lparam) */
+   len  = sizeof(out);
+   len2 = sizeof(tmp);
+   DO(rsa_encrypt_key(in, 20, out, &len, lparam, sizeof(lparam), &test_yarrow, prng_idx, hash_idx, &key));
+   /* change a byte */
+   out[0] ^= 1;
+   DO(rsa_decrypt_key(out, len, tmp, &len2, lparam, sizeof(lparam), &test_yarrow, prng_idx, hash_idx, &stat2, &key));
+   /* change a byte back */
+   out[0] ^= 1;
+   DO(rsa_decrypt_key(out, len, tmp, &len2, lparam, sizeof(lparam), &test_yarrow, prng_idx, hash_idx, &stat, &key));
+   if (!(stat == 1 && stat2 == 0)) {
+      printf("rsa_decrypt_key failed");
+      return 1;
+   }
+   if (len2 != 20 || memcmp(tmp, in, 20)) {
+      printf("rsa_decrypt_key mismatch len %lu", len2);
+      return 1;
+   }
+
+   /* sign a message (unsalted, lower cholestorol and Atkins approved) now */
+   len = sizeof(out);
+   DO(rsa_sign_hash(in, 20, out, &len, &test_yarrow, prng_idx, hash_idx, 0, &key));
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 0, &stat, &key));
+   /* change a byte */
+   in[0] ^= 1;
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 0, &stat2, &key));
+
+   if (!(stat == 1 && stat2 == 0)) {
+      printf("rsa_verify_hash (unsalted) failed, %d, %d", stat, stat2);
+      return 1;
+   }
+
+   /* sign a message (salted) now */
+   len = sizeof(out);
+   DO(rsa_sign_hash(in, 20, out, &len, &test_yarrow, prng_idx, hash_idx, 8, &key));
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 8, &stat, &key));
+   /* change a byte */
+   in[0] ^= 1;
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 8, &stat2, &key));
+
+   if (!(stat == 1 && stat2 == 0)) {
+      printf("rsa_verify_hash (salted) failed, %d, %d", stat, stat2);
+      return 1;
+   }
+
+   /* free the key and return */
+   rsa_free(&key);
+   return 0;
+}
============================================================
--- demos/test/store_test.c	d202711443c1aee0e06d8fcc691883ea5f8e56c5
+++ demos/test/store_test.c	d202711443c1aee0e06d8fcc691883ea5f8e56c5
@@ -0,0 +1,43 @@
+#include "test.h"
+
+int store_test(void)
+{
+  unsigned char buf[8];
+  unsigned long L;
+  ulong64 LL;
+
+  L = 0x12345678UL;
+  STORE32L (L, &buf[0]);
+  L = 0;
+  LOAD32L (L, &buf[0]);
+  if (L != 0x12345678UL) {
+    printf ("LOAD/STORE32 Little don't work");
+    return 1;
+  }
+  LL = CONST64 (0x01020304050607);
+  STORE64L (LL, &buf[0]);
+  LL = 0;
+  LOAD64L (LL, &buf[0])
+    if (LL != CONST64 (0x01020304050607)) {
+    printf ("LOAD/STORE64 Little don't work");
+    return 1;
+  }
+
+  L = 0x12345678UL;
+  STORE32H (L, &buf[0]);
+  L = 0;
+  LOAD32H (L, &buf[0]);
+  if (L != 0x12345678UL) {
+    printf ("LOAD/STORE32 High don't work, %08lx", L);
+    return 1;
+  }
+  LL = CONST64 (0x01020304050607);
+  STORE64H (LL, &buf[0]);
+  LL = 0;
+  LOAD64H (LL, &buf[0])
+    if (LL != CONST64 (0x01020304050607)) {
+    printf ("LOAD/STORE64 High don't work");
+    return 1;
+  }
+  return 0;
+}
============================================================
--- demos/test/test.c	671f2b2af594fcf024cf2c7819d3bb11b520372b
+++ demos/test/test.c	671f2b2af594fcf024cf2c7819d3bb11b520372b
@@ -0,0 +1,177 @@
+#include "test.h"
+
+test_entry tests[26];
+
+test_entry test_list[26] = {
+
+/* test name          provides    requires             entry */
+{"store_test",             "a",         "",          store_test           },
+{"cipher_hash_test",       "b",        "a",          cipher_hash_test     },
+{"modes_test",             "c",        "b",          modes_test           },
+{"mac_test",               "d",        "c",          mac_test             },
+{"pkcs_1_test",            "e",        "b",          pkcs_1_test          },
+{"rsa_test",               "f",        "e",          rsa_test             },
+{"ecc_test",               "g",        "a",          ecc_tests            },
+{"dsa_test",               "h",        "a",          dsa_test             },
+{"dh_test",                "i",        "a",          dh_tests             },
+
+{NULL, NULL, NULL, NULL}
+};
+
+prng_state test_yarrow;
+static int current_test;
+
+void run_cmd(int res, int line, char *file, char *cmd)
+{
+   if (res != CRYPT_OK) {
+      fprintf(stderr, "[%s]: %s (%d)\n%s:%d:%s\n", tests[current_test].name, error_to_string(res), res, file, line, cmd);
+      exit(EXIT_FAILURE);
+   }
+}
+
+void register_algs(void)
+{
+#ifdef RIJNDAEL
+  register_cipher (&aes_desc);
+#endif
+#ifdef BLOWFISH
+  register_cipher (&blowfish_desc);
+#endif
+#ifdef XTEA
+  register_cipher (&xtea_desc);
+#endif
+#ifdef RC5
+  register_cipher (&rc5_desc);
+#endif
+#ifdef RC6
+  register_cipher (&rc6_desc);
+#endif
+#ifdef SAFERP
+  register_cipher (&saferp_desc);
+#endif
+#ifdef TWOFISH
+  register_cipher (&twofish_desc);
+#endif
+#ifdef SAFER
+  register_cipher (&safer_k64_desc);
+  register_cipher (&safer_sk64_desc);
+  register_cipher (&safer_k128_desc);
+  register_cipher (&safer_sk128_desc);
+#endif
+#ifdef RC2
+  register_cipher (&rc2_desc);
+#endif
+#ifdef DES
+  register_cipher (&des_desc);
+  register_cipher (&des3_desc);
+#endif
+#ifdef CAST5
+  register_cipher (&cast5_desc);
+#endif
+#ifdef NOEKEON
+  register_cipher (&noekeon_desc);
+#endif
+#ifdef SKIPJACK
+  register_cipher (&skipjack_desc);
+#endif
+#ifdef TIGER
+  register_hash (&tiger_desc);
+#endif
+#ifdef MD2
+  register_hash (&md2_desc);
+#endif
+#ifdef MD4
+  register_hash (&md4_desc);
+#endif
+#ifdef MD5
+  register_hash (&md5_desc);
+#endif
+#ifdef SHA1
+  register_hash (&sha1_desc);
+#endif
+#ifdef SHA256
+  register_hash (&sha256_desc);
+#endif
+#ifdef SHA224
+  register_hash (&sha224_desc);
+#endif
+#ifdef SHA384
+  register_hash (&sha384_desc);
+#endif
+#ifdef SHA512
+  register_hash (&sha512_desc);
+#endif
+#ifdef RIPEMD128
+  register_hash (&rmd128_desc);
+#endif
+#ifdef RIPEMD160
+  register_hash (&rmd160_desc);
+#endif
+#ifdef WHIRLPOOL
+  register_hash (&whirlpool_desc);
+#endif
+
+   if (register_prng(&yarrow_desc) == -1) {
+      printf("Error registering yarrow PRNG\n");
+      exit(-1);
+   }
+
+   if (register_prng(&sprng_desc) == -1) {
+      printf("Error registering sprng PRNG\n");
+      exit(-1);
+   }
+}
+
+/* sort tests based on their requirement/services.  Helps make sure dependencies are tested first */
+void sort(void)
+{
+   unsigned x, y, z, a, pidx[26];
+
+   /* find out where things are provided */
+   zeromem(pidx, sizeof(pidx));
+   z = 0;
+   do {
+      y = 0;
+      for (x = 0; test_list[x].name != NULL; x++) {
+        if (test_list[x].entry == NULL) continue;
+        if (strlen(test_list[x].prov) == 0) {
+           y = 1;
+           tests[z++] = test_list[x]; test_list[x].entry = NULL;
+           pidx[test_list[x].prov[0]-'a'] = 1;
+           break;
+        } else {
+           for (a = 0; a < strlen(test_list[x].req); a++) {
+               if (pidx[test_list[x].req[a]-'a'] == 0) break;
+           }
+           if (a == strlen(test_list[x].req)) {
+              y = 1;
+              tests[z++] = test_list[x]; test_list[x].entry = NULL;
+              pidx[test_list[x].prov[0]-'a'] = 1;
+              break;
+           }
+        }
+      }
+   } while (y == 1);
+}
+
+int main(void)
+{
+   printf("Built with\n%s\n", crypt_build_settings);
+
+   srand(time(NULL));
+   sort();
+   register_algs();
+
+   // start dummy yarrow for internal use
+   DO(yarrow_start(&test_yarrow));
+   DO(yarrow_add_entropy("test", 4, &test_yarrow));
+   DO(yarrow_ready(&test_yarrow));
+
+   // do tests
+   for (current_test = 0; tests[current_test].name != NULL; current_test++) {
+       printf("[%-20s]: ", tests[current_test].name); fflush(stdout);
+       printf("\t%s\n", tests[current_test].entry()==0?"passed":"failed");
+   }
+
+   return 0;
+}
============================================================
--- demos/test/test.h	ca8227f354a804ca3d084fae803b0993c37dbf5d
+++ demos/test/test.h	ca8227f354a804ca3d084fae803b0993c37dbf5d
@@ -0,0 +1,29 @@
+#ifndef __TEST_H_
+#define __TEST_H_
+
+#include "mycrypt.h"
+
+typedef struct {
+    char *name, *prov, *req;
+    int  (*entry)(void);
+} test_entry;
+
+extern prng_state test_yarrow;
+
+void run_cmd(int res, int line, char *file, char *cmd);
+#define DO(x) run_cmd((x), __LINE__, __FILE__, #x)
+
+
+
+/* TESTS */
+int cipher_hash_test(void);
+int modes_test(void);
+int mac_test(void);
+int pkcs_1_test(void);
+int store_test(void);
+int rsa_test(void);
+int ecc_tests(void);
+int dsa_test(void);
+int dh_tests(void);
+
+#endif
============================================================
# doc/crypt.pdf is binary
============================================================
--- error_to_string.c	4b53223659cd11cfedabf2dbd1ac1f00064ec812
+++ error_to_string.c	4b53223659cd11cfedabf2dbd1ac1f00064ec812
@@ -0,0 +1,60 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+static const char *err_2_str[] =
+{
+   "CRYPT_OK",
+   "CRYPT_ERROR",
+   "Non-fatal 'no-operation' requested.",
+
+   "Invalid keysize for block cipher.",
+   "Invalid number of rounds for block cipher.",
+   "Algorithm failed test vectors.",
+
+   "Buffer overflow.",
+   "Invalid input packet.",
+
+   "Invalid number of bits for a PRNG.",
+   "Error reading the PRNG.",
+
+   "Invalid cipher specified.",
+   "Invalid hash specified.",
+   "Invalid PRNG specified.",
+
+   "Out of memory.",
+
+   "Invalid PK key or key type specified for function.",
+   "A private PK key is required.",
+
+   "Invalid argument provided.",
+   "File Not Found",
+
+   "Invalid PK type.",
+   "Invalid PK system.",
+   "Duplicate PK key found on keyring.",
+   "Key not found in keyring.",
+   "Invalid sized parameter.",
+
+   "Invalid size for prime.",
+
+};
+
+const char *error_to_string(int err)
+{
+   if (err < 0 || err >= (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) {
+      return "Invalid error code.";
+   } else {
+      return err_2_str[err];
+   }
+}
+
============================================================
--- ltc_tommath.h	c8e202d5b2b69feb8a255872514685eccf82bb03
+++ ltc_tommath.h	c8e202d5b2b69feb8a255872514685eccf82bb03
@@ -0,0 +1,556 @@
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+#ifndef BN_H_
+#define BN_H_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+
+#undef MIN
+#define MIN(x,y) ((x)<(y)?(x):(y))
+#undef MAX
+#define MAX(x,y) ((x)>(y)?(x):(y))
+
+#ifdef __cplusplus
+extern "C" {
+
+/* C++ compilers don't like assigning void * to mp_digit * */
+#define  OPT_CAST(x)  (x *)
+
+#else
+
+/* C on the other hand doesn't care */
+#define  OPT_CAST(x)
+
+#endif
+
+/* some default configurations.
+ *
+ * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
+ * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits
+ *
+ * At the very least a mp_digit must be able to hold 7 bits
+ * [any size beyond that is ok provided it doesn't overflow the data type]
+ */
+#ifdef MP_8BIT
+   typedef unsigned char      mp_digit;
+   typedef unsigned short     mp_word;
+#elif defined(MP_16BIT)
+   typedef unsigned short     mp_digit;
+   typedef unsigned long      mp_word;
+#elif defined(MP_64BIT)
+   /* for GCC only on supported platforms */
+#ifndef CRYPT
+   typedef unsigned long long ulong64;
+   typedef signed long long   long64;
+#endif
+
+   typedef ulong64            mp_digit;
+   typedef unsigned long      mp_word __attribute__ ((mode(TI)));
+
+   #define DIGIT_BIT          60
+#else
+   /* this is the default case, 28-bit digits */
+
+   /* this is to make porting into LibTomCrypt easier :-) */
+#ifndef CRYPT
+   #if defined(_MSC_VER) || defined(__BORLANDC__)
+      typedef unsigned __int64   ulong64;
+      typedef signed __int64     long64;
+   #else
+      typedef unsigned long long ulong64;
+      typedef signed long long   long64;
+   #endif
+#endif
+
+   typedef unsigned long      mp_digit;
+   typedef ulong64            mp_word;
+
+#ifdef MP_31BIT
+   /* this is an extension that uses 31-bit digits */
+   #define DIGIT_BIT          31
+#else
+   /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */
+   #define DIGIT_BIT          28
+   #define MP_28BIT
+#endif
+#endif
+
+/* define heap macros */
+#ifndef CRYPT
+   /* default to libc stuff */
+   #ifndef XMALLOC
+       #define XMALLOC  malloc
+       #define XFREE    free
+       #define XREALLOC realloc
+       #define XCALLOC  calloc
+   #else
+      /* prototypes for our heap functions */
+      extern void *XMALLOC(size_t n);
+      extern void *REALLOC(void *p, size_t n);
+      extern void *XCALLOC(size_t n, size_t s);
+      extern void XFREE(void *p);
+   #endif
+#endif
+
+
+/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */
+#ifndef DIGIT_BIT
+   #define DIGIT_BIT     ((int)((CHAR_BIT * sizeof(mp_digit) - 1)))  /* bits per digit */
+#endif
+
+#define MP_DIGIT_BIT     DIGIT_BIT
+#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
+#define MP_DIGIT_MAX     MP_MASK
+
+/* equalities */
+#define MP_LT        -1   /* less than */
+#define MP_EQ         0   /* equal to */
+#define MP_GT         1   /* greater than */
+
+#define MP_ZPOS       0   /* positive integer */
+#define MP_NEG        1   /* negative */
+
+#define MP_OKAY       0   /* ok result */
+#define MP_MEM        -2  /* out of mem */
+#define MP_VAL        -3  /* invalid input */
+#define MP_RANGE      MP_VAL
+
+#define MP_YES        1   /* yes response */
+#define MP_NO         0   /* no response */
+
+/* Primality generation flags */
+#define LTM_PRIME_BBS      0x0001 /* BBS style prime */
+#define LTM_PRIME_SAFE     0x0002 /* Safe prime (p-1)/2 == prime */
+#define LTM_PRIME_2MSB_OFF 0x0004 /* force 2nd MSB to 0 */
+#define LTM_PRIME_2MSB_ON  0x0008 /* force 2nd MSB to 1 */
+
+typedef int           mp_err;
+
+/* you'll have to tune these... */
+extern int KARATSUBA_MUL_CUTOFF,
+           KARATSUBA_SQR_CUTOFF,
+           TOOM_MUL_CUTOFF,
+           TOOM_SQR_CUTOFF;
+
+/* define this to use lower memory usage routines (exptmods mostly) */
+/* #define MP_LOW_MEM */
+
+/* default precision */
+#ifndef MP_PREC
+   #ifdef MP_LOW_MEM
+      #define MP_PREC                 64     /* default digits of precision */
+   #else
+      #define MP_PREC                 8      /* default digits of precision */
+   #endif
+#endif
+
+/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
+#define MP_WARRAY               (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
+
+/* the infamous mp_int structure */
+typedef struct  {
+    int used, alloc, sign;
+    mp_digit *dp;
+} mp_int;
+
+/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
+typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
+
+
+#define USED(m)    ((m)->used)
+#define DIGIT(m,k) ((m)->dp[(k)])
+#define SIGN(m)    ((m)->sign)
+
+/* error code to char* string */
+char *mp_error_to_string(int code);
+
+/* ---> init and deinit bignum functions <--- */
+/* init a bignum */
+int mp_init(mp_int *a);
+
+/* free a bignum */
+void mp_clear(mp_int *a);
+
+/* init a null terminated series of arguments */
+int mp_init_multi(mp_int *mp, ...);
+
+/* clear a null terminated series of arguments */
+void mp_clear_multi(mp_int *mp, ...);
+
+/* exchange two ints */
+void mp_exch(mp_int *a, mp_int *b);
+
+/* shrink ram required for a bignum */
+int mp_shrink(mp_int *a);
+
+/* grow an int to a given size */
+int mp_grow(mp_int *a, int size);
+
+/* init to a given number of digits */
+int mp_init_size(mp_int *a, int size);
+
+/* ---> Basic Manipulations <--- */
+#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
+#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
+#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
+
+/* set to zero */
+void mp_zero(mp_int *a);
+
+/* set to a digit */
+void mp_set(mp_int *a, mp_digit b);
+
+/* set a 32-bit const */
+int mp_set_int(mp_int *a, unsigned long b);
+
+/* get a 32-bit value */
+unsigned long mp_get_int(mp_int * a);
+
+/* initialize and set a digit */
+int mp_init_set (mp_int * a, mp_digit b);
+
+/* initialize and set 32-bit value */
+int mp_init_set_int (mp_int * a, unsigned long b);
+
+/* copy, b = a */
+int mp_copy(mp_int *a, mp_int *b);
+
+/* inits and copies, a = b */
+int mp_init_copy(mp_int *a, mp_int *b);
+
+/* trim unused digits */
+void mp_clamp(mp_int *a);
+
+/* ---> digit manipulation <--- */
+
+/* right shift by "b" digits */
+void mp_rshd(mp_int *a, int b);
+
+/* left shift by "b" digits */
+int mp_lshd(mp_int *a, int b);
+
+/* c = a / 2**b */
+int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);
+
+/* b = a/2 */
+int mp_div_2(mp_int *a, mp_int *b);
+
+/* c = a * 2**b */
+int mp_mul_2d(mp_int *a, int b, mp_int *c);
+
+/* b = a*2 */
+int mp_mul_2(mp_int *a, mp_int *b);
+
+/* c = a mod 2**d */
+int mp_mod_2d(mp_int *a, int b, mp_int *c);
+
+/* computes a = 2**b */
+int mp_2expt(mp_int *a, int b);
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a);
+
+/* I Love Earth! */
+
+/* makes a pseudo-random int of a given size */
+int mp_rand(mp_int *a, int digits);
+
+/* ---> binary operations <--- */
+/* c = a XOR b  */
+int mp_xor(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a OR b */
+int mp_or(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a AND b */
+int mp_and(mp_int *a, mp_int *b, mp_int *c);
+
+/* ---> Basic arithmetic <--- */
+
+/* b = -a */
+int mp_neg(mp_int *a, mp_int *b);
+
+/* b = |a| */
+int mp_abs(mp_int *a, mp_int *b);
+
+/* compare a to b */
+int mp_cmp(mp_int *a, mp_int *b);
+
+/* compare |a| to |b| */
+int mp_cmp_mag(mp_int *a, mp_int *b);
+
+/* c = a + b */
+int mp_add(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a - b */
+int mp_sub(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a * b */
+int mp_mul(mp_int *a, mp_int *b, mp_int *c);
+
+/* b = a*a  */
+int mp_sqr(mp_int *a, mp_int *b);
+
+/* a/b => cb + d == a */
+int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* c = a mod b, 0 <= c < b  */
+int mp_mod(mp_int *a, mp_int *b, mp_int *c);
+
+/* ---> single digit functions <--- */
+
+/* compare against a single digit */
+int mp_cmp_d(mp_int *a, mp_digit b);
+
+/* c = a + b */
+int mp_add_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a - b */
+int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a * b */
+int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* a/b => cb + d == a */
+int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
+
+/* a/3 => 3c + d == a */
+int mp_div_3(mp_int *a, mp_int *c, mp_digit *d);
+
+/* c = a**b */
+int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a mod b, 0 <= c < b  */
+int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);
+
+/* ---> number theory <--- */
+
+/* d = a + b (mod c) */
+int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* d = a - b (mod c) */
+int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* d = a * b (mod c) */
+int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* c = a * a (mod b) */
+int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = 1/a (mod b) */
+int mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = (a, b) */
+int mp_gcd(mp_int *a, mp_int *b, mp_int *c);
+
+/* produces value such that U1*a + U2*b = U3 */
+int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);
+
+/* c = [a, b] or (a*b)/(a, b) */
+int mp_lcm(mp_int *a, mp_int *b, mp_int *c);
+
+/* finds one of the b'th root of a, such that |c|**b <= |a|
+ *
+ * returns error if a < 0 and b is even
+ */
+int mp_n_root(mp_int *a, mp_digit b, mp_int *c);
+
+/* special sqrt algo */
+int mp_sqrt(mp_int *arg, mp_int *ret);
+
+/* is number a square? */
+int mp_is_square(mp_int *arg, int *ret);
+
+/* computes the jacobi c = (a | n) (or Legendre if b is prime)  */
+int mp_jacobi(mp_int *a, mp_int *n, int *c);
+
+/* used to setup the Barrett reduction for a given modulus b */
+int mp_reduce_setup(mp_int *a, mp_int *b);
+
+/* Barrett Reduction, computes a (mod b) with a precomputed value c
+ *
+ * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely
+ * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
+ */
+int mp_reduce(mp_int *a, mp_int *b, mp_int *c);
+
+/* setups the montgomery reduction */
+int mp_montgomery_setup(mp_int *a, mp_digit *mp);
+
+/* computes a = B**n mod b without division or multiplication useful for
+ * normalizing numbers in a Montgomery system.
+ */
+int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);
+
+/* computes x/R == x (mod N) via Montgomery Reduction */
+int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+
+/* returns 1 if a is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a);
+
+/* sets the value of "d" required for mp_dr_reduce */
+void mp_dr_setup(mp_int *a, mp_digit *d);
+
+/* reduces a modulo b using the Diminished Radix method */
+int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);
+
+/* returns true if a can be reduced with mp_reduce_2k */
+int mp_reduce_is_2k(mp_int *a);
+
+/* determines k value for 2k reduction */
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d);
+
+/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);
+
+/* d = a**b (mod c) */
+int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* ---> Primes <--- */
+
+/* number of primes */
+#ifdef MP_8BIT
+   #define PRIME_SIZE      31
+#else
+   #define PRIME_SIZE      256
+#endif
+
+/* table of first PRIME_SIZE primes */
+extern const mp_digit __prime_tab[];
+
+/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
+int mp_prime_is_divisible(mp_int *a, int *result);
+
+/* performs one Fermat test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+int mp_prime_fermat(mp_int *a, mp_int *b, int *result);
+
+/* performs one Miller-Rabin test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);
+
+/* This gives [for a given bit size] the number of trials required
+ * such that Miller-Rabin gives a prob of failure lower than 2^-96
+ */
+int mp_prime_rabin_miller_trials(int size);
+
+/* performs t rounds of Miller-Rabin on "a" using the first
+ * t prime bases.  Also performs an initial sieve of trial
+ * division.  Determines if "a" is prime with probability
+ * of error no more than (1/4)**t.
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime(mp_int *a, int t, int *result);
+
+/* finds the next prime after the number "a" using "t" trials
+ * of Miller-Rabin.
+ *
+ * bbs_style = 1 means the prime must be congruent to 3 mod 4
+ */
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style);
+
+/* makes a truly random prime of a given size (bytes),
+ * call with bbs = 1 if you want it to be congruent to 3 mod 4
+ *
+ * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ * The prime generated will be larger than 2^(8*size).
+ */
+#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)
+
+/* makes a truly random prime of a given size (bits),
+ *
+ * Flags are as follows:
+ *
+ *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
+ *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
+ *   LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
+ *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
+ *
+ * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ */
+int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);
+
+/* ---> radix conversion <--- */
+int mp_count_bits(mp_int *a);
+
+int mp_unsigned_bin_size(mp_int *a);
+int mp_read_unsigned_bin(mp_int *a, unsigned char *b, int c);
+int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
+
+int mp_signed_bin_size(mp_int *a);
+int mp_read_signed_bin(mp_int *a, unsigned char *b, int c);
+int mp_to_signed_bin(mp_int *a, unsigned char *b);
+
+int mp_read_radix(mp_int *a, char *str, int radix);
+int mp_toradix(mp_int *a, char *str, int radix);
+int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen);
+int mp_radix_size(mp_int *a, int radix, int *size);
+
+int mp_fread(mp_int *a, int radix, FILE *stream);
+int mp_fwrite(mp_int *a, int radix, FILE *stream);
+
+#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
+#define mp_raw_size(mp)           mp_signed_bin_size(mp)
+#define mp_toraw(mp, str)         mp_to_signed_bin((mp), (str))
+#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
+#define mp_mag_size(mp)           mp_unsigned_bin_size(mp)
+#define mp_tomag(mp, str)         mp_to_unsigned_bin((mp), (str))
+
+#define mp_tobinary(M, S)  mp_toradix((M), (S), 2)
+#define mp_tooctal(M, S)   mp_toradix((M), (S), 8)
+#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
+#define mp_tohex(M, S)     mp_toradix((M), (S), 16)
+
+/* lowlevel functions, do not call! */
+int s_mp_add(mp_int *a, mp_int *b, mp_int *c);
+int s_mp_sub(mp_int *a, mp_int *b, mp_int *c);
+#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
+int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int fast_s_mp_sqr(mp_int *a, mp_int *b);
+int s_mp_sqr(mp_int *a, mp_int *b);
+int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c);
+int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c);
+int mp_karatsuba_sqr(mp_int *a, mp_int *b);
+int mp_toom_sqr(mp_int *a, mp_int *b);
+int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode);
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y);
+void bn_reverse(unsigned char *s, int len);
+
+extern const char *mp_s_rmap;
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif
+
============================================================
--- modes_test.c	5fb32a2a1cdc4311654b80d027a10dbdcf09fc4b
+++ modes_test.c	5fb32a2a1cdc4311654b80d027a10dbdcf09fc4b
@@ -0,0 +1,46 @@
+/* test CFB/OFB/CBC modes */
+#include "test.h"
+
+int modes_test(void)
+{
+   unsigned char pt[64], ct[64], tmp[64], key[16], iv[16];
+   int x, cipher_idx;
+   symmetric_CBC cbc;
+
+   /* make a random pt, key and iv */
+   yarrow_read(pt, 64,  &test_yarrow);
+   yarrow_read(key, 16, &test_yarrow);
+   yarrow_read(iv, 16,  &test_yarrow);
+
+/* test CBC mode */
+   cipher_idx = find_cipher("aes");
+   if (cipher_idx == -1) {
+      printf("test requires AES");
+      return 1;
+   }
+
+
+   /* encode the block */
+   DO(cbc_start(cipher_idx, iv, key, 16, 0, &cbc));
+   for (x = 0; x < 4; x++) {
+      DO(cbc_encrypt(pt+x*16, ct+x*16, &cbc));
+   }
+
+   /* decode the block */
+   DO(cbc_start(cipher_idx, iv, key, 16, 0, &cbc));
+   for (x = 0; x < 4; x++) {
+      DO(cbc_decrypt(ct+x*16, tmp+x*16, &cbc));
+   }
+   if (memcmp(tmp, pt, 64) != 0) {
+      printf("CBC failed");
+      return 1;
+   }
+
+/*
+   extern int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
+                     int keylen, int num_rounds, symmetric_CBC *cbc);
+extern int cbc_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_CBC *cbc);
+extern int cbc_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_CBC *cbc);
+*/
+
+}
============================================================
--- mpi_to_ltc_error.c	7d237900c806bdaf1b45494089d37020aa4051f9
+++ mpi_to_ltc_error.c	7d237900c806bdaf1b45494089d37020aa4051f9
@@ -0,0 +1,36 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef MPI
+static const struct {
+    int mpi_code, ltc_code;
+} mpi_to_ltc_codes[] = {
+   { MP_OKAY ,  CRYPT_OK},
+   { MP_MEM  ,  CRYPT_MEM},
+   { MP_VAL  ,  CRYPT_INVALID_ARG},
+};
+
+/* convert a MPI error to a LTC error (Possibly the most powerful function ever!  Oh wait... no) */
+int mpi_to_ltc_error(int err)
+{
+   int x;
+
+   for (x = 0; x < (int)(sizeof(mpi_to_ltc_codes)/sizeof(mpi_to_ltc_codes[0])); x++) {
+       if (err == mpi_to_ltc_codes[x].mpi_code) {
+          return mpi_to_ltc_codes[x].ltc_code;
+       }
+   }
+   return CRYPT_ERROR;
+}
+#endif
+
============================================================
--- ofb_getiv.c	78815a65ad0934db29c875cf19333887ad1d46e5
+++ ofb_getiv.c	78815a65ad0934db29c875cf19333887ad1d46e5
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef OFB
+
+int ofb_getiv(unsigned char *IV, unsigned long *len, symmetric_OFB *ofb)
+{
+   _ARGCHK(IV  != NULL);
+   _ARGCHK(len != NULL);
+   _ARGCHK(ofb != NULL);
+   if ((unsigned long)ofb->blocklen > *len) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+   memcpy(IV, ofb->IV, ofb->blocklen);
+   *len = ofb->blocklen;
+
+   return CRYPT_OK;
+}
+
+#endif
============================================================
--- ofb_setiv.c	45017eac234d24e2f2f6c766f36ec6d7ff72788a
+++ ofb_setiv.c	45017eac234d24e2f2f6c766f36ec6d7ff72788a
@@ -0,0 +1,38 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef OFB
+
+int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb)
+{
+   int err;
+
+   _ARGCHK(IV  != NULL);
+   _ARGCHK(ofb != NULL);
+
+   if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) {
+       return err;
+   }
+
+   if (len != (unsigned long)ofb->blocklen) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* force next block */
+   ofb->padlen = 0;
+   cipher_descriptor[ofb->cipher].ecb_encrypt(IV, ofb->IV, &ofb->key);
+   return CRYPT_OK;
+}
+
+#endif
+
============================================================
--- pkcs_1_v15_es_decode.c	21f620c947db684ab3bc11e051edc1d0176086f4
+++ pkcs_1_v15_es_decode.c	21f620c947db684ab3bc11e051edc1d0176086f4
@@ -0,0 +1,61 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+/* PKCS #1 v1.5 Encryption Padding -- Tom St Denis */
+
+#ifdef PKCS_1
+
+int pkcs_1_v15_es_decode(const unsigned char *msg,  unsigned long msglen,
+                               unsigned long modulus_bitlen,
+                               unsigned char *out,  unsigned long outlen,
+                               int           *res)
+{
+   unsigned long x, modulus_bytelen;
+
+   _ARGCHK(msg != NULL);
+   _ARGCHK(out != NULL);
+   _ARGCHK(res != NULL);
+
+   /* default to failed */
+   *res = 0;
+
+   /* must be at least 12 bytes long */
+   if (msglen < 12) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   modulus_bytelen = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+   /* should start with 0x00 0x02 */
+   if (msg[0] != 0x00 || msg[1] != 0x02) {
+      return CRYPT_OK;
+   }
+
+   /* skip over PS */
+   x = 2 + (modulus_bytelen - outlen - 3);
+
+   /* should be 0x00 */
+   if (msg[x++] != 0x00) {
+      return CRYPT_OK;
+   }
+
+   /* the message is left */
+   if (x + outlen > modulus_bytelen) {
+      return CRYPT_PK_INVALID_SIZE;
+   }
+   memcpy(out, msg + x, outlen);
+   *res = 1;
+   return CRYPT_OK;
+}
+
+#endif
+
============================================================
--- pkcs_1_v15_es_encode.c	fb6d3ddfe5810de3c92b46edb0f4c8a7b6de615b
+++ pkcs_1_v15_es_encode.c	fb6d3ddfe5810de3c92b46edb0f4c8a7b6de615b
@@ -0,0 +1,55 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+/* v1.5 Encryption Padding for PKCS #1 -- Tom St Denis */
+
+#ifdef PKCS_1
+
+int pkcs_1_v15_es_encode(const unsigned char *msg,    unsigned long msglen,
+                               unsigned long  modulus_bitlen,
+                               prng_state    *prng,   int           prng_idx,
+                               unsigned char *out,    unsigned long *outlen)
+{
+   unsigned long modulus_bytelen, x, y;
+
+   _ARGCHK(msg    != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* get modulus len */
+   modulus_bytelen = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+   if (modulus_bytelen < 12) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* verify length */
+   if (msglen > (modulus_bytelen - 11) || *outlen < modulus_bytelen) {
+      return CRYPT_PK_INVALID_SIZE;
+   }
+
+   /* 0x00 0x02 PS 0x00 M */
+   x = 0;
+   out[x++] = 0x00;
+   out[x++] = 0x02;
+   y = modulus_bytelen - msglen - 3;
+   if (prng_descriptor[prng_idx].read(out+x, y, prng) != y) {
+      return CRYPT_ERROR_READPRNG;
+   }
+   x += y;
+   out[x++] = 0x00;
+   memcpy(out+x, msg, msglen);
+   *outlen = modulus_bytelen;
+
+   return CRYPT_OK;
+}
+
+#endif /* PKCS_1 */
============================================================
--- pkcs_1_v15_sa_decode.c	4f6aeaa76927807827ad5a472b8e84d600f9f6cd
+++ pkcs_1_v15_sa_decode.c	4f6aeaa76927807827ad5a472b8e84d600f9f6cd
@@ -0,0 +1,77 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+/* PKCS #1 v1.5 Signature Padding -- Tom St Denis */
+
+#ifdef PKCS_1
+
+int pkcs_1_v15_sa_decode(const unsigned char *msghash, unsigned long msghashlen,
+                         const unsigned char *sig,     unsigned long siglen,
+                               int           hash_idx, unsigned long modulus_bitlen,
+                               int          *res)
+{
+   unsigned long x, y, modulus_bytelen, derlen;
+   int err;
+
+   _ARGCHK(msghash != NULL);
+   _ARGCHK(sig     != NULL);
+   _ARGCHK(res     != NULL);
+
+   /* default to invalid */
+   *res = 0;
+
+   /* valid hash ? */
+   if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* get derlen */
+   derlen = hash_descriptor[hash_idx].DERlen;
+
+   /* get modulus len */
+   modulus_bytelen = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+   /* valid sizes? */
+   if ((msghashlen + 3 + derlen > modulus_bytelen) || (siglen != modulus_bytelen)) {
+      return CRYPT_PK_INVALID_SIZE;
+   }
+
+   /* packet is 0x00 0x01 PS 0x00 T, where PS == 0xFF repeated modulus_bytelen - 3 - derlen - msghashlen times, T == DER || hash */
+   x = 0;
+   if (sig[x++] != 0x00 || sig[x++] != 0x01) {
+      return CRYPT_OK;
+   }
+
+   /* now follows (modulus_bytelen - 3 - derlen - msghashlen) 0xFF bytes */
+   for (y = 0; y < (modulus_bytelen - 3 - derlen - msghashlen); y++) {
+     if (sig[x++] != 0xFF) {
+        return CRYPT_OK;
+     }
+   }
+
+   if (sig[x++] != 0x00) {
+      return CRYPT_OK;
+   }
+
+   for (y = 0; y < derlen; y++) {
+      if (sig[x++] != hash_descriptor[hash_idx].DER[y]) {
+         return CRYPT_OK;
+      }
+   }
+
+   if (memcmp(msghash, sig+x, msghashlen) == 0) {
+      *res = 1;
+   }
+   return CRYPT_OK;
+}
+
+#endif
============================================================
--- pkcs_1_v15_sa_encode.c	0f05185ad6c209d813573788e5cf5057e9dbaf66
+++ pkcs_1_v15_sa_encode.c	0f05185ad6c209d813573788e5cf5057e9dbaf66
@@ -0,0 +1,71 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+#include "mycrypt.h"
+
+/* PKCS #1 v1.5 Signature Padding -- Tom St Denis */
+
+#ifdef PKCS_1
+
+int pkcs_1_v15_sa_encode(const unsigned char *msghash,  unsigned long msghashlen,
+                               int            hash_idx, unsigned long modulus_bitlen,
+                               unsigned char *out,      unsigned long *outlen)
+{
+  unsigned long derlen, modulus_bytelen, x, y;
+  int err;
+
+  _ARGCHK(msghash != NULL)
+  _ARGCHK(out     != NULL);
+  _ARGCHK(outlen  != NULL);
+
+  if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+     return err;
+  }
+
+  /* hack, to detect any hash without a DER OID */
+  if (hash_descriptor[hash_idx].DERlen == 0) {
+     return CRYPT_INVALID_ARG;
+  }
+
+  /* get modulus len */
+  modulus_bytelen = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+  /* get der len ok?  Forgive my lame German accent.... */
+  derlen = hash_descriptor[hash_idx].DERlen;
+
+  /* valid sizes? */
+  if (msghashlen + 3 + derlen > modulus_bytelen) {
+     return CRYPT_PK_INVALID_SIZE;
+  }
+
+  if (*outlen < modulus_bytelen) {
+     return CRYPT_BUFFER_OVERFLOW;
+  }
+
+  /* packet is 0x00 0x01 PS 0x00 T, where PS == 0xFF repeated modulus_bytelen - 3 - derlen - msghashlen times, T == DER || hash */
+  x = 0;
+  out[x++] = 0x00;
+  out[x++] = 0x01;
+  for (y = 0; y < (modulus_bytelen - 3 - derlen - msghashlen); y++) {
+     out[x++] = 0xFF;
+  }
+  out[x++] = 0x00;
+  for (y = 0; y < derlen; y++) {
+     out[x++] = hash_descriptor[hash_idx].DER[y];
+  }
+  for (y = 0; y < msghashlen; y++) {
+     out[x++] = msghash[y];
+  }
+
+  *outlen = modulus_bytelen;
+  return CRYPT_OK;
+}
+
+#endif /* PKCS_1 */
============================================================
--- rsa_decrypt_key.c	471c35e6305e3e3a7819d08525526b0019248723
+++ rsa_decrypt_key.c	471c35e6305e3e3a7819d08525526b0019248723
@@ -0,0 +1,61 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+/* decrypt then OAEP depad  */
+int rsa_decrypt_key(const unsigned char *in,     unsigned long inlen,
+                          unsigned char *outkey, unsigned long *keylen,
+                    const unsigned char *lparam, unsigned long lparamlen,
+                          prng_state    *prng,   int           prng_idx,
+                          int            hash_idx, int *res,
+                          rsa_key       *key)
+{
+  unsigned long modulus_bitlen, modulus_bytelen, x;
+  int           err;
+
+  _ARGCHK(outkey != NULL);
+  _ARGCHK(keylen != NULL);
+  _ARGCHK(key    != NULL);
+  _ARGCHK(res    != NULL);
+
+  /* valid hash ? */
+  if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+     return err;
+  }
+
+  /* get modulus len in bits */
+  modulus_bitlen = mp_count_bits(&(key->N));
+
+  /* outlen must be at least the size of the modulus */
+  modulus_bytelen = mp_unsigned_bin_size(&(key->N));
+  if (modulus_bytelen != inlen) {
+     return CRYPT_INVALID_PACKET;
+  }
+
+  /* rsa decode the packet */
+  x = *keylen;
+  if ((err = rsa_exptmod(in, inlen, outkey, &x, PK_PRIVATE, prng, prng_idx, key)) != CRYPT_OK) {
+     return err;
+  }
+
+  /* now OAEP decode the packet */
+  return pkcs_1_oaep_decode(outkey, x, lparam, lparamlen, modulus_bitlen, hash_idx,
+                            outkey, keylen, res);
+}
+
+#endif /* MRSA */
+
+
+
+
============================================================
--- rsa_encrypt_key.c	1ca9226d54ce36a9e700000145db98a22b3753d5
+++ rsa_encrypt_key.c	1ca9226d54ce36a9e700000145db98a22b3753d5
@@ -0,0 +1,59 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+/* OAEP pad then encrypt */
+int rsa_encrypt_key(const unsigned char *inkey,  unsigned long inlen,
+                          unsigned char *outkey, unsigned long *outlen,
+                    const unsigned char *lparam, unsigned long lparamlen,
+                    prng_state *prng, int prng_idx, int hash_idx, rsa_key *key)
+{
+  unsigned long modulus_bitlen, modulus_bytelen, x;
+  int           err;
+
+  _ARGCHK(inkey  != NULL);
+  _ARGCHK(outkey != NULL);
+  _ARGCHK(outlen != NULL);
+  _ARGCHK(key    != NULL);
+
+  /* valid prng and hash ? */
+  if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+     return err;
+  }
+  if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+     return err;
+  }
+
+  /* get modulus len in bits */
+  modulus_bitlen = mp_count_bits(&(key->N));
+
+  /* outlen must be at least the size of the modulus */
+  modulus_bytelen = mp_unsigned_bin_size(&(key->N));
+  if (modulus_bytelen > *outlen) {
+     return CRYPT_BUFFER_OVERFLOW;
+  }
+
+  /* OAEP pad the key */
+  x = *outlen;
+  if ((err = pkcs_1_oaep_encode(inkey, inlen, lparam,
+                                lparamlen, modulus_bitlen, prng, prng_idx, hash_idx,
+                                outkey, &x)) != CRYPT_OK) {
+     return err;
+  }
+
+  /* rsa exptmod the OAEP pad */
+  return rsa_exptmod(outkey, x, outkey, outlen, PK_PUBLIC, prng, prng_idx, key);
+}
+
+#endif /* MRSA */
============================================================
--- rsa_export.c	520f23951ac1fd1e28ab14a9283ef84abacc8baa
+++ rsa_export.c	520f23951ac1fd1e28ab14a9283ef84abacc8baa
@@ -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, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key)
+{
+   unsigned long y, z;
+   int err;
+
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(key    != NULL);
+
+   /* can we store the static header?  */
+   if (*outlen < (PACKET_SIZE + 1)) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* type valid? */
+   if (!(key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) &&
+        (type == PK_PRIVATE || type == PK_PRIVATE_OPTIMIZED)) {
+      return CRYPT_PK_INVALID_TYPE;
+   }
+
+   /* start at offset y=PACKET_SIZE */
+   y = PACKET_SIZE;
+
+   /* output key type */
+   out[y++] = type;
+
+   /* output modulus */
+   OUTPUT_BIGNUM(&key->N, out, y, z);
+
+   /* output public key */
+   OUTPUT_BIGNUM(&key->e, out, y, z);
+
+   if (type == PK_PRIVATE || type == PK_PRIVATE_OPTIMIZED) {
+      OUTPUT_BIGNUM(&key->d, out, y, z);
+   }
+
+   if (type == PK_PRIVATE_OPTIMIZED) {
+      OUTPUT_BIGNUM(&key->dQ, out, y, z);
+      OUTPUT_BIGNUM(&key->dP, out, y, z);
+      OUTPUT_BIGNUM(&key->pQ, out, y, z);
+      OUTPUT_BIGNUM(&key->qP, out, y, z);
+      OUTPUT_BIGNUM(&key->p, out, y, z);
+      OUTPUT_BIGNUM(&key->q, out, y, z);
+   }
+
+   /* store packet header */
+   packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_KEY);
+
+   /* copy to the user buffer */
+   *outlen = y;
+
+   /* clear stack and return */
+   return CRYPT_OK;
+}
+
+#endif /* MRSA */
+
============================================================
--- rsa_import.c	4a7e1456f13ac5313a999164c2f7e41022c3419b
+++ rsa_import.c	4a7e1456f13ac5313a999164c2f7e41022c3419b
@@ -0,0 +1,81 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+   unsigned long x, y;
+   int err;
+
+   _ARGCHK(in  != NULL);
+   _ARGCHK(key != NULL);
+
+   /* check length */
+   if (inlen < (1+PACKET_SIZE)) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* test packet header */
+   if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_KEY)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* init key */
+   if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP,
+                     &key->pQ, &key->p, &key->q, NULL)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+
+   /* get key type */
+   y = PACKET_SIZE;
+   key->type = (int)in[y++];
+
+   /* load the modulus  */
+   INPUT_BIGNUM(&key->N, in, x, y, inlen);
+
+   /* load public exponent */
+   INPUT_BIGNUM(&key->e, in, x, y, inlen);
+
+   /* get private exponent */
+   if (key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) {
+      INPUT_BIGNUM(&key->d, in, x, y, inlen);
+   }
+
+   /* get CRT private data if required */
+   if (key->type == PK_PRIVATE_OPTIMIZED) {
+      INPUT_BIGNUM(&key->dQ, in, x, y, inlen);
+      INPUT_BIGNUM(&key->dP, in, x, y, inlen);
+      INPUT_BIGNUM(&key->pQ, in, x, y, inlen);
+      INPUT_BIGNUM(&key->qP, in, x, y, inlen);
+      INPUT_BIGNUM(&key->p, in, x, y, inlen);
+      INPUT_BIGNUM(&key->q, in, x, y, inlen);
+   }
+
+   /* free up ram not required */
+   if (key->type != PK_PRIVATE_OPTIMIZED) {
+      mp_clear_multi(&key->dQ, &key->dP, &key->pQ, &key->qP, &key->p, &key->q, NULL);
+   }
+   if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) {
+      mp_clear(&key->d);
+   }
+
+   return CRYPT_OK;
+error:
+   mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,
+                  &key->pQ, &key->qP, &key->p, &key->q, NULL);
+   return err;
+}
+
+#endif /* MRSA */
+
============================================================
--- rsa_sign_hash.c	d3856ae248e093d7f73f48dee96911f2293cd4a5
+++ rsa_sign_hash.c	d3856ae248e093d7f73f48dee96911f2293cd4a5
@@ -0,0 +1,59 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+/* PSS pad then sign */
+int rsa_sign_hash(const unsigned char *msghash,  unsigned long  msghashlen,
+                        unsigned char *sig,      unsigned long *siglen,
+                        prng_state    *prng,     int            prng_idx,
+                        int            hash_idx, unsigned long  saltlen,
+                        rsa_key *key)
+{
+   unsigned long modulus_bitlen, modulus_bytelen, x;
+   int           err;
+
+  _ARGCHK(msghash  != NULL);
+  _ARGCHK(sig      != NULL);
+  _ARGCHK(siglen   != NULL);
+  _ARGCHK(key      != NULL);
+
+  /* valid prng and hash ? */
+  if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+     return err;
+  }
+  if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+     return err;
+  }
+
+  /* get modulus len in bits */
+  modulus_bitlen = mp_count_bits(&(key->N));
+
+  /* outlen must be at least the size of the modulus */
+  modulus_bytelen = mp_unsigned_bin_size(&(key->N));
+  if (modulus_bytelen > *siglen) {
+     return CRYPT_BUFFER_OVERFLOW;
+  }
+
+  /* PSS pad the key */
+  x = *siglen;
+  if ((err = pkcs_1_pss_encode(msghash, msghashlen, saltlen, prng, prng_idx,
+                               hash_idx, modulus_bitlen, sig, &x)) != CRYPT_OK) {
+     return err;
+  }
+
+  /* RSA encode it */
+  return rsa_exptmod(sig, x, sig, siglen, PK_PRIVATE, prng, prng_idx, key);
+}
+
+#endif /* MRSA */
============================================================
--- rsa_verify_hash.c	a1667bf6fa35453ae0b69bfec574ab3c39525935
+++ rsa_verify_hash.c	a1667bf6fa35453ae0b69bfec574ab3c39525935
@@ -0,0 +1,69 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+/* design then PSS depad */
+int rsa_verify_hash(const unsigned char *sig,      unsigned long siglen,
+                    const unsigned char *msghash,  unsigned long msghashlen,
+                          prng_state    *prng,     int           prng_idx,
+                          int            hash_idx, unsigned long saltlen,
+                          int           *stat,     rsa_key      *key)
+{
+   unsigned long modulus_bitlen, modulus_bytelen, x;
+   int           err;
+   unsigned char *tmpbuf;
+
+  _ARGCHK(msghash  != NULL);
+  _ARGCHK(sig      != NULL);
+  _ARGCHK(stat     != NULL);
+  _ARGCHK(key      != NULL);
+
+  /* valid hash ? */
+  if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+     return err;
+  }
+
+  if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+     return err;
+  }
+
+  /* get modulus len in bits */
+  modulus_bitlen = mp_count_bits(&(key->N));
+
+  /* outlen must be at least the size of the modulus */
+  modulus_bytelen = mp_unsigned_bin_size(&(key->N));
+  if (modulus_bytelen != siglen) {
+     return CRYPT_INVALID_PACKET;
+  }
+
+  /* allocate temp buffer for decoded sig */
+  tmpbuf = XCALLOC(1, modulus_bytelen + 1);
+  if (tmpbuf == NULL) {
+     return CRYPT_MEM;
+  }
+
+  /* RSA decode it  */
+  x = siglen;
+  if ((err = rsa_exptmod(sig, siglen, tmpbuf, &x, PK_PUBLIC, prng, prng_idx, key)) != CRYPT_OK) {
+     XFREE(tmpbuf);
+     return err;
+  }
+
+  /* PSS decode it */
+  err = pkcs_1_pss_decode(msghash, msghashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat);
+  XFREE(tmpbuf);
+  return err;
+}
+
+#endif /* MRSA */
============================================================
--- tim_exptmod.c	80dfac51cb0dd33e4d80702187313fc7d96d52d4
+++ tim_exptmod.c	80dfac51cb0dd33e4d80702187313fc7d96d52d4
@@ -0,0 +1,77 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+/* RSA Code by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef RSA_TIMING
+
+/* decrypts c into m */
+int tim_exptmod(prng_state *prng, int prng_idx,
+                mp_int *c, mp_int *e, mp_int *d, mp_int *n, mp_int *m)
+{
+   int           err;
+   mp_int        r, tmp, tmp2;
+   unsigned char *rtmp;
+   unsigned long rlen;
+
+   _ARGCHK(c != NULL);
+   _ARGCHK(e != NULL);
+   _ARGCHK(d != NULL);
+   _ARGCHK(n != NULL);
+   _ARGCHK(m != NULL);
+
+   if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* pick random r */
+   rtmp = XMALLOC(MAX_RSA_SIZE/8);
+   if (rtmp == NULL) {
+      return CRYPT_MEM;
+   }
+
+
+   rlen = mp_unsigned_bin_size(n);
+   if (prng_descriptor[prng_idx].read(rtmp, rlen, prng) != rlen) {
+      XFREE(rtmp);
+      return CRYPT_ERROR_READPRNG;
+   }
+
+   if ((err = mp_init_multi(&r, &tmp, &tmp2, NULL)) != MP_OKAY) {
+      XFREE(rtmp);
+      return mpi_to_ltc_error(err);
+   }
+
+   /* read in r */
+   if ((err = mp_read_unsigned_bin(&r, rtmp, rlen)) != MP_OKAY)              { goto __ERR; }
+
+   /* compute tmp = r^e */
+   if ((err = mp_exptmod(&r, e, n, &tmp)) != MP_OKAY)                        { goto __ERR; }
+
+   /* multiply C into the mix */
+   if ((err = mp_mulmod(c, &tmp, n, &tmp)) != MP_OKAY)                       { goto __ERR; }
+
+   /* raise to d */
+   if ((err = mp_exptmod(&tmp, d, n, &tmp)) != MP_OKAY)                      { goto __ERR; }
+
+   /* invert r and multiply */
+   if ((err = mp_invmod(&r, n, &tmp2)) != MP_OKAY)                           { goto __ERR; }
+
+   /* multiply and we are totally set */
+   if ((err = mp_mulmod(&tmp, &tmp2, n, m)) != MP_OKAY)                      { goto __ERR; }
+
+__ERR:  mp_clear_multi(&r, &tmp, &tmp2, NULL);
+   XFREE(rtmp);
+   return mpi_to_ltc_error(err);
+}
+
+#endif
============================================================
--- aes.c	decb06209890d202bdaa2b2095344580bb9d4b13
+++ aes.c	34c70069a1c05c3e8d6e42f1ef10495b271f425d
@@ -30,16 +30,20 @@

 #ifdef RIJNDAEL

+#ifndef ENCRYPT_ONLY
+
+#define SETUP    rijndael_setup
+#define ECB_ENC  rijndael_ecb_encrypt
+#define ECB_DEC  rijndael_ecb_decrypt
+#define ECB_TEST rijndael_test
+#define ECB_KS   rijndael_keysize
+
 const struct _cipher_descriptor rijndael_desc =
 {
     "rijndael",
     6,
     16, 32, 16, 10,
-    &rijndael_setup,
-    &rijndael_ecb_encrypt,
-    &rijndael_ecb_decrypt,
-    &rijndael_test,
-    &rijndael_keysize
+    SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_KS
 };

 const struct _cipher_descriptor aes_desc =
@@ -47,21 +51,63 @@ const struct _cipher_descriptor aes_desc
     "aes",
     6,
     16, 32, 16, 10,
-    &rijndael_setup,
-    &rijndael_ecb_encrypt,
-    &rijndael_ecb_decrypt,
-    &rijndael_test,
-    &rijndael_keysize
+    SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_KS
 };

+#else
+
+#define SETUP    rijndael_enc_setup
+#define ECB_ENC  rijndael_enc_ecb_encrypt
+#define ECB_KS   rijndael_enc_keysize
+
+const struct _cipher_descriptor rijndael_enc_desc =
+{
+    "rijndael",
+    6,
+    16, 32, 16, 10,
+    SETUP, ECB_ENC, NULL, NULL, ECB_KS
+};
+
+const struct _cipher_descriptor aes_enc_desc =
+{
+    "aes",
+    6,
+    16, 32, 16, 10,
+    SETUP, ECB_ENC, NULL, NULL, ECB_KS
+};
+
+#endif
+
 #include "aes_tab.c"

-int rijndael_setup(const unsigned char *key, int keylen, int rounds, symmetric_key *skey)
+static ulong32 setup_mix(ulong32 temp)
 {
+   return (Te4_3[byte(temp, 2)]) ^
+          (Te4_2[byte(temp, 1)]) ^
+          (Te4_1[byte(temp, 0)]) ^
+          (Te4_0[byte(temp, 3)]);
+}
+
+#ifndef ENCRYPT_ONLY
+
+static ulong32 setup_mix2(ulong32 temp)
+{
+   return Td0(255 & Te4[byte(temp, 3)]) ^
+          Td1(255 & Te4[byte(temp, 2)]) ^
+          Td2(255 & Te4[byte(temp, 1)]) ^
+          Td3(255 & Te4[byte(temp, 0)]);
+}
+
+#endif
+
+int SETUP(const unsigned char *key, int keylen, int rounds, symmetric_key *skey)
+{
     int i, j;
-    ulong32 temp, *rk, *rrk;
-
-    _ARGCHK(key != NULL);
+    ulong32 temp, *rk;
+#ifndef ENCRYPT_ONLY
+    ulong32 *rrk;
+#endif
+    _ARGCHK(key  != NULL);
     _ARGCHK(skey != NULL);

     if (keylen != 16 && keylen != 24 && keylen != 32) {
@@ -85,12 +131,7 @@ int rijndael_setup(const unsigned char *
         j = 44;
         for (;;) {
             temp  = rk[3];
-            rk[4] = rk[0] ^
-                (Te4_3[byte(temp, 2)]) ^
-                (Te4_2[byte(temp, 1)]) ^
-                (Te4_1[byte(temp, 0)]) ^
-                (Te4_0[byte(temp, 3)]) ^
-                rcon[i];
+            rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i];
             rk[5] = rk[1] ^ rk[4];
             rk[6] = rk[2] ^ rk[5];
             rk[7] = rk[3] ^ rk[6];
@@ -109,12 +150,7 @@ int rijndael_setup(const unsigned char *
         #else
             temp = rk[5];
         #endif
-            rk[ 6] = rk[ 0] ^
-                (Te4_3[byte(temp, 2)]) ^
-                (Te4_2[byte(temp, 1)]) ^
-                (Te4_1[byte(temp, 0)]) ^
-                (Te4_0[byte(temp, 3)]) ^
-                rcon[i];
+            rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
             rk[ 7] = rk[ 1] ^ rk[ 6];
             rk[ 8] = rk[ 2] ^ rk[ 7];
             rk[ 9] = rk[ 3] ^ rk[ 8];
@@ -137,12 +173,7 @@ int rijndael_setup(const unsigned char *
         #else
             temp = rk[7];
         #endif
-            rk[ 8] = rk[ 0] ^
-                (Te4_3[byte(temp, 2)]) ^
-                (Te4_2[byte(temp, 1)]) ^
-                (Te4_1[byte(temp, 0)]) ^
-                (Te4_0[byte(temp, 3)]) ^
-                rcon[i];
+            rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
             rk[ 9] = rk[ 1] ^ rk[ 8];
             rk[10] = rk[ 2] ^ rk[ 9];
             rk[11] = rk[ 3] ^ rk[10];
@@ -150,11 +181,7 @@ int rijndael_setup(const unsigned char *
                 break;
             }
             temp = rk[11];
-            rk[12] = rk[ 4] ^
-                (Te4_3[byte(temp, 3)]) ^
-                (Te4_2[byte(temp, 2)]) ^
-                (Te4_1[byte(temp, 1)]) ^
-                (Te4_0[byte(temp, 0)]);
+            rk[12] = rk[ 4] ^ setup_mix(ROR(temp, 8));
             rk[13] = rk[ 5] ^ rk[12];
             rk[14] = rk[ 6] ^ rk[13];
             rk[15] = rk[ 7] ^ rk[14];
@@ -164,7 +191,8 @@ int rijndael_setup(const unsigned char *
        /* this can't happen */
        j = 4;
     }
-
+
+#ifndef ENCRYPT_ONLY
     /* setup the inverse key now */
     rk   = skey->rijndael.dK;
     rrk  = skey->rijndael.eK + j - 4;
@@ -182,29 +210,13 @@ int rijndael_setup(const unsigned char *
         rk  += 4;
     #ifdef SMALL_CODE
         temp = rrk[0];
-        rk[0] =
-            Td0(255 & Te4[byte(temp, 3)]) ^
-            Td1(255 & Te4[byte(temp, 2)]) ^
-            Td2(255 & Te4[byte(temp, 1)]) ^
-            Td3(255 & Te4[byte(temp, 0)]);
+        rk[0] = setup_mix2(temp);
         temp = rrk[1];
-        rk[1] =
-            Td0(255 & Te4[byte(temp, 3)]) ^
-            Td1(255 & Te4[byte(temp, 2)]) ^
-            Td2(255 & Te4[byte(temp, 1)]) ^
-            Td3(255 & Te4[byte(temp, 0)]);
+        rk[1] = setup_mix2(temp);
         temp = rrk[2];
-        rk[2] =
-            Td0(255 & Te4[byte(temp, 3)]) ^
-            Td1(255 & Te4[byte(temp, 2)]) ^
-            Td2(255 & Te4[byte(temp, 1)]) ^
-            Td3(255 & Te4[byte(temp, 0)]);
+        rk[2] = setup_mix2(temp);
         temp = rrk[3];
-        rk[3] =
-            Td0(255 & Te4[byte(temp, 3)]) ^
-            Td1(255 & Te4[byte(temp, 2)]) ^
-            Td2(255 & Te4[byte(temp, 1)]) ^
-            Td3(255 & Te4[byte(temp, 0)]);
+        rk[3] = setup_mix2(temp);
      #else
         temp = rrk[0];
         rk[0] =
@@ -241,6 +253,7 @@ int rijndael_setup(const unsigned char *
     *rk++ = *rrk++;
     *rk++ = *rrk++;
     *rk   = *rrk;
+#endif /* ENCRYPT_ONLY */

     return CRYPT_OK;
 }
@@ -248,7 +261,7 @@ static void _rijndael_ecb_encrypt(const
 #ifdef CLEAN_STACK
 static void _rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
 #else
-void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
+void ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
 #endif
 {
     ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
@@ -270,6 +283,44 @@ void rijndael_ecb_encrypt(const unsigned
     LOAD32H(s2, pt  +  8); s2 ^= rk[2];
     LOAD32H(s3, pt  + 12); s3 ^= rk[3];

+
+#ifdef SMALL_CODE
+
+    for (r = 0; ; r++) {
+        rk += 4;
+        t0 =
+            Te0(byte(s0, 3)) ^
+            Te1(byte(s1, 2)) ^
+            Te2(byte(s2, 1)) ^
+            Te3(byte(s3, 0)) ^
+            rk[0];
+        t1 =
+            Te0(byte(s1, 3)) ^
+            Te1(byte(s2, 2)) ^
+            Te2(byte(s3, 1)) ^
+            Te3(byte(s0, 0)) ^
+            rk[1];
+        t2 =
+            Te0(byte(s2, 3)) ^
+            Te1(byte(s3, 2)) ^
+            Te2(byte(s0, 1)) ^
+            Te3(byte(s1, 0)) ^
+            rk[2];
+        t3 =
+            Te0(byte(s3, 3)) ^
+            Te1(byte(s0, 2)) ^
+            Te2(byte(s1, 1)) ^
+            Te3(byte(s2, 0)) ^
+            rk[3];
+        if (r == Nr-2) {
+           break;
+        }
+        s0 = t0; s1 = t1; s2 = t2; s3 = t3;
+    }
+    rk += 4;
+
+#else
+
     /*
      * Nr - 1 full rounds:
      */
@@ -330,52 +381,57 @@ void rijndael_ecb_encrypt(const unsigned
             Te3(byte(t2, 0)) ^
             rk[3];
     }
+
+#endif
+
     /*
      * apply last round and
      * map cipher state to byte array block:
      */
     s0 =
-        (Te4_3[(t0 >> 24)       ]) ^
-        (Te4_2[(t1 >> 16) & 0xff]) ^
-        (Te4_1[(t2 >>  8) & 0xff]) ^
-        (Te4_0[(t3      ) & 0xff]) ^
+        (Te4_3[byte(t0, 3)]) ^
+        (Te4_2[byte(t1, 2)]) ^
+        (Te4_1[byte(t2, 1)]) ^
+        (Te4_0[byte(t3, 0)]) ^
         rk[0];
     STORE32H(s0, ct);
     s1 =
-        (Te4_3[(t1 >> 24)       ]) ^
-        (Te4_2[(t2 >> 16) & 0xff]) ^
-        (Te4_1[(t3 >>  8) & 0xff]) ^
-        (Te4_0[(t0      ) & 0xff]) ^
+        (Te4_3[byte(t1, 3)]) ^
+        (Te4_2[byte(t2, 2)]) ^
+        (Te4_1[byte(t3, 1)]) ^
+        (Te4_0[byte(t0, 0)]) ^
         rk[1];
     STORE32H(s1, ct+4);
     s2 =
-        (Te4_3[(t2 >> 24)       ]) ^
-        (Te4_2[(t3 >> 16) & 0xff]) ^
-        (Te4_1[(t0 >>  8) & 0xff]) ^
-        (Te4_0[(t1      ) & 0xff]) ^
+        (Te4_3[byte(t2, 3)]) ^
+        (Te4_2[byte(t3, 2)]) ^
+        (Te4_1[byte(t0, 1)]) ^
+        (Te4_0[byte(t1, 0)]) ^
         rk[2];
     STORE32H(s2, ct+8);
     s3 =
-        (Te4_3[(t3 >> 24)       ]) ^
-        (Te4_2[(t0 >> 16) & 0xff]) ^
-        (Te4_1[(t1 >>  8) & 0xff]) ^
-        (Te4_0[(t2      ) & 0xff]) ^
+        (Te4_3[byte(t3, 3)]) ^
+        (Te4_2[byte(t0, 2)]) ^
+        (Te4_1[byte(t1, 1)]) ^
+        (Te4_0[byte(t2, 0)]) ^
         rk[3];
     STORE32H(s3, ct+12);
 }

 #ifdef CLEAN_STACK
-void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
+void ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
 {
    _rijndael_ecb_encrypt(pt, ct, skey);
    burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
 }
 #endif

+#ifndef ENCRYPT_ONLY
+
 #ifdef CLEAN_STACK
 static void _rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
 #else
-void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
+void ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
 #endif
 {
     ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
@@ -397,6 +453,42 @@ void rijndael_ecb_decrypt(const unsigned
     LOAD32H(s2, ct  +  8); s2 ^= rk[2];
     LOAD32H(s3, ct  + 12); s3 ^= rk[3];

+#ifdef SMALL_CODE
+    for (r = 0; ; r++) {
+        rk += 4;
+        t0 =
+            Td0(byte(s0, 3)) ^
+            Td1(byte(s3, 2)) ^
+            Td2(byte(s2, 1)) ^
+            Td3(byte(s1, 0)) ^
+            rk[0];
+        t1 =
+            Td0(byte(s1, 3)) ^
+            Td1(byte(s0, 2)) ^
+            Td2(byte(s3, 1)) ^
+            Td3(byte(s2, 0)) ^
+            rk[1];
+        t2 =
+            Td0(byte(s2, 3)) ^
+            Td1(byte(s1, 2)) ^
+            Td2(byte(s0, 1)) ^
+            Td3(byte(s3, 0)) ^
+            rk[2];
+        t3 =
+            Td0(byte(s3, 3)) ^
+            Td1(byte(s2, 2)) ^
+            Td2(byte(s1, 1)) ^
+            Td3(byte(s0, 0)) ^
+            rk[3];
+        if (r == Nr-2) {
+           break;
+        }
+        s0 = t0; s1 = t1; s2 = t2; s3 = t3;
+    }
+    rk += 4;
+
+#else
+
     /*
      * Nr - 1 full rounds:
      */
@@ -459,51 +551,52 @@ void rijndael_ecb_decrypt(const unsigned
             Td3(byte(t0, 0)) ^
             rk[3];
     }
+#endif

     /*
      * apply last round and
      * map cipher state to byte array block:
      */
     s0 =
-        (Td4[(t0 >> 24)       ] & 0xff000000) ^
-        (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
-        (Td4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
-        (Td4[(t1      ) & 0xff] & 0x000000ff) ^
+        (Td4[byte(t0, 3)] & 0xff000000) ^
+        (Td4[byte(t3, 2)] & 0x00ff0000) ^
+        (Td4[byte(t2, 1)] & 0x0000ff00) ^
+        (Td4[byte(t1, 0)] & 0x000000ff) ^
         rk[0];
     STORE32H(s0, pt);
     s1 =
-        (Td4[(t1 >> 24)       ] & 0xff000000) ^
-        (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
-        (Td4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
-        (Td4[(t2      ) & 0xff] & 0x000000ff) ^
+        (Td4[byte(t1, 3)] & 0xff000000) ^
+        (Td4[byte(t0, 2)] & 0x00ff0000) ^
+        (Td4[byte(t3, 1)] & 0x0000ff00) ^
+        (Td4[byte(t2, 0)] & 0x000000ff) ^
         rk[1];
     STORE32H(s1, pt+4);
     s2 =
-        (Td4[(t2 >> 24)       ] & 0xff000000) ^
-        (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
-        (Td4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
-        (Td4[(t3      ) & 0xff] & 0x000000ff) ^
+        (Td4[byte(t2, 3)] & 0xff000000) ^
+        (Td4[byte(t1, 2)] & 0x00ff0000) ^
+        (Td4[byte(t0, 1)] & 0x0000ff00) ^
+        (Td4[byte(t3, 0)] & 0x000000ff) ^
         rk[2];
     STORE32H(s2, pt+8);
     s3 =
-        (Td4[(t3 >> 24)       ] & 0xff000000) ^
-        (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
-        (Td4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
-        (Td4[(t0      ) & 0xff] & 0x000000ff) ^
+        (Td4[byte(t3, 3)] & 0xff000000) ^
+        (Td4[byte(t2, 2)] & 0x00ff0000) ^
+        (Td4[byte(t1, 1)] & 0x0000ff00) ^
+        (Td4[byte(t0, 0)] & 0x000000ff) ^
         rk[3];
     STORE32H(s3, pt+12);
 }


 #ifdef CLEAN_STACK
-void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
+void ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
 {
    _rijndael_ecb_decrypt(ct, pt, skey);
    burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
 }
 #endif

-int rijndael_test(void)
+int ECB_TEST(void)
 {
  #ifndef LTC_TEST
     return CRYPT_NOP;
@@ -584,7 +677,9 @@ int rijndael_test(void)
  #endif
 }

-int rijndael_keysize(int *desired_keysize)
+#endif /* ENCRYPT_ONLY */
+
+int ECB_KS(int *desired_keysize)
 {
    _ARGCHK(desired_keysize != NULL);

============================================================
--- aes_tab.c	026d6575ce571ca3ca33e828c9c7c75dc787c696
+++ aes_tab.c	8d84d7ccee23e01c4a8f876735478b5a44d4bd42
@@ -157,6 +157,8 @@ static const ulong32 Te4[256] = {
     0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL,
 };

+#ifndef ENCRYPT_ONLY
+
 static const ulong32 TD0[256] = {
     0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL,
     0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL,
@@ -291,6 +293,8 @@ static const ulong32 Td4[256] = {
     0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL,
 };

+#endif /* ENCRYPT_ONLY */
+
 #ifdef SMALL_CODE

 #define Te0(x) TE0[x]
@@ -660,6 +664,8 @@ 0x41000000UL, 0x99000000UL, 0x2d000000UL
 0x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL
 };

+#ifndef ENCRYPT_ONLY
+
 static const ulong32 TD1[256] = {
     0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL,
     0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL,
@@ -999,6 +1005,8 @@ 0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL
 0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL
 };

+#endif /* ENCRYPT_ONLY */
+
 #endif /* SMALL CODE */

 static const ulong32 rcon[] = {
============================================================
--- cbc_decrypt.c	f6a28de38f7e35337bc38c2f5a81e60cdc104a05
+++ cbc_decrypt.c	290fb8f65b1037f8479d118dd94340458eeaed8d
@@ -25,14 +25,15 @@ int cbc_decrypt(const unsigned char *ct,
    if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
        return err;
    }
-   cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key);
-
+   _ARGCHK(cipher_descriptor[cbc->cipher].ecb_decrypt != NULL);
+
    /* is blocklen valid? */
    if (cbc->blocklen < 0 || cbc->blocklen > (int)sizeof(cbc->IV)) {
       return CRYPT_INVALID_ARG;
    }

-   /* xor IV against the plaintext of the previous step */
+   /* decrypt and xor IV against the plaintext of the previous step */
+   cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key);
    for (x = 0; x < cbc->blocklen; x++) {
        /* copy CT in case ct == pt */
        tmp2[x] = ct[x];
============================================================
--- changes	1dfeb3f2aedcb7f984297fb7d4a7afdbff1cb674
+++ changes	b68f47aa1ca092c730b59b38f794c822f473902e
@@ -1,3 +1,28 @@
+May 30th, 2004
+v0.96  -- Removed GF and Keyring code
+       -- Extended OAEP decoder to distinguish better [and use a more uniform API]
+       -- Changed PSS/OAEP API slightly to be more consistent with other PK functions (order of arguments)
+       -- rsa_exptmod() now pads with leading zeroes as per I2OSP.
+       -- added error checking to yarrow code
+       -- Mike Frysinger pointed out that tommath.h from this distro will overwrite tommath.h
+          from libtommath.  I changed this to ltc_tommath.h to avoid any such problems.
+       -- Fixed bug in PSS encoder/decoder that didn't handle the MSB properly
+       -- refactored AES, now sports an "encrypt only" descriptor which uses half as much code space.
+       -- modded Yarrow to try and use refactored AES code and added WHIRLPOOL support (d'oh) ;-)
+       -- updated ECB, OCB and CBC decrypt functions to detect when "encrypt only" descriptor is used.
+       -- replaced old RSA code with new code that uses PKCS #1 v2.0 padding
+       -- replaced old test harness with new over-engineer'ed one in /demos/test/
+       -- updated cbc/cfb/ofb/ctr code with setiv/getiv functions to change/read the IV without re-keying.
+       -- Added PKCS #1 v1.5 RSA encryption and signature padding routines
+       -- Added DER OID's to most hash descriptors (as many as I could find)
+       -- modded rsa_exptmod() to use timing-resilient tim_exptmod() when doing private key operations
+          added #define RSA_TIMING which can turn on/off this feature.
+       -- No more config.pl so please just read mycrypt_custom.h for build-time tweaks
+       -- Small update to rand_prime()
+       -- Updated sha1, md5 and sha256 so they are smaller when SMALL_CODE is defined.  If you want speed though,
+          you're going to have to undefine SMALL_CODE ;-)
+       -- Worked over AES so that it's even smaller now [in both modes].
+
 May 12th, 2004
 v0.95  -- Optimized AES and WHIRLPOOL for SMALL_CODE by taking advantage of the fact
           the transforms are circulant.  AES dropped 5KB and WHIRLPOOL dropped 13KB
============================================================
--- crypt.c	c1c89e3e4d520f3674362686f4b2eb652350c71f
+++ crypt.c	14fd6a0ac48eea8e092891cc828a900b55682689
@@ -120,6 +120,9 @@ const char *crypt_build_settings =
 #if defined(RIPEMD160)
    "   RIPEMD160\n"
 #endif
+#if defined(WHIRLPOOL)
+   "   WHIRLPOOL\n"
+#endif

     "\nBlock Chaining Modes:\n"
 #if defined(CFB)
@@ -151,8 +154,12 @@ const char *crypt_build_settings =

     "\nPK Algs:\n"
 #if defined(MRSA)
-    "   RSA\n"
+    "   RSA"
+#if defined(RSA_TIMING)
+    " + RSA_TIMING "
 #endif
+    "\n"
+#endif
 #if defined(MDH)
     "   DH\n"
 #endif
@@ -162,9 +169,6 @@ const char *crypt_build_settings =
 #if defined(MDSA)
     "   DSA\n"
 #endif
-#if defined(KR)
-    "   KR\n"
-#endif

     "\nCompiler:\n"
 #if defined(WIN32)
@@ -187,9 +191,6 @@ const char *crypt_build_settings =
 #endif

     "\nVarious others: "
-#if defined(GF)
-    " GF "
-#endif
 #if defined(BASE64)
     " BASE64 "
 #endif
@@ -223,6 +224,15 @@ const char *crypt_build_settings =
 #if defined(PKCS_5)
     " PKCS#5 "
 #endif
+#if defined(SMALL_CODE)
+    " SMALL_CODE "
+#endif
+#if defined(NO_FILE)
+    " NO_FILE "
+#endif
+#if defined(LTC_TEST)
+    " LTC_TEST "
+#endif
     "\n"
     "\n\n\n"
     ;
============================================================
--- crypt.tex	8e63225b182ba100c6698dcea5381fb0debcb46e
+++ crypt.tex	f230cd06ff9351b7e4a36fa9a6932a55cedc295f
@@ -47,7 +47,7 @@
 \def\gap{\vspace{0.5ex}}
 \makeindex
 \begin{document}
-\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.95}
+\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.96}
 \author{Tom St Denis \\
 \\
 tomstdenis@iahu.ca \\
@@ -103,7 +103,8 @@ \subsection{What the library IS for?}

 The library also serves well as a toolkit for applications where they don't need to be OpenPGP, PKCS, etc. compliant.
 Included are fully operational public key routines for encryption, decryption, signature generation and verification.
-These routines are fully portable but are not conformant to any known set of standards.  They are all based on established
+These routines are fully portable but are not conformant to any known set of standards\footnote{With the exception of
+the RSA code which is based on the PKCS \#1 standards.}.  They are all based on established
 number theory and cryptography.

 \subsection{What the library IS NOT for?}
@@ -241,19 +242,20 @@ \section{Introduction}
 if it failed.  Certain functions that return int will return $-1$ to indicate an error.  These functions will be explicitly
 commented upon.  When a function does return a CRYPT error code it can be translated into a string with

+\index{error\_to\_string()}
 \begin{verbatim}
-const char *error_to_string(int errno);
+const char *error_to_string(int err);
 \end{verbatim}

 An example of handling an error is:
 \begin{verbatim}
 void somefunc(void)
 {
-   int errno;
+   int err;

    /* call a cryptographic function */
-   if ((errno = some_crypto_function(...)) != CRYPT_OK) {
-      printf("A crypto error occured, %s\n", error_to_string(errno));
+   if ((err = some_crypto_function(...)) != CRYPT_OK) {
+      printf("A crypto error occured, %s\n", error_to_string(err));
       /* perform error handling */
    }
    /* continue on if no error occured */
@@ -320,14 +322,14 @@ \section{Functions with Variable Length
     rsa_key key;
     unsigned char buffer[1024];
     unsigned long x;
-    int errno;
+    int err;

     /* ... Make up the RSA key somehow */

     /* lets export the key, set x to the size of the output buffer */
     x = sizeof(buffer);
-    if ((errno = rsa_export(buffer, &x, PK_PUBLIC, &key)) != CRYPT_OK) {
-       printf("Export error: %s\n", error_to_string(errno));
+    if ((err = rsa_export(buffer, &x, PK_PUBLIC, &key)) != CRYPT_OK) {
+       printf("Export error: %s\n", error_to_string(err));
        return -1;
     }

@@ -411,12 +413,12 @@ \section{Core Functions}
 #include <mycrypt.h>
 int main(void)
 {
-   int keysize, errno;
+   int keysize, err;

    /* now given a 20 byte key what keysize does Twofish want to use? */
    keysize = 20;
-   if ((errno = twofish_keysize(&keysize)) != CRYPT_OK) {
-      printf("Error getting key size: %s\n", error_to_string(errno));
+   if ((err = twofish_keysize(&keysize)) != CRYPT_OK) {
+      printf("Error getting key size: %s\n", error_to_string(err));
       return -1;
    }
    printf("Twofish suggested a key size of %d\n", keysize);
@@ -434,22 +436,30 @@ \section{Core Functions}
 {
    unsigned char pt[8], ct[8], key[8];
    symmetric_key skey;
-   int errno;
+   int err;

    /* ... key is loaded appropriately in ``key'' ... */
    /* ... load a block of plaintext in ``pt'' ... */

    /* schedule the key */
-   if ((errno = blowfish_setup(key, 8, 0, &skey)) != CRYPT_OK) {
-      printf("Setup error: %s\n", error_to_string(errno));
+   if ((err = blowfish_setup(key,     /* the key we will use */
+                               8,     /* key is 8 bytes (64-bits) long */
+                               0,     /* 0 == use default # of rounds */
+                           &skey)     /* where to put the scheduled key */
+       ) != CRYPT_OK) {
+      printf("Setup error: %s\n", error_to_string(err));
       return -1;
    }

    /* encrypt the block */
-   blowfish_ecb_encrypt(pt, ct, &skey);
+   blowfish_ecb_encrypt(pt,             /* encrypt this 8-byte array */
+                        ct,             /* store encrypted data here */
+                        &skey);         /* our previously scheduled key */

    /* decrypt the block */
-   blowfish_ecb_decrypt(ct, pt, &skey);
+   blowfish_ecb_decrypt(ct,             /* decrypt this 8-byte array */
+                        pt,             /* store decrypted data here */
+                        &skey);         /* our previously scheduled key */

    return 0;
 }
@@ -501,6 +511,7 @@ \section{The Cipher Descriptors}

 As of this release the current cipher\_descriptors elements are

+\index{Cipher descriptor table}
 \begin{small}
 \begin{center}
 \begin{tabular}{|c|c|c|c|c|c|}
@@ -516,6 +527,7 @@ \section{The Cipher Descriptors}
      \hline Safer K128  & safer\_k128\_desc & 8 & 16 & 6 $\ldots$ 13 \\
      \hline Safer SK128 & safer\_sk128\_desc & 8 & 16 & 6 $\ldots$ 13 \\
      \hline AES & aes\_desc & 16 & 16, 24, 32 & 10, 12, 14 \\
+                & aes\_enc\_desc & 16 & 16, 24, 32 & 10, 12, 14 \\
      \hline Twofish & twofish\_desc & 16 & 16, 24, 32 & 16 \\
      \hline DES & des\_desc & 8 & 7 & 16 \\
      \hline 3DES (EDE mode) & des3\_desc & 8 & 21 & 16 \\
@@ -528,14 +540,32 @@ \subsection{Notes}
 \end{small}

 \subsection{Notes}
+\begin{small}
+\begin{enumerate}
+\item
+For AES (also known as Rijndael) there are four descriptors which complicate issues a little.  The descriptors
+rijndael\_desc and rijndael\_enc\_desc provide the cipher named ``rijndael''.  The descriptors aes\_desc and
+aes\_enc\_desc provide the cipher name ``aes''.  Functionally both ``rijndael'' and ``aes'' are the same cipher.  The
+only difference is when you call find\_cipher() you have to pass the correct name.  The cipher descriptors with ``enc''
+in the middle (e.g. rijndael\_enc\_desc) are related to an implementation of Rijndael with only the encryption routine
+and tables.  The decryption and self--test function pointers of both ``encrypt only'' descriptors are set to \textbf{NULL} and
+should not be called.
+
+The ``encrypt only'' descriptors are useful for applications that only use the encryption function of the cipher.  Algorithms such
+as EAX, PMAC and OMAC only require the encryption function.  So far this ``encrypt only'' functionality has only been implemented for
+Rijndael as it makes the most sense for this cipher.
+
+\item
 For the 64-bit SAFER famliy of ciphers (e.g K64, SK64, K128, SK128) the ecb\_encrypt() and ecb\_decrypt()
 functions are the same.  So if you want to use those functions directly just call safer\_ecb\_encrypt()
 or safer\_ecb\_decrypt() respectively.

+\item
 Note that for ``DES'' and ``3DES'' they use 8 and 24 byte keys but only 7 and 21 [respectively] bytes of the keys are in
 fact used for the purposes of encryption.  My suggestion is just to use random 8/24 byte keys instead of trying to make a 8/24
 byte string from the real 7/21 byte key.

+\item
 Note that ``Twofish'' has additional configuration options that take place at build time.  These options are found in
 the file ``mycrypt\_cfg.h''.  The first option is ``TWOFISH\_SMALL'' which when defined will force the Twofish code
 to not pre-compute the Twofish ``$g(X)$'' function as a set of four $8 \times 32$ s-boxes.  This means that a scheduled
@@ -545,6 +575,7 @@ \subsection{Notes}
 speed increase is useful when ``TWOFISH\_SMALL'' is defined since the s-boxes and MDS multiply form the heart of the
 Twofish round function.

+\index{Twofish build options}
 \begin{small}
 \begin{center}
 \begin{tabular}{|l|l|l|}
@@ -558,7 +589,11 @@ \subsection{Notes}
 \end{center}
 \end{small}

+\end{enumerate}
+\end{small}
+
 To work with the cipher\_descriptor array there is a function:
+\index{find\_cipher()}
 \begin{verbatim}
 int find_cipher(char *name)
 \end{verbatim}
@@ -571,7 +606,7 @@ \subsection{Notes}
 {
    unsigned char key[8];
    symmetric_key skey;
-   int errno;
+   int err;

    /* you must register a cipher before you use it */
    if (register_cipher(&blowfish_desc)) == -1) {
@@ -580,8 +615,8 @@ \subsection{Notes}
    }

    /* generic call to function (assuming the key in key[] was already setup) */
-   if ((errno = cipher_descriptor[find_cipher("blowfish")].setup(key, 8, 0, &skey)) != CRYPT_OK) {
-      printf("Error setting up Blowfish: %s\n", error_to_string(errno));
+   if ((err = cipher_descriptor[find