Applied changes from GnuPG stable.
authorWerner Koch <wk@gnupg.org>
Fri, 3 Aug 2001 10:57:34 +0000 (10:57 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 3 Aug 2001 10:57:34 +0000 (10:57 +0000)
Add a first tes program

29 files changed:
ChangeLog
Makefile.am
NEWS
THANKS
cipher/ChangeLog
cipher/Makefile.am
cipher/arcfour.c
cipher/blowfish.c
cipher/cast5.c
cipher/cipher.c
cipher/des.c
cipher/md5.c
cipher/primegen.c
cipher/random.c
cipher/rijndael.c
cipher/rmd160.c
cipher/rndlinux.c
cipher/rndunix.c
cipher/sha1.c
cipher/tiger.c
cipher/twofish.c
configure.in
libgcrypt.txt [new file with mode: 0644]
src/ChangeLog
src/gcrypt.h
src/global.c
tests/ChangeLog [new file with mode: 0644]
tests/Makefile.am [new file with mode: 0644]
tests/basic.c [new file with mode: 0644]

index bed5f6f..df1a684 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2001-08-03  Werner Koch  <wk@gnupg.org>
+
+       * tests/: New.
+       * Makefile.am: Included tests directory
+       
+       * configure.in (DYNLINK_MOD_CFLAGS): Use -shared with dec-osf.
+       Reported by Chris Adams.  Merged some cases.
+
 2001-05-31  Werner Koch  <wk@gnupg.org>
 
        Release 1.1.3.
index 8067208..86e2813 100644 (file)
@@ -1,6 +1,6 @@
 ## Process this file with automake to produce Makefile.in
 
-SUBDIRS = jnlib mpi cipher src doc
+SUBDIRS = jnlib mpi cipher src doc tests
 EXTRA_DIST = README-alpha BUGS
 DISTCLEANFILES = gcrypt-defs.h 
 
diff --git a/NEWS b/NEWS
index e815ed0..dc41db2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,19 @@
 
+  * Arcfour does now work.                   
 
-GnuPG has been spitted into libgcrypt and GnuPG.
+Noteworthy changes in version 1.1.3 (2001-05-31)
+------------------------------------------------
+
+  * First release of Libgcrypt which is a result of splitting GnuPG
+    into into libgcrypt and GnuPG.
+
+
+Copyright 2001 Free Software Foundation, Inc.
+
+This file is free software; as a special exception the author gives
+unlimited permission to copy and/or distribute it, with or without
+modifications, as long as this notice is preserved.
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/THANKS b/THANKS
index 4eeb8d9..fc47e6f 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -78,6 +78,7 @@ Philippe Laliberte       arsphl@oeil.qc.ca
 Peter Gutmann             pgut001@cs.auckland.ac.nz
 QingLong                  qinglong@bolizm.ihep.su
 Ralph Gillen              gillen@theochem.uni-duesseldorf.de
+Rami Lehti                 Rami.Lehti@finland.sun.com
 Rat                       ratinox@peorth.gweep.net
 Reinhard Wobst            R.Wobst@ifw-dresden.de
 Rémi Guyomarch            rguyom@mail.dotcom.fr
@@ -99,6 +100,7 @@ Thomas Roessler         roessler@guug.de
 Tom Spindler              dogcow@home.merit.edu
 Tom Zerucha               tzeruch@ceddec.com
 Tomas Fasth               tomas.fasth@twinspot.net
+Tommi Komulainen           Tommi.Komulainen@iki.fi
 Thomas Mikkelsen          tbm@image.dk
 Ulf Möller                3umoelle@informatik.uni-hamburg.de
 Urko Lusa                 ulusa@euskalnet.net
index e96ce48..ee01563 100644 (file)
@@ -1,5 +1,43 @@
+2001-08-03  Werner Koch  <wk@gnupg.org>
+
+       * cipher.c (cipher_encrypt, cipher_decrypt): Prepare to return
+       errors. We have to change the interface to all ciphers to make
+       this really work but we should do so to prepare for hardware
+       encryption modules.
+       (gcry_cipher_encrypt, gcry_cipher_decrypt): Return the error and
+       set lasterr. 
+       (gcry_cipher_ctl): Make sure that errors from setkey are returned.
+
 2001-08-02  Werner Koch  <wk@gnupg.org>
 
+       * rndlinux.c (gather_random): casted a size_t arg to int so that
+       the format string is correct.  Casting is okay here and avoids
+       translation changes. 
+
+       * random.c (fast_random_poll): Do not check the return code of
+       getrusage.
+
+       * rndunix.c: Add a signal.h header to avoid warnings on Solaris 7
+       and 8.
+
+       * tiger.c (print_abc,print_data): Removed.
+
+       * rijndael.c, des.c, blowfish.c, twofish.c, cast5.c, arcfour.c
+       (burn_stack): New.  Add wrappers for most functions to be able to
+       call burn_stack after the function invocation. This methods seems
+       to be the most portable way to zeroise the stack used. It does
+       only work on stack frame based machines but it is highly portable
+       and has no side effects.  Just setting the automatic variables at
+       the end of a function to zero does not work well because the
+       compiler will optimize them away - marking them as volatile would
+       be bad for performance.
+       * md5.c, sha1.c, rmd160.c, tiger.c (burn_stack): Likewise.
+       * random.c (burn_stack): New.
+       (mix_pool): Use it here to burn the stack of the mixblock function.
+
+       * primegen.c (_gcry_generate_elg_prime): Freed q at 3 places.
+       Thanks to Tommi Komulainen.
+
        * arcfour.c (arcfour_setkey): Check the minimim keylength against
        bytes and not bits.
        (selftest): Must reset the key before decryption. 
index 0d78e93..217aa35 100644 (file)
@@ -1,3 +1,21 @@
+# Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+#
+# This file is part of Libgcrypt.
+#
+# Libgcrypt is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Libgcrypt is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
 # Process this file with automake to produce Makefile.in
 
 
index c19d282..e9db410 100644 (file)
@@ -41,7 +41,19 @@ typedef struct {
 
 
 static void
-encrypt_stream( ARCFOUR_context *ctx,
+burn_stack (int bytes)
+{
+    char buf[64];
+    
+    memset (buf, 0, sizeof buf);
+    bytes -= sizeof buf;
+    if (bytes > 0)
+        burn_stack (bytes);
+}
+
+
+static void
+do_encrypt_stream( ARCFOUR_context *ctx,
                 byte *outbuf, const byte *inbuf, unsigned int length )
 {
     int t;  
@@ -60,9 +72,18 @@ encrypt_stream( ARCFOUR_context *ctx,
     ctx->idx_j = j;
 }
 
+static void
+encrypt_stream( ARCFOUR_context *ctx,
+                byte *outbuf, const byte *inbuf, unsigned int length )
+{
+
+    do_encrypt_stream (ctx, outbuf, inbuf, length );
+    burn_stack (64);
+}
+
 
 static int
-arcfour_setkey( ARCFOUR_context *ctx, const byte *key, unsigned int keylen )
+do_arcfour_setkey( ARCFOUR_context *ctx, const byte *key, unsigned int keylen )
 {
     static int initialized;
     static const char* selftest_failed;
@@ -98,6 +119,14 @@ arcfour_setkey( ARCFOUR_context *ctx, const byte *key, unsigned int keylen )
     return 0;
 }
 
+static int
+arcfour_setkey ( ARCFOUR_context *ctx, const byte *key, unsigned int keylen )
+{
+    int rc = do_arcfour_setkey (ctx, key, keylen );
+    burn_stack (300);
+    return rc;
+}
+
 
 static const char*
 selftest(void)
index 0847de3..dc8e3fe 100644 (file)
@@ -1,5 +1,5 @@
 /* blowfish.c  -  Blowfish encryption
- *     Copyright (C) 1998 Free Software Foundation, Inc.
+ *     Copyright (C) 1998, 2001 Free Software Foundation, Inc.
  *
  * For a description of the algorithm, see:
  *   Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996.
@@ -281,6 +281,17 @@ function_F( BLOWFISH_context *bc, u32 x )
 #endif
 #define R(l,r,i)  do { l ^= p[i]; r ^= F(l); } while(0)
 
+static void
+burn_stack (int bytes)
+{
+    char buf[64];
+    
+    memset (buf, 0, sizeof buf);
+    bytes -= sizeof buf;
+    if (bytes > 0)
+        burn_stack (bytes);
+}
+
 
 static void
 do_encrypt(  BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
@@ -416,7 +427,7 @@ decrypt(  BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
 #undef R
 
 static void
-encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
+do_encrypt_block ( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
 {
     u32 d1, d2;
 
@@ -433,9 +444,16 @@ encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
     outbuf[7] =  d2       & 0xff;
 }
 
+static void
+encrypt_block ( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
+{
+    do_encrypt_block (bc, outbuf, inbuf);
+    burn_stack (64);
+}
+
 
 static void
-decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
+do_decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
 {
     u32 d1, d2;
 
@@ -452,6 +470,13 @@ decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
     outbuf[7] =  d2       & 0xff;
 }
 
+static void
+decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
+{
+    do_decrypt_block (bc, outbuf, inbuf);
+    burn_stack (64);
+}
+
 
 static const char*
 selftest(void)
@@ -484,7 +509,7 @@ selftest(void)
 
 
 static int
-bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
+do_bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
 {
     int i, j;
     u32 data, datal, datar;
@@ -567,6 +592,15 @@ bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
 }
 
 
+static int
+bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
+{
+    int rc = do_bf_setkey (c, key, keylen);
+    burn_stack (64);
+    return rc;
+}
+
+
 /****************
  * Return some information about the algorithm.  We need algo here to
  * distinguish different flavors of the algorithm.
index 9811c45..e5ffaa9 100644 (file)
@@ -1,5 +1,5 @@
 /* cast5.c  -  CAST5 cipher (RFC2144)
- *     Copyright (C) 1998 Free Software Foundation, Inc.
+ *     Copyright (C) 1998, 2001 Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
@@ -358,7 +358,19 @@ rol(int n, u32 x)
     (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) )
 
 static void
-encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
+burn_stack (int bytes)
+{
+    char buf[64];
+    
+    memset (buf, 0, sizeof buf);
+    bytes -= sizeof buf;
+    if (bytes > 0)
+        burn_stack (bytes);
+}
+
+
+static void
+do_encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
 {
     u32 l, r, t;
     u32 I;   /* used by the Fx macros */
@@ -412,7 +424,16 @@ encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
 }
 
 static void
-decrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
+encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
+{
+    do_encrypt_block (c, outbuf, inbuf);
+    burn_stack (20+4*sizeof(void*));
+}
+
+\f
+
+static void
+do_decrypt_block (CAST5_context *c, byte *outbuf, byte *inbuf )
 {
     u32 l, r, t;
     u32 I;
@@ -452,7 +473,13 @@ decrypt_block(     CAST5_context *c, byte *outbuf, byte *inbuf )
     outbuf[7] =  l       & 0xff;
 }
 
-
+static void
+decrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
+{
+    do_decrypt_block (c, outbuf, inbuf);
+    burn_stack (20+4*sizeof(void*));
+}
+\f
 
 static const char*
 selftest(void)
@@ -500,6 +527,7 @@ selftest(void)
     return NULL;
 }
 
+\f
 
 static void
 key_schedule( u32 *x, u32 *z, u32 *k )
@@ -550,7 +578,7 @@ key_schedule( u32 *x, u32 *z, u32 *k )
 
 
 static int
-cast_setkey( CAST5_context *c, byte *key, unsigned keylen )
+do_cast_setkey( CAST5_context *c, byte *key, unsigned keylen )
 {
   static int initialized;
   static const char* selftest_failed;
@@ -592,6 +620,14 @@ cast_setkey( CAST5_context *c, byte *key, unsigned keylen )
     return 0;
 }
 
+static int
+cast_setkey( CAST5_context *c, byte *key, unsigned keylen )
+{
+    int rc = do_cast_setkey (c, key, keylen);
+    burn_stack (96+7*sizeof(void*));
+    return rc;
+}
+\f
 
 /****************
  * Return some information about the algorithm.  We need algo here to
index 0dfe866..a5afdc0 100644 (file)
@@ -701,18 +701,24 @@ do_cfb_decrypt( GCRY_CIPHER_HD c,
  * inbuf and outbuf may overlap or be the same.
  * Depending on the mode some contraints apply to NBYTES.
  */
-static void
+static int
 cipher_encrypt( GCRY_CIPHER_HD c, byte *outbuf,
                                  const byte *inbuf, unsigned int nbytes )
 {
+    int rc = 0;
+
     switch( c->mode ) {
       case GCRY_CIPHER_MODE_ECB:
-       assert(!(nbytes%c->blocksize));
-       do_ecb_encrypt(c, outbuf, inbuf, nbytes/c->blocksize );
+       if (!(nbytes%c->blocksize))
+            do_ecb_encrypt(c, outbuf, inbuf, nbytes/c->blocksize );
+        else 
+            rc = GCRYERR_INV_ARG;
        break;
       case GCRY_CIPHER_MODE_CBC:
-       assert(!(nbytes%c->blocksize));  
-       do_cbc_encrypt(c, outbuf, inbuf, nbytes/c->blocksize );
+       if (!(nbytes%c->blocksize))
+            do_cbc_encrypt(c, outbuf, inbuf, nbytes/c->blocksize );
+        else 
+            rc = GCRYERR_INV_ARG;
        break;
       case GCRY_CIPHER_MODE_CFB:
        do_cfb_encrypt(c, outbuf, inbuf, nbytes );
@@ -725,8 +731,12 @@ cipher_encrypt( GCRY_CIPHER_HD c, byte *outbuf,
        if( inbuf != outbuf )
            memmove( outbuf, inbuf, nbytes );
        break;
-      default: log_fatal("cipher_encrypt: invalid mode %d\n", c->mode );
+      default:
+        log_fatal("cipher_encrypt: invalid mode %d\n", c->mode );
+        rc = GCRYERR_INV_CIPHER_MODE;
+        break;
     }
+    return rc;
 }
 
 
@@ -738,21 +748,24 @@ int
 gcry_cipher_encrypt( GCRY_CIPHER_HD h, byte *out, size_t outsize,
                                       const byte  *in, size_t inlen )
 {
-    if( !in ) {
+    int rc;
+
+    if ( !in ) {
        /* caller requested in-place encryption */
        /* actullay cipher_encrypt() does not need to know about it, but
         * we may chnage this to get better performace */
-       cipher_encrypt( h, out, out, outsize );
+       rc = cipher_encrypt ( h, out, out, outsize );
     }
     else {
-       if( outsize < inlen )
-           return set_lasterr( GCRYERR_TOO_SHORT );
+       if ( outsize < inlen )
+           return set_lasterr ( GCRYERR_TOO_SHORT );
        /* fixme: check that the inlength is a multipe of the blocksize
         * if a blockoriented mode is used, or modify cipher_encrypt to
         * return an error in this case */
-       cipher_encrypt( h, out, in, inlen );
+       rc = cipher_encrypt ( h, out, in, inlen );
     }
-    return 0;
+
+    return rc? set_lasterr (rc):0;
 }
 
 
@@ -762,18 +775,24 @@ gcry_cipher_encrypt( GCRY_CIPHER_HD h, byte *out, size_t outsize,
  * inbuf and outbuf may overlap or be the same.
  * Depending on the mode some some contraints apply to NBYTES.
  */
-static void
+static int
 cipher_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf,
                                                        unsigned nbytes )
 {
+    int rc = 0;
+
     switch( c->mode ) {
       case GCRY_CIPHER_MODE_ECB:
-       assert(!(nbytes%c->blocksize));
-       do_ecb_decrypt(c, outbuf, inbuf, nbytes/c->blocksize );
+       if (!(nbytes%c->blocksize))
+            do_ecb_decrypt(c, outbuf, inbuf, nbytes/c->blocksize );
+        else 
+            rc = GCRYERR_INV_ARG;
        break;
       case GCRY_CIPHER_MODE_CBC:
-       assert(!(nbytes%c->blocksize));
-       do_cbc_decrypt(c, outbuf, inbuf, nbytes/c->blocksize );
+       if (!(nbytes%c->blocksize))
+            do_cbc_decrypt(c, outbuf, inbuf, nbytes/c->blocksize );
+        else 
+            rc = GCRYERR_INV_ARG;
        break;
       case GCRY_CIPHER_MODE_CFB:
        do_cfb_decrypt(c, outbuf, inbuf, nbytes );
@@ -786,8 +805,12 @@ cipher_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf,
        if( inbuf != outbuf )
            memmove( outbuf, inbuf, nbytes );
        break;
-      default: log_fatal("cipher_decrypt: invalid mode %d\n", c->mode );
+      default:
+        log_fatal ("cipher_decrypt: invalid mode %d\n", c->mode );
+        rc = GCRYERR_INV_CIPHER_MODE;
+        break;
     }
+    return rc;
 }
 
 
@@ -795,11 +818,13 @@ int
 gcry_cipher_decrypt( GCRY_CIPHER_HD h, byte *out, size_t outsize,
                                 const byte  *in, size_t inlen )
 {
+    int rc;
+
     if( !in ) {
        /* caller requested in-place encryption */
        /* actullay cipher_encrypt() does not need to know about it, but
         * we may chnage this to get better performace */
-       cipher_decrypt( h, out, out, outsize );
+       rc = cipher_decrypt( h, out, out, outsize );
     }
     else {
        if( outsize < inlen )
@@ -807,9 +832,9 @@ gcry_cipher_decrypt( GCRY_CIPHER_HD h, byte *out, size_t outsize,
        /* fixme: check that the inlength is a multipe of the blocksize
         * if a blockoriented mode is used, or modify cipher_encrypt to
         * return an error in this case */
-       cipher_decrypt( h, out, in, inlen );
+       rc = cipher_decrypt( h, out, in, inlen );
     }
-    return 0;
+    return rc? set_lasterr (rc):0;
 }
 
 
@@ -832,9 +857,11 @@ cipher_sync( GCRY_CIPHER_HD c )
 int
 gcry_cipher_ctl( GCRY_CIPHER_HD h, int cmd, void *buffer, size_t buflen)
 {
+    int rc = 0;
+
     switch( cmd ) {
       case GCRYCTL_SET_KEY:
-       cipher_setkey( h, buffer, buflen );
+       rc = cipher_setkey( h, buffer, buflen );
        break;
       case GCRYCTL_SET_IV:
        cipher_setiv( h, buffer, buflen );
@@ -853,9 +880,9 @@ gcry_cipher_ctl( GCRY_CIPHER_HD h, int cmd, void *buffer, size_t buflen)
        break;
 
       default:
-       return set_lasterr( GCRYERR_INV_OP );
+       rc = GCRYERR_INV_OP;
     }
-    return 0;
+    return set_lasterr (rc);
 }
 
 
index f421f39..7d089c5 100644 (file)
@@ -1,5 +1,5 @@
 /* des.c - DES and Triple-DES encryption/decryption Algorithm
- *     Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ *     Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
  *
  * Please see below for more legal information!
  *
@@ -136,6 +136,17 @@ working_memcmp( const char *a, const char *b, size_t n )
 }
 #endif
 
+static void
+burn_stack (int bytes)
+{
+    char buf[64];
+    
+    memset (buf, 0, sizeof buf);
+    bytes -= sizeof buf;
+    if (bytes > 0)
+        burn_stack (bytes);
+}
+
 
 
 /* Some defines/checks to support standalone modules */
@@ -561,6 +572,7 @@ des_setkey (struct _des_ctx *ctx, const byte * key)
     return GCRYERR_SELFTEST;
 
   des_key_schedule (key, ctx->encrypt_subkeys);
+  burn_stack (32);
 
   for(i=0; i<32; i+=2)
     {
@@ -619,6 +631,7 @@ tripledes_set2keys (struct _tripledes_ctx *ctx,
 
   des_key_schedule (key1, ctx->encrypt_subkeys);
   des_key_schedule (key2, &(ctx->decrypt_subkeys[32]));
+  burn_stack (32);
 
   for(i=0; i<32; i+=2)
     {
@@ -656,6 +669,7 @@ tripledes_set3keys (struct _tripledes_ctx *ctx,
   des_key_schedule (key1, ctx->encrypt_subkeys);
   des_key_schedule (key2, &(ctx->decrypt_subkeys[32]));
   des_key_schedule (key3, &(ctx->encrypt_subkeys[64]));
+  burn_stack (32);
 
   for(i=0; i<32; i+=2)
     {
@@ -950,8 +964,11 @@ do_tripledes_setkey ( struct _tripledes_ctx *ctx, byte *key, unsigned keylen )
 
     tripledes_set3keys ( ctx, key, key+8, key+16);
 
-    if( is_weak_key( key ) || is_weak_key( key+8 ) || is_weak_key( key+16 ) )
+    if( is_weak_key( key ) || is_weak_key( key+8 ) || is_weak_key( key+16 ) ) {
+        burn_stack (64);
        return GCRYERR_WEAK_KEY;
+    }
+    burn_stack (64);
 
     return 0;
 }
@@ -961,12 +978,14 @@ static void
 do_tripledes_encrypt( struct _tripledes_ctx *ctx, byte *outbuf, byte *inbuf )
 {
     tripledes_ecb_encrypt ( ctx, inbuf, outbuf );
+    burn_stack (32);
 }
 
 static void
 do_tripledes_decrypt( struct _tripledes_ctx *ctx, byte *outbuf, byte *inbuf )
 {
     tripledes_ecb_decrypt ( ctx, inbuf, outbuf );
+    burn_stack (32);
 }
 
 
index 60b1227..6258430 100644 (file)
@@ -60,6 +60,16 @@ md5_init( MD5_CONTEXT *ctx )
     ctx->count = 0;
 }
 
+static void
+burn_stack (int bytes)
+{
+    char buf[128];
+    
+    memset (buf, 0, sizeof buf);
+    bytes -= sizeof buf;
+    if (bytes > 0)
+        burn_stack (bytes);
+}
 
 
 
@@ -217,6 +227,7 @@ md5_write( MD5_CONTEXT *hd, byte *inbuf, size_t inlen)
 {
     if( hd->count == 64 ) { /* flush the buffer */
        transform( hd, hd->buf );
+        burn_stack (80+6*sizeof(void*));
        hd->count = 0;
        hd->nblocks++;
     }
@@ -229,6 +240,7 @@ md5_write( MD5_CONTEXT *hd, byte *inbuf, size_t inlen)
        if( !inlen )
            return;
     }
+    burn_stack (80+6*sizeof(void*));
 
     while( inlen >= 64 ) {
        transform( hd, inbuf );
@@ -294,6 +306,7 @@ md5_final( MD5_CONTEXT *hd )
     hd->buf[62] = msb >> 16;
     hd->buf[63] = msb >> 24;
     transform( hd, hd->buf );
+    burn_stack (80+6*sizeof(void*));
 
     p = hd->buf;
   #ifdef BIG_ENDIAN_HOST
index da8b01f..9489f0e 100644 (file)
@@ -190,6 +190,7 @@ _gcry_generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
                count1 = 0;
                qbits++;
                progress('>');
+                mpi_free (q);
                q = gen_prime( qbits, 0, 0 );
                goto next_try;
            }
@@ -201,6 +202,7 @@ _gcry_generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
                count2 = 0;
                qbits--;
                progress('<');
+                mpi_free (q);
                q = gen_prime( qbits, 0, 0 );
                goto next_try;
            }
@@ -227,14 +229,14 @@ _gcry_generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
 
     if( ret_factors ) { /* caller wants the factors */
        *ret_factors = gcry_xcalloc( n+2 , sizeof **ret_factors);
+        i = 0;
        if( mode == 1 ) {
-           i = 0;
            (*ret_factors)[i++] = mpi_copy( q_factor );
            for(; i <= n; i++ )
                (*ret_factors)[i] = mpi_copy( factors[i] );
        }
        else {
-           for(i=0; i < n; i++ )
+           for(; i < n; i++ )
                (*ret_factors)[i] = mpi_copy( factors[i] );
        }
     }
@@ -284,6 +286,7 @@ _gcry_generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
     gcry_free( pool );
     gcry_free(perms);
     mpi_free(val_2);
+    mpi_free (q);
     return prime;
 }
 
index f6eec21..91c8082 100644 (file)
@@ -1,5 +1,5 @@
 /* random.c  - random number generator
- *     Copyright (C) 1998, 2000 Free Software Foundation, Inc.
+ *     Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
@@ -138,6 +138,17 @@ initialize(void)
     _gcry_cipher_modules_constructor();
 }
 
+static void
+burn_stack (int bytes)
+{
+    char buf[128];
+    
+    memset (buf, 0, sizeof buf);
+    bytes -= sizeof buf;
+    if (bytes > 0)
+        burn_stack (bytes);
+}
+
 
 void
 _gcry_random_dump_stats()
@@ -280,6 +291,7 @@ mix_pool(byte *pool)
        _gcry_rmd160_mixblock( &md, hashbuf);
        memcpy(p, hashbuf, 20 );
     }
+    burn_stack (200); /* for the rmd160_mixblock() */
 }
 
 void
@@ -601,11 +613,14 @@ _gcry_fast_random_poll()
        #warning There is no RUSAGE_SELF on this system
       #endif
     #else
-    {  struct rusage buf;
+    {  
+        struct rusage buf;
         /* QNX/Neutrino does return ENOSYS - so we just ignore it and
-         * add whatever is in buf */
-        if( getrusage( RUSAGE_SELF, &buf ) && errno != ENOSYS )
-           BUG();
+         * add whatever is in buf.  In a chroot environment it might not
+         * work at all (i.e. because /proc/ is not accessible), so we better 
+         * ugnore all error codes and hope for the best
+         */
+        getrusage (RUSAGE_SELF, &buf );
        add_randomness( &buf, sizeof buf, 1 );
        memset( &buf, 0, sizeof buf );
     }
index ec110dc..fa43adb 100644 (file)
@@ -1706,10 +1706,23 @@ static const u32 rcon[30] = {
 };
 
 \f
+
+static void
+burn_stack (int bytes)
+{
+    char buf[64];
+    
+    memset (buf, 0, sizeof buf);
+    bytes -= sizeof buf;
+    if (bytes > 0)
+        burn_stack (bytes);
+}
+
+
 /* Perform the key setup.
  */  
 static int
-rijndael_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
+do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
 {
     static int initialized = 0;
     static const char *selftest_failed=0;
@@ -1808,6 +1821,15 @@ rijndael_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
     return 0;
 }
 
+static int
+rijndael_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
+{
+    int rc = do_setkey (ctx, key, keylen);
+    burn_stack ( 100 + 16*sizeof(int));
+    return rc;
+}
+
+
 /* make a decryption  key from an encryption key */
 static void
 prepare_decryption( RIJNDAEL_context *ctx )
@@ -1846,7 +1868,7 @@ prepare_decryption( RIJNDAEL_context *ctx )
 \f
 /* Encrypt one block.  A and B may be the same. */
 static void
-rijndael_encrypt (const RIJNDAEL_context *ctx, byte *b, const byte *a)
+do_encrypt (const RIJNDAEL_context *ctx, byte *b, const byte *a)
 {
     int r;
     byte temp[4][4];
@@ -1923,10 +1945,19 @@ rijndael_encrypt (const RIJNDAEL_context *ctx, byte *b, const byte *a)
     *((u32*)(b+12)) ^= *((u32*)rk[ROUNDS][3]);
   #undef rk
 }
+
+static void
+rijndael_encrypt (const RIJNDAEL_context *ctx, byte *b, const byte *a)
+{
+    do_encrypt (ctx, b, a);
+    burn_stack (16 + 2*sizeof(int));
+}
+
+
 \f
 /* Decrypt one block.  a and b may be the same. */
 static void
-rijndael_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a)
+do_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a)
 {
   #define rk  (ctx->keySched2)
     int ROUNDS = ctx->ROUNDS; 
@@ -1935,6 +1966,7 @@ rijndael_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a)
 
     if ( !ctx->decryption_prepared ) {
         prepare_decryption ( ctx );
+        burn_stack (64);
         ctx->decryption_prepared = 1;
     }
     
@@ -2008,6 +2040,13 @@ rijndael_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a)
        *((u32*)(b+12)) ^= *((u32*)rk[0][3]);
   #undef rk
 }
+
+static void
+rijndael_decrypt (RIJNDAEL_context *ctx, byte *b, const byte *a)
+{
+    do_decrypt (ctx, b, a);
+    burn_stack (16+2*sizeof(int));
+}
 \f
 /* Test a single encryption and decryption with each key size. */
 
index cce9d3c..d3f00f2 100644 (file)
  * 1 million times "a"   52783243c1697bdbe16d37f97f68f08325dc1528
  */
 
+static void
+burn_stack (int bytes)
+{
+    char buf[150];
+    
+    memset (buf, 0, sizeof buf);
+    bytes -= sizeof buf;
+    if (bytes > 0)
+        burn_stack (bytes);
+}
+
+
 
 void
 _gcry_rmd160_init( RMD160_CONTEXT *hd )
@@ -405,6 +417,7 @@ rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen)
 {
     if( hd->count == 64 ) { /* flush the buffer */
        transform( hd, hd->buf );
+        burn_stack (108+5*sizeof(void*));
        hd->count = 0;
        hd->nblocks++;
     }
@@ -425,6 +438,7 @@ rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen)
        inlen -= 64;
        inbuf += 64;
     }
