diff options
author | Werner Koch <[email protected]> | 1998-03-19 15:27:29 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 1998-03-19 15:27:29 +0000 |
commit | 6b91e7762c65097a103b2b17db304a4d85b3573d (patch) | |
tree | 4303dbf887db8130c58e1025cac3c8fe291c6ceb /cipher | |
parent | NEw test keyrings (diff) | |
download | gnupg-6b91e7762c65097a103b2b17db304a4d85b3573d.tar.gz gnupg-6b91e7762c65097a103b2b17db304a4d85b3573d.zip |
some cleanups
Diffstat (limited to 'cipher')
-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 |
8 files changed, 288 insertions, 22 deletions
diff --git a/cipher/ChangeLog b/cipher/ChangeLog index 0a316d1bb..fbd7bed8c 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,35 @@ +Thu Mar 19 13:54:48 1998 Werner Koch ([email protected]) + + * blowfish.c (blowfish_decode_cfb): changed XOR operation + (blowfish_encode_cfb): Ditto. + +Thu Mar 12 14:04:05 1998 Werner Koch ([email protected]) + + * sha1.c (transform): Rewrote + + * blowfish.c (encrypt): Unrolled for rounds == 16 + (decrypt): Ditto. + +Tue Mar 10 16:32:08 1998 Werner Koch ([email protected]) + + * rmd160.c (transform): Unrolled the loop. + +Tue Mar 10 13:05:14 1998 Werner Koch ([email protected]) + + * 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 ([email protected]) + + * md.c (md_digest_length): New. + +Tue Mar 10 11:27:41 1998 Werner Koch ([email protected]) + + * dsa.c (dsa_verify): Works. + Mon Mar 9 12:59:08 1998 Werner Koch ([email protected]) * dsa.c, dsa.h: Removed some unused code. diff --git a/cipher/blowfish.c b/cipher/blowfish.c index 55b99025c..09b15767d 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 8024ac0a2..8eb0cec93 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 2141db0cc..b211d7f6c 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 b19399653..0f49443b7 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 dcdfe8000..961f61710 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 5a6371995..025f20ecb 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 a8c506da7..c45c9831b 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 ); |