changeset 144:7ed585a2c53b libtomcrypt

propagate of 3f8f752126017cbe7d93c4086c27a91550df745f and 747ebf284d40a15b338e5a5c7730ecec6eade3d7 from branch 'au.asn.ucc.matt.ltc-orig' to 'au.asn.ucc.matt.ltc-db'
author Matt Johnston <matt@ucc.asn.au>
date Sun, 19 Dec 2004 11:47:33 +0000
parents 5d99163f7e32 (current diff) b1edc9158f6c (diff)
children c2b93763dac9
files Makefile.in crypt.c crypt_cipher_descriptor.c crypt_hash_descriptor.c crypt_prng_descriptor.c demos/test.c doc/crypt.pdf examples/ch1-01.c examples/ch1-02.c examples/ch1-03.c examples/ch2-01.c makefile makefile.msvc modes_test.c mycrypt.h mycrypt_argchk.h mycrypt_custom.h mycrypt_kr.h mycrypt_macros.h mycrypt_misc.h sha224.c sha256.c sha384.c sha512.c tiger.c whirl.c yarrow.c
diffstat 18 files changed, 3597 insertions(+), 364 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile.in	Sun Dec 19 11:47:33 2004 +0000
@@ -0,0 +1,253 @@
+# MAKEFILE for linux GCC
+#
+# Tom St Denis
+# Modified by Clay Culver
+
+# The version
+VERSION=0.99
+
+# Compiler and Linker Names
+#CC=gcc
+#LD=ld
+
+# Archiver [makes .a files]
+#AR=ar
+#ARFLAGS=r
+
+# Compilation flags. Note the += does not write over the user's CFLAGS!
+# The rest of the flags come from the parent Dropbear makefile
+CFLAGS += -c -I$(srcdir)
+# -Werror
+
+# optimize for SPEED
+#CFLAGS += -O3 -funroll-all-loops
+
+#add -fomit-frame-pointer.  hinders debugging!
+#CFLAGS += -fomit-frame-pointer
+
+# optimize for SIZE
+#CFLAGS += -Os -DSMALL_CODE
+
+# compile for DEBUGING (required for ccmalloc checking!!!)
+#CFLAGS += -g3
+
+#These flags control how the library gets built.
+
+#Output filenames for various targets.
+LIBNAME=libtomcrypt.a
+HASH=hashsum
+CRYPT=encrypt
+SMALL=small
+PROF=x86_prof
+TV=tv_gen
+
+#LIBPATH-The directory for libtomcrypt to be installed to.
+#INCPATH-The directory to install the header files for libtomcrypt.
+#DATAPATH-The directory to install the pdf docs.
+DESTDIR=
+LIBPATH=/usr/lib
+INCPATH=/usr/include
+DATAPATH=/usr/share/doc/libtomcrypt/pdf
+
+#List of objects to compile.
+
+#Leave MPI built-in or force developer to link against libtommath?
+#MPIOBJECT=mpi.o
+#Dropbear uses libtommath
+MPIOBJECT=
+
+OBJECTS=error_to_string.o mpi_to_ltc_error.o base64_encode.o base64_decode.o \
+\
+crypt.o                    crypt_find_cipher.o      crypt_find_hash_any.o      \
+crypt_hash_is_valid.o      crypt_register_hash.o    crypt_unregister_prng.o    \
+crypt_argchk.o             crypt_find_cipher_any.o  crypt_find_hash_id.o       \
+crypt_prng_descriptor.o    crypt_register_prng.o    crypt_cipher_descriptor.o  \
+crypt_find_cipher_id.o     crypt_find_prng.o        crypt_prng_is_valid.o      \
+crypt_unregister_cipher.o  crypt_cipher_is_valid.o  crypt_find_hash.o          \
+crypt_hash_descriptor.o    crypt_register_cipher.o  crypt_unregister_hash.o    \
+\
+sober128.o fortuna.o sprng.o yarrow.o rc4.o rng_get_bytes.o  rng_make_prng.o \
+\
+rand_prime.o is_prime.o \
+\
+ecc.o  dh.o \
+\
+rsa_decrypt_key.o  rsa_encrypt_key.o  rsa_exptmod.o  rsa_free.o  rsa_make_key.o  \
+rsa_sign_hash.o  rsa_verify_hash.o rsa_export.o rsa_import.o tim_exptmod.o \
+rsa_v15_encrypt_key.o rsa_v15_decrypt_key.o rsa_v15_sign_hash.o rsa_v15_verify_hash.o \
+\
+dsa_export.o  dsa_free.o  dsa_import.o  dsa_make_key.o  dsa_sign_hash.o  \
+dsa_verify_hash.o  dsa_verify_key.o \
+\
+aes.o aes_enc.o \
+\
+blowfish.o des.o safer_tab.o safer.o saferp.o rc2.o xtea.o \
+rc6.o rc5.o cast5.o noekeon.o twofish.o skipjack.o \
+\
+md2.o md4.o md5.o sha1.o sha256.o sha512.o tiger.o whirl.o \
+rmd128.o rmd160.o chc.o \
+\
+packet_store_header.o  packet_valid_header.o \
+\
+eax_addheader.o  eax_decrypt.o  eax_decrypt_verify_memory.o  eax_done.o  eax_encrypt.o  \
+eax_encrypt_authenticate_memory.o  eax_init.o  eax_test.o \
+\
+ocb_decrypt.o  ocb_decrypt_verify_memory.o  ocb_done_decrypt.o  ocb_done_encrypt.o  \
+ocb_encrypt.o  ocb_encrypt_authenticate_memory.o  ocb_init.o  ocb_ntz.o  \
+ocb_shift_xor.o  ocb_test.o s_ocb_done.o \
+\
+omac_done.o  omac_file.o  omac_init.o  omac_memory.o  omac_process.o  omac_test.o \
+\
+pmac_done.o  pmac_file.o  pmac_init.o  pmac_memory.o  pmac_ntz.o  pmac_process.o  \
+pmac_shift_xor.o  pmac_test.o \
+\
+cbc_start.o cbc_encrypt.o cbc_decrypt.o cbc_getiv.o cbc_setiv.o \
+cfb_start.o cfb_encrypt.o cfb_decrypt.o cfb_getiv.o cfb_setiv.o \
+ofb_start.o ofb_encrypt.o ofb_decrypt.o ofb_getiv.o ofb_setiv.o \
+ctr_start.o ctr_encrypt.o ctr_decrypt.o ctr_getiv.o ctr_setiv.o \
+ecb_start.o ecb_encrypt.o ecb_decrypt.o \
+\
+hash_file.o  hash_filehandle.o  hash_memory.o \
+\
+hmac_done.o  hmac_file.o  hmac_init.o  hmac_memory.o  hmac_process.o  hmac_test.o \
+\
+pkcs_1_mgf1.o pkcs_1_oaep_encode.o pkcs_1_oaep_decode.o  \
+pkcs_1_pss_encode.o pkcs_1_pss_decode.o pkcs_1_i2osp.o pkcs_1_os2ip.o \
+pkcs_1_v15_es_encode.o pkcs_1_v15_es_decode.o pkcs_1_v15_sa_encode.o pkcs_1_v15_sa_decode.o \
+\
+pkcs_5_1.o pkcs_5_2.o \
+\
+der_encode_integer.o der_decode_integer.o der_length_integer.o \
+der_put_multi_integer.o der_get_multi_integer.o \
+\
+burn_stack.o zeromem.o \
+\
+$(MPIOBJECT)
+
+TESTOBJECTS=demos/test.o
+HASHOBJECTS=demos/hashsum.o
+CRYPTOBJECTS=demos/encrypt.o
+SMALLOBJECTS=demos/small.o
+PROFS=demos/x86_prof.o
+TVS=demos/tv_gen.o
+
+#Files left over from making the crypt.pdf.
+LEFTOVERS=*.dvi *.log *.aux *.toc *.idx *.ilg *.ind *.out
+
+#Compressed filenames
+COMPRESSED=crypt-$(VERSION).tar.bz2 crypt-$(VERSION).zip
+
+#Header files used by libtomcrypt.
+HEADERS=ltc_tommath.h mycrypt_cfg.h \
+mycrypt_misc.h  mycrypt_prng.h mycrypt_cipher.h  mycrypt_hash.h \
+mycrypt_macros.h  mycrypt_pk.h mycrypt.h mycrypt_argchk.h \
+mycrypt_custom.h mycrypt_pkcs.h
+
+#The default rule for make builds the libtomcrypt library.
+default:library
+
+#ciphers come in two flavours... enc+dec and enc 
+aes_enc.o: aes.c aes_tab.c
+	$(CC) $(CFLAGS) -DENCRYPT_ONLY -c $(srcdir)/aes.c -o aes_enc.o
+
+#These are the rules to make certain object files.
+aes.o: aes.c aes_tab.c
+twofish.o: twofish.c twofish_tab.c
+whirl.o: whirl.c whirltab.c
+ecc.o: ecc.c ecc_sys.c
+dh.o: dh.c dh_sys.c
+sha512.o: sha512.c sha384.c
+sha256.o: sha256.c sha224.c
+
+#This rule makes the libtomcrypt library.
+library: $(LIBNAME)
+
+$(LIBNAME): $(OBJECTS)
+	$(AR) $(ARFLAGS) $@ $(OBJECTS) 
+	$(RANLIB) $@
+
+#This rule makes the hash program included with libtomcrypt
+hashsum: library $(HASHOBJECTS)
+	$(CC) $(HASHOBJECTS) $(LIBNAME) -o $(HASH) $(WARN)
+
+#makes the crypt program
+crypt: library $(CRYPTOBJECTS)
+	$(CC) $(CRYPTOBJECTS) $(LIBNAME) -o $(CRYPT) $(WARN)
+
+#makes the small program
+small: library $(SMALLOBJECTS)
+	$(CC) $(SMALLOBJECTS) $(LIBNAME) -o $(SMALL) $(WARN)
+	
+x86_prof: library $(PROFS)
+	$(CC) $(PROFS) $(LIBNAME) $(EXTRALIBS) -o $(PROF)
+
+tv_gen: library $(TVS)
+	$(CC) $(TVS) $(LIBNAME) $(EXTRALIBS) -o $(TV)
+
+#This rule installs the library and the header files. This must be run
+#as root in order to have a high enough permission to write to the correct
+#directories and to set the owner and group to root.
+install: library docs
+	install -d -g root -o root $(DESTDIR)$(LIBPATH)
+	install -d -g root -o root $(DESTDIR)$(INCPATH)
+	install -d -g root -o root $(DESTDIR)$(DATAPATH)
+	install -g root -o root $(LIBNAME) $(DESTDIR)$(LIBPATH)
+	install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH)
+	install -g root -o root doc/crypt.pdf $(DESTDIR)$(DATAPATH)
+
+install_lib: library
+	install -d -g root -o root $(DESTDIR)$(LIBPATH)
+	install -d -g root -o root $(DESTDIR)$(INCPATH)
+	install -g root -o root $(LIBNAME) $(DESTDIR)$(LIBPATH)
+	install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH)
+
+#This rule cleans the source tree of all compiled code, not including the pdf
+#documentation.
+clean:
+	-rm -f $(OBJECTS) $(TESTOBJECTS) $(HASHOBJECTS) $(CRYPTOBJECTS) $(SMALLOBJECTS) $(LEFTOVERS) $(LIBNAME)
+	-rm -f $(TEST) $(HASH) $(COMPRESSED) $(PROFS) $(PROF) $(TVS) $(TV)
+	-rm -f *.la *.lo *.o *.a *.dll *stackdump *.lib *.exe *.obj demos/*.obj demos/*.o *.bat *.txt *.il *.da demos/*.il demos/*.da *.dyn *.dpi \
+	*.gcda *.gcno demos/*.gcno demos/*.gcda *~ doc/*
+	-cd demos/test && make clean   
+	-rm -rf .libs demos/.libs demos/test/.libs
+	
+#This builds the crypt.pdf file. Note that the rm -f *.pdf has been removed
+#from the clean command! This is because most people would like to keep the
+#nice pre-compiled crypt.pdf that comes with libtomcrypt! We only need to
+#delete it if we are rebuilding it.
+docs: crypt.tex
+	-rm -f doc/crypt.pdf $(LEFTOVERS)
+	echo "hello" > crypt.ind
+	latex crypt > /dev/null
+	latex crypt > /dev/null
+	makeindex crypt.idx > /dev/null
+	latex crypt > /dev/null
+	dvipdf crypt
+	mv -ivf crypt.pdf doc/crypt.pdf
+	-rm -f $(LEFTOVERS)
+
+docdvi: crypt.tex
+	echo hello > crypt.ind
+	latex crypt > /dev/null
+	latex crypt > /dev/null
+	makeindex crypt.idx
+	latex crypt > /dev/null
+
+#pretty build
+pretty:
+	perl pretty.build
+
+#for GCC 3.4+
+profiled:
+	make clean
+	make CFLAGS="$(CFLAGS) -fprofile-generate" EXTRALIBS=-lgcov x86_prof
+	./x86_prof
+	rm *.o *.a x86_prof
+	make CFLAGS="$(CFLAGS) -fprofile-use" EXTRALIBS=-lgcov x86_prof
+
+#zipup the project (take that!)
+zipup: clean docs
+	cd .. ; rm -rf crypt* libtomcrypt-$(VERSION) ; mkdir libtomcrypt-$(VERSION) ; \
+	cp -R ./libtomcrypt/* ./libtomcrypt-$(VERSION)/ ; tar -c libtomcrypt-$(VERSION)/* > crypt-$(VERSION).tar ; \
+	bzip2 -9vv crypt-$(VERSION).tar ; zip -9 -r crypt-$(VERSION).zip libtomcrypt-$(VERSION)/* ; \
+	gpg -b -a crypt-$(VERSION).tar.bz2 ; gpg -b -a crypt-$(VERSION).zip
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PLAN	Sun Dec 19 11:47:33 2004 +0000
@@ -0,0 +1,38 @@
+The following functions are marked for removal and/or behavioural change by v1.00 of LibTomCrypt
+
+1.  RSA Support
+
+      rsa_pad, rsa_signpad, rsa_depad, rsa_signdepad, rsa_import, rsa_export
+
+They will be replaced with PKCS #1 compliant OAEP/PSS padding function as early as v0.96
+
+2.  DSA Support
+
+      dsa_import, dsa_export
+
+Will be replaced with suitable DSS [what is the standard?] compliant formats.  Planned for v0.96
+
+3.  Key Ring Support
+  
+      (all)
+
+The entire API will be dropped as early as v0.96.  It was just an experiment and nobody uses it anyways.
+
+4.  Test Harness
+ 
+      demos/test.c
+
+The test harness is well overdue for a makeover.  Planned for as early as v0.97
+
+
+Put things in order...
+
+v0.96  -- removed keyring.c and gf.c
+       -- removed LTC RSA padding
+       -- DSS support [whatever this entails]
+       -- Bug fixes/updates to the PKCS/DSS support, should be stable in this release
+
+v0.97  -- Re-written test harness
+       -- More demos in the manual and demos/ directory
+
+... future???
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ampi.c	Sun Dec 19 11:47:33 2004 +0000
@@ -0,0 +1,55 @@
+/* Code submitted by Svante Seleborg, cleaned up by Tom St Denis */
+
+#include "mycrypt.h"
+#include <stdarg.h>
+
+#ifdef MPI
+
+mp_err mp_init_multi(mp_int *mp, ...) 
+{
+    mp_err res = MP_OKAY;      /* Assume ok until proven otherwise */
+    int n = 0;                 /* Number of ok inits */
+    mp_int* cur_arg = mp;
+    va_list args;
+
+    va_start(args, mp);        /* init args to next argument from caller */
+    while (cur_arg != NULL) {
+        if (mp_init(cur_arg) != MP_OKAY) {
+            /* Oops - error! Back-track and mp_clear what we already
+               succeeded in init-ing, then return error.
+            */
+            va_list clean_args;
+            cur_arg = mp;
+            va_start(clean_args, mp);
+            while (n--) {
+                mp_clear(cur_arg);
+                cur_arg = va_arg(clean_args, mp_int*);
+            }
+            va_end(clean_args);
+            res = MP_MEM;
+            break;
+        }
+        n++;
+        cur_arg = va_arg(args, mp_int*);
+    }
+    va_end(args);
+    return res;                /* Assumed ok, if error flagged above. */
+}
+
+/*
+    Clear all arguments given, ended by a NULL marker.
+*/
+void mp_clear_multi(mp_int *mp, ...) 
+{
+    mp_int* next_mp = mp;
+    va_list args;
+    va_start(args, mp);
+    while (next_mp != NULL) {
+        mp_clear(next_mp);
+        next_mp = va_arg(args, mp_int*);
+    }
+    va_end(args);
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/base64.c	Sun Dec 19 11:47:33 2004 +0000
@@ -0,0 +1,121 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+/* compliant base64 code donated by Wayne Scott ([email protected]) */
+#include "mycrypt.h"
+
+#ifdef BASE64
+
+static const char *codes = 
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static const unsigned char map[256] = {
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63,
+ 52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255,
+255, 254, 255, 255, 255,   0,   1,   2,   3,   4,   5,   6,
+  7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,
+ 19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255,
+255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
+ 37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
+ 49,  50,  51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255 };
+
+int base64_encode(const unsigned char *in,  unsigned long len, 
+                        unsigned char *out, unsigned long *outlen)
+{
+   unsigned long i, len2, leven;
+   unsigned char *p;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* valid output size ? */
+   len2 = 4 * ((len + 2) / 3);
+   if (*outlen < len2 + 1) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+   p = out;
+   leven = 3*(len / 3);
+   for (i = 0; i < leven; i += 3) {
+       *p++ = codes[(in[0] >> 2) & 0x3F];
+       *p++ = codes[(((in[0] & 3) << 4) + (in[1] >> 4)) & 0x3F];
+       *p++ = codes[(((in[1] & 0xf) << 2) + (in[2] >> 6)) & 0x3F];
+       *p++ = codes[in[2] & 0x3F];
+       in += 3;
+   }
+   /* Pad it if necessary...  */
+   if (i < len) {
+       unsigned a = in[0];
+       unsigned b = (i+1 < len) ? in[1] : 0;
+
+       *p++ = codes[(a >> 2) & 0x3F];
+       *p++ = codes[(((a & 3) << 4) + (b >> 4)) & 0x3F];
+       *p++ = (i+1 < len) ? codes[(((b & 0xf) << 2)) & 0x3F] : '=';
+       *p++ = '=';
+   }
+
+   /* append a NULL byte */
+   *p = '\0';
+
+   /* return ok */
+   *outlen = p - out;
+   return CRYPT_OK;
+}
+
+int base64_decode(const unsigned char *in,  unsigned long len, 
+                        unsigned char *out, unsigned long *outlen)
+{
+   unsigned long t, x, y, z;
+   unsigned char c;
+   int           g;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   g = 3;
+   for (x = y = z = t = 0; x < len; x++) {
+       c = map[in[x]&0xFF];
+       if (c == 255) continue;
+       if (c == 254) { c = 0; g--; }
+       t = (t<<6)|c;
+       if (++y == 4) {
+          if (z + g > *outlen) { 
+             return CRYPT_BUFFER_OVERFLOW; 
+          }
+          out[z++] = (unsigned char)((t>>16)&255);
+          if (g > 1) out[z++] = (unsigned char)((t>>8)&255);
+          if (g > 2) out[z++] = (unsigned char)(t&255);
+          y = t = 0;
+       }
+   }
+   if (y != 0) {
+       return CRYPT_INVALID_PACKET;
+   }
+   *outlen = z;
+   return CRYPT_OK;
+}
+
+#endif
+
--- a/crypt.c	Sun Dec 19 11:34:45 2004 +0000
+++ b/crypt.c	Sun Dec 19 11:47:33 2004 +0000
@@ -10,6 +10,8 @@
  */
 #include "mycrypt.h"
 
+/* Dropbear doesn't need these 
+
 const char *crypt_build_settings =
    "LibTomCrypt " SCRYPT "\n\n"
    "Endianess: "
@@ -250,4 +252,5 @@
     "\n"
     "\n\n\n"
     ;
+	*/
 
Binary file doc/crypt.pdf has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gf.c	Sun Dec 19 11:47:33 2004 +0000
@@ -0,0 +1,305 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+/* polynomial basis GF(2^w) routines */
+#include "mycrypt.h"
+
+#ifdef GF
+
+#define FORLOOP for (i = 0; i < LSIZE; i++) 
+
+/* c = a + b */
+void gf_add(gf_intp a, gf_intp b, gf_intp c)
+{
+   int i;
+   FORLOOP c[i] = a[i]^b[i];
+}
+
+/* b = a */
+void gf_copy(gf_intp a, gf_intp b)
+{
+   int i;
+   FORLOOP b[i] = a[i];
+}
+
+/* a = 0 */
+void gf_zero(gf_intp a)
+{
+   int i;
+   FORLOOP a[i] = 0;
+}
+
+/* is a zero? */
+int gf_iszero(gf_intp a)
+{
+   int i;
+   FORLOOP if (a[i]) {
+      return 0;
+   }
+   return 1;
+}
+
+/* is a one? */
+int gf_isone(gf_intp a)
+{ 
+   int i;
+   for (i = 1; i < LSIZE; i++) {
+       if (a[i]) {
+          return 0;
+       }
+   }
+   return a[0] == 1;
+}
+
+/* b = a << 1*/
+void gf_shl(gf_intp a, gf_intp b)
+{
+   int i;
+   gf_int tmp;
+
+   gf_copy(a, tmp);
+   for (i = LSIZE-1; i > 0; i--) 
+       b[i] = ((tmp[i]<<1)|((tmp[i-1]&0xFFFFFFFFUL)>>31))&0xFFFFFFFFUL;
+   b[0] = (tmp[0] << 1)&0xFFFFFFFFUL;
+   gf_zero(tmp);
+}
+
+/* b = a >> 1 */
+void gf_shr(gf_intp a, gf_intp b)
+{
+   int i;
+   gf_int tmp;
+
+   gf_copy(a, tmp);
+   for (i = 0; i < LSIZE-1; i++)
+       b[i] = (((tmp[i]&0xFFFFFFFFUL)>>1)|(tmp[i+1]<<31))&0xFFFFFFFFUL;
+   b[LSIZE-1] = (tmp[LSIZE-1]&0xFFFFFFFFUL)>>1;
+   gf_zero(tmp);
+}
+
+/* returns -1 if its zero, otherwise degree of a */
+int gf_deg(gf_intp a)
+{
+   int i, ii;
+   unsigned long t;
+
+   ii = -1;
+   for (i = LSIZE-1; i >= 0; i--)
+       if (a[i]) {
+          for (t = a[i], ii = 0; t; t >>= 1, ++ii);
+          break;
+       }
+   if (i == -1) i = 0;
+   return (i<<5)+ii;
+}
+
+/* c = ab */
+void gf_mul(gf_intp a, gf_intp b, gf_intp c)
+{
+   gf_int ta, tb;
+   int i, n;
+
+   gf_copy(a, ta);
+   gf_copy(b, tb);
+   gf_zero(c);
+   n = gf_deg(ta)+1;
+   for (i = 0; i < n; i++) {
+       if (ta[i>>5]&(1<<(i&31)))
+          gf_add(c, tb, c);
+       gf_shl(tb, tb);
+   }
+   gf_zero(ta);
+   gf_zero(tb);
+}
+
+/* q = a/b, r = a%b */
+void gf_div(gf_intp a, gf_intp b, gf_intp q, gf_intp r)
+{
+   gf_int ta, tb, shifts[LSIZE*32];
+   int i, magb, mag;
+
+   mag  = gf_deg(a);
+   magb = gf_deg(b);
+
+   /* special cases */
+   if (magb > mag) {
+      gf_copy(a, r);
+      gf_zero(q);
+      return;
+   }
+   if (magb == -1) {
+      return;
+   }
+
+   /* copy locally */
+   gf_copy(a, ta);
+   gf_copy(b, tb);
+   gf_zero(q);
+
+   /* make shifted versions of "b" */
+   gf_copy(tb, shifts[0]);
+   for (i = 1; i <= (mag-magb); i++) 
+       gf_shl(shifts[i-1], shifts[i]);
+
+   while (mag >= magb) {
+       i = (mag - magb);
+       q[i>>5] |= (1<<(i&31));
+       gf_add(ta, shifts[i], ta);
+       mag = gf_deg(ta);
+   }
+   gf_copy(ta, r);
+   gf_zero(ta);
+   gf_zero(tb);
+   zeromem(shifts, sizeof(shifts));
+}
+
+/* b = a mod m */
+void gf_mod(gf_intp a, gf_intp m, gf_intp b)
+{
+   gf_int tmp;
+   gf_div(a,m,tmp,b);
+   gf_zero(tmp);
+}
+
+/* c = ab (mod m) */
+void gf_mulmod(gf_intp a, gf_intp b, gf_intp m, gf_intp c)
+{
+   gf_int tmp;
+   gf_mul(a, b, tmp);
+   gf_mod(tmp, m, c);
+   gf_zero(tmp);
+}
+
+/* B = 1/A mod M */
+void gf_invmod(gf_intp A, gf_intp M, gf_intp B)
+{
+  gf_int m, n, p0, p1, p2, r, q, tmp;
+
+  /* put all variables in known setup state */
+  gf_zero(p0);
+  gf_zero(p2);
+  gf_copy(M, m);
+  gf_copy(A, n);
+  p0[0] = 1;
+  gf_div(m, n, p1, r);
+  gf_copy(p1, q);
+
+  /* loop until r == 0 */
+  while (!gf_iszero(r)) {
+     gf_copy(n, m);
+     gf_copy(r, n);
+     gf_div(m, n, q, r);
+     gf_mul(q, p1, tmp);
+     gf_add(tmp, p0, p2);
+     gf_copy(p1, p0);
+     gf_copy(p2, p1);
+  }
+  gf_copy(p0, B);
+  gf_zero(p0);
+}
+
+/* find a square root modulo a prime.  Note the number of 
+ * elements is 2^k - 1, so we must square k-2 times to get the
+ * square root.. 
+ */
+void gf_sqrt(gf_intp a, gf_intp M, gf_intp b)
+{
+   int k;
+   k = gf_deg(M)-2;
+   gf_copy(a, b);
+   while (k--)
+      gf_mulmod(b, b, M, b);
+}
+
+/* c = gcd(A,B) */
+void gf_gcd(gf_intp A, gf_intp B, gf_intp c)
+{
+   gf_int a, b, r;
+   int n;
+
+   gf_add(A, B, r);
+   n = gf_deg(r);
+   if (gf_deg(A) > n) {
+      gf_copy(A, a);
+      gf_copy(B, b);
+   } else {
+      gf_copy(A, b);
+      gf_copy(B, a);
+   }
+
+   do {
+      gf_mod(a, b, r);
+      gf_copy(b, a);
+      gf_copy(r, b);
+   } while (!gf_iszero(r));
+   gf_copy(a, c);
+   gf_zero(a);
+   gf_zero(b);
+}
+
+/* returns non-zero if 'a' is irreducible */
+int gf_is_prime(gf_intp a)
+{
+   gf_int u, tmp;
+   int m, n;
+
+   gf_zero(u);
+   u[0] = 2;			/* u(x) = x */
+   m = gf_deg(a);
+   for (n = 0; n < (m/2); n++) { 
+       gf_mulmod(u, u, a, u);   /* u(x) = u(x)^2 mod a(x) */
+       gf_copy(u, tmp);
+       tmp[0] ^= 2;		/* tmp(x) = u(x) - x */
+       gf_gcd(tmp, a, tmp);     /* tmp(x) = gcd(a(x), u(x) - x) */
+       if (!gf_isone(tmp)) {
+          return 0;
+       }
+   }
+   return 1;
+}  
+
+/* returns bytes required to store a gf_int */
+int gf_size(gf_intp a)
+{
+   int n;
+
+   n = gf_deg(a);
+   if (n == -1) {
+      return 4;
+   }
+   n = n + (32 - (n&31));
+   return n/8;
+}
+
+/* store a gf_int */
+void gf_toraw(gf_intp a, unsigned char *dst)
+{
+   int x, n;
+   n = gf_size(a)/4;
+   for (x = 0; x < n; x++) {
+       STORE32L(a[x], dst);
+       dst += 4;
+   }
+}
+
+/* read a gf_int (len == in bytes) */
+void gf_readraw(gf_intp a, unsigned char *str, int len)
+{
+   int x;
+   gf_zero(a);
+   for (x = 0; x < len/4; x++) {
+       LOAD32L(a[x], str);
+       str += 4;
+   }
+}
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/keyring.c	Sun Dec 19 11:47:33 2004 +0000
@@ -0,0 +1,862 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+/* Provides keyring functionality for libtomcrypt, Tom St Denis */
+#include <mycrypt.h>
+
+#ifdef KR
+
+static const unsigned char key_magic[4]  = { 0x12, 0x34, 0x56, 0x78 };
+static const unsigned char file_magic[4] = { 0x9A, 0xBC, 0xDE, 0xF0 };
+static const unsigned char sign_magic[4] = { 0x87, 0x56, 0x43, 0x21 };
+static const unsigned char enc_magic[4]  = { 0x0F, 0xED, 0xCB, 0xA9 };
+
+static const unsigned long crc_table[256] = {
+  0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+  0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+  0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+  0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+  0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+  0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+  0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+  0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+  0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+  0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+  0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+  0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+  0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+  0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+  0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+  0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+  0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+  0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+  0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+  0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+  0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+  0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+  0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+  0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+  0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+  0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+  0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+  0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+  0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+  0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+  0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+  0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+  0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+  0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+  0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+  0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+  0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+  0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+  0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+  0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+  0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+  0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+  0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+  0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+  0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+  0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+  0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+  0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+  0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+  0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+  0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+  0x2d02ef8dUL
+};
+
+#define DO1(buf) crc = crc_table[(crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
+#define DO2(buf)  DO1(buf); DO1(buf);
+#define DO4(buf)  DO2(buf); DO2(buf);
+#define DO8(buf)  DO4(buf); DO4(buf);
+
+static unsigned long crc32 (unsigned long crc, const unsigned char *buf, unsigned long len)
+{
+  //_ARGCHK(buf != NULL  && len == 0);
+  crc = crc ^ 0xffffffffL;
+  while (len >= 8) {
+      DO8 (buf);
+      len -= 8;
+  }
+  
+  if (len > 0) {
+    do {
+	   DO1 (buf);
+    } while (--len > 0);
+  }    
+  return crc ^ 0xffffffffUL;
+}
+
+int kr_init(pk_key **pk)
+{
+   _ARGCHK(pk != NULL);
+
+   *pk = XCALLOC(1, sizeof(pk_key));
+   if (*pk == NULL) {
+      return CRYPT_MEM;
+   }
+   (*pk)->system = NON_KEY;
+   return CRYPT_OK;
+}
+
+unsigned long kr_crc(const unsigned char *name, const unsigned char *email, const unsigned char *description)
+{
+   unsigned long crc;
+   _ARGCHK(name != NULL);
+   _ARGCHK(email != NULL);
+   _ARGCHK(description != NULL);
+   crc = crc32(0UL, NULL, 0UL);
+   crc = crc32(crc, name,  (unsigned long)MIN(MAXLEN, strlen((char *)name)));
+   crc = crc32(crc, email, (unsigned long)MIN(MAXLEN, strlen((char *)email)));
+   return crc32(crc, description, (unsigned long)MIN(MAXLEN, strlen((char *)description)));
+}
+
+pk_key *kr_find(pk_key *pk, unsigned long ID)
+{
+   _ARGCHK(pk != NULL);
+
+   while (pk != NULL) {
+        if (pk->system != NON_KEY && pk->ID == ID) {
+           return pk;
+        }
+        pk = pk->next;
+   }
+   return NULL;
+}
+
+pk_key *kr_find_name(pk_key *pk, const char *name)
+{
+   _ARGCHK(pk != NULL);
+   _ARGCHK(name != NULL);
+
+   while (pk != NULL) {
+        if (pk->system != NON_KEY && strncmp((char *)pk->name, (char *)name, sizeof(pk->name)-1) == 0) {
+           return pk;
+        }
+        pk = pk->next;
+   }
+   return NULL;
+}
+ 
+
+int kr_add(pk_key *pk, int key_type, int sys, const unsigned char *name, 
+           const unsigned char *email, const unsigned char *description, const _pk_key *key)
+{
+   _ARGCHK(pk != NULL);
+   _ARGCHK(name != NULL);
+   _ARGCHK(email != NULL);
+   _ARGCHK(description != NULL);
+   _ARGCHK(key != NULL);
+
+   /* check parameters */
+   if (key_type != PK_PRIVATE && key_type != PK_PRIVATE_OPTIMIZED && key_type != PK_PUBLIC) {
+      return CRYPT_PK_INVALID_TYPE;
+   }
+ 
+   if (sys != RSA_KEY && sys != DH_KEY && sys != ECC_KEY) {
+      return CRYPT_PK_INVALID_SYSTEM;
+   }
+
+   /* see if its a dupe  */
+   if (kr_find(pk, kr_crc(name, email, description)) != NULL) {
+      return CRYPT_PK_DUP;
+   }
+   
+   /* find spot in key ring */
+   while (pk->system != NON_KEY) {
+         if (pk->next == NULL) {
+            return CRYPT_ERROR;
+         }
+         pk = pk->next;
+   }
+
+   /* now we have a spot make a next spot */
+   pk->next = XCALLOC(1, sizeof(pk_key));
+   if (pk->next == NULL) {
+      return CRYPT_MEM;
+   }
+   pk->next->system = NON_KEY;
+
+   /* now add this new data to this ring spot */
+   pk->key_type = key_type;
+   pk->system   = sys;
+   strncpy((char *)pk->name, (char *)name, sizeof(pk->name)-1);
+   strncpy((char *)pk->email, (char *)email, sizeof(pk->email)-1);
+   strncpy((char *)pk->description, (char *)description, sizeof(pk->description)-1);
+   pk->ID       = kr_crc(pk->name, pk->email, pk->description);
+
+   /* clear the memory area */
+   zeromem(&(pk->key), sizeof(pk->key));
+
+   /* copy the key */
+   switch (sys) {
+         case RSA_KEY:
+              memcpy(&(pk->key.rsa), &(key->rsa), sizeof(key->rsa));
+              break;
+         case DH_KEY:
+              memcpy(&(pk->key.dh), &(key->dh), sizeof(key->dh));
+              break;
+         case ECC_KEY:
+              memcpy(&(pk->key.ecc), &(key->ecc), sizeof(key->ecc));
+              break;
+   }
+   return CRYPT_OK;
+}
+
+int kr_del(pk_key **_pk, unsigned long ID)
+{
+   pk_key *ppk, *pk;
+
+   _ARGCHK(_pk != NULL);
+
+   pk  = *_pk;
+   ppk = NULL;
+   while (pk->system != NON_KEY && pk->ID != ID) {
+        ppk = pk;
+        pk  = pk->next;
+        if (pk == NULL) {
+           return CRYPT_PK_NOT_FOUND;
+        }
+   }
+
+   switch (pk->system) {
+        case RSA_KEY:
+            rsa_free(&(pk->key.rsa));
+            break;
+        case DH_KEY:
+            dh_free(&(pk->key.dh));
+            break;
+        case ECC_KEY:
+            ecc_free(&(pk->key.ecc));
+            break;
+   }
+
+   if (ppk == NULL) {       /* the first element matches the ID */
+      ppk = pk->next;       /* get the 2nd element */
+      XFREE(pk);             /* free the first */
+      *_pk = ppk;           /* make the first element the second */
+   } else {                 /* (not) first element matches the ID */
+      ppk->next = pk->next; /* make the previous'es next point to the current next */
+      XFREE(pk);             /* free the element */
+   }
+   return CRYPT_OK;
+}
+
+int kr_clear(pk_key **pk)
+{
+   int err;
+   _ARGCHK(pk != NULL);
+
+   while ((*pk)->system != NON_KEY) {
+       if ((err = kr_del(pk, (*pk)->ID)) != CRYPT_OK) { 
+          return err;
+       }
+   }       
+   XFREE(*pk);
+   *pk = NULL;
+   return CRYPT_OK;
+}
+
+static unsigned long _write(unsigned char *buf, unsigned long len, FILE *f, symmetric_CTR *ctr)
+{
+#ifdef NO_FILE
+   return 0;
+#else
+   _ARGCHK(buf != NULL);
+   _ARGCHK(f   != NULL);
+   if (ctr != NULL) {
+      if (ctr_encrypt(buf, buf, len, ctr) != CRYPT_OK) {
+         return 0;
+      }
+   }
+   return (unsigned long)fwrite(buf, 1, (size_t)len, f);
+#endif
+}
+
+static unsigned long _read(unsigned char *buf, unsigned long len, FILE *f, symmetric_CTR *ctr)
+{
+#ifdef NO_FILE
+    return 0;
+#else
+   unsigned long y;
+   _ARGCHK(buf != NULL);
+   _ARGCHK(f   != NULL);
+   y = (unsigned long)fread(buf, 1, (size_t)len, f);
+   if (ctr != NULL) {
+      if (ctr_decrypt(buf, buf, y, ctr) != CRYPT_OK) {
+         return 0;
+      }
+   }
+   return y;
+#endif
+}
+
+int kr_export(pk_key *pk, unsigned long ID, int key_type, unsigned char *out, unsigned long *outlen)
+{
+   unsigned char buf[8192], *obuf;
+   pk_key *ppk;
+   unsigned long len;
+   int err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(out != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* find the desired key */
+   ppk = kr_find(pk, ID);
+   if (ppk == NULL) {
+      return CRYPT_PK_NOT_FOUND;
+   }
+
+   if (ppk->key_type == PK_PUBLIC && key_type != PK_PUBLIC) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   /* this makes PK_PRIVATE an alias for PK_PRIVATE_OPTIMIZED type */
+   if (ppk->key_type == PK_PRIVATE_OPTIMIZED && key_type == PK_PRIVATE) {
+      key_type = PK_PRIVATE_OPTIMIZED;
+   }
+
+   /* now copy the header and various other details */
+   memcpy(buf, key_magic, 4);                              /* magic info */
+   buf[4] = key_type;                                      /* key type */
+   buf[5] = ppk->system;                                   /* system */
+   STORE32L(ppk->ID, buf+6);                               /* key ID */
+   memcpy(buf+10, ppk->name, MAXLEN);                      /* the name */
+   memcpy(buf+10+MAXLEN, ppk->email, MAXLEN);              /* the email */
+   memcpy(buf+10+MAXLEN+MAXLEN, ppk->description, MAXLEN); /* the description */
+   
+   /* export key */
+   len = sizeof(buf) - (6 + 4 + MAXLEN*3);
+   obuf = buf+6+4+MAXLEN*3;
+   switch (ppk->system) {
+       case RSA_KEY:
+           if ((err = rsa_export(obuf, &len, key_type, &(ppk->key.rsa))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+       case DH_KEY:
+           if ((err = dh_export(obuf, &len, key_type, &(ppk->key.dh))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+       case ECC_KEY:
+           if ((err = ecc_export(obuf, &len, key_type, &(ppk->key.ecc))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+   }
+
+   /* get the entire length of the packet */
+   len += 6 + 4 + 3*MAXLEN;
+
+   if (*outlen < len) {
+      #ifdef CLEAN_STACK
+          zeromem(buf, sizeof(buf));
+      #endif
+      return CRYPT_BUFFER_OVERFLOW;
+   } else {
+      *outlen = len;
+      memcpy(out, buf, len);
+      #ifdef CLEAN_STACK
+          zeromem(buf, sizeof(buf));
+      #endif
+      return CRYPT_OK;
+   }
+}
+
+int kr_import(pk_key *pk, const unsigned char *in, unsigned long inlen)
+{
+   _pk_key key;
+   int sys, key_type, err;
+   unsigned long ID;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(in != NULL);
+
+   if (inlen < 10) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   if (memcmp(in, key_magic, 4) != 0) {
+      return CRYPT_INVALID_PACKET;
+   }
+   key_type = in[4];                                 /* get type */
+   sys      = in[5];                                 /* get system */
+   LOAD32L(ID,in+6);                                 /* the ID */
+
+   if (ID != kr_crc(in+10, in+10+MAXLEN, in+10+MAXLEN+MAXLEN)) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   zeromem(&key, sizeof(key));
+   
+   /* size of remaining packet */
+   inlen -= 10 + 3*MAXLEN;
+   
+   switch (sys) {
+        case RSA_KEY:
+            if ((err = rsa_import(in+10+3*MAXLEN, inlen, &(key.rsa))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+        case DH_KEY:
+            if ((err = dh_import(in+10+3*MAXLEN, inlen, &(key.dh))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+        case ECC_KEY:
+            if ((err = ecc_import(in+10+3*MAXLEN, inlen, &(key.ecc))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+   }
+   return kr_add(pk, key_type, sys, 
+                 in+10,                           /* the name */
+                 in+10+MAXLEN,                    /* email address */
+                 in+10+MAXLEN+MAXLEN,             /* description */
+                 &key);
+}
+
+
+int kr_load(pk_key **pk, FILE *in, symmetric_CTR *ctr)
+{
+   unsigned char buf[8192], blen[4];
+   unsigned long len;
+   int res, err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(in != NULL);
+
+   /* init keyring */
+   if ((err = kr_init(pk)) != CRYPT_OK) { 
+      return err; 
+   }
+
+   /* read in magic bytes */
+   if (_read(buf, 6, in, ctr) != 6)           { goto done2; }
+
+   if (memcmp(buf, file_magic, 4) != 0) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   len = (unsigned long)buf[4] | ((unsigned long)buf[5] << 8);
+   if (len > CRYPT) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* while there are lengths to read... */
+   while (_read(blen, 4, in, ctr) == 4) {
+      /* get length */
+      LOAD32L(len, blen);
+
+      if (len > (unsigned long)sizeof(buf)) {
+         return CRYPT_INVALID_PACKET;
+      }
+
+      if (_read(buf, len, in, ctr) != len)           { goto done2; }
+      if ((err = kr_import(*pk, buf, len)) != CRYPT_OK) { 
+         return err; 
+      }
+   }
+
+   res = CRYPT_OK;
+   goto done;
+done2:
+   res = CRYPT_ERROR;
+done:
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+   return res;
+}
+
+int kr_save(pk_key *pk, FILE *out, symmetric_CTR *ctr)
+{
+   unsigned char buf[8192], blen[4];
+   unsigned long len;
+   int res, err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(out != NULL);
+
+   /* write out magic bytes */
+   memcpy(buf, file_magic, 4);
+   buf[4] = (unsigned char)(CRYPT&255);
+   buf[5] = (unsigned char)((CRYPT>>8)&255);
+   if (_write(buf, 6, out, ctr) != 6)           { goto done2; }
+
+   while (pk->system != NON_KEY) {
+         len = sizeof(buf);
+         if ((err = kr_export(pk, pk->ID, pk->key_type, buf, &len)) != CRYPT_OK) { 
+            return err;
+         }
+          
+         STORE32L(len, blen);
+         if (_write(blen, 4, out, ctr) != 4)    { goto done2; }
+         if (_write(buf, len, out, ctr) != len) { goto done2; }
+
+         pk = pk->next;
+   }
+         
+   res = CRYPT_OK;
+   goto done;
+done2:
+   res = CRYPT_ERROR;
+done:
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+   return res;
+}
+
+int kr_make_key(pk_key *pk, prng_state *prng, int wprng, 
+                int sys, int keysize, const unsigned char *name,
+                const unsigned char *email, const unsigned char *description)
+{
+   _pk_key key;
+   int key_type, err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(name != NULL);
+   _ARGCHK(email != NULL);
+   _ARGCHK(description != NULL);
+
+   /* valid PRNG? */
+   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* make the key first */
+   zeromem(&key, sizeof(key));
+   switch (sys) {
+      case RSA_KEY: 
+          if ((err = rsa_make_key(prng, wprng, keysize, 65537, &(key.rsa))) != CRYPT_OK) {
+             return err;
+          }
+          key_type = key.rsa.type;
+          break;
+      case DH_KEY: 
+          if ((err = dh_make_key(prng, wprng, keysize, &(key.dh))) != CRYPT_OK) {
+             return err;
+          }
+          key_type = key.dh.type;
+          break;
+      case ECC_KEY: 
+          if ((err = ecc_make_key(prng, wprng, keysize, &(key.ecc))) != CRYPT_OK) {
+             return err;
+          }
+          key_type = key.ecc.type;
+          break;
+      default:
+          return CRYPT_PK_INVALID_SYSTEM;
+   }
+
+   /* now add the key */
+   if ((err = kr_add(pk, key_type, sys, name, email, description, &key)) != CRYPT_OK) {
+      return err;
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(&key, sizeof(key));
+#endif
+   return CRYPT_OK;
+}
+
+int kr_encrypt_key(pk_key *pk, unsigned long ID, 
+                   const unsigned char *in, unsigned long inlen,
+                   unsigned char *out, unsigned long *outlen,
+                   prng_state *prng, int wprng, int hash)
+{
+   unsigned char buf[8192];
+   unsigned long len;
+   pk_key *kr;
+   int err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(in != NULL);
+   _ARGCHK(out != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* find the key */
+   kr = kr_find(pk, ID);
+   if (kr == NULL) {
+      return CRYPT_PK_NOT_FOUND;
+   }
+
+   /* store the header */
+   memcpy(buf, enc_magic, 4);
+
+   /* now store the ID */
+   STORE32L(kr->ID,buf+4);
+
+   /* now encrypt it */
+   len = sizeof(buf)-12;
+   switch (kr->system) {
+        case RSA_KEY:
+            if ((err = rsa_encrypt_key(in, inlen, buf+12, &len, prng, wprng, &(kr->key.rsa))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+        case DH_KEY:
+            if ((err = dh_encrypt_key(in, inlen, buf+12, &len, prng, wprng, hash, &(kr->key.dh))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+        case ECC_KEY:
+            if ((err = ecc_encrypt_key(in, inlen, buf+12, &len, prng, wprng, hash, &(kr->key.ecc))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+    }
+    STORE32L(len,buf+8);
+    len += 12;
+
+    if (len > *outlen) {
+       #ifdef CLEAN_STACK
+           zeromem(buf, sizeof(buf));
+       #endif
+       return CRYPT_BUFFER_OVERFLOW;
+    } else {
+       memcpy(out, buf, len);
+       #ifdef CLEAN_STACK
+           zeromem(buf, sizeof(buf));
+       #endif
+       *outlen = len;
+       return CRYPT_OK;
+    }
+}
+
+int kr_decrypt_key(pk_key *pk, const unsigned char *in,
+                   unsigned char *out, unsigned long *outlen)
+{
+   unsigned char buf[8192];
+   unsigned long pklen, len, ID;
+   pk_key *kr;
+   int err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(in != NULL);
+   _ARGCHK(out != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* check magic header */
+   if (memcmp(in, enc_magic, 4)) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* now try to find key */
+   LOAD32L(ID,in+4);
+   kr = kr_find(pk, ID);
+   if (kr == NULL) {
+      return CRYPT_PK_NOT_FOUND;
+   }
+
+   /* is it public? */
+   if (kr->key_type == PK_PUBLIC) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   /* now try and decrypt it */
+   LOAD32L(pklen,in+8);
+   len = sizeof(buf);
+   switch (kr->system) {
+       case RSA_KEY:
+           if ((err = rsa_decrypt_key(in+12, pklen, buf, &len, &(kr->key.rsa))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+       case DH_KEY:
+           if ((err = dh_decrypt_key(in+12, pklen, buf, &len, &(kr->key.dh))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+       case ECC_KEY:
+           if ((err = ecc_decrypt_key(in+12, pklen, buf, &len, &(kr->key.ecc))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+   }
+
+    if (len > *outlen) {
+       #ifdef CLEAN_STACK
+           zeromem(buf, sizeof(buf));
+       #endif
+       return CRYPT_BUFFER_OVERFLOW;
+    } else {
+       memcpy(out, buf, len);
+       #ifdef CLEAN_STACK
+           zeromem(buf, sizeof(buf));
+       #endif
+       *outlen = len;
+       return CRYPT_OK;
+    }
+}
+
+int kr_sign_hash(pk_key *pk, unsigned long ID, 
+                 const unsigned char *in, unsigned long inlen,
+                 unsigned char *out, unsigned long *outlen,
+                 prng_state *prng, int wprng)
+{
+   unsigned char buf[8192];
+   unsigned long len;
+   pk_key *kr;
+   int err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(in != NULL);
+   _ARGCHK(out != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* find the key */
+   kr = kr_find(pk, ID);
+   if (kr == NULL) {
+      return CRYPT_PK_NOT_FOUND;
+   }
+
+   /* is it public? */
+   if (kr->key_type == PK_PUBLIC) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   /* store the header */
+   memcpy(buf, sign_magic, 4);
+
+   /* now store the ID */
+   STORE32L(kr->ID,buf+4);
+
+   /* now sign it */
+   len = sizeof(buf)-16;
+   switch (kr->system) {
+        case RSA_KEY:
+            if ((err = rsa_sign_hash(in, inlen, buf+16, &len, &(kr->key.rsa))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+        case DH_KEY:
+            if ((err = dh_sign_hash(in, inlen, buf+16, &len, prng, wprng, &(kr->key.dh))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+        case ECC_KEY:
+            if ((err = ecc_sign_hash(in, inlen, buf+16, &len, prng, wprng, &(kr->key.ecc))) != CRYPT_OK) {
+               return err;
+            }
+            break;
+    }
+    STORE32L(inlen,buf+8);
+    STORE32L(len,buf+12);
+    len += 16;
+
+    if (len > *outlen) {
+       #ifdef CLEAN_STACK
+           zeromem(buf, sizeof(buf));
+       #endif
+       return CRYPT_BUFFER_OVERFLOW;
+    } else {
+       memcpy(out, buf, len);
+       #ifdef CLEAN_STACK
+           zeromem(buf, sizeof(buf));
+       #endif
+       *outlen = len;
+       return CRYPT_OK;
+    }
+}
+
+int kr_verify_hash(pk_key *pk, const unsigned char *in, const unsigned char *hash, 
+                   unsigned long hashlen, int *stat)
+{
+   unsigned long inlen, pklen, ID;
+   pk_key *kr;
+   int err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(in != NULL);
+   _ARGCHK(hash != NULL);
+   _ARGCHK(stat != NULL);
+
+   /* default to not match */
+   *stat = 0;
+
+   /* check magic header */
+   if (memcmp(in, sign_magic, 4)) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* now try to find key */
+   LOAD32L(ID,in+4);
+   kr = kr_find(pk, ID);
+   if (kr == NULL) {
+      return CRYPT_PK_NOT_FOUND;
+   }
+
+   /* now try and verify it */
+   LOAD32L(inlen,in+8);         /* this is the length of the original inlen */
+   LOAD32L(pklen,in+12);        /* size of the PK packet */
+   if (inlen != hashlen) {      /* size doesn't match means the signature is invalid */
+      return CRYPT_OK;
+   }
+
+   switch (kr->system) {
+       case RSA_KEY:
+           if ((err = rsa_verify_hash(in+16, pklen, hash, stat, &(kr->key.rsa))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+       case DH_KEY:
+           if ((err = dh_verify_hash(in+16, pklen, hash, inlen, stat, &(kr->key.dh))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+       case ECC_KEY:
+           if ((err = ecc_verify_hash(in+16, pklen, hash, inlen, stat, &(kr->key.ecc))) != CRYPT_OK) {
+              return err;
+           }
+           break;
+   }
+   return CRYPT_OK;
+}
+
+int kr_fingerprint(pk_key *pk, unsigned long ID, int hash,
+                   unsigned char *out, unsigned long *outlen)
+{
+   unsigned char buf[8192];
+   unsigned long len;
+   int err;
+
+   _ARGCHK(pk != NULL);
+   _ARGCHK(out != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* valid hash? */
+   if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+      return err;
+   }
+
+   len = (unsigned long)sizeof(buf);
+   if ((err = kr_export(pk, ID, PK_PUBLIC, buf, &len)) != CRYPT_OK) {
+      return err;
+   }
+   
+   /* now hash it */
+   if ((err = hash_memory(hash, buf, len, out, outlen)) != CRYPT_OK) {
+      return err;
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+   return CRYPT_OK;
+}
+
+#endif
+
+
--- a/makefile	Sun Dec 19 11:34:45 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +0,0 @@
-# MAKEFILE for linux GCC
-#
-# Tom St Denis
-# Modified by Clay Culver
-
-# The version
-VERSION=0.99
-
-# Compiler and Linker Names
-#CC=gcc
-#LD=ld
-
-# Archiver [makes .a files]
-#AR=ar
-#ARFLAGS=r
-
-# Compilation flags. Note the += does not write over the user's CFLAGS!
-CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wshadow 
-# -Werror
-
-# optimize for SPEED
-#CFLAGS += -O3 -funroll-all-loops
-
-#add -fomit-frame-pointer.  hinders debugging!
-#CFLAGS += -fomit-frame-pointer
-
-# optimize for SIZE
-CFLAGS += -Os -DSMALL_CODE
-
-# compile for DEBUGING (required for ccmalloc checking!!!)
-#CFLAGS += -g3
-
-#These flags control how the library gets built.
-
-#Output filenames for various targets.
-LIBNAME=libtomcrypt.a
-HASH=hashsum
-CRYPT=encrypt
-SMALL=small
-PROF=x86_prof
-TV=tv_gen
-
-#LIBPATH-The directory for libtomcrypt to be installed to.
-#INCPATH-The directory to install the header files for libtomcrypt.
-#DATAPATH-The directory to install the pdf docs.
-DESTDIR=
-LIBPATH=/usr/lib
-INCPATH=/usr/include
-DATAPATH=/usr/share/doc/libtomcrypt/pdf
-
-#List of objects to compile.
-
-#Leave MPI built-in or force developer to link against libtommath?
-MPIOBJECT=mpi.o
-
-OBJECTS=error_to_string.o mpi_to_ltc_error.o base64_encode.o base64_decode.o \
-\
-crypt.o                    crypt_find_cipher.o      crypt_find_hash_any.o      \
-crypt_hash_is_valid.o      crypt_register_hash.o    crypt_unregister_prng.o    \
-crypt_argchk.o             crypt_find_cipher_any.o  crypt_find_hash_id.o       \
-crypt_prng_descriptor.o    crypt_register_prng.o    crypt_cipher_descriptor.o  \
-crypt_find_cipher_id.o     crypt_find_prng.o        crypt_prng_is_valid.o      \
-crypt_unregister_cipher.o  crypt_cipher_is_valid.o  crypt_find_hash.o          \
-crypt_hash_descriptor.o    crypt_register_cipher.o  crypt_unregister_hash.o    \
-\
-sober128.o fortuna.o sprng.o yarrow.o rc4.o rng_get_bytes.o  rng_make_prng.o \
-\
-rand_prime.o is_prime.o \
-\
-ecc.o  dh.o \
-\
-rsa_decrypt_key.o  rsa_encrypt_key.o  rsa_exptmod.o  rsa_free.o  rsa_make_key.o  \
-rsa_sign_hash.o  rsa_verify_hash.o rsa_export.o rsa_import.o tim_exptmod.o \
-rsa_v15_encrypt_key.o rsa_v15_decrypt_key.o rsa_v15_sign_hash.o rsa_v15_verify_hash.o \
-\
-dsa_export.o  dsa_free.o  dsa_import.o  dsa_make_key.o  dsa_sign_hash.o  \
-dsa_verify_hash.o  dsa_verify_key.o \
-\
-aes.o aes_enc.o \
-\
-blowfish.o des.o safer_tab.o safer.o saferp.o rc2.o xtea.o \
-rc6.o rc5.o cast5.o noekeon.o twofish.o skipjack.o \
-\
-md2.o md4.o md5.o sha1.o sha256.o sha512.o tiger.o whirl.o \
-rmd128.o rmd160.o chc.o \
-\
-packet_store_header.o  packet_valid_header.o \
-\
-eax_addheader.o  eax_decrypt.o  eax_decrypt_verify_memory.o  eax_done.o  eax_encrypt.o  \
-eax_encrypt_authenticate_memory.o  eax_init.o  eax_test.o \
-\
-ocb_decrypt.o  ocb_decrypt_verify_memory.o  ocb_done_decrypt.o  ocb_done_encrypt.o  \
-ocb_encrypt.o  ocb_encrypt_authenticate_memory.o  ocb_init.o  ocb_ntz.o  \
-ocb_shift_xor.o  ocb_test.o s_ocb_done.o \
-\
-omac_done.o  omac_file.o  omac_init.o  omac_memory.o  omac_process.o  omac_test.o \
-\
-pmac_done.o  pmac_file.o  pmac_init.o  pmac_memory.o  pmac_ntz.o  pmac_process.o  \
-pmac_shift_xor.o  pmac_test.o \
-\
-cbc_start.o cbc_encrypt.o cbc_decrypt.o cbc_getiv.o cbc_setiv.o \
-cfb_start.o cfb_encrypt.o cfb_decrypt.o cfb_getiv.o cfb_setiv.o \
-ofb_start.o ofb_encrypt.o ofb_decrypt.o ofb_getiv.o ofb_setiv.o \
-ctr_start.o ctr_encrypt.o ctr_decrypt.o ctr_getiv.o ctr_setiv.o \
-ecb_start.o ecb_encrypt.o ecb_decrypt.o \
-\
-hash_file.o  hash_filehandle.o  hash_memory.o \
-\
-hmac_done.o  hmac_file.o  hmac_init.o  hmac_memory.o  hmac_process.o  hmac_test.o \
-\
-pkcs_1_mgf1.o pkcs_1_oaep_encode.o pkcs_1_oaep_decode.o  \
-pkcs_1_pss_encode.o pkcs_1_pss_decode.o pkcs_1_i2osp.o pkcs_1_os2ip.o \
-pkcs_1_v15_es_encode.o pkcs_1_v15_es_decode.o pkcs_1_v15_sa_encode.o pkcs_1_v15_sa_decode.o \
-\
-pkcs_5_1.o pkcs_5_2.o \
-\
-der_encode_integer.o der_decode_integer.o der_length_integer.o \
-der_put_multi_integer.o der_get_multi_integer.o \
-\
-burn_stack.o zeromem.o \
-\
-$(MPIOBJECT)
-
-TESTOBJECTS=demos/test.o
-HASHOBJECTS=demos/hashsum.o
-CRYPTOBJECTS=demos/encrypt.o
-SMALLOBJECTS=demos/small.o
-PROFS=demos/x86_prof.o
-TVS=demos/tv_gen.o
-
-#Files left over from making the crypt.pdf.
-LEFTOVERS=*.dvi *.log *.aux *.toc *.idx *.ilg *.ind *.out
-
-#Compressed filenames
-COMPRESSED=crypt-$(VERSION).tar.bz2 crypt-$(VERSION).zip
-
-#Header files used by libtomcrypt.
-HEADERS=ltc_tommath.h mycrypt_cfg.h \
-mycrypt_misc.h  mycrypt_prng.h mycrypt_cipher.h  mycrypt_hash.h \
-mycrypt_macros.h  mycrypt_pk.h mycrypt.h mycrypt_argchk.h \
-mycrypt_custom.h mycrypt_pkcs.h tommath_class.h tommath_superclass.h
-
-#The default rule for make builds the libtomcrypt library.
-default:library
-
-#ciphers come in two flavours... enc+dec and enc 
-aes_enc.o: aes.c aes_tab.c
-	$(CC) $(CFLAGS) -DENCRYPT_ONLY -c aes.c -o aes_enc.o
-
-#These are the rules to make certain object files.
-aes.o: aes.c aes_tab.c
-twofish.o: twofish.c twofish_tab.c
-whirl.o: whirl.c whirltab.c
-ecc.o: ecc.c ecc_sys.c
-dh.o: dh.c dh_sys.c
-sha512.o: sha512.c sha384.c
-sha256.o: sha256.c sha224.c
-
-#This rule makes the libtomcrypt library.
-library: $(LIBNAME)
-
-$(LIBNAME): $(OBJECTS)
-	$(AR) $(ARFLAGS) $@ $(OBJECTS) 
-
-#This rule makes the hash program included with libtomcrypt
-hashsum: library $(HASHOBJECTS)
-	$(CC) $(HASHOBJECTS) $(LIBNAME) -o $(HASH) $(WARN)
-
-#makes the crypt program
-crypt: library $(CRYPTOBJECTS)
-	$(CC) $(CRYPTOBJECTS) $(LIBNAME) -o $(CRYPT) $(WARN)
-
-#makes the small program
-small: library $(SMALLOBJECTS)
-	$(CC) $(SMALLOBJECTS) $(LIBNAME) -o $(SMALL) $(WARN)
-	
-x86_prof: library $(PROFS)
-	$(CC) $(PROFS) $(LIBNAME) $(EXTRALIBS) -o $(PROF)
-
-tv_gen: library $(TVS)
-	$(CC) $(TVS) $(LIBNAME) $(EXTRALIBS) -o $(TV)
-
-#This rule installs the library and the header files. This must be run
-#as root in order to have a high enough permission to write to the correct
-#directories and to set the owner and group to root.
-install: library docs
-	install -d -g root -o root $(DESTDIR)$(LIBPATH)
-	install -d -g root -o root $(DESTDIR)$(INCPATH)
-	install -d -g root -o root $(DESTDIR)$(DATAPATH)
-	install -g root -o root $(LIBNAME) $(DESTDIR)$(LIBPATH)
-	install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH)
-	install -g root -o root doc/crypt.pdf $(DESTDIR)$(DATAPATH)
-
-install_lib: library
-	install -d -g root -o root $(DESTDIR)$(LIBPATH)
-	install -d -g root -o root $(DESTDIR)$(INCPATH)
-	install -g root -o root $(LIBNAME) $(DESTDIR)$(LIBPATH)
-	install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH)
-
-#This rule cleans the source tree of all compiled code, not including the pdf
-#documentation.
-clean:
-	rm -f $(OBJECTS) $(TESTOBJECTS) $(HASHOBJECTS) $(CRYPTOBJECTS) $(SMALLOBJECTS) $(LEFTOVERS) $(LIBNAME)
-	rm -f $(TEST) $(HASH) $(COMPRESSED) $(PROFS) $(PROF) $(TVS) $(TV)
-	rm -f *.la *.lo *.o *.a *.dll *stackdump *.lib *.exe *.obj demos/*.obj demos/*.o *.bat *.txt *.il *.da demos/*.il demos/*.da *.dyn *.dpi \
-	*.gcda *.gcno demos/*.gcno demos/*.gcda *~ doc/*
-	cd demos/test ; make clean   
-	rm -rf .libs demos/.libs demos/test/.libs
-	
-#This builds the crypt.pdf file. Note that the rm -f *.pdf has been removed
-#from the clean command! This is because most people would like to keep the
-#nice pre-compiled crypt.pdf that comes with libtomcrypt! We only need to
-#delete it if we are rebuilding it.
-docs: crypt.tex
-	rm -f doc/crypt.pdf $(LEFTOVERS)
-	echo "hello" > crypt.ind
-	latex crypt > /dev/null
-	latex crypt > /dev/null
-	makeindex crypt.idx > /dev/null
-	latex crypt > /dev/null
-	dvipdf crypt
-	mv -ivf crypt.pdf doc/crypt.pdf
-	rm -f $(LEFTOVERS)
-
-docdvi: crypt.tex
-	echo hello > crypt.ind
-	latex crypt > /dev/null
-	latex crypt > /dev/null
-	makeindex crypt.idx
-	latex crypt > /dev/null
-
-#pretty build
-pretty:
-	perl pretty.build
-
-#for GCC 3.4+
-profiled:
-	make clean
-	make CFLAGS="$(CFLAGS) -fprofile-generate" EXTRALIBS=-lgcov x86_prof
-	./x86_prof
-	rm *.o *.a x86_prof
-	make CFLAGS="$(CFLAGS) -fprofile-use" EXTRALIBS=-lgcov x86_prof
-
-#zipup the project (take that!)
-zipup: clean docs
-	cd .. ; rm -rf crypt* libtomcrypt-$(VERSION) ; mkdir libtomcrypt-$(VERSION) ; \
-	cp -R ./libtomcrypt/* ./libtomcrypt-$(VERSION)/ ; tar -c libtomcrypt-$(VERSION)/* > crypt-$(VERSION).tar ; \
-	bzip2 -9vv crypt-$(VERSION).tar ; zip -9 -r crypt-$(VERSION).zip libtomcrypt-$(VERSION)/* ; \
-	gpg -b -a crypt-$(VERSION).tar.bz2 ; gpg -b -a crypt-$(VERSION).zip
--- a/mycrypt.h	Sun Dec 19 11:34:45 2004 +0000
+++ b/mycrypt.h	Sun Dec 19 11:47:33 2004 +0000
@@ -23,7 +23,8 @@
 #define MAXBLOCKSIZE  64
 
 /* descriptor table size */
-#define TAB_SIZE      32
+/* Dropbear change - this should be smaller, saves some size */
+#define TAB_SIZE    4
 
 /* error codes [will be expanded in future releases] */
 enum {
--- a/mycrypt_custom.h	Sun Dec 19 11:34:45 2004 +0000
+++ b/mycrypt_custom.h	Sun Dec 19 11:47:33 2004 +0000
@@ -5,6 +5,9 @@
 #ifndef MYCRYPT_CUSTOM_H_
 #define MYCRYPT_CUSTOM_H_
 
+/* this will sort out which stuff based on the user-config in options.h */
+#include "../options.h"
+
 /* macros for various libc functions you can change for embedded targets */
 #define XMALLOC  malloc
 #define XREALLOC realloc
@@ -17,11 +20,13 @@
 #define XCLOCK   clock
 #define XCLOCKS_PER_SEC CLOCKS_PER_SEC
 
-/* Use small code where possible */
-// #define SMALL_CODE
+#ifdef DROPBEAR_SMALL_CODE
+#define SMALL_CODE
+#endif
 
 /* Enable self-test test vector checking */
-#define LTC_TEST
+/* Not for dropbear */
+//#define LTC_TEST
 
 /* clean the stack of functions which put private information on stack */
 // #define CLEAN_STACK
@@ -29,131 +34,46 @@
 /* disable all file related functions */
 // #define NO_FILE
 
-/* various ciphers */
+#define CLEAN_STACK
+
+#ifdef DROPBEAR_BLOWFISH_CBC
 #define BLOWFISH
-#define RC2
-#define RC5
-#define RC6
-#define SAFERP
+#endif
+
+#ifdef DROPBEAR_AES128_CBC
 #define RIJNDAEL
-#define XTEA
-/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format
- * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */
+#endif
+
+#ifdef DROPBEAR_TWOFISH128_CBC
 #define TWOFISH
-#define TWOFISH_TABLES
-// #define TWOFISH_ALL_TABLES
-// #define TWOFISH_SMALL
-/* DES includes EDE triple-DES */
-#define DES
-#define CAST5
-#define NOEKEON
-#define SKIPJACK
-/* SAFER code isn't public domain.  It appears to be free to use 
- * but has been disabled by default to avoid any such problems 
- */
-//#define SAFER
 
-/* block cipher modes of operation */
-#define CFB
-#define OFB
-#define ECB
+/* enabling just TWOFISH_SMALL will make the binary ~1kB smaller, turning on
+ * TWOFISH_TABLES will make it a few kB bigger, but perhaps reduces runtime
+ * memory usage? */
+#define TWOFISH_SMALL
+/*#define TWOFISH_TABLES*/
+#endif
+
+#ifdef DROPBEAR_3DES_CBC
+#define DES
+#endif
 #define CBC
-#define CTR
 
-/* hash functions */
-#define CHC_HASH
-#define WHIRLPOOL
+#if defined(DROPBEAR_DSS) && defined(DSS_PROTOK)
 #define SHA512
-#define SHA384
-#define SHA256
-#define SHA224
-#define TIGER
+#endif
+
 #define SHA1
+
+#ifdef DROPBEAR_MD5_HMAC
 #define MD5
-#define MD4
-#define MD2
-#define RIPEMD128
-#define RIPEMD160
+#endif
 
-/* MAC functions */
 #define HMAC
-#define OMAC
-#define PMAC
-
-/* Encrypt + Authenticate Modes */
-#define EAX_MODE
-#define OCB_MODE
 
 /* Various tidbits of modern neatoness */
 #define BASE64
 
-/* Yarrow */
-#define YARROW
-// which descriptor of AES to use? 
-// 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full]
-#define YARROW_AES 0
-
-#if defined(YARROW) && !defined(CTR)
-   #error YARROW requires CTR chaining mode to be defined!
-#endif
-
-#define SPRNG
-#define RC4
-
-/* Fortuna PRNG */
-#define FORTUNA
-/* reseed every N calls to the read function */
-#define FORTUNA_WD    10
-/* number of pools (4..32) can save a bit of ram by lowering the count */
-#define FORTUNA_POOLS 32
-
-/* Greg's SOBER128 PRNG ;-0 */
-#define SOBER128
-
-#define DEVRANDOM
-#define TRY_URANDOM_FIRST
-
-/* Public Key Neatoness */
-#define MRSA
-/* enable RSA side channel timing prevention */
-#define RSA_TIMING
-
-/* Digital Signature Algorithm */
-#define MDSA
-/* Max diff between group and modulus size in bytes */
-#define MDSA_DELTA     512
-/* Max DSA group size in bytes (default allows 4k-bit groups) */
-#define MDSA_MAX_GROUP 512
-
-/* Diffie-Hellman */
-#define MDH
-/* Supported Key Sizes */
-#define DH768
-#define DH1024
-#define DH1280
-#define DH1536
-#define DH1792
-#define DH2048
-#define DH2560
-#define DH3072
-#define DH4096
-
-/* ECC */
-#define MECC
-/* Supported Key Sizes */
-#define ECC160
-#define ECC192
-#define ECC224
-#define ECC256
-#define ECC384
-#define ECC521
-
-/* Include the MPI functionality?  (required by the PK algorithms) */
-#define MPI
-
-/* PKCS #1 (RSA) and #5 (Password Handling) stuff */
-#define PKCS_1
-#define PKCS_5
 
 #endif
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mycrypt_gf.h	Sun Dec 19 11:47:33 2004 +0000
@@ -0,0 +1,32 @@
+
+/* ---- GF(2^w) polynomial basis ---- */
+#ifdef GF
+#define   LSIZE    32   /* handle upto 1024-bit GF numbers */
+
+typedef unsigned long gf_int[LSIZE];
+typedef unsigned long *gf_intp;
+
+extern void gf_copy(gf_intp a, gf_intp b);
+extern void gf_zero(gf_intp a);
+extern int gf_iszero(gf_intp a);
+extern int gf_isone(gf_intp a);
+extern int gf_deg(gf_intp a);
+
+extern void gf_shl(gf_intp a, gf_intp b);
+extern void gf_shr(gf_intp a, gf_intp b);
+extern void gf_add(gf_intp a, gf_intp b, gf_intp c);
+extern void gf_mul(gf_intp a, gf_intp b, gf_intp c);
+extern void gf_div(gf_intp a, gf_intp b, gf_intp q, gf_intp r);
+
+extern void gf_mod(gf_intp a, gf_intp m, gf_intp b);
+extern void gf_mulmod(gf_intp a, gf_intp b, gf_intp m, gf_intp c);
+extern void gf_invmod(gf_intp A, gf_intp M, gf_intp B);
+extern void gf_sqrt(gf_intp a, gf_intp M, gf_intp b);
+extern void gf_gcd(gf_intp A, gf_intp B, gf_intp c);
+extern int gf_is_prime(gf_intp a);
+
+extern int gf_size(gf_intp a);
+extern void gf_toraw(gf_intp a, unsigned char *dst);
+extern void gf_readraw(gf_intp a, unsigned char *str, int len);
+
+#endif
--- a/mycrypt_misc.h	Sun Dec 19 11:34:45 2004 +0000
+++ b/mycrypt_misc.h	Sun Dec 19 11:47:33 2004 +0000
@@ -14,4 +14,7 @@
  const char *error_to_string(int err);
  int mpi_to_ltc_error(int err);
 
- extern const char *crypt_build_settings;
+#if 0
+/* Takes up space we don\'t need for Dropbear */
+extern const char *crypt_build_settings;
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rsa.c	Sun Dec 19 11:47:33 2004 +0000
@@ -0,0 +1,273 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+
+/* RSA Code by Tom St Denis */
+#include "mycrypt.h"
+
+#ifdef MRSA
+
+int rsa_signpad(const unsigned char *in,  unsigned long inlen,
+                      unsigned char *out, unsigned long *outlen)
+{
+   unsigned long x, y;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   if (*outlen < (3 * inlen)) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* check inlen */
+   if (inlen > MAX_RSA_SIZE/8) {
+      return CRYPT_PK_INVALID_SIZE;
+   }
+
+   for (y = x = 0; x < inlen; x++)
+       out[y++] = (unsigned char)0xFF;
+   for (x = 0; x < inlen; x++)
+       out[y++] = in[x];
+   for (x = 0; x < inlen; x++)
+       out[y++] = (unsigned char)0xFF;
+   *outlen = 3 * inlen;
+   return CRYPT_OK;
+}
+
+int rsa_pad(const unsigned char *in,  unsigned long inlen,
+                  unsigned char *out, unsigned long *outlen,
+                  int wprng, prng_state *prng)
+{
+   unsigned char buf[3*(MAX_RSA_SIZE/8)];
+   unsigned long x;
+   int err;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* is output big enough? */
+   if (*outlen < (3 * inlen)) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* get random padding required */
+   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* check inlen */
+   if (inlen > (MAX_RSA_SIZE/8)) {
+      return CRYPT_PK_INVALID_SIZE;
+   }
+
+   if (prng_descriptor[wprng].read(buf, inlen*2-2, prng) != (inlen*2 - 2))  {
+       return CRYPT_ERROR_READPRNG;
+   }
+
+   /* pad it like a sandwhich
+    *
+    * Looks like 0xFF R1 M R2 0xFF
+    *
+    * Where R1/R2 are random and exactly equal to the length of M minus one byte.
+    */
+   for (x = 0; x < inlen-1; x++) {
+       out[x+1] = buf[x];
+   }
+
+   for (x = 0; x < inlen; x++) {
+       out[x+inlen] = in[x];
+   }
+
+   for (x = 0; x < inlen-1; x++) {
+       out[x+inlen+inlen] = buf[x+inlen-1];
+   }
+
+   /* last and first bytes are 0xFF */
+   out[0] = out[inlen+inlen+inlen-1] = (unsigned char)0xFF;
+
+   /* clear up and return */
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+   *outlen = inlen*3;
+   return CRYPT_OK;
+}
+
+int rsa_signdepad(const unsigned char *in,  unsigned long inlen,
+                        unsigned char *out, unsigned long *outlen)
+{
+   unsigned long x;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   if (*outlen < inlen/3) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* check padding bytes */
+   for (x = 0; x < inlen/3; x++) {
+       if (in[x] != (unsigned char)0xFF || in[x+(inlen/3)+(inlen/3)] != (unsigned char)0xFF) {
+          return CRYPT_INVALID_PACKET;
+       }
+   }
+   for (x = 0; x < inlen/3; x++) {
+       out[x] = in[x+(inlen/3)];
+   }
+   *outlen = inlen/3;
+   return CRYPT_OK;
+}
+
+int rsa_depad(const unsigned char *in,  unsigned long inlen,
+                    unsigned char *out, unsigned long *outlen)
+{
+   unsigned long x;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   if (*outlen < inlen/3) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+   for (x = 0; x < inlen/3; x++) {
+       out[x] = in[x+(inlen/3)];
+   }
+   *outlen = inlen/3;
+   return CRYPT_OK;
+}
+
+int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key)
+{
+   unsigned long y, z; 
+   int err;
+
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(key    != NULL);
+   
+   /* can we store the static header?  */
+   if (*outlen < (PACKET_SIZE + 1)) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }   
+
+   /* type valid? */
+   if (!(key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) &&
+        (type == PK_PRIVATE || type == PK_PRIVATE_OPTIMIZED)) {
+      return CRYPT_PK_INVALID_TYPE;
+   }
+
+   /* start at offset y=PACKET_SIZE */
+   y = PACKET_SIZE;
+
+   /* output key type */
+   out[y++] = type;
+
+   /* output modulus */
+   OUTPUT_BIGNUM(&key->N, out, y, z);
+
+   /* output public key */
+   OUTPUT_BIGNUM(&key->e, out, y, z);
+
+   if (type == PK_PRIVATE || type == PK_PRIVATE_OPTIMIZED) {
+      OUTPUT_BIGNUM(&key->d, out, y, z);
+   }
+
+   if (type == PK_PRIVATE_OPTIMIZED) {
+      OUTPUT_BIGNUM(&key->dQ, out, y, z);
+      OUTPUT_BIGNUM(&key->dP, out, y, z);
+      OUTPUT_BIGNUM(&key->pQ, out, y, z);
+      OUTPUT_BIGNUM(&key->qP, out, y, z);
+      OUTPUT_BIGNUM(&key->p, out, y, z);
+      OUTPUT_BIGNUM(&key->q, out, y, z);
+   }
+
+   /* store packet header */
+   packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_KEY);
+
+   /* copy to the user buffer */
+   *outlen = y;
+
+   /* clear stack and return */
+   return CRYPT_OK;
+}
+
+int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+   unsigned long x, y;
+   int err;
+
+   _ARGCHK(in  != NULL);
+   _ARGCHK(key != NULL);
+
+   /* check length */
+   if (inlen < (1+PACKET_SIZE)) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* test packet header */
+   if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_KEY)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* init key */
+   if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP,
+                     &key->pQ, &key->p, &key->q, NULL)) != MP_OKAY) {
+      return mpi_to_ltc_error(err);
+   }
+
+   /* get key type */
+   y = PACKET_SIZE;
+   key->type = (int)in[y++];
+
+   /* load the modulus  */
+   INPUT_BIGNUM(&key->N, in, x, y, inlen);
+
+   /* load public exponent */
+   INPUT_BIGNUM(&key->e, in, x, y, inlen);
+
+   /* get private exponent */
+   if (key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) {
+      INPUT_BIGNUM(&key->d, in, x, y, inlen);
+   }
+
+   /* get CRT private data if required */
+   if (key->type == PK_PRIVATE_OPTIMIZED) {
+      INPUT_BIGNUM(&key->dQ, in, x, y, inlen);
+      INPUT_BIGNUM(&key->dP, in, x, y, inlen);
+      INPUT_BIGNUM(&key->pQ, in, x, y, inlen);
+      INPUT_BIGNUM(&key->qP, in, x, y, inlen);
+      INPUT_BIGNUM(&key->p, in, x, y, inlen);
+      INPUT_BIGNUM(&key->q, in, x, y, inlen);
+   }
+
+   /* free up ram not required */
+   if (key->type != PK_PRIVATE_OPTIMIZED) {
+      mp_clear_multi(&key->dQ, &key->dP, &key->pQ, &key->qP, &key->p, &key->q, NULL);
+   }
+   if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) {
+      mp_clear(&key->d);
+   }
+
+   return CRYPT_OK;
+error:
+   mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,
+                  &key->pQ, &key->qP, &key->p, &key->q, NULL);
+   return err;
+}
+
+#include "rsa_sys.c"
+
+#endif /* RSA */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rsa_sys.c	Sun Dec 19 11:47:33 2004 +0000
@@ -0,0 +1,274 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+
+/* these are smaller routines written by Clay Culver.  They do the same function as the rsa_encrypt/decrypt 
+ * except that they are used to RSA encrypt/decrypt a single value and not a packet.
+ */
+int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen,
+                    unsigned char *outkey, unsigned long *outlen,
+                    prng_state *prng, int wprng, rsa_key *key)
+{
+   unsigned char rsa_in[RSA_STACK], rsa_out[RSA_STACK];
+   unsigned long x, y, rsa_size;
+   int err;
+
+   _ARGCHK(inkey  != NULL);
+   _ARGCHK(outkey != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(key    != NULL);
+   
+   /* only allow keys from 64 to 256 bits */
+   if (inlen < 8 || inlen > 32) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* are the parameters valid? */
+   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+      return err; 
+   }
+
+   /* rsa_pad the symmetric key */
+   y = (unsigned long)sizeof(rsa_in); 
+   if ((err = rsa_pad(inkey, inlen, rsa_in, &y, wprng, prng)) != CRYPT_OK) {
+      return CRYPT_ERROR;
+   }
+   
+   /* rsa encrypt it */
+   rsa_size = (unsigned long)sizeof(rsa_out);
+   if ((err = rsa_exptmod(rsa_in, y, rsa_out, &rsa_size, PK_PUBLIC, key)) != CRYPT_OK) {
+      return CRYPT_ERROR;
+   }
+
+   /* check size */
+   if (*outlen < (PACKET_SIZE+4+rsa_size)) { 
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* store header */
+   packet_store_header(outkey, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY);
+
+   /* now lets make the header */
+   y = PACKET_SIZE;
+   
+   /* store the size of the RSA value */
+   STORE32L(rsa_size, (outkey+y));
+   y += 4;
+
+   /* store the rsa value */
+   for (x = 0; x < rsa_size; x++, y++) {
+       outkey[y] = rsa_out[x];
+   }
+
+   *outlen = y;
+#ifdef CLEAN_STACK
+   /* clean up */
+   zeromem(rsa_in, sizeof(rsa_in));
+   zeromem(rsa_out, sizeof(rsa_out));
+#endif
+
+   return CRYPT_OK;
+}
+
+int rsa_decrypt_key(const unsigned char *in, unsigned long inlen,
+                          unsigned char *outkey, unsigned long *keylen, 
+                          rsa_key *key)
+{
+   unsigned char sym_key[MAXBLOCKSIZE], rsa_out[RSA_STACK];
+   unsigned long x, y, z, i, rsa_size;
+   int err;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(outkey != NULL);
+   _ARGCHK(keylen != NULL);
+   _ARGCHK(key    != NULL);
+
+   /* right key type? */
+   if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   if (inlen < PACKET_SIZE+4) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= PACKET_SIZE+4;
+   }
+
+   /* check the header */
+   if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* grab length of the rsa key */
+   y = PACKET_SIZE;
+   LOAD32L(rsa_size, (in+y));
+   if (inlen < rsa_size) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= rsa_size;
+   }
+   y += 4;
+
+   /* decrypt it */
+   x = (unsigned long)sizeof(rsa_out);
+   if ((err = rsa_exptmod(in+y, rsa_size, rsa_out, &x, PK_PRIVATE, key)) != CRYPT_OK) {
+      return err;
+   }
+   y += rsa_size;
+
+   /* depad it */
+   z = (unsigned long)sizeof(sym_key);
+   if ((err = rsa_depad(rsa_out, x, sym_key, &z)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* check size */
+   if (*keylen < z) { 
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   for (i = 0; i < z; i++) {
+     outkey[i] = sym_key[i];
+   }
+   
+#ifdef CLEAN_STACK
+   /* clean up */
+   zeromem(sym_key, sizeof(sym_key));
+   zeromem(rsa_out, sizeof(rsa_out));
+#endif
+   *keylen = z;
+   return CRYPT_OK;
+}
+
+int rsa_sign_hash(const unsigned char *in,  unsigned long inlen, 
+                        unsigned char *out, unsigned long *outlen, 
+                        rsa_key *key)
+{
+   unsigned long rsa_size, x, y;
+   unsigned char rsa_in[RSA_STACK], rsa_out[RSA_STACK];
+   int err;
+
+   _ARGCHK(in     != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(key    != NULL);
+   
+   /* reject nonsense sizes */
+   if (inlen > (512/3) || inlen < 16) {
+      return CRYPT_INVALID_ARG;
+   }
+
+   /* type of key? */
+   if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+
+   /* pad it */
+   x = (unsigned long)sizeof(rsa_out);
+   if ((err = rsa_signpad(in, inlen, rsa_out, &x)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* sign it */
+   rsa_size = (unsigned long)sizeof(rsa_in);
+   if ((err = rsa_exptmod(rsa_out, x, rsa_in, &rsa_size, PK_PRIVATE, key)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* check size */
+   if (*outlen < (PACKET_SIZE+4+rsa_size)) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* now lets output the message */
+   y = PACKET_SIZE;
+
+   /* output the len */
+   STORE32L(rsa_size, (out+y));
+   y += 4;
+
+   /* store the signature */
+   for (x = 0; x < rsa_size; x++, y++) {
+       out[y] = rsa_in[x];
+   }
+
+   /* store header */
+   packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_SIGNED);
+
+#ifdef CLEAN_STACK
+   /* clean up */
+   zeromem(rsa_in, sizeof(rsa_in));
+   zeromem(rsa_out, sizeof(rsa_out));
+#endif
+   *outlen = y;
+   return CRYPT_OK;
+}
+
+int rsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+                    const unsigned char *md, int *stat, rsa_key *key)
+{
+   unsigned long rsa_size, x, y, z;
+   unsigned char rsa_in[RSA_STACK], rsa_out[RSA_STACK];
+   int err;
+
+   _ARGCHK(sig  != NULL);
+   _ARGCHK(md   != NULL);
+   _ARGCHK(stat != NULL);
+   _ARGCHK(key  != NULL);
+
+   /* always be incorrect by default */
+   *stat = 0;
+   
+   if (siglen < PACKET_SIZE+4) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      siglen -= PACKET_SIZE+4;
+   }
+
+   /* verify header */
+   if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_RSA, PACKET_SUB_SIGNED)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* get the len */
+   y = PACKET_SIZE;
+   LOAD32L(rsa_size, (sig+y));
+   if (siglen < rsa_size) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      siglen -= rsa_size;
+   }
+   y += 4;
+
+   /* exptmod it */
+   x = (unsigned long)sizeof(rsa_out);
+   if ((err = rsa_exptmod(sig+y, rsa_size, rsa_out, &x, PK_PUBLIC, key)) != CRYPT_OK) {
+      return err;
+   }
+   y += rsa_size;
+
+   /* depad it */
+   z = (unsigned long)sizeof(rsa_in);
+   if ((err = rsa_signdepad(rsa_out, x, rsa_in, &z)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* check? */
+   if (memcmp(rsa_in, md, (size_t)z) == 0) {
+      *stat = 1;
+   }
+
+#ifdef CLEAN_STACK
+   zeromem(rsa_in, sizeof(rsa_in));
+   zeromem(rsa_out, sizeof(rsa_out));
+#endif
+   return CRYPT_OK;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/serpent.c	Sun Dec 19 11:47:33 2004 +0000
@@ -0,0 +1,698 @@
+#include "mycrypt.h"
+
+#ifdef SERPENT
+
+const struct _cipher_descriptor serpent_desc =
+{
+    "serpent",
+    5,
+    16, 32, 16, 32,
+    &serpent_setup,
+    &serpent_ecb_encrypt,
+    &serpent_ecb_decrypt,
+    &serpent_test,
+    &serpent_keysize
+};
+
+/* These defines are derived from Brian Gladman's work.  Contact him at [email protected] 
+ *
+ * Available on the web at http://fp.gladman.plus.com/cryptography_technology/aes/index.htm
+ */
+#define sb0(a,b,c,d,e,f,g,h)    \
+    t1 = a ^ d;     \
+    t2 = a & d;     \
+    t3 = c ^ t1;    \
+    t6 = b & t1;    \
+    t4 = b ^ t3;    \
+    t10 = ~t3;      \
+    h = t2 ^ t4;    \
+    t7 = a ^ t6;    \
+    t14 = ~t7;      \
+    t8 = c | t7;    \
+    t11 = t3 ^ t7;  \
+    g = t4 ^ t8;    \
+    t12 = h & t11;  \
+    f = t10 ^ t12;  \
+    e = t12 ^ t14
+
+/* 15 terms */
+
+#define ib0(a,b,c,d,e,f,g,h)    \
+    t1 = ~a;        \
+    t2 = a ^ b;     \
+    t3 = t1 | t2;   \
+    t4 = d ^ t3;    \
+    t7 = d & t2;    \
+    t5 = c ^ t4;    \
+    t8 = t1 ^ t7;   \
+    g = t2 ^ t5;    \
+    t11 = a & t4;   \
+    t9 = g & t8;    \
+    t14 = t5 ^ t8;  \
+    f = t4 ^ t9;    \
+    t12 = t5 | f;   \
+    h = t11 ^ t12;  \
+    e = h ^ t14
+
+/* 14 terms!  */
+
+#define sb1(a,b,c,d,e,f,g,h)    \
+    t1 = ~a;        \
+    t2 = b ^ t1;    \
+    t3 = a | t2;    \
+    t4 = d | t2;    \
+    t5 = c ^ t3;    \
+    g = d ^ t5;     \
+    t7 = b ^ t4;    \
+    t8 = t2 ^ g;    \
+    t9 = t5 & t7;   \
+    h = t8 ^ t9;    \
+    t11 = t5 ^ t7;  \
+    f = h ^ t11;    \
+    t13 = t8 & t11; \
+    e = t5 ^ t13
+
+/* 17 terms */
+
+#define ib1(a,b,c,d,e,f,g,h)    \
+    t1 = a ^ d;     \
+    t2 = a & b;     \
+    t3 = b ^ c;     \
+    t4 = a ^ t3;    \
+    t5 = b | d;     \
+    t7 = c | t1;    \
+    h = t4 ^ t5;    \
+    t8 = b ^ t7;    \
+    t11 = ~t2;      \
+    t9 = t4 & t8;   \
+    f = t1 ^ t9;    \
+    t13 = t9 ^ t11; \
+    t12 = h & f;    \
+    g = t12 ^ t13;  \
+    t15 = a & d;    \
+    t16 = c ^ t13;  \
+    e = t15 ^ t16
+
+/* 16 terms */
+
+#define sb2(a,b,c,d,e,f,g,h)    \
+    t1 = ~a;        \
+    t2 = b ^ d;     \
+    t3 = c & t1;    \
+    t13 = d | t1;   \
+    e = t2 ^ t3;    \
+    t5 = c ^ t1;    \
+    t6 = c ^ e;     \
+    t7 = b & t6;    \
+    t10 = e | t5;   \
+    h = t5 ^ t7;    \
+    t9 = d | t7;    \
+    t11 = t9 & t10; \
+    t14 = t2 ^ h;   \
+    g = a ^ t11;    \
+    t15 = g ^ t13;  \
+    f = t14 ^ t15
+
+/* 16 terms */
+
+#define ib2(a,b,c,d,e,f,g,h)    \
+    t1 = b ^ d;     \
+    t2 = ~t1;       \
+    t3 = a ^ c;     \
+    t4 = c ^ t1;    \
+    t7 = a | t2;    \
+    t5 = b & t4;    \
+    t8 = d ^ t7;    \
+    t11 = ~t4;      \
+    e = t3 ^ t5;    \
+    t9 = t3 | t8;   \
+    t14 = d & t11;  \
+    h = t1 ^ t9;    \
+    t12 = e | h;    \
+    f = t11 ^ t12;  \
+    t15 = t3 ^ t12; \
+    g = t14 ^ t15
+
+/* 17 terms */
+
+#define sb3(a,b,c,d,e,f,g,h)    \
+    t1 = a ^ c;     \
+    t2 = d ^ t1;    \
+    t3 = a & t2;    \
+    t4 = d ^ t3;    \
+    t5 = b & t4;    \
+    g = t2 ^ t5;    \
+    t7 = a | g;     \
+    t8 = b | d;     \
+    t11 = a | d;    \
+    t9 = t4 & t7;   \
+    f = t8 ^ t9;    \
+    t12 = b ^ t11;  \
+    t13 = g ^ t9;   \
+    t15 = t3 ^ t8;  \
+    h = t12 ^ t13;  \
+    t16 = c & t15;  \
+    e = t12 ^ t16
+
+/* 16 term solution that performs less well than 17 term one
+   in my environment (PPro/PII)                                  
+
+#define sb3(a,b,c,d,e,f,g,h)    \
+    t1 = a ^ b;     \
+    t2 = a & c;     \
+    t3 = a | d;     \
+    t4 = c ^ d;     \
+    t5 = t1 & t3;   \
+    t6 = t2 | t5;   \
+    g = t4 ^ t6;    \
+    t8 = b ^ t3;    \
+    t9 = t6 ^ t8;   \
+    t10 = t4 & t9;  \
+    e = t1 ^ t10;   \
+    t12 = g & e;    \
+    f = t9 ^ t12;   \
+    t14 = b | d;    \
+    t15 = t4 ^ t12; \
+    h = t14 ^ t15
+*/
+
+/* 17 terms */
+
+#define ib3(a,b,c,d,e,f,g,h)    \
+    t1 = b ^ c;     \
+    t2 = b | c;     \
+    t3 = a ^ c;     \
+    t7 = a ^ d;     \
+    t4 = t2 ^ t3;   \
+    t5 = d | t4;    \
+    t9 = t2 ^ t7;   \
+    e = t1 ^ t5;    \
+    t8 = t1 | t5;   \
+    t11 = a & t4;   \
+    g = t8 ^ t9;    \
+    t12 = e | t9;   \
+    f = t11 ^ t12;  \
+    t14 = a & g;    \
+    t15 = t2 ^ t14; \
+    t16 = e & t15;  \
+    h = t4 ^ t16
+
+/* 15 terms */
+
+#define sb4(a,b,c,d,e,f,g,h)    \
+    t1 = a ^ d;     \
+    t2 = d & t1;    \
+    t3 = c ^ t2;    \
+    t4 = b | t3;    \
+    h = t1 ^ t4;    \
+    t6 = ~b;        \
+    t7 = t1 | t6;   \
+    e = t3 ^ t7;    \
+    t9 = a & e;     \
+    t10 = t1 ^ t6;  \
+    t11 = t4 & t10; \
+    g = t9 ^ t11;   \
+    t13 = a ^ t3;   \
+    t14 = t10 & g;  \
+    f = t13 ^ t14
+
+/* 17 terms */
+
+#define ib4(a,b,c,d,e,f,g,h)    \
+    t1 = c ^ d;     \
+    t2 = c | d;     \
+    t3 = b ^ t2;    \
+    t4 = a & t3;    \
+    f = t1 ^ t4;    \
+    t6 = a ^ d;     \
+    t7 = b | d;     \
+    t8 = t6 & t7;   \
+    h = t3 ^ t8;    \
+    t10 = ~a;       \
+    t11 = c ^ h;    \
+    t12 = t10 | t11;\
+    e = t3 ^ t12;   \
+    t14 = c | t4;   \
+    t15 = t7 ^ t14; \
+    t16 = h | t10;  \
+    g = t15 ^ t16
+
+/* 16 terms */
+
+#define sb5(a,b,c,d,e,f,g,h)    \
+    t1 = ~a;        \
+    t2 = a ^ b;     \
+    t3 = a ^ d;     \
+    t4 = c ^ t1;    \
+    t5 = t2 | t3;   \
+    e = t4 ^ t5;    \
+    t7 = d & e;     \
+    t8 = t2 ^ e;    \
+    t10 = t1 | e;   \
+    f = t7 ^ t8;    \
+    t11 = t2 | t7;  \
+    t12 = t3 ^ t10; \
+    t14 = b ^ t7;   \
+    g = t11 ^ t12;  \
+    t15 = f & t12;  \
+    h = t14 ^ t15
+
+/* 16 terms */
+
+#define ib5(a,b,c,d,e,f,g,h)    \
+    t1 = ~c;        \
+    t2 = b & t1;    \
+    t3 = d ^ t2;    \
+    t4 = a & t3;    \
+    t5 = b ^ t1;    \
+    h = t4 ^ t5;    \
+    t7 = b | h;     \
+    t8 = a & t7;    \
+    f = t3 ^ t8;    \
+    t10 = a | d;    \
+    t11 = t1 ^ t7;  \
+    e = t10 ^ t11;  \
+    t13 = a ^ c;    \
+    t14 = b & t10;  \
+    t15 = t4 | t13; \
+    g = t14 ^ t15
+
+/* 15 terms */
+
+#define sb6(a,b,c,d,e,f,g,h)    \
+    t1 = ~a;        \
+    t2 = a ^ d;     \
+    t3 = b ^ t2;    \
+    t4 = t1 | t2;   \
+    t5 = c ^ t4;    \
+    f = b ^ t5;     \
+    t13 = ~t5;      \
+    t7 = t2 | f;    \
+    t8 = d ^ t7;    \
+    t9 = t5 & t8;   \
+    g = t3 ^ t9;    \
+    t11 = t5 ^ t8;  \
+    e = g ^ t11;    \
+    t14 = t3 & t11; \
+    h = t13 ^ t14
+
+/* 15 terms */
+
+#define ib6(a,b,c,d,e,f,g,h)    \
+    t1 = ~a;        \
+    t2 = a ^ b;     \
+    t3 = c ^ t2;    \
+    t4 = c | t1;    \
+    t5 = d ^ t4;    \
+    t13 = d & t1;   \
+    f = t3 ^ t5;    \
+    t7 = t3 & t5;   \
+    t8 = t2 ^ t7;   \
+    t9 = b | t8;    \
+    h = t5 ^ t9;    \
+    t11 = b | h;    \
+    e = t8 ^ t11;   \
+    t14 = t3 ^ t11; \
+    g = t13 ^ t14
+
+/* 17 terms */
+
+#define sb7(a,b,c,d,e,f,g,h)    \
+    t1 = ~c;        \
+    t2 = b ^ c;     \
+    t3 = b | t1;    \
+    t4 = d ^ t3;    \
+    t5 = a & t4;    \
+    t7 = a ^ d;     \
+    h = t2 ^ t5;    \
+    t8 = b ^ t5;    \
+    t9 = t2 | t8;   \
+    t11 = d & t3;   \
+    f = t7 ^ t9;    \
+    t12 = t5 ^ f;   \
+    t15 = t1 | t4;  \
+    t13 = h & t12;  \
+    g = t11 ^ t13;  \
+    t16 = t12 ^ g;  \
+    e = t15 ^ t16
+
+/* 17 terms */
+
+#define ib7(a,b,c,d,e,f,g,h)    \
+    t1 = a & b;     \
+    t2 = a | b;     \
+    t3 = c | t1;    \
+    t4 = d & t2;    \
+    h = t3 ^ t4;    \
+    t6 = ~d;        \
+    t7 = b ^ t4;    \
+    t8 = h ^ t6;    \
+    t11 = c ^ t7;   \
+    t9 = t7 | t8;   \
+    f = a ^ t9;     \
+    t12 = d | f;    \
+    e = t11 ^ t12;  \
+    t14 = a & h;    \
+    t15 = t3 ^ f;   \
+    t16 = e ^ t14;  \
+    g = t15 ^ t16
+
+#define k_xor(r,a,b,c,d)             \
+    a ^= skey->serpent.K[4 * (r) + 0]; \
+    b ^= skey->serpent.K[4 * (r) + 1]; \
+    c ^= skey->serpent.K[4 * (r) + 2]; \
+    d ^= skey->serpent.K[4 * (r) + 3]
+
+#define k_set(r,a,b,c,d)   \
+    a = lkey[4 * (r) +  8];  \
+    b = lkey[4 * (r) +  9];  \
+    c = lkey[4 * (r) + 10];  \
+    d = lkey[4 * (r) + 11]
+
+#define k_get(r,a,b,c,d)            \
+    skey->serpent.K[4 * (r) + 0] = a; \
+    skey->serpent.K[4 * (r) + 1] = b; \
+    skey->serpent.K[4 * (r) + 2] = c; \
+    skey->serpent.K[4 * (r) + 3] = d
+
+/* the linear transformation and its inverse    */
+
+#define rot(a,b,c,d)    \
+    a = ROL(a, 13);    \
+    c = ROL(c, 3);     \
+    d ^= c ^ (a << 3);  \
+    b ^= a ^ c;         \
+    d = ROL(d, 7);     \
+    b = ROL(b, 1);     \
+    a ^= b ^ d;         \
+    c ^= d ^ (b << 7);  \
+    a = ROL(a, 5);     \
+    c = ROL(c, 22)
+
+#define irot(a,b,c,d)   \
+    c = ROR(c, 22);    \
+    a = ROR(a, 5);     \
+    c ^= d ^ (b << 7);  \
+    a ^= b ^ d;         \
+    d = ROR(d, 7);     \
+    b = ROR(b, 1);     \
+    d ^= c ^ (a << 3);  \
+    b ^= a ^ c;         \
+    c = ROR(c, 3);     \
+    a = ROR(a, 13)
+    
+#ifdef CLEAN_STACK
+static int _serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#else
+int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+#endif
+{
+    unsigned long lkey[140], t, a, b, c, d, e, f, g, h, x;
+    unsigned long t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16;
+    unsigned char buf[32];
+
+    _ARGCHK(key != NULL);
+    _ARGCHK(skey != NULL);
+
+    /* check rounds */
+    if (num_rounds != 0 && num_rounds != 32) {
+       return CRYPT_INVALID_ROUNDS;
+    }
+
+    /* check keylen */
+    if (keylen < 16 || keylen > 32) {
+       return CRYPT_INVALID_KEYSIZE;
+    }
+
+    /* copy key and expand to 32bytes as required */
+    for (x = 0; x < (unsigned long)keylen; x++) {
+        buf[x] = key[x];
+    }
+
+    if (x < 32) {
+       buf[x++] = (unsigned char)0x01;
+       while (x < 32) {
+           buf[x++] = (unsigned char)0;
+       }
+    }
+
+    /* copy key into 32-bit words */
+    for (x = 0; x < 8; x++) {
+        LOAD32L(lkey[x], &buf[x*4]);
+    }
+
+    /* expand using the LFSR to 140 words */
+    for (x = 0; x < 132; x++) {
+        t = lkey[x] ^ lkey[x+3] ^ lkey[x+5] ^ lkey[x+7] ^ x ^ 0x9E3779B9UL;
+        lkey[x + 8] = ROL(t, 11);
+    }
+
+    /* perform the substituions */
+    for (x = 0; x < 32; ) {
+       k_set( x,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x;
+       k_set( x,a,b,c,d);sb2(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x;
+       k_set( x,a,b,c,d);sb1(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x;
+       k_set( x,a,b,c,d);sb0(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x;
+       k_set( x,a,b,c,d);sb7(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x;
+       k_set( x,a,b,c,d);sb6(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x;
+       k_set( x,a,b,c,d);sb5(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x;
+       k_set( x,a,b,c,d);sb4(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x;
+    }
+    k_set(32,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get(32,e,f,g,h);
+    return CRYPT_OK;
+}
+
+#ifdef CLEAN_STACK
+int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+   int x;
+   x = _serpent_setup(key, keylen, num_rounds, skey);
+   burn_stack(sizeof(unsigned long)*166 + sizeof(unsigned char)*32);
+   return x;
+}
+#endif
+
+#ifdef CLEAN_STACK
+static void _serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
+#else
+void serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
+#endif
+{
+    unsigned long a,b,c,d,e,f,g,h;
+    unsigned long t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16;
+
+    _ARGCHK(pt != NULL);
+    _ARGCHK(ct != NULL);
+    _ARGCHK(skey != NULL);
+
+    LOAD32L(a, &pt[0]);LOAD32L(b, &pt[4]);LOAD32L(c, &pt[8]);LOAD32L(d, &pt[12]);
+    k_xor( 0,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);
+    k_xor( 1,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);
+    k_xor( 2,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);
+    k_xor( 3,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);
+    k_xor( 4,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);
+    k_xor( 5,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);
+    k_xor( 6,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);
+    k_xor( 7,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d);
+    k_xor( 8,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);
+    k_xor( 9,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d); 
+    k_xor(10,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);
+    k_xor(11,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);
+    k_xor(12,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);
+    k_xor(13,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);
+    k_xor(14,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);
+    k_xor(15,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d);
+    k_xor(16,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);
+    k_xor(17,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);
+    k_xor(18,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);
+    k_xor(19,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);
+    k_xor(20,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);
+    k_xor(21,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);
+    k_xor(22,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);
+    k_xor(23,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d);
+    k_xor(24,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);
+    k_xor(25,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);
+    k_xor(26,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);
+    k_xor(27,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);
+    k_xor(28,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);
+    k_xor(29,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);
+    k_xor(30,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);
+    k_xor(31,e,f,g,h); sb7(e,f,g,h,a,b,c,d); k_xor(32,a,b,c,d);
+    STORE32L(a, &ct[0]);STORE32L(b, &ct[4]);STORE32L(c, &ct[8]);STORE32L(d, &ct[12]);
+}
+
+#ifdef CLEAN_STACK
+void serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
+{
+   _serpent_ecb_encrypt(pt, ct, skey);
+   burn_stack(sizeof(unsigned long)*24);
+}
+#endif
+
+#ifdef CLEAN_STACK
+static void _serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
+#else
+void serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
+#endif
+{
+    unsigned long a,b,c,d,e,f,g,h;
+    unsigned long t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16;
+
+    _ARGCHK(pt != NULL);
+    _ARGCHK(ct != NULL);
+    _ARGCHK(skey != NULL);
+
+    LOAD32L(a, &ct[0]);LOAD32L(b, &ct[4]);LOAD32L(c, &ct[8]);LOAD32L(d, &ct[12]);
+    k_xor(32,a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(31,e,f,g,h);
+    irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(30,a,b,c,d);
+    irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(29,e,f,g,h);
+    irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(28,a,b,c,d);
+    irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(27,e,f,g,h);
+    irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(26,a,b,c,d);
+    irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor(25,e,f,g,h);
+    irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor(24,a,b,c,d);
+    irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(23,e,f,g,h);
+    irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(22,a,b,c,d);
+    irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(21,e,f,g,h);
+    irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(20,a,b,c,d);
+    irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(19,e,f,g,h);
+    irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(18,a,b,c,d);
+    irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor(17,e,f,g,h);
+    irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor(16,a,b,c,d);
+    irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(15,e,f,g,h);
+    irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(14,a,b,c,d);
+    irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(13,e,f,g,h);
+    irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(12,a,b,c,d);
+    irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(11,e,f,g,h);
+    irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(10,a,b,c,d);
+    irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor( 9,e,f,g,h);
+    irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor( 8,a,b,c,d);
+    irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor( 7,e,f,g,h);
+    irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor( 6,a,b,c,d);
+    irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor( 5,e,f,g,h);
+    irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor( 4,a,b,c,d);
+    irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor( 3,e,f,g,h);
+    irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor( 2,a,b,c,d);
+    irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor( 1,e,f,g,h);
+    irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor( 0,a,b,c,d);
+    STORE32L(a, &pt[0]);STORE32L(b, &pt[4]);STORE32L(c, &pt[8]);STORE32L(d, &pt[12]);
+}
+
+#ifdef CLEAN_STACK
+void serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
+{
+   _serpent_ecb_decrypt(ct, pt, skey);
+   burn_stack(sizeof(unsigned long)*24);
+}
+#endif
+
+int serpent_test(void)
+{
+   static const struct {
+       int keylen;
+       unsigned char key[32], pt[16], ct[16];
+   } tests[] = {
+   {
+      16,
+      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0xdd, 0xd2, 0x6b, 0x98, 0xa5, 0xff, 0xd8, 0x2c,
+        0x05, 0x34, 0x5a, 0x9d, 0xad, 0xbf, 0xaf, 0x49 }
+   },
+   {
+      16,
+      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 },
+      { 0x4a, 0xe9, 0xa2, 0x0b, 0x2b, 0x14, 0xa1, 0x02,
+        0x90, 0xcb, 0xb8, 0x20, 0xb7, 0xff, 0xb5, 0x10 }
+   },
+   {
+      24,
+      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 },
+      { 0xe1, 0x1b, 0x01, 0x52, 0x4e, 0xa1, 0xf4, 0x65, 
+        0xa2, 0xa2, 0x00, 0x43, 0xeb, 0x9f, 0x7e, 0x8a }
+   },
+   {
+      32,
+      { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0xe0, 0x88, 0x5d, 0x44, 0x60, 0x37, 0x34, 0x69,
+        0xd1, 0xfa, 0x6c, 0x36, 0xa6, 0xe1, 0xc5, 0x2f }
+   },
+   {
+      32,
+      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0x17, 0xc6, 0x25, 0x8e, 0x60, 0x09, 0xe2, 0x82,
+        0x66, 0x18, 0x69, 0xd5, 0x25, 0xf7, 0xd2, 0x04 }
+   },
+   {
+      32,
+      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0x9f, 0xe1, 0x43, 0x25, 0x0d, 0x00, 0xe2, 0x56, 
+        0x96, 0xb0, 0x1e, 0x0a, 0x2e, 0xd0, 0x5d, 0xb3 }
+   }
+   };
+
+   unsigned char buf[2][16];
+   int x, err;
+   symmetric_key key;
+
+   for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
+      /* setup key */
+      if ((err = serpent_setup(tests[x].key, tests[x].keylen, 0, &key))!= CRYPT_OK) {
+         return err;
+      }
+
+      /* encrypt and decrypt */
+      serpent_ecb_encrypt(tests[x].pt, buf[0], &key);
+      serpent_ecb_decrypt(buf[0], buf[1], &key);
+
+      /* compare */
+      if (memcmp(buf[0], tests[x].ct, 16) != 0 || memcmp(buf[1], tests[x].pt, 16) != 0) {
+         return CRYPT_FAIL_TESTVECTOR;
+      }
+   }
+   return CRYPT_OK;
+}
+
+int serpent_keysize(int *desired_keysize)
+{
+   _ARGCHK(desired_keysize != NULL);
+
+   if (*desired_keysize < 16)
+      return CRYPT_INVALID_KEYSIZE;
+   if (*desired_keysize > 32)
+      *desired_keysize = 32;
+   return CRYPT_OK;
+}
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/strings.c	Sun Dec 19 11:47:33 2004 +0000
@@ -0,0 +1,86 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+
+/* Future releases will make use of this */
+#include "mycrypt.h"
+
+static const char *err_2_str[] =
+{
+   "CRYPT_OK",
+   "CRYPT_ERROR",
+   "Non-fatal 'no-operation' requested.",
+
+   "Invalid keysize for block cipher.",
+   "Invalid number of rounds for block cipher.",
+   "Algorithm failed test vectors.",
+
+   "Buffer overflow.",
+   "Invalid input packet.",
+
+   "Invalid number of bits for a PRNG.",
+   "Error reading the PRNG.",
+
+   "Invalid cipher specified.",
+   "Invalid hash specified.",
+   "Invalid PRNG specified.",
+
+   "Out of memory.",
+
+   "Invalid PK key or key type specified for function.",
+   "A private PK key is required.",
+
+   "Invalid argument provided.",
+   "File Not Found",
+
+   "Invalid PK type.",
+   "Invalid PK system.",
+   "Duplicate PK key found on keyring.",
+   "Key not found in keyring.",
+   "Invalid sized parameter.",
+
+   "Invalid size for prime.",
+
+};
+
+#ifdef MPI
+static const struct {
+    int mpi_code, ltc_code;
+} mpi_to_ltc_codes[] = {
+   { MP_OKAY ,  CRYPT_OK},
+   { MP_MEM  ,  CRYPT_MEM},
+   { MP_VAL  ,  CRYPT_INVALID_ARG},
+};
+#endif
+
+const char *error_to_string(int err)
+{
+   if (err < 0 || err >= (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) {
+      return "Invalid error code.";
+   } else {
+      return err_2_str[err];
+   }   
+}
+
+#ifdef MPI
+/* convert a MPI error to a LTC error (Possibly the most powerful function ever!  Oh wait... no) */
+int mpi_to_ltc_error(int err)
+{
+   int x;
+
+   for (x = 0; x < (int)(sizeof(mpi_to_ltc_codes)/sizeof(mpi_to_ltc_codes[0])); x++) {
+       if (err == mpi_to_ltc_codes[x].mpi_code) { 
+          return mpi_to_ltc_codes[x].ltc_code;
+       }
+   }
+   return CRYPT_ERROR;
+}
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tommath.h	Sun Dec 19 11:47:33 2004 +0000
@@ -0,0 +1,558 @@
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://math.libtomcrypt.org
+ */
+#ifndef BN_H_
+#define BN_H_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+
+#define NO_LTM_TOOM 1
+
+#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
+