+    burn_stack (108+5*sizeof(void*));
     for( ; inlen && hd->count < 64; inlen-- )
        hd->buf[hd->count++] = *inbuf++;
 }
@@ -497,6 +511,7 @@ rmd160_final( RMD160_CONTEXT *hd )
     hd->buf[62] = msb >> 16;
     hd->buf[63] = msb >> 24;
     transform( hd, hd->buf );
+    burn_stack (108+5*sizeof(void*));
 
     p = hd->buf;
   #ifdef BIG_ENDIAN_HOST
index cf3df66..e044240 100644 (file)
@@ -125,7 +125,8 @@ gather_random( void (*add)(const void*, size_t, int), int requester,
                fprintf(stderr,
 _("\n"
 "Not enough random bytes available.  Please do some other work to give\n"
-"the OS a chance to collect more entropy! (Need %d more bytes)\n"), length );
+"the OS a chance to collect more entropy! (Need %d more bytes)\n"),
+                        (int)length );
            warn = 1;
            continue;
        }
index 8ef1cae..bcb1f3f 100644 (file)
@@ -82,6 +82,7 @@
 #endif                         /* _AIX */
 #ifndef __QNX__
 #include <sys/shm.h>
+#include <signal.h>
 #include <sys/signal.h>
 #endif                         /* __QNX__ */
 #include <sys/stat.h>
