Kaynağa Gözat

added libtomcrypt-0.99

Tom St Denis 21 yıl önce
ebeveyn
işleme
1c1822d510
80 değiştirilmiş dosya ile 3331 ekleme ve 888 silme
  1. 1 1
      LICENSE
  2. 28 0
      changes
  3. 261 0
      chc.c
  4. 0 25
      crypt
  5. 3 0
      crypt.c
  6. 306 119
      crypt.tex
  7. 219 0
      cscope.tmplst
  8. 11 2
      demos/hashsum.c
  9. 3 3
      demos/test/cipher_hash_test.c
  10. 82 0
      demos/test/der_tests.c
  11. 12 0
      demos/test/dh_tests.c
  12. 14 2
      demos/test/dsa_test.c
  13. 12 0
      demos/test/ecc_test.c
  14. 3 3
      demos/test/makefile
  15. 1 1
      demos/test/makefile.icc
  16. 1 1
      demos/test/makefile.msvc
  17. 19 0
      demos/test/makefile.shared
  18. 13 0
      demos/test/pkcs_1_test.c
  19. 68 7
      demos/test/rsa_test.c
  20. 39 18
      demos/test/test.c
  21. 1 0
      demos/test/test.h
  22. 12 2
      demos/tv_gen.c
  23. 12 0
      demos/tv_gen.lo
  24. 12 3
      demos/x86_prof.c
  25. 83 0
      der_decode_integer.c
  26. 93 0
      der_encode_integer.c
  27. 50 0
      der_get_multi_integer.c
  28. 54 0
      der_length_integer.c
  29. 49 0
      der_put_multi_integer.c
  30. BIN
      doc/crypt.pdf
  31. 6 5
      ecc.c
  32. 3 1
      fortuna.c
  33. 4 2
      hash_filehandle.c
  34. 3 1
      hash_memory.c
  35. 3 1
      hmac_done.c
  36. 4 1
      hmac_init.c
  37. 18 14
      ltc_tommath.h
  38. 19 14
      makefile
  39. 9 5
      makefile.cygwin_dll
  40. 5 1
      makefile.icc
  41. 6 2
      makefile.msvc
  42. 186 0
      makefile.shared
  43. 2 1
      md2.c
  44. 10 5
      md4.c
  45. 10 5
      md5.c
  46. 202 428
      mpi.c
  47. 2 2
      mycrypt.h
  48. 1 1
      mycrypt_argchk.h
  49. 6 0
      mycrypt_cfg.h
  50. 8 13
      mycrypt_custom.h
  51. 52 29
      mycrypt_hash.h
  52. 30 4
      mycrypt_macros.h
  53. 9 2
      mycrypt_pk.h
  54. 2 2
      mycrypt_prng.h
  55. 35 0
      notes/hash_tv.txt
  56. 35 0
      notes/hmac_tv.txt
  57. 7 5
      omac_done.c
  58. 4 1
      omac_test.c
  59. 3 1
      pkcs_1_mgf1.c
  60. 3 1
      pkcs_1_pss_decode.c
  61. 3 1
      pkcs_1_pss_encode.c
  62. 3 1
      pkcs_5_1.c
  63. 10 5
      rmd128.c
  64. 10 5
      rmd160.c
  65. 25 42
      rsa_export.c
  66. 11 12
      rsa_exptmod.c
  67. 1 1
      rsa_free.c
  68. 32 44
      rsa_import.c
  69. 3 10
      rsa_make_key.c
  70. 10 5
      sha1.c
  71. 2 1
      sha224.c
  72. 9 6
      sha256.c
  73. 2 1
      sha384.c
  74. 10 6
      sha512.c
  75. 1 1
      sober128.c
  76. 10 5
      tiger.c
  77. 955 0
      tommath_class.h
  78. 70 0
      tommath_superclass.h
  79. 11 6
      whirl.c
  80. 4 2
      yarrow.c

+ 1 - 1
LICENSE

@@ -2,7 +2,7 @@ LibTomCrypt is public domain.  As should all quality software be.
 
 All of the software was either written by or donated to Tom St Denis for the purposes
 of this project.  The only exception is the SAFER.C source which has no known
-license status (assumed copyrighted) which is why SAFER,C is shipped as disabled.
+license status (assumed copyrighted) which is why SAFER.C is shipped as disabled.
 
 Tom St Denis
 

+ 28 - 0
changes

@@ -1,3 +1,31 @@
+October 29th, 2004
+v0.99  -- Merged in the latest version of LTM which includes all of the recent bug fixes
+       -- Deprecated LTMSSE and removed it (to be replaced with TFM later on)
+       -- Stefan Arentz pointed out that mp_s_rmap should be extern
+       -- Kristian Gjøsteen pointed out that there are typos in the 
+          "test" makefile and minor issues in Yarrow and Sober [just cosmetics really]
+       -- Matthew P. Cashdollar pointed out that "export" is a C++ keyword 
+          so changed the PRNG api to use "pexport" and "pimport"
+       -- Updated "hashsum" demo so it builds ;-)
+       -- Added automatic support for x86-64 (will configure for 64-bit little endian automagically)
+       -- Zhi Chen pointed out a bug in rsa_exptmod which would leak memory on error. 
+       -- Made hash functions "init" return an int.  slight change to API ;-(
+       -- Added "CHC" mode which turns any cipher into a hash the other LTC functions can use
+       -- Added CHC mode stuff to demos such as tv_gen and hashsum
+       -- Added "makefile.shared" which builds and installs shared/static object copies
+          of the library.
+       -- Added DER for bignum support 
+       -- RSA is now fully joy.  rsa_export/rsa_import use PKCS #1 encodings and should be 
+          compatible with other crypto libs that use the format.
+       -- Added support for x86-64 for the ROL/ROR macros 
+       -- Changed the DLL and SO makefiles to optimize for speed, commented SMALL_CODE in
+          mycrypt_custom.h and added -DSMALL_CODE to the default makefile
+       -- Updated primality testing code so it does a minimum of 5 tests [of Miller-Rabin]
+          (AFAIK not a security fix, just warm fuzzies)
+       -- Minor updates to the OMAC code (additional __ARGCHK and removed printf from omac_test... oops!)
+       -- Update build and configuration info which was really really really out of date.  (Chapter 14)
+       ++ Minor update, switch RSA to use the PKCS style CRT
+
 August 6th, 2004
 v0.98  -- Update to hmac_init to free all allocated memory on error
        -- Update to PRNG API to fix import/export functions of Fortuna and Yarrow

+ 261 - 0
chc.c

@@ -0,0 +1,261 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+#ifdef CHC_HASH
+
+#define UNDEFED_HASH  -17
+
+/* chc settings */
+static int            cipher_idx=UNDEFED_HASH,        /* which cipher */
+                      cipher_blocksize;               /* blocksize of cipher */
+
+
+const struct _hash_descriptor chc_desc = {
+   "chc_hash", 12, 0, 0, { 0 }, 0,
+   &chc_init,
+   &chc_process,
+   &chc_done,
+   &chc_test
+};
+
+/* initialize the CHC state with a given cipher */
+int chc_register(int cipher)
+{
+   int err, kl, idx;
+
+   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
+      return err;
+   }
+
+   /* will it be valid? */
+   kl = cipher_descriptor[cipher].block_length;
+
+   /* must be >64 bit block */
+   if (kl <= 8) {
+      return CRYPT_INVALID_CIPHER;
+   }
+
+   /* can we use the ideal keysize? */
+   if ((err = cipher_descriptor[cipher].keysize(&kl)) != CRYPT_OK) {
+      return err;
+   }
+   /* we require that key size == block size be a valid choice */
+   if (kl != cipher_descriptor[cipher].block_length) {
+      return CRYPT_INVALID_CIPHER;
+   }
+
+   /* determine if chc_hash has been register_hash'ed already */
+   if ((err = hash_is_valid(idx = find_hash("chc_hash"))) != CRYPT_OK) {
+      return err;
+   }
+
+   /* store into descriptor */
+   hash_descriptor[idx].hashsize  = 
+   hash_descriptor[idx].blocksize = cipher_descriptor[cipher].block_length;
+
+   /* store the idx and block size */
+   cipher_idx       = cipher;
+   cipher_blocksize = cipher_descriptor[cipher].block_length;
+   return CRYPT_OK;
+}
+
+/* "hash init" is simply encrypt 0 with the 0 key.  Simple way to make an IV */
+int chc_init(hash_state *md)
+{
+   symmetric_key *key;
+   unsigned char  buf[MAXBLOCKSIZE];
+   int            err;
+ 
+   _ARGCHK(md != NULL);
+
+   /* is the cipher valid? */
+   if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) {
+      return err;
+   }
+
+   if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) {
+      return CRYPT_INVALID_CIPHER;
+   }
+
+   if ((key = XMALLOC(sizeof(*key))) == NULL) {
+      return CRYPT_MEM;
+   }
+
+   /* zero key and what not */   
+   zeromem(buf, cipher_blocksize);
+   if ((err = cipher_descriptor[cipher_idx].setup(buf, cipher_blocksize, 0, key)) != CRYPT_OK) {
+      XFREE(key);
+      return err;
+   }
+
+   /* encrypt zero block */
+   cipher_descriptor[cipher_idx].ecb_encrypt(buf, md->chc.state, key);
+
+   /* zero other members */
+   md->chc.length = 0;
+   md->chc.curlen = 0;
+   zeromem(md->chc.buf, sizeof(md->chc.buf));
+   XFREE(key);
+   return CRYPT_OK;
+}
+
+/* 
+   key    <= state
+   T0,T1  <= block
+   T0     <= encrypt T0
+   state  <= state xor T0 xor T1
+*/
+static int chc_compress(hash_state *md, unsigned char *buf)
+{
+   unsigned char  T[2][MAXBLOCKSIZE];
+   symmetric_key *key;
+   int            err, x;
+
+   if ((key = XMALLOC(sizeof(*key))) == NULL) {
+      return CRYPT_MEM;
+   }
+   if ((err = cipher_descriptor[cipher_idx].setup(md->chc.state, cipher_blocksize, 0, key)) != CRYPT_OK) {
+      XFREE(key);
+      return err;
+   }
+   memcpy(T[1], buf, cipher_blocksize);
+   cipher_descriptor[cipher_idx].ecb_encrypt(buf, T[0], key);
+   for (x = 0; x < cipher_blocksize; x++) {
+       md->chc.state[x] ^= T[0][x] ^ T[1][x];
+   }
+   XFREE(key);
+#ifdef CLEAN_STACK
+   zeromem(T, sizeof(T));
+   zeromem(&key, sizeof(key));
+#endif
+   return CRYPT_OK;
+}
+
+HASH_PROCESS(_chc_process, chc_compress, chc, (unsigned long)cipher_blocksize)
+
+int chc_process(hash_state * md, const unsigned char *buf, unsigned long len)
+{
+   int err;
+
+   _ARGCHK(md   != NULL);
+   _ARGCHK(buf  != NULL);
+
+   /* is the cipher valid? */
+   if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) {
+      return err;
+   }
+   if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) {
+      return CRYPT_INVALID_CIPHER;
+   }
+
+   return _chc_process(md, buf, len);
+}
+
+int chc_done(hash_state *md, unsigned char *buf)
+{
+    int err;
+
+    _ARGCHK(md   != NULL);
+    _ARGCHK(buf  != NULL);
+
+    /* is the cipher valid? */
+    if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) {
+       return err;
+    }
+    if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) {
+       return CRYPT_INVALID_CIPHER;
+    }
+
+    if (md->chc.curlen >= sizeof(md->chc.buf)) {
+       return CRYPT_INVALID_ARG;
+    }
+
+    /* increase the length of the message */
+    md->chc.length += md->chc.curlen * 8;
+
+    /* append the '1' bit */
+    md->chc.buf[md->chc.curlen++] = (unsigned char)0x80;
+
+    /* if the length is currently above l-8 bytes we append zeros
+     * then compress.  Then we can fall back to padding zeros and length
+     * encoding like normal.
+     */
+    if (md->chc.curlen > (unsigned long)(cipher_blocksize - 8)) {
+        while (md->chc.curlen < (unsigned long)cipher_blocksize) {
+            md->chc.buf[md->chc.curlen++] = (unsigned char)0;
+        }
+        chc_compress(md, md->chc.buf);
+        md->chc.curlen = 0;
+    }
+
+    /* pad upto l-8 bytes of zeroes */
+    while (md->chc.curlen < (unsigned long)(cipher_blocksize - 8)) {
+        md->chc.buf[md->chc.curlen++] = (unsigned char)0;
+    }
+
+    /* store length */
+    STORE64L(md->chc.length, md->chc.buf+(cipher_blocksize-8));
+    chc_compress(md, md->chc.buf);
+
+    /* copy output */
+    XMEMCPY(buf, md->chc.state, cipher_blocksize);
+
+#ifdef CLEAN_STACK
+    zeromem(md, sizeof(hash_state));
+#endif
+    return CRYPT_OK;
+}
+
+int chc_test(void)
+{
+   static const struct {
+      unsigned char *msg,
+                    md[MAXBLOCKSIZE];
+      int            len;
+   } tests[] = {
+{
+   (unsigned char *)"hello world",
+   { 0xcf, 0x57, 0x9d, 0xc3, 0x0a, 0x0e, 0xea, 0x61, 
+     0x0d, 0x54, 0x47, 0xc4, 0x3c, 0x06, 0xf5, 0x4e },
+   16
+}
+};
+   int x, oldhashidx, idx;
+   unsigned char out[MAXBLOCKSIZE];
+   hash_state md;
+
+   /* AES can be under rijndael or aes... try to find it */
+   if ((idx = find_cipher("aes")) == -1) {
+      if ((idx = find_cipher("rijndael")) == -1) {
+         return CRYPT_NOP;
+      }
+   }
+   oldhashidx = cipher_idx;
+   chc_register(idx);
+
+   for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
+       chc_init(&md);
+       chc_process(&md, tests[x].msg, strlen((char *)tests[x].msg));
+       chc_done(&md, out);
+       if (memcmp(out, tests[x].md, tests[x].len)) {
+          return CRYPT_FAIL_TESTVECTOR;
+       }
+   }
+   if (oldhashidx != UNDEFED_HASH) {
+      chc_register(oldhashidx);
+   }
+
+   return CRYPT_OK;
+}
+
+#endif

+ 0 - 25
crypt

@@ -1,25 +0,0 @@
-%PDF-1.3
-%Çì�¢
-3 0 obj
-<< /Type /Pages /Kids [
-] /Count 0
->>
-endobj
-1 0 obj
-<</Type /Catalog /Pages 3 0 R
->>
-endobj
-2 0 obj
-<</Producer(ESP Ghostscript 7.07)>>endobj
-xref
-0 4
-0000000000 65535 f 
-0000000068 00000 n 
-0000000116 00000 n 
-0000000015 00000 n 
-trailer
-<< /Size 4 /Root 1 0 R /Info 2 0 R
->>
-startxref
-166
-%%EOF

+ 3 - 0
crypt.c

@@ -123,6 +123,9 @@ const char *crypt_build_settings =
 #if defined(WHIRLPOOL)
    "   WHIRLPOOL\n"
 #endif
+#if defined(CHC_HASH)
+   "   CHC_HASH \n"
+#endif
 
     "\nBlock Chaining Modes:\n"
 #if defined(CFB)

+ 306 - 119
crypt.tex

@@ -47,7 +47,7 @@
 \def\gap{\vspace{0.5ex}}
 \makeindex
 \begin{document}
-\title{LibTomCrypt \\ Version 0.98}
+\title{LibTomCrypt \\ Version 0.99}
 \author{Tom St Denis \\
 \\
 [email protected] \\
@@ -199,24 +199,6 @@ of the ciphers and hashes are patent free or under patents that have since expir
 The RC2 and RC4 symmetric ciphers are not under patents but are under trademark regulations.  This means you can use 
 the ciphers you just can't advertise that you are doing so.  
 
-\section{Building the library}
-
-To build the library on a GCC equipped platform simply type ``make'' at your command prompt.  It will build the library
-file ``libtomcrypt.a''.  
-
-To install the library copy all of the ``.h'' files into your ``\#include'' path and the single libtomcrypt.a file into 
-your library path.
-
-With MSVC you can build the library with ``nmake -f makefile.msvc''.  This will produce a ``tomcrypt.lib'' file which
-is the core library.  Copy the header files into your MSVC include path and the library in the lib path (typically
-under where VC98 is installed).
-
-\section{Building against the library}
-
-In the recent versions the build steps have changed.  The build options are now stored in ``mycrypt\_custom.h'' and
-no longer in the makefile.  If you change a build option in that file you must re-build the library from clean to
-ensure the build is intact.  
-
 \section{Thanks}
 I would like to give thanks to the following people (in no particular order) for helping me develop this project from
 early on:
@@ -1354,7 +1336,60 @@ int register_hash(const struct _hash_descriptor *hash);
 int unregister_hash(const struct _hash_descriptor *hash);
 \end{verbatim}
 
-\subsection{Notice}
+\section{Cipher Hash Construction}
+\index{Cipher Hash Construction}
+An addition to the suite of hash functions is the ``Cipher Hash Construction'' or ``CHC'' mode.  In this mode
+applicable block ciphers (such as AES) can be turned into hash functions that other LTC functions can use.  In 
+particular this allows a cryptosystem to be designed using very few moving parts.
+
+In order to use the CHC system the developer will have to take a few extra steps.  First the ``chc\_desc'' hash
+descriptor must be registered with register\_hash().  At this point the CHC hash cannot be used to hash
+data.  While it is in the hash system you still have to tell the CHC code which cipher to use.  This is accomplished
+via the chc\_register() function.
+
+\index{chc\_register()}
+\begin{verbatim}
+int chc_register(int cipher);
+\end{verbatim}
+
+A cipher has to be registered with CHC (and also in the cipher descriptor tables with 
+register\_cipher()).  The chc\_register() function will bind a cipher to the CHC system.  Only one cipher can 
+be bound to the CHC hash at a time.  There are additional requirements for the system to work.
+
+\begin{enumerate}
+   \item The cipher must have a block size greater than 64--bits.  
+   \item The cipher must allow an input key the size of the block size.
+\end{enumerate}
+
+Example of using CHC with the AES block cipher.
+
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   int err; 
+
+   /* register cipher and hash */
+   if (register_cipher(&aes_enc_desc) == -1) {
+      printf("Could not register cipher\n");
+      return EXIT_FAILURE;
+   }
+   if (register_hash(&chc_desc) == -1) {
+      printf("Could not register hash\n");
+      return EXIT_FAILURE;
+   }
+
+   /* start chc with AES */
+   if ((err = chc_register(find_cipher("aes"))) != CRYPT_OK) {
+      printf("Error binding AES to CHC: %s\n", error_to_string(err));
+   }
+
+   /* now you can use chc_hash in any LTC function [aside from pkcs...] */
+   /* ... */
+\end{verbatim}
+
+
+\section{Notice}
 It is highly recommended that you \textbf{not} use the MD4 or MD5 hashes for the purposes of digital signatures or authentication codes.  
 These hashes are provided for completeness and they still can be used for the purposes of password hashing or one-way accumulators
 (e.g. Yarrow).
@@ -2260,10 +2295,11 @@ Note that the ``rsa\_make\_key()'' function allocates memory at runtime when you
 ``rsa\_free()'' (see below) when you are finished with the key.  If ``rsa\_make\_key()'' fails it will automatically 
 free the ram allocated itself.
 
-There are three types of RSA keys.  The types are {\bf PK\_PRIVATE\_OPTIMIZED}, {\bf PK\_PRIVATE} and {\bf PK\_PUBLIC}.  The first
-two are private keys where the ``optimized'' type uses the Chinese Remainder Theorem to speed up decryption/signatures.  By 
-default all new keys are of the ``optimized'' type.  The non-optimized private type is provided for backwards compatibility
-as well as to save space since the optimized key requires about four times as much memory.
+\index{PK\_PRIVATE} \index{PK\_PUBLIC}
+There are two types of RSA keys.  The types are {\bf PK\_PRIVATE} and {\bf PK\_PUBLIC}.  The first type is a private 
+RSA key which includes the CRT parameters\footnote{As of v0.99 the PK\_PRIVATE\_OPTIMIZED type has been deprecated
+and has been replaced by the PK\_PRIVATE type.} in the form of a RSAPrivateKey.  The second type is a public RSA key
+which only includes the modulus and public exponent.  It takes the form of a RSAPublicKey.
 
 \subsection{RSA Exponentiation}
 
@@ -2416,79 +2452,6 @@ int main(void)
 }
 \end{verbatim}
 
