Browse Source

added libtomcrypt-0.79

Tom St Denis 22 years ago
parent
commit
d5fbe63b70
35 changed files with 1919 additions and 710 deletions
  1. 1 1
      authors
  2. 1 3
      base64.c
  3. 25 0
      changes
  4. 143 0
      config.pl
  5. 31 28
      crypt.c
  6. BIN
      crypt.pdf
  7. 26 20
      crypt.tex
  8. 157 271
      demos/test.c
  9. 82 93
      dh.c
  10. 56 14
      dh_sys.c
  11. 398 0
      dsa.c
  12. 155 92
      ecc.c
  13. 45 11
      ecc_sys.c
  14. 18 0
      examples/ch1-01.c
  15. 25 0
      examples/ch1-02.c
  16. 29 0
      examples/ch1-03.c
  17. 23 18
      keyring.c
  18. 110 38
      makefile
  19. 23 0
      makefile.out
  20. 38 10
      makefile.ps2
  21. 41 3
      makefile.vc
  22. 211 2
      mpi.c
  23. 5 0
      mpi.h
  24. 26 26
      mycrypt.h
  25. 5 16
      mycrypt_argchk.h
  26. 10 30
      mycrypt_cfg.h
  27. 2 0
      mycrypt_misc.h
  28. 37 15
      mycrypt_pk.h
  29. 1 3
      packet.c
  30. 0 2
      prime.c
  31. 29 4
      rsa.c
  32. 32 8
      rsa_sys.c
  33. 2 1
      sha1.c
  34. 1 1
      strings.c
  35. 131 0
      update_libtomcrypt.sh

+ 1 - 1
authors

@@ -25,7 +25,7 @@ [email protected].
 
 6) Clay Culver
 
-   Submitted a fix for "rsa.c" which cleaned up some code.
+   Submitted a fix for "rsa.c" which cleaned up some code.  Submited some other fixes too.  :-)
 
 7) Jason Klapste
 

+ 1 - 3
base64.c