index 3958320..8f0cfc1 100644 (file)
@@ -50,6 +50,16 @@ typedef struct {
 } SHA1_CONTEXT;
 
 
+static void
+burn_stack (int bytes)
+{
+    char buf[128];
+    
+    memset (buf, 0, sizeof buf);
+    bytes -= sizeof buf;
+    if (bytes > 0)
+        burn_stack (bytes);
+}
 
 
 static void
@@ -214,6 +224,7 @@ sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen)
 {
     if( hd->count == 64 ) { /* flush the buffer */
        transform( hd, hd->buf );
+        burn_stack (88+4*sizeof(void*));
        hd->count = 0;
        hd->nblocks++;
     }
@@ -234,6 +245,7 @@ sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen)
        inlen -= 64;
        inbuf += 64;
     }
+    burn_stack (88+4*sizeof(void*));
     for( ; inlen && hd->count < 64; inlen-- )
        hd->buf[hd->count++] = *inbuf++;
 }
@@ -290,6 +302,7 @@ sha1_final(SHA1_CONTEXT *hd)
     hd->buf[62] = lsb >>  8;
     hd->buf[63] = lsb     ;
     transform( hd, hd->buf );
+    burn_stack (88+4*sizeof(void*));
 
     p = hd->buf;
   #ifdef BIG_ENDIAN_HOST