-\chapter{Password Based Cryptography}
-\section{PKCS \#5}
-In order to securely handle user passwords for the purposes of creating session keys and chaining IVs the PKCS \#5 was drafted.   PKCS \#5
-is made up of two algorithms, Algorithm One and Algorithm Two.  Algorithm One is the older fairly limited algorithm which has been implemented
-for completeness.  Algorithm Two is a bit more modern and more flexible to work with.
-
-\section{Algorithm One}
-Algorithm One accepts as input a password, an 8--byte salt and an iteration counter.  The iteration counter is meant to act as delay for
-people trying to brute force guess the password.  The higher the iteration counter the longer the delay.  This algorithm also requires a hash 
-algorithm and produces an output no longer than the output of the hash.  
-
-\index{pkcs\_5\_alg1()}
-\begin{alltt}
-int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, 
-                const unsigned char *salt, 
-                int iteration_count,  int hash_idx,
-                unsigned char *out,   unsigned long *outlen)
-\end{alltt}
-Where ``password'' is the users password.  Since the algorithm allows binary passwords you must also specify the length in ``password\_len''.  
-The ``salt'' is a fixed size 8--byte array which should be random for each user and session.  The ``iteration\_count'' is the delay desired
-on the password.  The ``hash\_idx'' is the index of the hash you wish to use in the descriptor table.  
-
-The output of length upto ``outlen'' is stored in ``out''.  If ``outlen'' is initially larger than the size of the hash functions output
-it is set to the number of bytes stored.  If it is smaller than not all of the hash output is stored in ``out''.
-
-\section{Algorithm Two}
-
-Algorithm Two is the recommended algorithm for this task.  It allows variable length salts and can produce outputs larger than the 
-hash functions output.  As such it can easily be used to derive session keys for ciphers and MACs as well initial vectors as required
-from a single password and invokation of this algorithm.
-
-\index{pkcs\_5\_alg2()}
-\begin{alltt}
-int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, 
-                const unsigned char *salt,     unsigned long salt_len,
-                int iteration_count,           int hash_idx,
-                unsigned char *out,            unsigned long *outlen)
-\end{alltt}
-Where ``password'' is the users password.  Since the algorithm allows binary passwords you must also specify the length in ``password\_len''.  
-The ``salt'' is an array of size ``salt\_len''.  It should be random for each user and session.  The ``iteration\_count'' is the delay desired
-on the password.  The ``hash\_idx'' is the index of the hash you wish to use in the descriptor table.   The output of length upto 
-``outlen'' is stored in ``out''.
-
-\begin{alltt}
-/* demo to show how to make session state material from a password */
-#include <mycrypt.h>
-int main(void)
-\{
-    unsigned char password[100], salt[100],
-                  cipher_key[16], cipher_iv[16],
-                  mac_key[16], outbuf[48];
-    int           err, hash_idx;
-    unsigned long outlen, password_len, salt_len;
-
-    /* register hash and get it's idx .... */
-
-    /* get users password and make up a salt ... */
-
-    /* create the material (100 iterations in algorithm) */
-    outlen = sizeof(outbuf);
-    if ((err = pkcs_5_alg2(password, password_len, salt, salt_len, 
-                           100, hash_idx, outbuf, &outlen)) != CRYPT_OK) \{
-       /* error handle */
-    \}
-
-    /* now extract it */
-    memcpy(cipher_key, outbuf, 16);
-    memcpy(cipher_iv,  outbuf+16, 16);
-    memcpy(mac_key,    outbuf+32, 16);
-
-    /* use material (recall to store the salt in the output) */
-\}
-\end{alltt}
 
 \chapter{Diffie-Hellman Key Exchange}
 
@@ -2918,8 +2881,6 @@ int dsa_verify_key(dsa_key *key, int *stat);
 This will test ``key'' and store the result in ``stat''.  If the result is $stat = 0$ the DSA key failed one of the tests
 and should not be used at all.  If the result is $stat = 1$ the DSA key is valid (as far as valid mathematics are concerned).
 
-
-
 \section{Signatures}
 To generate a DSA signature call the following function
 
@@ -2969,6 +2930,153 @@ int dsa_import(const unsigned char *in, unsigned long inlen,
 This will import the DSA key from the buffer ``in'' of length ``inlen'' to the ``key''.  If the process fails the function
 will automatically free all of the heap allocated in the process (you don't have to call dsa\_free()).  
 
+\chapter{Standards Support}
+\section{DER Support}
+DER or ``Distinguished Encoding Rules'' is a subset of the ASN.1 encoding rules that is fully deterministic and
+ideal for cryptography.  In particular ASN.1 specifies an INTEGER type for storing arbitrary sized integers.  DER
+further limits the ASN.1 specifications to a deterministic encoding.
+
+\subsection{Storing INTEGER types}
+\index{der\_encode\_integer()}
+\begin{alltt}
+int der_encode_integer(mp_int *num, unsigned char *out, unsigned long *outlen);
+\end{alltt}
+
+This will store the integer in ``num'' to the output buffer ``out'' of length ``outlen''.  It only stores
+non--negative numbers.  It stores the number of octets used back in ``outlen''.
+
+\subsection{Reading INTEGER types}
+\index{der\_decode\_integer()}
+\begin{alltt}
+int der_decode_integer(const unsigned char *in, unsigned long *inlen, mp_int *num);
+\end{alltt}
+This will decode the DER encoded INTEGER in ``in'' of length ``inlen'' and store the resulting integer
+in ``num''.  It will store the bytes read in ``inlen'' which is handy if you have to parse multiple
+data items out of a binary packet.
+
+\subsection{INTEGER length}
+\index{der\_length\_integer()}
+\begin{alltt}
+int der_length_integer(mp_int *num, unsigned long *len);
+\end{alltt}
+This will determine the length of the DER encoding of the integer ``num'' and store it in ``len''.
+
+\subsection{Multiple INTEGER types}
+To simplify the DER encoding/decoding there are two functions two handle multple types at once.
+
+\index{der\_put\_multi\_integer()}
+\index{der\_get\_multi\_integer()}
+\begin{alltt}
+int der_put_multi_integer(unsigned char *dst, unsigned long *outlen, mp_int *num, ...);
+int der_get_multi_integer(const unsigned char *src, unsigned long *inlen,  mp_int *num, ...);
+\end{alltt}
+
+These will handle multiple encodings/decodings at once.  They work like their single operand counterparts
+except they handle a \textbf{NULL} terminated list of operands.
+
+\begin{verbatim}
+#include <mycrypt.h>
+int main(void)
+{
+   mp_int        a, b, c, d;
+   unsigned char buffer[1000];
+   unsigned long len;
+   int           err;
+
+   /* init a,b,c,d with some values ... */
+
+   /* ok we want to store them now... */
+   len = sizeof(buffer);
+   if ((err = der_put_multi_integer(buffer, &len, 
+                                    &a, &b, &c, &d, NULL)) != CRYPT_OK) {
+      // error
+   }
+   printf("I stored %lu bytes in buf\n", len);
+
+   /* ok say we want to get them back for fun */
+   /* len set previously...otherwise set it to the size of the packet */
+   if ((err = der_get_multi_integer(buffer, &len,
+                                    &a, &b, &c, &d, NULL)) != CRYPT_OK) {
+      // error
+   }
+   printf("I read %lu bytes from buf\n", len);
+}
+\end{verbatim}
+\section{Password Based Cryptography}
+\subsection{PKCS \#5}
+In order to securely handle user passwords for the purposes of creating session keys and chaining IVs the PKCS \#5 was drafted.   PKCS \#5
+is made up of two algorithms, Algorithm One and Algorithm Two.  Algorithm One is the older fairly limited algorithm which has been implemented
+for completeness.  Algorithm Two is a bit more modern and more flexible to work with.
+
+\subsection{Algorithm One}
+Algorithm One accepts as input a password, an 8--byte salt and an iteration counter.  The iteration counter is meant to act as delay for
+people trying to brute force guess the password.  The higher the iteration counter the longer the delay.  This algorithm also requires a hash 
+algorithm and produces an output no longer than the output of the hash.  
+
+\index{pkcs\_5\_alg1()}
+\begin{alltt}
+int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, 
+                const unsigned char *salt, 
+                int iteration_count,  int hash_idx,
+                unsigned char *out,   unsigned long *outlen)
+\end{alltt}
+Where ``password'' is the users password.  Since the algorithm allows binary passwords you must also specify the length in ``password\_len''.  
+The ``salt'' is a fixed size 8--byte array which should be random for each user and session.  The ``iteration\_count'' is the delay desired
+on the password.  The ``hash\_idx'' is the index of the hash you wish to use in the descriptor table.  
+
+The output of length upto ``outlen'' is stored in ``out''.  If ``outlen'' is initially larger than the size of the hash functions output
+it is set to the number of bytes stored.  If it is smaller than not all of the hash output is stored in ``out''.
+
+\subsection{Algorithm Two}
+
+Algorithm Two is the recommended algorithm for this task.  It allows variable length salts and can produce outputs larger than the 
+hash functions output.  As such it can easily be used to derive session keys for ciphers and MACs as well initial vectors as required
+from a single password and invokation of this algorithm.
+
+\index{pkcs\_5\_alg2()}
+\begin{alltt}
+int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, 
+                const unsigned char *salt,     unsigned long salt_len,
+                int iteration_count,           int hash_idx,
+                unsigned char *out,            unsigned long *outlen)
+\end{alltt}
+Where ``password'' is the users password.  Since the algorithm allows binary passwords you must also specify the length in ``password\_len''.  
+The ``salt'' is an array of size ``salt\_len''.  It should be random for each user and session.  The ``iteration\_count'' is the delay desired
+on the password.  The ``hash\_idx'' is the index of the hash you wish to use in the descriptor table.   The output of length upto 
+``outlen'' is stored in ``out''.
+
+\begin{alltt}
+/* demo to show how to make session state material from a password */
+#include <mycrypt.h>
+int main(void)
+\{
+    unsigned char password[100], salt[100],
+                  cipher_key[16], cipher_iv[16],
+                  mac_key[16], outbuf[48];
+    int           err, hash_idx;
+    unsigned long outlen, password_len, salt_len;
+
+    /* register hash and get it's idx .... */
+
+    /* get users password and make up a salt ... */
+
+    /* create the material (100 iterations in algorithm) */
+    outlen = sizeof(outbuf);
+    if ((err = pkcs_5_alg2(password, password_len, salt, salt_len, 
+                           100, hash_idx, outbuf, &outlen)) != CRYPT_OK) \{
+       /* error handle */
+    \}
+
+    /* now extract it */
+    memcpy(cipher_key, outbuf, 16);
+    memcpy(cipher_iv,  outbuf+16, 16);
+    memcpy(mac_key,    outbuf+32, 16);
+
+    /* use material (recall to store the salt in the output) */
+\}
+\end{alltt}
+
+
 \chapter{Miscellaneous}
 \section{Base64 Encoding and Decoding}
 The library provides functions to encode and decode a RFC1521 base64 coding scheme.  This means that it can decode what it 
@@ -3202,18 +3310,77 @@ possible as some compilers may ignore the ``volatile'' keyword or have multiple
 is modular enough putting the locks in the right place should not bloat the code significantly and will solve all thread
 safety issues within the library.
 
-\chapter{Configuring the Library}
+\chapter{Configuring and Building the Library}
 \section{Introduction}
 The library is fairly flexible about how it can be built, used and generally distributed.  Additions are being made with
-each new release that will make the library even more flexible.  Most options are placed in the makefile and others
-are in ``mycrypt\_cfg.h''.  All are used when the library is built from scratch.
+each new release that will make the library even more flexible.  Each of the classes of functions can be disabled during
+the build process to make a smaller library.  This is particularly useful for shared libraries.
+
+\section{Building a Static Library}
+The library can be built as a static library which is generally the simplest and most portable method of 
+building the library.  With a CC or GCC equipped platform you can issue the following
+
+\begin{alltt}
+make install_lib
+\end{alltt}
+
+Which will build the library and install it in /usr/lib (as well as the headers in /usr/include).  The destination
+directory of the library and headers can be changed by editing ``makefile''.  The variable LIBNAME controls
+where the library is to be installed and INCNAME controls where the headers are to be installed.  A developer can 
+then use the library by including ``mycrypt.h'' in their program and linking against ``libtomcrypt.a''.
 
-For GCC platforms the file ``makefile'' is the makefile to be used.  On MSVC platforms ``makefile.vc'' and on PS2 platforms
-``makefile.ps2''.
+A static library can also be built with the Intel C Compiler  (ICC) by issuing the following
+
+\begin{alltt}
+make -f makefile.icc install
+\end{alltt}
+
+This will also build ``libtomcrypt.a'' except that it will use ICC.  Additionally Microsoft's Visual C 6.00 can be used
+by issuing
+
+\begin{alltt}
+nmake -f makefile.msvc
+\end{alltt}
+
+You will have to manually copy ``tomcrypt.lib'' and the headers to your MSVC lib/inc directories.
+
+\subsection{MPI Control}
+If you already have LibTomMath installed you can safely remove it from the build.  By commenting the line
+in the appropriate makefile which starts with 
+
+\begin{alltt}
+MPIOBJECT=mpi
+\end{alltt}
+
+Simply place a \# at the start and re-build the library.  To properly link applications you will have to also
+link in LibTomMath.  Removing MPI has the benefit of cutting down the library size as well potentially have access
+to the latest mpi.
+
+\section{Building a Shared Library}
+LibTomCrypt can also be built as a shared library (.so, .dll, etc...).  With non-Windows platforms the assumption
+of the presence of gcc and ``libtool'' has been made.  These are fairly common on Unix/Linux/BSD platforms.  To
+build a .so shared library issue 
+
+\begin{alltt}
+make -f makefile.shared
+\end{alltt}
+This will use libtool and gcc to build a shared library ``libtomcrypt.la'' as well as a static library ``libtomcrypt.a''
+and install them into /usr/lib (and the headers into /usr/include).  To link your application you should use the 
+libtool program in ``--mode=link''.
+
+You can also build LibTomCrypt as a shared library (DLL) in Windows with Cygwin.  Issue the following
+
+\begin{alltt}
+make -f makefile.cygwin_dll
+\end{alltt}
+This will build ``libtomcrypt.dll.a'' which is an import library for ``libtomcrypt.dll''.  You must copy 
+``libtomcrypt.dll.a'' to your library directory, ``libtomcrypt.dll' to somewhere in your PATH and the header
+files to your include directory.  So long as ``libtomcrypt.dll'' is in your system path you can run any LibTomCrypt
+program that uses it.
 
 \section{mycrypt\_cfg.h}
-The file ``mycrypt\_cfg.h'' is what lets you control what functionality you want to remove from the library.  By default,
-everything the library has to offer it built.  
+The file ``mycrypt\_cfg.h'' is what lets you control various high level macros which control the behaviour 
+of the library. 
 
 \subsubsection{ARGTYPE}
 This lets you control how the \_ARGCHK macro will behave.  The macro is used to check pointers inside the functions against
@@ -3226,17 +3393,18 @@ and no error checking will be performed.
 There are five macros related to endianess issues.  For little endian platforms define, ENDIAN\_LITTLE.  For big endian
 platforms define ENDIAN\_BIG.  Similarly when the default word size of an ``unsigned long'' is 32-bits define ENDIAN\_32BITWORD
 or define ENDIAN\_64BITWORD when its 64-bits.  If you do not define any of them the library will automatically use ENDIAN\_NEUTRAL
-which will work on all platforms.  Currently the system will automatically detect GCC or MSVC on a windows platform as well
-as GCC on a PS2 platform.
+which will work on all platforms.
+
+Currently LibTomCrypt will detect x86-32 and x86-64 running GCC as well as x86-32 running MSVC.  
 
 \section{The Configure Script}
-There are also options you can specify from the configure script or ``mycrypt\_config.h''.  
+There are also options you can specify from the configure script or ``mycrypt\_custom.h''.  
 
 \subsubsection{X memory routines}
-The makefiles must define three macros denoted as XMALLOC, XCALLOC and XFREE which resolve to the name of the respective
-functions.  This lets you substitute in your own memory routines.  If you substitute in your own functions they must behave
-like the standard C library functions in terms of what they expect as input and output.  By default the library uses the
-standard C routines.
+At the top of mycrypt\_custom.h are four macros denoted as XMALLOC, XCALLOC, XREALLOC and XFREE which resolve to 
+the name of the respective functions.  This lets you substitute in your own memory routines.  If you substitute in 
+your own functions they must behave like the standard C library functions in terms of what they expect as input and 
+output.  By default the library uses the standard C routines.
 
 \subsubsection{X clock routines}
 The rng\_get\_bytes() function can call a function that requires the clock() function.  These macros let you override
@@ -3244,17 +3412,22 @@ the default clock() used with a replacement.  By default the standard C library
 
 \subsubsection{NO\_FILE}
 During the build if NO\_FILE is defined then any function in the library that uses file I/O will not call the file I/O 
-functions and instead simply return CRYPT\_ERROR.  This should help resolve any linker errors stemming from a lack of
+functions and instead simply return CRYPT\_NOP.  This should help resolve any linker errors stemming from a lack of
 file I/O on embedded platforms.
 
 \subsubsection{CLEAN\_STACK}
-When this functions is defined the functions that store key material on the stack will clean up afterwards.  Assumes that
-you have no memory paging with the stack.
+When this functions is defined the functions that store key material on the stack will clean up afterwards.  
+Assumes that you have no memory paging with the stack.
+
+\subsubsection{LTC\_TEST}
+When this has been defined the various self--test functions (for ciphers, hashes, prngs, etc) are included in the build.
+When this has been undefined the tests are removed and if called will return CRYPT\_NOP.
 
 \subsubsection{Symmetric Ciphers, One-way Hashes, PRNGS and Public Key Functions}
-There are a plethora of macros for the ciphers, hashes, PRNGs and public key functions which are fairly self-explanatory.  
-When they are defined the functionality is included otherwise it is not.  There are some dependency issues which are
-noted in the file.  For instance, Yarrow requires CTR chaining mode, a block cipher and a hash function.
+There are a plethora of macros for the ciphers, hashes, PRNGs and public key functions which are fairly 
+self-explanatory.  When they are defined the functionality is included otherwise it is not.  There are some 
+dependency issues which are noted in the file.  For instance, Yarrow requires CTR chaining mode, a block 
+cipher and a hash function.
 
 \subsubsection{TWOFISH\_SMALL and TWOFISH\_TABLES}
 Twofish is a 128-bit symmetric block cipher that is provided within the library.  The cipher itself is flexible enough
@@ -3272,6 +3445,20 @@ it will not speed up the encryption or decryption functions.
 When this is defined some of the code such as the Rijndael and SAFER+ ciphers are replaced with smaller code variants.
 These variants are slower but can save quite a bit of code space.
 
+\section{MPI Tweaks}
+\subsection{RSA Only Tweak}
+If you plan on only using RSA with moduli in the range of 1024 to 2560 bits you can enable a series of tweaks
+to reduce the library size.  Follow these steps
+
+\begin{enumerate}
+   \item Undefine MDSA, MECC and MDH from mycrypt\_custom.h
+   \item Undefine LTM\_ALL  from tommath\_superclass.h
+   \item Define SC\_RSA\_1 from tommath\_superclass.h
+   \item Rebuild the library.
+\end{enumerate}
+
+
+
 \input{crypt.ind}
 
 \end{document}

+ 219 - 0
cscope.tmplst

@@ -0,0 +1,219 @@
+./aes.c
+./aes_tab.c
+./base64_decode.c
+./base64_encode.c
+./blowfish.c
+./burn_stack.c
+./cast5.c
+./cbc_decrypt.c
+./cbc_encrypt.c
+./cbc_getiv.c
+./cbc_setiv.c
+./cbc_start.c
+./cfb_decrypt.c
+./cfb_encrypt.c
+./cfb_getiv.c
+./cfb_setiv.c
+./cfb_start.c
+./chc.c
+./crypt.c
+./crypt_argchk.c
+./crypt_cipher_descriptor.c
+./crypt_cipher_is_valid.c
+./crypt_find_cipher.c
+./crypt_find_cipher_any.c
+./crypt_find_cipher_id.c
+./crypt_find_hash.c
+./crypt_find_hash_any.c
+./crypt_find_hash_id.c
+./crypt_find_prng.c
+./crypt_hash_descriptor.c
+./crypt_hash_is_valid.c
+./crypt_prng_descriptor.c
+./crypt_prng_is_valid.c
+./crypt_register_cipher.c
+./crypt_register_hash.c
+./crypt_register_prng.c
+./crypt_unregister_cipher.c
+./crypt_unregister_hash.c
+./crypt_unregister_prng.c
+./ctr_decrypt.c
+./ctr_encrypt.c
+./ctr_getiv.c
+./ctr_setiv.c
+./ctr_start.c
+./demos/encrypt.c
+./demos/hashsum.c
+./demos/small.c
+./demos/test/base64_test.c
+./demos/test/cipher_hash_test.c
+./demos/test/der_tests.c
+./demos/test/dh_tests.c
+./demos/test/dsa_test.c
+./demos/test/ecc_test.c
+./demos/test/mac_test.c
+./demos/test/makefile
+./demos/test/makefile.icc
+./demos/test/makefile.msvc
+./demos/test/makefile.shared
+./demos/test/modes_test.c
+./demos/test/pkcs_1_test.c
+./demos/test/rsa_test.c
+./demos/test/store_test.c
+./demos/test/test.c
+./demos/test/test.h
+./demos/tv_gen.c
+./demos/x86_prof.c
+./der_decode_integer.c
+./der_encode_integer.c
+./der_get_multi_integer.c
+./der_length_integer.c
+./der_put_multi_integer.c
+./des.c
+./dh.c
+./dh_sys.c
+./dsa_export.c
+./dsa_free.c
+./dsa_import.c
+./dsa_make_key.c
+./dsa_sign_hash.c
+./dsa_verify_hash.c
+./dsa_verify_key.c
+./eax_addheader.c
+./eax_decrypt.c
+./eax_decrypt_verify_memory.c
+./eax_done.c
+./eax_encrypt.c
+./eax_encrypt_authenticate_memory.c
+./eax_init.c
+./eax_test.c
+./ecb_decrypt.c
+./ecb_encrypt.c
+./ecb_start.c
+./ecc.c
+./ecc_sys.c
+./error_to_string.c
+./fortuna.c
+./hash_file.c
+./hash_filehandle.c
+./hash_memory.c
+./hmac_done.c
+./hmac_file.c
+./hmac_init.c
+./hmac_memory.c
+./hmac_process.c
+./hmac_test.c
+./is_prime.c
+./ltc_tommath.h
+./makefile
+./makefile.cygwin_dll
+./makefile.icc
+./makefile.msvc
+./makefile.shared
+./md2.c
+./md4.c
+./md5.c
+./mpi.c
+./mpi_to_ltc_error.c
+./mycrypt.h
+./mycrypt_argchk.h
+./mycrypt_cfg.h
+./mycrypt_cipher.h
+./mycrypt_custom.h
+./mycrypt_hash.h
+./mycrypt_macros.h
+./mycrypt_misc.h
+./mycrypt_pk.h
+./mycrypt_pkcs.h
+./mycrypt_prng.h
+./noekeon.c
+./notes/etc/whirlgen.c
+./notes/etc/whirltest.c
+./ocb_decrypt.c
+./ocb_decrypt_verify_memory.c
+./ocb_done_decrypt.c
+./ocb_done_encrypt.c
+./ocb_encrypt.c
+./ocb_encrypt_authenticate_memory.c
+./ocb_init.c
+./ocb_ntz.c
+./ocb_shift_xor.c
+./ocb_test.c
+./ofb_decrypt.c
+./ofb_encrypt.c
+./ofb_getiv.c
+./ofb_setiv.c
+./ofb_start.c
+./omac_done.c
+./omac_file.c
+./omac_init.c
+./omac_memory.c
+./omac_process.c
+./omac_test.c
+./packet_store_header.c
+./packet_valid_header.c
+./pkcs_1_i2osp.c
+./pkcs_1_mgf1.c
+./pkcs_1_oaep_decode.c
+./pkcs_1_oaep_encode.c
+./pkcs_1_os2ip.c
+./pkcs_1_pss_decode.c
+./pkcs_1_pss_encode.c
+./pkcs_1_v15_es_decode.c
+./pkcs_1_v15_es_encode.c
+./pkcs_1_v15_sa_decode.c
+./pkcs_1_v15_sa_encode.c
+./pkcs_5_1.c
+./pkcs_5_2.c
+./pmac_done.c
+./pmac_file.c
+./pmac_init.c
+./pmac_memory.c
+./pmac_ntz.c
+./pmac_process.c
+./pmac_shift_xor.c
+./pmac_test.c
+./rand_prime.c
+./rc2.c
+./rc4.c
+./rc5.c
+./rc6.c
+./rmd128.c
+./rmd160.c
+./rng_get_bytes.c
+./rng_make_prng.c
+./rsa_decrypt_key.c
+./rsa_encrypt_key.c
+./rsa_export.c
+./rsa_exptmod.c
+./rsa_free.c
+./rsa_import.c
+./rsa_make_key.c
+./rsa_sign_hash.c
+./rsa_v15_decrypt_key.c
+./rsa_v15_encrypt_key.c
+./rsa_v15_sign_hash.c
+./rsa_v15_verify_hash.c
+./rsa_verify_hash.c
+./s_ocb_done.c
+./safer.c
+./safer_tab.c
+./saferp.c
+./sha1.c
+./sha224.c
+./sha256.c
+./sha384.c
+./sha512.c
+./skipjack.c
+./sober128.c
+./sober128tab.c
+./sprng.c
+./tiger.c
+./tim_exptmod.c
+./twofish.c
+./twofish_tab.c
+./whirl.c
+./whirltab.c
+./xtea.c
+./yarrow.c
+./zeromem.c

+ 11 - 2
demos/hashsum.c

@@ -7,7 +7,7 @@
  * more functions ;)
 */
 