@@ -91,7 +91,7 @@ int base64_decode(const unsigned char *in,  unsigned long len,
        if (c == 254) { c = 0; g--; }
        t = (t<<6)|c;
        if (++y == 4) {
-	  if (z + g > *outlen) goto error;
+	   if (z + g > *outlen) { return CRYPT_BUFFER_OVERFLOW; }
           out[z++] = (unsigned char)((t>>16)&255);
           if (g > 1) out[z++] = (unsigned char)((t>>8)&255);
           if (g > 2) out[z++] = (unsigned char)(t&255);
@@ -103,8 +103,6 @@ int base64_decode(const unsigned char *in,  unsigned long len,
    }
    *outlen = z;
    return CRYPT_OK;
-error:
-   return CRYPT_BUFFER_OVERFLOW;
 }
 
 #endif

+ 25 - 0
changes

@@ -1,3 +1,28 @@
+Dec 14th, 2002
+v0.79  -- Change to PK code [binary and source].  I made it so you have to pass the buffer size to the *_decrypt_key and
+          *_verify_hash functions.  This prevents malformed packets from performing buffer overflows.  I've also trimmed
+          the packet header size [by 4 bytes].
+       -- Made the test program halt on the first error it occurs.  Also made it trap more errors than before.
+       -- Wrote the first chapter of my new book [DRAFT!], not in this package but check my website!
+       -- Included a perl script "config.pl" that will make "makefile.out" according to the users needs.  
+       -- Added shell script to look for latest release
+       -- Merge DH and ECC key defines from mycrypt_cfg.h into the makefiles
+       -- updated the makefile to use BSD friendly archiving invokations
+       -- Changed the DH and ECC code to use base64 static key settings [e.g. the primes].  Dropped the code size by 3KB
+          and is ever-so-slightly faster than before.
+       -- added "mp_shrink" function to shrink the size of bignums.  Specially useful for PK code :-)
+       -- Added new exptmod function that calculates a^b mod c with fewer multiplies then before [~20% for crypto
+          sized numbers].  Also added a "low mem" variant that doesn't use more than 20KB [upto 4096 bit nums] of
+          heap todo the calculation.  Both are #define'able controlled
+       -- Added XREALLOC macro to provide realloc() functionality.
+       -- Added fix where in rsa_import() if you imported a public key or a non-optimized key it would free the mp_int's
+          not being used.
+       -- Fixed potential bug in the ECC code.  Only would occur on platforms where char is not eight bits [which isn't
+          often!]
+       -- Fixed up the ECC point multiplication, its about 15% faster now
+       -- While I was at it [since the lib isn't binary backwards compatible anyways] I've fixed the PK export routines
+          so they export as "unsigned" types saving 1 byte per bignum outputted.  Not a lot but heck why not.
+          
 Nov 28th, 2002
 v0.78  -- Made the default ARGCHK macro a function call instead which reduced the code size from 264KB to 239KB.
        -- Fixed a bug in the XTEA keysize function which called ARGCHK incorrectly.

+ 143 - 0
config.pl

@@ -0,0 +1,143 @@
+#!/usr/bin/perl
+#
+# Generates a makefile based on user input
+#
+# Tom St Denis, [email protected], http://tom.iahu.ca
+
+@settings = (
+   "CC,Compiler,gcc",
+   "AR,Archiver,ar",
+   "LD,Linker,ld",
+   "CFLAGS,Optimizations,-Os",
+   "CFLAGS,Warnings,-Wall -Wsign-compare -W -Wno-unused -Werror",
+   "CFLAGS,Include Paths,-I./",
+   "CFLAGS,Other compiler options,",
+   "CFLAGS,XMALLOC,-DXMALLOC=malloc",
+   "CFLAGS,XCALLOC,-DXCALLOC=calloc",
+   "CFLAGS,XFREE,-DXFREE=free",
+   "CFLAGS,XCLOCK,-DXCLOCK=clock",
+   "CFLAGS,XCLOCKS_PER_SEC,-DXCLOCKS_PER_SEC=CLOCKS_PER_SEC",
+);
+
+@opts = (
+   "SMALL_CODE,Use small code where possible (slower code),y",
+   "NO_FILE,Avoid file I/O calls,n",
+   "CLEAN_STACK,Clean the stack within functions,n",
+
+   "BLOWFISH,Include Blowfish block cipher,y",
+   "RC2,Include RC2 block cipher,y",
+   "RC5,Include RC5 block cipher,y",
+   "RC6,Include RC6 block cipher,y",
+   "SERPENT,Include Serpent block cipher,y",
+   "SAFERP,Include Safer+ block cipher,y",
+   "SAFER,Include Safer-64 block ciphers,y",
+   "RIJNDAEL,Include Rijndael (AES) block cipher,y",
+   "XTEA,Include XTEA block cipher,y",
+   "TWOFISH,Include Twofish block cipher,y",
+   "TWOFISH_SMALL,Include Use a low ram variant of Twofish,n",
+   "TWOFISH_TABLES,Include Use precomputed tables to speed up the low-ram variant,n",
+   "DES,Include DES and 3DES block ciphers,y",
+   "CAST5,Include CAST5 (aka CAST-128) block cipher,y",
+   "NOEKEON,Include Noekeon block cipher,y",
+
+   "CFB,Include CFB block mode of operation,y",
+   "OFB,Include OFB block mode of operation,y",
+   "ECB,Include ECB block mode of operation,y",
+   "CBC,Include CBC block mode of operation,y",
+   "CTR,Include CTR block mode of operation,y",
+
+   "SHA512,Include SHA512 one-way hash,y",
+   "SHA384,Include SHA384 one-way hash (requires SHA512),y",
+   "SHA256,Include SHA256 one-way hash,y",
+   "TIGER,Include TIGER one-way hash,y",
+   "SHA1,Include SHA1 one-way hash,y",
+   "MD5,Include MD5 one-way hash,y",
+   "MD4,Include MD4 one-way hash,y",
+   "MD2,Include MD2 one-way hash,y",
+   "HMAC,Include Hash based Message Authentication Support,y",
+
+   "BASE64,Include Base64 encoding support,y",
+
+   "YARROW,Include Yarrow PRNG,y",
+   "SPRNG,Include Secure PRNG base on RNG code,y",
+   "RC4,Include RC4 PRNG,y",
+   "DEVRANDOM,Use /dev/random or /dev/urandom if available?,y",
+   "TRY_URANDOM_FIRST,Try /dev/urandom before /dev/random?,n",
+
+   "MRSA,Include RSA public key support,y",
+   "MDH,Include Diffie-Hellman (over Z/pZ) public key support,y",
+   "MECC,Include Eliptic Curve public key crypto support,y",
+   "MDSA,Include Digital Signature Algoritm (DSA) support\n(not required for signatures in the other three),y",
+   "KR,Include Keyring support (groups all three PK systems),y",
+   
+   "DH768,768-bit DH key support,y",
+   "DH1024,1024-bit DH key support,y",
+   "DH1280,1280-bit DH key support,y",
+   "DH1536,1280-bit DH key support,y",
+   "DH1792,1792-bit DH key support,y",
+   "DH2048,2048-bit DH key support,y",
+   "DH2560,2560-bit DH key support,y",
+   "DH3072,3072-bit DH key support,y",
+   "DH4096,4096-bit DH key support,y",
+   
+   "ECC160,160-bit ECC key support,y",
+   "ECC192,192-bit ECC key support,y",
+   "ECC224,224-bit ECC key support,y",
+   "ECC256,256-bit ECC key support,y",
+   "ECC384,384-bit ECC key support,y",
+   "ECC521,521-bit ECC key support,y",
+   
+   "DSA1024,1024-bit (160-bit) DSA key support,y",
+   "DSA2048,2048-bit (256-bit) DSA key support,y",
+   "DSA4096,4096-bit (512-bit) DSA key support,y",
+
+   "GF,Include GF(2^w) math support (not used internally),n",
+   
+   "MPI,Include MPI big integer math support (required by the public key code),y",
+   "MPI_FASTEXPT,Use the faster exponentiation code (uses some heap but is faster),y",
+   "MPI_FASTEXPT_LOWMEM,Use the low ram variant of the fast code\nRequires the fast code to enabled,n",
+   
+   
+);
+
+# scan for switches and make variables
+for (@settings) {
+   @m = split(",", $_);
+   print "@m[1]: [@m[2]] ";
+   $r = <>; $r = @m[2] if ($r eq "\n");
+   chomp($r);
+   @vars{@m[0]} = @vars{@m[0]} . $r . " ";
+}
+
+# scan for build flags
+for (@opts) {
+   @m = split(",", $_);
+   print "@m[1]: [@m[2]]";
+   $r = <>;  @vars{'CFLAGS'} = @vars{'CFLAGS'} . "-D" . $m[0] . " " if (($r eq "y\n") || ($r eq "\n" && @m[2] eq "y"));
+}   
+
+open(OUT,">makefile.out");
+print OUT "#makefile generated with config.pl\n#\n#Tom St Denis (tomstdenis\@yahoo.com, http://tom.iahu.ca) \n\n";
+
+# output unique vars first
+for (@settings) {
+   @m = split(",", $_);
+   print OUT "@m[0] = @vars{@m[0]}\n"   if (@vars{@m[0]} ne "" && @m[0] ne "CFLAGS");
+   print OUT "CFLAGS += @vars{@m[0]}\n" if (@vars{@m[0]} ne "" && @m[0] eq "CFLAGS");
+   @vars{@m[0]} = "";
+}
+
+# output objects
+print OUT "\ndefault: library\n\n";
+print OUT "OBJECTS = keyring.o gf.o mem.o sprng.o dsa.o ecc.o base64.o dh.o rsa.o bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o ampi.o mpi.o prime.o twofish.o packet.o hmac.o strings.o\n\n";
+
+# some depends
+print OUT "rsa.o: rsa_sys.c\ndh.o: dh_sys.c\necc.o: ecc_sys.c\n\n";
+
+# targets 
+print OUT "library: \$(OBJECTS)\n\t \$(AR) rs libtomcrypt.a \$(OBJECTS)\n\n";
+print OUT "clean:\n\trm -f \$(OBJECTS) libtomcrypt.a \n\n";
+
+close OUT;
+
+print "\n\nmakefile.out was written.\n";

+ 31 - 28
crypt.c

@@ -1,7 +1,9 @@
 #include "mycrypt.h"
 #include <signal.h>
 
-struct _cipher_descriptor cipher_descriptor[32] = {
+#define TAB_SIZE    32
+
+struct _cipher_descriptor cipher_descriptor[TAB_SIZE] = {
 { NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
 { NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
 { NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
@@ -35,7 +37,7 @@ struct _cipher_descriptor cipher_descriptor[32] = {
 { NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
 { NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL } };
 
-struct _hash_descriptor hash_descriptor[32] = {
+struct _hash_descriptor hash_descriptor[TAB_SIZE] = {
 { NULL, 0, 0, 0, NULL, NULL, NULL, NULL },
 { NULL, 0, 0, 0, NULL, NULL, NULL, NULL },
 { NULL, 0, 0, 0, NULL, NULL, NULL, NULL },
@@ -69,7 +71,7 @@ struct _hash_descriptor hash_descriptor[32] = {
 { NULL, 0, 0, 0, NULL, NULL, NULL, NULL },
 { NULL, 0, 0, 0, NULL, NULL, NULL, NULL } };
 
-struct _prng_descriptor prng_descriptor[32] = {
+struct _prng_descriptor prng_descriptor[TAB_SIZE] = {
 { NULL, NULL, NULL, NULL, NULL },
 { NULL, NULL, NULL, NULL, NULL },
 { NULL, NULL, NULL, NULL, NULL },
@@ -103,26 +105,27 @@ struct _prng_descriptor prng_descriptor[32] = {
 { NULL, NULL, NULL, NULL, NULL },
 { NULL, NULL, NULL, NULL, NULL } };
 
-#if (ARGTYPE == 0) && defined(SMALL_CODE)
-
+/* ch1-01-1 */
+#if (ARGTYPE == 0)
 void crypt_argchk(char *v, char *s, int d)
 {
 #ifdef SONY_PS2
-   printf("_ARGCHK '%s' failure on line %d of file %s\n", v, d, s);
+ printf("_ARGCHK '%s' failure on line %d of file %s\n", 
+         v, d, s);
 #else 
-   fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n", v, d, s);
+ fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n", 
+         v, d, s);
 #endif
-   raise(SIGABRT);
+ raise(SIGABRT);
 }
-
 #endif
-   
+/* ch1-01-1 */
 
 int find_cipher(const char *name)
 {
    int x;
    _ARGCHK(name != NULL);
-   for (x = 0; x < 32; x++) {
+   for (x = 0; x < TAB_SIZE; x++) {
        if (cipher_descriptor[x].name != NULL && !strcmp(cipher_descriptor[x].name, name)) {
           return x;
        }
@@ -134,7 +137,7 @@ int find_hash(const char *name)
 {
    int x;
    _ARGCHK(name != NULL);
-   for (x = 0; x < 32; x++) {
+   for (x = 0; x < TAB_SIZE; x++) {
        if (hash_descriptor[x].name != NULL && !strcmp(hash_descriptor[x].name, name)) {
           return x;
        }
@@ -146,7 +149,7 @@ int find_prng(const char *name)
 {
    int x;
    _ARGCHK(name != NULL);
-   for (x = 0; x < 32; x++) {
+   for (x = 0; x < TAB_SIZE; x++) {
        if ((prng_descriptor[x].name != NULL) && !strcmp(prng_descriptor[x].name, name)) {
           return x;
        }
@@ -157,7 +160,7 @@ int find_prng(const char *name)
 int find_cipher_id(unsigned char ID)
 {
    int x;
-   for (x = 0; x < 32; x++) {
+   for (x = 0; x < TAB_SIZE; x++) {
        if (cipher_descriptor[x].ID == ID) {
           return (cipher_descriptor[x].name == NULL) ? -1 : x;
        }
@@ -168,7 +171,7 @@ int find_cipher_id(unsigned char ID)
 int find_hash_id(unsigned char ID)
 {
    int x;
-   for (x = 0; x < 32; x++) {
+   for (x = 0; x < TAB_SIZE; x++) {
        if (hash_descriptor[x].ID == ID) {
           return (hash_descriptor[x].name == NULL) ? -1 : x;
        }
@@ -186,7 +189,7 @@ int find_cipher_any(const char *name, int blocklen, int keylen)
    x = find_cipher(name);
    if (x != -1) return x;
 
-   for (x = 0; cipher_descriptor[x].name != NULL; x++) {
+   for (x = 0; cipher_descriptor[x].name != NULL && x < TAB_SIZE; x++) {
        if (blocklen <= (int)cipher_descriptor[x].block_length && keylen <= (int)cipher_descriptor[x].max_key_length) {
           return x;
        }
@@ -201,14 +204,14 @@ int register_cipher(const struct _cipher_descriptor *cipher)
    _ARGCHK(cipher != NULL);
 
    /* is it already registered? */
-   for (x = 0; x < 32; x++) {
+   for (x = 0; x < TAB_SIZE; x++) {
        if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) {
           return x;
        }
    }
 
    /* find a blank spot */
-   for (x = 0; x < 32; x++) {
+   for (x = 0; x < TAB_SIZE; x++) {
        if (cipher_descriptor[x].name == NULL) {
           memcpy(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor));
           return x;
@@ -226,7 +229,7 @@ int unregister_cipher(const struct _cipher_descriptor *cipher)
    _ARGCHK(cipher != NULL);
 
    /* is it already registered? */
-   for (x = 0; x < 32; x++) {
+   for (x = 0; x < TAB_SIZE; x++) {
        if (!memcmp(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor))) {
           cipher_descriptor[x].name = NULL;
           cipher_descriptor[x].ID   = 255;
@@ -243,14 +246,14 @@ int register_hash(const struct _hash_descriptor *hash)
    _ARGCHK(hash != NULL);
 
    /* is it already registered? */
-   for (x = 0; x < 32; x++) {
+   for (x = 0; x < TAB_SIZE; x++) {
        if (!memcmp(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor))) {
           return x;
        }
    }
 
    /* find a blank spot */
-   for (x = 0; x < 32; x++) {
+   for (x = 0; x < TAB_SIZE; x++) {
        if (hash_descriptor[x].name == NULL) {
           memcpy(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor));
           return x;
@@ -268,7 +271,7 @@ int unregister_hash(const struct _hash_descriptor *hash)
    _ARGCHK(hash != NULL);
 
    /* is it already registered? */
-   for (x = 0; x < 32; x++) {
+   for (x = 0; x < TAB_SIZE; x++) {
        if (!memcmp(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor))) {
           hash_descriptor[x].name = NULL;
           return CRYPT_OK;
@@ -284,14 +287,14 @@ int register_prng(const struct _prng_descriptor *prng)
    _ARGCHK(prng != NULL);
 
    /* is it already registered? */
-   for (x = 0; x < 32; x++) {
+   for (x = 0; x < TAB_SIZE; x++) {
        if (!memcmp(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor))) {
           return x;
        }
    }
 
    /* find a blank spot */
-   for (x = 0; x < 32; x++) {
+   for (x = 0; x < TAB_SIZE; x++) {
        if (prng_descriptor[x].name == NULL) {
           memcpy(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor));
           return x;
@@ -309,7 +312,7 @@ int unregister_prng(const struct _prng_descriptor *prng)
    _ARGCHK(prng != NULL);
 
    /* is it already registered? */
-   for (x = 0; x < 32; x++) {
+   for (x = 0; x < TAB_SIZE; x++) {
        if (!memcmp(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor))) {
           prng_descriptor[x].name = NULL;
           return CRYPT_OK;
@@ -320,7 +323,7 @@ int unregister_prng(const struct _prng_descriptor *prng)
 
 int cipher_is_valid(int idx)
 {
-   if (idx < 0 || idx > 32 || cipher_descriptor[idx].name == NULL) {
+   if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx].name == NULL) {
       return CRYPT_INVALID_CIPHER;
    }
    return CRYPT_OK;
@@ -328,7 +331,7 @@ int cipher_is_valid(int idx)
 
 int hash_is_valid(int idx)
 {
-   if (idx < 0 || idx > 32 || hash_descriptor[idx].name == NULL) {
+   if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) {
       return CRYPT_INVALID_HASH;
    }
    return CRYPT_OK;
@@ -336,7 +339,7 @@ int hash_is_valid(int idx)
 
 int prng_is_valid(int idx)
 {
-   if (idx < 0 || idx > 32 || prng_descriptor[idx].name == NULL) {
+   if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) {
       return CRYPT_INVALID_PRNG;
    }
    return CRYPT_OK;

BIN
crypt.pdf


+ 26 - 20
crypt.tex

@@ -44,7 +44,7 @@
 \def\gap{\vspace{0.5ex}}
 \makeindex
 \begin{document}
-\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.78}
+\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.79}
 \author{Tom St Denis \\
 Algonquin College \\
 \\
@@ -192,6 +192,7 @@ I would like to give thanks to the following people (in no particular order) for
    \item Wayne Scott
    \item Andrew Tyler
    \item Sky Schulz
+   \item Christopher Imes
 \end{enumerate}
 
 \chapter{The Application Programming Interface (API)}
@@ -1367,15 +1368,18 @@ int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen,
                           unsigned char *outkey, unsigned long *outlen,
                           prng_state *prng, int wprng, rsa_key *key);
 
-int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey, 
-                          unsigned long *keylen, rsa_key *key);
+int rsa_decrypt_key(const unsigned char *in, unsigned long inlen, 
+                          unsigned char *outkey, unsigned long *keylen, 
+                          rsa_key *key);
 \end{verbatim}
 
 The ``rsa\_encrypt\_key()'' function accepts a symmetric key (limited to 32 bytes) as input in ``inkey''.  ``inlen''
 is the size of the input key in bytes.  The function will then ``rsa\_pad()'' the key and encrypt it using the RSA
-algorithm.  It will store the result in ``outkey'' along with the length in ``outlen''.  The ``rsa\_decrypt\_key()'' function
-performs the opposite.  The ``in'' variable is where the RSA packet goes and it will store the original symmetric key in
-the ``outkey'' variable along with its length in ``keylen''.
+algorithm.  It will store the result in ``outkey'' along with the length in ``outlen''.  
+
+The ``rsa\_decrypt\_key()'' function performs the opposite.  The ``in'' variable is where the RSA packet of length 
+``inlen'' goes and it will store the original symmetric key in the ``outkey'' variable along with its length in 
+``keylen''.
 
 Similarly to sign or verify a hash of a message the following two messages are provided.  The idea is to hash your 
 message then use these functions to RSA sign the hash.  
@@ -1384,8 +1388,8 @@ int rsa_sign_hash(const unsigned char *in,  unsigned long inlen,
                         unsigned char *out, unsigned long *outlen, 
                         rsa_key *key);
 
-int rsa_verify_hash(const unsigned char *sig, const unsigned char *hash,
-                          int *stat, rsa_key *key);
+int rsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+                    const unsigned char *hash, int *stat, rsa_key *key);
 \end{verbatim}
 For ``rsa\_sign\_hash'' the input is intended to be the hash of a message the user wants to sign.  The output is the 
 RSA signed packet which ``rsa\_verify\_hash'' can verify.  For the verification function ``sig'' is the RSA signature
@@ -1633,12 +1637,13 @@ int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen,
                          prng_state *prng, int wprng, int hash, 
                          dh_key *key);
 
-int dh_decrypt_key(const unsigned char *in, unsigned char *outkey, 
-                         unsigned long *keylen, dh_key *key);
+int dh_decrypt_key(const unsigned char *in, unsigned long inlen,
+                         unsigned char *outkey, unsigned long *keylen, 
+                         dh_key *key);
 \end{verbatim}
 Where ``inkey'' is an input symmetric key of no more than 32 bytes.  Essentially these routines created a random public key
-and find the hash of the shared secret.  The message digest is than XOR'ed against the symmetric key.  All of the required
-data is placed in ``out'' by ``dh\_encrypt\_key()''.   The hash must produce a message digest at least as large
+and find the hash of the shared secret.  The message digest is than XOR'ed against the symmetric key.  All of the 
+required data is placed in ``out'' by ``dh\_encrypt\_key()''.   The hash must produce a message digest at least as large
 as the symmetric key you are trying to share.
 
 Similar to the RSA system you can sign and verify a hash of a message.
@@ -1647,9 +1652,9 @@ int dh_sign_hash(const unsigned char *in,  unsigned long inlen,
                        unsigned char *out, unsigned long *outlen,
                        prng_state *prng, int wprng, dh_key *key);
 
-int dh_verify_hash(const unsigned char *sig, const unsigned char *hash, 
-                         unsigned long inlen, int *stat, 
-                         dh_key *key);
+int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
+                         const unsigned char *hash, unsigned long hashlen, 
+                         int *stat, dh_key *key);
 \end{verbatim}
 
 The ``dh\_sign\_hash'' function signs the message hash in ``in'' of length ``inlen'' and forms a DH packet in ``out''.  
@@ -1742,8 +1747,9 @@ int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
                           prng_state *prng, int wprng, int hash, 
                           ecc_key *key);
 
-int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey, 
-                          unsigned long *keylen, ecc_key *key);
+int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
+                          unsigned char *outkey, unsigned long *keylen, 
+                          ecc_key *key);
 \end{verbatim}
 
 Where ``inkey'' is an input symmetric key of no more than 32 bytes.  Essentially these routines created a random public key
@@ -1757,9 +1763,9 @@ int ecc_sign_hash(const unsigned char *in,  unsigned long inlen,
                         unsigned char *out, unsigned long *outlen,
                         prng_state *prng, int wprng, ecc_key *key);
 
-int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash, 
-                          unsigned long inlen, int *stat, 
-                          ecc_key *key);
+int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
+                    const unsigned char *hash, unsigned long hashlen, 
+                          int *stat, ecc_key *key);
 \end{verbatim}
 
 The ``ecc\_sign\_hash'' function signs the message hash in ``in'' of length ``inlen'' and forms a ECC packet in ``out''.  

+ 157 - 271
demos/test.c

@@ -63,23 +63,23 @@ void store_tests(void)
  STORE32L(L, &buf[0]);
  L = 0;
  LOAD32L(L, &buf[0]);
- if (L != 0x12345678UL) printf("LOAD/STORE32 Little don't work\n");
+ if (L != 0x12345678UL)  { printf("LOAD/STORE32 Little don't work\n"); exit(-1); }
  LL = CONST64(0x01020304050607);
  STORE64L(LL, &buf[0]);
  LL = 0;
  LOAD64L(LL, &buf[0])
- if (LL != CONST64(0x01020304050607)) printf("LOAD/STORE64 Little don't work\n");
+ if (LL != CONST64(0x01020304050607)) { printf("LOAD/STORE64 Little don't work\n"); exit(-1); }
 
  L = 0x12345678UL;
  STORE32H(L, &buf[0]);
  L = 0;
  LOAD32H(L, &buf[0]);
- if (L != 0x12345678UL) printf("LOAD/STORE32 High don't work\n");
+ if (L != 0x12345678UL) { printf("LOAD/STORE32 High don't work\n"); exit(-1); }
  LL = CONST64(0x01020304050607);
  STORE64H(LL, &buf[0]);
  LL = 0;
  LOAD64H(LL, &buf[0])
- if (LL != CONST64(0x01020304050607)) printf("LOAD/STORE64 High don't work\n");
+ if (LL != CONST64(0x01020304050607)) { printf("LOAD/STORE64 High don't work\n"); exit(-1); }
 }
 
 void cipher_tests(void) {
@@ -103,10 +103,12 @@ void ecb_tests(void)
  for (x = 0; cipher_descriptor[x].name != NULL; x++) {
      printf(" %12s: ",
            cipher_descriptor[x].name);
-     if ((errno = cipher_descriptor[x].test()) != CRYPT_OK)
+     if ((errno = cipher_descriptor[x].test()) != CRYPT_OK) {
         printf(" **failed** Reason: %s\n", error_to_string(errno));
-     else 
+        exit(-1);
+     } else {
         printf("passed\n");
+     }
  }
 }
 
@@ -124,11 +126,15 @@ void cbc_tests(void)
  for (x = 0; x < 32; x++) blk[x] = IV[x] = x;
 
  /* now lets start a cbc session */
- if ((errno = cbc_start(find_cipher("blowfish"), IV, key, 16, 0, &cbc)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
+ if ((errno = cbc_start(find_cipher("blowfish"), IV, key, 16, 0, &cbc)) != CRYPT_OK) { 
+    printf("CBC Setup: %s\n", error_to_string(errno)); exit(-1); }
 
  /* now lets encode 32 bytes */
- for (x = 0; x < 4; x++)
-    cbc_encrypt(blk+8*x, ct+8*x, &cbc);
+ for (x = 0; x < 4; x++) {
+    if ((errno = cbc_encrypt(blk+8*x, ct+8*x, &cbc)) != CRYPT_OK) {
+       printf("CBC encrypt: %s\n", error_to_string(errno)); exit(-1);
+    }
+ }
 
  zeromem(blk, sizeof(blk));
 
@@ -137,11 +143,16 @@ void cbc_tests(void)
  for (x = 0; x < 32; x++) IV[x] = x;
 
  /* now lets start a cbc session */
- if ((errno = cbc_start(find_cipher("blowfish"), IV, key, 16, 0, &cbc)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
+ if ((errno = cbc_start(find_cipher("blowfish"), IV, key, 16, 0, &cbc)) != CRYPT_OK) { 
+     printf("CBC Setup: %s\n", error_to_string(errno)); exit(-1); }
 
  /* now lets decode 32 bytes */
- for (x = 0; x < 4; x++)
-    cbc_decrypt(ct+8*x, blk+8*x, &cbc);
+ for (x = 0; x < 4; x++) {
+    if ((errno = cbc_decrypt(ct+8*x, blk+8*x, &cbc)) != CRYPT_OK) {
+       printf("CBC decrypt: %s\n", error_to_string(errno)); exit(-1);
+    }
+ }
+    
 
  /* print output */
  for (x = y = 0; x < 32; x++) if (blk[x] != x) y = 1;
@@ -157,6 +168,7 @@ void cbc_tests(void)
     printf("CBC failed logical testing.\n");
     for (x = 0; x < 16; x++) printf("%02x ", ct[x]);
     printf("\n");
+    exit(-1);
  } else {
     printf("CBC passed logical testing.\n");
  }
@@ -178,11 +190,15 @@ void ofb_tests(void)
  for (x = 0; x < 32; x++) blk[x] = IV[x] = x;
 
  /* now lets start a ofb session */
- if ((errno = ofb_start(find_cipher("blowfish"), IV, key, 16, 0, &ofb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
+ if ((errno = ofb_start(find_cipher("cast5"), IV, key, 16, 0, &ofb)) != CRYPT_OK) { 
+ 	printf("OFB Setup: %s\n", error_to_string(errno)); exit(-1); }
 
  /* now lets encode 32 bytes */
- for (x = 0; x < 4; x++)
-    ofb_encrypt(blk+8*x, ct+8*x, 8, &ofb);
+ for (x = 0; x < 4; x++) {
+    if ((errno = ofb_encrypt(blk+8*x, ct+8*x, 8, &ofb)) != CRYPT_OK) {
+       printf("OFB encrypt: %s\n", error_to_string(errno)); exit(-1);
+    }
+ }
 
  zeromem(blk, sizeof(blk));
 
@@ -191,15 +207,20 @@ void ofb_tests(void)
  for (x = 0; x < 32; x++) IV[x] = x;
 
  /* now lets start a ofb session */
- if ((errno = ofb_start(find_cipher("blowfish"), IV, key, 16, 0, &ofb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
+ if ((errno = ofb_start(find_cipher("cast5"), IV, key, 16, 0, &ofb)) != CRYPT_OK) { 
+ 	printf("OFB setup: %s\n", error_to_string(errno)); exit(-1); }
 
  /* now lets decode 32 bytes */
- for (x = 0; x < 4; x++)
-    ofb_decrypt(ct+8*x, blk+8*x, 8, &ofb);
+ for (x = 0; x < 4; x++) {
+    if ((errno = ofb_decrypt(ct+8*x, blk+8*x, 8, &ofb)) != CRYPT_OK) {
+       printf("OFB decrypt: %s\n", error_to_string(errno)); exit(-1);
+    }
+ }
 
  /* print output */
  for (x = y = 0; x < 32; x++) if (blk[x] != x) y = 1;
  printf("  %s\n", y?"failed":"passed");
+ if (y) exit(-1);
 }
 #else
 void ofb_tests(void) { printf("OFB not compiled in\n"); }
@@ -218,11 +239,15 @@ void cfb_tests(void)
  for (x = 0; x < 32; x++) blk[x] = IV[x] = x;
 
  /* now lets start a cfb session */
- if ((errno = cfb_start(find_cipher("blowfish"), IV, key, 16, 0, &cfb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
+ if ((errno = cfb_start(find_cipher("blowfish"), IV, key, 16, 0, &cfb)) != CRYPT_OK) { 
+ 	printf("CFB setup: %s\n", error_to_string(errno)); exit(-1); }
 
  /* now lets encode 32 bytes */
- for (x = 0; x < 4; x++)
-    cfb_encrypt(blk+8*x, ct+8*x, 8, &cfb);
+ for (x = 0; x < 4; x++) {
+    if ((errno = cfb_encrypt(blk+8*x, ct+8*x, 8, &cfb)) != CRYPT_OK) {
+       printf("CFB encrypt: %s\n", error_to_string(errno)); exit(-1);
+    }
+ }
 
  zeromem(blk, sizeof(blk));
 
@@ -231,15 +256,20 @@ void cfb_tests(void)
  for (x = 0; x < 32; x++) IV[x] = x;
 
  /* now lets start a cfb session */
- if ((errno = cfb_start(find_cipher("blowfish"), IV, key, 16, 0, &cfb)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
+ if ((errno = cfb_start(find_cipher("blowfish"), IV, key, 16, 0, &cfb)) != CRYPT_OK) { 
+ 	printf("CFB Setup: %s\n", error_to_string(errno)); exit(-1); }
 
  /* now lets decode 32 bytes */
- for (x = 0; x < 4; x++)
-    cfb_decrypt(ct+8*x, blk+8*x, 8, &cfb);
+ for (x = 0; x < 4; x++) {
+    if ((errno = cfb_decrypt(ct+8*x, blk+8*x, 8, &cfb)) != CRYPT_OK) {
+       printf("CFB decrypt: %s\n", error_to_string(errno)); exit(-1);
+    }
+ }
 
  /* print output */
  for (x = y = 0; x < 32; x++) if (blk[x] != x) y = 1;
  printf("  %s\n", y?"failed":"passed");
+ if (y) exit(-1);
 }
 #else
 void cfb_tests(void) { printf("CFB not compiled in\n"); }
@@ -259,11 +289,15 @@ void ctr_tests(void)
  for (x = 0; x < 32; x++) blk[x] = count[x] = x;
 
  /* now lets start a ctr session */
- if ((errno = ctr_start(find_cipher("aes"), count, key, 16, 0, &ctr)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
+ if ((errno = ctr_start(find_cipher("xtea"), count, key, 16, 0, &ctr)) != CRYPT_OK) { 
+ 	printf("CTR Setup: %s\n", error_to_string(errno)); exit(-1); }
 
  /* now lets encode 32 bytes */
- for (x = 0; x < 4; x++)
-    ctr_encrypt(blk+8*x, ct+8*x, 8, &ctr);
+ for (x = 0; x < 4; x++) {
+    if ((errno = ctr_encrypt(blk+8*x, ct+8*x, 8, &ctr)) != CRYPT_OK) {
+       printf("CTR encrypt: %s\n", error_to_string(errno)); exit(-1);
+    }
+ }
 
  zeromem(blk, sizeof(blk));
 
@@ -272,15 +306,20 @@ void ctr_tests(void)
  for (x = 0; x < 32; x++) count[x] = x;
 
  /* now lets start a cbc session */
- if ((errno = ctr_start(find_cipher("aes"), count, key, 16, 0, &ctr)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
+ if ((errno = ctr_start(find_cipher("xtea"), count, key, 16, 0, &ctr)) != CRYPT_OK) { 
+ 	printf("CTR Setup: %s\n", error_to_string(errno)); exit(-1); }
 
  /* now lets decode 32 bytes */
- for (x = 0; x < 4; x++)
-    ctr_decrypt(ct+8*x, blk+8*x, 8, &ctr);
+ for (x = 0; x < 4; x++) {
+    if ((errno = ctr_decrypt(ct+8*x, blk+8*x, 8, &ctr)) != CRYPT_OK) {
+       printf("CTR decrypt: %s\n", error_to_string(errno)); exit(-1);
+    }
+ }
 
  /* print output */
  for (x = y = 0; x < 32; x++) if (blk[x] != x) y = 1;
  printf("  %s\n", y?"failed":"passed");
+ if (y) exit(-1);
 
  /* lets actually check the bytes */
  memset(count, 0, 8); count[0] = 0xFF;        /* IV  = FF 00 00 00 00 00 00 00 */
@@ -325,17 +364,18 @@ void pad_test(void)
 
  /* pad the message so that random filler is placed before and after it */
  y = 100;
- if ((errno = rsa_pad(in, 16, out, &y, find_prng("yarrow"), &prng)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
+ if ((errno = rsa_pad(in, 16, out, &y, find_prng("yarrow"), &prng)) != CRYPT_OK) { 
+     printf("Error: %s\n", error_to_string(errno)); exit(-1); }
 
  /* depad the message to get the original content */
  memset(in, 0, sizeof(in));
  x = 100;
- if ((errno = rsa_depad(out, y, in, &x)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
+ if ((errno = rsa_depad(out, y, in, &x)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
 
  /* check outcome */
  printf("rsa_pad: ");
- if (x != 16) { printf("Failed.  Wrong size.\n"); return; }
- for (x = 0; x < 16; x++) if (in[x] != x) { printf("Failed.  Expected %02lx and got %02x.\n", x, in[x]); return; }
+ if (x != 16) { printf("Failed.  Wrong size.\n"); exit(-1); }
+ for (x = 0; x < 16; x++) if (in[x] != x) { printf("Failed.  Expected %02lx and got %02x.\n", x, in[x]); exit(-1); }
  printf("passed.\n");
 }
 
@@ -349,100 +389,40 @@ void rsa_test(void)
 
  /* ---- SINGLE ENCRYPT ---- */
  /* encrypt a short 8 byte string */
- if ((errno = rsa_make_key(&prng, find_prng("yarrow"), 1024/8, 65537, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
+ if ((errno = rsa_make_key(&prng, find_prng("yarrow"), 1024/8, 65537, &key)) != CRYPT_OK) { 
+ 	printf("Error: %s\n", error_to_string(errno)); exit(-1); }
  for (x = 0; x < 8; x++) in[x] = (unsigned char)(x+1);
  y = sizeof(in);
- if ((errno = rsa_exptmod(in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
+ if ((errno = rsa_exptmod(in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { 
+ 	printf("Error: %s\n", error_to_string(errno)); exit(-1); }
 
  /* decrypt it */
  zeromem(in, sizeof(in));
  x = sizeof(out);
- if ((errno = rsa_exptmod(out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
+ if ((errno = rsa_exptmod(out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { 
+ 	printf("Error: %s\n", error_to_string(errno)); exit(-1); }
 
  /* compare */
  printf("RSA    : ");
- for (x = 0; x < 8; x++) if (in[x] != (x+1)) { printf("Failed.  x==%02lx, in[%ld]==%02x\n", x, x, in[x]); }
+ for (x = 0; x < 8; x++) if (in[x] != (x+1)) { printf("Failed.  x==%02lx, in[%ld]==%02x\n", x, x, in[x]); exit(-1); }
  printf("passed.\n");
 
-#ifdef PK_PACKET 
- /* ---- BLOCK ENCRYPT ---- */
- /* now lets test rsa_encrypt() */
- for (x = 0; x < 8; x++) in[x] = (unsigned char)x;
- x = sizeof(out);
- if ((errno = rsa_encrypt(in, 8, out, &x, &prng, find_prng("yarrow"), find_cipher("aes"), &key)) != CRYPT_OK) {
-    printf("Error: %s\n", error_to_string(errno));
-    return;
- }
-
- /* test rsa_decrypt() */
- zeromem(in, sizeof(in));
- y = sizeof(in);
- if ((errno = rsa_decrypt(out, x, in, &y, &key)) != CRYPT_OK) {
-    printf("Error: %s\n", error_to_string(errno));
-    return;
- }
- printf("rsa_encrypt()/rsa_decrypt(): ");
- for (y = 0; y < 8; y++) if (in[y] != y) { printf("failed.\n"); return; }
- printf("Passed.\n");
-
- /* ---- SIGNATURES ---- */
- x = sizeof(in);
- if ((errno = rsa_sign("hello", 5, in, &x, find_hash("md5"), &key)) != CRYPT_OK) {
-    printf("Error: %s\n", error_to_string(errno));
-    return;
- }
- if ((errno = rsa_verify(in, "hello", 5, &stat, &key)) != CRYPT_OK) {
-    printf("Error: %s\n", error_to_string(errno));
-    return;
- }
- printf("RSA Signatures: %s, ", (stat==1)?"pass":"fail");
- if ((errno = rsa_verify(in, "abcde", 5, &stat, &key)) != CRYPT_OK) {
-    printf("Error: %s\n", error_to_string(errno));
-    return;
- }
- printf("%s\n", (stat==0)?"pass":"fail");
-
- /* ---- EXPORT/IMPORT ---- */
- x = sizeof(out);
- if ((errno = rsa_export(out, &x, PK_PRIVATE_OPTIMIZED, &key)) != CRYPT_OK) {
-    printf("Error: %s\n", error_to_string(errno));
-    return;
- }
- printf("RSA Export takes %lu bytes\n", x);
- rsa_free(&key);
- if ((errno = rsa_import(out, &key, x)) != CRYPT_OK) {
-    printf("Error: %s\n", error_to_string(errno));
-    return;
- }
- printf("RSA Import: ");
- if ((errno = rsa_verify(in, "hello", 5, &stat, &key)) != CRYPT_OK) { 
-    printf("Error: %s\n", error_to_string(errno));
-    return;
- }
- printf("%s, ", (stat==1)?"pass":"fail");
- if ((errno = rsa_verify(in, "abcde", 5, &stat, &key)) != CRYPT_OK) { 
-    printf("Error: %s\n", error_to_string(errno));
-    return;
- }
- printf("%s\n", (stat==0)?"pass":"fail");
-#endif 
-
  /* test the rsa_encrypt_key functions */
  for (x = 0; x < 16; x++) in[x] = x;
  y = sizeof(out);
  if ((errno = rsa_encrypt_key(in, 16, out, &y, &prng, find_prng("yarrow"), &key)) != CRYPT_OK) {
     printf("Error: %s\n", error_to_string(errno));
-    return;
+    exit(-1);
  }
  zeromem(in, sizeof(in));
  x = sizeof(in);
- if ((errno = rsa_decrypt_key(out, in, &x, &key)) != CRYPT_OK) {
+ if ((errno = rsa_decrypt_key(out, y, in, &x, &key)) != CRYPT_OK) {
     printf("Error: %s\n", error_to_string(errno));
-    return;
+    exit(-1);
  }
  printf("RSA en/de crypt key routines: ");
- if (x != 16) { printf("Failed (length)\n"); return; }
- for (x = 0; x < 16; x++) if (in[x] != x) { printf("Failed (contents)\n"); return; }
+ if (x != 16) { printf("Failed (length)\n"); exit(-1); }
+ for (x = 0; x < 16; x++) if (in[x] != x) { printf("Failed (contents)\n"); exit(-1); }
  printf("Passed\n");
 
  /* test sign_hash functions */
@@ -450,24 +430,25 @@ void rsa_test(void)
  x = sizeof(in);
  if ((errno = rsa_sign_hash(in, 16, out, &x, &key)) != CRYPT_OK) {
     printf("Error: %s\n", error_to_string(errno));
-    return;
+    exit(-1);
  }
  printf("RSA signed hash: %lu bytes\n", x);
- if ((errno = rsa_verify_hash(out, in, &stat, &key)) != CRYPT_OK) {
+ if ((errno = rsa_verify_hash(out, x, in, &stat, &key)) != CRYPT_OK) {
     printf("Error: %s\n", error_to_string(errno));
-    return;
+    exit(-1);
  }
  printf("Verify hash: %s, ", stat?"passed":"failed");
  in[0] ^= 1;
- if ((errno = rsa_verify_hash(out, in, &stat, &key)) != CRYPT_OK) {
+ if ((errno = rsa_verify_hash(out, x, in, &stat, &key)) != CRYPT_OK) {
     printf("Error: %s\n", error_to_string(errno));
-    return;
+    exit(-1);
  }
  printf("%s\n", (!stat)?"passed":"failed");
+ if (stat) exit(-1);
  rsa_free(&key);
 
  /* make a RSA key */
-#ifdef SONY_PS2
+#ifdef SONY_PS2_NOPE
    limit = 1024;
 #else
    limit = 2048;
@@ -475,21 +456,21 @@ void rsa_test(void)
 
  for (z = 1024; z <= limit; z += 512) {
     t = XCLOCK();
-    if ((errno = rsa_make_key(&prng, find_prng("yarrow"), z/8, 65537, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
+    if ((errno = rsa_make_key(&prng, find_prng("yarrow"), z/8, 65537, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
     t = XCLOCK() - t;
     printf("Took %.0f ms to make a %ld-bit RSA key.\n", 1000.0 * ((double)t / (double)XCLOCKS_PER_SEC), z);
 
     /* time encryption */
     y = sizeof(in);
     t = XCLOCK();
-    if ((errno = rsa_exptmod(in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
+    if ((errno = rsa_exptmod(in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
     t = XCLOCK() - t;
     printf("Took %.0f ms to encrypt with a %ld-bit RSA key.\n", 1000.0 * ((double)t / (double)XCLOCKS_PER_SEC), z);
 
     /* time decryption */
     x = sizeof(out);
     t = XCLOCK();
-    if ((errno = rsa_exptmod(out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); return; }
+    if ((errno = rsa_exptmod(out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
     t = XCLOCK() - t;
     printf("Took %.0f ms to decrypt with a %ld-bit RSA key.\n", 1000.0 * ((double)t / (double)XCLOCKS_PER_SEC), z);
     rsa_free(&key);
@@ -516,19 +497,19 @@ void base64_test(void)
    x = 100;
    if (base64_encode(buf[0], 16, buf[1], &x) != CRYPT_OK) {
       printf("  error: %s\n", error_to_string(errno));
-      return;
+      exit(-1);
    }
    printf("  encoded 16 bytes to %ld bytes...[%s]\n", x, buf[1]);
    memset(buf[0], 0, 100);
    y = 100;
    if (base64_decode(buf[1], x, buf[0], &y) != CRYPT_OK) {
       printf("  error: %s\n", error_to_string(errno));
-      return;
+      exit(-1);
    }
    printf("  decoded %ld bytes to %ld bytes\n", x, y);
    for (x = 0; x < 16; x++) if (buf[0][x] != x) { 
       printf(" **failed**\n"); 
-      return; 
+      exit(-1); 
    }
    printf("  passed\n");
 }
@@ -642,50 +623,50 @@ void dh_tests(void)
    /* make up two keys */
    if ((errno = dh_make_key(&prng, find_prng("yarrow"), 96, &usera)) != CRYPT_OK) {
       printf("Error: %s\n", error_to_string(errno));
-      return;
+      exit(-1);
    }
    if ((errno = dh_make_key(&prng, find_prng("yarrow"), 96, &userb)) != CRYPT_OK) {
       printf("Error: %s\n", error_to_string(errno));
-      return;
+      exit(-1);
    }
 
    /* make the shared secret */
    x = 4096;
    if ((errno = dh_shared_secret(&usera, &userb, buf[0], &x)) != CRYPT_OK) {
       printf("Error: %s\n", error_to_string(errno));
-      return;
+      exit(-1);
    }
 
    y = 4096;
    if ((errno = dh_shared_secret(&userb, &usera, buf[1], &y)) != CRYPT_OK) {
       printf("Error: %s\n", error_to_string(errno));
-      return;
+      exit(-1);
    }
-   if (y != x) { printf("DH Shared keys are not same size.\n"); return; }
-   if (memcmp(buf[0], buf[1], x)) { printf("DH Shared keys not same contents.\n"); return; }
+   if (y != x) { printf("DH Shared keys are not same size.\n"); exit(-1); }
+   if (memcmp(buf[0], buf[1], x)) { printf("DH Shared keys not same contents.\n"); exit(-1); }
 
    /* now export userb */
    y = 4096;
    if ((errno = dh_export(buf[1], &y, PK_PUBLIC, &userb)) != CRYPT_OK) {
       printf("Error: %s\n", error_to_string(errno));
-      return;
+      exit(-1);
    }
    dh_free(&userb);
 
    /* import and make the shared secret again */
    if ((errno = dh_import(buf[1], y, &userb)) != CRYPT_OK) {
       printf("Error: %s\n", error_to_string(errno));
-      return;
+      exit(-1);
    }
    z = 4096;
    if ((errno = dh_shared_secret(&usera, &userb, buf[2], &z)) != CRYPT_OK) {
       printf("Error: %s\n", error_to_string(errno));
-      return;
+      exit(-1);
    }
 
    printf("DH routines: ");
-   if (z != x) { printf("failed.  Size don't match?\n"); return; }
-   if (memcmp(buf[0], buf[2], x)) { printf("Failed.  Content didn't match.\n"); return; }
+   if (z != x) { printf("failed.  Size don't match?\n"); exit(-1); }
+   if (memcmp(buf[0], buf[2], x)) { printf("Failed.  Content didn't match.\n"); exit(-1); }
    printf("Passed\n");
    dh_free(&usera);
    dh_free(&userb);
@@ -703,7 +684,7 @@ void dh_tests(void)
    printf("Make dh-1024 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC));
    dh_free(&usera);
 
-#ifndef SONY_PS2
+#ifndef SONY_PS2_NOPE
    t1 = XCLOCK();
    dh_make_key(&prng, find_prng("yarrow"), 160, &usera);
    t1 = XCLOCK() - t1;
@@ -735,71 +716,23 @@ void dh_tests(void)
    dh_free(&usera);
 #endif   
    
-#ifdef PK_PACKET
-/* try dh packet stuff */
-   for (x = 0; x < 16; x++) buf[0][x] = (unsigned char)x;
-   dh_make_key(&prng, find_prng("yarrow"), 24, &usera);
-
-   x = 4096;
-   if (dh_encrypt(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), find_cipher("aes"),
-                   find_hash("sha1"), &usera) != CRYPT_OK) {
-      printf("dh_encrypt says %s\n", error_to_string(errno));
-      return;
-   }
-   printf("dh encrypted 16 bytes into %ld bytes!\n", x);
-
-   y = 4096;
-   if ((errno = dh_decrypt(buf[1], x, buf[2], &y, &usera)) != CRYPT_OK) {
-      printf("dh_decrypt says %s\n", error_to_string(errno));
-      return;
-   }
-
-   printf("dh packet: ");
-   if (16 != y) { printf("Failed: Sizes different! 16 vs %ld\n", y); return; }
-   if (memcmp(buf[0], buf[2], 16)) { printf("Failed; Content mismatch.\n"); return; }
-   printf("Passed!\n");
-   dh_free(&usera);
-
-/* try dh signatures */
-   dh_make_key(&prng, find_prng("yarrow"), 96, &usera);
-   x = 4096;
-   if ((errno = dh_sign("hello", 5, buf[0], &x, find_hash("sha1"), &prng, find_prng("yarrow"), &usera)) != CRYPT_OK) {
-      printf("Error: %s\n", error_to_string(errno));
-      return;
-   }
-
-   printf("dh-768 Signature took %ld bytes\n", x);
-
-   if ((errno = dh_verify(buf[0], "hello", 5, &stat, &usera)) != CRYPT_OK) {
-      printf("Error: %s\n", error_to_string(errno));
-      return;
-   }
-   if ((errno = dh_verify(buf[0], "hellp", 5, &stat2, &usera)) != CRYPT_OK) {
-      printf("Error: %s\n", error_to_string(errno));
-      return;
-   }
-
-   printf("dh Signatures: %s (%d,%d)\n", ((stat==1)&&(stat2==0))?"passed":"failed", stat,stat2);
-   dh_free(&usera);
-#endif  
-
 /* test encrypt_key */
  dh_make_key(&prng, find_prng("yarrow"), 96, &usera);
  for (x = 0; x < 16; x++) buf[0][x] = x;
  y = sizeof(buf[1]);
  if ((errno = dh_encrypt_key(buf[0], 16, buf[1], &y, &prng, find_prng("yarrow"), find_hash("md5"), &usera)) != CRYPT_OK) {
     printf("Error: %s\n", error_to_string(errno));
-    return;
+    exit(-1);
  }
  zeromem(buf[0], sizeof(buf[0]));
  x = sizeof(buf[0]);
- if ((errno = dh_decrypt_key(buf[1], buf[0], &x, &usera)) != CRYPT_OK) {
+ if ((errno = dh_decrypt_key(buf[1], y, buf[0], &x, &usera)) != CRYPT_OK) {
     printf("Error: %s\n", error_to_string(errno));
-    return;
+    exit(-1);
  }
  printf("DH en/de crypt key routines: ");
- if (x != 16) { printf("Failed (length)\n"); return; }
- for (x = 0; x < 16; x++) if (buf[0][x] != x) { printf("Failed (contents)\n"); return; }
+ if (x != 16) { printf("Failed (length)\n"); exit(-1); }
+ for (x = 0; x < 16; x++) if (buf[0][x] != x) { printf("Failed (contents)\n"); exit(-1); }
  printf("Passed (size %lu)\n", y);
 
 /* test sign_hash */
@@ -807,16 +740,16 @@ void dh_tests(void)
    x = sizeof(buf[1]);
    if ((errno = dh_sign_hash(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), &usera)) != CRYPT_OK) {
     printf("Error: %s\n", error_to_string(errno));
-    return;
+    exit(-1);
    }
-   if (dh_verify_hash(buf[1], buf[0], 16, &stat, &usera)) {
+   if (dh_verify_hash(buf[1], x, buf[0], 16, &stat, &usera)) {
     printf("Error: %s\n", error_to_string(errno));
-    return;
+    exit(-1);
    }
    buf[0][0] ^= 1;
-   if (dh_verify_hash(buf[1], buf[0], 16, &stat2, &usera)) {
+   if (dh_verify_hash(buf[1], x, buf[0], 16, &stat2, &usera)) {
     printf("Error: %s\n", error_to_string(errno));
-    return;
+    exit(-1);
    }
    printf("dh_sign/verify_hash: %s (%d,%d)\n", ((stat==1)&&(stat2==0))?"passed":"failed", stat,stat2);
  dh_free(&usera);
@@ -868,7 +801,7 @@ void ecc_tests(void)
    ecc_key usera, userb;
    clock_t t1;
 
-   if ((errno = ecc_test()) != CRYPT_OK) printf("ecc Error: %s\n", error_to_string(errno));
+   if ((errno = ecc_test()) != CRYPT_OK) { printf("ecc Error: %s\n", error_to_string(errno)); exit(-1); }
 
    ecc_sizes(&low, &high);
    printf("ecc Keys from %d to %d supported.\n", low*8, high*8);
@@ -876,35 +809,35 @@ void ecc_tests(void)
    /* make up two keys */
    if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 24, &usera)) != CRYPT_OK) {
       printf("Error: %s\n", error_to_string(errno));
-      return;
+      exit(-1);
    }
    if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 24, &userb)) != CRYPT_OK) {
       printf("Error: %s\n", error_to_string(errno));
-      return;
+      exit(-1);
    }
 
    /* make the shared secret */
    x = 4096;
    if ((errno = ecc_shared_secret(&usera, &userb, buf[0], &x)) != CRYPT_OK) {
       printf("Error: %s\n", error_to_string(errno));
-      return;
+      exit(-1);
    }
 
    y = 4096;
    if ((errno = ecc_shared_secret(&userb, &usera, buf[1], &y)) != CRYPT_OK) {
       printf("Error: %s\n", error_to_string(errno));
-      return;
+      exit(-1);
    }
 
-   if (y != x) { printf("ecc Shared keys are not same size.\n"); return; }
+   if (y != x) { printf("ecc Shared keys are not same size.\n"); exit(-1); }
 
-   if (memcmp(buf[0], buf[1], x)) { printf("ecc Shared keys not same contents.\n"); return; }
+   if (memcmp(buf[0], buf[1], x)) { printf("ecc Shared keys not same contents.\n"); exit(-1); }
 
    /* now export userb */
    y = 4096;
    if ((errno = ecc_export(buf[1], &y, PK_PUBLIC, &userb)) != CRYPT_OK) {
       printf("Error: %s\n", error_to_string(errno));
-      return;
+      exit(-1);
    }
    ecc_free(&userb);
    printf("ECC-192 export took %ld bytes\n", y);
@@ -912,142 +845,94 @@ void ecc_tests(void)
    /* import and make the shared secret again */
    if ((errno = ecc_import(buf[1], y, &userb)) != CRYPT_OK) {
       printf("Error: %s\n", error_to_string(errno));
-      return;
+      exit(-1);
    }
 
    z = 4096;
    if ((errno = ecc_shared_secret(&usera, &userb, buf[2], &z)) != CRYPT_OK) {
       printf("Error: %s\n", error_to_string(errno));
-      return;
+      exit(-1);
    }
 
    printf("ecc routines: ");
-   if (z != x) { printf("failed.  Size don't match?\n"); return; }
-   if (memcmp(buf[0], buf[2], x)) { printf("Failed.  Content didn't match.\n"); return; }
+   if (z != x) { printf("failed.  Size don't match?\n"); exit(-1); }
+   if (memcmp(buf[0], buf[2], x)) { printf("Failed.  Content didn't match.\n"); exit(-1); }
    printf("Passed\n");
    ecc_free(&usera);
    ecc_free(&userb);
 
 /* time stuff */
    t1 = XCLOCK();
-   ecc_make_key(&prng, find_prng("yarrow"), 20, &usera);
+   if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 20, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
    t1 = XCLOCK() - t1;
    printf("Make ECC-160 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC));
    ecc_free(&usera);
 
    t1 = XCLOCK();
-   ecc_make_key(&prng, find_prng("yarrow"), 24, &usera);
+   if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 24, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
    t1 = XCLOCK() - t1;
    printf("Make ECC-192 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC));
    ecc_free(&usera);
 
    t1 = XCLOCK();
-   ecc_make_key(&prng, find_prng("yarrow"), 28, &usera);
+   if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 28, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
    t1 = XCLOCK() - t1;
    printf("Make ECC-224 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC));
    ecc_free(&usera);
    
 #ifndef SONY_PS2
    t1 = XCLOCK();
-   ecc_make_key(&prng, find_prng("yarrow"), 32, &usera);
+   if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 32, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
    t1 = XCLOCK() - t1;
    printf("Make ECC-256 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC));
    ecc_free(&usera);
 
    t1 = XCLOCK();
-   ecc_make_key(&prng, find_prng("yarrow"), 48, &usera);
+   if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 48, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
    t1 = XCLOCK() - t1;
    printf("Make ECC-384 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC));
    ecc_free(&usera);
 
    t1 = XCLOCK();
-   ecc_make_key(&prng, find_prng("yarrow"), 65, &usera);
+   if ((errno = ecc_make_key(&prng, find_prng("yarrow"), 65, &usera)) != CRYPT_OK) { printf("Error: %s\n", error_to_string(errno)); exit(-1); }
    t1 = XCLOCK() - t1;
    printf("Make ECC-521 key took %f msec\n", 1000.0 * ((double)t1 / (double)XCLOCKS_PER_SEC));
    ecc_free(&usera);
 #endif   
 
-#ifdef PK_PACKET
-/* try ECC packet stuff */
-   for (x = 0; x < 16; x++) buf[0][x] = (unsigned char)x;
-   ecc_make_key(&prng, find_prng("yarrow"), 20, &usera);
-
-   x = 4096;
-   if (ecc_encrypt(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), find_cipher("aes"),
-                   find_hash("tiger"), &usera) != CRYPT_OK) {
-      printf("ecc_encrypt says %s\n", error_to_string(errno));
-      return;
-   }
-   printf("Ecc encrypted 16 bytes into %ld bytes!\n", x);
-
-   y = 4096;
-   if ((errno = ecc_decrypt(buf[1], x, buf[2], &y, &usera)) != CRYPT_OK) {
-      printf("ecc_decrypt says %s\n", error_to_string(errno));
-      return;
-   }
-
-   printf("ECC packet: ");
-   if (16 != y) { printf("Failed: Sizes different! 16 vs %ld\n", y); return; }
-   if (memcmp(buf[0], buf[2], 16)) { printf("Failed; Content mismatch.\n"); return; }
-   printf("Passed!\n");
-   ecc_free(&usera);
-
-/* try ECC signatures */
-   ecc_make_key(&prng, find_prng("yarrow"), 20, &usera);
-   x = 4096;
-   if ((errno = ecc_sign("hello", 5, buf[0], &x, find_hash("sha1"), &prng, find_prng("yarrow"), &usera)) != CRYPT_OK) {
-      printf("Error: %s\n", error_to_string(errno));
-      return;
-   }
-
-   printf("ECC-160 Signature took %ld bytes\n", x);
-
-   if ((errno = ecc_verify(buf[0], "hello", 5, &stat, &usera)) != CRYPT_OK) {
-      printf("Error: %s\n", error_to_string(errno));
-      return;
-   }
-   if ((errno = ecc_verify(buf[0], "hellp", 5, &stat2, &usera)) != CRYPT_OK) {
-      printf("Error: %s\n", error_to_string(errno));
-      return;
-   }
-
-   printf("ECC Signatures: %s (%d,%d)\n", ((stat==1)&&(stat2==0))?"passed":"failed", stat,stat2);
-   ecc_free(&usera);
-#endif
-
 /* test encrypt_key */
  ecc_make_key(&prng, find_prng("yarrow"), 32, &usera);
  for (x = 0; x < 16; x++) buf[0][x] = x;
  y = sizeof(buf[1]);
  if ((errno = ecc_encrypt_key(buf[0], 16, buf[1], &y, &prng, find_prng("yarrow"), find_hash("md5"), &usera)) != CRYPT_OK) {
     printf("Error: %s\n", error_to_string(errno));
-    return;
+    exit(-1);
  }
  zeromem(buf[0], sizeof(buf[0]));
  x = sizeof(buf[0]);
- if ((errno = ecc_decrypt_key(buf[1],buf[0], &x, &usera)) != CRYPT_OK) {
+ if ((errno = ecc_decrypt_key(buf[1], y, buf[0], &x, &usera)) != CRYPT_OK) {
     printf("Error: %s\n", error_to_string(errno));
-    return;
+    exit(-1);
  }
  printf("ECC en/de crypt key routines: ");
- if (x != 16) { printf("Failed (length)\n"); return; }
- for (x = 0; x < 16; x++) if (buf[0][x] != x) { printf("Failed (contents)\n"); return; }
+ if (x != 16) { printf("Failed (length)\n"); exit(-1); }
+ for (x = 0; x < 16; x++) if (buf[0][x] != x) { printf("Failed (contents)\n"); exit(-1); }
  printf("Passed (size: %lu)\n", y);
 /* test sign_hash */
    for (x = 0; x < 16; x++) buf[0][x] = x;
    x = sizeof(buf[1]);
    if ((errno = ecc_sign_hash(buf[0], 16, buf[1], &x, &prng, find_prng("yarrow"), &usera)) != CRYPT_OK) {
     printf("Error: %s\n", error_to_string(errno));
-    return;
+    exit(-1);
    }
-   if (ecc_verify_hash(buf[1], buf[0], 16, &stat, &usera)) {
+   if (ecc_verify_hash(buf[1], x, buf[0], 16, &stat, &usera)) {
     printf("Error: %s\n", error_to_string(errno));
-    return;
+    exit(-1);
    }
    buf[0][0] ^= 1;
-   if (ecc_verify_hash(buf[1], buf[0], 16, &stat2, &usera)) {
+   if (ecc_verify_hash(buf[1], x, buf[0], 16, &stat2, &usera)) {
     printf("Error: %s\n", error_to_string(errno));
-    return;
+    exit(-1);
    }
    printf("ecc_sign/verify_hash: %s (%d,%d)\n", ((stat==1)&&(stat2==0))?"passed":"failed", stat,stat2);
  ecc_free(&usera);
@@ -1185,15 +1070,16 @@ void register_all_algs(void)
 
    register_cipher(&null_desc);
 
+#ifdef SHA1
+   register_hash(&sha1_desc);
+#endif
 #ifdef SHA256
    register_hash(&sha256_desc);
 #endif
 #ifdef TIGER
    register_hash(&tiger_desc);
 #endif
-#ifdef SHA1
-   register_hash(&sha1_desc);
-#endif
+
 #ifdef MD5
    register_hash(&md5_desc);
 #endif
@@ -1383,18 +1269,18 @@ void kr_test(void)
 
        len = sizeof(buf2);
        if ((errno = kr_sign_hash(kr, _kr->ID, buf, 32, buf2, &len, &prng, find_prng("yarrow"))) != CRYPT_OK) {
-          printf("kr_sign_hash failed, %i, %lu\n", i, len);
+          printf("kr_sign_hash failed, %i, %s\n", i, error_to_string(errno));
           exit(-1);
        }
        printf("kr_sign_hash: ");
        if ((errno = kr_verify_hash(kr, buf2, buf, 32, &stat)) != CRYPT_OK) {
-          printf("kr_sign_hash failed, %i, %lu\n", i, len);
+          printf("kr_sign_hash failed, %i, %s\n", i, error_to_string(errno));
           exit(-1);
        }
        printf("%s, ", stat?"passed":"failed");
        buf[15] ^= 1;
        if ((errno = kr_verify_hash(kr, buf2, buf, 32, &stat)) != CRYPT_OK) {
-          printf("kr_sign_hash failed, %i, %lu\n", i, len);
+          printf("kr_sign_hash failed, %i, %s\n", i, error_to_string(errno));
           exit(-1);
        }
        printf("%s\n", (!stat)?"passed":"failed");
@@ -1542,7 +1428,7 @@ int main(void)
  if ((errno = yarrow_ready(&prng)) != CRYPT_OK) {
     printf("yarrow_ready: %s\n", error_to_string(errno));
  }
-
+ 
  printf(crypt_build_settings);
  test_errs();
 

+ 82 - 93
dh.c

@@ -12,10 +12,9 @@ static const struct {
    96,
    "DH-768",
    "2",
-   "2893527720709661239493896562339544088620375736490408468011883030469939904368"
-   "0860923364582982212457078989335831907131881773994018526277492109945959747917"
-   "8279025394653904396221302707492255957231214118178743427870878320796645901947"
-   "9487"
+   "1tH+dRFGpEYyVLe4ydZcYyGDpeAxnChz0yk+pNCtkEXwUsOORyguBtx8spUD"
+   "FAjEDS8PutUBTEu2q4USqu19dUbCLj9D2jY7y3871RnSccurMBsMm35ILcyQ"
+    "rpN0MQKc/"
 },
 #endif
 #ifdef DH1024
@@ -23,11 +22,9 @@ static const struct {
    128,
    "DH-1024",
    "2",
-   "3477431594398766260792527967974222231775354473882066076071816639030459075912"
-   "0194047822362172211817327089848758298713770865641434468581617942085516098634"
-   "0457973820182883508387588163122354089264395604796675278966117567294812714812"
-   "7968205965648764507160662831267200108590414847865290564578963676831229604111"
-   "36319"
+   "Uypu+t9nfUnCj7xD+xokM+Cd6mASW4ofg1jpC2BpQasC5edtA1dJC+RjbOBZ"
+   "z+5mvq5VYT8Wfjmlpjm9tQxHOYB0+3Myl7gbCQ5SRljWT2oBLukLNvgFjiU4"
+   "wiWkmu41Ern/j6uxwKb740C+VIgDAdeUY4fA5hyfr3/+DWYb14/"
 },
 #endif
 #ifdef DH1280
@@ -35,12 +32,10 @@ static const struct {
    160,
    "DH-1280",
    "2",
-   "2618298020488323341377089635550383393554460131909411928885489146533597039863"
-   "5379029297773089246854323581071445272213255646852180580463169755159411503866"
-   "4190218001872082125570169842848154404911652982668791288605239288293106162305"
-   "7236093554796242806887062958692596037823904832542385180840218330924392268465"
-   "0197244314233248991982159235832322194332167923655574170280697353556560854901"
-   "280047"
+   "520QV4Tsq4NwK9Mt5CGR9xk4slvaikgi/ax3OPky5GERKTsoqEXOlFyMzURP"
+   "P8jYzCVz1izKd2zTDxbFfLxrJry0ceaQ5YZa5N4teByCPVlQh4v6iQl+944+"
+   "/NDlKzvWpx7HG7k8cGKhva7aFF8bP/CvLpaQhrfXlOX+X9pcmML9QH63tUjq"
+   "B80l8Yx9KN0dC3iNnsTV3DnqnEvFQkoqql"
 },
 #endif
 #ifdef DH1536
@@ -48,13 +43,11 @@ static const struct {
    192,
    "DH-1536",
    "3",
-   "2992593690703251306835100868059076484222548092264611010748654597096560864537"
-   "1704684310938824733433085888971827086341295918925237859522548192211945291282"
-   "1170570153374563548621496076860061698150233114892317627457427359445435608693"
-   "5625000902194809114890745455404045166957722404567939575618007347432055137282"
-   "3291711752537781447636541738638119983678441628437171377508654097130147131310"
-   "9209393805685590941710151477648542896503595482724205166251069428524927527085"
-   "2602467"
+   "1FTWXrPcY1w74oZ0ouIzSN8uZcRiOf6U11fx0ka6+7fqIAezPhd3Ab43QnDf"
+   "KFg+or/fFRGEWAxF8WIE2jx8iTOu010yNEQyH14CK0RAyy2zY4gRs2MpnU5r"
+   "/feWf60OkLtnPzN34+Xnlg5xf7Jl00wkHRCeJG17L3SklOidAPxWnE+Wm4BS"
+   "SOzdQBgiZOjlhrYS1+TIU3NP5H7BrtKFcf+ZwBULibf29L7LkDOgQbie1+43"
+   "lU+8SHAyBwAeGYMfZ"
 },
 #endif
 #ifdef DH1792
@@ -62,14 +55,11 @@ static const struct {
    224,
    "DH-1792",
    "2",
-   "3210090394251532205679207425273650879078185529033544241951292722086520015900"
-   "0402371844205168176419829949232601235193754977706171541009393172204470047690"
-   "6659627844880912479392592056697278305733615369406596661203184035142652643118"
-   "1379603333858737848321053048184938839622944591194935387992479717305577175500"
-   "2554620614907177847128950276247571809502831255425929468853285490357704941968"
-   "3407102520889651917659577334897408316217748346860775479727332331727022096550"
-   "7718799868459391361770854814013613619048768630587629568449528005570971478547"
-   "34960319"
+   "IPo3wjvfS7vBYnFHwJHmesA51od9fnR8Aenezif4qLE2HX+YCv1tpvHA8yLH"
+   "yYbKe9QfSHHtOgVjK8AYEyPirpXxlmdykGuj+dX7EiWMRGYc+v1kKkqmCn0o"
+   "5tU416O/1HXTpQ2Hps0buchUD+HlCMrSgnIqRxK6Fjr0ZfiCS4XgAD6sLgi0"
+   "BxKFMxDsVzpGMNwF5Lj2R/cJiTi0cNDDY3gn4lK/PRUsJtRKU+9sxy0q5Yof"
+   "aG5VO8VcHkZJVwUKhDFHkZYWMHV808TGHXM2RQ9kRa2QvS2mXxMrDSCloQ/"
 },
 #endif
 #ifdef DH2048
@@ -77,15 +67,12 @@ static const struct {
    256,
    "DH-2048",
    "2",
-   "4726642895635639316469736509812041897640060270607231273592407174543853221823"
-   "7979333351774907308168340693326687317443721193266215155735814510792148768576"
-   "4984911991227443513994894535335532038333186916782632419417062569961974604240"
-   "2901241901263467186228353234265630967717360250949841797609150915436003989316"
-   "5037637034737020327399910409885798185771003505320583967737293415979917317338"
-   "9858373857347474783642420203804168920566508414708692945275435973492502995396"
-   "8243060517332102902655554683247304860032703684578197028928889831788842751736"
-   "4945316709081173840186150794397479045034008257793436817683392375274635794835"
-   "245695887"
+   "5sR1VmdsQQzzjN0iridVVyveug6sAC3+/jTIHSgEoimPOREXQ05r2WJZJAF2"
+   "CRu8kuusiPw2ivRli+fdLr63v1uZG5nQa28uLwNxZEsu4gu6TrGjepXeXm4Z"
+   "CVOC1HMmi660fLZ2ruHLa4v2NWex2Zx91/y4ygPlZM+K//iy+Gft9Ma9Ayn0"
+   "eYwofZeUL9vJSfutPVp2ZrIEUQDBKMvMm0SRSLiUjDtzXqrH+b/wuwIFG1K4"
+   "var3ucsT45mDzD9qb3tBdksSPZbr6yrELV8h+qmjiBr15oHKEglS0XwSvCap"
+   "abUn5XPPVoaKv13+tOnG9mGgzQ8JeClVXN63Q+GGEF"
 },
 #endif
 #ifdef DH2560
@@ -93,17 +80,14 @@ static const struct {
    320,
    "DH-2560",
    "3",
-   "4364638085059577685748948703943497396233464406019459611612544400721432981520"
-   "4010567649104824811014627875285783993051576616744140702150122992472133564455"
-   "7342265864606569000117714935185566842453630868849121480179691838399545644365"
-   "5711067577313173717585579907818806913366955847993133136872874688941488237617"
-   "8558298254958618375680644901754262226787427510387748147553499120184991222267"
-   "0102069951687572917937634467778042874315463238062009202992087620963771759666"
-   "4482665328580794026699200252242206134194410697184828373996126449788399252071"
-   "0987084027819404215874884544513172913711709852902888677006373648742061314404"
-   "5836803985635654192482395882603511950547826439092832800532152534003936926017"
-   "6124466061356551464456206233957889787267447285030586700468858762515271223502"
-   "75750995227"
+   "G7UVKk+N6LfpGkdBP6XLB4QJ3wzee5YH/3o6tBDMwr4FS8YjCmeP6l4gu0hX"
+   "dzY2Rive4TYOu4Akm4naZuv32d71/2lQeNcO23BNYOEPxtn9BU8uYfaHP9Mo"
+   "M+m76oUCiI5uqpag5RH3BO34FyE4BiKkzjEXq9xxc8ERacG8Mo8DNiXu79p9"
+   "Q/0wsRz+W/lIN4gYw3w4iLMooAGnDrhcj5cZb0HysHWYfqmFo+jTBP6Egi0g"
+   "cmVO2qWQh2cZIQMfppaf1Ffq0XGIJpgDFyOHPl3NVxDabVK1tkVct+hathxJ"
+   "UTdqZmR2VFwMASXjfgj4VFdvFCUxV8Xr8JcwXkwlMjOJbAl0LoCa4M7hpYvz"
+   "G/0XviGCpv7qQaONKtsiQ6mHhMcyo9hBCRZXtNPkfPMZkPeV05akvaDs6Ek7"
+   "DZ62oKR"
 },
 #endif
 #ifdef DH3072
@@ -111,19 +95,15 @@ static const struct {
    384,
    "DH-3072",
    "2",
-   "1142416747335183639807830604262436227795642944052113706188970261176634876069"
-   "2206243140413411077394583180726863277012016602279290144126785129569474909173"
-   "5847898223419867427192303319460727303195559844849117167970588759054009995043"
-   "0587724584911968750902323279027363746682105257685923245298206183100977078603"
-   "1785669030271542286603956118755585683996118896215213488875253101894663403069"
-   "6777459483058938495054342017637452328957807119724320113448575216910178963168"
-   "6140320644942133224365885545343578400651720289418164056243357539082138421096"
-   "0117518650374602256601091379644034244332285065935413233557998331562749140202"
-   "9658442193362989700115138825649355387042894469683222814519074873620465114612"
-   "2132979989735099337056069750580968643878203623537213701573130477907243026098"
-   "6460269894522159103008260495503005267165927542949439526272736586626709581721"
-   "0321895327263896436255906801057848442461527026701693042037830722750891947548"
-   "89511973916207"
+   "1zsV6XgY57R/hu2RR4H/BjwRqmQL9h+Dc5rgoWOcqiTS8qpVTWafi1KFV77V"
+   "rUcjcer1EDgCV0tpzlemtyrC2pHpw7hr3EEl2evfWOvg05FRI6mKc2UPNv2c"
+   "2Bjww4LD/tdsLleX7AHHXCXFSSyd6C3qWq7BqABZriSpQeaEtXbWfeC6ytFe"
+   "2i3VeQsLa40XQ21UxwhPAjamjSOfYzkW7xi0fwI1e+4OQiFcWOfOuvswoaEf"
+   "MIICyAmVp67vjGo66dk81dMemyplipgXAWPdl7ppnDd6cEjyN4N90D7kQiNg"
+   "lVmJlKLecldOUtdIqMnbJCbiN/t/3/AEFaokGO9om5ckc6M9gG5PG0T7Oh1N"
+   "dSx/PstGdxwvs9DOwjyo5wl5C9QSLtUYJl2+GZYMj6WfsgCrb6jjRJJJQe2C"
+   "y7wUcBILbRsP3lYT8s14zm4xFBrfMUoLN287j3wQ1TNUXjYSCi4ZLKT1XDai"
+   "93345OiutLOqGGikFg6ypnymJK3yeHuul"
 },
 #endif
 #ifdef DH4096
@@ -131,23 +111,18 @@ static const struct {
    512,
    "DH-4096", 
    "3",
-   "1214855636816562637502584060163403830270705000634713483015101384881871978446"
-   "8012247985361554068958233050354675916325310675478909486951171720769542207270"
-   "7568804875102242119871203284889005635784597424656074834791863005085393369779"
-   "2254955890439720297560693579400297062396904306270145886830719309296352765295"
-   "7121830407731464190228751653827780070401099576097395898755908857011261979060"
-   "6362013395489321661267883850754077713843779770560245371955901763398648664952"
-   "3611975865005712371194067612263330335590526176087004421363598470302731349138"
-   "7732059014477046821815179040647356365184624522427916765417252923789255682968"
-   "5801015185232631677751193503753101741391050692192245066693320227848902452126"
-   "3798482237150056835746454842662048692127173834433089016107854491097456725016"
-   "3277096631997382384421648431471327891537255132571679155551620949708535844479"
-   "9312548860769600816980737473671129700747381225627224548940589847029717873802"
-   "9484459690836250560495461579533254473316340608217876781986188705928270735695"
-   "7528308255279638383554197625162460286802809880204019145518254873499903069763"
-   "0409310938445143881325121105159739212749146489879740678917545306796007200859"
-   "0614886532333015881171367104445044718144312416815712216611576221546455968770"
-   "801413440778423979"
+   "Id8ukxZdao3hS0NGTKAXdt3c8PpiyigIyBY8lwOHjM2cqkaZgwvr1pA6OowS"
+   "32kJkeOqKB8gNTZZZVqOFkPXgvC4WveUgA5a7rhTj28pDidNROmMO70CCcSw"
+   "aHI3GLFuEMz3JJyvQKGaGwpV3C9gS70dFWTxEfNRzdYEdvIic8/SXI79VgNP"
+   "LGR68nzd4qxCgaLpVBnWsanRp7mfEj52S/7Kxjs14lrbAOMjCuHgN4F6THWh"
+   "PNhG0VXfFFIwAMW2unrfpdo+gQHNclqCf2N1FALpABzvUesgs3wIP+QTMqms"
+   "os/AkuulG7MusbeFl3SoCtaoW12CF038ZbqW+e+DKI1zObhtsLanvaiZm/N4"
+   "BsJirW7avcWNQYm1oYjZ2bR/jYqfoJ0CLXLO/vqHb8J9a5VE9nz7cqMD3/MH"
+   "k/g7BapsOtKuol6ipbUvxQPtf4KCwqQQ40JeqgS6amivI/aLu05S7bAxKOwE"
+   "Yu8YxjN6lXm3co5Wy+BmNSuRlzKhxICyHEqMfKwUtm48XHzHuPaGQzHgkn6H"
+   "3A+FQjQGLHewADYlbfdTF3sHYyc5k9h/9cYVkbmv7bQze53CJGr3T1hZYbN6"
+   "+fuz0SPnfjiKu+bWD+8RYtZpLs2+f32huMz3OqoryGfULxC2aEjL2rdBn+ZR"
+   "PT0+ZAUyLSAVHbsul++cawh"
 },
 #endif
 {   
@@ -180,9 +155,8 @@ int dh_test(void)
 #if 0
         printf("dh_test():testing size %d-bits\n", sets[x].size * 8);
 #endif
-        /* see if g^((p-1)/2) == 1 mod p. */
-        if (mp_read_radix(&g, sets[x].base, 10) != MP_OKAY)           { goto error; }
-        if (mp_read_radix(&p, sets[x].prime, 10) != MP_OKAY)          { goto error; }
+        if (mp_read_radix(&g, sets[x].base, 64) != MP_OKAY)           { goto error; }
+        if (mp_read_radix(&p, sets[x].prime, 64) != MP_OKAY)          { goto error; }
 
         /* ensure p is prime */
         if ((res = is_prime(&p, &primality)) != CRYPT_OK)             { goto done; }
@@ -276,18 +250,21 @@ int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key)
    if (mp_init_multi(&g, &p, &key->x, &key->y, NULL) != MP_OKAY) {
       return CRYPT_MEM;
    }
-   if (mp_read_radix(&g, sets[x].base, 10) != MP_OKAY)             { goto error2; }
-   if (mp_read_radix(&p, sets[x].prime, 10) != MP_OKAY)            { goto error2; }
+   if (mp_read_radix(&g, sets[key->idx].base, 64) != MP_OKAY)      { goto error; }
+   if (mp_read_radix(&p, sets[key->idx].prime, 64) != MP_OKAY)     { goto error; }
 
    /* load the x value */
    mp_read_raw(&key->x, buf, keysize+1);
-   if (mp_exptmod(&g, &key->x, &p, &key->y) != MP_OKAY)            { goto error2; }
+   if (mp_exptmod(&g, &key->x, &p, &key->y) != MP_OKAY)            { goto error; }
    key->type = PK_PRIVATE;
+   
+   if (mp_shrink(&key->x) != MP_OKAY)                              { goto error; }
+   if (mp_shrink(&key->y) != MP_OKAY)                              { goto error; }
 
    /* free up ram */
    res = CRYPT_OK;
    goto done2;
-error2:
+error:
    res = CRYPT_MEM;
    mp_clear_multi(&key->x, &key->y, NULL);
 done2:
@@ -304,10 +281,10 @@ void dh_free(dh_key *key)
 
 #define OUTPUT_BIGNUM(num, buf2, y, z)         \
 {                                              \
-      z = mp_raw_size(num);                    \
+      z = mp_unsigned_bin_size(num);           \
       STORE32L(z, buf2+y);                     \
       y += 4;                                  \
-      mp_toraw(num, buf2+y);                   \
+      mp_to_unsigned_bin(num, buf2+y);         \
       y += z;                                  \
 }
 
@@ -329,11 +306,15 @@ void dh_free(dh_key *key)
      }                                                           \
                                                                  \
      /* load it */                                               \
-     if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\
-        errno =  CRYPT_MEM;                                        \
+     if (mp_read_unsigned_bin(num, (unsigned char *)in+y, x) != MP_OKAY) {\
+        errno =  CRYPT_MEM;                                      \
         goto error;                                              \
      }                                                           \
      y += x;                                                     \
+     if (mp_shrink(num) != MP_OKAY) {                            \
+        errno = CRYPT_MEM;                                       \
+        goto error;                                              \
+     }                                                           \
 }
 
 
@@ -374,14 +355,16 @@ int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key)
    }
 
    /* store header */
-   packet_store_header(buf2, PACKET_SECT_DH, PACKET_SUB_KEY, y);
+   packet_store_header(buf2, PACKET_SECT_DH, PACKET_SUB_KEY);
 
    /* output it */
    *outlen = y;
    memcpy(out, buf2, y);
 
    /* clear mem */
+#ifdef CLEAN_STACK   
    zeromem(buf2, sizeof(buf2));
+#endif   
    return CRYPT_OK;
 }
 
@@ -436,6 +419,12 @@ int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key)
    if (key->type == PK_PRIVATE) {
       INPUT_BIGNUM(&key->x, in, x, y);
    }
+
+   /* eliminate private key if public */
+   if (key->type == PK_PUBLIC) {
+      mp_clear(&key->x);
+   }      
+
    return CRYPT_OK;
 error:
    mp_clear_multi(&key->y, &key->x, NULL);
@@ -469,7 +458,7 @@ int dh_shared_secret(dh_key *private_key, dh_key *public_key,
       return CRYPT_MEM;
    }
 
-   if (mp_read_radix(&p, sets[private_key->idx].prime, 10) != MP_OKAY)     { goto error; }
+   if (mp_read_radix(&p, sets[private_key->idx].prime, 64) != MP_OKAY)     { goto error; }
    if (mp_exptmod(&public_key->y, &private_key->x, &p, &tmp) != MP_OKAY)   { goto error; }
 
    /* enough space for output? */

+ 56 - 14
dh_sys.c

@@ -80,7 +80,7 @@ int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen,
     }
 
     /* store header */
-    packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_ENC_KEY, y);
+    packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_ENC_KEY);
 
 #ifdef CLEAN_STACK
     /* clean up */
@@ -93,8 +93,9 @@ int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen,
     return CRYPT_OK;
 }
 
-int dh_decrypt_key(const unsigned char *in, unsigned char *outkey, 
-                         unsigned long *keylen, dh_key *key)
+int dh_decrypt_key(const unsigned char *in, unsigned long inlen,
+                         unsigned char *outkey, unsigned long *keylen, 
+                         dh_key *key)
 {
    unsigned char shared_secret[1536], skey[MAXBLOCKSIZE];
    unsigned long x, y, z, res, hashsize, keysize;
@@ -111,6 +112,13 @@ int dh_decrypt_key(const unsigned char *in, unsigned char *outkey,
       return CRYPT_PK_NOT_PRIVATE;
    }
 
+   /* check if initial header should fit */
+   if (inlen < PACKET_SIZE+1+4+4) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= PACKET_SIZE+1+4+4;
+   }
+
    /* is header correct? */
    if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_ENC_KEY)) != CRYPT_OK)  {
       return errno;
@@ -128,6 +136,14 @@ int dh_decrypt_key(const unsigned char *in, unsigned char *outkey,
 
    /* get public key */
    LOAD32L(x, in+y);
+   
+   /* now check if the imported key will fit */
+   if (inlen < x) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= x;
+   }
+   
    y += 4;
    if ((errno = dh_import(in+y, x, &pubkey)) != CRYPT_OK) {
       return errno;
@@ -149,6 +165,14 @@ int dh_decrypt_key(const unsigned char *in, unsigned char *outkey,
 
    /* load in the encrypted key */
    LOAD32L(keysize, in+y);
+   
+   /* will the outkey fit as part of the input */
+   if (inlen < keysize) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= keysize;
+   }
+   
    if (keysize > *keylen) {
        res = CRYPT_BUFFER_OVERFLOW;
        goto done;
@@ -223,8 +247,8 @@ int dh_sign_hash(const unsigned char *in,  unsigned long inlen,
    if (mp_read_raw(&k, buf, sets[key->idx].size) != MP_OKAY)                { goto error; }
 
    /* load g, p and p1 */
-   if (mp_read_radix(&g, sets[key->idx].base, 10) != MP_OKAY)               { goto error; }
-   if (mp_read_radix(&p, sets[key->idx].prime, 10) != MP_OKAY)              { goto error; }
+   if (mp_read_radix(&g, sets[key->idx].base, 64) != MP_OKAY)               { goto error; }
+   if (mp_read_radix(&p, sets[key->idx].prime, 64) != MP_OKAY)              { goto error; }
    if (mp_sub_d(&p, 1, &p1) != MP_OKAY)                                     { goto error; }
    if (mp_div_2(&p1, &p1) != MP_OKAY)                                       { goto error; } /* p1 = (p-1)/2 */
 
@@ -256,7 +280,7 @@ int dh_sign_hash(const unsigned char *in,  unsigned long inlen,
    }
 
    /* store header */
-   packet_store_header(buf, PACKET_SECT_DH, PACKET_SUB_SIGNED, y);
+   packet_store_header(buf, PACKET_SECT_DH, PACKET_SUB_SIGNED);
 
    /* store it */
    memcpy(out, buf, y);
@@ -275,9 +299,9 @@ done:
    return res;
 }
 
-int dh_verify_hash(const unsigned char *sig, const unsigned char *hash, 
-                         unsigned long inlen, int *stat, 
-                         dh_key *key)
+int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
+                   const unsigned char *hash, unsigned long hashlen, 
+                         int *stat, dh_key *key)
 {
    mp_int a, b, p, g, m, tmp;
    unsigned char md[MAXBLOCKSIZE];
@@ -292,17 +316,24 @@ int dh_verify_hash(const unsigned char *sig, const unsigned char *hash,
    /* default to invalid */
    *stat = 0;
 
+   /* check initial input length */
+   if (siglen < PACKET_SIZE+4+4) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      siglen -= PACKET_SIZE + 4 + 4;
+   }
+
    /* header ok? */
    if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_DH, PACKET_SUB_SIGNED)) != CRYPT_OK) {
       return errno;
    }
-
+   
    /* get hash out of packet */
    y = PACKET_SIZE;
 
    /* hash the message */
    md[0] = 0;
-   memcpy(md+1, hash, MIN(sizeof(md) - 1, inlen));
+   memcpy(md+1, hash, MIN(sizeof(md) - 1, hashlen));
 
    /* init all bignums */
    if (mp_init_multi(&a, &p, &b, &g, &m, &tmp, NULL) != MP_OKAY) { 
@@ -311,21 +342,32 @@ int dh_verify_hash(const unsigned char *sig, const unsigned char *hash,
 
    /* load a and b */
    LOAD32L(x, sig+y);
+   if (siglen < x) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      siglen -= x;
+   }
+   
    y += 4;
    if (mp_read_raw(&a, (unsigned char *)sig+y, x) != MP_OKAY)            { goto error; }
    y += x;
 
    LOAD32L(x, sig+y);
+   if (siglen < x) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      siglen -= x;
+   }
    y += 4;
    if (mp_read_raw(&b, (unsigned char *)sig+y, x) != MP_OKAY)            { goto error; }
    y += x;
 
    /* load p and g */
-   if (mp_read_radix(&p, sets[key->idx].prime, 10) != MP_OKAY)           { goto error; }
-   if (mp_read_radix(&g, sets[key->idx].base, 10) != MP_OKAY)            { goto error; }
+   if (mp_read_radix(&p, sets[key->idx].prime, 64) != MP_OKAY)           { goto error; }
+   if (mp_read_radix(&g, sets[key->idx].base, 64) != MP_OKAY)            { goto error; }
 
    /* load m */
-   if (mp_read_raw(&m, md, 1+MIN(sizeof(md)-1, inlen)) != MP_OKAY)       { goto error; }
+   if (mp_read_raw(&m, md, 1+MIN(sizeof(md)-1, hashlen)) != MP_OKAY)     { goto error; }
 
    /* find g^m mod p */
    if (mp_exptmod(&g, &m, &p, &m) != MP_OKAY)                            { goto error; } /* m = g^m mod p */

+ 398 - 0
dsa.c

@@ -0,0 +1,398 @@
+/* Implementation of the Digital Signature Algorithm (DSA) by Tom St Denis */
+#ifdef MDSA
+
+#include <mycrypt.h>
+
+static const struct {
+    int   size, osize;
+    char *order,
+         *prime,
+         *base;
+} sets[] = {
+#ifdef DSA1024
+{
+    1024, 160, 
+
+    "PE6GbKzFwpeAAMtC3PUsqsRQMWl",
+
+    "PyhJv87GTec3fBvC8BQT4yQ8gSYB8rk6DfLRfeirnZsQaQBVwh8PZ7V1hKfD"
+	"SGGUgr1cAb3YrnZw97HvyaKmypY2dM19OxeNWNI4f6IyYwj/mcAiJpkjxMmZ"
+    "mYVrTbGxBG8OaKBD9vFd9/Jif8djJ18GnaRsdRoCBDec+W++x6D",
+    
+    "3uYLnHhrVRR6hATv30lj/XX5AecEE2tJVgtWcHkbwKuR3WEqqvP8xBUG70Ve"
+	"p6kUchz/E/kZaGIJ0mrqme6bNDIxoNqtshyDfska/Zfm/QHuDZWljVGbPx68"
+    "eSBw1vzkRKFCmR8QgpT+R887JufEgQRRIQOuLK8c1ND61efJH2t"
+},
+#endif
+#ifdef DSA2048
+{
+    2048, 256,
+    
+    "TZLgPgD7D46uoATLyNSgKsgh6LglcVDwlPFvT6dcOdN",
+    
+    "EUlAFvO8lXjhXn/6BobNq4bo0st12+zwgpshNJgoUap/LFCQcGeVGt/s/ocD"
+	"M+4v+bU3dNKjFJEYzb+sxmy5dbzQsa15+Ud4v1UJ/7D4p0IyA+h9aeU9i/C9"
+	"tJQC824mQhmL5cxx7SbQPMD/2+P04hLyeDOir1L1vmvE1tWZg43Jbza2LTQJ"
+	"52wi/Sguai3vFZVMObEPBfbXzg9b8pH1i75Q1os9w0LtfJ4pYQJD3Xn66jYF"
+	"mpLVqK4yuMXOOq07bkM5Nx+jQvFpGuRiD5e4a2FB1NjXbCGMtRxu6eurPAIY"
+    "F5dw3QWXkZm74SFmLTi0GW+3pipDWiBSUu9pUpp6rr",
+    
+    "79PG50FKgZgffOnFiUuuZLhWicqFZ6EwvWXQi7uBmvMQUoXNEBschAhRtLQE"
+	"ev5iHrR2g41rEEundwwFTbRdyq2txBS2bClkFjGlojPwayWvXLAaDltfkhws"
+	"TjS/gNKch4qD1nPu+Kd1RmjWp1B1JzBXnlcj/z5qMaF8oL4bk9qGGEmaeOLs"
+	"90vW0Z/7QWBC8h+65SohFBmydUWwXhs4rAa7NwHbPltnXdF6kZHpQOtT5h+4"
+	"hYA83eYzdeOl5rYrFDiyJ+nfOptgLiLIHB9L0wkOhFrb52+S7qKpgYe1+oof"
+    "K1/Rd4D8fL5qvGyXWz1dB8W2iqAXeXKlkWZrvHQdMM"
+},
+#endif
+#ifdef DSA4096
+{
+    4096, 512,
+    
+    "4GO4hUY+2MqiwNBYFx/JqRejRKXXJfcaY7mIBYksn2Dwn6JQZp9Qpg3bbnOJ"
+    "kt5ZqH2dtEjbV9B/AXF51jOkW/",
+    
+    "Jddrq1iN+f03IKVqcDSOz7IquBVxzb34Cwzmc7rHpIOW3DqW7IjMz47ETtWu"
+	"KvG3JxFdYaiv69lAE+X38DEqQSTE8Ba9jfNYs9PYeH4RfsT5op/u3r41anRW"
+	"jJTHMhnvwwQ0eQrZ+9d7LQePnQSUs3eXb8ZdNsh8/h30b3gIMk+08bZoJejF"
+	"6Y2vMtMQUHmmoM/+IlrMz7TZ4tu0jkYWBp1y74WLGemXkYvU6pqH8dTQX1MM"
+	"oG93eBKQ87jHbtBJ+L6EbcqO/jVa6lwUivEbBs9UtKf4lC0pe3SZqfFhrJde"
+	"2b5LfbPBLk2pNdC5MJCsIVz7TUL28SWYwx7Nx7ybxtKd76L8kgbLfoOYiJRx"
+	"WIFGRE40Q9/0zuqzz6D1WHKQE4wg5oy6WQeO3Q5BN1UC6O4EUSkD7mC3KmWA"
+	"MgxNDZYMA+BSCTirVL2eS90WCA4LkTsHhoLgafwZT5xanUKGY/cZix29sy21"
+	"J1Ut4cbPFjxg76OVu9obONitMLg+63dz3Ho8LMhXaKN43yl5Kc4PxeUCQWVU"
+	"gHXg8RSldQMOvhwohHFibiMUrRkkCs2//Ts6hVdS3cEFgfYhpnzeEiGBCuat"
+	"ZZYpaWKZlmrlcUYH7Rg9SyHH1h4DLrki5ySIjGxozT6JhIrMme8uQcN9YOiq"
+    "GwRhjR3AM1QiOUfolENTYCn",
+    
+    "3VIJLic34uyamh2TbNHEjECeH289m938S2wvHYe/3xPNiCjVhBxl6RAgom+Q"
+	"3X7+r8EII4QQKXXdqR3Ad/nXzJkgMUJVvt5d5lIwwKM7+ffbLmhJWldO0Jkc"
+	"7oZQr7t81khBUG4wgPVZO8OwjB66v9npPCcBLNLO6DAWE82CM8YfPJzQt0tr"
+	"JSHwcgixvkFft25SdI0V9zg2H6sj2Q/yAYUEAPzyDfQVvLzqEN2tmIhturnR"
+	"wUW4WLy8PSls/tt5eWjdI++ofdGHNJmKaZjHgym52GhNQmWZYWzK/hcllWtC"
+	"U8vCw7GY3nE4uF74YuTYC6LGx7wXS5ivj531KTPe4EarZ4j+aVw9ZJhfy/h+"
+	"K0esj9ALQP9jSz3OMDKeYaJKjj/scC5NrPdSjeJf7EvlVf41ufZHNGrFVmVW"
+	"kqaEuNZr+SmC6/2buPEmL4UO94H1z4QItK+rHqNWEQP6ptST0lcFwHO4uESR"
+	"qp8scA2/Fh+G0TfJ/rg8wImqbWsgrUwGnmDmKtFLRiX4aMPIsyFIsJvPQECT"
+	"EIR6yd6QIRVGZbCRiVsCqMrHsn0KZWSeKdtW9TRt/yNu+VKcgRZFfU991Nab"
+	"OBxkAS1kw9kyj/HZYxPG4NrqL0j5bnb1VjqQZKEEQMSBAyMMfDuMyWhrmsxV"
+    "ffmF/sYGxFHCbacGeu06C3U"
+},
+#endif
+{
+    0, 0,
+    NULL,
+    NULL,
+    NULL
+}
+};
+
+int dsa_test(void)
+{
+   mp_int q, p, g, t;
+   int errno, i, res, primality;
+   
+   /* init memory */
+   if (mp_init_multi(&q, &p, &g, &t, NULL) != MP_OKAY) {
+      return CRYPT_MEM;
+   }
+   
+   res = CRYPT_MEM;
+   for (i = 0; i < sets[i].size; i++) {
+   #if 0
+       printf("Testing size: %d\n", sets[i].size);
+   #endif
+       /* read in order, prime, generator */
+       if (mp_read_radix(&q, sets[i].order, 64) != MP_OKAY)       { goto error; }
+       if (mp_read_radix(&p, sets[i].prime, 64) != MP_OKAY)       { goto error; }
+       if (mp_read_radix(&g, sets[i].base, 64) != MP_OKAY)        { goto error; }
+       
+       /* now see if the order and modulus are prime */
+       if ((errno = is_prime(&q, &primality)) != CRYPT_OK) {
+          res = errno;
+          goto error;
+       }
+       if (primality == 0) {
+          res = CRYPT_FAIL_TESTVECTOR;
+          goto error;
+       }
+       
+       if ((errno = is_prime(&p, &primality)) != CRYPT_OK) {
+          res = errno;
+          goto error;
+       }
+       if (primality == 0) {
+          res = CRYPT_FAIL_TESTVECTOR;
+          goto error;
+       }
+       
+       /* now see what g^q mod p is (should be 1) */
+       if (mp_exptmod(&g, &q, &p, &t) != MP_OKAY)                { goto error; }
+       if (mp_cmp_d(&t, 1)) {
+          res = CRYPT_FAIL_TESTVECTOR;
+          goto error;
+       }
+   }
+   res = CRYPT_OK;
+error:
+   mp_clear_multi(&t, &g, &p, &q, NULL);
+   return res;
+}
+
+int dsa_make_key(prng_state *prng, int wprng, int keysize, dsa_key *key)
+{
+   mp_int g, p, q;
+   unsigned char buf[64];
+   int errno, idx, x;
+   
+   _ARGCHK(prng != NULL);
+   _ARGCHK(key != NULL);
+   
+   /* good prng? */
+   if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
+      return errno;
+   }
+
+   /* find key size */
+   for (x = 0; (keysize > sets[x].size) && (sets[x].size); x++);
+   if (sets[x].size == 0) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+   key->idx = x;
+   keysize = sets[x].osize;
+
+   /* read prng */
+   if (prng_descriptor[wprng].read(buf, keysize, prng) != (unsigned long)keysize) {
+      return CRYPT_ERROR_READPRNG;
+   }
+   
+   /* init parameters */
+   if (mp_init_multi(&g, &p, &q, &key->x, &key->y, NULL) != MP_OKAY) {
+      return CRYPT_MEM;
+   }
+   if (mp_read_radix(&q, sets[x].order, 64) != MP_OKAY)            { goto error; }
+   if (mp_read_radix(&g, sets[x].base, 64) != MP_OKAY)             { goto error; }
+   if (mp_read_radix(&p, sets[x].prime, 64) != MP_OKAY)            { goto error; }
+   
+   /* load exponent */
+   if (mp_read_unsigned_bin(&key->x, buf, keysize) != MP_OKAY)     { goto error; }
+   if (mp_mod(&key->x, &q, &key->x) != MP_OKAY)                    { goto error; }
+   
+   /* calc public key */
+   if (mp_exptmod(&g, &key->x, &p, &key->y) != MP_OKAY)            { goto error; }
+   key->type = PK_PRIVATE;
+   
+   /* shrink values */
+   if (mp_shrink(&key->x) != MP_OKAY)                              { goto error; }
+   if (mp_shrink(&key->y) != MP_OKAY)                              { goto error; }
+   
+   /* free temps */
+   mp_clear_multi(&g, &q, &p, NULL);
+#ifdef CLEAN_STACK
+   zeromem(buf, sizeof(buf));
+#endif
+
+   return CRYPT_OK;
+error:
+   mp_clear_multi(&g, &q, &p, &key->x, &key->y, NULL);
+   return CRYPT_MEM;
+}
+
+void dsa_free(dsa_key *key)
+{
+   _ARGCHK(key != NULL);
+   mp_clear_multi(&key->x, &key->y, NULL);
+}
+
+static int is_valid_idx(int n)
+{
+   int x;
+
+   for (x = 0; sets[x].size; x++);
+   if ((n < 0) || (n >= x)) {
+      return 0;
+   }
+   return 1;
+}
+
+int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key)
+{
+   unsigned char buf[4096];
+   unsigned long x, y;
+   
+   _ARGCHK(out != NULL);
+   _ARGCHK(outlen != NULL);
+   _ARGCHK(key != NULL);
+   
+   if (is_valid_idx(key->idx) == 0) {
+      return CRYPT_PK_INVALID_TYPE;
+   }
+   
+   if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
+      return CRYPT_PK_NOT_PRIVATE;
+   }
+   
+   y = PACKET_SIZE;
+   
+   buf[y++] = type;
+   buf[y++] = sets[key->idx].osize/8;
+   
+   x = mp_unsigned_bin_size(&key->y);
+   STORE32L(x, &buf[y]);
+   y += 4;
+   mp_to_unsigned_bin(&key->y, &buf[y]);
+   y += x;
+   
+   if (type == PK_PRIVATE) {
+      x = mp_unsigned_bin_size(&key->x);
+      STORE32L(x, &buf[y]);
+      y += 4;
+      mp_to_unsigned_bin(&key->x, &buf[y]);
+      y += x;
+   }
+      
+   /* check for overflow */
+   if (*outlen < y) {
+      #ifdef CLEAN_STACK
+         zeromem(buf, sizeof(buf));
+      #endif
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+
+   /* store header */
+   packet_store_header(buf, PACKET_SECT_DSA, PACKET_SUB_KEY);
+
+   /* output it */
+   *outlen = y;
+   memcpy(out, buf, y);
+
+   /* clear mem */
+#ifdef CLEAN_STACK   
+   zeromem(buf, sizeof(buf));
+#endif   
+   return CRYPT_OK;
+}
+
+#define INPUT_BIGNUM(num, in, x, y)                              \
+{                                                                \
+     /* load value */                                            \
+     if (y + 4 > inlen) {                                        \
+        errno = CRYPT_INVALID_PACKET;                            \
+        goto error;                                              \
+     }                                                           \
+     LOAD32L(x, in+y);                                           \
+     y += 4;                                                     \
+                                                                 \
+     /* sanity check... */                                       \
+     if (x+y > inlen) {                                          \
+        errno = CRYPT_INVALID_PACKET;                            \
+        goto error;                                              \
+     }                                                           \
+                                                                 \
+     /* load it */                                               \
+     if (mp_read_unsigned_bin(num, (unsigned char *)in+y, x) != MP_OKAY) {\
+        errno =  CRYPT_MEM;                                      \
+        goto error;                                              \
+     }                                                           \
+     y += x;                                                     \
+     if (mp_shrink(num) != MP_OKAY) {                            \
+        errno = CRYPT_MEM;                                       \
+        goto error;                                              \
+     }                                                           \
+}
+
+int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
+{
+   unsigned long x, y, s;
+   int errno;
+
+   _ARGCHK(in != NULL);
+   _ARGCHK(key != NULL);
+
+   /* check type byte */
+   if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_DSA, PACKET_SUB_KEY)) != CRYPT_OK) {
+      return errno;
+   }
+   
+   if (2+PACKET_SIZE > inlen) {
+      return CRYPT_INVALID_PACKET;
+   }
+
+
+   /* init */
+   if (mp_init_multi(&key->x, &key->y, NULL) != MP_OKAY) { 
+      return CRYPT_MEM;
+   }
+
+   y = PACKET_SIZE;
+   key->type = in[y++];
+   s  = (long)in[y++] * 8;
+   
+   for (x = 0; (s > (unsigned long)sets[x].osize) && (sets[x].osize); x++);
+   if (sets[x].osize == 0) {
+      errno = CRYPT_INVALID_KEYSIZE;
+      goto error;
+   }
+   key->idx = x;
+
+   /* type check both values */
+   if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE))  {
+      errno = CRYPT_PK_TYPE_MISMATCH;
+      goto error;
+   }
+
+   /* is the key idx valid? */
+   if (!is_valid_idx(key->idx)) {
+      errno = CRYPT_PK_TYPE_MISMATCH;
+      goto error;
+   }
+
+   /* load public value g^x mod p*/
+   INPUT_BIGNUM(&key->y, in, x, y);
+
+   if (key->type == PK_PRIVATE) {
+      INPUT_BIGNUM(&key->x, in, x, y);
+   }
+
+   /* eliminate private key if public */
+   if (key->type == PK_PUBLIC) {
+      mp_clear(&key->x);
+   }      
+
+   return CRYPT_OK;
+error:
+   mp_clear_multi(&key->y, &key->x, NULL);
+   return errno;
+}
+   
+   
+
+int dsa_sign_hash(const unsigned char *in,  unsigned long inlen,
+                        unsigned char *out, unsigned long *outlen,
+                        prng_state *prng, int wprng, dsa_key *key)
+{
+    mp_int g, q, p, k, tmp;
+    unsigned char buf[4096];
+    int x, y, errno;
+    
+    _ARGCHK(in != NULL);
+    _ARGCHK(out != NULL);
+    _ARGCHK(outlen != NULL);
+    _ARGCHK(prng != NULL);
+    _ARGCHK(key != NULL);
+    
+    if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
+       return errno;
+    }
+    
+    if (is_valid_idx(key->idx) == 0) {
+       return CRYPT_PK_INVALID_TYPE;
+    }
+
+return 0;
+}
+
+
+
+#endif /* MDSA */
+

+ 155 - 92
ecc.c

@@ -18,15 +18,15 @@ static const struct {
    20,
    "ECC-160",
    /* prime */
-   "1461501637330902918203684832716283019655932542983",
+   "G00000000000000000000000007",
    /* B */
-   "1C9E7C2E5891CBE097BD46",
+   "1oUV2vOaSlWbxr6",
    /* order */
-   "1461501637330902918203686297565868358251373258181",
+   "G0000000000004sCQUtDxaqDUN5",
    /* Gx */
-   "2DCF462904B478D868A7FF3F2BF1FCD9",
+   "jpqOf1BHus6Yd/pyhyVpP",
    /* Gy */
-   "DFFAF2EE3848FA75FB967CEC7B9A399E085ACED8",
+   "D/wykuuIFfr+vPyx7kQEPu8MixO",
 },
 #endif
 #ifdef ECC192
@@ -34,19 +34,19 @@ static const struct {
     24,
    "ECC-192",
    /* prime */
-   "6277101735386680763835789423207666416083908700390324961279",
+   "/////////////////////l//////////",
 
    /* B */
-   "64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
+   "P2456UMSWESFf+chSYGmIVwutkp1Hhcn",
 
    /* order */
-   "6277101735386680763835789423176059013767194773182842284081",
+   "////////////////cTxuDXHhoR6qqYWn",
 
    /* Gx */
-   "188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
+   "68se3h0maFPylo3hGw680FJ/2ls2/n0I",
 
    /* Gy */
-   "07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
+   "1nahbV/8sdXZ417jQoJDrNFvTw4UUKWH"
 },
 #endif
 #ifdef ECC224
@@ -55,19 +55,19 @@ static const struct {
    "ECC-224",
 
    /* prime */
-   "26959946667150639794667015087019630673637144422540572481103610249951",
+   "400000000000000000000000000000000000BV",
 
    /* B */
-   "2051BA041508CED34B3",
+   "21HkWGL2CxJIp",
 
    /* order */
-   "26959946667150639794667015087019637467111563745054605861463538557247",
+   "4000000000000000000Kxnixk9t8MLzMiV264/",
 
    /* Gx */
-   "2DCF462904B478D868A7FF3F2BF1FCD9",
+   "jpqOf1BHus6Yd/pyhyVpP",
  
    /* Gy */
-   "CF337F320BC44A15C3EDB8C4258BB958E57A0CAFA73EB46E9C4BA9AE",
+   "3FCtyo2yHA5SFjkCGbYxbOvNeChwS+j6wSIwck",
 },
 #endif
 #ifdef ECC256
@@ -75,19 +75,19 @@ static const struct {
    32,
    "ECC-256",
    /* Prime */
-   "115792089210356248762697446949407573530086143415290314195533631308867097853951",
+   "F////y000010000000000000000////////////////",
 
    /* B */
-   "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
+   "5h6DTYgEfFdi+kzLNQOXhnb7GQmp5EmzZlEF3udqc1B",
 
    /* Order */
-   "115792089210356248762697446949407573529996955224135760342422259061068512044369",
+   "F////y00000//////////+yvlgjfnUUXFEvoiByOoLH",
 
    /* Gx */
-   "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
+   "6iNqVBXB497+BpcvMEaGF9t0ts1BUipeFIXEKNOcCAM",
 
    /* Gy */
-   "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
+   "4/ZGkB+6d+RZkVhIdmFdXOhpZDNQp5UpiksG6Wtlr7r"
 }, 
 #endif
 #ifdef ECC384
@@ -95,22 +95,23 @@ static const struct {
    48,
    "ECC-384",
    /* prime */
-   "394020061963944792122790401001436138050797392704654466679482934042457217714968"
-   "70329047266088258938001861606973112319",
-
+   "//////////////////////////////////////////x/////00000000003/"
+   "////",
+   
    /* B */
-   "b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed1"
-   "9d2a85c8edd3ec2aef",
-
+   "ip4lf+8+v+IOZWLhu/Wj6HWTd6x+WK4I0nG8Zr0JXrh6LZcDYYxHdIg5oEtJ"
+   "x2hl",
+   
    /* Order */
-   "394020061963944792122790401001436138050797392704654466679469052796276593991132"
-   "63569398956308152294913554433653942643",
+   "////////////////////////////////nsDDWVGtBTzO6WsoIB2dUkpi6MhC"
+   "nIbp",
 
    /* Gx and Gy */
-   "aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf5529"
-   "6c3a545e3872760ab7",
-   "3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e81"
-   "9d7a431d7c90ea0e5f"
+   "geVA8hwB1JUEiSSUyo2jT6uTEsABfvkOMVT1u89KAZXL0l9TlrKfR3fKNZXo"
+   "TWgt",
+   
+   "DXVUIfOcB6zTdfY/afBSAVZq7RqecXHywTen4xNmkC0AOB7E7Nw1dNf37NoG"
+   "wWvV"
 },
 #endif
 #ifdef ECC521
@@ -118,22 +119,23 @@ static const struct {
    65,
    "ECC-521",
    /* prime */ 
-   "686479766013060971498190079908139321726943530014330540939446345918554318339765"
-   "6052122559640661454554977296311391480858037121987999716643812574028291115057151",
+   "V///////////////////////////////////////////////////////////"
+   "///////////////////////////",
  
    /* B */
-   "051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7"
-   "e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
+   "56LFhbXZXoQ7vAQ8Q2sXK3kejfoMvcp5VEuj8cHZl49uLOPEL7iVfDx5bB0l"
+   "JknlmSrSz+8FImqyUz57zHhK3y0",
  
    /* Order */ 
-   "686479766013060971498190079908139321726943530014330540939446345918554318339765"
-   "5394245057746333217197532963996371363321113864768612440380340372808892707005449",
+   "V//////////////////////////////////////////+b66XuE/BvPhVym1I"
+   "FS9fT0xjScuYPn7hhjljnwHE6G9",
 
    /* Gx and Gy */
-   "c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe7"
-   "5928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
-   "11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef"
-   "42640c550b9013fad0761353c7086a272c24088be94769fd16650",
+   "CQ5ZWQt10JfpPu+osOZbRH2d6I1EGK/jI7uAAzWQqqzkg5BNdVlvrae/Xt19"
+   "wB/gDupIBF1XMf2c/b+VZ72vRrc",
+   
+   "HWvAMfucZl015oANxGiVHlPcFL4ILURH6WNhxqN9pvcB9VkSfbUz2P0nL2v0"
+   "J+j1s4rF726edB2G8Y+b7QVqMPG",
 },
 #endif
 {
@@ -251,7 +253,7 @@ static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus)
    /* s = (3Xp^2 + a) / (2Yp) */
    if (mp_mul_2(&P->y, &tmp) != MP_OKAY)                   { goto error; } /* tmp = 2*y */
    if (mp_invmod(&tmp, modulus, &tmp) != MP_OKAY)          { goto error; } /* tmp = 1/tmp mod modulus */
-   if (mp_sqr(&P->x,  &s) != MP_OKAY)                      { goto error; } /* s = x^2  */
+   if (mp_sqr(&P->x, &s) != MP_OKAY)                       { goto error; } /* s = x^2  */
    if (mp_mul_d(&s,(mp_digit)3, &s) != MP_OKAY)            { goto error; } /* s = 3*(x^2) */
    if (mp_sub_d(&s,(mp_digit)3, &s) != MP_OKAY)            { goto error; } /* s = 3*(x^2) - 3 */
    if (mp_mulmod(&s, &tmp, modulus, &s) != MP_OKAY)        { goto error; } /* s = tmp * s mod modulus */
@@ -329,59 +331,103 @@ done:
 /* perform R = kG where k == integer and G == ecc_point */
 static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus, int idx)
 {
-   ecc_point *tG;
-   int i, j, z, first, res;
+   ecc_point *tG, *M[14];
+   int i, j, m, z, first, res;
    mp_digit d;
    unsigned char bits[768];
    
+   /* init M tab */
+   for (i = 0; i < 14; i++) {
+       M[i] = new_point();
+       if (M[i] == NULL) {
+          for (j = 0; j < i; j++) {
+              del_point(M[j]);
+          }
+          return CRYPT_MEM;
+       }
+   }
+   
    /* get bits of k */
+   first = m = 0;
    for (z = i = 0; z < (int)USED(k); z++) {
        d = DIGIT(k, z);
-       
-#define DO1 bits[i++] = d&1; d >>= 1;
-#define DO2 DO1 DO1
-#define DO4 DO2 DO2
-
-       DO4; DO4; DO4; DO4
-
-#undef DO4
-#undef DO2
-#undef DO1
+       for (j = 0; j < (int)MP_DIGIT_BIT; j++) {
+           first |= (d&1)<<(m++);
+           if (m == 4) {
+              bits[i++] = first;
+              first = m = 0;
+           }
+           d >>= 1;
+       }
+   }
+   
+   /* residue of multiplicand [if any] */
+   if (m) {
+      bits[i++] = first;
    }
 
    /* make a copy of G incase R==G */
    tG = new_point();
-   if (tG == NULL) { 
-      return CRYPT_MEM;
-   }
+   if (tG == NULL)                                          { goto error; }
 
+   /* skip leading digits which are zero */   
+   --i; while (i && bits[i] == 0) { --i; }
+   
+   if (i == 0) {
+      res = CRYPT_INVALID_ARG;
+      goto done;
+   }
+   
+   /* now calc the M tab, note that there are only 14 spots, the normal M[0] is a no-op, and M[1] is the input
+      point (saves ram)
+   */
+   
+   /* M[0] now is 2*G */
+   if (dbl_point(G, M[0], modulus) != CRYPT_OK)             { goto error; }
+   for (j = 1; j < 14; j++) {
+       if (add_point(M[j-1], G, M[j], modulus) != CRYPT_OK) { goto error; }
+   }
+  
    /* tG = G */
-   if (mp_copy(&G->x, &tG->x) != MP_OKAY)     { goto error; }
-   if (mp_copy(&G->y, &tG->y) != MP_OKAY)     { goto error; }
-
-   /* set result to G, R = G */
-   if (mp_copy(&G->x, &R->x) != MP_OKAY)      { goto error; }
-   if (mp_copy(&G->y, &R->y) != MP_OKAY)      { goto error; }
-   first = 0;
-
-   /* now do dbl+add through all the bits */
-   for (j = i-1; j >= 0; j--) {
-       if (first) {
-           if (dbl_point(R, R, modulus) != CRYPT_OK)       { goto error; }
+   if (mp_copy(&G->x, &tG->x) != MP_OKAY)                   { goto error; }
+   if (mp_copy(&G->y, &tG->y) != MP_OKAY)                   { goto error; }
+
+   /* set result M[bits[i]] */
+   if (bits[i] == 1) {
+     if (mp_copy(&G->x, &R->x) != MP_OKAY)                  { goto error; }
+     if (mp_copy(&G->y, &R->y) != MP_OKAY)                  { goto error; }
+   } else if (bits[i]>=2) {
+     if (mp_copy(&M[bits[i]-2]->x, &R->x) != MP_OKAY)       { goto error; }
+     if (mp_copy(&M[bits[i]-2]->y, &R->y) != MP_OKAY)       { goto error; }
+   }
+   
+   while (--i >= 0) {
+       /* double */
+       for (j = 0; j < 4; j++) {
+          if (dbl_point(R, R, modulus) != CRYPT_OK)               { goto error; }
        }
-       if (bits[j] == 1) {
-          if (first) {
-             if (add_point(R, tG, R, modulus) != CRYPT_OK) { goto error; }
-          }
-          first = 1;
+       
+       /* now based on the value of bits[i] we do ops */
+       if (bits[i] == 0) {
+          /* nop */
+       } else if (bits[i] == 1) {
+          /* add base point */
+          if (add_point(R, tG, R, modulus) != CRYPT_OK)           { goto error; }
+       } else {
+          /* other case */
+          if (add_point(R, M[bits[i]-2], R, modulus) != CRYPT_OK) { goto error; }
        }
    }
+   
    res = CRYPT_OK; 
    goto done;
 error:
    res = CRYPT_MEM;
 done:
    del_point(tG);
+   for (i = 0; i < 14; i++) {
+       del_point(M[i]);
+   }
 #ifdef CLEAN_STACK
    zeromem(bits, sizeof(bits)); 
 #endif
@@ -412,8 +458,11 @@ int ecc_test(void)
    }
 
    for (i = 0; sets[i].size; i++) {
-       if (mp_read_radix(&modulus, (unsigned char *)sets[i].prime, 10) != MP_OKAY)   { goto error; }
-       if (mp_read_radix(&order, (unsigned char *)sets[i].order, 10) != MP_OKAY)     { goto error; }
+       #if 0
+          printf("Testing %d\n", sets[i].size);
+       #endif
+       if (mp_read_radix(&modulus, (unsigned char *)sets[i].prime, 64) != MP_OKAY)   { goto error; }
+       if (mp_read_radix(&order, (unsigned char *)sets[i].order, 64) != MP_OKAY)     { goto error; }
 
        /* is prime actually prime? */
        if (is_prime(&modulus, &primality) != CRYPT_OK)           { goto error; }
@@ -429,8 +478,8 @@ int ecc_test(void)
           goto done1;
        }
 
-       if (mp_read_radix(&G->x, (unsigned char *)sets[i].Gx, 16) != MP_OKAY) { goto error; }
-       if (mp_read_radix(&G->y, (unsigned char *)sets[i].Gy, 16) != MP_OKAY) { goto error; }
+       if (mp_read_radix(&G->x, (unsigned char *)sets[i].Gx, 64) != MP_OKAY) { goto error; }
+       if (mp_read_radix(&G->y, (unsigned char *)sets[i].Gy, 64) != MP_OKAY) { goto error; }
 
        /* then we should have G == (order + 1)G */
        if (mp_add_d(&order, 1, &order) != MP_OKAY)                  { goto error; }
@@ -509,14 +558,19 @@ int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
    }
 
    /* read in the specs for this key */
-   if (mp_read_radix(&prime, (unsigned char *)sets[x].prime, 10) != MP_OKAY)  { goto error; }
-   if (mp_read_radix(&base->x, (unsigned char *)sets[x].Gx, 16) != MP_OKAY)   { goto error; }
-   if (mp_read_radix(&base->y, (unsigned char *)sets[x].Gy, 16) != MP_OKAY)   { goto error; }
+   if (mp_read_radix(&prime, (unsigned char *)sets[key->idx].prime, 64) != MP_OKAY)  { goto error; }
+   if (mp_read_radix(&base->x, (unsigned char *)sets[key->idx].Gx, 64) != MP_OKAY)   { goto error; }
+   if (mp_read_radix(&base->y, (unsigned char *)sets[key->idx].Gy, 64) != MP_OKAY)   { goto error; }
    if (mp_read_raw(&key->k, (unsigned char *)buf, keysize+1) != MP_OKAY)      { goto error; }
 
    /* make the public key */
    if (ecc_mulmod(&key->k, base, &key->pubkey, &prime, x) != CRYPT_OK) { goto error; }
    key->type = PK_PRIVATE;
+   
+   /* shrink key */
+   if (mp_shrink(&key->k) != MP_OKAY)          { goto error; }
+   if (mp_shrink(&key->pubkey.x) != MP_OKAY)   { goto error; }
+   if (mp_shrink(&key->pubkey.y) != MP_OKAY)   { goto error; }
 
    /* free up ram */
    res = CRYPT_OK;
@@ -551,12 +605,12 @@ static int compress_y_point(ecc_point *pt, int idx, int *result)
    }
 
    /* get x^3 - 3x + b */
-   if (mp_read_radix(&p, (unsigned char *)sets[idx].B, 16) != MP_OKAY) { goto error; } /* p = B */
+   if (mp_read_radix(&p, (unsigned char *)sets[idx].B, 64) != MP_OKAY) { goto error; } /* p = B */
    if (mp_expt_d(&pt->x, 3, &tmp) != MP_OKAY)              { goto error; } /* tmp = pX^3  */
    if (mp_mul_d(&pt->x, 3, &tmp2) != MP_OKAY)              { goto error; } /* tmp2 = 3*pX^3 */
    if (mp_sub(&tmp, &tmp2, &tmp) != MP_OKAY)               { goto error; } /* tmp = tmp - tmp2 */
    if (mp_add(&tmp, &p, &tmp) != MP_OKAY)                  { goto error; } /* tmp = tmp + p */
-   if (mp_read_radix(&p, (unsigned char *)sets[idx].prime, 10) != MP_OKAY)  { goto error; } /* p = prime */
+   if (mp_read_radix(&p, (unsigned char *)sets[idx].prime, 64) != MP_OKAY)  { goto error; } /* p = prime */
    if (mp_mod(&tmp, &p, &tmp) != MP_OKAY)                  { goto error; } /* tmp = tmp mod p */
 
    /* now find square root */
@@ -593,12 +647,12 @@ static int expand_y_point(ecc_point *pt, int idx, int result)
    }
 
    /* get x^3 - 3x + b */
-   if (mp_read_radix(&p, (unsigned char *)sets[idx].B, 16) != MP_OKAY) { goto error; } /* p = B */
+   if (mp_read_radix(&p, (unsigned char *)sets[idx].B, 64) != MP_OKAY) { goto error; } /* p = B */
    if (mp_expt_d(&pt->x, 3, &tmp) != MP_OKAY)              { goto error; } /* tmp = pX^3 */
    if (mp_mul_d(&pt->x, 3, &tmp2) != MP_OKAY)              { goto error; } /* tmp2 = 3*pX^3 */
    if (mp_sub(&tmp, &tmp2, &tmp) != MP_OKAY)               { goto error; } /* tmp = tmp - tmp2 */
    if (mp_add(&tmp, &p, &tmp) != MP_OKAY)                  { goto error; } /* tmp = tmp + p */
-   if (mp_read_radix(&p, (unsigned char *)sets[idx].prime, 10) != MP_OKAY)  { goto error; } /* p = prime */
+   if (mp_read_radix(&p, (unsigned char *)sets[idx].prime, 64) != MP_OKAY)  { goto error; } /* p = prime */
    if (mp_mod(&tmp, &p, &tmp) != MP_OKAY)                  { goto error; } /* tmp = tmp mod p */
 
    /* now find square root */
@@ -625,10 +679,10 @@ done:
 
 #define OUTPUT_BIGNUM(num, buf2, y, z)         \
 {                                              \
-      z = mp_raw_size(num);                    \
+      z = mp_unsigned_bin_size(num);           \
       STORE32L(z, buf2+y);                     \
       y += 4;                                  \
-      mp_toraw(num, buf2+y);                   \
+      mp_to_unsigned_bin(num, buf2+y);         \
       y += z;                                  \
 }
 
@@ -650,11 +704,15 @@ done:
      }                                                           \
                                                                  \
      /* load it */                                               \
-     if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\
+     if (mp_read_unsigned_bin(num, (unsigned char *)in+y, x) != MP_OKAY) {\
         errno = CRYPT_MEM;                                       \
         goto error;                                              \
      }                                                           \
      y += x;                                                     \
+     if (mp_shrink(num) != MP_OKAY) {                            \
+        errno = CRYPT_MEM;                                       \
+        goto error;                                              \
+     }                                                           \
 }
 
 int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
@@ -696,7 +754,7 @@ int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key
    }
 
    /* store header */
-   packet_store_header(buf2, PACKET_SECT_ECC, PACKET_SUB_KEY, y);
+   packet_store_header(buf2, PACKET_SECT_ECC, PACKET_SUB_KEY);
 
    memcpy(out, buf2, y);
    *outlen = y;
@@ -765,10 +823,15 @@ int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key)
       /* load private key */
       INPUT_BIGNUM(&key->k, in, x, y);
    }
+   
+   /* eliminate private key if public */
+   if (key->type == PK_PUBLIC) {
+      mp_clear(&key->k);
+   }      
+   
    return CRYPT_OK;
 error:
    mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL);
-done:
    return errno;
 }
 
@@ -805,7 +868,7 @@ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
       return CRYPT_MEM;
    }
 
-   if (mp_read_radix(&prime, (unsigned char *)sets[private_key->idx].prime, 10) != MP_OKAY) { goto error; }
+   if (mp_read_radix(&prime, (unsigned char *)sets[private_key->idx].prime, 64) != MP_OKAY) { goto error; }
    if ((errno = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime, private_key->idx)) != CRYPT_OK) { res = errno; goto done1; }
 
    x = mp_raw_size(&result->x);

+ 45 - 11
ecc_sys.c

@@ -84,7 +84,7 @@ int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
     }
 
     /* store header */
-    packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY, y);
+    packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY);
 
 #ifdef CLEAN_STACK
     /* clean up */
@@ -96,8 +96,9 @@ int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
     return CRYPT_OK;
 }
 
-int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey, 
-                          unsigned long *keylen, ecc_key *key)
+int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
+                          unsigned char *outkey, unsigned long *keylen, 
+                          ecc_key *key)
 {
    unsigned char shared_secret[256], skey[MAXBLOCKSIZE];
    unsigned long x, y, z, res, hashsize, keysize;
@@ -113,6 +114,13 @@ int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey,
    if (key->type != PK_PRIVATE) {
       return CRYPT_PK_NOT_PRIVATE;
    }
+   
+   /* correct length ? */
+   if (inlen < PACKET_SIZE+1+4+4) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= PACKET_SIZE+1+4+4;
+   }
 
    /* is header correct? */
    if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
@@ -131,6 +139,11 @@ int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey,
 
    /* get public key */
    LOAD32L(x, in+y);
+   if (inlen < x) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= x;
+   }
    y += 4;
    if ((errno = ecc_import(in+y, x, &pubkey)) != CRYPT_OK) {
       return errno;
@@ -151,6 +164,11 @@ int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey,
    }
 
    LOAD32L(keysize, in+y);
+   if (inlen < keysize) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= keysize;
+   }
    y += 4;
 
    if (*keylen < keysize) {
@@ -223,7 +241,7 @@ int ecc_sign_hash(const unsigned char *in,  unsigned long inlen,
       ecc_free(&pubkey);
       return CRYPT_MEM;
    }
-   if (mp_read_radix(&p, (unsigned char *)sets[key->idx].order, 10) != MP_OKAY)            { goto error; }
+   if (mp_read_radix(&p, (unsigned char *)sets[key->idx].order, 64) != MP_OKAY)            { goto error; }
    if (mp_read_raw(&b, md, 1+MIN(sizeof(md)-1,inlen)) != MP_OKAY)                          { goto error; }
 
    /* find b = (m - x)/k */
@@ -266,7 +284,7 @@ int ecc_sign_hash(const unsigned char *in,  unsigned long inlen,
    }
 
    /* store header */
-   packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_SIGNED, y);
+   packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_SIGNED);
 
    /* clear memory */
    *outlen = y;
@@ -286,9 +304,9 @@ done1:
 }
 
 /* verify that mG = (bA + Y) */
-int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash, 
-                     unsigned long inlen, int *stat, 
-                     ecc_key *key)
+int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
+                    const unsigned char *hash, unsigned long inlen, 
+                    int *stat, ecc_key *key)
 {
    ecc_point *mG;
    ecc_key   pubkey;
@@ -305,6 +323,12 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash,
    /* default to invalid signature */
    *stat = 0;
 
+   if (siglen < PACKET_SIZE+4+4) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      siglen -= PACKET_SIZE+4+4;
+   }
+
    /* is the message format correct? */
    if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_ECC, PACKET_SUB_SIGNED)) != CRYPT_OK) {
       return errno;
@@ -315,6 +339,11 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash,
 
    /* get size of public key */
    LOAD32L(x, sig+y);
+   if (siglen < x) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      siglen -= x;
+   }
    y += 4;
 
    /* load the public key */
@@ -325,6 +354,11 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash,
 
    /* load size of 'b' */
    LOAD32L(x, sig+y);
+   if (siglen < x) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      siglen -= x;
+   }
    y += 4;
 
    /* init values */
@@ -350,7 +384,7 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash,
    if (mp_read_raw(&m, md, 1+MIN(sizeof(md)-1,inlen)) != MP_OKAY)                  { goto error; }
    
    /* load prime */
-   if (mp_read_radix(&p, (unsigned char *)sets[key->idx].prime, 10) != MP_OKAY)    { goto error; }
+   if (mp_read_radix(&p, (unsigned char *)sets[key->idx].prime, 64) != MP_OKAY)    { goto error; }
 
    /* get bA */
    if (ecc_mulmod(&b, &pubkey.pubkey, &pubkey.pubkey, &p, key->idx) != CRYPT_OK)   { goto error; }
@@ -359,8 +393,8 @@ int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash,
    if (add_point(&pubkey.pubkey, &key->pubkey, &pubkey.pubkey, &p) != CRYPT_OK)    { goto error; }
 
    /* get mG */
-   if (mp_read_radix(&mG->x, (unsigned char *)sets[key->idx].Gx, 16) != MP_OKAY)   { goto error; }
-   if (mp_read_radix(&mG->y, (unsigned char *)sets[key->idx].Gy, 16) != MP_OKAY)   { goto error; }
+   if (mp_read_radix(&mG->x, (unsigned char *)sets[key->idx].Gx, 64) != MP_OKAY)   { goto error; }
+   if (mp_read_radix(&mG->y, (unsigned char *)sets[key->idx].Gy, 64) != MP_OKAY)   { goto error; }
    if (ecc_mulmod(&m, mG, mG, &p, key->idx) != CRYPT_OK)                           { goto error; }
 
    /* compare mG to bA + Y */

+ 18 - 0
examples/ch1-01.c

@@ -0,0 +1,18 @@
+/* 
+ * Name      : ch1-01.c
+ * Purpose   : Demonstration of a basic libtomcrypt program
+ * Author    : Tom St Denis
+ *
+ * History   : v0.79 Initial release
+ */
+ 
+/* ch1-01-1  */
+/* Include the default headers and libtomcrypt headers */
+#include <mycrypt.h>
+
+int main(void)
+{
+   return 0;
+}
+/* ch1-01-1  */
+

+ 25 - 0
examples/ch1-02.c

@@ -0,0 +1,25 @@
+/* 
+ * Name      : ch1-02.c
+ * Purpose   : Demonstration of error handling
+ * Author    : Tom St Denis
+ *
+ * History   : v0.79 Initial release
+ */
+ 
+/* ch1-01-1 */
+#include <mycrypt.h>
+
+int main(void)
+{
+   int errno;
+   
+   if ((errno = some_func(...)) != CRYPT_OK) {
+      printf("Error: %s\n", error_to_string(errno));
+      return EXIT_FAILURE;
+   }
+   
+   return 0;
+}
+/*ch1-01-1 */
+
+

+ 29 - 0
examples/ch1-03.c

@@ -0,0 +1,29 @@
+/* 
+ * Name      : ch1-03.c
+ * Purpose   : Demonstration of variable length outputs
+ * Author    : Tom St Denis
+ *
+ * History   : v0.79 Initial release
+ */
+ 
+ /* ch1-01-1 */
+ #include <mycrypt.h>
+ 
+ int main(void)
+ {
+    unsigned long length;
+    unsigned char buffer[512];
+    int errno;
+    
+    length = sizeof(buffer);
+    if ((errno = some_func(..., buffer, &length)) != CRYPT_OK) {
+       printf("Error: %s\n", error_to_string(errno));
+       return EXIT_FAILURE;
+    }
+    printf("Size of output is %lu bytes\n", length);
+    return 0;
+}
+/* ch1-01-1 */
+
+
+    

+ 23 - 18
keyring.c

@@ -70,6 +70,7 @@ static const unsigned long crc_table[256] = {
 
 static unsigned long crc32 (unsigned long crc, const unsigned char *buf, unsigned long len)
 {
+  //_ARGCHK(buf != NULL  && len == 0);
   crc = crc ^ 0xffffffffL;
   while (len >= 8) {
       DO8 (buf);
@@ -587,25 +588,26 @@ int kr_encrypt_key(pk_key *pk, unsigned long ID,
    STORE32L(kr->ID,buf+4);
 
    /* now encrypt it */
-   len = sizeof(buf)-8;
+   len = sizeof(buf)-12;
    switch (kr->system) {
         case RSA_KEY:
-            if ((errno = rsa_encrypt_key(in, inlen, buf+8, &len, prng, wprng, &(kr->key.rsa))) != CRYPT_OK) {
+            if ((errno = rsa_encrypt_key(in, inlen, buf+12, &len, prng, wprng, &(kr->key.rsa))) != CRYPT_OK) {
                return errno;
             }
             break;
         case DH_KEY:
-            if ((errno = dh_encrypt_key(in, inlen, buf+8, &len, prng, wprng, hash, &(kr->key.dh))) != CRYPT_OK) {
+            if ((errno = dh_encrypt_key(in, inlen, buf+12, &len, prng, wprng, hash, &(kr->key.dh))) != CRYPT_OK) {
                return errno;
             }
             break;
         case ECC_KEY:
-            if ((errno = ecc_encrypt_key(in, inlen, buf+8, &len, prng, wprng, hash, &(kr->key.ecc))) != CRYPT_OK) {
+            if ((errno = ecc_encrypt_key(in, inlen, buf+12, &len, prng, wprng, hash, &(kr->key.ecc))) != CRYPT_OK) {
                return errno;
             }
             break;
     }
-    len += 8;
+    STORE32L(len,buf+8);
+    len += 12;
 
     if (len > *outlen) {
        #ifdef CLEAN_STACK
@@ -626,7 +628,7 @@ int kr_decrypt_key(pk_key *pk, const unsigned char *in,
                    unsigned char *out, unsigned long *outlen)
 {
    unsigned char buf[8192];
-   unsigned long len, ID;
+   unsigned long pklen, len, ID;
    pk_key *kr;
    int errno;
 
@@ -653,20 +655,21 @@ int kr_decrypt_key(pk_key *pk, const unsigned char *in,
    }
 
    /* now try and decrypt it */
+   LOAD32L(pklen,in+8);
    len = sizeof(buf);
    switch (kr->system) {
        case RSA_KEY:
-           if ((errno = rsa_decrypt_key(in+8, buf, &len, &(kr->key.rsa))) != CRYPT_OK) {
+           if ((errno = rsa_decrypt_key(in+12, pklen, buf, &len, &(kr->key.rsa))) != CRYPT_OK) {
               return errno;
            }
            break;
        case DH_KEY:
-           if ((errno = dh_decrypt_key(in+8, buf, &len, &(kr->key.dh))) != CRYPT_OK) {
+           if ((errno = dh_decrypt_key(in+12, pklen, buf, &len, &(kr->key.dh))) != CRYPT_OK) {
               return errno;
            }
            break;
        case ECC_KEY:
-           if ((errno = ecc_decrypt_key(in+8, buf, &len, &(kr->key.ecc))) != CRYPT_OK) {
+           if ((errno = ecc_decrypt_key(in+12, pklen, buf, &len, &(kr->key.ecc))) != CRYPT_OK) {
               return errno;
            }
            break;
@@ -720,26 +723,27 @@ int kr_sign_hash(pk_key *pk, unsigned long ID,
    STORE32L(kr->ID,buf+4);
 
    /* now sign it */
-   len = sizeof(buf)-12;
+   len = sizeof(buf)-16;
    switch (kr->system) {
         case RSA_KEY:
-            if ((errno = rsa_sign_hash(in, inlen, buf+12, &len, &(kr->key.rsa))) != CRYPT_OK) {
+            if ((errno = rsa_sign_hash(in, inlen, buf+16, &len, &(kr->key.rsa))) != CRYPT_OK) {
                return errno;
             }
             break;
         case DH_KEY:
-            if ((errno = dh_sign_hash(in, inlen, buf+12, &len, prng, wprng, &(kr->key.dh))) != CRYPT_OK) {
+            if ((errno = dh_sign_hash(in, inlen, buf+16, &len, prng, wprng, &(kr->key.dh))) != CRYPT_OK) {
                return errno;
             }
             break;
         case ECC_KEY:
-            if ((errno = ecc_sign_hash(in, inlen, buf+12, &len, prng, wprng, &(kr->key.ecc))) != CRYPT_OK) {
+            if ((errno = ecc_sign_hash(in, inlen, buf+16, &len, prng, wprng, &(kr->key.ecc))) != CRYPT_OK) {
                return errno;
             }
             break;
     }
     STORE32L(inlen,buf+8);
-    len += 12;
+    STORE32L(len,buf+12);
+    len += 16;
 
     if (len > *outlen) {
        #ifdef CLEAN_STACK
@@ -759,7 +763,7 @@ int kr_sign_hash(pk_key *pk, unsigned long ID,
 int kr_verify_hash(pk_key *pk, const unsigned char *in, const unsigned char *hash, 
                    unsigned long hashlen, int *stat)
 {
-   unsigned long inlen, ID;
+   unsigned long inlen, pklen, ID;
    pk_key *kr;
    int errno;
 
@@ -785,23 +789,24 @@ int kr_verify_hash(pk_key *pk, const unsigned char *in, const unsigned char *has
 
    /* now try and verify it */
    LOAD32L(inlen,in+8);         /* this is the length of the original inlen */
+   LOAD32L(pklen,in+12);        /* size of the PK packet */
    if (inlen != hashlen) {      /* size doesn't match means the signature is invalid */
       return CRYPT_OK;
    }
 
    switch (kr->system) {
        case RSA_KEY:
-           if ((errno = rsa_verify_hash(in+12, hash, stat, &(kr->key.rsa))) != CRYPT_OK) {
+           if ((errno = rsa_verify_hash(in+16, pklen, hash, stat, &(kr->key.rsa))) != CRYPT_OK) {
               return errno;
            }
            break;
        case DH_KEY:
-           if ((errno = dh_verify_hash(in+12, hash, inlen, stat, &(kr->key.dh))) != CRYPT_OK) {
+           if ((errno = dh_verify_hash(in+16, pklen, hash, inlen, stat, &(kr->key.dh))) != CRYPT_OK) {
               return errno;
            }
            break;
        case ECC_KEY:
-           if ((errno = ecc_verify_hash(in+12, hash, inlen, stat, &(kr->key.ecc))) != CRYPT_OK) {
+           if ((errno = ecc_verify_hash(in+16, pklen, hash, inlen, stat, &(kr->key.ecc))) != CRYPT_OK) {
               return errno;
            }
            break;

+ 110 - 38
makefile

@@ -9,62 +9,77 @@
 # a build. This is easy to remedy though, for those that have problems.
 
 # The version
-VERSION=0.78
+VERSION=0.79
 
-#Compiler and Linker Names
+#ch1-01-1
+# Compiler and Linker Names
 CC=gcc
 LD=ld
 
-#Archiver [makes .a files]
+# Archiver [makes .a files]
 AR=ar
-ARFLAGS=rs
+ARFLAGS=r
+#ch1-01-1
 
-#here you can set the malloc/calloc/free functions you want
+#ch1-01-2
+# here you can set the malloc/calloc/free functions you want
 XMALLOC=malloc
 XCALLOC=calloc
+XREALLOC=realloc
 XFREE=free
 
-#you can redefine the clock
+# you can redefine the clock
 XCLOCK=clock
 XCLOCKS_PER_SEC=CLOCKS_PER_SEC
+#ch1-01-2
 
-#Compilation flags. Note the += does not write over the user's CFLAGS!
+#ch1-01-3
+# Compilation flags. Note the += does not write over the user's CFLAGS!
 CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wno-unused -Werror  \
-   -DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) -DXCLOCK=$(XCLOCK) \
+   -DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) \
+   -DXREALLOC=$(XREALLOC) -DXCLOCK=$(XCLOCK) \
    -DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC)
 
-#optimize for SPEED (comment out SIZE/DEBUG line as well)
+# optimize for SPEED
 #CFLAGS += -O3 -funroll-loops
 
-#optimize for SIZE (comment out SPEED/DEBUG line as well)
+# optimize for SIZE 
 CFLAGS += -Os 
 
-#Use small code variants of functions when possible?  (Slows it down!)
-CFLAGS += -DSMALL_CODE
-
-#compile for DEBUGGING 
+# compile for DEBUGGING 
 #CFLAGS += -g3
+#ch1-01-3
 
 #These flags control how the library gets built.
 
-#no file support, when defined the library will not have any functions that can read/write files 
-#(comment out to have file support)
+#ch1-01-4
+# Use small code variants of functions when possible?  
+CFLAGS += -DSMALL_CODE
+
+# no file support, when defined the library will not 
+# have any functions that can read/write files 
+# (comment out to have file support)
 #CFLAGS += -DNO_FILE
 
-#Support the UNIX /dev/random or /dev/urandom
+# Support the UNIX /dev/random or /dev/urandom
 CFLAGS += -DDEVRANDOM
 
-# Use /dev/urandom first on devices where /dev/random is too slow */
+# Use /dev/urandom first on devices where 
+# /dev/random is too slow 
 #CFLAGS += -DTRY_URANDOM_FIRST
 
-# Clean the stack after sensitive functions.  Not always required... 
-# With this defined most of the ciphers and hashes will clean their stack area
-# after usage with a (sometimes) huge penalty in speed.  Normally this is not
-# required if you simply lock your stack and wipe it when your program is done.
+# Clean the stack after sensitive functions.  Not 
+# always required... With this defined most of 
+# the ciphers and hashes will clean their stack area
+# after usage with a (sometimes) huge penalty in speed.
+# Normally this is not required if you simply lock your 
+# stack and wipe it when your program is done.
 #
 #CFLAGS += -DCLEAN_STACK
+#ch1-01-4
 
-# What algorithms to include? comment out and rebuild to remove em
+#ch1-01-5
+# What algorithms to include? comment out and rebuild to remove them
 CFLAGS += -DBLOWFISH
 CFLAGS += -DRC2
 CFLAGS += -DRC5
@@ -78,6 +93,7 @@ CFLAGS += -DTWOFISH
 CFLAGS += -DDES
 CFLAGS += -DCAST5
 CFLAGS += -DNOEKEON
+#ch1-01-5
 
 #You can also customize the Twofish code.  All four combinations 
 #of the flags are possible but only three of them make sense.
@@ -90,17 +106,23 @@ CFLAGS += -DNOEKEON
 #_TABLES defined: Very fast, not faster than if both were undefined.  Code is ~1KB bigger
 #                 faster keysetup though...
 
-# Small Ram Variant of Twofish.  For this you must have TWOFISH defined.  This
-# variant requires about 4kb less memory but is considerably slower.  It is ideal
-# when high throughput is less important than conserving memory. By default it is
-# not defined which means the larger ram (about 4.2Kb used) variant is built.
+#ch1-01-6
+# Small Ram Variant of Twofish.  For this you must have TWOFISH 
+# defined.  This variant requires about 4kb less memory but 
+# is considerably slower.  It is ideal when high throughput is 
+# less important than conserving memory. By default it is not 
+# defined which means the larger ram (about 4.2Kb used) variant 
+# is built.
 #CFLAGS += -DTWOFISH_SMALL
 
-# Tell Twofish to use precomputed tables.  If you want to use the small table
-# variant of Twofish you may want to turn this on.  Essentially it tells Twofish to use
-# precomputed S-boxes (Q0 and Q1) as well as precomputed GF multiplications [in the MDS].
-# This speeds up the cipher somewhat.
+# Tell Twofish to use precomputed tables.  If you want to use 
+# the small table variant of Twofish you may want to turn 
+# this on.  Essentially it tells Twofish to use precomputed 
+# S-boxes (Q0 and Q1) as well as precomputed GF 
+# multiplications [in the MDS].  This speeds up the cipher 
+# somewhat.
 #CFLAGS += -DTWOFISH_TABLES 
+#ch1-01-6
 
 #Use fast PK routines.  Basically this limits the size of the private key in the
 #DH system to 256 bits.  The group order remains unchanged so the best
@@ -110,13 +132,16 @@ CFLAGS += -DNOEKEON
 #security so its by default not turned on.  USE AT YOUR RISK!
 #CFLAGS += -DFAST_PK
 
+#ch1-01-7
 # Chaining modes
 CFLAGS += -DCFB
 CFLAGS += -DOFB
 CFLAGS += -DECB
 CFLAGS += -DCBC
 CFLAGS += -DCTR
+#ch1-01-7
 
+#ch1-01-8
 #One-way hashes
 CFLAGS += -DSHA512
 CFLAGS += -DSHA384
@@ -126,29 +151,73 @@ CFLAGS += -DSHA1
 CFLAGS += -DMD5
 CFLAGS += -DMD4
 CFLAGS += -DMD2
+#ch1-01-8
 
-# base64 
-CFLAGS += -DBASE64
-
+#ch1-01-9
 # prngs 
 CFLAGS += -DYARROW
 CFLAGS += -DSPRNG
 CFLAGS += -DRC4
+#ch1-01-9
 
+#ch1-01-10
 # PK code 
 CFLAGS += -DMRSA
 CFLAGS += -DMDH
 CFLAGS += -DMECC
+#CFLAGS += -DMDSA
 CFLAGS += -DKR
+#ch1-01-10
+
+#ch1-01-12
+# Control which built in DH or ECC key paramaters
+# are to be allowed
+CFLAGS += -DDH768
+CFLAGS += -DDH1024
+CFLAGS += -DDH1280
+CFLAGS += -DDH1536
+CFLAGS += -DDH1792
+CFLAGS += -DDH2048
+CFLAGS += -DDH2560
+CFLAGS += -DDH3072
+CFLAGS += -DDH4096
+
+CFLAGS += -DECC160
+CFLAGS += -DECC192
+CFLAGS += -DECC224
+CFLAGS += -DECC256
+CFLAGS += -DECC384
+CFLAGS += -DECC521
+
+CFLAGS += -DDSA1024
+CFLAGS += -DDSA2048
+CFLAGS += -DDSA4096
+#ch1-01-12
+
+#ch1-01-11
+# base64 
+CFLAGS += -DBASE64
 
-# include GF math routines?  (not currently used by anything internally)
+# include GF math routines?
+# (not currently used by anything internally)
 #CFLAGS += -DGF
 
 # include large integer math routines? (required by the PK code)
 CFLAGS += -DMPI
 
+# use the fast exptmod operation (used in dsa/rsa/dh and is_prime)
+# This uses slightly more heap than the old code [only during the function call]
+# this is also fairly faster than the previous code
+CFLAGS += -DMPI_FASTEXPT
+
+# use a "low" mem variant of the fast exptmod.  It is still always 
+# faster then the old exptmod but its savings drops off after 
+# 1024 to 2048-bits 
+#CFLAGS += -DMPI_FASTEXPT_LOWMEM
+
 # include HMAC support
 CFLAGS += -DHMAC
+#ch1-01-11
 
 #Output filenames for various targets.
 LIBNAME=libtomcrypt.a
@@ -163,7 +232,7 @@ LIBPATH=/usr/lib
 INCPATH=/usr/include
 
 #List of objects to compile.
-OBJECTS=keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o \
+OBJECTS=keyring.o gf.o mem.o sprng.o dsa.o ecc.o base64.o dh.o rsa.o \
 bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o \
 md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o \
 safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o \
@@ -199,6 +268,7 @@ sha512.o: sha512.c sha384.c
 #This rule makes the libtomcrypt library.
 library: $(OBJECTS) 
 	$(AR) $(ARFLAGS) $(LIBNAME) $(OBJECTS)
+	ranlib $(LIBNAME)
 
 #This rule makes the test program included with libtomcrypt
 test: library $(TESTOBJECTS)
@@ -219,9 +289,11 @@ small: library $(SMALLOBJECTS)
 #This rule installs the library and the header files. This must be run
 #as root in order to have a high enough permission to write to the correct
 #directories and to set the owner and group to root.
-install: library
+install: library docs
 	install -g root -o root $(LIBNAME) $(LIBPATH)
 	install -g root -o root $(HEADERS) $(INCPATH)
+	mkdir -p /usr/doc/libtomcrypt/pdf
+	cp crypt.pdf /usr/doc/libtomcrypt/pdf/
 
 #This rule cleans the source tree of all compiled code, not including the pdf
 #documentation.
@@ -241,7 +313,7 @@ docs: crypt.tex
 	makeindex crypt > /dev/null
 	pdflatex crypt > /dev/null
 	rm -f $(LEFTOVERS)
-
+       
 #zipup the project (take that!)
 zipup: clean docs
 	chdir .. ; rm -rf crypt* libtomcrypt-$(VERSION) ; mkdir libtomcrypt-$(VERSION) ; \

+ 23 - 0
makefile.out

@@ -0,0 +1,23 @@
+#makefile generated with config.pl
+#
+#Tom St Denis ([email protected], http://tom.iahu.ca) 
+
+CC = gcc 
+AR = ar 
+LD = ld 
+CFLAGS += -Os -Wall -Wsign-compare -W -Wno-unused -Werror -I./  -DXMALLOC=malloc -DXCALLOC=calloc -DXFREE=free -DXCLOCK=clock -DXCLOCKS_PER_SEC=CLOCKS_PER_SEC -DSMALL_CODE -DBLOWFISH -DRC2 -DRC5 -DRC6 -DSERPENT -DSAFERP -DSAFER -DRIJNDAEL -DXTEA -DTWOFISH -DDES -DCAST5 -DNOEKEON -DCFB -DOFB -DECB -DCBC -DCTR -DSHA512 -DSHA384 -DSHA256 -DTIGER -DSHA1 -DMD5 -DMD4 -DMD2 -DHMAC -DBASE64 -DYARROW -DSPRNG -DRC4 -DDEVRANDOM -DMRSA -DMDH -DMECC -DMDSA -DKR -DDH768 -DDH1024 -DDH1280 -DDH1536 -DDH1792 -DDH2048 -DDH2560 -DDH3072 -DDH4096 -DECC160 -DECC192 -DECC224 -DECC256 -DECC384 -DECC521 -DDSA1024 -DDSA2048 -DDSA4096 -DMPI -DMPI_FASTEXPT 
+
+default: library
+
+OBJECTS = keyring.o gf.o mem.o sprng.o dsa.o ecc.o base64.o dh.o rsa.o bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o ampi.o mpi.o prime.o twofish.o packet.o hmac.o strings.o
+
+rsa.o: rsa_sys.c
+dh.o: dh_sys.c
+ecc.o: ecc_sys.c
+
+library: $(OBJECTS)
+	 $(AR) rs libtomcrypt.a $(OBJECTS)
+
+clean:
+	rm -f $(OBJECTS) libtomcrypt.a 
+

+ 38 - 10
makefile.ps2

@@ -32,6 +32,7 @@ ARFLAGS=rs
 #here you can set the malloc/calloc/free functions you want
 XMALLOC=malloc
 XCALLOC=calloc
+XREALLOC=realloc
 XFREE=free
 
 #you can redefine the clock
@@ -40,7 +41,8 @@ XCLOCKS_PER_SEC=576000
 
 #Compilation flags. Note the += does not write over the user's CFLAGS!
 CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wno-unused -Werror  \
-   -DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) -DXCLOCK=$(XCLOCK) \
+   -DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) \
+   -DXREALLOC=$(XREALLOC) -DXCLOCK=$(XCLOCK) \
    -DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC)
 
 #optimize for SPEED (comment out SIZE line as well)
@@ -103,14 +105,6 @@ CFLAGS += -DNOEKEON
 # This speeds up the cipher somewhat.
 # CFLAGS += -DTWOFISH_TABLES 
 
-#Small code variant of the SAFER+ cipher, uses same RAM but less code space
-#With this defined the cipher is slower.  On my x86 with GCC 3.2 it required 50KB less space
-CFLAGS += -DSAFERP_SMALL
-
-#Small Rijndael [saves 13KB on an x86]
-#With this defined the cipher is slower (by 50Mbit/sec on an Athon XP)
-CFLAGS += -DRIJNDAEL_SMALL
-
 #Use fast PK routines.  Basically this limits the size of the private key in the
 #DH system to 256 bits.  The group order remains unchanged so the best
 #attacks are still GNFS (for DH upto 2560-bits)
@@ -148,14 +142,48 @@ CFLAGS += -DRC4
 CFLAGS += -DMRSA
 CFLAGS += -DMDH
 CFLAGS += -DMECC
+#CFLAGS += -DDSA
 CFLAGS += -DKR
 
+# Control which built in DH or ECC key paramaters
+# are to be allowed
+CFLAGS += -DDH768
+CFLAGS += -DDH1024
+CFLAGS += -DDH1280
+CFLAGS += -DDH1536
+CFLAGS += -DDH1792
+CFLAGS += -DDH2048
+CFLAGS += -DDH2560
+CFLAGS += -DDH3072
+CFLAGS += -DDH4096
+
+CFLAGS += -DECC160
+CFLAGS += -DECC192
+CFLAGS += -DECC224
+CFLAGS += -DECC256
+CFLAGS += -DECC384
+CFLAGS += -DECC521
+
+CFLAGS += -DDSA1024
+CFLAGS += -DDSA2048
+CFLAGS += -DDSA4096
+
 # include GF math routines?  (not currently used by anything internally)
 #CFLAGS += -DGF
 
 # include large integer math routines? (required by the PK code)
 CFLAGS += -DMPI
 
+# use the fast exptmod operation (used in dsa/rsa/dh and is_prime)
+# This uses slightly more heap than the old code [only during the function call]
+# this is also fairly faster than the previous code
+CFLAGS += -DMPI_FASTEXPT
+
+# use a "low" mem variant of the fast exptmod.  It is still always 
+# faster then the old exptmod but its savings drops off after 
+# 1024-bits 
+CFLAGS += -DMPI_FASTEXPT_LOWMEM
+
 # include HMAC support
 CFLAGS += -DHMAC
 
@@ -175,7 +203,7 @@ LIBPATH=/usr/lib
 INCPATH=/usr/include
 
 #List of objects to compile.
-OBJECTS=keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o \
+OBJECTS=keyring.o gf.o mem.o sprng.o dsa.o ecc.o base64.o dh.o rsa.o \
 bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o \
 md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o \
 safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o \

+ 41 - 3
makefile.vc

@@ -8,13 +8,14 @@ AR=lib
 #here you can set the malloc/calloc/free functions you want
 XMALLOC=malloc
 XCALLOC=calloc
+XREALLOC=realloc
 XFREE=free
 
 #you can redefine the clock
 XCLOCK=clock
 XCLOCKS_PER_SEC=CLOCKS_PER_SEC
 
-CFLAGS = /c /Ogisy1 /Gs /I. /W3 /DWIN32 /DXMALLOC=$(XMALLOC) /DXCALLOC=$(XCALLOC) /DXFREE=$(XFREE) /DXCLOCK=$(XCLOCK) /DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC)
+CFLAGS = /c /Ogisy1 /Gs /I. /W3 /DWIN32 /DXREALLOC=$(XREALLOC) /DXMALLOC=$(XMALLOC) /DXCALLOC=$(XCALLOC) /DXFREE=$(XFREE) /DXCLOCK=$(XCLOCK) /DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC)
 
 #Small code (smaller variants of some block ciphers)
 CFLAGS += /DSMALL_CODE
@@ -113,14 +114,49 @@ CFLAGS += /DRC4
 CFLAGS += /DMRSA
 CFLAGS += /DMDH
 CFLAGS += /DMECC
+#CFLAGS += /DDSA
 CFLAGS += /DKR
 
+# Control which built in DH or ECC key paramaters
+# are to be allowed
+CFLAGS += /DDH768
+CFLAGS += /DDH1024
+CFLAGS += /DDH1280
+CFLAGS += /DDH1536
+CFLAGS += /DDH1792
+CFLAGS += /DDH2048
+CFLAGS += /DDH2560
+CFLAGS += /DDH3072
+CFLAGS += /DDH4096
+
+CFLAGS += /DECC160
+CFLAGS += /DECC192
+CFLAGS += /DECC224
+CFLAGS += /DECC256
+CFLAGS += /DECC384
+CFLAGS += /DECC521
+
+CFLAGS += /DDSA1024
+CFLAGS += /DDSA2048
+CFLAGS += /DDSA4096
+
 # include GF math routines?  (not currently used by anything internally)
 #CFLAGS += /DGF
 
 # include large integer math routines? (required by the PK code)
 CFLAGS += /DMPI
 
+# use the fast exptmod operation (used in dsa/rsa/dh and is_prime)
+# This uses slightly more heap than the old code [only during the function call]
+# this is also fairly faster than the previous code
+CFLAGS += /DMPI_FASTEXPT
+
+# use a "low" mem variant of the fast exptmod.  It is still always 
+# faster then the old exptmod but its savings drops off after 
+# 1024-bits 
+#CFLAGS += /DMPI_FASTEXPT_LOWMEM
+
+
 # include HMAC support
 CFLAGS += /DHMAC
 
@@ -216,6 +252,8 @@ cast5.obj: cast5.c
 	$(CC) $(CFLAGS) cast5.c
 noekeon.obj: noekeon.c
 	$(CC) $(CFLAGS) noekeon.c
+dsa.obj: dsa.c
+	$(CC) $(CFLAGS) dsa.c
 
 demos/test.obj: demos/test.c
 	$(CC) $(CFLAGS) demos/test.c
@@ -223,11 +261,11 @@ demos/test.obj: demos/test.c
 demos/hashsum.obj: demos/hashsum.c
 	$(CC) $(CFLAGS) demos/hashsum.c
 
-tomcrypt.lib: keyring.obj gf.obj mem.obj sprng.obj ecc.obj  base64.obj dh.obj rsa.obj bits.obj hmac.obj  \
+tomcrypt.lib: keyring.obj gf.obj mem.obj sprng.obj dsa.obj ecc.obj  base64.obj dh.obj rsa.obj bits.obj hmac.obj  \
 yarrow.obj cfb.obj ofb.obj ecb.obj ctr.obj cbc.obj hash.obj tiger.obj sha1.obj md2.obj md5.obj md4.obj sha256.obj sha512.obj xtea.obj \
 aes.obj serpent.obj safer_tab.obj safer.obj safer+.obj cast5.obj noekeon.obj rc2.obj rc6.obj rc5.obj des.obj blowfish.obj crypt.obj ampi.obj \
 strings.obj mpi.obj prime.obj twofish.obj packet.obj
-	$(AR) /out:tomcrypt.lib keyring.obj gf.obj mem.obj sprng.obj ecc.obj  base64.obj dh.obj rsa.obj hmac.obj \
+	$(AR) /out:tomcrypt.lib keyring.obj gf.obj mem.obj sprng.obj dsa.obj ecc.obj  base64.obj dh.obj rsa.obj hmac.obj \
 bits.obj yarrow.obj cfb.obj ofb.obj ecb.obj ctr.obj cbc.obj hash.obj tiger.obj sha1.obj md2.obj md5.obj md4.obj sha256.obj \
 strings.obj sha512.obj xtea.obj aes.obj serpent.obj safer_tab.obj safer.obj safer+.obj cast5.obj noekeon.obj rc2.obj rc6.obj rc5.obj des.obj \
 blowfish.obj crypt.obj ampi.obj mpi.obj prime.obj twofish.obj packet.obj

+ 211 - 2
mpi.c

@@ -1635,8 +1635,159 @@ mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c)
 
 /* }}} */
 
+/* shrinks the memory required to store a mp_int if possible */
+mp_err mp_shrink(mp_int *a)
+{
+   if (a->used != a->alloc) {
+      if ((a->dp = XREALLOC(a->dp, a->used * sizeof(mp_digit))) == NULL) {
+         return MP_MEM;
+      } else {
+         a->alloc = a->used;
+         return MP_OKAY;
+      }
+   } else {
+      return MP_OKAY;
+   }
+}      
+
 /* {{{ mp_exptmod(a, b, m, c) */
 
+#ifdef MPI_FASTEXPT
+
+/* computes y == g^x mod p */
+mp_err mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y)
+{
+   mp_int *M, tx, mu, res;
+   int QQQ, QQ, Q, x, *vals, err;
+
+   /* determine the value of Q */
+   x = (USED(X) - 1) * DIGIT_BIT;
+   Q = DIGIT(X, USED(X)-1);
+   while (Q) { 
+      ++x;
+      Q >>= 1;
+   }
+        if (x <= 8)    { Q = 2; }
+   else if (x <= 64)   { Q = 3; }
+   else if (x <= 256)  { Q = 4; }
+   else if (x <= 950)  { Q = 5; }
+   else if (x <= 2755) { Q = 6; }
+   else                { Q = 7; }
+   
+#ifdef MPI_FASTEXPT_LOWMEM
+   if (Q > 5) {
+      Q = 5;
+   }
+#endif
+
+   /* alloc room for table */
+   vals = XCALLOC(sizeof(int), USED(X)*((DIGIT_BIT/Q)+((DIGIT_BIT%Q)?1:0)));
+   if (vals == NULL) { err = MP_MEM; goto _ERR; }
+
+   M    = XCALLOC(sizeof(mp_int), 1<<Q);
+   if (M == NULL)    { err = MP_MEM; goto _VALS; }
+
+   /* init M table */
+   for (x = 0; x < (1<<Q); x++) {
+       if (mp_init(&M[x]) != MP_OKAY) {
+          for (Q = 0; Q < x; Q++) {
+              mp_clear(&M[x]);
+          }
+          err = MP_MEM;
+          goto __M;
+       }
+   }
+
+  /* init the barett reduction */
+  /* mu = b^2k / m */
+  if ((err = mp_init(&mu)) != MP_OKAY) {
+     goto _M;
+  }
+
+  if ((err = mp_init(&res)) != MP_OKAY) {
+     goto _MU;
+  }
+
+  mp_set(&mu, 1); 
+  s_mp_lshd(&mu, 2 * USED(P));
+  if((err = mp_div(&mu, P, &mu, NULL)) != MP_OKAY){
+    goto _RES;
+  }
+
+   /* now init the M array with powers of the base */
+   mp_set(&M[0], 1);
+   if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { goto _RES; }
+   
+   /* shrink first two */
+   for (x = 0; x < 2; x++) {
+      if ((err = mp_shrink(&M[x])) != MP_OKAY) { goto _RES; }
+   }
+   
+   for (x = 2; x < (1<<Q); x++) {
+       if (USED(&M[x]) == 1 && DIGIT(&M[x], 0) == 0) {
+          if ((err = mp_mul(&M[x-1], &M[1], &M[x])) != MP_OKAY)      { goto _RES; }
+          if ((err = s_mp_reduce(&M[x], P, &mu)) != MP_OKAY)         { goto _RES; }
+          if ((err = mp_shrink(&M[x])) != MP_OKAY)                   { goto _RES; }
+          
+          QQQ = x;
+          QQ  = x * 2;
+          while (QQ < (1<<Q)) {
+              if ((err = mp_sqr(&M[QQQ], &M[QQ])) != MP_OKAY)        { goto _RES; }
+              if ((err = s_mp_reduce(&M[QQ], P, &mu)) != MP_OKAY)    { goto _RES; }
+              if ((err = mp_shrink(&M[QQ])) != MP_OKAY)              { goto _RES; }
+              QQQ = QQ;
+              QQ  *= 2;
+          }
+       }
+   }
+   
+   /* now grab the bits */
+   if ((err = mp_init_copy(&tx, X)) != MP_OKAY) {
+      goto _RES;
+   }
+
+   x = 0;
+   while (mp_cmp_d(&tx, 0)) {
+       vals[x++] = DIGIT(&tx, 0) & ((1<<Q)-1);
+       s_mp_div_2d(&tx, Q);
+   }
+
+   /* now set output equal to the first digit exponent */
+   if ((err = mp_copy(&M[vals[--x]], &res)) != MP_OKAY)        { goto _TX; }
+
+   while (--x >= 0) {
+      for (QQ = 0; QQ < Q; QQ++) {
+          if ((err = s_mp_sqr(&res)) != MP_OKAY)               { goto _TX; }
+          if ((err = s_mp_reduce(&res, P, &mu)) != MP_OKAY)    { goto _TX; }
+      }
+      if (vals[x] != 0) {
+         if ((err = s_mp_mul(&res, &M[vals[x]])) != MP_OKAY)   { goto _TX; }
+         if ((err = s_mp_reduce(&res, P, &mu)) != MP_OKAY)     { goto _TX; }
+      }
+   }
+   s_mp_exch(&res, Y);
+
+   /* free ram */
+_TX:
+   mp_clear(&tx);
+_RES:
+   mp_clear(&res);
+_MU:
+   mp_clear(&mu);
+_M:
+   for (x = 0; x < (1<<Q); x++) {
+       mp_clear(&M[x]);
+   }
+__M:
+   XFREE(M);
+_VALS:
+   XFREE(vals);
+_ERR:
+   return err;
+}
+
+#else 
+
 /*
   mp_exptmod(a, b, m, c)
 
@@ -1731,6 +1882,8 @@ mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
 
 } /* end mp_exptmod() */
 
+#endif
+
 /* }}} */
 
 /* {{{ mp_exptmod_d(a, d, m, c) */
@@ -2888,7 +3041,9 @@ void     s_mp_rshd(mp_int *mp, mp_size p)
   for(ix = p; ix < USED(mp); ix++)
     dp[ix - p] = dp[ix];
 
+
   /* Fill the top digits with zeroes */
+  
   ix -= p;
   while(ix < USED(mp))
     dp[ix++] = 0;
@@ -2966,10 +3121,14 @@ void     s_mp_mod_2d(mp_int *mp, mp_digit d)
   dp[ndig] &= dmask;
 
   /* Flush all digits above the one with 2^d in it */
+
+/*
   for(ix = ndig + 1; ix < USED(mp); ix++)
     dp[ix] = 0;
 
   s_mp_clamp(mp);
+*/
+  USED(mp) = ndig;
 
 } /* end s_mp_mod_2d() */
 
@@ -3431,6 +3590,56 @@ mp_err   s_mp_mul(mp_int *a, mp_int *b)
 
 } /* end s_mp_mul() */
 
+/* Compute a = |a| * |b| max of digs digits */
+mp_err   s_mp_mul_dig(mp_int *a, mp_int *b, int digs)
+{
+  mp_word   w, k = 0;
+  mp_int    tmp;
+  mp_err    res;
+  mp_size   ix, jx, ua = USED(a), ub = USED(b);
+  mp_digit *pa, *pb, *pt, *pbt;
+
+  if((res = mp_init_size(&tmp, digs+1)) != MP_OKAY)
+    return res;
+
+  /* This has the effect of left-padding with zeroes... */
+  USED(&tmp) = digs+1;
+
+  /* We're going to need the base value each iteration */
+  pbt = DIGITS(&tmp);
+
+  /* Outer loop:  Digits of b */
+
+  pb = DIGITS(b);
+  for(ix = 0; ix < ub; ++ix, ++pb) {
+    if(*pb == 0) 
+      continue;
+
+    /* Inner product:  Digits of a */
+    pa = DIGITS(a);
+    for(jx = 0; jx < ua; ++jx, ++pa) {
+      if ((int)(ix+jx) > digs) { break; }
+      pt = pbt + ix + jx;
+      w = *pb * *pa + k + *pt;
+      *pt = ACCUM(w);
+      k = CARRYOUT(w);
+    }
+    if ((int)(ix + jx) < digs) {
+       pbt[ix + jx] = k;
+    }
+    k = 0;
+  }
+
+  USED(&tmp) = digs;
+  s_mp_clamp(&tmp);
+  s_mp_exch(&tmp, a);
+
+  mp_clear(&tmp);
+
+  return MP_OKAY;
+
+} /* end s_mp_mul() */
+
 /* }}} */
 
 /* {{{ s_mp_kmul(a, b, out, len) */
@@ -3763,8 +3972,8 @@ mp_err   s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu)
   s_mp_mod_2d(x, (mp_digit)(DIGIT_BIT * (um + 1)));
 
   /* q = q * m mod b^(k+1), quick (no division) */
-  s_mp_mul(&q, m);
-  s_mp_mod_2d(&q, (mp_digit)(DIGIT_BIT * (um + 1)));
+  s_mp_mul_dig(&q, m, um + 1);
+//  s_mp_mod_2d(&q, (mp_digit)(DIGIT_BIT * (um + 1)));
 
   /* x = x - q */
   if((res = mp_sub(x, &q, x)) != MP_OKAY)

+ 5 - 0
mpi.h

@@ -98,6 +98,8 @@ void   mp_clear_array(mp_int mp[], int count);
 void   mp_zero(mp_int *mp);
 void   mp_set(mp_int *mp, mp_digit d);
 mp_err mp_set_int(mp_int *mp, long z);
+mp_err mp_shrink(mp_int *a);
+
 
 /*------------------------------------------------------------------------*/
 /* Single digit arithmetic                                                */
@@ -149,6 +151,9 @@ mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c);
 #define mp_sqrmod(a, m, c) mp_mulmod(a, a, m, c)
 #endif
 mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
+mp_err s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu);
+mp_err   s_mp_lshd(mp_int *mp, mp_size p);
+mp_err   s_mp_mul_dig(mp_int *a, mp_int *b, int digs);
 mp_err mp_exptmod_d(mp_int *a, mp_digit d, mp_int *m, mp_int *c);
 #endif /* MP_MODARITH */
 

+ 26 - 26
mycrypt.h

@@ -13,46 +13,48 @@ extern "C" {
 #endif
 
 /* version */
-#define CRYPT   0x0078
-#define SCRYPT  "0.78"
+#define CRYPT   0x0079
+#define SCRYPT  "0.79"
 
 /* max size of either a cipher/hash block or symmetric key [largest of the two] */
 #define MAXBLOCKSIZE           128
 
+/* ch1-01-1 */
 /* error codes [will be expanded in future releases] */
 enum {
-   CRYPT_OK=0,
-   CRYPT_ERROR,
+   CRYPT_OK=0,             /* Result OK */
+   CRYPT_ERROR,            /* Generic Error */
 
-   CRYPT_INVALID_KEYSIZE,
-   CRYPT_INVALID_ROUNDS,
-   CRYPT_FAIL_TESTVECTOR,
+   CRYPT_INVALID_KEYSIZE,  /* Invalid key size given */
+   CRYPT_INVALID_ROUNDS,   /* Invalid number of rounds */
+   CRYPT_FAIL_TESTVECTOR,  /* Algorithm failed test vectors */
 
-   CRYPT_BUFFER_OVERFLOW,
-   CRYPT_INVALID_PACKET,
+   CRYPT_BUFFER_OVERFLOW,  /* Not enough space for output */
+   CRYPT_INVALID_PACKET,   /* Invalid input packet given */
 
-   CRYPT_INVALID_PRNGSIZE,
-   CRYPT_ERROR_READPRNG,
+   CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */
+   CRYPT_ERROR_READPRNG,   /* Could not read enough from PRNG */
 
-   CRYPT_INVALID_CIPHER,
-   CRYPT_INVALID_HASH,
-   CRYPT_INVALID_PRNG,
+   CRYPT_INVALID_CIPHER,   /* Invalid cipher specified */
+   CRYPT_INVALID_HASH,     /* Invalid hash specified */
+   CRYPT_INVALID_PRNG,     /* Invalid PRNG specified */
 
-   CRYPT_MEM,
+   CRYPT_MEM,              /* Out of memory */
 
-   CRYPT_PK_TYPE_MISMATCH,
-   CRYPT_PK_NOT_PRIVATE,
+   CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */
+   CRYPT_PK_NOT_PRIVATE,   /* Requires a private PK key */
 
-   CRYPT_INVALID_ARG,
+   CRYPT_INVALID_ARG,      /* Generic invalid argument */
 
-   CRYPT_PK_INVALID_TYPE,
-   CRYPT_PK_INVALID_SYSTEM,
-   CRYPT_PK_DUP,
-   CRYPT_PK_NOT_FOUND,
-   CRYPT_PK_INVALID_SIZE,
+   CRYPT_PK_INVALID_TYPE,  /* Invalid type of PK key */
+   CRYPT_PK_INVALID_SYSTEM,/* Invalid PK system specified */
+   CRYPT_PK_DUP,           /* Duplicate key already in key ring */
+   CRYPT_PK_NOT_FOUND,     /* Key not found in keyring */
+   CRYPT_PK_INVALID_SIZE,  /* Invalid size input for PK parameters */
 
-   CRYPT_INVALID_PRIME_SIZE
+   CRYPT_INVALID_PRIME_SIZE/* Invalid size of prime requested */
 };
+/* ch1-01-1 */
 
 #include <mycrypt_cfg.h>
 #include <mycrypt_macros.h>
@@ -63,10 +65,8 @@ enum {
 #include <mycrypt_gf.h>
 #include <mycrypt_misc.h>
 #include <mycrypt_kr.h>
-
 #include <mycrypt_argchk.h>
 
-
 #ifdef __cplusplus
    }
 #endif

+ 5 - 16
mycrypt_argchk.h

@@ -1,26 +1,14 @@
 /* Defines the _ARGCHK macro used within the library */
 
+/* ch1-01-1 */
 /* ARGTYPE is defined in mycrypt_cfg.h */
 #if ARGTYPE == 0
 
 #include <signal.h>
 
-/* this is the default LibTomCrypt macro 
- *
- * On embedded platforms you can change the fprintf() to be a routine that would display a message
- * somehow 
- */
- 
-#ifdef SMALL_CODE 
-   extern void crypt_argchk(char *v, char *s, int d);
-   #define _ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); }
-#else
-   #ifdef SONY_PS2
-      #define _ARGCHK(x) if (!(x)) { printf("_ARGCHK '%s' failure on line %d of file %s\n", #x, __LINE__, __FILE__); raise(SIGABRT); }
-   #else
-      #define _ARGCHK(x) if (!(x)) { fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n", #x, __LINE__, __FILE__); raise(SIGABRT); }
-   #endif
-#endif   
+/* this is the default LibTomCrypt macro  */
+extern void crypt_argchk(char *v, char *s, int d);
+#define _ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); }
 
 #elif ARGTYPE == 1
 
@@ -32,4 +20,5 @@
 #define _ARGCHK(x) 
 
 #endif
+/* ch1-01-1 */
 

+ 10 - 30
mycrypt_cfg.h

@@ -9,18 +9,21 @@
 
 /* you can change how memory allocation works ... */
 extern void *XMALLOC(size_t n);
+extern void *REALLOC(void *p, size_t n);
 extern void *XCALLOC(size_t n, size_t s);
 extern void XFREE(void *p);
 
 /* change the clock function too */
 extern clock_t XCLOCK(void);
 
+/* ch1-01-1 */
 /* type of argument checking, 0=default, 1=fatal and 2=none */
 #define ARGTYPE  0
+/* ch1-01-1 */
 
 /* Controls endianess and size of registers.  Leave uncommented to get platform neutral [slower] code */
 /* detect x86-32 machines somewhat */
-#if (defined(_MSC_VER) && defined(WIN32))  || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__)))
+#if (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__)))
    #define ENDIAN_LITTLE
    #define ENDIAN_32BITWORD
 #endif
@@ -53,7 +56,7 @@ extern clock_t XCLOCK(void);
 
 #ifdef YARROW
    #ifndef CTR
-      #error YARROW Requires CTR mode
+      #error YARROW requires CTR chaining mode to be defined!
    #endif
 #endif
 
@@ -62,12 +65,13 @@ extern clock_t XCLOCK(void);
     #define PACKET
 
     /* size of a packet header in bytes */
-    #define PACKET_SIZE            8
+    #define PACKET_SIZE            4
 
     /* Section tags */
     #define PACKET_SECT_RSA        0
     #define PACKET_SECT_DH         1
     #define PACKET_SECT_ECC        2
+    #define PACKET_SECT_DSA        4
 
     /* Subsection Tags for the first three sections */
     #define PACKET_SUB_KEY         0
@@ -76,33 +80,6 @@ extern clock_t XCLOCK(void);
     #define PACKET_SUB_ENC_KEY     3
 #endif
 
-/* Diffie-Hellman key settings you can omit ones you don't want to save space */
-#ifdef MDH
-
-#define DH768
-#define DH1024
-#define DH1280
-#define DH1536
-#define DH1792
-#define DH2048
-#define DH2560
-#define DH3072
-#define DH4096
-
-#endif /* MDH */
-
-/* ECC Key settings */
-#ifdef MECC 
-
-#define ECC160
-#define ECC192
-#define ECC224
-#define ECC256
-#define ECC384
-#define ECC521
-
-#endif /* MECC */
-
 #ifdef MPI
    #include "mpi.h"
 #else
@@ -115,6 +92,9 @@ extern clock_t XCLOCK(void);
    #ifdef MDH
       #error DH requires the big int library 
    #endif
+   #ifdef MDSA
+      #error DSA requires the big int library 
+   #endif
 #endif /* MPI */
 
 #endif /* MYCRYPT_CFG_H */

+ 2 - 0
mycrypt_misc.h

@@ -11,6 +11,8 @@ extern int base64_decode(const unsigned char *in,  unsigned long len,
 extern void zeromem(void *dst, unsigned long len);
 extern void burn_stack(unsigned long len);
 
+/* ch1-01-1*/
 extern const char *error_to_string(int errno);
+/* ch1-01-1*/
 
 extern const char *crypt_build_settings;

+ 37 - 15
mycrypt_pk.h

@@ -17,7 +17,7 @@ extern void mp_clear_multi(mp_int* mp, ...);
 /* ---- PACKET ---- */
 #ifdef PACKET
 
-extern void packet_store_header(unsigned char *dst, int section, int subsection, unsigned long length);
+extern void packet_store_header(unsigned char *dst, int section, int subsection);
 extern int packet_valid_header(unsigned char *src, int section, int subsection);
 
 #endif
@@ -56,15 +56,16 @@ extern int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen,
                                  unsigned char *outkey, unsigned long *outlen,
                                  prng_state *prng, int wprng, rsa_key *key);
 
-extern int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey, 
-                                 unsigned long *keylen, rsa_key *key);
+extern int rsa_decrypt_key(const unsigned char *in, unsigned long inlen,
+                                 unsigned char *outkey, unsigned long *keylen, 
+                                 rsa_key *key);
 
 extern int rsa_sign_hash(const unsigned char *in,  unsigned long inlen, 
                                unsigned char *out, unsigned long *outlen, 
                                rsa_key *key);
 
-extern int rsa_verify_hash(const unsigned char *sig, const unsigned char *hash,
-                                 int *stat, rsa_key *key);
+extern int rsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+                           const unsigned char *hash, int *stat, rsa_key *key);
 
 extern int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key);
 extern int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key);
@@ -96,16 +97,17 @@ extern int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen,
                                 prng_state *prng, int wprng, int hash, 
                                 dh_key *key);
 
-extern int dh_decrypt_key(const unsigned char *in,  unsigned char *outkey, 
-                                unsigned long *keylen, dh_key *key);
+extern int dh_decrypt_key(const unsigned char *in,  unsigned long inlen, 
+                                unsigned char *outkey, unsigned long *keylen, 
+                                dh_key *key);
 
 extern int dh_sign_hash(const unsigned char *in,  unsigned long inlen,
                               unsigned char *out, unsigned long *outlen,
                               prng_state *prng, int wprng, dh_key *key);
 
-extern int dh_verify_hash(const unsigned char *sig, const unsigned char *hash, 
-                                unsigned long inlen, int *stat, 
-                                dh_key *key);
+extern int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
+                          const unsigned char *hash, unsigned long hashlen, 
+                                int *stat, dh_key *key);
 
 
 #endif
@@ -140,15 +142,35 @@ extern int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
                                  prng_state *prng, int wprng, int hash, 
                                  ecc_key *key);
 
-extern int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey, 
-                                 unsigned long *keylen, ecc_key *key);
+extern int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
+                                 unsigned char *outkey, unsigned long *keylen, 
+                                 ecc_key *key);
 
 extern int ecc_sign_hash(const unsigned char *in,  unsigned long inlen,
                                unsigned char *out, unsigned long *outlen,
                                prng_state *prng, int wprng, ecc_key *key);
 
-extern int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash, 
-                                 unsigned long inlen, int *stat, 
-                                 ecc_key *key);
+extern int ecc_verify_hash(const unsigned char *sig,  unsigned long siglen,
+                           const unsigned char *hash, unsigned long hashlen, 
+                                 int *stat, ecc_key *key);
+#endif
+
+#ifdef MDSA
+
+typedef struct {
+    int type, idx;
+    mp_int x, y;
+} dsa_key;
+
+extern int dsa_test(void);
+
+extern int dsa_make_key(prng_state *prng, int wprng, int keysize, dsa_key *key);
+extern void dsa_free(dsa_key *key);
+
+extern int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key);
+extern int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key);
+
+
+
 #endif
 

+ 1 - 3
packet.c

@@ -2,7 +2,7 @@
 
 #ifdef PACKET
 
-void packet_store_header(unsigned char *dst, int section, int subsection, unsigned long length)
+void packet_store_header(unsigned char *dst, int section, int subsection)
 {
    _ARGCHK(dst != NULL);
 
@@ -14,8 +14,6 @@ void packet_store_header(unsigned char *dst, int section, int subsection, unsign
    dst[2] = section & 255;
    dst[3] = subsection & 255;
 
-   /* store length */
-   STORE32L(length, &dst[4]);
 }
 
 int packet_valid_header(unsigned char *src, int section, int subsection)

+ 0 - 2
prime.c

@@ -230,8 +230,6 @@ done:
     return res;
 }
 
-
-
 int rand_prime(mp_int *N, long len, prng_state *prng, int wprng)
 {
    unsigned char buf[260];

+ 29 - 4
rsa.c

@@ -73,7 +73,19 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
 
    if (mp_copy(&p, &key->p) != MP_OKAY)                    { goto error2; }
    if (mp_copy(&q, &key->q) != MP_OKAY)                    { goto error2; }
+   
  
+   /* shrink ram required  */
+   if (mp_shrink(&key->e) != MP_OKAY)                      { goto error2; }
+   if (mp_shrink(&key->d) != MP_OKAY)                      { goto error2; }
+   if (mp_shrink(&key->N) != MP_OKAY)                      { goto error2; }
+   if (mp_shrink(&key->dQ) != MP_OKAY)                     { goto error2; }
+   if (mp_shrink(&key->dP) != MP_OKAY)                     { goto error2; }
+   if (mp_shrink(&key->qP) != MP_OKAY)                     { goto error2; }
+   if (mp_shrink(&key->pQ) != MP_OKAY)                     { goto error2; }
+   if (mp_shrink(&key->p) != MP_OKAY)                      { goto error2; }
+   if (mp_shrink(&key->q) != MP_OKAY)                      { goto error2; }
+   
    res = CRYPT_OK;
    key->type = PK_PRIVATE_OPTIMIZED;
    goto done;
@@ -293,10 +305,10 @@ int rsa_depad(const unsigned char *in,  unsigned long inlen,
 
 #define OUTPUT_BIGNUM(num, buf2, y, z)         \
 {                                              \
-      z = mp_raw_size(num);                    \
+      z = mp_unsigned_bin_size(num);           \
       STORE32L(z, buf2+y);                     \
       y += 4;                                  \
-      mp_toraw(num, buf2+y);                   \
+      mp_to_unsigned_bin(num, buf2+y);         \
       y += z;                                  \
 }
 
@@ -318,11 +330,16 @@ int rsa_depad(const unsigned char *in,  unsigned long inlen,
      }                                                           \
                                                                  \
      /* load it */                                               \
-     if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\
+     if (mp_read_unsigned_bin(num, (unsigned char *)in+y, x) != MP_OKAY) {\
         errno = CRYPT_MEM;                                       \
         goto error2;                                             \
      }                                                           \
      y += x;                                                     \
+                                                                 \
+     if (mp_shrink(num) != MP_OKAY) {                            \
+        errno = CRYPT_MEM;                                       \
+        goto error2;                                             \
+     }                                                           \
 }
 
 int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key)
@@ -371,7 +388,7 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key
    }
 
    /* store packet header */
-   packet_store_header(buf2, PACKET_SECT_RSA, PACKET_SUB_KEY, y);
+   packet_store_header(buf2, PACKET_SECT_RSA, PACKET_SUB_KEY);
 
    /* copy to the user buffer */
    memcpy(out, buf2, y);
@@ -431,6 +448,14 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
       INPUT_BIGNUM(&key->p, in, x, y);
       INPUT_BIGNUM(&key->q, in, x, y);
    }
+   
+   /* free up ram not required */
+   if (key->type != PK_PRIVATE_OPTIMIZED) {
+      mp_clear_multi(&key->dQ, &key->dP, &key->pQ, &key->qP, &key->p, &key->q, NULL);
+   }
+   if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) {
+      mp_clear(&key->d);
+   }
 
    return CRYPT_OK;
 error2:

+ 32 - 8
rsa_sys.c

@@ -49,7 +49,7 @@ int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen,
    }
 
    /* store header */
-   packet_store_header(outkey, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY, y);
+   packet_store_header(outkey, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY);
 
 #ifdef CLEAN_STACK
    /* clean up */
@@ -60,8 +60,9 @@ int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen,
    return CRYPT_OK;
 }
 
-int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey, 
-                    unsigned long *keylen, rsa_key *key)
+int rsa_decrypt_key(const unsigned char *in, unsigned long inlen,
+                          unsigned char *outkey, unsigned long *keylen, 
+                          rsa_key *key)
 {
    unsigned char sym_key[MAXBLOCKSIZE], rsa_in[4096], rsa_out[4096];
    unsigned long x, y, z, i, rsa_size;
@@ -77,6 +78,12 @@ int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey,
       return CRYPT_PK_NOT_PRIVATE;
    }
 
+   if (inlen < PACKET_SIZE+4) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= PACKET_SIZE+4;
+   }
+
    /* check the header */
    if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
       return errno;
@@ -84,7 +91,12 @@ int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey,
 
    /* grab length of the rsa key */
    y = PACKET_SIZE;
-   LOAD32L(rsa_size, (in+y))
+   LOAD32L(rsa_size, (in+y));
+   if (inlen < rsa_size) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      inlen -= rsa_size;
+   }
    y += 4;
 
    /* read it in */
@@ -94,8 +106,9 @@ int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey,
 
    /* decrypt it */
    x = sizeof(rsa_out);
-   if ((errno = rsa_exptmod(rsa_in, rsa_size, rsa_out, &x, PK_PRIVATE, key)) != CRYPT_OK) 
+   if ((errno = rsa_exptmod(rsa_in, rsa_size, rsa_out, &x, PK_PRIVATE, key)) != CRYPT_OK) {
       return errno;
+   }
 
    /* depad it */
    z = sizeof(sym_key);
@@ -170,7 +183,7 @@ int rsa_sign_hash(const unsigned char *in,  unsigned long inlen,
    }
 
    /* store header */
-   packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_SIGNED, y);
+   packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_SIGNED);
 
 #ifdef CLEAN_STACK
    /* clean up */
@@ -181,8 +194,8 @@ int rsa_sign_hash(const unsigned char *in,  unsigned long inlen,
    return CRYPT_OK;
 }
 
-int rsa_verify_hash(const unsigned char *sig, const unsigned char *md,
-                          int *stat, rsa_key *key)
+int rsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+                    const unsigned char *md, int *stat, rsa_key *key)
 {
    unsigned long rsa_size, x, y, z;
    unsigned char rsa_in[4096], rsa_out[4096];
@@ -195,6 +208,12 @@ int rsa_verify_hash(const unsigned char *sig, const unsigned char *md,
 
    /* always be incorrect by default */
    *stat = 0;
+   
+   if (siglen < PACKET_SIZE+4) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      siglen -= PACKET_SIZE+4;
+   }
 
    /* verify header */
    if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_RSA, PACKET_SUB_SIGNED)) != CRYPT_OK) {
@@ -204,6 +223,11 @@ int rsa_verify_hash(const unsigned char *sig, const unsigned char *md,
    /* get the len */
    y = PACKET_SIZE;
    LOAD32L(rsa_size, (sig+y));
+   if (siglen < rsa_size) {
+      return CRYPT_INVALID_PACKET;
+   } else {
+      siglen -= rsa_size;
+   }
    y += 4;
 
    /* load the signature */

+ 2 - 1
sha1.c

@@ -25,7 +25,7 @@ static void _sha1_compress(hash_state *md)
 static void sha1_compress(hash_state *md)
 #endif
 {
-    unsigned long a,b,c,d,e,W[80],i,j;
+    unsigned long a,b,c,d,e,W[80],i,j,j2,j3;
 
     _ARGCHK(md != NULL);
 
@@ -47,6 +47,7 @@ static void sha1_compress(hash_state *md)
         W[i] = ROL(j, 1);
     }
 
+
     /* compress */
     /* round one */
     for (i = 0;  i < 20; i++)  { 

+ 1 - 1
strings.c

@@ -38,7 +38,7 @@ static const char *err_2_str[] =
 
 const char *error_to_string(int errno)
 {
-   if (errno < 0 || errno > (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) {
+   if (errno < 0 || errno >= (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) {
       return "Invalid error code.";
    } else {
       return err_2_str[errno];

+ 131 - 0
update_libtomcrypt.sh

@@ -0,0 +1,131 @@
+#!/bin/tcsh
+# Get latest copy of libtomcrypt and install it using "tcsh"
+#
+# Tom St Denis
+echo libtomcrypt update script, Tom St Denis
+echo "http://libtomcrypt.iahu.ca\n"
+
+if ($1 == "--help") then
+   echo "update_libtomcrypt.sh [makefile] [sig]-- Download and optionally build the libtomcrypt project.\n"
+   echo "\t[makefile] --\tYou can optionally specify which makefile you want to build with. If you specify "
+   echo "\t\t\t'nobuild' then the library is not built, just downloaded and unzipped.  If you "
+   echo "\t\t\tleave it empty the default 'makefile' is used to build the library.\n"
+   echo "\t[sig] -- \tOptionally verify [via GPG] the signature of the package."
+   exit
+endif
+
+if ($1 == "" || $1 == "sig") then
+   set make = "makefile"
+else
+   set make = $1;
+endif
+
+if ($1 == "sig" || $2 == "sig") then
+   set sig = "sig"
+else
+   set sig = ""
+endif   
+
+rm -f latest
+echo Getting latest version number from website.
+wget -q http://iahu.ca:8080/download/latest
+if (-r latest) then 
+   set a = `cat latest`
+   echo "Latest release is v$a.\n"
+   if (-d "libtomcrypt-$a" && (-r "libtomcrypt-$a/libtomcrypt.a" || $make == "nobuild")) then
+      echo Libtomcrypt v$a is already installed on your system.
+   else   
+      echo "Downloading libtomcrypt v$a ..."
+      if (-r "crypt-$a.tar.bz2") then 
+         rm -f crypt-$a.tar.bz2
+      endif
+      wget http://iahu.ca:8080/download/crypt-$a.tar.bz2
+      if (-r "crypt-$a.tar.bz2") then 
+         if (-d "libtomcrypt-$a") then
+            echo "WARNING!  Directory libtomcrypt-$a already exists.  Cannot continue.\n"
+            exit            
+         endif
+         if ($sig == "sig") then
+            if (!(-r public.asc)) then
+               echo "Downloading and installing code signing key...\n"
+               wget -q http://iahu.ca:8080/download/public.asc
+               if (-r public.asc) then 
+                  gpg --import public.asc
+                  if ($? != 0) then
+                     echo Could not import signing key required to verify the package.
+                     exit
+                  else
+                     echo "\n********************************************************************************"
+                     echo "A new key has been imported to your keyring.  You should check that it is valid."
+                     echo "********************************************************************************"
+                  endif
+               else 
+                  echo "Could not download the key to import."
+                  exit
+               endif
+            endif
+            echo Verifying signature...
+            wget -q http://iahu.ca:8080/download/crypt-$a.tar.bz2.asc
+            if (!(-r "crypt-$a.tar.bz2.asc")) then
+               echo Could not download signature to test.
+               exit
+            endif
+            gpg -q --verify crypt-$a.tar.bz2.asc
+            if ($? != 0) then 
+               echo "\n\nSignature for crypt-$a.tar.bz2 is ****not**** valid.\n\n"
+               exit
+            else
+               echo "\n\nSignature for crypt-$a.tar.bz2 is valid.\n\n"
+            endif
+         endif
+         bzip2 -d -c crypt-$a.tar.bz2 | tar -x 
+         if (-d "libtomcrypt-$a") then
+            if (-r "libtomcrypt-$a/$make") then 
+               cd libtomcrypt-$a
+               make -f $make
+               if (-r "libtomcrypt.a") then
+                  echo "\n\n*****************************************************************"
+                  echo The library has been built and you can now install it either with
+                  echo 
+                  echo "cd libtomcrypt-$a ; make install"
+                  echo
+                  echo Or by editing the makefile and changing the user you wish to install 
+                  echo it with, or simply copy "libtomcrypt.a" to your library directory and 
+                  echo copy "*.h" to your include directory
+                  echo "*****************************************************************"
+               else 
+                  echo "\n\n*****************************************************************"
+                  echo The library failed to build.  Please note the errors and send them to [email protected]
+                  echo "*****************************************************************"
+               endif
+            else if ($make == "nobuild") then
+                  echo "\n\n*****************************************************************"
+                  echo "The library was downloaded and unzipped into libtomcrypt-$a/"
+                  echo "*****************************************************************"
+            else
+               echo "The makefile '$make' was not found in the archive.\n";
+            endif
+         else 
+            echo "Could not unpack the libtomcrypt archive (corrupt?)."
+         endif
+         cd ..
+      else
+         echo "Could not download the libtomcrypt archive from server."
+      endif
+   endif
+   if (-r "libtomcrypt-$a/changes") then
+      perl <<!
+      open(IN,"<libtomcrypt-$a/changes") or die "Can't open libtomcrypt change log.";
+      print "\nChange log for v$a :\n";
+      \$a = <IN>; print \$a; \$a = <IN>;
+      while (<IN>) { 
+         if (\$_ =~ m/^(v\d\.\d\d)/) { close(IN); exit(0); } 
+         print "\$a"; \$a = \$_; 
+      }
+!
+   else 
+      echo "Change log not found.  Is the package really installed?"
+   endif
+else 
+   echo "Could not download latest file from server to check version."
+endif