summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>1998-03-19 15:27:26 +0000
committerWerner Koch <wk@gnupg.org>1998-03-19 15:27:26 +0000
commitfa3731d01d66ad6fcd9faf1383611e55e11a3f5a (patch)
treed46eeb9ee4859e591922182ee325da7e4c95e5e7
parent198d5240d567568480862afae628a4639617815f (diff)
downloadlibgcrypt-fa3731d01d66ad6fcd9faf1383611e55e11a3f5a.tar.gz
some cleanups
-rw-r--r--THANKS1
-rw-r--r--cipher/ChangeLog32
-rw-r--r--cipher/blowfish.c150
-rw-r--r--cipher/dsa.c60
-rw-r--r--cipher/elgamal.c7
-rw-r--r--cipher/md.c15
-rw-r--r--cipher/md.h1
-rw-r--r--cipher/random.c44
-rw-r--r--cipher/random.h1
-rw-r--r--configure.in4
-rw-r--r--mpi/ChangeLog4
-rw-r--r--mpi/mpi-bit.c19
12 files changed, 315 insertions, 23 deletions
diff --git a/THANKS b/THANKS
index 4d043651..4b564ddd 100644
--- 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
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