-#include <mycrypt_custom.h>
+#include <mycrypt.h>
 
 int errno;
 
@@ -26,7 +26,7 @@ int main(int argc, char **argv)
       printf("usage: ./hash algorithm file [file ...]\n");
       printf("Algorithms:\n");
       for (x = 0; hash_descriptor[x].name != NULL; x++) {
-         printf(" %s\n", hash_descriptor[x].name);
+         printf(" %s (%d)\n", hash_descriptor[x].name, hash_descriptor[x].ID);
       }
       exit(EXIT_SUCCESS);
    }
@@ -66,6 +66,8 @@ int main(int argc, char **argv)
 
 void register_algs(void)
 {
+  int err;
+
 #ifdef TIGER
   register_hash (&tiger_desc);
 #endif
@@ -102,5 +104,12 @@ void register_algs(void)
 #ifdef WHIRLPOOL
   register_hash (&whirlpool_desc);
 #endif
+#ifdef CHC_HASH
+  register_hash(&chc_desc);
+  if ((err = chc_register(register_cipher(&aes_enc_desc))) != CRYPT_OK) {
+     printf("chc_register error: %s\n", error_to_string(err));
+     exit(EXIT_FAILURE);
+  }
+#endif
 
 }

+ 3 - 3
demos/test/cipher_hash_test.c

@@ -23,12 +23,12 @@ int cipher_hash_test(void)
    for (x = 0; prng_descriptor[x].name != NULL; x++) {
       DO(prng_descriptor[x].test());
       DO(prng_descriptor[x].start(&nprng));
-      DO(prng_descriptor[x].add_entropy("helloworld12", 12, &nprng));
+      DO(prng_descriptor[x].add_entropy((unsigned char *)"helloworld12", 12, &nprng));
       DO(prng_descriptor[x].ready(&nprng));
       n = sizeof(buf);
-      DO(prng_descriptor[x].export(buf, &n, &nprng));
+      DO(prng_descriptor[x].pexport(buf, &n, &nprng));
       prng_descriptor[x].done(&nprng);
-      DO(prng_descriptor[x].import(buf, n, &nprng));
+      DO(prng_descriptor[x].pimport(buf, n, &nprng));
       DO(prng_descriptor[x].ready(&nprng));
       if (prng_descriptor[x].read(buf, 100, &nprng) != 100) {
          fprintf(stderr, "Error reading from imported PRNG!\n");

+ 82 - 0
demos/test/der_tests.c

@@ -0,0 +1,82 @@
+#include "test.h"
+
+int der_tests(void)
+{
+   unsigned long x, y, z, zz;
+   unsigned char buf[2][4096];
+   mp_int a, b, c, d, e, f, g;
+
+   DO(mpi_to_ltc_error(mp_init_multi(&a, &b, &c, &d, &e, &f, &g, NULL)));
+   for (zz = 0; zz < 16; zz++) {
+      for (z = 0; z < 1024; z++) {
+         if (yarrow_read(buf[0], z, &test_yarrow) != z) {
+            printf("Failed to read %lu bytes from yarrow\n", z);
+            return 1;
+         }
+         DO(mpi_to_ltc_error(mp_read_unsigned_bin(&a, buf[0], z)));
+         x = sizeof(buf[0]);
+         DO(der_encode_integer(&a, buf[0], &x));
+         y = x;
+         mp_zero(&b);
+         DO(der_decode_integer(buf[0], &y, &b));
+         if (y != x || mp_cmp(&a, &b) != MP_EQ) {
+            printf("%lu: %lu vs %lu\n", z, x, y);
+#ifdef BN_MP_TORADIX_C
+            mp_todecimal(&a, buf[0]);
+            mp_todecimal(&b, buf[1]);
+            printf("a == %s\nb == %s\n", buf[0], buf[1]);
+#endif
+            mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL);
+            return 1;
+         }
+      }
+   }
+   
+
+/* test the multi */
+   mp_set(&a, 1);
+   x = sizeof(buf[0]);
+   DO(der_put_multi_integer(buf[0], &x, &a, NULL));
+   y = x;
+   mp_zero(&a);
+   DO(der_get_multi_integer(buf[0], &y, &a, NULL));   
+   if (x != y || mp_cmp_d(&a, 1)) {
+      printf("%lu, %lu, %d\n", x, y, mp_cmp_d(&a, 1));
+      mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL);
+      return 1;
+   }   
+
+   mp_set(&a, 1);
+   mp_set(&b, 2);
+   x = sizeof(buf[0]);
+   DO(der_put_multi_integer(buf[0], &x, &a, &b, NULL));
+   y = x;
+   mp_zero(&a);
+   mp_zero(&b);
+   DO(der_get_multi_integer(buf[0], &y, &a, &b, NULL));   
+   if (x != y || mp_cmp_d(&a, 1) || mp_cmp_d(&b, 2)) {
+      printf("%lu, %lu, %d, %d\n", x, y, mp_cmp_d(&a, 1), mp_cmp_d(&b, 2));
+      mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL);
+      return 1;
+   }   
+
+   mp_set(&a, 1);
+   mp_set(&b, 2);
+   mp_set(&c, 3);
+   x = sizeof(buf[0]);
+   DO(der_put_multi_integer(buf[0], &x, &a, &b, &c, NULL));
+   y = x;
+   mp_zero(&a);
+   mp_zero(&b);
+   mp_zero(&c);
+   DO(der_get_multi_integer(buf[0], &y, &a, &b, &c, NULL));   
+   if (x != y || mp_cmp_d(&a, 1) || mp_cmp_d(&b, 2) || mp_cmp_d(&c, 3)) {
+      printf("%lu, %lu, %d, %d, %d\n", x, y, mp_cmp_d(&a, 1), mp_cmp_d(&b, 2), mp_cmp_d(&c, 3));
+      mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL);
+      return 1;
+   }   
+
+
+   mp_clear_multi(&a, &b, &c, &d, &e, &f, &g, NULL);
+   return 0;
+}

+ 12 - 0
demos/test/dh_tests.c

@@ -1,5 +1,7 @@
 #include "test.h"
 
+#ifdef MDH
+
 int dh_tests (void)
 {
   unsigned char buf[3][4096];
@@ -85,3 +87,13 @@ int dh_tests (void)
   dh_free (&usera);
   return 0;
 }
+
+#else
+
+int dh_tests(void)
+{
+   printf("NOP");
+   return 0;
+}
+
+#endif

+ 14 - 2
demos/test/dsa_test.c

@@ -1,10 +1,12 @@
 #include "test.h"
 
+#ifdef MDSA
+
 int dsa_test(void)
 {
    unsigned char msg[16], out[1024], out2[1024];
-   unsigned long x, y;
-   int err, stat1, stat2;
+   unsigned long x;
+   int stat1, stat2;
    dsa_key key, key2;
 
    /* make a random key */
@@ -49,3 +51,13 @@ int dsa_test(void)
 
    return 0;
 }
+
+#else
+
+int dsa_test(void)
+{
+  printf("NOP");
+  return 0;
+}
+
+#endif

+ 12 - 0
demos/test/ecc_test.c

@@ -1,5 +1,7 @@
 #include "test.h"
 
+#ifdef MECC
+
 int ecc_tests (void)
 {
   unsigned char buf[4][4096];
@@ -87,3 +89,13 @@ int ecc_tests (void)
   ecc_free (&usera);
   return 0;
 }
+
+#else
+
+int ecc_tests(void)
+{
+   printf("NOP");
+   return 0;
+}
+
+#endif

+ 3 - 3
demos/test/makefile

@@ -10,7 +10,7 @@ CFLAGS += -fomit-frame-pointer
 default: test
 
 OBJECTS=test.o cipher_hash_test.o mac_test.o modes_test.o \
-pkcs_1_test.o store_test.o rsa_test.o ecc_test.o dsa_test.c dh_tests.o 
+pkcs_1_test.o store_test.o rsa_test.o ecc_test.o dsa_test.o dh_tests.o der_tests.o 
 
 #uncomment this to get heap checking [e.g. memory leaks].  Note 
 #that you *MUST* build libtomcrypt.a with -g3 enabled [and make install it]
@@ -19,7 +19,7 @@ pkcs_1_test.o store_test.o rsa_test.o ecc_test.o dsa_test.c dh_tests.o
 #CCMALLOC = -lccmalloc -ldl
 
 test: $(OBJECTS)
-	$(CC) $(OBJECTS) -ltomcrypt  $(CCMALLOC) -o test
+	$(CC) $(OBJECTS) /usr/lib/libtomcrypt.a  $(CCMALLOC) -o test
 	
 clean:
-	rm -f test *.o *.obj *.exe *~	
+	rm -rf test *.o *.obj *.exe *~	.libs

+ 1 - 1
demos/test/makefile.icc

@@ -5,7 +5,7 @@ CC=icc
 default: test
 
 OBJECTS=test.o cipher_hash_test.o mac_test.o modes_test.o \
-pkcs_1_test.o store_test.o rsa_test.o ecc_test.o dsa_test.c dh_tests.o 
+pkcs_1_test.o store_test.o rsa_test.o ecc_test.o dsa_test.o dh_tests.o der_tests.o
 
 test: $(OBJECTS)
 	$(CC) $(OBJECTS) -ltomcrypt -o test

+ 1 - 1
demos/test/makefile.msvc

@@ -4,7 +4,7 @@ CFLAGS = $(CFLAGS) /W3 /Ox -I../../ -I./
 default: test.exe
 
 OBJECTS = test.obj cipher_hash_test.obj mac_test.obj modes_test.obj \
-pkcs_1_test.obj store_test.obj rsa_test.obj ecc_test.obj dsa_test.c dh_tests.obj 
+pkcs_1_test.obj store_test.obj rsa_test.obj ecc_test.obj dsa_test.c dh_tests.obj der_tests.obj
 
 
 test.exe: $(OBJECTS)

+ 19 - 0
demos/test/makefile.shared

@@ -0,0 +1,19 @@
+# make test harness, it is good.
+CFLAGS += -Wall -W -Os -I../../ -I./
+
+# if you're not debugging
+CFLAGS += -fomit-frame-pointer
+
+default: test
+
+#if you don't have mpi.o 
+#MPISHARED=-ltommath
+
+OBJECTS=test.o cipher_hash_test.o mac_test.o modes_test.o \
+pkcs_1_test.o store_test.o rsa_test.o ecc_test.o dsa_test.o dh_tests.o der_tests.o 
+
+test: $(OBJECTS)
+	libtool --mode=link gcc $(CFLAGS) $(OBJECTS) -o test -ltomcrypt $(MPISHARED)
+	
+clean:
+	rm -f test *.o *.obj *.exe *~	

+ 13 - 0
demos/test/pkcs_1_test.c

@@ -1,5 +1,7 @@
 #include "test.h"
 
+#ifdef PKCS_1
+
 int pkcs_1_test(void)
 {
    unsigned char buf[3][128];
@@ -101,3 +103,14 @@ int pkcs_1_test(void)
    }
    return 0;
 }
+
+#else
+
+int pkcs_1_test(void)
+{
+   printf("NOP");
+   return 0;
+}
+
+#endif
+

+ 68 - 7
demos/test/rsa_test.c

@@ -1,12 +1,13 @@
 #include "test.h"
 
-#define RSA_MSGSIZE 78
+#ifdef MRSA 
 
+#define RSA_MSGSIZE 78
 
 int rsa_test(void)
 {
    unsigned char in[1024], out[1024], tmp[1024];
-   rsa_key       key;
+   rsa_key       key, privKey, pubKey;
    int           hash_idx, prng_idx, stat, stat2;
    unsigned long rsa_msgsize, len, len2;
    static unsigned char lparam[] = { 0x01, 0x02, 0x03, 0x04 };
@@ -128,30 +129,90 @@ int rsa_test(void)
    /* sign a message (unsalted, lower cholestorol and Atkins approved) now */
    len = sizeof(out);
    DO(rsa_sign_hash(in, 20, out, &len, &test_yarrow, prng_idx, hash_idx, 0, &key));
+
+/* export key and import as both private and public */
+   len2 = sizeof(tmp);
+   DO(rsa_export(tmp, &len2, PK_PRIVATE, &key)); 
+   DO(rsa_import(tmp, len2, &privKey)); 
+   len2 = sizeof(tmp);
+   DO(rsa_export(tmp, &len2, PK_PUBLIC, &key));
+   DO(rsa_import(tmp, len2, &pubKey));
+
+   /* verify with original */
    DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 0, &stat, &key));
    /* change a byte */
    in[0] ^= 1;
    DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 0, &stat2, &key));
    
    if (!(stat == 1 && stat2 == 0)) {
-      printf("rsa_verify_hash (unsalted) failed, %d, %d", stat, stat2);
+      printf("rsa_verify_hash (unsalted, origKey) failed, %d, %d", stat, stat2);
+      rsa_free(&key);
+      rsa_free(&pubKey);
+      rsa_free(&privKey);
       return 1;
    }
 
-   /* sign a message (salted) now */
+   /* verify with privKey */
+   /* change a byte */
+   in[0] ^= 1;
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 0, &stat, &privKey));
+   /* change a byte */
+   in[0] ^= 1;
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 0, &stat2, &privKey));
+   
+   if (!(stat == 1 && stat2 == 0)) {
+      printf("rsa_verify_hash (unsalted, privKey) failed, %d, %d", stat, stat2);
+      rsa_free(&key);
+      rsa_free(&pubKey);
+      rsa_free(&privKey);
+      return 1;
+   }
+
+   /* verify with pubKey */
+   /* change a byte */
+   in[0] ^= 1;
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 0, &stat, &pubKey));
+   /* change a byte */
+   in[0] ^= 1;
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 0, &stat2, &pubKey));
+   
+   if (!(stat == 1 && stat2 == 0)) {
+      printf("rsa_verify_hash (unsalted, pubkey) failed, %d, %d", stat, stat2);
+      rsa_free(&key);
+      rsa_free(&pubKey);
+      rsa_free(&privKey);
+      return 1;
+   }
+
+   /* sign a message (salted) now (use privKey to make, pubKey to verify) */
    len = sizeof(out);
-   DO(rsa_sign_hash(in, 20, out, &len, &test_yarrow, prng_idx, hash_idx, 8, &key));
-   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 8, &stat, &key));
+   DO(rsa_sign_hash(in, 20, out, &len, &test_yarrow, prng_idx, hash_idx, 8, &privKey));
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 8, &stat, &pubKey));
    /* change a byte */
    in[0] ^= 1;
-   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 8, &stat2, &key));
+   DO(rsa_verify_hash(out, len, in, 20, &test_yarrow, prng_idx, hash_idx, 8, &stat2, &pubKey));
    
    if (!(stat == 1 && stat2 == 0)) {
       printf("rsa_verify_hash (salted) failed, %d, %d", stat, stat2);
+      rsa_free(&key);
+      rsa_free(&pubKey);
+      rsa_free(&privKey);
       return 1;
    }
    
    /* free the key and return */
    rsa_free(&key);
+   rsa_free(&pubKey);
+   rsa_free(&privKey);
    return 0;
 }
+
+#else
+
+int rsa_test(void)
+{
+   printf("NOP");
+   return 0;
+}
+
+#endif

+ 39 - 18
demos/test/test.c

@@ -9,12 +9,13 @@ test_entry test_list[26] = {
 {"cipher_hash_test",       "b",        "a",          cipher_hash_test     },
 {"modes_test",             "c",        "b",          modes_test           },
 {"mac_test",               "d",        "c",          mac_test             },
+{"der_test",               "e",         "",          der_tests            },
 
-{"pkcs_1_test",            "e",        "b",          pkcs_1_test          },
-{"rsa_test",               "f",        "",          rsa_test             },
-{"ecc_test",               "g",        "a",          ecc_tests            },
-{"dsa_test",               "h",        "a",          dsa_test             },
-{"dh_test",                "i",        "a",          dh_tests             },
+{"pkcs_1_test",            "f",        "e",          pkcs_1_test          },
+{"rsa_test",               "g",        "e",          rsa_test             },
+{"ecc_test",               "h",        "a",          ecc_tests            },
+{"dsa_test",               "i",        "a",          dsa_test             },
+{"dh_test",                "j",        "a",          dh_tests             },
 
 {NULL, NULL, NULL, NULL} 
 };