index 7152492..c4b107d 100644 (file)
@@ -1,5 +1,5 @@
 /* tiger.c  -  The TIGER hash function
- *     Copyright (C) 1998 Free Software Foundation, Inc.
+ *     Copyright (C) 1998, 2001 Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
@@ -590,44 +590,16 @@ static u64 sbox4[256] = {
 
 
 static void
-print_abc( const char *text, u64 a, u64 b, u64 c )
+burn_stack (int bytes)
 {
-/*printf("%s: %08X%08X %08X%08X %08X%08X\n",
-        text,
-        (u32)(a>>32),
-        (u32)(a),
-        (u32)(b>>32),
-        (u32)(b),
-        (u32)(c>>32),
-        (u32)(c) );*/
+    char buf[256];
+    
+    memset (buf, 0, sizeof buf);
+    bytes -= sizeof buf;
+    if (bytes > 0)
+        burn_stack (bytes);
 }
 
-static void
-print_data( const char *text, u64 a, u64 b, u64 c,
-                             u64 d, u64 e, u64 f,
-                             u64 g, u64 h )
-{
-/*printf("%s: %08X%08X %08X%08X %08X%08X %08X%08X\n"
-        "%s  %08X%08X %08X%08X %08X%08X %08X%08X\n",
-        text,
-        (u32)(a>>32),
-        (u32)(a),
-        (u32)(b>>32),
-        (u32)(b),
-        (u32)(c>>32),
-        (u32)(c),
-        (u32)(d>>32),
-        (u32)(d),
-        text,
-        (u32)(e>>32),
-        (u32)(e),
-        (u32)(f>>32),
-        (u32)(f),
-        (u32)(g>>32),
-        (u32)(g),
-        (u32)(h>>32),
-        (u32)(h) );*/
-}
 
 
 static void
