some cleanups
authorWerner Koch <wk@gnupg.org>
Thu, 19 Mar 1998 15:27:26 +0000 (15:27 +0000)
committerWerner Koch <wk@gnupg.org>
Thu, 19 Mar 1998 15:27:26 +0000 (15:27 +0000)
12 files changed:
THANKS
cipher/ChangeLog
cipher/blowfish.c
cipher/dsa.c
cipher/elgamal.c
cipher/md.c
cipher/md.h
cipher/random.c
cipher/random.h
configure.in
mpi/ChangeLog
mpi/mpi-bit.c

diff --git a/THANKS b/THANKS
index 4d04365..4b564dd 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -12,6 +12,7 @@ Hendrik Buschkamp     buschkamp@rheumanet.org
 James Troup            J.J.Troup@scm.brad.ac.uk
 Jean-loup Gailly       gzip@prep.ai.mit.edu
 Jens Bachem            bachem@rrz.uni-koeln.de
+Marco d'Itri            md@linux.it
 Mark Adler             madler@alumni.caltech.edu
 Martin Schulte         schulte@thp.uni-koeln.de
 Peter Gutmann          pgut001@cs.auckland.ac.nz
index 0a316d1..fbd7bed 100644 (file)
@@ -1,3 +1,35 @@
+Thu Mar 19 13:54:48 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * blowfish.c (blowfish_decode_cfb): changed XOR operation
+       (blowfish_encode_cfb): Ditto.
+
+Thu Mar 12 14:04:05 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * sha1.c (transform): Rewrote
+
+       * blowfish.c (encrypt): Unrolled for rounds == 16
+       (decrypt): Ditto.
+
+Tue Mar 10 16:32:08 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * rmd160.c (transform): Unrolled the loop.
+
+Tue Mar 10 13:05:14 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * random.c (read_pool): Add pool_balance stuff.
+       (get_random_bits): New.
+
+       * elgamal.c (elg_generate): Now uses get_random_bits to generate x.
+
+
+Tue Mar 10 11:33:51 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * md.c (md_digest_length): New.
+
+Tue Mar 10 11:27:41 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * dsa.c (dsa_verify): Works.
+
 Mon Mar  9 12:59:08 1998  Werner Koch  (wk@isil.d.shuttle.de)
 
        * dsa.c, dsa.h: Removed some unused code.