@@ -32,6 +33,8 @@ void run_cmd(int res, int line, char *file, char *cmd)
 
 void register_algs(void)
 {
+  int err;
+
 #ifdef RIJNDAEL
   register_cipher (&aes_desc);
 #endif
@@ -111,6 +114,14 @@ void register_algs(void)
 #ifdef WHIRLPOOL
   register_hash (&whirlpool_desc);
 #endif
+#ifdef CHC_HASH
+  register_hash(&chc_desc);
+  if ((err = chc_register(register_cipher(&aes_enc_desc))) != CRYPT_OK) {
+     printf("chc_register error: %s\n", error_to_string(err));
+     exit(EXIT_FAILURE);
+  }
+#endif
+
 
 #ifdef YARROW
    register_prng(&yarrow_desc);
@@ -197,6 +208,7 @@ void stack_check(void)
 int main(void)
 {
    int x;
+   unsigned char buf[16];
 
    /* setup stack checker */
    srand(time(NULL));
@@ -212,23 +224,32 @@ int main(void)
       
    // start dummy yarrow for internal use 
    DO(yarrow_start(&test_yarrow));
-   DO(yarrow_add_entropy("test", 4, &test_yarrow));
+   sprng_read(buf, 16, NULL);
+   DO(yarrow_add_entropy(buf, 16, &test_yarrow));
    DO(yarrow_ready(&test_yarrow));
 
    // output sizes 
    printf("Sizes of objects (in bytes)\n");
-   printf("\tsymmetric_key\t=\t%5d\n", sizeof(symmetric_key));
-   printf("\thash_state\t=\t%5d\n", sizeof(hash_state));
-   printf("\thmac_state\t=\t%5d\n", sizeof(hmac_state));
-   printf("\tomac_state\t=\t%5d\n", sizeof(omac_state));
-   printf("\tpmac_state\t=\t%5d\n", sizeof(pmac_state));
-   printf("\tocb_state\t=\t%5d\n", sizeof(ocb_state));
-   printf("\teax_state\t=\t%5d\n", sizeof(eax_state));
-   printf("\tmp_int\t\t=\t%5d\n", sizeof(mp_int));
-   printf("\trsa_key\t\t=\t%5d\n", sizeof(rsa_key));
-   printf("\tdsa_key\t\t=\t%5d\n", sizeof(dsa_key));
-   printf("\tdh_key\t\t=\t%5d\n", sizeof(dh_key));
-   printf("\tecc_key\t\t=\t%5d\n", sizeof(ecc_key));
+   printf("\tsymmetric_key\t=\t%5lu\n", sizeof(symmetric_key));
+   printf("\thash_state\t=\t%5lu\n", sizeof(hash_state));
+   printf("\thmac_state\t=\t%5lu\n", sizeof(hmac_state));
+   printf("\tomac_state\t=\t%5lu\n", sizeof(omac_state));
+   printf("\tpmac_state\t=\t%5lu\n", sizeof(pmac_state));
+   printf("\tocb_state\t=\t%5lu\n", sizeof(ocb_state));
+   printf("\teax_state\t=\t%5lu\n", sizeof(eax_state));
+   printf("\tmp_int\t\t=\t%5lu\n", sizeof(mp_int));
+#ifdef MRSA
+   printf("\trsa_key\t\t=\t%5lu\n", sizeof(rsa_key));
+#endif
+#ifdef MDSA
+   printf("\tdsa_key\t\t=\t%5lu\n", sizeof(dsa_key));
+#endif
+#ifdef MDH
+   printf("\tdh_key\t\t=\t%5lu\n", sizeof(dh_key));
+#endif
+#ifdef MECC
+   printf("\tecc_key\t\t=\t%5lu\n", sizeof(ecc_key));
+#endif
 
    printf("\n\n");
    // do tests

+ 1 - 0
demos/test/test.h

@@ -35,5 +35,6 @@ int rsa_test(void);
 int ecc_tests(void);
 int dsa_test(void);
 int dh_tests(void);
+int der_tests(void);
 
 #endif

+ 12 - 2
demos/tv_gen.c

@@ -2,6 +2,8 @@
 
 void reg_algs(void)
 {
+  int err;
+
 #ifdef RIJNDAEL
   register_cipher (&aes_desc);
 #endif
@@ -82,6 +84,14 @@ void reg_algs(void)
 #ifdef WHIRLPOOL
   register_hash (&whirlpool_desc);
 #endif
+#ifdef CHC_HASH
+  register_hash(&chc_desc);
+  if ((err = chc_register(register_cipher(&aes_desc))) != CRYPT_OK) {
+     printf("chc_register error: %s\n", error_to_string(err));
+     exit(EXIT_FAILURE);
+  }
+#endif
+
 }
 
 void hash_gen(void)
@@ -98,7 +108,7 @@ void hash_gen(void)
    
    fprintf(out, "Hash Test Vectors:\n\nThese are the hashes of nn bytes '00 01 02 03 .. (nn-1)'\n\n");
    for (x = 0; hash_descriptor[x].name != NULL; x++) {
-      buf = XMALLOC(2 * hash_descriptor[x].blocksize);
+      buf = XMALLOC(2 * hash_descriptor[x].blocksize + 1);
       if (buf == NULL) {
          perror("can't alloc mem");
          exit(EXIT_FAILURE);
@@ -222,7 +232,7 @@ void hmac_gen(void)
           key[y] = (y&255);
       }
 
-      input = XMALLOC(hash_descriptor[x].blocksize * 2);
+      input = XMALLOC(hash_descriptor[x].blocksize * 2 + 1);
       if (input == NULL) {
          perror("Can't malloc memory");
          exit(EXIT_FAILURE);

+ 12 - 0
demos/tv_gen.lo

@@ -0,0 +1,12 @@
+# demos/tv_gen.lo - a libtool object file
+# Generated by ltmain.sh - GNU libtool 1.5.2 (1.1220.2.60 2004/01/25 12:25:08)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object='.libs/tv_gen.o'
+
+# Name of the non-PIC object.
+non_pic_object='tv_gen.o'
+

+ 12 - 3
demos/x86_prof.c

@@ -49,9 +49,9 @@ void tally_results(int type)
 static ulong64 rdtsc (void)
    {
    #if defined __GNUC__
-      #ifdef __i386__
-         ulong64 a;
-         __asm__ __volatile__ ("rdtsc ":"=A" (a));
+      #if defined(__i386__) || defined(__x86_64__)
+         unsigned long long a;
+         __asm__ __volatile__ ("rdtsc\nmovl %%eax,%0\nmovl %%edx,4+%0\n"::"m"(a):"%eax","%edx");
          return a;
       #else /* gcc-IA64 version */
          unsigned long result;
@@ -110,6 +110,7 @@ void init_timer(void)
 
 void reg_algs(void)
 {
+  int err;
 #ifdef RIJNDAEL
   register_cipher (&aes_desc);
 #endif
@@ -190,6 +191,14 @@ void reg_algs(void)
 #ifdef WHIRLPOOL
   register_hash (&whirlpool_desc);
 #endif
+#ifdef CHC_HASH
+  register_hash(&chc_desc);
+  if ((err = chc_register(register_cipher(&aes_desc))) != CRYPT_OK) {
+     printf("chc_register error: %s\n", error_to_string(err));
+     exit(EXIT_FAILURE);
+  }
+#endif
+
 
 #ifndef YARROW 
    #error This demo requires Yarrow.

+ 83 - 0
der_decode_integer.c

@@ -0,0 +1,83 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+
+/* decodes a DER INTEGER in [in].  You have to tell this function
+ * how many bytes are available [inlen].  It will then attempt to 
+ * read the INTEGER.  If all goes well it stores the number of bytes
+ * read in [inlen] and the number in [num].
+ */
+int der_decode_integer(const unsigned char *in, unsigned long *inlen, mp_int *num)
+{
+   unsigned long tmplen, y, z;
+
+   _ARGCHK(num    != NULL);
+   _ARGCHK(in     != NULL);
+   _ARGCHK(inlen  != NULL);
+
+   /* save copy of max output size */
+   tmplen = *inlen;
+   *inlen = 0;
+
+   /* min DER INTEGER is 0x02 01 00 == 0 */
+   if (tmplen < (1 + 1 + 1)) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+   /* ok expect 0x02 when we AND with 0011 1111 [3F] */
+   if ((*in++ & 0x3F) != 0x02) {
+      return CRYPT_INVALID_PACKET;
+   }
+   ++(*inlen);
+
+   /* now decode the len stuff */
+   z = *in++;
+   ++(*inlen);
+
+   if ((z & 0x80) == 0x00) {
+      /* short form */
+
+      /* will it overflow? */
+      if (*inlen + z > tmplen) {
+         return CRYPT_INVALID_PACKET;
+      }
+     
+      /* no so read it */
+      (*inlen) += z;
+      return mpi_to_ltc_error(mp_read_unsigned_bin(num, (unsigned char *)in, z));
+   } else {
+      /* long form */
+      z &= 0x7F;
+      
+      /* will number of length bytes overflow? (or > 4) */
+      if (((*inlen + z) > tmplen) || (z > 4)) {
+         return CRYPT_INVALID_PACKET;
+      }
+
+      /* now read it in */
+      y = 0;
+      while (z--) {
+         y = ((unsigned long)(*in++)) | (y << 8);
+         ++(*inlen);
+      }
+
+      /* now will reading y bytes overrun? */
+      if ((*inlen + y) > tmplen) {
+         return CRYPT_INVALID_PACKET;
+      }
+
+      /* no so read it */
+      (*inlen) += y;
+      return mpi_to_ltc_error(mp_read_unsigned_bin(num, (unsigned char *)in, y));
+   }
+}

+ 93 - 0
der_encode_integer.c

@@ -0,0 +1,93 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+/* Exports a positive bignum as DER format (upto 2^32 bytes in size) */
+int der_encode_integer(mp_int *num, unsigned char *out, unsigned long *outlen)
+{  
+   unsigned long tmplen, x, y, z;
+   int           err, leading_zero;
+
+   _ARGCHK(num    != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* find out how big this will be */
+   if ((err = der_length_integer(num, &tmplen)) != CRYPT_OK) {
+      return err;
+   }
+
+   if (*outlen < tmplen) {
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* we only need a leading zero if the msb of the first byte is one */
+   if ((mp_count_bits(num) & 7) == 7 || mp_iszero(num) == MP_YES) {
+      leading_zero = 1;
+   } else {
+      leading_zero = 0;
+   }
+
+   /* get length of num in bytes (plus 1 since we force the msbyte to zero) */
+   y = mp_unsigned_bin_size(num) + leading_zero;
+
+   /* now store initial data */
+   *out++ = 0x02;
+   if (y < 128) {
+      /* short form */
+      *out++ = (unsigned char)y;
+   } else {
+      /* long form (relies on y != 0) */
+
+      /* get length of length... ;-) */
+      x = y;
+      z = 0;
+      while (x) {
+         ++z;
+         x >>= 8;
+      }
+      
+      /* store length of length */
+      *out++ = 0x80 | ((unsigned char)z);
+
+      /* now store length */
+      
+      /* first shift length up so msbyte != 0 */
+      x = y;
+      while ((x & 0xFF000000) == 0) {
+          x <<= 8;
+      }
+
+      /* now store length */
+      while (z--) {
+         *out++ = (unsigned char)((x >> 24) & 0xFF);
+         x <<= 8;
+      }
+   }
+
+   /* now store msbyte of zero if num is non-zero */
+   if (leading_zero) {
+      *out++ = 0x00;
+   }
+
+   /* if it's not zero store it as big endian */
+   if (mp_iszero(num) == MP_NO) {
+      /* now store the mpint */
+      if ((err = mp_to_unsigned_bin(num, out)) != MP_OKAY) {
+          return mpi_to_ltc_error(err);
+      }
+   }
+
+   /* we good */
+   *outlen = tmplen; 
+   return CRYPT_OK;
+}

+ 50 - 0
der_get_multi_integer.c

@@ -0,0 +1,50 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include <stdarg.h>
+#include "mycrypt.h"
+
+/* will read multiple DER INTEGER encoded mp_ints from src
+ * of upto [inlen] bytes.  It will store the number of bytes
+ * read back into [inlen].
+ */
+int der_get_multi_integer(const unsigned char *src, unsigned long *inlen, 
+                  mp_int *num, ...)
+{
+   va_list        args;
+   mp_int        *next;
+   unsigned long  wrote, len;
+   int            err;
+
+   _ARGCHK(src    != NULL);
+   _ARGCHK(inlen  != NULL);
+
+   /* setup va list */
+   next  = num;
+   len   = *inlen;
+   wrote = 0;
+   va_start(args, num);
+
+   while (next != NULL) {
+       if ((err = der_decode_integer(src, inlen, next)) != CRYPT_OK) {
+          va_end(args);
+          return err;
+       }
+       wrote += *inlen;
+       src   += *inlen;
+       len   -= *inlen;
+       *inlen = len;
+        next     = va_arg(args, mp_int*);
+   }
+   va_end(args);
+   *inlen = wrote;
+   return CRYPT_OK;
+}
+

+ 54 - 0
der_length_integer.c

@@ -0,0 +1,54 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+
+#include "mycrypt.h"
+
+/* Gets length of DER encoding of num */
+
+int der_length_integer(mp_int *num, unsigned long *outlen)
+{
+   unsigned long z, len;
+   int           leading_zero;
+
+   _ARGCHK(num     != NULL);
+   _ARGCHK(outlen  != NULL);
+
+   /* we only need a leading zero if the msb of the first byte is one */
+   if ((mp_count_bits(num) & 7) == 7 || mp_iszero(num) == MP_YES) {
+      leading_zero = 1;
+   } else {
+      leading_zero = 0;
+   }
+
+   /* size for bignum */
+   z = len = leading_zero + mp_unsigned_bin_size(num);
+
+   /* we need a 0x02 */
+   ++len;
+
+   /* now we need a length */
+   if (z < 128) {
+      /* short form */
+      ++len;
+   } else {
+      /* long form (relies on z != 0) */
+      ++len;
+
+      while (z) {
+         ++len;
+         z >>= 8;
+      }
+   }
+
+   *outlen = len; 
+   return CRYPT_OK;
+}
+

+ 49 - 0
der_put_multi_integer.c

@@ -0,0 +1,49 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtomcrypt.org
+ */
+#include <stdarg.h>
+#include "mycrypt.h"
+
+/* store multiple mp_ints in DER INTEGER format to the dst, will not
+ * overflow the length you give it [outlen] and store the number of 
+ * bytes used in [outlen] 
+ */
+int der_put_multi_integer(unsigned char *dst, unsigned long *outlen, 
+                  mp_int *num, ...)
+{
+   va_list        args;
+   mp_int        *next;
+   unsigned long  wrote, len;
+   int            err;
+
+   _ARGCHK(dst    != NULL);
+   _ARGCHK(outlen != NULL);
+
+   /* setup va list */
+   next  = num;
+   len   = *outlen;
+   wrote = 0;
+   va_start(args, num);
+
+   while (next != NULL) {
+        if ((err = der_encode_integer(next, dst, outlen)) != CRYPT_OK) {
+           va_end(args);
+           return err;
+        }
+        wrote   += *outlen;
+        dst     += *outlen;
+        len     -= *outlen;
+        *outlen  = len;
+        next     = va_arg(args, mp_int*);
+   }
+   va_end(args);
+   *outlen = wrote;
+   return CRYPT_OK;
+}

BIN
doc/crypt.pdf


+ 6 - 5
ecc.c

@@ -22,6 +22,9 @@
 /* size of our temp buffers for exported keys */
 #define ECC_BUF_SIZE 160
 
+/* max private key size */
+#define ECC_MAXSIZE  66
+
 /* This holds the key settings.  ***MUST*** be organized by size from smallest to largest. */
 static const struct {
    int size;
@@ -222,9 +225,6 @@ void ecc_find_base(void)
  
 #endif
 
-
-
-
 static int is_valid_idx(int n)
 {
    int x;
@@ -613,6 +613,7 @@ int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
    /* find key size */
    for (x = 0; (keysize > sets[x].size) && (sets[x].size != 0); x++);
    keysize = sets[x].size;
+   _ARGCHK(keysize <= ECC_MAXSIZE);
 
    if (sets[x].size == 0) {
       return CRYPT_INVALID_KEYSIZE;
@@ -621,7 +622,7 @@ int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
 
    /* allocate ram */
    base = NULL;
-   buf  = XMALLOC(128);
+   buf  = XMALLOC(ECC_MAXSIZE);
    if (buf == NULL) {
       return CRYPT_MEM;
    }
@@ -669,7 +670,7 @@ __ERR:
    mp_clear(&prime);
 __ERR2:
 #ifdef CLEAN_STACK
-   zeromem(buf, 128);
+   zeromem(buf, ECC_MAXSIZE);
 #endif
 
    XFREE(buf);

+ 3 - 1
fortuna.c

@@ -274,7 +274,9 @@ int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
       }
 
       /* now hash it */
-      sha256_init(md);
+      if ((err = sha256_init(md)) != CRYPT_OK) {
+         goto __ERR;
+      }
       if ((err = sha256_process(md, out+x*32, 32)) != CRYPT_OK) {
          goto __ERR;
       }

+ 4 - 2
hash_filehandle.c

@@ -31,9 +31,11 @@ int hash_filehandle(int hash, FILE *in, unsigned char *dst, unsigned long *outle
     if (*outlen < hash_descriptor[hash].hashsize) {
        return CRYPT_BUFFER_OVERFLOW;
     }
-    *outlen = hash_descriptor[hash].hashsize;
+    if ((err = hash_descriptor[hash].init(&md)) != CRYPT_OK) {
+       return err;
+    }
 
-    hash_descriptor[hash].init(&md);
+    *outlen = hash_descriptor[hash].hashsize;
     do {
         x = fread(buf, 1, sizeof(buf), in);
         if ((err = hash_descriptor[hash].process(&md, buf, x)) != CRYPT_OK) {

+ 3 - 1
hash_memory.c

@@ -32,7 +32,9 @@ int hash_memory(int hash, const unsigned char *data, unsigned long len, unsigned
        return CRYPT_MEM;
     }
 
-    hash_descriptor[hash].init(md);
+    if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) {
+       goto __ERR;
+    }
     if ((err = hash_descriptor[hash].process(md, data, len)) != CRYPT_OK) {
        goto __ERR;
     }

+ 3 - 1
hmac_done.c

@@ -75,7 +75,9 @@ int hmac_done(hmac_state *hmac, unsigned char *hashOut, unsigned long *outlen)
     }
 
     /* Now calculate the "outer" hash for step (5), (6), and (7) */
-    hash_descriptor[hash].init(&hmac->md);
+    if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) {
+       goto __ERR;
+    }
     if ((err = hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE)) != CRYPT_OK) {
        goto __ERR;
     }

+ 4 - 1
hmac_init.c

@@ -91,7 +91,10 @@ int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned lon
     }
 
     /* Pre-pend that to the hash data */
-    hash_descriptor[hash].init(&hmac->md);
+    if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) {
+       goto __ERR;
+    }
+
     if ((err = hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE)) != CRYPT_OK) {
        goto __ERR;
     }

+ 18 - 14
ltc_tommath.h

@@ -1,4 +1,3 @@
-
 /* LibTomMath, multiple-precision integer library -- Tom St Denis
  *
  * LibTomMath is a library that provides multiple-precision
@@ -21,7 +20,8 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include <limits.h>
-#include <mycrypt_custom.h>
+
+#include <tommath_class.h>
 
 #undef MIN
 #define MIN(x,y) ((x)<(y)?(x):(y))
@@ -41,6 +41,14 @@ extern "C" {
 
 #endif
 
+
+/* detect 64-bit mode if possible */
+#if defined(__x86_64__) 
+   #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT))
+      #define MP_64BIT
+   #endif
+#endif
+
 /* some default configurations.
  *
  * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
@@ -62,7 +70,7 @@ extern "C" {
    typedef signed long long   long64;
 #endif
 
-   typedef ulong64            mp_digit;
+   typedef unsigned long      mp_digit;
    typedef unsigned long      mp_word __attribute__ ((mode(TI)));
 
    #define DIGIT_BIT          60
@@ -101,16 +109,12 @@ extern "C" {
        #define XFREE    free
        #define XREALLOC realloc
        #define XCALLOC  calloc
-       #define XMEMSET  memset
-       #define XMEMCPY  memcpy
    #else
       /* prototypes for our heap functions */
-       void *XMALLOC(size_t n);
-       void *REALLOC(void *p, size_t n);
-       void *XCALLOC(size_t n, size_t s);
-       void XFREE(void *p);
-      void *XMEMCPY(void *dest, const void *src, size_t n);
-      int   XMEMCMP(const void *s1, const void *s2, size_t n);
+      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
 
@@ -159,7 +163,7 @@ extern int KARATSUBA_MUL_CUTOFF,
 
 /* default precision */
 #ifndef MP_PREC
-   #ifdef MP_LOW_MEM
+   #ifndef MP_LOW_MEM
       #define MP_PREC                 64     /* default digits of precision */
    #else
       #define MP_PREC                 8      /* default digits of precision */
@@ -547,13 +551,13 @@ 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 mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c);
 int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
 int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode);
 int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y);
 void bn_reverse(unsigned char *s, int len);
 
- const char *mp_s_rmap;
-
+extern const char *mp_s_rmap;
 
 #ifdef __cplusplus
    }

+ 19 - 14
makefile

@@ -4,7 +4,7 @@
 # Modified by Clay Culver
 
 # The version
-VERSION=0.98
+VERSION=0.99
 
 # Compiler and Linker Names
 #CC=gcc
@@ -19,13 +19,13 @@ CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wshadow
 # -Werror
 
 # optimize for SPEED
-#CFLAGS += -O3 -funroll-loops
+#CFLAGS += -O3 -funroll-all-loops
 
 #add -fomit-frame-pointer.  hinders debugging!
-CFLAGS += -fomit-frame-pointer
+#CFLAGS += -fomit-frame-pointer
 
 # optimize for SIZE
-CFLAGS += -Os
+CFLAGS += -Os -DSMALL_CODE
 
 # compile for DEBUGING (required for ccmalloc checking!!!)
 #CFLAGS += -g3
@@ -82,7 +82,7 @@ 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 \
+rmd128.o rmd160.o chc.o \
 \
 packet_store_header.o  packet_valid_header.o \
 \
@@ -114,7 +114,11 @@ pkcs_1_v15_es_encode.o pkcs_1_v15_es_decode.o pkcs_1_v15_sa_encode.o pkcs_1_v15_
 \
 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
@@ -134,7 +138,7 @@ COMPRESSED=crypt-$(VERSION).tar.bz2 crypt-$(VERSION).zip
 HEADERS=ltc_tommath.h mycrypt_cfg.h \
 mycrypt_misc.h  mycrypt_prng.h mycrypt_cipher.h  mycrypt_hash.h \
 mycrypt_macros.h  mycrypt_pk.h mycrypt.h mycrypt_argchk.h \
-mycrypt_custom.h mycrypt_pkcs.h
+mycrypt_custom.h mycrypt_pkcs.h tommath_class.h tommath_superclass.h
 
 #The default rule for make builds the libtomcrypt library.
 default:library
@@ -187,15 +191,22 @@ install: library docs
 	install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH)
 	install -g root -o root doc/crypt.pdf $(DESTDIR)$(DATAPATH)
 
+install_lib: library
+	install -d -g root -o root $(DESTDIR)$(LIBPATH)
+	install -d -g root -o root $(DESTDIR)$(INCPATH)
+	install -g root -o root $(LIBNAME) $(DESTDIR)$(LIBPATH)
+	install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH)
+
 #This rule cleans the source tree of all compiled code, not including the pdf
 #documentation.
 clean:
 	rm -f $(OBJECTS) $(TESTOBJECTS) $(HASHOBJECTS) $(CRYPTOBJECTS) $(SMALLOBJECTS) $(LEFTOVERS) $(LIBNAME)
 	rm -f $(TEST) $(HASH) $(COMPRESSED) $(PROFS) $(PROF) $(TVS) $(TV)
