diff options
author | Werner Koch <wk@gnupg.org> | 1998-03-19 15:27:26 +0000 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 1998-03-19 15:27:26 +0000 |
commit | fa3731d01d66ad6fcd9faf1383611e55e11a3f5a (patch) | |
tree | d46eeb9ee4859e591922182ee325da7e4c95e5e7 | |
parent | 198d5240d567568480862afae628a4639617815f (diff) | |
download | libgcrypt-fa3731d01d66ad6fcd9faf1383611e55e11a3f5a.tar.gz |
some cleanups
-rw-r--r-- | THANKS | 1 | ||||
-rw-r--r-- | cipher/ChangeLog | 32 | ||||
-rw-r--r-- | cipher/blowfish.c | 150 | ||||
-rw-r--r-- | cipher/dsa.c | 60 | ||||
-rw-r--r-- | cipher/elgamal.c | 7 | ||||
-rw-r--r-- | cipher/md.c | 15 | ||||
-rw-r--r-- | cipher/md.h | 1 | ||||
-rw-r--r-- | cipher/random.c | 44 | ||||
-rw-r--r-- | cipher/random.h | 1 | ||||
-rw-r--r-- | configure.in | 4 | ||||
-rw-r--r-- | mpi/ChangeLog | 4 | ||||
-rw-r--r-- | mpi/mpi-bit.c | 19 |
12 files changed, 315 insertions, 23 deletions
@@ -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 diff --git a/cipher/ChangeLog b/cipher/ChangeLog index 0a316d1b..fbd7bed8 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -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. diff --git a/cipher/blowfish.c b/cipher/blowfish.c index 55b99025..09b15767 100644 --- a/cipher/blowfish.c +++ b/cipher/blowfish.c @@ -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, } + diff --git a/cipher/dsa.c b/cipher/dsa.c index 8024ac0a..8eb0cec9 100644 --- a/cipher/dsa.c +++ b/cipher/dsa.c @@ -27,6 +27,32 @@ #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 ); diff --git a/cipher/elgamal.c b/cipher/elgamal.c index 2141db0c..b211d7f6 100644 --- a/cipher/elgamal.c +++ b/cipher/elgamal.c @@ -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); diff --git a/cipher/md.c b/cipher/md.c index b1939965..0f49443b 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -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 ) diff --git a/cipher/md.h b/cipher/md.h index dcdfe800..961f6171 100644 --- a/cipher/md.h +++ b/cipher/md.h @@ -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) diff --git a/cipher/random.c b/cipher/random.c index 5a637199..025f20ec 100644 --- a/cipher/random.c +++ b/cipher/random.c @@ -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 ); } diff --git a/cipher/random.h b/cipher/random.h index a8c506da..c45c9831 100644 --- a/cipher/random.h +++ b/cipher/random.h @@ -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 ); diff --git a/configure.in b/configure.in index 43ca5a18..ba738cfc 100644 --- a/configure.in +++ b/configure.in @@ -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 diff --git a/mpi/ChangeLog b/mpi/ChangeLog index ddcfce75..5a2f0399 100644 --- a/mpi/ChangeLog +++ b/mpi/ChangeLog @@ -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 diff --git a/mpi/mpi-bit.c b/mpi/mpi-bit.c index eff7be25..cae29d22 100644 --- a/mpi/mpi-bit.c +++ b/mpi/mpi-bit.c @@ -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 |