@@ -736,17 +708,11 @@ transform( TIGER_CONTEXT *hd, byte *data )
     b = bb = hd->b;
     c = cc = hd->c;
 
-    print_data(" key0", x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7] );
-    print_abc(" init", a, b, c );
     pass( &a, &b, &c, x, 5);
-    print_abc("pass1", a, b, c );
     key_schedule( x );
     pass( &c, &a, &b, x, 7);
-    print_abc("pass2", a, b, c );
     key_schedule( x );
     pass( &b, &c, &a, x, 9);
-    print_abc("pass3", a, b, c );
-
 
     /* feedforward */
     a ^= aa;
@@ -768,6 +734,7 @@ tiger_write( TIGER_CONTEXT *hd, byte *inbuf, size_t inlen)
 {
     if( hd->count == 64 ) { /* flush the buffer */
        transform( hd, hd->buf );
+        burn_stack (21*8+11*sizeof(void*));
        hd->count = 0;
        hd->nblocks++;
     }
@@ -788,6 +755,7 @@ tiger_write( TIGER_CONTEXT *hd, byte *inbuf, size_t inlen)
        inlen -= 64;
        inbuf += 64;
     }
+    burn_stack (21*8+11*sizeof(void*));
     for( ; inlen && hd->count < 64; inlen-- )
        hd->buf[hd->count++] = *inbuf++;
 }