-	rm -f *.a *.dll *stackdump *.lib *.exe *.obj demos/*.obj demos/*.o *.bat *.txt *.il *.da demos/*.il demos/*.da *.dyn *.dpi \
+	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
@@ -230,12 +241,6 @@ profiled:
 	rm *.o *.a x86_prof
 	make CFLAGS="$(CFLAGS) -fprofile-use" EXTRALIBS=-lgcov x86_prof
 
-#beta
-beta: clean
-	cd .. ; rm -rf crypt* libtomcrypt-$(VERSION)-beta ; mkdir libtomcrypt-$(VERSION)-beta ; \
-	cp -R ./libtomcrypt/* ./libtomcrypt-$(VERSION)-beta/ ; tar -c libtomcrypt-$(VERSION)-beta/* > crypt-$(VERSION)-beta.tar ; \
-	bzip2 -9vv crypt-$(VERSION)-beta.tar ; zip -9 -r crypt-$(VERSION)-beta.zip libtomcrypt-$(VERSION)-beta/*
-
 #zipup the project (take that!)
 zipup: clean docs
 	cd .. ; rm -rf crypt* libtomcrypt-$(VERSION) ; mkdir libtomcrypt-$(VERSION) ; \

+ 9 - 5
makefile.cygwin_dll

@@ -7,13 +7,13 @@ default: ltc_dll
 CFLAGS += -I./ -Wall -Wsign-compare -W -Wno-unused -Wshadow -mno-cygwin -DWIN32
 
 # optimize for SPEED
-#CFLAGS += -O3 -funroll-loops
+CFLAGS += -O3 -funroll-all-loops
 
 #add -fomit-frame-pointer.  v3.2 is buggy for certain platforms!
-#CFLAGS += -fomit-frame-pointer
+CFLAGS += -fomit-frame-pointer
 
 # optimize for SIZE
-CFLAGS += -Os
+#CFLAGS += -Os
 
 #Leave MPI built-in or force developer to link against libtommath?
 MPIOBJECT=mpi.o
@@ -28,7 +28,7 @@ crypt_find_cipher_id.o     crypt_find_prng.o        crypt_prng_is_valid.o      \
 crypt_unregister_cipher.o  crypt_cipher_is_valid.o  crypt_find_hash.o          \
 crypt_hash_descriptor.o    crypt_register_cipher.o  crypt_unregister_hash.o    \
 \
-sprng.o fortuna.o sober128.o yarrow.o rc4.o rng_get_bytes.o  rng_make_prng.o \
+sober128.o fortuna.o sprng.o yarrow.o rc4.o rng_get_bytes.o  rng_make_prng.o \
 \
 rand_prime.o is_prime.o \
 \
@@ -47,7 +47,7 @@ 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 \
+rmd128.o rmd160.o chc.o \
 \
 packet_store_header.o  packet_valid_header.o \
 \
@@ -79,7 +79,11 @@ pkcs_1_v15_es_encode.o pkcs_1_v15_es_decode.o pkcs_1_v15_sa_encode.o pkcs_1_v15_
 \
 pkcs_5_1.o pkcs_5_2.o \
 \
+der_encode_integer.o der_decode_integer.o der_length_integer.o \
+der_put_multi_integer.o der_get_multi_integer.o \
+\
 burn_stack.o zeromem.o \
+\
 $(MPIOBJECT)
 
 #ciphers come in two flavours... enc+dec and enc 

+ 5 - 1
makefile.icc

@@ -98,7 +98,7 @@ 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 \
+rmd128.o rmd160.o chc.o \
 \
 packet_store_header.o  packet_valid_header.o \
 \
@@ -130,7 +130,11 @@ pkcs_1_v15_es_encode.o pkcs_1_v15_es_decode.o pkcs_1_v15_sa_encode.o pkcs_1_v15_
 \
 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)
 
 

+ 6 - 2
makefile.msvc

@@ -18,7 +18,7 @@ crypt_find_cipher_id.obj     crypt_find_prng.obj        crypt_prng_is_valid.obj
 crypt_unregister_cipher.obj  crypt_cipher_is_valid.obj  crypt_find_hash.obj          \
 crypt_hash_descriptor.obj    crypt_register_cipher.obj  crypt_unregister_hash.obj    \
 \
-sprng.obj fortuna.obj sober128.obj yarrow.obj rc4.obj rng_get_bytes.obj  rng_make_prng.obj \
+sober128.obj fortuna.obj sprng.obj yarrow.obj rc4.obj rng_get_bytes.obj  rng_make_prng.obj \
 \
 rand_prime.obj is_prime.obj \
 \
@@ -37,7 +37,7 @@ blowfish.obj des.obj safer_tab.obj safer.obj saferp.obj rc2.obj xtea.obj \
 rc6.obj rc5.obj cast5.obj noekeon.obj twofish.obj skipjack.obj \
 \
 md2.obj md4.obj md5.obj sha1.obj sha256.obj sha512.obj tiger.obj whirl.obj \
-rmd128.obj rmd160.obj \
+rmd128.obj rmd160.obj chc.obj \
 \
 packet_store_header.obj  packet_valid_header.obj \
 \
@@ -69,7 +69,11 @@ pkcs_1_v15_es_encode.obj pkcs_1_v15_es_decode.obj pkcs_1_v15_sa_encode.obj pkcs_
 \
 pkcs_5_1.obj pkcs_5_2.obj \
 \
+der_encode_integer.obj der_decode_integer.obj der_length_integer.obj \
+der_put_multi_integer.obj der_get_multi_integer.obj \
+\
 burn_stack.obj zeromem.obj \
+\
 $(MPIOBJECT)
 
 #ciphers come in two flavours... enc+dec and enc 

+ 186 - 0
makefile.shared

@@ -0,0 +1,186 @@
+# MAKEFILE for linux GCC
+#
+# Tom St Denis
+# Modified by Clay Culver
+
+# The version
+VERSION=0:99
+
+# Compiler and Linker Names
+CC=libtool --mode=compile gcc
+
+# Archiver [makes .a files]
+AR=libtool --mode=link 
+
+# Compilation flags. Note the += does not write over the user's CFLAGS!
+CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wshadow 
+# -Werror
+
+# optimize for SPEED
+CFLAGS += -O3 -funroll-all-loops
+
+#add -fomit-frame-pointer.  hinders debugging!
+CFLAGS += -fomit-frame-pointer
+
+# optimize for SIZE
+#CFLAGS += -Os
+
+# compile for DEBUGING (required for ccmalloc checking!!!)
+#CFLAGS += -g3
+
+#These flags control how the library gets built.
+
+#Output filenames for various targets.
+LIBNAME=libtomcrypt.la
+HASH=hashsum
+CRYPT=encrypt
+SMALL=small
+PROF=x86_prof
+TV=tv_gen
+
+#LIBPATH-The directory for libtomcrypt to be installed to.
+#INCPATH-The directory to install the header files for libtomcrypt.
+#DATAPATH-The directory to install the pdf docs.
+DESTDIR=
+LIBPATH=/usr/lib
+INCPATH=/usr/include
+DATAPATH=/usr/share/doc/libtomcrypt/pdf
+
+#List of objects to compile.
+
+#Leave MPI built-in or force developer to link against libtommath?
+MPIOBJECT=mpi.o
+
+#If you don't want mpi.o then add this
+#MPISHARED=$(LIBPATH)/libtommath.la
+
+OBJECTS=error_to_string.o mpi_to_ltc_error.o base64_encode.o base64_decode.o \
+\
+crypt.o                    crypt_find_cipher.o      crypt_find_hash_any.o      \
+crypt_hash_is_valid.o      crypt_register_hash.o    crypt_unregister_prng.o    \
+crypt_argchk.o             crypt_find_cipher_any.o  crypt_find_hash_id.o       \
+crypt_prng_descriptor.o    crypt_register_prng.o    crypt_cipher_descriptor.o  \
+crypt_find_cipher_id.o     crypt_find_prng.o        crypt_prng_is_valid.o      \
+crypt_unregister_cipher.o  crypt_cipher_is_valid.o  crypt_find_hash.o          \
+crypt_hash_descriptor.o    crypt_register_cipher.o  crypt_unregister_hash.o    \
+\
+sober128.o fortuna.o sprng.o yarrow.o rc4.o rng_get_bytes.o  rng_make_prng.o \
+\
+rand_prime.o is_prime.o \
+\
+ecc.o  dh.o \
+\
+rsa_decrypt_key.o  rsa_encrypt_key.o  rsa_exptmod.o  rsa_free.o  rsa_make_key.o  \
+rsa_sign_hash.o  rsa_verify_hash.o rsa_export.o rsa_import.o tim_exptmod.o \
+rsa_v15_encrypt_key.o rsa_v15_decrypt_key.o rsa_v15_sign_hash.o rsa_v15_verify_hash.o \
+\
+dsa_export.o  dsa_free.o  dsa_import.o  dsa_make_key.o  dsa_sign_hash.o  \
+dsa_verify_hash.o  dsa_verify_key.o \
+\
+aes.o aes_enc.o \
+\
+blowfish.o des.o safer_tab.o safer.o saferp.o rc2.o xtea.o \
+rc6.o rc5.o cast5.o noekeon.o twofish.o skipjack.o \
+\
+md2.o md4.o md5.o sha1.o sha256.o sha512.o tiger.o whirl.o \
+rmd128.o rmd160.o chc.o \
+\
+packet_store_header.o  packet_valid_header.o \
+\
+eax_addheader.o  eax_decrypt.o  eax_decrypt_verify_memory.o  eax_done.o  eax_encrypt.o  \
+eax_encrypt_authenticate_memory.o  eax_init.o  eax_test.o \
+\
+ocb_decrypt.o  ocb_decrypt_verify_memory.o  ocb_done_decrypt.o  ocb_done_encrypt.o  \
+ocb_encrypt.o  ocb_encrypt_authenticate_memory.o  ocb_init.o  ocb_ntz.o  \
+ocb_shift_xor.o  ocb_test.o s_ocb_done.o \
+\
+omac_done.o  omac_file.o  omac_init.o  omac_memory.o  omac_process.o  omac_test.o \
+\
+pmac_done.o  pmac_file.o  pmac_init.o  pmac_memory.o  pmac_ntz.o  pmac_process.o  \
+pmac_shift_xor.o  pmac_test.o \
+\
+cbc_start.o cbc_encrypt.o cbc_decrypt.o cbc_getiv.o cbc_setiv.o \
+cfb_start.o cfb_encrypt.o cfb_decrypt.o cfb_getiv.o cfb_setiv.o \
+ofb_start.o ofb_encrypt.o ofb_decrypt.o ofb_getiv.o ofb_setiv.o \
+ctr_start.o ctr_encrypt.o ctr_decrypt.o ctr_getiv.o ctr_setiv.o \
+ecb_start.o ecb_encrypt.o ecb_decrypt.o \
+\
+hash_file.o  hash_filehandle.o  hash_memory.o \
+\
+hmac_done.o  hmac_file.o  hmac_init.o  hmac_memory.o  hmac_process.o  hmac_test.o \
+\
+pkcs_1_mgf1.o pkcs_1_oaep_encode.o pkcs_1_oaep_decode.o  \
+pkcs_1_pss_encode.o pkcs_1_pss_decode.o pkcs_1_i2osp.o pkcs_1_os2ip.o \
+pkcs_1_v15_es_encode.o pkcs_1_v15_es_decode.o pkcs_1_v15_sa_encode.o pkcs_1_v15_sa_decode.o \
+\
+pkcs_5_1.o pkcs_5_2.o \
+\
+der_encode_integer.o der_decode_integer.o der_length_integer.o \
+der_put_multi_integer.o der_get_multi_integer.o \
+\
+burn_stack.o zeromem.o \
+\
+$(MPIOBJECT)
+
+TESTOBJECTS=demos/test.o
+HASHOBJECTS=demos/hashsum.o
+CRYPTOBJECTS=demos/encrypt.o
+SMALLOBJECTS=demos/small.o
+PROFS=demos/x86_prof.o
+TVS=demos/tv_gen.o
+
+#Files left over from making the crypt.pdf.
+LEFTOVERS=*.dvi *.log *.aux *.toc *.idx *.ilg *.ind *.out
+
+#Compressed filenames
+COMPRESSED=crypt-$(VERSION).tar.bz2 crypt-$(VERSION).zip
+
+#Header files used by libtomcrypt.
+HEADERS=ltc_tommath.h mycrypt_cfg.h \
+mycrypt_misc.h  mycrypt_prng.h mycrypt_cipher.h  mycrypt_hash.h \
+mycrypt_macros.h  mycrypt_pk.h mycrypt.h mycrypt_argchk.h \
+mycrypt_custom.h mycrypt_pkcs.h tommath_class.h tommath_superclass.h
+
+#The default rule for make builds the libtomcrypt library.
+default:library
+
+#ciphers come in two flavours... enc+dec and enc 
+aes_enc.o: aes.c aes_tab.c
+	$(CC) $(CFLAGS) -DENCRYPT_ONLY -c aes.c -o aes_enc.o
+
+#These are the rules to make certain object files.
+aes.o: aes.c aes_tab.c
+twofish.o: twofish.c twofish_tab.c
+whirl.o: whirl.c whirltab.c
+ecc.o: ecc.c ecc_sys.c
+dh.o: dh.c dh_sys.c
+sha512.o: sha512.c sha384.c
+sha256.o: sha256.c sha224.c
+
+#This rule makes the libtomcrypt library.
+library: $(LIBNAME)
+
+$(LIBNAME): $(OBJECTS)
+	libtool --mode=link gcc $(CFLAGS) *.lo -o libtomcrypt.la -rpath $(LIBPATH) -version-info $(VERSION)
+	libtool --mode=link gcc $(CFLAGS) *.o  -o libtomcrypt.a
+	libtool --mode=install install -c libtomcrypt.la $(LIBPATH)/libtomcrypt.la
+	install -d -g root -o root $(DESTDIR)$(INCPATH)
+	install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH)
+
+#This rule makes the hash program included with libtomcrypt
+hashsum: library
+	gcc $(CFLAGS) demos/hashsum.c -o hashsum.o
+	libtool --mode=link gcc -o hashsum hashsum.o -ltomcrypt $(MPISHARED)
+
+#makes the crypt program
+crypt: library 
+	gcc $(CFLAGS) demos/encrypt.c -o encrypt.o
+	libtool --mode=link gcc -o crypt encrypt.o -ltomcrypt $(MPISHARED)
+
+x86_prof: library
+	gcc $(CFLAGS) demos/x86_prof.c -o x86_prof.o
+	libtool --mode=link gcc -o x86_prof x86_prof.o -ltomcrypt $(MPISHARED) $(EXTRALIBS)
+
+tv_gen: library $(TVS)
+	gcc $(CFLAGS) demos/tv_gen.c -o tv_gen.o
+	libtool --mode=link gcc -o tv_gen tv_gen.o -ltomcrypt $(MPISHARED)

+ 2 - 1
md2.c

@@ -90,7 +90,7 @@ static void md2_compress(hash_state *md)
    }
 }
 
-void md2_init(hash_state *md)
+int md2_init(hash_state *md)
 {
    _ARGCHK(md != NULL);
 
@@ -99,6 +99,7 @@ void md2_init(hash_state *md)
    zeromem(md->md2.chksum, sizeof(md->md2.chksum));
    zeromem(md->md2.buf, sizeof(md->md2.buf));
    md->md2.curlen = 0;
+   return CRYPT_OK;
 }
 
 int md2_process(hash_state *md, const unsigned char *buf, unsigned long len)

+ 10 - 5
md4.c

@@ -68,9 +68,9 @@ const struct _hash_descriptor md4_desc =
   }
 
 #ifdef CLEAN_STACK
-static void _md4_compress(hash_state *md, unsigned char *buf)
+static int _md4_compress(hash_state *md, unsigned char *buf)
 #else
-static void md4_compress(hash_state *md, unsigned char *buf)
+static int  md4_compress(hash_state *md, unsigned char *buf)
 #endif
 {
     ulong32 x[16], a, b, c, d;
@@ -147,17 +147,21 @@ static void md4_compress(hash_state *md, unsigned char *buf)
     md->md4.state[1] = md->md4.state[1] + b;
     md->md4.state[2] = md->md4.state[2] + c;
     md->md4.state[3] = md->md4.state[3] + d;
+
+    return CRYPT_OK;
 }
 
 #ifdef CLEAN_STACK
-static void md4_compress(hash_state *md, unsigned char *buf)
+static int md4_compress(hash_state *md, unsigned char *buf)
 {
-   _md4_compress(md, buf);
+   int err;
+   err = _md4_compress(md, buf);
    burn_stack(sizeof(ulong32) * 20 + sizeof(int));
+   return err;
 }
 #endif
 
-void md4_init(hash_state * md)
+int md4_init(hash_state * md)
 {
    _ARGCHK(md != NULL);
    md->md4.state[0] = 0x67452301UL;
@@ -166,6 +170,7 @@ void md4_init(hash_state * md)
    md->md4.state[3] = 0x10325476UL;
    md->md4.length  = 0;
    md->md4.curlen  = 0;
+   return CRYPT_OK;
 }
 
 HASH_PROCESS(md4_process, md4_compress, md4, 64)

+ 10 - 5
md5.c

@@ -81,9 +81,9 @@ static const ulong32 Korder[64] = {
 #endif   
 
 #ifdef CLEAN_STACK
-static void _md5_compress(hash_state *md, unsigned char *buf)
+static int _md5_compress(hash_state *md, unsigned char *buf)
 #else
-static void md5_compress(hash_state *md, unsigned char *buf)
+static int  md5_compress(hash_state *md, unsigned char *buf)
 #endif
 {
     ulong32 i, W[16], a, b, c, d;
@@ -194,17 +194,21 @@ static void md5_compress(hash_state *md, unsigned char *buf)
     md->md5.state[1] = md->md5.state[1] + b;
     md->md5.state[2] = md->md5.state[2] + c;
     md->md5.state[3] = md->md5.state[3] + d;
+
+    return CRYPT_OK;
 }
 
 #ifdef CLEAN_STACK
-static void md5_compress(hash_state *md, unsigned char *buf)
+static int md5_compress(hash_state *md, unsigned char *buf)
 {
-   _md5_compress(md, buf);
+   int err;
+   err = _md5_compress(md, buf);
    burn_stack(sizeof(ulong32) * 21);
+   return err;
 }
 #endif
 
-void md5_init(hash_state * md)
+int md5_init(hash_state * md)
 {
    _ARGCHK(md != NULL);
    md->md5.state[0] = 0x67452301UL;
@@ -213,6 +217,7 @@ void md5_init(hash_state * md)
    md->md5.state[3] = 0x10325476UL;
    md->md5.curlen = 0;
    md->md5.length = 0;
+   return CRYPT_OK;
 }
 
 HASH_PROCESS(md5_process, md5_compress, md5, 64)

Dosya farkı çok büyük olduğundan ihmal edildi
+ 202 - 428
mpi.c


+ 2 - 2
mycrypt.h

@@ -16,8 +16,8 @@ extern "C" {
 #endif
 
 /* version */
-#define CRYPT   0x0098
-#define SCRYPT  "0.98"
+#define CRYPT   0x0099
+#define SCRYPT  "0.99"
 
 /* max size of either a cipher/hash block or symmetric key [largest of the two] */
 #define MAXBLOCKSIZE  64

+ 1 - 1
mycrypt_argchk.h

@@ -5,7 +5,7 @@
 #include <signal.h>
 
 /* this is the default LibTomCrypt macro  */
- void crypt_argchk(char *v, char *s, int d);
+void crypt_argchk(char *v, char *s, int d);
 #define _ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); }
 
 #elif ARGTYPE == 1

+ 6 - 0
mycrypt_cfg.h

@@ -42,6 +42,12 @@ int   XMEMCMP(const void *s1, const void *s2, size_t n);
    #define ENDIAN_64BITWORD
 #endif
 
+/* detect amd64 */
+#if defined(__x86_64__)
+   #define ENDIAN_LITTLE
+   #define ENDIAN_64BITWORD
+#endif
+
 /* #define ENDIAN_LITTLE */
 /* #define ENDIAN_BIG */
 

+ 8 - 13
mycrypt_custom.h

@@ -18,7 +18,7 @@
 #define XCLOCKS_PER_SEC CLOCKS_PER_SEC
 
 /* Use small code where possible */
-#define SMALL_CODE
+// #define SMALL_CODE
 
 /* Enable self-test test vector checking */
 #define LTC_TEST
@@ -27,7 +27,7 @@
 // #define CLEAN_STACK
 
 /* disable all file related functions */
-//#define NO_FILE
+// #define NO_FILE
 
 /* various ciphers */
 #define BLOWFISH
@@ -37,10 +37,13 @@
 #define SAFERP
 #define RIJNDAEL
 #define XTEA
+/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format
+ * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */
 #define TWOFISH
 #define TWOFISH_TABLES
 // #define TWOFISH_ALL_TABLES
 // #define TWOFISH_SMALL
+/* DES includes EDE triple-DES */
 #define DES
 #define CAST5
 #define NOEKEON
@@ -50,7 +53,7 @@
  */
 //#define SAFER
 
-/* modes of operation */
+/* block cipher modes of operation */
 #define CFB
 #define OFB
 #define ECB
@@ -58,6 +61,7 @@
 #define CTR
 
 /* hash functions */
+#define CHC_HASH
 #define WHIRLPOOL
 #define SHA512
 #define SHA384
@@ -147,16 +151,7 @@
 /* Include the MPI functionality?  (required by the PK algorithms) */
 #define MPI
 
-/* Use SSE2 optimizations in LTM?  Requires GCC or ICC and a P4 or K8 processor */
-// #define LTMSSE
-
-/* prevents the code from being "unportable" at least to non i386 platforms */
-#if defined(LTMSSE) && !( (defined(__GNUC__) && defined(__i386__)) || defined(INTEL_CC)) 
-   #warning LTMSSE is only available for GNU CC (i386) or Intel CC
-   #undef LTMSSE
-#endif
-
-/* PKCS #1 and #5 stuff */
+/* PKCS #1 (RSA) and #5 (Password Handling) stuff */
 #define PKCS_1
 #define PKCS_5
 

+ 52 - 29
mycrypt_hash.h

@@ -78,7 +78,18 @@ struct whirlpool_state {
 };
 #endif
 