index 55b9902..09b1576 100644 (file)
@@ -227,8 +227,7 @@ static const u32 ps[BLOWFISH_ROUNDS+2] = {
 
 
 
-
-
+#if BLOWFISH_ROUNDS != 16
 static inline u32
 function_F( BLOWFISH_context *bc, u32 x )
 {
@@ -248,48 +247,130 @@ function_F( BLOWFISH_context *bc, u32 x )
 
     return ((bc->s0[a] + bc->s1[b]) ^ bc->s2[c] ) + bc->s3[d];
 }
+#endif
+
+#ifdef BIG_ENDIAN_HOST
+  #define F(x) ((( s0[((byte*)&x)[0]] + s1[((byte*)&x)[1]])     \
+                  ^ s2[((byte*)&x)[2]]) + s3[((byte*)&x)[3]] )
+#else
+  #define F(x) ((( s0[((byte*)&x)[3]] + s1[((byte*)&x)[2]])     \
+                  ^ s2[((byte*)&x)[1]]) + s3[((byte*)&x)[0]] )
+#endif
+#define R(l,r,i)  do { l ^= p[i]; r ^= F(l); } while(0)
 
 
 static void
 encrypt(  BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
 {
-    u32 xl, xr, temp;
+  #if BLOWFISH_ROUNDS == 16
+    u32 xl, xr, *s0, *s1, *s2, *s3, *p;
+
+    xl = *ret_xl;
+    xr = *ret_xr;
+    p = bc->p;
+    s0 = bc->s0;
+    s1 = bc->s1;
+    s2 = bc->s2;
+    s3 = bc->s3;
+
+    R( xl, xr, 0);
+    R( xr, xl, 1);
+    R( xl, xr, 2);
+    R( xr, xl, 3);
+    R( xl, xr, 4);
+    R( xr, xl, 5);
+    R( xl, xr, 6);
+    R( xr, xl, 7);
+    R( xl, xr, 8);
+    R( xr, xl, 9);
+    R( xl, xr, 10);
+    R( xr, xl, 11);
+    R( xl, xr, 12);
+    R( xr, xl, 13);
+    R( xl, xr, 14);
+    R( xr, xl, 15);
+
+    xl ^= p[BLOWFISH_ROUNDS];
+    xr ^= p[BLOWFISH_ROUNDS+1];
+
+    *ret_xl = xr;
+    *ret_xr = xl;
+
+  #else
+    u32 xl, xr, temp, *p;
     int i;
 
     xl = *ret_xl;
     xr = *ret_xr;
+    p = bc->p;
 
     for(i=0; i < BLOWFISH_ROUNDS; i++ ) {
-       xl ^= bc->p[i];
+       xl ^= p[i];
        xr ^= function_F(bc, xl);
        temp = xl;
        xl = xr;
        xr = temp;
     }
-
     temp = xl;
     xl = xr;
     xr = temp;
 
-    xr ^= bc->p[BLOWFISH_ROUNDS];
-    xl ^= bc->p[BLOWFISH_ROUNDS+1];
+    xr ^= p[BLOWFISH_ROUNDS];
+    xl ^= p[BLOWFISH_ROUNDS+1];
 
     *ret_xl = xl;
     *ret_xr = xr;
+  #endif
 }
 
 
 static void
 decrypt(  BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
 {
-    u32 xl, xr, temp;
+  #if BLOWFISH_ROUNDS == 16
+    u32 xl, xr, *s0, *s1, *s2, *s3, *p;
+
+    xl = *ret_xl;
+    xr = *ret_xr;
+    p = bc->p;
+    s0 = bc->s0;
+    s1 = bc->s1;
+    s2 = bc->s2;
+    s3 = bc->s3;
+
+    R( xl, xr, 17);
+    R( xr, xl, 16);
+    R( xl, xr, 15);
+    R( xr, xl, 14);
+    R( xl, xr, 13);
+    R( xr, xl, 12);
+    R( xl, xr, 11);
+    R( xr, xl, 10);
+    R( xl, xr, 9);
+    R( xr, xl, 8);
+    R( xl, xr, 7);
+    R( xr, xl, 6);
+    R( xl, xr, 5);
+    R( xr, xl, 4);
+    R( xl, xr, 3);
+    R( xr, xl, 2);
+
+    xl ^= p[1];
+    xr ^= p[0];
+
+    *ret_xl = xr;
+    *ret_xr = xl;
+
+  #else
+    u32 xl, xr, temp, *p;
     int i;
 
     xl = *ret_xl;
     xr = *ret_xr;
+    p = bc->p;
 
     for(i=BLOWFISH_ROUNDS+1; i > 1; i-- ) {
-       xl ^= bc->p[i];
+       xl ^= p[i];
        xr ^= function_F(bc, xl);
        temp = xl;
        xl = xr;
@@ -300,13 +381,17 @@ decrypt(  BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
     xl = xr;
     xr = temp;
 
-    xr ^= bc->p[1];
-    xl ^= bc->p[0];
+    xr ^= p[1];
+    xl ^= p[0];
 
     *ret_xl = xl;
     *ret_xr = xr;
+  #endif
 }
 
+#undef F
+#undef R
+
 static void
 encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
 {
@@ -539,6 +624,7 @@ blowfish_encode_cfb( BLOWFISH_context *c, byte *outbuf,
                                          byte *inbuf, unsigned nbytes)
 {
     unsigned n;
+    int is_aligned;
 
     if( c->count ) {  /* must make a full block first */
        assert( c->count < BLOWFISH_BLOCKSIZE );
@@ -560,8 +646,26 @@ blowfish_encode_cfb( BLOWFISH_context *c, byte *outbuf,
            return;
     }
     assert(!c->count);
+    is_aligned = !((ulong)inbuf % SIZEOF_UNSIGNED_LONG);
     while( nbytes >= BLOWFISH_BLOCKSIZE ) {
-       xorblock( outbuf, c->eniv, inbuf, BLOWFISH_BLOCKSIZE);
+       if( is_aligned ) {
+         #if SIZEOF_UNSIGNED_LONG == BLOWFISH_BLOCKSIZE
+           *(ulong*)outbuf = *(ulong*)c->eniv ^ *(ulong*)inbuf;
+         #elif (2*SIZEOF_UNSIGNED_LONG) == BLOWFISH_BLOCKSIZE
+           ((ulong*)outbuf)[0] = ((ulong*)c->eniv)[0] ^ ((ulong*)inbuf)[0];
+           ((ulong*)outbuf)[1] = ((ulong*)c->eniv)[1] ^ ((ulong*)inbuf)[1];
+         #elif (4*SIZEOF_UNSIGNED_LONG) == BLOWFISH_BLOCKSIZE
+           ((ulong*)outbuf)[0] = ((ulong*)c->eniv)[0] ^ ((ulong*)inbuf)[0];
+           ((ulong*)outbuf)[1] = ((ulong*)c->eniv)[1] ^ ((ulong*)inbuf)[1];
+           ((ulong*)outbuf)[2] = ((ulong*)c->eniv)[2] ^ ((ulong*)inbuf)[2];
+           ((ulong*)outbuf)[3] = ((ulong*)c->eniv)[3] ^ ((ulong*)inbuf)[3];
+         #else
+           #error Please remove this info line.
+           xorblock( outbuf, c->eniv, inbuf, BLOWFISH_BLOCKSIZE);
+         #endif
+       }
+       else  /* not aligned */
+           xorblock( outbuf, c->eniv, inbuf, BLOWFISH_BLOCKSIZE);
        memcpy( c->iv, outbuf, BLOWFISH_BLOCKSIZE);
        encrypt_block( c, c->eniv, c->iv );
        nbytes -= BLOWFISH_BLOCKSIZE;
@@ -583,6 +687,7 @@ blowfish_decode_cfb( BLOWFISH_context *c, byte *outbuf,
                                          byte *inbuf, unsigned nbytes)
 {
     unsigned n;
+    int is_aligned;
 
     if( c->count ) {  /* must make a full block first */
        assert( c->count < BLOWFISH_BLOCKSIZE );
@@ -605,9 +710,27 @@ blowfish_decode_cfb( BLOWFISH_context *c, byte *outbuf,
     }
 
     assert(!c->count);
+    is_aligned = !((ulong)inbuf % SIZEOF_UNSIGNED_LONG);
     while( nbytes >= BLOWFISH_BLOCKSIZE ) {
        memcpy( c->iv, inbuf, BLOWFISH_BLOCKSIZE);
-       xorblock( outbuf, c->eniv, inbuf, BLOWFISH_BLOCKSIZE);
+       if( is_aligned ) {
+         #if SIZEOF_UNSIGNED_LONG == BLOWFISH_BLOCKSIZE
+           *(ulong*)outbuf = *(ulong*)c->eniv ^ *(ulong*)inbuf;
+         #elif (2*SIZEOF_UNSIGNED_LONG) == BLOWFISH_BLOCKSIZE
+           ((ulong*)outbuf)[0] = ((ulong*)c->eniv)[0] ^ ((ulong*)inbuf)[0];
+           ((ulong*)outbuf)[1] = ((ulong*)c->eniv)[1] ^ ((ulong*)inbuf)[1];
+         #elif (4*SIZEOF_UNSIGNED_LONG) == BLOWFISH_BLOCKSIZE
+           ((ulong*)outbuf)[0] = ((ulong*)c->eniv)[0] ^ ((ulong*)inbuf)[0];
+           ((ulong*)outbuf)[1] = ((ulong*)c->eniv)[1] ^ ((ulong*)inbuf)[1];
+           ((ulong*)outbuf)[2] = ((ulong*)c->eniv)[2] ^ ((ulong*)inbuf)[2];
+           ((ulong*)outbuf)[3] = ((ulong*)c->eniv)[3] ^ ((ulong*)inbuf)[3];
+         #else
+           #error Please remove this info line.
+           xorblock( outbuf, c->eniv, inbuf, BLOWFISH_BLOCKSIZE);
+         #endif
+       }
+       else  /* not aligned */
+           xorblock( outbuf, c->eniv, inbuf, BLOWFISH_BLOCKSIZE);
        encrypt_block( c, c->eniv, c->iv );
        nbytes -= BLOWFISH_BLOCKSIZE;
        inbuf += BLOWFISH_BLOCKSIZE;
@@ -622,3 +745,4 @@ blowfish_decode_cfb( BLOWFISH_context *c, byte *outbuf,
 
 }
 
+
index 8024ac0..8eb0cec 100644 (file)
 #include "cipher.h"
 #include "dsa.h"
 
+/****************
+ * Generate a random secret exponent k less than q
+ */
+static MPI
+gen_k( MPI q )
+{
+    MPI k = mpi_alloc_secure( mpi_get_nlimbs(q) );
+    unsigned nbits = mpi_get_nbits(q);
+
+    if( DBG_CIPHER )
+       log_debug("choosing a random k ");
+    for(;;) {
+       if( DBG_CIPHER )
+           fputc('.', stderr);
+       mpi_set_bytes( k, nbits , get_random_byte, 1 );
+       if( !(mpi_cmp( k, q ) < 0) )  /* check: k < q */
+           continue; /* no  */
+       if( !(mpi_cmp_ui( k, 0 ) > 0) ) /* check: k > 0 */
+           continue; /* no */
+       break;  /* okay */
+    }
+    if( DBG_CIPHER )
+       fputc('\n', stderr);
+
+    return k;
+}
 
 void
 dsa_free_public_key( DSA_public_key *pk )
@@ -67,12 +93,36 @@ dsa_check_secret_key( DSA_secret_key *sk )
 
 
 /****************
- * Make a DSA signature out of INPUT
+ * Make a DSA signature from HASH and put it into r and s.
  */
 
 void
-dsa_sign(MPI r, MPI s, MPI input, DSA_secret_key *skey )
+dsa_sign(MPI r, MPI s, MPI hash, DSA_secret_key *skey )
 {
+    MPI k;
+    MPI kinv;
+    MPI tmp;
+
+    /* select a random k with 0 < k < q */
+    k = gen_k( skey->q );
+
+    /* r = (a^k mod p) mod q */
+    mpi_powm( r, skey->g, k, skey->p );
+    mpi_fdiv_r( r, r, skey->q );
+
+    /* kinv = k^(-1) mod q */
+    kinv = mpi_alloc( mpi_get_nlimbs(k) );
+    mpi_invm(kinv, k, skey->q );
+
+    /* s = (kinv * ( hash + x * r)) mod q */
+    tmp = mpi_alloc( mpi_get_nlimbs(skey->p) );
+    mpi_mul( tmp, skey->x, r );
+    mpi_add( tmp, tmp, hash );
+    mpi_mulm( s , kinv, tmp, skey->q );
+
+    mpi_free(k);
+    mpi_free(kinv);
+    mpi_free(tmp);
 }
 
 
@@ -80,7 +130,7 @@ dsa_sign(MPI r, MPI s, MPI input, DSA_secret_key *skey )
  * Returns true if the signature composed from R and S is valid.
  */
 int
-dsa_verify(MPI r, MPI s, MPI input, DSA_public_key *pkey )
+dsa_verify(MPI r, MPI s, MPI hash, DSA_public_key *pkey )
 {
     int rc;
     MPI w, u1, u2, v;
@@ -100,8 +150,8 @@ dsa_verify(MPI r, MPI s, MPI input, DSA_public_key *pkey )
     /* w = s^(-1) mod q */
     mpi_invm( w, s, pkey->q );
 
-    /* u1 = (input * w) mod q */
-    mpi_mulm( u1, input, w, pkey->q );
+    /* u1 = (hash * w) mod q */
+    mpi_mulm( u1, hash, w, pkey->q );
 
     /* u2 = r * w mod q  */
     mpi_mulm( u2, r, w, pkey->q );
index 2141db0..b211d7f 100644 (file)
@@ -152,9 +152,14 @@ elg_generate( ELG_public_key *pk, ELG_secret_key *sk,
     if( DBG_CIPHER )
        log_debug("choosing a random x ");
     do {
+       byte *rndbuf;
        if( DBG_CIPHER )
            fputc('.', stderr);
-       mpi_set_bytes( x, nbits, get_random_byte, 2 );
+       rndbuf = get_random_bits( nbits, 2, 1 );
+       mpi_set_buffer( x, rndbuf, (nbits+7)/8, 0 );
+       m_free(rndbuf);
+       mpi_clear_highbit( x, nbits+1 );
+       log_mpidump("  x: ", x );
     } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) );
 
     y = mpi_alloc(nbits/BITS_PER_MPI_LIMB);
index b193996..0f49443 100644 (file)
@@ -170,6 +170,21 @@ md_get_algo( MD_HANDLE a )
     return 0;
 }
 
+/****************
+ * Return the length of the digest
+ */
+int
+md_digest_length( int algo )
+{
+    switch( algo ) {
+      case DIGEST_ALGO_RMD160:
+      case DIGEST_ALGO_SHA1:
+       return 20;
+      default:
+       return 16;
+    }
+}
+
 
 const byte *
 md_asn_oid( int algo, size_t *asnlen, size_t *mdlen )
index dcdfe80..961f617 100644 (file)
@@ -58,6 +58,7 @@ void md_write( MD_HANDLE a, byte *inbuf, size_t inlen);
 void md_final(MD_HANDLE a);
 byte *md_read( MD_HANDLE a, int algo );
 int md_get_algo( MD_HANDLE a );
+int md_digest_length( int algo );
 const byte *md_asn_oid( int algo, size_t *asnlen, size_t *mdlen );
 #define md_is_secure(a) ((a)->secure)
 
index 5a63719..025f20e 100644 (file)
@@ -89,6 +89,7 @@ static char *keypool; /* allocated size is POOLSIZE+BLOCKLEN */
 static size_t pool_readpos;
 static size_t pool_writepos;
 static int pool_filled;
+static int pool_balance;
 static int just_mixed;
 
 static int secure_alloc;
@@ -166,6 +167,26 @@ get_random_byte( int level )
 }
 
 
+
+/****************
+ * Return a pointer to a randomized buffer of level 0 and LENGTH bits
+ * caller must free the buffer. This function does not use the
+ * cache (will be removed in future). Note: The returned value is
+ * rounded up to bytes.
+ */
+byte *
+get_random_bits( size_t nbits, int level, int secure )
+{
+    byte *buf;
+    size_t nbytes = (nbits+7)/8;
+
+    MASK_LEVEL(level);
+    buf = secure? m_alloc_secure( nbytes ) : m_alloc( nbytes );
+    read_pool( buf, nbytes, level );
+    return buf;
+}
+
+
 /****************
  * Mix the pool
  */
@@ -223,9 +244,23 @@ read_pool( byte *buffer, size_t length, int level )
        return;
     }
 
-    /* always do a random poll if we need strong numbers */
-    if( pool_filled && level == 2 )
-       random_poll();
+    /* for level 2 make sure that there is enough random in the pool */
+    if( level == 2 && pool_balance < length ) {
+       size_t needed;
+       byte *p;
+
+       if( pool_balance < 0 )
+           pool_balance = 0;
+       needed = length - pool_balance;
+       if( needed > POOLSIZE )
+           BUG();
+       p = m_alloc_secure( needed );
+       read_dev_random( p, needed, 2 ); /* read /dev/random */
+       add_randomness( p, needed, 3);
+       m_free(p);
+       pool_balance += needed;
+    }
+
     /* make sure the pool is filled */
     while( !pool_filled )
        random_poll();
@@ -250,7 +285,10 @@ read_pool( byte *buffer, size_t length, int level )
        *buffer++ = keypool[pool_readpos++];
        if( pool_readpos >= POOLSIZE )
            pool_readpos = 0;
+       pool_balance--;
     }
+    if( pool_balance < 0 )
+       pool_balance = 0;
     /* and clear the keypool */
     memset( keypool, 0, POOLSIZE );
 }
index a8c506d..c45c983 100644 (file)
@@ -27,6 +27,7 @@ void secure_random_alloc(void);
 int  quick_random_gen( int onoff );
 void randomize_buffer( byte *buffer, size_t length, int level );
 byte get_random_byte( int level );
+byte *get_random_bits( size_t nbits, int level, int secure );
 void add_randomness( const void *buffer, size_t length, int source );
 
 
index 43ca5a1..ba738cf 100644 (file)
@@ -21,7 +21,7 @@ fi
 
 VERSION=`cat $srcdir/VERSION`
 PACKAGE=gnupg
-ALL_LINGUAS="de"
+ALL_LINGUAS="de it"
 AC_SUBST(VERSION)
 AC_SUBST(PACKAGE)
 AC_DEFINE_UNQUOTED(VERSION, "$VERSION")
@@ -108,6 +108,8 @@ dnl Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
 AC_C_INLINE
 AC_TYPE_SIZE_T
+AC_TYPE_SIGNAL
+AC_DECL_SYS_SIGLIST
 
 WK_CHECK_ENDIAN
 
index ddcfce7..5a2f039 100644 (file)
@@ -1,3 +1,7 @@
+Tue Mar 10 13:40:34 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * mpi-bit.c (mpi_clear_highbit): New.
+
 Mon Mar  2 19:29:00 1998  Werner Koch  (wk@isil.d.shuttle.de)
 
        * Makefile.am (DISTCLEANFILES): New
index eff7be2..cae29d2 100644 (file)
@@ -135,6 +135,25 @@ mpi_set_highbit( MPI a, unsigned n )
 }
 
 /****************
+ * clear bit N of A and all bits above
+ */
+void
+mpi_clear_highbit( MPI a, unsigned n )
+{
+    unsigned limbno, bitno;
+
+    limbno = n / BITS_PER_MPI_LIMB;
+    bitno  = n % BITS_PER_MPI_LIMB;
+
+    if( limbno >= a->nlimbs )
+       return; /* not allocated, so need to clear bits :-) */
+
+    for( ; bitno < BITS_PER_MPI_LIMB; bitno++ )
+       a->d[limbno] &= ~(A_LIMB_1 << bitno);
+    a->nlimbs = limbno+1;
+}
+
+/****************
  * Clear bit N of A.
  */
 void