@@ -841,6 +809,7 @@ tiger_final( TIGER_CONTEXT *hd )
     hd->buf[62] = msb >> 16;
     hd->buf[63] = msb >> 24;
     transform( hd, hd->buf );
+    burn_stack (21*8+11*sizeof(void*));
 
     p = hd->buf;
   #ifdef BIG_ENDIAN_HOST
index a7cbb30..eb41d87 100644 (file)
@@ -544,11 +544,24 @@ static byte calc_sb_tbl[512] = {
    x += y; y += x; ctx->a[j] = x; \
    ctx->a[(j) + 1] = (y << 9) + (y >> 23)
 \f
+
+static void
+burn_stack (int bytes)
+{
+    char buf[64];
+    
+    memset (buf, 0, sizeof buf);
+    bytes -= sizeof buf;
+    if (bytes > 0)
+        burn_stack (bytes);
+}
+
+
 /* Perform the key setup.  Note that this works only with 128- and 256-bit
  * keys, despite the API that looks like it might support other sizes. */
 
 static int
-twofish_setkey (TWOFISH_context *ctx, const byte *key, const unsigned keylen)
+do_twofish_setkey (TWOFISH_context *ctx, const byte *key, const unsigned keylen)
 {
     int i, j, k;
 
@@ -681,6 +694,16 @@ twofish_setkey (TWOFISH_context *ctx, const byte *key, const unsigned keylen)
 
     return 0;
 }
+
+static int
+twofish_setkey (TWOFISH_context *ctx, const byte *key, unsigned int keylen)
+{
+    int rc = do_twofish_setkey (ctx, key, keylen);
+    burn_stack (23+6*sizeof(void*));
+    return rc;
+}
+
+
 \f
 /* Macros to compute the g() function in the encryption and decryption
  * rounds.  G1 is the straight g() function; G2 includes the 8-bit
@@ -743,7 +766,7 @@ twofish_setkey (TWOFISH_context *ctx, const byte *key, const unsigned keylen)
 /* Encrypt one block.  in and out may be the same. */
 
 static void
-twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
+do_twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
 {
    /* The four 32-bit chunks of the text. */
    u32 a, b, c, d;
@@ -773,11 +796,19 @@ twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
    OUTUNPACK (2, a, 6);
    OUTUNPACK (3, b, 7);
 }
+
+static void
+twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
+{
+    do_twofish_encrypt (ctx, out, in);
+    burn_stack (24+3*sizeof (void*));
+}
+
 \f
 /* Decrypt one block.  in and out may be the same. */
 
 static void
-twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
+do_twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
 {
    /* The four 32-bit chunks of the text. */
    u32 a, b, c, d;
@@ -807,6 +838,14 @@ twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
    OUTUNPACK (2, c, 2);
    OUTUNPACK (3, d, 3);
 }
+
+static void
+twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in)
+{
+    do_twofish_decrypt (ctx, out, in);
+    burn_stack (24+3*sizeof (void*));
+}
+
 \f
 /* Test a single encryption and decryption with each key size. */
 
index a1ff1da..c4526d1 100644 (file)
@@ -258,21 +258,14 @@ esac
 AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME")
 
 dnl  Fixme: Are these the best flags for OpenBSD????
-dnl (I have removed the -lc from * ...CFLAGS for test purposes.)
 case "${target}" in
-    *-openbsd*)
+    *-openbsd* | *-netbsd*)
         NAME_OF_DEV_RANDOM="/dev/srandom"
         NAME_OF_DEV_URANDOM="/dev/urandom"
         DYNLINK_MOD_CFLAGS="-shared -rdynamic $CFLAGS_PIC -Wl,-Bshareable -Wl,-x"
         ;;
 
-    *-netbsd*)
-        NAME_OF_DEV_RANDOM="/dev/random"
-        NAME_OF_DEV_URANDOM="/dev/urandom"
-        DYNLINK_MOD_CFLAGS="-shared -rdynamic $CFLAGS_PIC -Wl,-Bshareable -Wl,-x"
-        ;;
-
-    *-solaris*)
+    *-solaris* | *-irix* | *-dec-osf* )
         NAME_OF_DEV_RANDOM="/dev/random"
         NAME_OF_DEV_URANDOM="/dev/random"
         DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC"
@@ -725,5 +718,6 @@ doc/Makefile
 doc/version.sgml
 src/Makefile
 src/libgcrypt-config
+tests/Makefile
 ])
 
diff --git a/libgcrypt.txt b/libgcrypt.txt
new file mode 100644 (file)
index 0000000..1367761
--- /dev/null
@@ -0,0 +1,93 @@
+%%comments:
+Copyright (C) 2001 Free Software Foundation, Inc.
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
+Texts. A copy of the license is included in the file COPYING.
+
+%%name: Libgcrypt
+
+%%short-description: Cryptographic library
+
+%%full-description: This is a general purpose cryptographic library
+based on the code from GnuPG.  It provides functions for all
+cryptograhic building blocks: symmetric ciphers
+(AES,DES,Blowfish,CAST5,Twofish,Arcfour), hash algorithms (MD5,
+RIPE-MD160, SHA-1, TIGER-192), MACs (HMAC for all hash algorithms),
+public key algorithms (RSA, ElGamal, DSA), large integer functions,
+random numbers and a lot of supporting functions.
+
+%%category: security, libraries
+
+%%license: GPL
+%%license verified by: 
+%%license verified on: 
+
+%%maintainer: g10 Code GmbH <libgcrypt@g10code.com>
+
+%%updated: 2001-06-01
+
+%%keywords: encryption, public key, digital signature, hash
+
+%%interface:
+
+%%programs: 
+
+%%GNU: (I am not sure - it is a spring-off from GnuPG)
+
+%%web-page: http://www.gnupg.org
+
+%%support: paid extension/consulting from http://www.g10code.com
+
+%%doc: English programmer reference in Texinfo, Postscript, HTML included
+
+%%developers:  Matthew Skala, Michael Roth, Niklas Hernaeus, Remi
+Guyomarch, Werner Koch <wk@gnupg.org>.
+
+%%contributors: 
+
+%%sponsors: 
+
+%%source: ftp://ftp.gnupg.org/gcrypt/alpha/libgcrypt/
+
+%%debian:
+
+%%redhat:
+
+%%repository:  See http://www.gnupg.org/cvs-access.html
+
+%%related: 
+
+%%source-language: C
+
+%%supported-languages: C, C++
+
+%%use-requirements:
+
+%%build-prerequisites:
+
+%%weak-prerequisites: 
+
+%%source-prerequisites:
+
+%%version: 1.1.3 alpha released on 2001-05-31
+
+%%announce-list: announce@gnupg.org  announce-request@gnupg.org
+
+%%announce-news:
+
+%%help-list: 
+
+%%help-news:
+
+%%dev-list: gcrypt-devel@gnupg.org  gcrypt-devel-request@gnupg.org
+
+%%dev-news:
+
+%%bug-list: 
+
+%%bug-database: 
+
+%%entry written by: Werner Koch <wk@gnupg.org>
\ No newline at end of file
index 2ba366d..fbc03f4 100644 (file)
@@ -1,3 +1,11 @@
+2001-08-03  Werner Koch  <wk@gnupg.org>
+
+       * global.c (gcry_strerror): Updated list of error codes.
+
+2001-07-23  Werner Koch  <wk@gnupg.org>
+
+       * gcrypt.h: Replaced the last ulong.  Noted by Rami Lehti.
+
 2001-05-31  Werner Koch  <wk@gnupg.org>
 
        * gcrypt.h, mpi.h: Made some mpi functions public.
index 63f121d..b13e387 100644 (file)
@@ -1,5 +1,5 @@
 /* gcrypt.h -  GNU digital encryption library interface
- *     Copyright (C) 1998 Free Software Foundation, Inc.
+ *     Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
@@ -224,7 +224,7 @@ void     gcry_mpi_add(GCRY_MPI w, GCRY_MPI u, GCRY_MPI v);
 void     gcry_mpi_add_ui(GCRY_MPI w, GCRY_MPI u, unsigned long v );
 void     gcry_mpi_addm(GCRY_MPI w, GCRY_MPI u, GCRY_MPI v, GCRY_MPI m);
 void     gcry_mpi_sub( GCRY_MPI w, GCRY_MPI u, GCRY_MPI v);
-void     gcry_mpi_sub_ui(GCRY_MPI w, GCRY_MPI u, ulong v );
+void     gcry_mpi_sub_ui(GCRY_MPI w, GCRY_MPI u, unsigned long v );
 void     gcry_mpi_subm( GCRY_MPI w, GCRY_MPI u, GCRY_MPI v, GCRY_MPI m);
 void     gcry_mpi_mul_ui(GCRY_MPI w, GCRY_MPI u, unsigned long v );
 void     gcry_mpi_mul_2exp( GCRY_MPI w, GCRY_MPI u, unsigned long cnt);
index 8466dac..f78b6f7 100644 (file)
@@ -211,23 +211,36 @@ gcry_strerror( int ec )
        ec = gcry_errno();
   #define X(n,a) case GCRYERR_##n : s = a; break;
     switch( ec ) {
-      X(SUCCESS,       N_("no error"))
-      X(GENERAL,       N_("general error"))
+      X(SUCCESS,        N_("no error"))
+      X(GENERAL,        N_("general error"))
+
+      X(INV_PK_ALGO,   N_("invalid public key algorithm"))
+      X(INV_MD_ALGO,   N_("invalid hash algorithm"))
+      X(BAD_PUBLIC_KEY ,N_("bad public key"))
+      X(BAD_SECRET_KEY ,N_("bad secret key"))
+      X(BAD_SIGNATURE , N_("bad signature"))
+
+      X(INV_CIPHER_ALGO,N_("invalid cipher algorithm"))
+      X(BAD_MPI,        N_("bad big integer"))
+      X(WRONG_PK_ALGO, N_("unusable public key algorithm"))
+      X(WEAK_KEY,      N_("weak encryption key"))
+      X(INV_KEYLEN,     N_("invalid key length"))
+      X(INV_ARG,       N_("invalid argument"))
+      X(SELFTEST,       N_("selftest failed"))
+
       X(INV_OP,        N_("invalid operation code or ctl command"))
       X(NO_MEM,        N_("out of core"))
-      X(INV_ARG,       N_("invalid argument"))
       X(INTERNAL,      N_("internal error"))
       X(EOF,           N_("EOF"))
+      X(INV_OBJ,       N_("an object is not valid"))
       X(TOO_SHORT,     N_("provided buffer too short"))
       X(TOO_LARGE,     N_("object is too large"))
-      X(INV_OBJ,       N_("an object is not valid"))
-      X(WEAK_KEY,      N_("weak encryption key"))
-      X(INV_PK_ALGO,   N_("invalid public key algorithm"))
-      X(INV_CIPHER_ALGO,N_("invalid cipher algorithm"))
-      X(INV_MD_ALGO,   N_("invalid hash algorithm"))
-      X(WRONG_PK_ALGO, N_("unusable public key algorithm"))
+      X(NO_OBJ,         N_("no object"))
+      X(NOT_IMPL,       N_("not implemented"))
       X(CONFLICT,      N_("conflict"))
       X(INV_CIPHER_MODE,N_("invalid cipher mode"))
+
+
       default:
        sprintf( buf, "ec=%d", ec );
        s = buf;
diff --git a/tests/ChangeLog b/tests/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644 (file)
index 0000000..9875feb
--- /dev/null
@@ -0,0 +1,38 @@
+# Copyright (C) 2001 Free Software Foundation, Inc.
+#
+# This file is part of Libgcrypt.
+#
+# Libgcrypt is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# Libgcrypt is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+## Process this file with automake to produce Makefile.in
+
+
+# TESTS_ENVIRONMENT =  
+
+TESTS = basic
+
+EXTRA_DIST = 
+
+INCLUDES = 
+LDADD = ../src/libgcrypt.la
+
+noinst_PROGRAMS = $(TESTS) 
+
+
+
+
+
+
+
diff --git a/tests/basic.c b/tests/basic.c
new file mode 100644 (file)
index 0000000..c850ca6
--- /dev/null
@@ -0,0 +1,166 @@
+/* basic.c  -  basic regression tests
+ *     Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include "../src/gcrypt.h"
+
+static int error_count;
+
+static void
+fail ( const char *format, ... )
+{
+    va_list arg_ptr ;
+
+    va_start( arg_ptr, format ) ;
+    vfprintf (stderr, format, arg_ptr );
+    va_end(arg_ptr);
+    error_count++;
+}
+
+static void
+die ( const char *format, ... )
+{
+    va_list arg_ptr ;
+
+    va_start( arg_ptr, format ) ;
+    vfprintf (stderr, format, arg_ptr );
+    va_end(arg_ptr);
+    exit (1);
+}
+
+
+static void
+check_one_cipher (int algo, int mode)
+{
+    GCRY_CIPHER_HD hd;
+    char key[32], plain[16], in[16], out[16];
+    int keylen;
+
+    memcpy (key, "0123456789abcdef.,;/[]{}-=ABCDEF", 32);
+    memcpy (plain, "foobar42FOOBAR17", 16);
+
+    keylen = gcry_cipher_get_algo_keylen (algo);
+    if (keylen < 40/8 || keylen > 32 ) {
+        fail ("algo %d, mode %d, keylength problem (%d)\n",
+              algo, mode, keylen );
+        return;
+    }
+
+    hd = gcry_cipher_open (algo, mode, 0);
+    if (!hd) {
+        fail ("algo %d, mode %d, grcy_open_cipher failed: %s\n",
+              algo, mode, gcry_strerror (-1) );
+        return;
+    }
+
+    
+    if (gcry_cipher_setkey (hd, key, keylen)) { 
+        fail ("algo %d, mode %d, gcry_cipher_setkey failed: %s\n",
+              algo, mode, gcry_strerror (-1) );
+        gcry_cipher_close (hd);
+        return;
+    }
+    
+    if ( gcry_cipher_encrypt (hd, out, 16, plain, 16)) { 
+        fail ("algo %d, mode %d, gcry_cipher_encrypt failed: %s\n",
+              algo, mode, gcry_strerror (-1) );
+        gcry_cipher_close (hd);
+        return;
+    }
+
+    gcry_cipher_close (hd);
+    hd = gcry_cipher_open (algo, mode, 0);
+    if (!hd) {
+        fail ("algo %d, mode %d, grcy_open_cipher failed: %s\n",
+              algo, mode, gcry_strerror (-1) );
+        return;
+    }
+
+    if (gcry_cipher_setkey (hd, key, keylen)) { 
+        fail ("algo %d, mode %d, gcry_cipher_setkey[2] failed: %s\n",
+              algo, mode, gcry_strerror (-1) );
+        gcry_cipher_close (hd);
+        return;
+    }
+    
+    if ( gcry_cipher_decrypt (hd, in, 16, out, 16)) { 
+        fail ("algo %d, mode %d, gcry_cipher_decrypt failed: %s\n",
+              algo, mode, gcry_strerror (-1) );
+        gcry_cipher_close (hd);
+        return;
+    }
+
+    gcry_cipher_close (hd);
+
+    if ( memcmp (plain, in, 16) )
+        fail ("algo %d, mode %d, encrypt-decrypt mismatch\n", algo, mode);
+}
+
+
+static void
+check_ciphers (void)
+{
+    static int algos[] = {
+        GCRY_CIPHER_3DES,
+        GCRY_CIPHER_CAST5,
+        GCRY_CIPHER_BLOWFISH,
+        GCRY_CIPHER_RIJNDAEL,
+        GCRY_CIPHER_RIJNDAEL192,
+        GCRY_CIPHER_RIJNDAEL256,
+        GCRY_CIPHER_TWOFISH,
+        0
+    };
+    int i;
+
+    for (i=0; algos[i]; i++ ) {
+        check_one_cipher (algos[i], GCRY_CIPHER_MODE_ECB);
+        check_one_cipher (algos[i], GCRY_CIPHER_MODE_CFB);
+        check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC);
+    }
+
+    check_one_cipher (GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM);
+    /* we have now run all cipher's selftests */
+    /* TODO: add some extra encryption to test the higher level functions */
+
+}
+
+
+static void
+check_digests ()
+{
+    /* TODO */
+}
+
+
+int
+main (int argc, char **argv)
+{
+    if (!gcry_check_version (GCRYPT_VERSION))
+        die ("Version mismatch\n");
+    check_ciphers ();
+    check_digests ();
+
+    return error_count? 1:0;
+}
+
+