+#ifdef CHC_HASH
+struct chc_state {
+    ulong64 length;
+    unsigned char state[MAXBLOCKSIZE], buf[MAXBLOCKSIZE];
+    ulong32 curlen;
+};
+#endif
+
 typedef union Hash_state {
+#ifdef CHC_HASH
+    struct chc_state chc;
+#endif
 #ifdef WHIRLPOOL
     struct whirlpool_state whirlpool;
 #endif
@@ -118,26 +129,34 @@ extern  struct _hash_descriptor {
     unsigned long blocksize;      /* the block size the hash uses */
     unsigned char DER[64];        /* DER encoded identifier */
     unsigned long DERlen;         /* length of DER encoding */
-    void (*init)(hash_state *);
+    int (*init)(hash_state *);
     int (*process)(hash_state *, const unsigned char *, unsigned long);
     int (*done)(hash_state *, unsigned char *);
-    int  (*test)(void);
+    int (*test)(void);
 } hash_descriptor[];
 
+#ifdef CHC_HASH
+ int chc_register(int cipher);
+ int chc_init(hash_state * md);
+ int chc_process(hash_state * md, const unsigned char *buf, unsigned long len);
+ int chc_done(hash_state * md, unsigned char *hash);
+ int chc_test(void);
+ extern const struct _hash_descriptor chc_desc;
+#endif
 
 #ifdef WHIRLPOOL
- void whirlpool_init(hash_state * md);
+ int whirlpool_init(hash_state * md);
  int whirlpool_process(hash_state * md, const unsigned char *buf, unsigned long len);
  int whirlpool_done(hash_state * md, unsigned char *hash);
- int  whirlpool_test(void);
+ int whirlpool_test(void);
  extern const struct _hash_descriptor whirlpool_desc;
 #endif
 
 #ifdef SHA512
- void sha512_init(hash_state * md);
+ int sha512_init(hash_state * md);
  int sha512_process(hash_state * md, const unsigned char *buf, unsigned long len);
  int sha512_done(hash_state * md, unsigned char *hash);
- int  sha512_test(void);
+ int sha512_test(void);
  extern const struct _hash_descriptor sha512_desc;
 #endif
 
@@ -145,89 +164,88 @@ extern  struct _hash_descriptor {
 #ifndef SHA512
    #error SHA512 is required for SHA384
 #endif
- void sha384_init(hash_state * md);
+ int sha384_init(hash_state * md);
 #define sha384_process sha512_process
  int sha384_done(hash_state * md, unsigned char *hash);
- int  sha384_test(void);
+ int sha384_test(void);
  extern const struct _hash_descriptor sha384_desc;
 #endif
 
 #ifdef SHA256
- void sha256_init(hash_state * md);
+ int sha256_init(hash_state * md);
  int sha256_process(hash_state * md, const unsigned char *buf, unsigned long len);
  int sha256_done(hash_state * md, unsigned char *hash);
- int  sha256_test(void);
+ int sha256_test(void);
  extern const struct _hash_descriptor sha256_desc;
 
 #ifdef SHA224
 #ifndef SHA256
    #error SHA256 is required for SHA224
 #endif
- void sha224_init(hash_state * md);
+ int sha224_init(hash_state * md);
 #define sha224_process sha256_process
  int sha224_done(hash_state * md, unsigned char *hash);
- int  sha224_test(void);
+ int sha224_test(void);
  extern const struct _hash_descriptor sha224_desc;
 #endif
 #endif
 
 #ifdef SHA1
- void sha1_init(hash_state * md);
+ int sha1_init(hash_state * md);
  int sha1_process(hash_state * md, const unsigned char *buf, unsigned long len);
  int sha1_done(hash_state * md, unsigned char *hash);
- int  sha1_test(void);
+ int sha1_test(void);
  extern const struct _hash_descriptor sha1_desc;
 #endif
 
 #ifdef MD5
- void md5_init(hash_state * md);
+ int md5_init(hash_state * md);
  int md5_process(hash_state * md, const unsigned char *buf, unsigned long len);
  int md5_done(hash_state * md, unsigned char *hash);
- int  md5_test(void);
+ int md5_test(void);
  extern const struct _hash_descriptor md5_desc;
 #endif
 
 #ifdef MD4
- void md4_init(hash_state * md);
+ int md4_init(hash_state * md);
  int md4_process(hash_state * md, const unsigned char *buf, unsigned long len);
  int md4_done(hash_state * md, unsigned char *hash);
- int  md4_test(void);
+ int md4_test(void);
  extern const struct _hash_descriptor md4_desc;
 #endif
 
 #ifdef MD2
- void md2_init(hash_state * md);
+ int md2_init(hash_state * md);
  int md2_process(hash_state * md, const unsigned char *buf, unsigned long len);
  int md2_done(hash_state * md, unsigned char *hash);
- int  md2_test(void);
+ int md2_test(void);
  extern const struct _hash_descriptor md2_desc;
 #endif
 
 #ifdef TIGER
- void tiger_init(hash_state * md);
+ int tiger_init(hash_state * md);
  int tiger_process(hash_state * md, const unsigned char *buf, unsigned long len);
  int tiger_done(hash_state * md, unsigned char *hash);
- int  tiger_test(void);
+ int tiger_test(void);
  extern const struct _hash_descriptor tiger_desc;
 #endif
 
 #ifdef RIPEMD128
- void rmd128_init(hash_state * md);
+ int rmd128_init(hash_state * md);
  int rmd128_process(hash_state * md, const unsigned char *buf, unsigned long len);
  int rmd128_done(hash_state * md, unsigned char *hash);
- int  rmd128_test(void);
+ int rmd128_test(void);
  extern const struct _hash_descriptor rmd128_desc;
 #endif
 
 #ifdef RIPEMD160
- void rmd160_init(hash_state * md);
+ int rmd160_init(hash_state * md);
  int rmd160_process(hash_state * md, const unsigned char *buf, unsigned long len);
  int rmd160_done(hash_state * md, unsigned char *hash);
- int  rmd160_test(void);
+ int rmd160_test(void);
  extern const struct _hash_descriptor rmd160_desc;
 #endif
 
-
  int find_hash(const char *name);
  int find_hash_id(unsigned char ID);
  int find_hash_any(const char *name, int digestlen);
@@ -244,6 +262,7 @@ extern  struct _hash_descriptor {
 int func_name (hash_state * md, const unsigned char *buf, unsigned long len)               \
 {                                                                                           \
     unsigned long n;                                                                        \
+    int           err;                                                                      \
     _ARGCHK(md != NULL);                                                                    \
     _ARGCHK(buf != NULL);                                                                   \
     if (md-> state_var .curlen > sizeof(md-> state_var .buf)) {                             \
@@ -251,7 +270,9 @@ int func_name (hash_state * md, const unsigned char *buf, unsigned long len)
     }                                                                                       \
     while (len > 0) {                                                                       \
         if (md-> state_var .curlen == 0 && len >= block_size) {                             \
-           compress_name (md, (unsigned char *)buf);                                        \
+           if ((err = compress_name (md, (unsigned char *)buf)) != CRYPT_OK) { \
+              return err;         \
+           }                                        \
            md-> state_var .length += block_size * 8;                                        \
            buf             += block_size;                                                   \
            len             -= block_size;                                                   \
@@ -262,7 +283,9 @@ int func_name (hash_state * md, const unsigned char *buf, unsigned long len)
            buf             += n;                                                            \
            len             -= n;                                                            \
            if (md-> state_var .curlen == block_size) {                                      \
-              compress_name (md, md-> state_var .buf);                                      \
+              if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) {\
+                 return err;                                      \
+              } \
               md-> state_var .length += 8*block_size;                                       \
               md-> state_var .curlen = 0;                                                   \
            }                                                                                \

+ 30 - 4
mycrypt_macros.h

@@ -10,7 +10,11 @@
 /* this is the "32-bit at least" data type 
  * Re-define it to suit your platform but it must be at least 32-bits 
  */
-typedef unsigned long ulong32;
+#if defined(__x86_64__)
+   typedef unsigned ulong32;
+#else
+   typedef unsigned long ulong32;
+#endif
 
 /* ---- HELPER MACROS ---- */
 #ifdef ENDIAN_NEUTRAL
@@ -194,9 +198,9 @@ typedef unsigned long ulong32;
 #define ROR(x,n) _lrotr(x,n)
 #define ROL(x,n) _lrotl(x,n)
 
-#elif defined(__GNUC__) && defined(__i386__) && !defined(INTEL_CC)
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC)
 
-static inline unsigned long ROL(unsigned long word, int i)
+static inline unsigned ROL(unsigned word, int i)
 {
    __asm__("roll %%cl,%0"
       :"=r" (word)
@@ -204,7 +208,7 @@ static inline unsigned long ROL(unsigned long word, int i)
    return word;
 }
 
-static inline unsigned long ROR(unsigned long word, int i)
+static inline unsigned ROR(unsigned word, int i)
 {
    __asm__("rorl %%cl,%0"
       :"=r" (word)
@@ -220,6 +224,26 @@ static inline unsigned long ROR(unsigned long word, int i)
 
 #endif
 
+#if defined(__GNUCC__) && defined(__x86_64__)
+
+static inline unsigned long ROL64(unsigned long word, int i)
+{
+   __asm__("rolq %%cl,%0"
+      :"=r" (word)
+      :"0" (word),"c" (i));
+   return word;
+}
+
+static inline unsigned long ROR64(unsigned long word, int i)
+{
+   __asm__("rorq %%cl,%0"
+      :"=r" (word)
+      :"0" (word),"c" (i));
+   return word;
+}
+
+#else
+
 #define ROL64(x, y) \
     ( (((x)<<((ulong64)(y)&63)) | \
       (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
@@ -228,6 +252,8 @@ static inline unsigned long ROR(unsigned long word, int i)
     ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
       ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
 
+#endif
+
 #undef MAX
 #undef MIN
 #define MAX(x, y) ( ((x)>(y))?(x):(y) )

+ 9 - 2
mycrypt_pk.h

@@ -67,7 +67,6 @@
 
 #define PK_PRIVATE            0        /* PK private keys */
 #define PK_PUBLIC             1        /* PK public keys */
-#define PK_PRIVATE_OPTIMIZED  2        /* PK private key [rsa optimized] */
 
 /* ---- PACKET ---- */
 #ifdef PACKET
@@ -90,7 +89,7 @@
 
 typedef struct Rsa_key {
     int type;
-    mp_int e, d, N, qP, pQ, dP, dQ, p, q;
+    mp_int e, d, N, p, q, qP, dP, dQ;
 } rsa_key;
 
  int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key);
@@ -276,3 +275,11 @@ typedef struct {
  int dsa_verify_key(dsa_key *key, int *stat);
 
 #endif
+
+/* DER handling */
+int der_encode_integer(mp_int *num, unsigned char *out, unsigned long *outlen);
+int der_decode_integer(const unsigned char *in, unsigned long *inlen, mp_int *num);
+int der_length_integer(mp_int *num, unsigned long *len);
+int der_put_multi_integer(unsigned char *dst, unsigned long *outlen, mp_int *num, ...);
+int der_get_multi_integer(const unsigned char *src, unsigned long *inlen,  mp_int *num, ...);
+

+ 2 - 2
mycrypt_prng.h

@@ -60,8 +60,8 @@ extern struct _prng_descriptor {
     int (*ready)(prng_state *);
     unsigned long (*read)(unsigned char *, unsigned long, prng_state *);
     int (*done)(prng_state *);
-    int (*export)(unsigned char *, unsigned long *, prng_state *);
-    int (*import)(const unsigned char *, unsigned long, prng_state *);
+    int (*pexport)(unsigned char *, unsigned long *, prng_state *);
+    int (*pimport)(const unsigned char *, unsigned long, prng_state *);
     int (*test)(void);
 } prng_descriptor[];
 

+ 35 - 0
notes/hash_tv.txt

@@ -1734,3 +1734,38 @@ Hash: whirlpool
 127: 3C9A7F387B7104DF19CF264B0B5821B2E46E44ADC79262546E98FFA113EB3D45799EAC78CCA4643C937FCC3C1D249A212FACB34C63D45EEC81069095D7CDCE7B
 128: 803A3B37C89E84FBBEC75BEE3D00DD728FFC4246B5A5E989DC8DC2CD0F7937966AB78C79E1D4648EE6EB40F3D70491CB46B8AB42E155672E2AB8374FCF70DD79
 
+Hash: chc_hash
+  0: 4047929F1F572643B55F829EB3291D11
+  1: 8898FD04F810507740E7A8DBF44C18E8
+  2: 1445928BB912A6D3C5111923B6C5D48D
+  3: D85B2E8854D16A440CF32DDDA741DA52
+  4: 5F3082124472598098B03649EA409CDC
+  5: 604A19622A06D0486D559A07C95B297A
+  6: A16F89E4DACA6C8174C9D66AA23B15AF
+  7: FC6893F79A2D28315FBBEFCAF0280793
+  8: 6A80F04CB93B1CFB947DED28141E877A
+  9: D036D0B4DEF1FA138C3181367143D1A9
+ 10: F031A2DC2A196B268046F73728EE7831
+ 11: 2E05C9B5A43CFB01AD026ABA8AE8201F
+ 12: 8B49EF0BC936792F905E61AE621E63C3
+ 13: 485CF5E83BC66843D446D9922547E43B
+ 14: 704767A75D1FD6639CE72291AE1F6CD8
+ 15: 19F6228C2531747CB20F644F9EC65691
+ 16: B78FEC0628D7F47B042A3C15C57750FB
+ 17: 3EF9AFAAFAE9C80D09CD078E1CC0BD8A
+ 18: 5E4501C8DD0D49589F4FFA20F278D316
+ 19: 00D2D0FDD0E0476C9D40DE5A04508849
+ 20: CC7382E78D8DF07F0BAB66203F191745
+ 21: 85B841BCCCB4AD2420BCABCFD06A0757
+ 22: 7159E38F4D7E4CEBEBF86A65A984BA2A
+ 23: C8949A9D92601726F77E1AEF0E5F1E0F
+ 24: 8CE35EF6EC7DDA294134077420159F68
+ 25: A0F4E4522832676B49E7CD393E6D9761
+ 26: F55C27D180948585819833322D7BC4CA
+ 27: 0A3975A0113E1FE6A66F8C7D529715B5
+ 28: F77135C5D04096181305C0906BAEE789
+ 29: 31FF81B49B9003D73F878F810D49C851
+ 30: BE1E12BF021D0DB2FC5CE7D5348A1DE7
+ 31: CB4AF60D7340EC6849574DF1E5BAA24E
+ 32: 7C5ABDBA19396D7BE48C2A84F8CC747B
+

+ 35 - 0
notes/hmac_tv.txt

@@ -1734,3 +1734,38 @@ HMAC-whirlpool
 127: 1D8B2525E519A3FF8BDAAF31E80EE695F5914B78E7DAB801729B5D84C3A7A2B36A33803F5E0723981CF8A9586EC1BEABC58154EFD919AFF08935FBD756327AAB
 128: 4AABF1C3F24C20FFAA61D6106E32EF1BB7CDEB607354BD4B6251893941730054244E198EECD4943C77082CC9B406A2E12271BCA455DF15D3613336615C36B22E
 
+HMAC-chc_hash
+  0: 0607F24D43AA98A86FCC45B53DA04F9D
+  1: BE4FB5E0BC4BD8132DB14BCBD7E4CD10
+  2: A3246C609FE39D7C9F7CFCF16185FB48
+  3: 3C7EA951205937240F0756BC0F2F4D1B
+  4: 7F69A5DD411DFE6BB99D1B8391B31272
+  5: DCB4D4D7F3B9AF6F51F30DCF733068CC
+  6: 1363B27E6B28BCD8AE3DCD0F55B387D7
+  7: BB525342845B1253CFE98F00237A85F3
+  8: 89FB247A36A9926FDA10F2013119151B
+  9: 54EB023EF9CE37EDC986373E23A9ED16
+ 10: 2358D8884471CB1D9E233107C7A7A4A0
+ 11: 94BAB092B00574C5FBEB1D7E54B684C4
+ 12: DF1819707621B8A66D9709397E92DC2F
+ 13: 3044DFFC7947787FDB12F62141B9E4FB
+ 14: 9EA9943FC2635AD852D1C5699234915D
+ 15: 1CC75C985BE6EDD3AD5907ED72ECE05E
+ 16: 1A826C4817FF59E686A59B0B96C9A619
+ 17: 44DB2A64264B125DE535A182CB7B2B2C
+ 18: 4741D46F73F2A860F95751E7E14CC244
+ 19: 13FDD4463084FEEB24F713DD9858E7F4
+ 20: D3308382E65E588D576D970A792BAC61
+ 21: 38E04BD5885FEA9E140F065F37DD09FC
+ 22: 5C309499657F24C1812FD8B926A419E2
+ 23: D1FDB9E8AC245737DA836D68FA507736
+ 24: F6924085988770FCC3BC9EEA8F72604E
+ 25: C72B261A79411F74D707C6B6F45823BD
+ 26: 2ED2333EBAC77F291FC6E844F2A7E42D
+ 27: CE0D3EF674917CEA5171F1A52EA62AAE
+ 28: 55EDEAC9F935ABEAF2956C8E83F3E447
+ 29: 820B799CB66DC9763FFD9AB634D971EC
+ 30: E14B18AB25025BF5DF2C1A73C235AD8B
+ 31: DE9F394575B9F525A734F302F0DB0A42
+ 32: 625ED3B09144ADFF57B6659BB2044FBE
+

+ 7 - 5
omac_done.c

@@ -15,10 +15,12 @@
 
 int omac_done(omac_state *state, unsigned char *out, unsigned long *outlen)
 {
-   int err, mode, x;
+   int       err, mode;
+   unsigned  x;
 
-   _ARGCHK(state != NULL);
-   _ARGCHK(out   != NULL);
+   _ARGCHK(state  != NULL);
+   _ARGCHK(out    != NULL);
+   _ARGCHK(outlen != NULL);
    if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) {
       return err;
    }
@@ -43,7 +45,7 @@ int omac_done(omac_state *state, unsigned char *out, unsigned long *outlen)
    }
 
    /* now xor prev + Lu[mode] */
-   for (x = 0; x < state->blklen; x++) {
+   for (x = 0; x < (unsigned)state->blklen; x++) {
        state->block[x] ^= state->prev[x] ^ state->Lu[mode][x];
    }
 
@@ -51,7 +53,7 @@ int omac_done(omac_state *state, unsigned char *out, unsigned long *outlen)
    cipher_descriptor[state->cipher_idx].ecb_encrypt(state->block, state->block, &state->key);
  
    /* output it */
-   for (x = 0; x < state->blklen && (unsigned long)x < *outlen; x++) {
+   for (x = 0; x < (unsigned)state->blklen && x < *outlen; x++) {
        out[x] = state->block[x];
    }
    *outlen = x;

+ 4 - 1
omac_test.c

@@ -65,7 +65,7 @@ int omac_test(void)
 
     };
     unsigned char out[16];
-    int x, y, err, idx;
+    int x, err, idx;
     unsigned long len;
 
 
@@ -83,8 +83,11 @@ int omac_test(void)
        }
 
        if (memcmp(out, tests[x].tag, 16) != 0) {
+#if 0
+          int y;
           printf("\n\nTag: ");
           for (y = 0; y < 16; y++) printf("%02x", out[y]); printf("\n\n");
+#endif
           return CRYPT_FAIL_TESTVECTOR;
        }
     }

+ 3 - 1
pkcs_1_mgf1.c

@@ -56,7 +56,9 @@ int pkcs_1_mgf1(const unsigned char *seed, unsigned long seedlen,
        ++counter;
 
        /* get hash of seed || counter */
-       hash_descriptor[hash_idx].init(md);
+       if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) {
+          goto __ERR;
+       }
        if ((err = hash_descriptor[hash_idx].process(md, seed, seedlen)) != CRYPT_OK) {
           goto __ERR;
        }

+ 3 - 1
pkcs_1_pss_decode.c

@@ -118,7 +118,9 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
    }
 
    /* M = (eight) 0x00 || msghash || salt, mask = H(M) */
-   hash_descriptor[hash_idx].init(&md);
+   if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) {
+      goto __ERR;
+   }
    zeromem(mask, 8);
    if ((err = hash_descriptor[hash_idx].process(&md, mask, 8)) != CRYPT_OK) {
       goto __ERR;

+ 3 - 1
pkcs_1_pss_encode.c

@@ -77,7 +77,9 @@ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
    }
 
    /* M = (eight) 0x00 || msghash || salt, hash = H(M) */
-   hash_descriptor[hash_idx].init(&md);
+   if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) {
+      goto __ERR;
+   }
    zeromem(DB, 8);
    if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) {
       goto __ERR;

+ 3 - 1
pkcs_5_1.c

@@ -47,7 +47,9 @@ int pkcs_5_alg1(const unsigned char *password, unsigned long password_len,
    }        
 
    /* hash initial password + salt */
-   hash_descriptor[hash_idx].init(md);
+   if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) {
+       goto __ERR;
+   }
    if ((err = hash_descriptor[hash_idx].process(md, password, password_len)) != CRYPT_OK) {
        goto __ERR;
    }

+ 10 - 5
rmd128.c

@@ -75,9 +75,9 @@ const struct _hash_descriptor rmd128_desc =
       (a) = ROL((a), (s));
 
 #ifdef CLEAN_STACK
-static void _rmd128_compress(hash_state *md, unsigned char *buf)
+static int _rmd128_compress(hash_state *md, unsigned char *buf)
 #else
-static void rmd128_compress(hash_state *md, unsigned char *buf)
+static int  rmd128_compress(hash_state *md, unsigned char *buf)
 #endif
 {
    ulong32 aa,bb,cc,dd,aaa,bbb,ccc,ddd,X[16];
@@ -244,17 +244,21 @@ static void rmd128_compress(hash_state *md, unsigned char *buf)
    md->rmd128.state[2] = md->rmd128.state[3] + aa + bbb;
    md->rmd128.state[3] = md->rmd128.state[0] + bb + ccc;
    md->rmd128.state[0] = ddd;
+
+   return CRYPT_OK;
 }
 
 #ifdef CLEAN_STACK
-static void rmd128_compress(hash_state *md, unsigned char *buf)
+static int rmd128_compress(hash_state *md, unsigned char *buf)
 {
-   _rmd128_compress(md, buf);
+   int err;
+   err = _rmd128_compress(md, buf);
    burn_stack(sizeof(ulong32) * 24 + sizeof(int));
+   return err;
 }
 #endif
 
-void rmd128_init(hash_state * md)
+int rmd128_init(hash_state * md)
 {
    _ARGCHK(md != NULL);
    md->rmd128.state[0] = 0x67452301UL;
@@ -263,6 +267,7 @@ void rmd128_init(hash_state * md)
    md->rmd128.state[3] = 0x10325476UL;
    md->rmd128.curlen   = 0;
    md->rmd128.length   = 0;
+   return CRYPT_OK;
 }
 
 HASH_PROCESS(rmd128_process, rmd128_compress, rmd128, 64)

+ 10 - 5
rmd160.c

@@ -96,9 +96,9 @@ const struct _hash_descriptor rmd160_desc =
 
 
 #ifdef CLEAN_STACK
-static void _rmd160_compress(hash_state *md, unsigned char *buf)
+static int _rmd160_compress(hash_state *md, unsigned char *buf)
 #else
-static void rmd160_compress(hash_state *md, unsigned char *buf)
+static int  rmd160_compress(hash_state *md, unsigned char *buf)
 #endif
 {
    ulong32 aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16];
@@ -303,17 +303,21 @@ static void rmd160_compress(hash_state *md, unsigned char *buf)
    md->rmd160.state[3] = md->rmd160.state[4] + aa + bbb;
    md->rmd160.state[4] = md->rmd160.state[0] + bb + ccc;
    md->rmd160.state[0] = ddd;
+
+   return CRYPT_OK;
 }
 
 #ifdef CLEAN_STACK
-static void rmd160_compress(hash_state *md, unsigned char *buf)
+static int rmd160_compress(hash_state *md, unsigned char *buf)
 {
-   _rmd160_compress(md, buf);
+   int err;
+   err = _rmd160_compress(md, buf);
    burn_stack(sizeof(ulong32) * 26 + sizeof(int));
+   return err;
 }
 #endif
 
-void rmd160_init(hash_state * md)
+int rmd160_init(hash_state * md)
 {
    _ARGCHK(md != NULL);
    md->rmd160.state[0] = 0x67452301UL;
@@ -323,6 +327,7 @@ void rmd160_init(hash_state * md)
    md->rmd160.state[4] = 0xc3d2e1f0UL;
    md->rmd160.curlen   = 0;
    md->rmd160.length   = 0;
+   return CRYPT_OK;
 }
 
 HASH_PROCESS(rmd160_process, rmd160_compress, rmd160, 64)

+ 25 - 42
rsa_export.c

@@ -13,60 +13,43 @@
 
 #ifdef MRSA
 
-/* Export an RSA key */
+/* This will export either an RSAPublicKey or RSAPrivateKey [defined in PKCS #1 v2.1] */
 int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key)
 {
-   unsigned long y, z; 
    int err;
 
    _ARGCHK(out    != NULL);
    _ARGCHK(outlen != NULL);
    _ARGCHK(key    != NULL);
-   
-   /* can we store the static header?  */
-   if (*outlen < (PACKET_SIZE + 1)) {
-      return CRYPT_BUFFER_OVERFLOW;
-   }   
 
    /* type valid? */
-   if (!(key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) &&
-        (type == PK_PRIVATE || type == PK_PRIVATE_OPTIMIZED)) {
+   if (!(key->type == PK_PRIVATE) && (type == PK_PRIVATE)) {
       return CRYPT_PK_INVALID_TYPE;
    }
-
-   /* start at offset y=PACKET_SIZE */
-   y = PACKET_SIZE;
-
-   /* output key type */
-   out[y++] = type;
-
-   /* output modulus */
-   OUTPUT_BIGNUM(&key->N, out, y, z);
-
-   /* output public key */
-   OUTPUT_BIGNUM(&key->e, out, y, z);
-
-   if (type == PK_PRIVATE || type == PK_PRIVATE_OPTIMIZED) {
-      OUTPUT_BIGNUM(&key->d, out, y, z);
+  
+   if (type == PK_PRIVATE) {
+      /* private key */
+      mp_int zero;
+
+      /* first INTEGER == 0 to signify two-prime RSA */
+      if ((err = mp_init(&zero)) != MP_OKAY) {
+         return mpi_to_ltc_error(err);
+      }
+ 
+      /* output is 
+            Version, n, e, d, p, q, d mod (p-1), d mod (q - 1), 1/q mod p
+       */
+      err = der_put_multi_integer(out, outlen, &zero, &key->N, &key->e,
+                          &key->d, &key->p, &key->q, &key->dP,
+                          &key->dQ, &key->qP, NULL);
+ 
+      /* clear zero and return */
+      mp_clear(&zero);
+      return err;
+   } else {
+      /* public key */
+      return der_put_multi_integer(out, outlen, &key->N, &key->e, NULL);
    }
-
-   if (type == PK_PRIVATE_OPTIMIZED) {
-      OUTPUT_BIGNUM(&key->dQ, out, y, z);
-      OUTPUT_BIGNUM(&key->dP, out, y, z);
-      OUTPUT_BIGNUM(&key->pQ, out, y, z);
-      OUTPUT_BIGNUM(&key->qP, out, y, z);
-      OUTPUT_BIGNUM(&key->p, out, y, z);
-      OUTPUT_BIGNUM(&key->q, out, y, z);
-   }
-
-   /* store packet header */
-   packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_KEY);
-
-   /* copy to the user buffer */
-   *outlen = y;
-
-   /* clear stack and return */
-   return CRYPT_OK;
 }
 
 #endif /* MRSA */

+ 11 - 12
rsa_exptmod.c

@@ -35,7 +35,7 @@ int rsa_exptmod(const unsigned char *in,   unsigned long inlen,
    }
 
    /* is the key of the right type for the operation? */
-   if (which == PK_PRIVATE && (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED)) {
+   if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) {
       return CRYPT_PK_NOT_PRIVATE;
    }
 
@@ -45,7 +45,7 @@ int rsa_exptmod(const unsigned char *in,   unsigned long inlen,
    }
 
    /* init and copy into tmp */
-   if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != MP_OKAY)                     { goto error; }
+   if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != MP_OKAY)                     { return mpi_to_ltc_error(err); }
    if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, (int)inlen)) != MP_OKAY) { goto error; }
 
    /* sanity check on the input */
@@ -55,24 +55,23 @@ int rsa_exptmod(const unsigned char *in,   unsigned long inlen,
    }
 
    /* are we using the private exponent and is the key optimized? */
-   if (which == PK_PRIVATE && key->type == PK_PRIVATE_OPTIMIZED) {
+   if (which == PK_PRIVATE) {
       /* tmpa = tmp^dP mod p */
       if ((err = tim_exptmod(prng, prng_idx, &tmp, &key->e, &key->dP, &key->p, &tmpa)) != MP_OKAY)    { goto error; }
 
       /* tmpb = tmp^dQ mod q */
       if ((err = tim_exptmod(prng, prng_idx, &tmp, &key->e,  &key->dQ, &key->q, &tmpb)) != MP_OKAY)    { goto error; }
 
-      /* tmp = tmpa*qP + tmpb*pQ mod N */
-      if ((err = mp_mul(&tmpa, &key->qP, &tmpa)) != MP_OKAY)                { goto error; }
-      if ((err = mp_mul(&tmpb, &key->pQ, &tmpb)) != MP_OKAY)                { goto error; }
-      if ((err = mp_addmod(&tmpa, &tmpb, &key->N, &tmp)) != MP_OKAY)        { goto error; }
+      /* tmp = (tmpa - tmpb) * qInv (mod p) */
+      if ((err = mp_sub(&tmpa, &tmpb, &tmp)) != MP_OKAY)                    { goto error; }
+      if ((err = mp_mulmod(&tmp, &key->qP, &key->p, &tmp)) != MP_OKAY)      { goto error; }
+
+      /* tmp = tmpb + q * tmp */
+      if ((err = mp_mul(&tmp, &key->q, &tmp)) != MP_OKAY)                   { goto error; }
+      if ((err = mp_add(&tmp, &tmpb, &tmp)) != MP_OKAY)                     { goto error; }
    } else {
       /* exptmod it */
-      if (which == PK_PRIVATE) {
-         if ((err = tim_exptmod(prng, prng_idx, &tmp, &key->e, &key->d, &key->N, &tmp)) != MP_OKAY) { goto error; }
-      } else {
-         if ((err = mp_exptmod(&tmp, &key->e, &key->N, &tmp)) != MP_OKAY) { goto error; }
-      }
+      if ((err = mp_exptmod(&tmp, &key->e, &key->N, &tmp)) != MP_OKAY) { goto error; }
    }
 
    /* read it back */

+ 1 - 1
rsa_free.c

@@ -18,7 +18,7 @@ void rsa_free(rsa_key *key)
 {
    _ARGCHK(key != NULL);
    mp_clear_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP,
-                  &key->qP, &key->pQ, &key->p, &key->q, NULL);
+                  &key->qP, &key->p, &key->q, NULL);
 }
 
 #endif

+ 32 - 44
rsa_import.c

@@ -13,67 +13,55 @@
 
 #ifdef MRSA
 
+/* import an RSAPublicKey or RSAPrivateKey [two-prime only, defined in PKCS #1 v2.1] */
 int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
 {
-   unsigned long x, y;
+   unsigned long x;
    int err;
 
    _ARGCHK(in  != NULL);
    _ARGCHK(key != NULL);
 
-   /* check length */
-   if (inlen < (1+PACKET_SIZE)) {
-      return CRYPT_INVALID_PACKET;
-   }
-
-   /* test packet header */
-   if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_KEY)) != CRYPT_OK) {
-      return err;
-   }
-
    /* init key */
    if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP,
-                     &key->pQ, &key->p, &key->q, NULL)) != MP_OKAY) {
+                     &key->p, &key->q, NULL)) != MP_OKAY) {
       return mpi_to_ltc_error(err);
    }
 
-   /* get key type */
-   y = PACKET_SIZE;
-   key->type = (int)in[y++];
-
-   /* load the modulus  */
-   INPUT_BIGNUM(&key->N, in, x, y, inlen);
-
-   /* load public exponent */
-   INPUT_BIGNUM(&key->e, in, x, y, inlen);
-
-   /* get private exponent */
-   if (key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) {
-      INPUT_BIGNUM(&key->d, in, x, y, inlen);
-   }
-
-   /* 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);
+   /* read first number, it's either N or 0 [0 == private key] */
+   x = inlen;
+   if ((err = der_get_multi_integer(in, &x, &key->N, NULL)) != CRYPT_OK) {
+      goto __ERR;
    }
 
-   /* 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);
+   /* advance */
+   inlen -= x;
+   in    += x;
+
+   if (mp_cmp_d(&key->N, 0) == MP_EQ) {
+      /* it's a private key */
+      if ((err = der_get_multi_integer(in, &inlen, &key->N, &key->e,
+                          &key->d, &key->p, &key->q, &key->dP,
+                          &key->dQ, &key->qP, NULL)) != CRYPT_OK) {
+         goto __ERR;
+      }
+
+      key->type = PK_PRIVATE;
+   } else {
+      /* it's a public key and we lack e */
+      if ((err = der_get_multi_integer(in, &inlen, &key->e, NULL)) != CRYPT_OK) {
+         goto __ERR;
+      }
+
+      /* free up some ram */
+      mp_clear_multi(&key->p, &key->q, &key->qP, &key->dP, &key->dQ, NULL);
+
+      key->type = PK_PUBLIC;
    }
-   if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) {
-      mp_clear(&key->d);
-   }
-
    return CRYPT_OK;
-error:
+__ERR:
    mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,
-                  &key->pQ, &key->qP, &key->p, &key->q, NULL);
+                  &key->qP, &key->p, &key->q, NULL);
    return err;
 }
 

+ 3 - 10
rsa_make_key.c

@@ -61,7 +61,7 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
 
    /* make key */
    if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP,
-                     &key->qP, &key->pQ, &key->p, &key->q, NULL)) != MP_OKAY) {
+                     &key->qP, &key->p, &key->q, NULL)) != MP_OKAY) {
       goto error;
    }
 
@@ -73,15 +73,9 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
    /* find d mod q-1 and d mod p-1 */
    if ((err = mp_sub_d(&p, 1, &tmp1)) != MP_OKAY)                     { goto error2; } /* tmp1 = q-1 */
    if ((err = mp_sub_d(&q, 1, &tmp2)) != MP_OKAY)                     { goto error2; } /* tmp2 = p-1 */
-
    if ((err = mp_mod(&key->d, &tmp1, &key->dP)) != MP_OKAY)           { goto error2; } /* dP = d mod p-1 */
    if ((err = mp_mod(&key->d, &tmp2, &key->dQ)) != MP_OKAY)           { goto error2; } /* dQ = d mod q-1 */
-
    if ((err = mp_invmod(&q, &p, &key->qP)) != MP_OKAY)                { goto error2; } /* qP = 1/q mod p */
-   if ((err = mp_mulmod(&key->qP, &q, &key->N, &key->qP)) != MP_OKAY) { goto error2; } /* qP = q * (1/q mod p) mod N */
-
-   if ((err = mp_invmod(&p, &q, &key->pQ)) != MP_OKAY)                { goto error2; } /* pQ = 1/p mod q */
-   if ((err = mp_mulmod(&key->pQ, &p, &key->N, &key->pQ)) != MP_OKAY) { goto error2; } /* pQ = p * (1/p mod q) mod N */
 
    if ((err = mp_copy(&p, &key->p)) != MP_OKAY)                       { goto error2; }
    if ((err = mp_copy(&q, &key->q)) != MP_OKAY)                       { goto error2; }
@@ -93,19 +87,18 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
    if ((err = mp_shrink(&key->dQ)) != MP_OKAY)                        { goto error2; }
    if ((err = mp_shrink(&key->dP)) != MP_OKAY)                        { goto error2; }
    if ((err = mp_shrink(&key->qP)) != MP_OKAY)                        { goto error2; }
-   if ((err = mp_shrink(&key->pQ)) != MP_OKAY)                        { goto error2; }
    if ((err = mp_shrink(&key->p)) != MP_OKAY)                         { goto error2; }
    if ((err = mp_shrink(&key->q)) != MP_OKAY)                         { goto error2; }
 
    /* set key type (in this case it's CRT optimized) */
-   key->type = PK_PRIVATE_OPTIMIZED;
+   key->type = PK_PRIVATE;
 
    /* return ok and free temps */
    err       = CRYPT_OK;
    goto done;
 error2:
    mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,
-                  &key->qP, &key->pQ, &key->p, &key->q, NULL);
+                  &key->qP, &key->p, &key->q, NULL);
 error:
    err = mpi_to_ltc_error(err);
 done:

+ 10 - 5
sha1.c

@@ -38,9 +38,9 @@ const struct _hash_descriptor sha1_desc =
 #define F3(x,y,z)  (x ^ y ^ z)
 
 #ifdef CLEAN_STACK
-static void _sha1_compress(hash_state *md, unsigned char *buf)
+static int _sha1_compress(hash_state *md, unsigned char *buf)
 #else
-static void sha1_compress(hash_state *md, unsigned char *buf)
+static int  sha1_compress(hash_state *md, unsigned char *buf)
 #endif
 {
     ulong32 a,b,c,d,e,W[80],i;
@@ -139,17 +139,21 @@ static void sha1_compress(hash_state *md, unsigned char *buf)
     md->sha1.state[2] = md->sha1.state[2] + c;
     md->sha1.state[3] = md->sha1.state[3] + d;
     md->sha1.state[4] = md->sha1.state[4] + e;
+
+    return CRYPT_OK;
 }
 
 #ifdef CLEAN_STACK
-static void sha1_compress(hash_state *md, unsigned char *buf)
+static int sha1_compress(hash_state *md, unsigned char *buf)
 {
-   _sha1_compress(md, buf);
+   int err;
+   err = _sha1_compress(md, buf);
    burn_stack(sizeof(ulong32) * 87);
+   return err;
 }
 #endif
 
-void sha1_init(hash_state * md)
+int sha1_init(hash_state * md)
 {
    _ARGCHK(md != NULL);
    md->sha1.state[0] = 0x67452301UL;
@@ -159,6 +163,7 @@ void sha1_init(hash_state * md)
    md->sha1.state[4] = 0xc3d2e1f0UL;
    md->sha1.curlen = 0;
    md->sha1.length = 0;
+   return CRYPT_OK;
 }
 
 HASH_PROCESS(sha1_process, sha1_compress, sha1, 64)

+ 2 - 1
sha224.c

@@ -28,7 +28,7 @@ const struct _hash_descriptor sha224_desc =
 };
 
 /* init the sha256 er... sha224 state ;-) */
-void sha224_init(hash_state * md)
+int sha224_init(hash_state * md)
 {
     _ARGCHK(md != NULL);
 
@@ -42,6 +42,7 @@ void sha224_init(hash_state * md)
     md->sha256.state[5] = 0x68581511UL;
     md->sha256.state[6] = 0x64f98fa7UL;
     md->sha256.state[7] = 0xbefa4fa4UL;
+    return CRYPT_OK;
 }
 
 int sha224_done(hash_state * md, unsigned char *hash)

+ 9 - 6
sha256.c

@@ -66,9 +66,9 @@ static const unsigned long K[64] = {
 
 /* compress 512-bits */
 #ifdef CLEAN_STACK
-static void _sha256_compress(hash_state * md, unsigned char *buf)
+static int _sha256_compress(hash_state * md, unsigned char *buf)
 #else
-static void sha256_compress(hash_state * md, unsigned char *buf)
+static int  sha256_compress(hash_state * md, unsigned char *buf)
 #endif
 {
     ulong32 S[8], W[64], t0, t1;
@@ -185,19 +185,21 @@ static void sha256_compress(hash_state * md, unsigned char *buf)
     for (i = 0; i < 8; i++) {
         md->sha256.state[i] = md->sha256.state[i] + S[i];
     }
-
+    return CRYPT_OK;
 }
 
 #ifdef CLEAN_STACK
-static void sha256_compress(hash_state * md, unsigned char *buf)
+static int sha256_compress(hash_state * md, unsigned char *buf)
 {
-    _sha256_compress(md, buf);
+    int err;
+    err = _sha256_compress(md, buf);
     burn_stack(sizeof(ulong32) * 74);
+    return err;
 }
 #endif
 
 /* init the sha256 state */
-void sha256_init(hash_state * md)
+int sha256_init(hash_state * md)
 {
     _ARGCHK(md != NULL);
 
@@ -211,6 +213,7 @@ void sha256_init(hash_state * md)
     md->sha256.state[5] = 0x9B05688CUL;
     md->sha256.state[6] = 0x1F83D9ABUL;
     md->sha256.state[7] = 0x5BE0CD19UL;
+    return CRYPT_OK;
 }
 
 HASH_PROCESS(sha256_process, sha256_compress, sha256, 64)

+ 2 - 1
sha384.c

@@ -30,7 +30,7 @@ const struct _hash_descriptor sha384_desc =
     &sha384_test
 };
 
-void sha384_init(hash_state * md)
+int sha384_init(hash_state * md)
 {
     _ARGCHK(md != NULL);
 
@@ -44,6 +44,7 @@ void sha384_init(hash_state * md)
     md->sha512.state[5] = CONST64(0x8eb44a8768581511);
     md->sha512.state[6] = CONST64(0xdb0c2e0d64f98fa7);
     md->sha512.state[7] = CONST64(0x47b5481dbefa4fa4);
+    return CRYPT_OK;
 }
 
 int sha384_done(hash_state * md, unsigned char *hash)

+ 10 - 6
sha512.c

@@ -90,9 +90,9 @@ CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)
 
 /* compress 1024-bits */
 #ifdef CLEAN_STACK
-static void _sha512_compress(hash_state * md, unsigned char *buf)
+static int _sha512_compress(hash_state * md, unsigned char *buf)
 #else
-static void sha512_compress(hash_state * md, unsigned char *buf)
+static int  sha512_compress(hash_state * md, unsigned char *buf)
 #endif
 {
     ulong64 S[8], W[80], t0, t1;
@@ -151,22 +151,25 @@ static void sha512_compress(hash_state * md, unsigned char *buf)
     for (i = 0; i < 8; i++) {
         md->sha512.state[i] = md->sha512.state[i] + S[i];
     }
+
+    return CRYPT_OK;
 }
 
 /* compress 1024-bits */
 #ifdef CLEAN_STACK
-static void sha512_compress(hash_state * md, unsigned char *buf)
+static int sha512_compress(hash_state * md, unsigned char *buf)
 {
-    _sha512_compress(md, buf);
+    int err;
+    err = _sha512_compress(md, buf);
     burn_stack(sizeof(ulong64) * 90 + sizeof(int));
+    return err;
 }
 #endif
 
 /* init the sha512 state */
-void sha512_init(hash_state * md)
+int sha512_init(hash_state * md)
 {
     _ARGCHK(md != NULL);
-
     md->sha512.curlen = 0;
     md->sha512.length = 0;
     md->sha512.state[0] = CONST64(0x6a09e667f3bcc908);
@@ -177,6 +180,7 @@ void sha512_init(hash_state * md)
     md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f);
     md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b);
     md->sha512.state[7] = CONST64(0x5be0cd19137e2179);
+    return CRYPT_OK;
 }
 
 HASH_PROCESS(sha512_process, sha512_compress, sha512, 128)

+ 1 - 1
sober128.c

@@ -438,7 +438,7 @@ int sober128_test(void)
    }
    return CRYPT_OK;
 #endif
-};
+}
 
 #endif
 

+ 10 - 5
tiger.c

@@ -606,9 +606,9 @@ static void key_schedule(ulong64 *x)
 }    
 
 #ifdef CLEAN_STACK
-static void _tiger_compress(hash_state *md, unsigned char *buf)
+static int _tiger_compress(hash_state *md, unsigned char *buf)
 #else
-static void tiger_compress(hash_state *md, unsigned char *buf)
+static int  tiger_compress(hash_state *md, unsigned char *buf)
 #endif
 {
     ulong64 a, b, c, x[8];
@@ -632,17 +632,21 @@ static void tiger_compress(hash_state *md, unsigned char *buf)
     md->tiger.state[0] = a ^ md->tiger.state[0];
     md->tiger.state[1] = b - md->tiger.state[1];
     md->tiger.state[2] = c + md->tiger.state[2];
+
+    return CRYPT_OK;
 }
 
 #ifdef CLEAN_STACK
-static void tiger_compress(hash_state *md, unsigned char *buf)
+static int tiger_compress(hash_state *md, unsigned char *buf)
 {
-   _tiger_compress(md, buf);
+   int err;
+   err = _tiger_compress(md, buf);
    burn_stack(sizeof(ulong64) * 11 + sizeof(unsigned long));
+   return err;
 }
 #endif
 
-void tiger_init(hash_state *md)
+int tiger_init(hash_state *md)
 {
     _ARGCHK(md != NULL);
     md->tiger.state[0] = CONST64(0x0123456789ABCDEF);
@@ -650,6 +654,7 @@ void tiger_init(hash_state *md)
     md->tiger.state[2] = CONST64(0xF096A5B4C3B2E187);
     md->tiger.curlen = 0;
     md->tiger.length = 0;
+    return CRYPT_OK;
 }
 
 HASH_PROCESS(tiger_process, tiger_compress, tiger, 64)

+ 955 - 0
tommath_class.h

@@ -0,0 +1,955 @@
+#if !(defined(LTM1) && defined(LTM2) && defined(LTM3))
+#if defined(LTM2)
+#define LTM3
+#endif
+#if defined(LTM1)
+#define LTM2
+#endif
+#define LTM1
+
+#if defined(LTM_ALL)
+#define BN_ERROR_C
+#define BN_FAST_MP_INVMOD_C
+#define BN_FAST_MP_MONTGOMERY_REDUCE_C
+#define BN_FAST_S_MP_MUL_DIGS_C
+#define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+#define BN_FAST_S_MP_SQR_C
+#define BN_MP_2EXPT_C
+#define BN_MP_ABS_C
+#define BN_MP_ADD_C
+#define BN_MP_ADD_D_C
+#define BN_MP_ADDMOD_C
+#define BN_MP_AND_C
+#define BN_MP_CLAMP_C
+#define BN_MP_CLEAR_C
+#define BN_MP_CLEAR_MULTI_C
+#define BN_MP_CMP_C
+#define BN_MP_CMP_D_C
+#define BN_MP_CMP_MAG_C
+#define BN_MP_CNT_LSB_C
+#define BN_MP_COPY_C
+#define BN_MP_COUNT_BITS_C
+#define BN_MP_DIV_C
+#define BN_MP_DIV_2_C
+#define BN_MP_DIV_2D_C
+#define BN_MP_DIV_3_C
+#define BN_MP_DIV_D_C
+#define BN_MP_DR_IS_MODULUS_C
+#define BN_MP_DR_REDUCE_C
+#define BN_MP_DR_SETUP_C
+#define BN_MP_EXCH_C
+#define BN_MP_EXPT_D_C
+#define BN_MP_EXPTMOD_C
+#define BN_MP_EXPTMOD_FAST_C
+#define BN_MP_EXTEUCLID_C
+#define BN_MP_FREAD_C
+#define BN_MP_FWRITE_C
+#define BN_MP_GCD_C
+#define BN_MP_GET_INT_C
+#define BN_MP_GROW_C
+#define BN_MP_INIT_C
+#define BN_MP_INIT_COPY_C
+#define BN_MP_INIT_MULTI_C
+#define BN_MP_INIT_SET_C
+#define BN_MP_INIT_SET_INT_C
+#define BN_MP_INIT_SIZE_C
+#define BN_MP_INVMOD_C
+#define BN_MP_INVMOD_SLOW_C
+#define BN_MP_IS_SQUARE_C
+#define BN_MP_JACOBI_C
+#define BN_MP_KARATSUBA_MUL_C
+#define BN_MP_KARATSUBA_SQR_C
+#define BN_MP_LCM_C
+#define BN_MP_LSHD_C
+#define BN_MP_MOD_C
+#define BN_MP_MOD_2D_C
+#define BN_MP_MOD_D_C
+#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+#define BN_MP_MONTGOMERY_REDUCE_C
+#define BN_MP_MONTGOMERY_SETUP_C
+#define BN_MP_MUL_C
+#define BN_MP_MUL_2_C
+#define BN_MP_MUL_2D_C
+#define BN_MP_MUL_D_C
+#define BN_MP_MULMOD_C
+#define BN_MP_N_ROOT_C
+#define BN_MP_NEG_C
+#define BN_MP_OR_C
+#define BN_MP_PRIME_FERMAT_C
+#define BN_MP_PRIME_IS_DIVISIBLE_C
+#define BN_MP_PRIME_IS_PRIME_C
+#define BN_MP_PRIME_MILLER_RABIN_C
+#define BN_MP_PRIME_NEXT_PRIME_C
+#define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+#define BN_MP_PRIME_RANDOM_EX_C
+#define BN_MP_RADIX_SIZE_C
+#define BN_MP_RADIX_SMAP_C
+#define BN_MP_RAND_C
+#define BN_MP_READ_RADIX_C
+#define BN_MP_READ_SIGNED_BIN_C
+#define BN_MP_READ_UNSIGNED_BIN_C
+#define BN_MP_REDUCE_C
+#define BN_MP_REDUCE_2K_C
+#define BN_MP_REDUCE_2K_SETUP_C
+#define BN_MP_REDUCE_IS_2K_C
+#define BN_MP_REDUCE_SETUP_C
+#define BN_MP_RSHD_C
+#define BN_MP_SET_C
+#define BN_MP_SET_INT_C
+#define BN_MP_SHRINK_C
+#define BN_MP_SIGNED_BIN_SIZE_C
+#define BN_MP_SQR_C
+#define BN_MP_SQRMOD_C
+#define BN_MP_SQRT_C
+#define BN_MP_SUB_C
+#define BN_MP_SUB_D_C
+#define BN_MP_SUBMOD_C
+#define BN_MP_TO_SIGNED_BIN_C
+#define BN_MP_TO_UNSIGNED_BIN_C
+#define BN_MP_TOOM_MUL_C
+#define BN_MP_TOOM_SQR_C
+#define BN_MP_TORADIX_C
+#define BN_MP_TORADIX_N_C
+#define BN_MP_UNSIGNED_BIN_SIZE_C
+#define BN_MP_XOR_C
+#define BN_MP_ZERO_C
+#define BN_PRIME_TAB_C
+#define BN_REVERSE_C
+#define BN_S_MP_ADD_C
+#define BN_S_MP_EXPTMOD_C
+#define BN_S_MP_MUL_DIGS_C
+#define BN_S_MP_MUL_HIGH_DIGS_C
+#define BN_S_MP_SQR_C
+#define BN_S_MP_SUB_C
+#define BNCORE_C
+#endif
+
+#if defined(BN_ERROR_C)
+   #define BN_MP_ERROR_TO_STRING_C
+#endif
+
+#if defined(BN_FAST_MP_INVMOD_C)
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ABS_C
+   #define BN_MP_SET_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_ADD_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C)
+   #define BN_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_GROW_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_FAST_S_MP_MUL_DIGS_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+   #define BN_FAST_S_MP_MUL_DIGS_C
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_FAST_S_MP_SQR_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_2EXPT_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_ABS_C)
+   #define BN_MP_COPY_C
+#endif
+
+#if defined(BN_MP_ADD_C)
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_ADD_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_ADDMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_AND_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_CLAMP_C)
+#endif
+
+#if defined(BN_MP_CLEAR_C)
+#endif
+
+#if defined(BN_MP_CLEAR_MULTI_C)
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_CMP_C)
+   #define BN_MP_CMP_MAG_C
+#endif
+
+#if defined(BN_MP_CMP_D_C)
+#endif
+
+#if defined(BN_MP_CMP_MAG_C)
+#endif
+
+#if defined(BN_MP_CNT_LSB_C)
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_COPY_C)
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_COUNT_BITS_C)
+#endif
+
+#if defined(BN_MP_DIV_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_SET_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SUB_C
+   #define BN_MP_ADD_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_INIT_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DIV_2_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_DIV_2D_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_DIV_3_C)
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DIV_D_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_COPY_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DR_IS_MODULUS_C)
+#endif
+
+#if defined(BN_MP_DR_REDUCE_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_DR_SETUP_C)
+#endif
+
+#if defined(BN_MP_EXCH_C)
+#endif
+
+#if defined(BN_MP_EXPT_D_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_SET_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MUL_C
+#endif
+
+#if defined(BN_MP_EXPTMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_INVMOD_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_ABS_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_DR_IS_MODULUS_C
+   #define BN_MP_REDUCE_IS_2K_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_EXPTMOD_FAST_C
+   #define BN_S_MP_EXPTMOD_C
+#endif
+
+#if defined(BN_MP_EXPTMOD_FAST_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MONTGOMERY_SETUP_C
+   #define BN_FAST_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_DR_SETUP_C
+   #define BN_MP_DR_REDUCE_C
+   #define BN_MP_REDUCE_2K_SETUP_C
+   #define BN_MP_REDUCE_2K_C
+   #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+   #define BN_MP_MULMOD_C
+   #define BN_MP_SET_C
+   #define BN_MP_MOD_C
+   #define BN_MP_COPY_C
+   #define BN_MP_SQR_C
+   #define BN_MP_MUL_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_EXTEUCLID_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_SET_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SUB_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_FREAD_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_S_RMAP_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_CMP_D_C
+#endif
+
+#if defined(BN_MP_FWRITE_C)
+   #define BN_MP_RADIX_SIZE_C
+   #define BN_MP_TORADIX_C
+#endif
+
+#if defined(BN_MP_GCD_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ABS_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_GET_INT_C)
+#endif
+
+#if defined(BN_MP_GROW_C)
+#endif
+
+#if defined(BN_MP_INIT_C)
+#endif
+
+#if defined(BN_MP_INIT_COPY_C)
+   #define BN_MP_COPY_C
+#endif
+
+#if defined(BN_MP_INIT_MULTI_C)
+   #define BN_MP_ERR_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_INIT_SET_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+#endif
+
+#if defined(BN_MP_INIT_SET_INT_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_INT_C
+#endif
+
+#if defined(BN_MP_INIT_SIZE_C)
+   #define BN_MP_INIT_C
+#endif
+
+#if defined(BN_MP_INVMOD_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ISODD_C
+   #define BN_FAST_MP_INVMOD_C
+   #define BN_MP_INVMOD_SLOW_C
+#endif
+
+#if defined(BN_MP_INVMOD_SLOW_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_SET_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_IS_SQUARE_C)
+   #define BN_MP_MOD_D_C
+   #define BN_MP_INIT_SET_INT_C
+   #define BN_MP_MOD_C
+   #define BN_MP_GET_INT_C
+   #define BN_MP_SQRT_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_JACOBI_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_MOD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_KARATSUBA_MUL_C)
+   #define BN_MP_MUL_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_SUB_C
+   #define BN_MP_ADD_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_KARATSUBA_SQR_C)
+   #define BN_MP_KARATSUBA_MUL_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_SQR_C
+   #define BN_MP_SUB_C
+   #define BN_S_MP_ADD_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_LCM_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_GCD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_DIV_C
+   #define BN_MP_MUL_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_LSHD_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_RSHD_C
+#endif
+
+#if defined(BN_MP_MOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_DIV_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_ADD_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_MOD_2D_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_COPY_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MOD_D_C)
+   #define BN_MP_DIV_D_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_2EXPT_C
+   #define BN_MP_SET_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_REDUCE_C)
+   #define BN_MP_MUL_C
+   #define BN_FAST_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_GROW_C
+   #define BN_MP_MONTGOMERY_SETUP_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_SETUP_C)
+#endif
+
+#if defined(BN_MP_MUL_C)
+   #define BN_MP_TOOM_MUL_C
+   #define BN_MP_KARATSUBA_MUL_C
+   #define BN_FAST_S_MP_MUL_DIGS_C
+   #define BN_S_MP_MUL_C
+   #define BN_S_MP_MUL_DIGS_C
+#endif
+
+#if defined(BN_MP_MUL_2_C)
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_MUL_2D_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_GROW_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MUL_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MULMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_MUL_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_N_ROOT_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+   #define BN_MP_COPY_C
+   #define BN_MP_EXPT_D_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SUB_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_NEG_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_OR_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_FERMAT_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_INIT_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_CMP_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_IS_DIVISIBLE_C)
+   #define BN_MP_MOD_D_C
+#endif
+
+#if defined(BN_MP_PRIME_IS_PRIME_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_PRIME_IS_DIVISIBLE_C
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+   #define BN_MP_PRIME_MILLER_RABIN_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_MILLER_RABIN_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SQRMOD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_NEXT_PRIME_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_SET_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_MOD_D_C
+   #define BN_MP_INIT_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_PRIME_MILLER_RABIN_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C)
+#endif
+
+#if defined(BN_MP_PRIME_RANDOM_EX_C)
+   #define BN_MP_READ_UNSIGNED_BIN_C
+   #define BN_MP_PRIME_IS_PRIME_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_D_C
+#endif
+
+#if defined(BN_MP_RADIX_SIZE_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_RADIX_SMAP_C)
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_RAND_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_LSHD_C
+#endif
+
+#if defined(BN_MP_READ_RADIX_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_S_RMAP_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_READ_SIGNED_BIN_C)
+   #define BN_MP_READ_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_READ_UNSIGNED_BIN_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_REDUCE_C)
+   #define BN_MP_REDUCE_SETUP_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_C
+   #define BN_S_MP_MUL_HIGH_DIGS_C
+   #define BN_MP_MOD_2D_C
+   #define BN_S_MP_MUL_DIGS_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_SET_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CMP_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_SETUP_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_2EXPT_C
+   #define BN_MP_CLEAR_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_REDUCE_IS_2K_C)
+   #define BN_MP_REDUCE_2K_C
+   #define BN_MP_COUNT_BITS_C
+#endif
+
+#if defined(BN_MP_REDUCE_SETUP_C)
+   #define BN_MP_2EXPT_C
+   #define BN_MP_DIV_C
+#endif
+
+#if defined(BN_MP_RSHD_C)
+   #define BN_MP_ZERO_C
+#endif
+
+#if defined(BN_MP_SET_C)
+   #define BN_MP_ZERO_C
+#endif
+
+#if defined(BN_MP_SET_INT_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_SHRINK_C)
+#endif
+
+#if defined(BN_MP_SIGNED_BIN_SIZE_C)
+   #define BN_MP_UNSIGNED_BIN_SIZE_C
+#endif
+
+#if defined(BN_MP_SQR_C)
+   #define BN_MP_TOOM_SQR_C
+   #define BN_MP_KARATSUBA_SQR_C
+   #define BN_FAST_S_MP_SQR_C
+   #define BN_S_MP_SQR_C
+#endif
+
+#if defined(BN_MP_SQRMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_SQRT_C)
+   #define BN_MP_N_ROOT_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_DIV_C
+   #define BN_MP_ADD_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_SUB_C)
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_SUB_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_SUBMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_TO_SIGNED_BIN_C)
+   #define BN_MP_TO_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TO_UNSIGNED_BIN_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_TOOM_MUL_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_TOOM_SQR_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_SQR_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_TORADIX_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_TORADIX_N_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_UNSIGNED_BIN_SIZE_C)
+   #define BN_MP_COUNT_BITS_C
+#endif
+
+#if defined(BN_MP_XOR_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_ZERO_C)
+#endif
+
+#if defined(BN_PRIME_TAB_C)
+#endif
+
+#if defined(BN_REVERSE_C)
+#endif
+
+#if defined(BN_S_MP_ADD_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_S_MP_EXPTMOD_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_REDUCE_SETUP_C
+   #define BN_MP_MOD_C
+   #define BN_MP_COPY_C
+   #define BN_MP_SQR_C
+   #define BN_MP_REDUCE_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SET_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_S_MP_MUL_DIGS_C)
+   #define BN_FAST_S_MP_MUL_DIGS_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_MUL_HIGH_DIGS_C)
+   #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_SQR_C)
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_SUB_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BNCORE_C)
+#endif
+
+#ifdef LTM3
+#define LTM_LAST
+#endif
+#include <tommath_superclass.h>
+#include <tommath_class.h>
+#else
+#define LTM_LAST
+#endif

+ 70 - 0
tommath_superclass.h

@@ -0,0 +1,70 @@
+/* super class file for PK algos */
+
+/* default ... include all MPI */
+#define LTM_ALL
+
+/* RSA only (does not support DH/DSA/ECC) */
+// #define SC_RSA_1
+
+/* For reference.... On an Athlon64 optimizing for speed...
+   LTM's mpi.o with all functions [striped] is 142KiB in size.
+*/
+
+/* Works for RSA only, mpi.o is 68KiB */
+#ifdef SC_RSA_1
+   #define BN_MP_SHRINK_C
+   #define BN_MP_LCM_C
+   #define BN_MP_PRIME_RANDOM_EX_C
+   #define BN_MP_INVMOD_C
+   #define BN_MP_GCD_C
+   #define BN_MP_MOD_C
+   #define BN_MP_MULMOD_C
+   #define BN_MP_ADDMOD_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_SET_INT_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_UNSIGNED_BIN_SIZE_C
+   #define BN_MP_TO_UNSIGNED_BIN_C
+   #define BN_MP_MOD_D_C
+   #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+   #define BN_REVERSE_C
+   #define BN_PRIME_TAB_C
+
+   /* other modifiers */
+//   #define BN_MP_DIV_SMALL                    /* Slower division, not critical (currently buggy?) */
+
+   /* here we are on the last pass so we turn things off.  The functions classes are still there
+    * but we remove them specifically from the build.  This also invokes tweaks in functions
+    * like removing support for even moduli, etc...
+    */
+#ifdef LTM_LAST
+   #undef  BN_MP_TOOM_MUL_C
+   #undef  BN_MP_TOOM_SQR_C
+   #undef  BN_MP_KARATSUBA_MUL_C
+   #undef  BN_MP_KARATSUBA_SQR_C
+   #undef  BN_MP_REDUCE_C
+   #undef  BN_MP_REDUCE_SETUP_C
+   #undef  BN_MP_DR_IS_MODULUS_C
+   #undef  BN_MP_DR_SETUP_C
+   #undef  BN_MP_DR_REDUCE_C
+   #undef  BN_MP_REDUCE_IS_2K_C
+   #undef  BN_MP_REDUCE_2K_SETUP_C
+   #undef  BN_MP_REDUCE_2K_C
+   #undef  BN_S_MP_EXPTMOD_C
+   #undef  BN_MP_DIV_3_C
+   #undef  BN_S_MP_MUL_HIGH_DIGS_C
+   #undef  BN_FAST_S_MP_MUL_HIGH_DIGS_C
+   #undef  BN_FAST_MP_INVMOD_C
+
+   /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold
+    * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] 
+    * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without
+    * trouble.  
+    */
+   #undef  BN_S_MP_MUL_DIGS_C
+   #undef  BN_S_MP_SQR_C
+   #undef  BN_MP_MONTGOMERY_REDUCE_C
+#endif
+
+#endif

+ 11 - 6
whirl.c

@@ -50,9 +50,9 @@ const struct _hash_descriptor whirlpool_desc =
     SB7(GB(a, i-7, 0))
 
 #ifdef CLEAN_STACK
-static void _whirlpool_compress(hash_state *md, unsigned char *buf)
+static int _whirlpool_compress(hash_state *md, unsigned char *buf)
 #else
-static void whirlpool_compress(hash_state *md, unsigned char *buf)
+static int whirlpool_compress(hash_state *md, unsigned char *buf)
 #endif
 {
    ulong64 K[2][8], T[3][8];
@@ -90,7 +90,7 @@ static void whirlpool_compress(hash_state *md, unsigned char *buf)
        /* xor the constant */
        K[0][0] ^= cont[x+1];
        
-       /* apply main transform to T[0] into T[1] */
+       /* apply main transform to T[1] into T[0] */
        for (y = 0; y < 8; y++) {
            T[0][y] = theta_pi_gamma(T[1], y) ^ K[0][y];
        }
@@ -100,22 +100,27 @@ static void whirlpool_compress(hash_state *md, unsigned char *buf)
    for (x = 0; x < 8; x++) {
       md->whirlpool.state[x] ^= T[0][x] ^ T[2][x];
    }
+
+   return CRYPT_OK;
 }
 
 
 #ifdef CLEAN_STACK
-static void whirlpool_compress(hash_state *md, unsigned char *buf)
+static int whirlpool_compress(hash_state *md, unsigned char *buf)
 {
-   _whirlpool_compress(md, buf);
+   int err;
+   err = _whirlpool_compress(md, buf);
    burn_stack((5 * 8 * sizeof(ulong64)) + (2 * sizeof(int)));
+   return err;
 }
 #endif
 
 
-void whirlpool_init(hash_state * md)
+int whirlpool_init(hash_state * md)
 {
    _ARGCHK(md != NULL);
    zeromem(&md->whirlpool, sizeof(md->whirlpool));
+   return CRYPT_OK;
 }
 
 HASH_PROCESS(whirlpool_process, whirlpool_compress, whirlpool, 64)

+ 4 - 2
yarrow.c

@@ -65,7 +65,7 @@ int yarrow_start(prng_state *prng)
    prng->yarrow.cipher = register_cipher(&safer_sk128_desc);
 #elif defined(DES)
    prng->yarrow.cipher = register_cipher(&des3_desc);
-#elif
+#else
    #error YARROW needs at least one CIPHER
 #endif
    if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) {
@@ -118,7 +118,9 @@ int yarrow_add_entropy(const unsigned char *buf, unsigned long len, prng_state *
    }
 
    /* start the hash */
-   hash_descriptor[prng->yarrow.hash].init(&md);
+   if ((err = hash_descriptor[prng->yarrow.hash].init(&md)) != CRYPT_OK) {
+      return err; 
+   }
 
    /* hash the current pool */
    if ((err = hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool, 

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor