diff --git a/NEWS b/NEWS index c73652e66..2e110e64c 100644 --- a/NEWS +++ b/NEWS @@ -1,11 +1,15 @@ Noteworthy changes in version 0.2.15 ------------------------------------ + * Fixed a bug with the old checksum calculation for secret keys. + If you run the program without --batch, a warning does inform + you if your secret key needs to be converted; simply use + --change-passphrase to recalculate the checksum. Please do this + soon, as the compatible mode will be removed sometime in the future. + * CAST5 works (using the PGP's special CFB mode). - - Noteworthy changes in version 0.2.14 ------------------------------------ diff --git a/TODO b/TODO index 3e753c11b..897bb6093 100644 --- a/TODO +++ b/TODO @@ -49,3 +49,12 @@ * fix the problems with "\v" in gettext + * calculation of cechksums for secret keys is wrong. We used a + the complete chunk length instead of the real number of bits. + The problme ist that it is how to stay compatible to old + keys? - Do wee need a kludge to calculate both versions of + checksums???? (keygen.c, seckey-cert.c) + + + + diff --git a/checks/encryptp.test b/checks/encryptp.test index 8dc0bb0d2..ac86fb54e 100755 --- a/checks/encryptp.test +++ b/checks/encryptp.test @@ -5,6 +5,6 @@ #info Checking encryption with a pipe for i in $plain_files $data_files ; do run_gpg -e --yes -r "$usrname2" < $i | run_gpg --yes > y - cmp $i y || error "$i: mismatch" + cmp $i y || fatal "$i: mismatch" done diff --git a/cipher/ChangeLog b/cipher/ChangeLog index d76846591..e1bc0b8ec 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,10 @@ +Tue Apr 7 18:46:49 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c: New + * misc.c (check_cipher_algo): Moved to cipher.c + * cast5.c: Moved many functions to cipher.c + * blowfish.c: Likewise. + Sat Apr 4 19:52:08 1998 Werner Koch (wk@isil.d.shuttle.de) * cast5.c: Implemented and tested. diff --git a/cipher/Makefile.am b/cipher/Makefile.am index ff2e9f37f..945ae3dbc 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -6,7 +6,8 @@ EXTRA_DIST = @CIPHER_EXTRA_DIST@ noinst_LIBRARIES = libcipher.a -libcipher_a_SOURCES = blowfish.c \ +libcipher_a_SOURCES = cipher.c \ + blowfish.c \ blowfish.h \ cast5.c \ cast5.h \ diff --git a/cipher/Makefile.in b/cipher/Makefile.in index 91ed0a95b..d6bfab330 100644 --- a/cipher/Makefile.in +++ b/cipher/Makefile.in @@ -97,7 +97,8 @@ EXTRA_DIST = @CIPHER_EXTRA_DIST@ noinst_LIBRARIES = libcipher.a -libcipher_a_SOURCES = blowfish.c \ +libcipher_a_SOURCES = cipher.c \ + blowfish.c \ blowfish.h \ cast5.c \ cast5.h \ @@ -131,8 +132,8 @@ DEFS = @DEFS@ -I. -I$(srcdir) -I.. CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ -libcipher_a_OBJECTS = blowfish.o cast5.o elgamal.o md5.o primegen.o \ -random.o rmd160.o sha1.o dsa.o md.o misc.o smallprime.o +libcipher_a_OBJECTS = cipher.o blowfish.o cast5.o elgamal.o md5.o \ +primegen.o random.o rmd160.o sha1.o dsa.o md.o misc.o smallprime.o AR = ar CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) @@ -144,9 +145,9 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = tar GZIP = --best -DEP_FILES = .deps/blowfish.P .deps/cast5.P .deps/dsa.P .deps/elgamal.P \ -.deps/md.P .deps/md5.P .deps/misc.P .deps/primegen.P .deps/random.P \ -.deps/rmd160.P .deps/sha1.P .deps/smallprime.P +DEP_FILES = .deps/blowfish.P .deps/cast5.P .deps/cipher.P .deps/dsa.P \ +.deps/elgamal.P .deps/md.P .deps/md5.P .deps/misc.P .deps/primegen.P \ +.deps/random.P .deps/rmd160.P .deps/sha1.P .deps/smallprime.P SOURCES = $(libcipher_a_SOURCES) OBJECTS = $(libcipher_a_OBJECTS) diff --git a/cipher/blowfish.c b/cipher/blowfish.c index 09b15767d..9e3c2bdcc 100644 --- a/cipher/blowfish.c +++ b/cipher/blowfish.c @@ -37,7 +37,6 @@ #include "util.h" #include "types.h" #include "blowfish.h" -#include "random.h" /* precomputed S boxes */ static const u32 ks0[256] = { @@ -392,8 +391,8 @@ decrypt( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr ) #undef F #undef R -static void -encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) +void +blowfish_encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) { u32 d1, d2; @@ -429,8 +428,8 @@ encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) } -static void -decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) +void +blowfish_decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ) { u32 d1, d2; @@ -477,18 +476,18 @@ selftest() byte cipher3[] = { 0xE1, 0x13, 0xF4, 0x10, 0x2C, 0xFC, 0xCE, 0x43 }; blowfish_setkey( &c, "abcdefghijklmnopqrstuvwxyz", 26 ); - encrypt_block( &c, buffer, plain ); + blowfish_encrypt_block( &c, buffer, plain ); if( memcmp( buffer, "\x32\x4E\xD0\xFE\xF4\x13\xA2\x03", 8 ) ) log_error("wrong blowfish encryption\n"); - decrypt_block( &c, buffer, buffer ); + blowfish_decrypt_block( &c, buffer, buffer ); if( memcmp( buffer, plain, 8 ) ) log_bug("blowfish failed\n"); blowfish_setkey( &c, key3, 8 ); - encrypt_block( &c, buffer, plain3 ); + blowfish_encrypt_block( &c, buffer, plain3 ); if( memcmp( buffer, cipher3, 8 ) ) log_error("wrong blowfish encryption (3)\n"); - decrypt_block( &c, buffer, buffer ); + blowfish_decrypt_block( &c, buffer, buffer ); if( memcmp( buffer, plain3, 8 ) ) log_bug("blowfish failed (3)\n"); } @@ -507,8 +506,6 @@ blowfish_setkey( BLOWFISH_context *c, byte *key, unsigned keylen ) selftest(); } - fast_random_poll(); - for(i=0; i < BLOWFISH_ROUNDS+2; i++ ) c->p[i] = ps[i]; for(i=0; i < 256; i++ ) { @@ -563,186 +560,3 @@ blowfish_setkey( BLOWFISH_context *c, byte *key, unsigned keylen ) } -void -blowfish_setiv( BLOWFISH_context *c, byte *iv ) -{ - if( iv ) - memcpy( c->iv, iv, BLOWFISH_BLOCKSIZE ); - else - memset( c->iv, 0, BLOWFISH_BLOCKSIZE ); - c->count = 0; - encrypt_block( c, c->eniv, c->iv ); -} - - -void -blowfish_encode( BLOWFISH_context *c, byte *outbuf, byte *inbuf, - unsigned nblocks ) -{ - unsigned n; - - for(n=0; n < nblocks; n++ ) { - encrypt_block( c, outbuf, inbuf ); - inbuf += BLOWFISH_BLOCKSIZE;; - outbuf += BLOWFISH_BLOCKSIZE; - } -} - -void -blowfish_decode( BLOWFISH_context *c, byte *outbuf, byte *inbuf, - unsigned nblocks ) -{ - unsigned n; - - for(n=0; n < nblocks; n++ ) { - decrypt_block( c, outbuf, inbuf ); - inbuf += BLOWFISH_BLOCKSIZE;; - outbuf += BLOWFISH_BLOCKSIZE; - } -} - - - -/**************** - * FIXME: Make use of bigger chunks - * (out may overlap with a or b) - */ -static void -xorblock( byte *out, byte *a, byte *b, unsigned count ) -{ - for( ; count ; count--, a++, b++ ) - *out++ = *a ^ *b ; -} - - - -/**************** - * Encode buffer in CFB mode. nbytes can be an arbitrary value. - */ -void -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 ); - n = BLOWFISH_BLOCKSIZE - c->count; - if( n > nbytes ) - n = nbytes; - xorblock( outbuf, c->eniv+c->count, inbuf, n); - memcpy( c->iv+c->count, outbuf, n); - c->count += n; - nbytes -= n; - inbuf += n; - outbuf += n; - assert( c->count <= BLOWFISH_BLOCKSIZE); - if( c->count == BLOWFISH_BLOCKSIZE ) { - encrypt_block( c, c->eniv, c->iv ); - c->count = 0; - } - else - return; - } - assert(!c->count); - is_aligned = !((ulong)inbuf % SIZEOF_UNSIGNED_LONG); - while( nbytes >= 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; - inbuf += BLOWFISH_BLOCKSIZE; - outbuf += BLOWFISH_BLOCKSIZE; - } - - if( nbytes ) { - xorblock( outbuf, c->eniv, inbuf, nbytes ); - memcpy( c->iv, outbuf, nbytes ); - c->count = nbytes; - } - -} - - -void -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 ); - n = BLOWFISH_BLOCKSIZE - c->count; - if( n > nbytes ) - n = nbytes; - memcpy( c->iv+c->count, inbuf, n); - xorblock( outbuf, c->eniv+c->count, inbuf, n); - c->count += n; - nbytes -= n; - inbuf += n; - outbuf += n; - assert( c->count <= BLOWFISH_BLOCKSIZE); - if( c->count == BLOWFISH_BLOCKSIZE ) { - encrypt_block( c, c->eniv, c->iv ); - c->count = 0; - } - else - return; - } - - assert(!c->count); - is_aligned = !((ulong)inbuf % SIZEOF_UNSIGNED_LONG); - while( nbytes >= BLOWFISH_BLOCKSIZE ) { - memcpy( c->iv, 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; - outbuf += BLOWFISH_BLOCKSIZE; - } - - if( nbytes ) { - memcpy( c->iv, inbuf, nbytes ); - xorblock( outbuf, c->eniv, inbuf, nbytes ); - c->count = nbytes; - } - -} - - diff --git a/cipher/blowfish.h b/cipher/blowfish.h index 998bc0c09..db96d3720 100644 --- a/cipher/blowfish.h +++ b/cipher/blowfish.h @@ -31,21 +31,10 @@ typedef struct { u32 s2[256]; u32 s3[256]; u32 p[BLOWFISH_ROUNDS+2]; - byte iv[BLOWFISH_BLOCKSIZE]; - byte eniv[BLOWFISH_BLOCKSIZE]; - int count; } BLOWFISH_context; void blowfish_setkey( BLOWFISH_context *c, byte *key, unsigned keylen ); -void blowfish_setiv( BLOWFISH_context *c, byte *iv ); -void blowfish_encode( BLOWFISH_context *c, byte *outbuf, byte *inbuf, - unsigned nblocks ); -void blowfish_decode( BLOWFISH_context *c, byte *outbuf, byte *inbuf, - unsigned nblocks ); -void blowfish_encode_cfb( BLOWFISH_context *c, byte *outbuf, - byte *inbuf, unsigned nbytes); -void blowfish_decode_cfb( BLOWFISH_context *c, byte *outbuf, - byte *inbuf, unsigned nbytes); - +void blowfish_encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ); +void blowfish_decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf ); #endif /*G10_BLOWFISH_H*/ diff --git a/cipher/cast5.c b/cipher/cast5.c index a14abaa37..99791e05e 100644 --- a/cipher/cast5.c +++ b/cipher/cast5.c @@ -43,7 +43,6 @@ #include "util.h" #include "types.h" #include "cast5.h" -#include "random.h" static const u32 s1[256] = { 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, @@ -339,8 +338,8 @@ rol(int n, u32 x) #define F3(D,m,r) ( (I = ((m) - (D))), (I=rol((r),I)), \ (((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 ) +void +cast5_encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf ) { u32 l, r, t; u32 I; /* used by the Fx macros */ @@ -393,8 +392,8 @@ encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf ) outbuf[7] = l & 0xff; } -static void -decrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf ) +void +cast5_decrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf ) { u32 l, r, t; u32 I; @@ -447,10 +446,10 @@ selftest() byte buffer[8]; cast5_setkey( &c, key, 16 ); - encrypt_block( &c, buffer, plain ); + cast5_encrypt_block( &c, buffer, plain ); if( memcmp( buffer, cipher, 8 ) ) log_error("wrong cast5-128 encryption\n"); - decrypt_block( &c, buffer, buffer ); + cast5_decrypt_block( &c, buffer, buffer ); if( memcmp( buffer, plain, 8 ) ) log_bug("cast5-128 failed\n"); @@ -468,11 +467,11 @@ selftest() for(i=0; i < 1000000; i++ ) { cast5_setkey( &c, b0, 16 ); - encrypt_block( &c, a0, a0 ); - encrypt_block( &c, a0+8, a0+8 ); + cast5_encrypt_block( &c, a0, a0 ); + cast5_encrypt_block( &c, a0+8, a0+8 ); cast5_setkey( &c, a0, 16 ); - encrypt_block( &c, b0, b0 ); - encrypt_block( &c, b0+8, b0+8 ); + cast5_encrypt_block( &c, b0, b0 ); + cast5_encrypt_block( &c, b0+8, b0+8 ); } if( memcmp( a0, a1, 16 ) || memcmp( b0, b1, 16 ) ) log_bug("cast5-128 maintenance test failed\n"); @@ -543,7 +542,6 @@ cast5_setkey( CAST5_context *c, byte *key, unsigned keylen ) initialized = 1; selftest(); } - fast_random_poll(); assert(keylen==16); x[0] = key[0] << 24 | key[1] << 16 | key[2] << 8 | key[3]; @@ -567,198 +565,3 @@ cast5_setkey( CAST5_context *c, byte *key, unsigned keylen ) } -void -cast5_setiv( CAST5_context *c, byte *iv ) -{ - if( iv ) - memcpy( c->iv, iv, CAST5_BLOCKSIZE ); - else - memset( c->iv, 0, CAST5_BLOCKSIZE ); - c->count = 0; - encrypt_block( c, c->eniv, c->iv ); -} - - -void -cast5_encode( CAST5_context *c, byte *outbuf, byte *inbuf, - unsigned nblocks ) -{ - unsigned n; - - for(n=0; n < nblocks; n++ ) { - encrypt_block( c, outbuf, inbuf ); - inbuf += CAST5_BLOCKSIZE;; - outbuf += CAST5_BLOCKSIZE; - } -} - -void -cast5_decode( CAST5_context *c, byte *outbuf, byte *inbuf, - unsigned nblocks ) -{ - unsigned n; - - for(n=0; n < nblocks; n++ ) { - decrypt_block( c, outbuf, inbuf ); - inbuf += CAST5_BLOCKSIZE;; - outbuf += CAST5_BLOCKSIZE; - } -} - - - -/**************** - * FIXME: Make use of bigger chunks - * (out may overlap with a or b) - */ -static void -xorblock( byte *out, byte *a, byte *b, unsigned count ) -{ - for( ; count ; count--, a++, b++ ) - *out++ = *a ^ *b ; -} - - - -/**************** - * Encode buffer in CFB mode. nbytes can be an arbitrary value. - */ -void -cast5_encode_cfb( CAST5_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 < CAST5_BLOCKSIZE ); - n = CAST5_BLOCKSIZE - c->count; - if( n > nbytes ) - n = nbytes; - xorblock( outbuf, c->eniv+c->count, inbuf, n); - memcpy( c->iv+c->count, outbuf, n); - c->count += n; - nbytes -= n; - inbuf += n; - outbuf += n; - assert( c->count <= CAST5_BLOCKSIZE); - if( c->count == CAST5_BLOCKSIZE ) { - encrypt_block( c, c->eniv, c->iv ); - c->count = 0; - } - else - return; - } - assert(!c->count); - is_aligned = !((ulong)inbuf % SIZEOF_UNSIGNED_LONG); - while( nbytes >= CAST5_BLOCKSIZE ) { - if( is_aligned ) { - #if SIZEOF_UNSIGNED_LONG == CAST5_BLOCKSIZE - *(ulong*)outbuf = *(ulong*)c->eniv ^ *(ulong*)inbuf; - #elif (2*SIZEOF_UNSIGNED_LONG) == CAST5_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) == CAST5_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, CAST5_BLOCKSIZE); - #endif - } - else /* not aligned */ - xorblock( outbuf, c->eniv, inbuf, CAST5_BLOCKSIZE); - memcpy( c->iv, outbuf, CAST5_BLOCKSIZE); - encrypt_block( c, c->eniv, c->iv ); - nbytes -= CAST5_BLOCKSIZE; - inbuf += CAST5_BLOCKSIZE; - outbuf += CAST5_BLOCKSIZE; - } - - if( nbytes ) { - xorblock( outbuf, c->eniv, inbuf, nbytes ); - memcpy( c->iv, outbuf, nbytes ); - c->count = nbytes; - } - -} - - -void -cast5_decode_cfb( CAST5_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 < CAST5_BLOCKSIZE ); - n = CAST5_BLOCKSIZE - c->count; - if( n > nbytes ) - n = nbytes; - memcpy( c->iv+c->count, inbuf, n); - xorblock( outbuf, c->eniv+c->count, inbuf, n); - c->count += n; - nbytes -= n; - inbuf += n; - outbuf += n; - assert( c->count <= CAST5_BLOCKSIZE); - if( c->count == CAST5_BLOCKSIZE ) { - encrypt_block( c, c->eniv, c->iv ); - c->count = 0; - } - else - return; - } - - assert(!c->count); - is_aligned = !((ulong)inbuf % SIZEOF_UNSIGNED_LONG); - while( nbytes >= CAST5_BLOCKSIZE ) { - memcpy( c->iv, inbuf, CAST5_BLOCKSIZE); - if( is_aligned ) { - #if SIZEOF_UNSIGNED_LONG == CAST5_BLOCKSIZE - *(ulong*)outbuf = *(ulong*)c->eniv ^ *(ulong*)inbuf; - #elif (2*SIZEOF_UNSIGNED_LONG) == CAST5_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) == CAST5_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, CAST5_BLOCKSIZE); - #endif - } - else /* not aligned */ - xorblock( outbuf, c->eniv, inbuf, CAST5_BLOCKSIZE); - encrypt_block( c, c->eniv, c->iv ); - nbytes -= CAST5_BLOCKSIZE; - inbuf += CAST5_BLOCKSIZE; - outbuf += CAST5_BLOCKSIZE; - } - - if( nbytes ) { - memcpy( c->iv, inbuf, nbytes ); - xorblock( outbuf, c->eniv, inbuf, nbytes ); - c->count = nbytes; - } - -} - - - -void -cast5_sync_cfb( CAST5_context *c ) -{ - if( c->count ) { - memmove(c->iv + c->count, c->iv, CAST5_BLOCKSIZE - c->count ); - memcpy(c->iv, c->eniv + CAST5_BLOCKSIZE - c->count, c->count); - c->count = 0; - } -} - - diff --git a/cipher/cast5.h b/cipher/cast5.h index 4afaf2a8a..6d943c25e 100644 --- a/cipher/cast5.h +++ b/cipher/cast5.h @@ -27,22 +27,11 @@ typedef struct { u32 Km[16]; byte Kr[16]; - byte iv[CAST5_BLOCKSIZE]; - byte eniv[CAST5_BLOCKSIZE]; - int count; } CAST5_context; void cast5_setkey( CAST5_context *c, byte *key, unsigned keylen ); -void cast5_setiv( CAST5_context *c, byte *iv ); -void cast5_encode( CAST5_context *c, byte *outbuf, byte *inbuf, - unsigned nblocks ); -void cast5_decode( CAST5_context *c, byte *outbuf, byte *inbuf, - unsigned nblocks ); -void cast5_encode_cfb( CAST5_context *c, byte *outbuf, - byte *inbuf, unsigned nbytes); -void cast5_decode_cfb( CAST5_context *c, byte *outbuf, - byte *inbuf, unsigned nbytes); -void cast5_sync_cfb( CAST5_context *c ); +void cast5_encrypt_block( CAST5_context *bc, byte *outbuf, byte *inbuf ); +void cast5_decrypt_block( CAST5_context *bc, byte *outbuf, byte *inbuf ); #endif /*G10_CAST5_H*/ diff --git a/cipher/cipher.c b/cipher/cipher.c new file mode 100644 index 000000000..6e2bcce08 --- /dev/null +++ b/cipher/cipher.c @@ -0,0 +1,425 @@ +/* cipher.c - cipher dispatcher + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG 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 + */ + +#define DEFINES_CIPHER_HANDLE 1 + +#include +#include +#include +#include +#include +#include +#include "util.h" +#include "errors.h" +#include "cipher.h" +#include "blowfish.h" +#include "cast5.h" + +#define STD_BLOCKSIZE 8 + +#if BLOWFISH_BLOCKSIZE != STD_BLOCKSIZE + #error Invalid BLOWFISH blocksize +#elif CAST5_BLOCKSIZE != STD_BLOCKSIZE + #error Invalid CAST blocksize +#endif + + +static struct { const char *name; int algo;} cipher_names[] = { + { "IDEA", CIPHER_ALGO_IDEA }, + { "3DES", CIPHER_ALGO_3DES }, + { "CAST", CIPHER_ALGO_CAST }, + { "BLOWFISH128", CIPHER_ALGO_BLOWFISH128 }, + { "ROT_N", CIPHER_ALGO_ROT_N }, + { "SAFER_SK128", CIPHER_ALGO_SAFER_SK128 }, + { "DES_SK", CIPHER_ALGO_DES_SK }, + { "BLOWFISH", CIPHER_ALGO_BLOWFISH }, + {NULL} }; + + +/* Hmmm, no way for a void arg in function pointer? */ +#define FNCCAST_SETKEY(f) (void(*)(void*, byte*, unsigned))(f) +#define FNCCAST_CRYPT(f) (void(*)(void*, byte*, byte*))(f) + + +struct cipher_handle_s { + int algo; + int mode; + byte iv[STD_BLOCKSIZE]; /* (this should be ulong aligned) */ + byte lastiv[STD_BLOCKSIZE]; + int unused; /* in IV */ + void (*setkey)( void *c, byte *key, unsigned keylen ); + void (*encrypt)( void *c, byte *outbuf, byte *inbuf ); + void (*decrypt)( void *c, byte *outbuf, byte *inbuf ); + void (*sync_cfb)( void *c ); + union { + int context; + BLOWFISH_context blowfish; + CAST5_context cast5; + } c; +}; + + +/**************** + * Map a string to the cipher algo + */ +int +string_to_cipher_algo( const char *string ) +{ + int i; + const char *s; + + for(i=0; (s=cipher_names[i].name); i++ ) + if( !stricmp( s, string ) ) + return cipher_names[i].algo; + return 0; +} + +/**************** + * Map a cipher algo to a string + */ +const char * +cipher_algo_to_string( int algo ) +{ + int i; + + for(i=0; cipher_names[i].name; i++ ) + if( cipher_names[i].algo == algo ) + return cipher_names[i].name; + return NULL; +} + +/**************** + * Return 0 if the cipher algo is available + */ +int +check_cipher_algo( int algo ) +{ + switch( algo ) { + case CIPHER_ALGO_BLOWFISH128: + case CIPHER_ALGO_BLOWFISH: + case CIPHER_ALGO_CAST: + return 0; + default: + return G10ERR_CIPHER_ALGO; + } +} + + +/**************** + * Open a cipher handle for use with algorithm ALGO, in mode MODE + * and put it into secure memory if SECURE is true. + */ +CIPHER_HANDLE +cipher_open( int algo, int mode, int secure ) +{ + CIPHER_HANDLE hd; + + fast_random_poll(); + /* performance hint: + * It is possible to allocate less memory depending on the cipher */ + hd = secure ? m_alloc_secure_clear( sizeof *hd ) + : m_alloc_clear( sizeof *hd ); + hd->algo = algo; + if( mode == CIPHER_MODE_AUTO_CFB ) { + if( algo == CIPHER_ALGO_CAST ) + hd->mode = CIPHER_MODE_PHILS_CFB; + else + hd->mode = CIPHER_MODE_CFB; + } + else + hd->mode = mode; + switch( algo ) { + case CIPHER_ALGO_BLOWFISH: + case CIPHER_ALGO_BLOWFISH128: + hd->setkey = FNCCAST_SETKEY(blowfish_setkey); + hd->encrypt = FNCCAST_CRYPT(blowfish_encrypt_block); + hd->decrypt = FNCCAST_CRYPT(blowfish_decrypt_block); + break; + + case CIPHER_ALGO_CAST: + hd->setkey = FNCCAST_SETKEY(cast5_setkey); + hd->encrypt = FNCCAST_CRYPT(cast5_encrypt_block); + hd->decrypt = FNCCAST_CRYPT(cast5_decrypt_block); + break; + + default: log_fatal("cipher_open: invalid algo %d\n", algo ); + } + + return hd; +} + + +void +cipher_close( CIPHER_HANDLE c ) +{ + m_free(c); +} + + +void +cipher_setkey( CIPHER_HANDLE c, byte *key, unsigned keylen ) +{ + (*c->setkey)( &c->c.context, key, keylen ); +} + + +void +cipher_setiv( CIPHER_HANDLE c, const byte *iv ) +{ + if( iv ) + memcpy( c->iv, iv, STD_BLOCKSIZE ); + else + memset( c->iv, 0, STD_BLOCKSIZE ); + c->unused = 0; +} + + + +static void +do_ecb_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks ) +{ + unsigned n; + + for(n=0; n < nblocks; n++ ) { + (*c->encrypt)( &c->c.context, outbuf, inbuf ); + inbuf += CAST5_BLOCKSIZE;; + outbuf += CAST5_BLOCKSIZE; + } +} + +static void +do_ecb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks ) +{ + unsigned n; + + for(n=0; n < nblocks; n++ ) { + (*c->decrypt)( &c->c.context, outbuf, inbuf ); + inbuf += CAST5_BLOCKSIZE;; + outbuf += CAST5_BLOCKSIZE; + } +} + + +static void +do_cfb_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes ) +{ + byte *ivp; + + if( nbytes <= c->unused ) { + /* short enough to be encoded by the remaining XOR mask */ + /* XOR the input with the IV and store input into IV */ + c->unused -= nbytes; + for(ivp=c->iv+STD_BLOCKSIZE - c->unused; nbytes; nbytes-- ) + *outbuf++ = (*ivp++ ^= *inbuf++); + return; + } + + if( c->unused ) { + /* XOR the input with the IV and store input into IV */ + nbytes -= c->unused; + for(ivp=c->iv+STD_BLOCKSIZE - c->unused; c->unused; c->unused-- ) + *outbuf++ = (*ivp++ ^= *inbuf++); + } + + /* now we can process complete blocks */ + while( nbytes >= STD_BLOCKSIZE ) { + int i; + /* encrypt the IV (and save the current one) */ + memcpy( c->lastiv, c->iv, STD_BLOCKSIZE ); + (*c->encrypt)( &c->c.context, c->iv, c->iv ); + /* XOR the input with the IV and store input into IV */ + for(ivp=c->iv,i=0; i < STD_BLOCKSIZE; i++ ) + *outbuf++ = (*ivp++ ^= *inbuf++); + nbytes -= STD_BLOCKSIZE; + } + if( nbytes ) { /* process the remaining bytes */ + /* encrypt the IV (and save the current one) */ + memcpy( c->lastiv, c->iv, STD_BLOCKSIZE ); + (*c->encrypt)( &c->c.context, c->iv, c->iv ); + c->unused = STD_BLOCKSIZE; + /* and apply the xor */ + c->unused -= nbytes; + for(ivp=c->iv; nbytes; nbytes-- ) + *outbuf++ = (*ivp++ ^= *inbuf++); + } +} + + +static void +do_cfb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes ) +{ + byte *ivp; + ulong temp; + + if( nbytes <= c->unused ) { + /* short enough to be encoded by the remaining XOR mask */ + /* XOR the input with the IV and store input into IV */ + c->unused -= nbytes; + for(ivp=c->iv+STD_BLOCKSIZE - c->unused; nbytes; nbytes-- ) { + temp = *inbuf++; + *outbuf++ = *ivp ^ temp; + *ivp++ = temp; + } + return; + } + + if( c->unused ) { + /* XOR the input with the IV and store input into IV */ + nbytes -= c->unused; + for(ivp=c->iv+STD_BLOCKSIZE - c->unused; c->unused; c->unused-- ) { + temp = *inbuf++; + *outbuf++ = *ivp ^ temp; + *ivp++ = temp; + } + } + + /* now we can process complete blocks */ + #ifdef BIG_ENDIAN_HOST + /* This does only make sense for big endian hosts, due to ... ivp = temp*/ + if( !((ulong)inbuf % SIZEOF_UNSIGNED_LONG) ) { + while( nbytes >= STD_BLOCKSIZE ) { + /* encrypt the IV (and save the current one) */ + memcpy( c->lastiv, c->iv, STD_BLOCKSIZE ); + (*c->encrypt)( &c->c.context, c->iv, c->iv ); + ivp = c->iv; + /* XOR the input with the IV and store input into IV */ + #if SIZEOF_UNSIGNED_LONG == STD_BLOCKSIZE + temp = *(ulong*)inbuf; + *(ulong*)outbuf = *(ulong*)c->iv ^ temp; + *(ulong*)ivp = temp; + #elif (2*SIZEOF_UNSIGNED_LONG) == STD_BLOCKSIZE + temp = ((ulong*)inbuf)[0]; + ((ulong*)outbuf)[0] = ((ulong*)c->iv)[0] ^ temp; + ((ulong*)ivp)[0] = temp; + temp = ((ulong*)inbuf)[1]; + ((ulong*)outbuf)[1] = ((ulong*)c->iv)[1] ^ temp; + ((ulong*)ivp)[1] = temp; + #elif (4*SIZEOF_UNSIGNED_LONG) == STD_BLOCKSIZE + temp = ((ulong*)inbuf)[0]; + ((ulong*)outbuf)[0] = ((ulong*)c->iv)[0] ^ temp; + ((ulong*)ivp)[0] = temp; + temp = ((ulong*)inbuf)[1]; + ((ulong*)outbuf)[1] = ((ulong*)c->iv)[1] ^ temp; + ((ulong*)ivp)[1] = temp; + temp = ((ulong*)inbuf)[2]; + ((ulong*)outbuf)[2] = ((ulong*)c->iv)[2] ^ temp; + ((ulong*)ivp)[2] = temp; + temp = ((ulong*)inbuf)[3]; + ((ulong*)outbuf)[3] = ((ulong*)c->iv)[3] ^ temp; + ((ulong*)ivp)[3] = temp; + #else + #error Please disable the align test. + #endif + nbytes -= STD_BLOCKSIZE; + } + } + else { /* non aligned version */ + #endif /* BIG_ENDIAN_HOST */ + while( nbytes >= STD_BLOCKSIZE ) { + int i; + /* encrypt the IV (and save the current one) */ + memcpy( c->lastiv, c->iv, STD_BLOCKSIZE ); + (*c->encrypt)( &c->c.context, c->iv, c->iv ); + /* XOR the input with the IV and store input into IV */ + for(ivp=c->iv,i=0; i < STD_BLOCKSIZE; i++ ) { + temp = *inbuf++; + *outbuf++ = *ivp ^ temp; + *ivp++ = temp; + } + nbytes -= STD_BLOCKSIZE; + } + #ifdef BIG_ENDIAN_HOST + } + #endif + if( nbytes ) { /* process the remaining bytes */ + /* encrypt the IV (and save the current one) */ + memcpy( c->lastiv, c->iv, STD_BLOCKSIZE ); + (*c->encrypt)( &c->c.context, c->iv, c->iv ); + c->unused = STD_BLOCKSIZE; + /* and apply the xor */ + c->unused -= nbytes; + for(ivp=c->iv; nbytes; nbytes-- ) { + temp = *inbuf++; + *outbuf++ = *ivp ^ temp; + *ivp++ = temp; + } + } +} + + +/**************** + * Encrypt INBUF to OUTBUF with the mode selected at open. + * inbuf and outbuf may overlap or be the same. + * Depending on the mode some some contraints apply to NBYTES. + */ +void +cipher_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes ) +{ + switch( c->mode ) { + case CIPHER_MODE_ECB: + assert(!(nbytes%8)); + do_ecb_encrypt(c, outbuf, inbuf, nbytes/8 ); + break; + case CIPHER_MODE_CFB: + case CIPHER_MODE_PHILS_CFB: + do_cfb_encrypt(c, outbuf, inbuf, nbytes ); + break; + default: log_fatal("cipher_encrypt: invalid mode %d\n", c->mode ); + } +} + + +/**************** + * Decrypt INBUF to OUTBUF with the mode selected at open. + * inbuf and outbuf may overlap or be the same. + * Depending on the mode some some contraints apply to NBYTES. + */ +void +cipher_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes ) +{ + switch( c->mode ) { + case CIPHER_MODE_ECB: + assert(!(nbytes%8)); + do_ecb_decrypt(c, outbuf, inbuf, nbytes/8 ); + break; + case CIPHER_MODE_CFB: + case CIPHER_MODE_PHILS_CFB: + do_cfb_decrypt(c, outbuf, inbuf, nbytes ); + break; + default: log_fatal("cipher_decrypt: invalid mode %d\n", c->mode ); + } +} + + + +/**************** + * Used for PGP's somewhat strange CFB mode. Does only work if + * the handle is in PHILS_CFB mode + */ +void +cipher_sync( CIPHER_HANDLE c ) +{ + if( c->mode == CIPHER_MODE_PHILS_CFB && c->unused ) { + memmove(c->iv + c->unused, c->iv, CAST5_BLOCKSIZE - c->unused ); + memcpy(c->iv, c->lastiv + CAST5_BLOCKSIZE - c->unused, c->unused); + c->unused = 0; + } +} + diff --git a/cipher/misc.c b/cipher/misc.c index d251955ee..35761e4f5 100644 --- a/cipher/misc.c +++ b/cipher/misc.c @@ -27,17 +27,6 @@ #include "cipher.h" -static struct { const char *name; int algo;} cipher_names[] = { - { "IDEA", CIPHER_ALGO_IDEA }, - { "3DES", CIPHER_ALGO_3DES }, - { "CAST", CIPHER_ALGO_CAST }, - { "BLOWFISH128", CIPHER_ALGO_BLOWFISH128 }, - { "ROT_N", CIPHER_ALGO_ROT_N }, - { "SAFER_SK128", CIPHER_ALGO_SAFER_SK128 }, - { "DES_SK", CIPHER_ALGO_DES_SK }, - { "BLOWFISH", CIPHER_ALGO_BLOWFISH }, - {NULL} }; - static struct { const char *name; int algo;} pubkey_names[] = { { "RSA", PUBKEY_ALGO_RSA }, { "RSA-E", PUBKEY_ALGO_RSA_E }, @@ -57,35 +46,7 @@ static struct { const char *name; int algo;} digest_names[] = { {NULL} }; -/**************** - * Map a string to the cipher algo - */ -int -string_to_cipher_algo( const char *string ) -{ - int i; - const char *s; - for(i=0; (s=cipher_names[i].name); i++ ) - if( !stricmp( s, string ) ) - return cipher_names[i].algo; - return 0; -} - - -/**************** - * Map a cipher algo to a string - */ -const char * -cipher_algo_to_string( int algo ) -{ - int i; - - for(i=0; cipher_names[i].name; i++ ) - if( cipher_names[i].algo == algo ) - return cipher_names[i].name; - return NULL; -} /**************** @@ -153,21 +114,6 @@ digest_algo_to_string( int algo ) -/**************** - * Return 0 if the cipher algo is available - */ -int -check_cipher_algo( int algo ) -{ - switch( algo ) { - case CIPHER_ALGO_BLOWFISH128: - case CIPHER_ALGO_BLOWFISH: - case CIPHER_ALGO_CAST: - return 0; - default: - return G10ERR_CIPHER_ALGO; - } -} int diff --git a/g10/ChangeLog b/g10/ChangeLog index e16f15550..d3e06d2b7 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,18 @@ +Tue Apr 7 19:28:07 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c, encr-data.c, seckey-cert.c: Now uses cipher_xxxx + functions instead of blowfish_xxx or cast_xxx + +Tue Apr 7 11:04:02 1998 Werner Koch (wk@isil.d.shuttle.de) + + * Makefile.am (g10maint.o): Changed the way it is created. + +Mon Apr 6 11:17:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * misc.c: New. + * keygen.c (checksum,checksum_u16,checksum_mpi): Moved to misc.c + * seckey-cert.c: Kludge for wrong ELG checksum implementation. + Sat Apr 4 20:07:01 1998 Werner Koch (wk@isil.d.shuttle.de) * cipher.c (cipher_filter): Support for CAST5 diff --git a/g10/Makefile.am b/g10/Makefile.am index 438acec19..ba9ca29df 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -3,7 +3,6 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl -I../intl EXTRA_DIST = OPTIONS pubring.asc OMIT_DEPENDENCIES = zlib.h zconf.h -BUILT_SOURCES = g10maint.c needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a bin_PROGRAMS = gpg gpgm gpgd @@ -28,6 +27,7 @@ common_source = \ elg.c \ dsa.c \ rsa.c \ + misc.c \ options.h \ openfile.c \ keyid.c \ @@ -60,8 +60,7 @@ gpg_SOURCES = g10.c \ keygen.c -gpgm_SOURCES = g10maint.c \ - dearmor.c \ +gpgm_SOURCES = dearmor.c \ $(common_source) gpgd_SOURCES = gpgd.c \ @@ -70,8 +69,11 @@ gpgd_SOURCES = gpgd.c \ LDADD = @INTLLIBS@ $(needed_libs) @ZLIBS@ -g10maint.c : g10.c - $(CPP) $(CFLAGS) $(DEFS) $(INCLUDES) -DIS_G10MAINT $< > $@ || rm $@ +gpgm_LDADD = g10maint.o $(LDADD) + +g10maint.o: g10.c + $(COMPILE) -DIS_G10MAINT -o g10maint.o -c g10.c + $(PROGRAMS): $(needed_libs) diff --git a/g10/Makefile.in b/g10/Makefile.in index 60aed6e28..b2a106c2b 100644 --- a/g10/Makefile.in +++ b/g10/Makefile.in @@ -95,7 +95,6 @@ l = @l@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl -I../intl EXTRA_DIST = OPTIONS pubring.asc OMIT_DEPENDENCIES = zlib.h zconf.h -BUILT_SOURCES = g10maint.c needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a bin_PROGRAMS = gpg gpgm gpgd @@ -120,6 +119,7 @@ common_source = \ elg.c \ dsa.c \ rsa.c \ + misc.c \ options.h \ openfile.c \ keyid.c \ @@ -151,14 +151,15 @@ gpg_SOURCES = g10.c \ decrypt.c \ keygen.c -gpgm_SOURCES = g10maint.c \ - dearmor.c \ +gpgm_SOURCES = dearmor.c \ $(common_source) gpgd_SOURCES = gpgd.c \ $(common_source) LDADD = @INTLLIBS@ $(needed_libs) @ZLIBS@ + +gpgm_LDADD = g10maint.o $(LDADD) mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs CONFIG_HEADER = ../config.h CONFIG_CLEAN_FILES = @@ -171,32 +172,31 @@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ gpg_OBJECTS = g10.o build-packet.o compress.o free-packet.o getkey.o \ pkclist.o skclist.o ringedit.o kbnode.o mainproc.o armor.o mdfilter.o \ -textfilter.o cipher.o elg.o dsa.o rsa.o openfile.o keyid.o trustdb.o \ -parse-packet.o passphrase.o pubkey-enc.o seckey-cert.o seskey.o \ -import.o export.o comment.o status.o sign.o plaintext.o encr-data.o \ -encode.o revoke.o keylist.o sig-check.o signal.o verify.o decrypt.o \ -keygen.o +textfilter.o cipher.o elg.o dsa.o rsa.o misc.o openfile.o keyid.o \ +trustdb.o parse-packet.o passphrase.o pubkey-enc.o seckey-cert.o \ +seskey.o import.o export.o comment.o status.o sign.o plaintext.o \ +encr-data.o encode.o revoke.o keylist.o sig-check.o signal.o verify.o \ +decrypt.o keygen.o gpg_LDADD = $(LDADD) gpg_DEPENDENCIES = ../cipher/libcipher.a ../mpi/libmpi.a \ ../util/libutil.a gpg_LDFLAGS = -gpgm_OBJECTS = g10maint.o dearmor.o build-packet.o compress.o \ -free-packet.o getkey.o pkclist.o skclist.o ringedit.o kbnode.o \ -mainproc.o armor.o mdfilter.o textfilter.o cipher.o elg.o dsa.o rsa.o \ -openfile.o keyid.o trustdb.o parse-packet.o passphrase.o pubkey-enc.o \ +gpgm_OBJECTS = dearmor.o build-packet.o compress.o free-packet.o \ +getkey.o pkclist.o skclist.o ringedit.o kbnode.o mainproc.o armor.o \ +mdfilter.o textfilter.o cipher.o elg.o dsa.o rsa.o misc.o openfile.o \ +keyid.o trustdb.o parse-packet.o passphrase.o pubkey-enc.o \ seckey-cert.o seskey.o import.o export.o comment.o status.o sign.o \ plaintext.o encr-data.o encode.o revoke.o keylist.o sig-check.o \ signal.o -gpgm_LDADD = $(LDADD) -gpgm_DEPENDENCIES = ../cipher/libcipher.a ../mpi/libmpi.a \ +gpgm_DEPENDENCIES = g10maint.o ../cipher/libcipher.a ../mpi/libmpi.a \ ../util/libutil.a gpgm_LDFLAGS = gpgd_OBJECTS = gpgd.o build-packet.o compress.o free-packet.o getkey.o \ pkclist.o skclist.o ringedit.o kbnode.o mainproc.o armor.o mdfilter.o \ -textfilter.o cipher.o elg.o dsa.o rsa.o openfile.o keyid.o trustdb.o \ -parse-packet.o passphrase.o pubkey-enc.o seckey-cert.o seskey.o \ -import.o export.o comment.o status.o sign.o plaintext.o encr-data.o \ -encode.o revoke.o keylist.o sig-check.o signal.o +textfilter.o cipher.o elg.o dsa.o rsa.o misc.o openfile.o keyid.o \ +trustdb.o parse-packet.o passphrase.o pubkey-enc.o seckey-cert.o \ +seskey.o import.o export.o comment.o status.o sign.o plaintext.o \ +encr-data.o encode.o revoke.o keylist.o sig-check.o signal.o gpgd_LDADD = $(LDADD) gpgd_DEPENDENCIES = ../cipher/libcipher.a ../mpi/libmpi.a \ ../util/libutil.a @@ -214,15 +214,14 @@ GZIP = --best DEP_FILES = .deps/armor.P .deps/build-packet.P .deps/cipher.P \ .deps/comment.P .deps/compress.P .deps/dearmor.P .deps/decrypt.P \ .deps/dsa.P .deps/elg.P .deps/encode.P .deps/encr-data.P .deps/export.P \ -.deps/free-packet.P .deps/g10.P .deps/g10maint .deps/g10maint.P \ -.deps/getkey.P .deps/gpgd.P .deps/import.P .deps/kbnode.P \ -.deps/keygen.P .deps/keyid.P .deps/keylist.P .deps/mainproc.P \ -.deps/mdfilter.P .deps/openfile.P .deps/parse-packet.P \ -.deps/passphrase.P .deps/pkclist.P .deps/plaintext.P .deps/pubkey-enc.P \ -.deps/revoke.P .deps/ringedit.P .deps/rsa.P .deps/seckey-cert.P \ -.deps/seskey.P .deps/sig-check.P .deps/sign.P .deps/signal.P \ -.deps/skclist.P .deps/status.P .deps/textfilter.P .deps/trustdb.P \ -.deps/verify.P +.deps/free-packet.P .deps/g10.P .deps/getkey.P .deps/gpgd.P \ +.deps/import.P .deps/kbnode.P .deps/keygen.P .deps/keyid.P \ +.deps/keylist.P .deps/mainproc.P .deps/mdfilter.P .deps/misc.P \ +.deps/openfile.P .deps/parse-packet.P .deps/passphrase.P \ +.deps/pkclist.P .deps/plaintext.P .deps/pubkey-enc.P .deps/revoke.P \ +.deps/ringedit.P .deps/rsa.P .deps/seckey-cert.P .deps/seskey.P \ +.deps/sig-check.P .deps/sign.P .deps/signal.P .deps/skclist.P \ +.deps/status.P .deps/textfilter.P .deps/trustdb.P .deps/verify.P SOURCES = $(gpg_SOURCES) $(gpgm_SOURCES) $(gpgd_SOURCES) OBJECTS = $(gpg_OBJECTS) $(gpgm_OBJECTS) $(gpgd_OBJECTS) @@ -421,8 +420,8 @@ installdirs mostlyclean-generic distclean-generic clean-generic \ maintainer-clean-generic clean mostlyclean distclean maintainer-clean -g10maint.c : g10.c - $(CPP) $(CFLAGS) $(DEFS) $(INCLUDES) -DIS_G10MAINT $< > $@ || rm $@ +g10maint.o: g10.c + $(COMPILE) -DIS_G10MAINT -o g10maint.o -c g10.c $(PROGRAMS): $(needed_libs) diff --git a/g10/cipher.c b/g10/cipher.c index 8e6c91aa9..3fe4e9ea4 100644 --- a/g10/cipher.c +++ b/g10/cipher.c @@ -67,42 +67,21 @@ cipher_filter( void *opaque, int control, randomize_buffer( temp, 8, 1 ); temp[8] = temp[6]; temp[9] = temp[7]; - if( cfx->dek->algo == CIPHER_ALGO_BLOWFISH - || cfx->dek->algo == CIPHER_ALGO_BLOWFISH128 ) { - cfx->bf_ctx = m_alloc_secure( sizeof *cfx->bf_ctx ); - blowfish_setkey( cfx->bf_ctx, cfx->dek->key, cfx->dek->keylen ); - blowfish_setiv( cfx->bf_ctx, NULL ); - blowfish_encode_cfb( cfx->bf_ctx, temp, temp, 10); - } - else if( cfx->dek->algo == CIPHER_ALGO_CAST ) { - cfx->cast5_ctx = m_alloc_secure( sizeof *cfx->cast5_ctx ); - cast5_setkey( cfx->cast5_ctx, cfx->dek->key, cfx->dek->keylen ); - cast5_setiv( cfx->cast5_ctx, NULL ); - cast5_encode_cfb( cfx->cast5_ctx, temp, temp, 10); - cast5_sync_cfb( cfx->cast5_ctx ); - } - else - log_bug("no cipher algo %d\n", cfx->dek->algo); - + cfx->cipher_hd = cipher_open( cfx->dek->algo, + CIPHER_MODE_AUTO_CFB, 1 ); + cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen ); + cipher_setiv( cfx->cipher_hd, NULL ); + cipher_encrypt( cfx->cipher_hd, temp, temp, 10); + cipher_sync( cfx->cipher_hd ); iobuf_write(a, temp, 10); cfx->header=1; } - - if( cfx->dek->algo == CIPHER_ALGO_BLOWFISH - || cfx->dek->algo == CIPHER_ALGO_BLOWFISH128 ) - blowfish_encode_cfb( cfx->bf_ctx, buf, buf, size); - else if( cfx->dek->algo == CIPHER_ALGO_CAST ) - cast5_encode_cfb( cfx->cast5_ctx, buf, buf, size); - + cipher_encrypt( cfx->cipher_hd, buf, buf, size); if( iobuf_write( a, buf, size ) ) rc = G10ERR_WRITE_FILE; } else if( control == IOBUFCTRL_FREE ) { - if( cfx->dek->algo == CIPHER_ALGO_BLOWFISH - || cfx->dek->algo == CIPHER_ALGO_BLOWFISH128 ) - m_free(cfx->bf_ctx); - else if( cfx->dek->algo == CIPHER_ALGO_CAST ) - m_free(cfx->cast5_ctx); + cipher_close(cfx->cipher_hd); } else if( control == IOBUFCTRL_DESC ) { *(char**)buf = "cipher_filter"; diff --git a/g10/comment.c b/g10/comment.c index 77b9a7ece..fef831cc7 100644 --- a/g10/comment.c +++ b/g10/comment.c @@ -79,9 +79,6 @@ make_mpi_comment_node( const char *s, MPI a ) nb1 = mpi_get_nbits( a ); p = buf = mpi_get_buffer( a, &n1, NULL ); - for( ; !*p && n1; p++, n1-- ) /* skip leading null bytes */ - ; - pkt = m_alloc_clear( sizeof *pkt ); pkt->pkttype = PKT_COMMENT; pkt->pkt.comment = m_alloc( sizeof *pkt->pkt.comment + n + 2 + n1 ); diff --git a/g10/encr-data.c b/g10/encr-data.c index 4f8aa897d..e7e56408a 100644 --- a/g10/encr-data.c +++ b/g10/encr-data.c @@ -35,9 +35,7 @@ static int decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len); typedef struct { - int is_cast5; - BLOWFISH_context *bf_ctx; - CAST5_context *cast5_ctx; + CIPHER_HANDLE cipher_hd; } decode_filter_ctx_t; @@ -50,7 +48,7 @@ decrypt_data( PKT_encrypted *ed, DEK *dek ) { decode_filter_ctx_t dfx; byte *p; - int c, i; + int rc, c, i; byte temp[16]; if( opt.verbose ) { @@ -60,25 +58,14 @@ decrypt_data( PKT_encrypted *ed, DEK *dek ) else log_info("encrypted with unknown algorithm %d\n", dek->algo ); } - if( dek->algo != CIPHER_ALGO_BLOWFISH - && dek->algo != CIPHER_ALGO_BLOWFISH128 - && dek->algo != CIPHER_ALGO_CAST ) - return G10ERR_CIPHER_ALGO; + if( (rc=check_cipher_algo(dek->algo)) ) + return rc; if( ed->len && ed->len < 10 ) log_bug("Nanu\n"); /* oops: found a bug */ - if( dek->algo == CIPHER_ALGO_CAST ) { - dfx.is_cast5 = 1; - dfx.cast5_ctx = m_alloc_secure( sizeof *dfx.cast5_ctx ); - cast5_setkey( dfx.cast5_ctx, dek->key, dek->keylen ); - cast5_setiv( dfx.cast5_ctx, NULL ); - } - else { - dfx.is_cast5 = 0; - dfx.bf_ctx = m_alloc_secure( sizeof *dfx.bf_ctx ); - blowfish_setkey( dfx.bf_ctx, dek->key, dek->keylen ); - blowfish_setiv( dfx.bf_ctx, NULL ); - } + dfx.cipher_hd = cipher_open( dek->algo, CIPHER_MODE_AUTO_CFB, 1 ); + cipher_setkey( dfx.cipher_hd, dek->key, dek->keylen ); + cipher_setiv( dfx.cipher_hd, NULL ); if( ed->len ) { iobuf_set_limit( ed->buf, ed->len ); @@ -93,15 +80,11 @@ decrypt_data( PKT_encrypted *ed, DEK *dek ) else temp[i] = c; } - if( dfx.is_cast5 ) { - cast5_decode_cfb( dfx.cast5_ctx, temp, temp, 10); - cast5_sync_cfb( dfx.cast5_ctx ); - } - else - blowfish_decode_cfb( dfx.bf_ctx, temp, temp, 10); + cipher_decrypt( dfx.cipher_hd, temp, temp, 10); + cipher_sync( dfx.cipher_hd ); p = temp; if( p[6] != p[8] || p[7] != p[9] ) { - m_free(dfx.bf_ctx); + cipher_close(dfx.cipher_hd); return G10ERR_BAD_KEY; } iobuf_push_filter( ed->buf, decode_filter, &dfx ); @@ -112,7 +95,7 @@ decrypt_data( PKT_encrypted *ed, DEK *dek ) else iobuf_clear_eof( ed->buf ); ed->buf = NULL; - m_free(dfx.bf_ctx); + cipher_close(dfx.cipher_hd); return 0; } @@ -132,12 +115,8 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len) buf[n] = c; } - if( n ) { - if( fc->is_cast5 ) - cast5_decode_cfb( fc->cast5_ctx, buf, buf, n); - else - blowfish_decode_cfb( fc->bf_ctx, buf, buf, n); - } + if( n ) + cipher_decrypt( fc->cipher_hd, buf, buf, n); else rc = -1; /* eof */ *ret_len = n; diff --git a/g10/filter.h b/g10/filter.h index fac1e0e2b..1bd8ba050 100644 --- a/g10/filter.h +++ b/g10/filter.h @@ -60,8 +60,7 @@ typedef struct { typedef struct { DEK *dek; u32 datalen; - BLOWFISH_context *bf_ctx; - CAST5_context *cast5_ctx; + CIPHER_HANDLE cipher_hd; int header; } cipher_filter_context_t; diff --git a/g10/getkey.c b/g10/getkey.c index edc5c8355..7868df951 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -554,6 +554,7 @@ lookup( PKT_public_cert *pkc, int mode, u32 *keyid, const char *name ) int rc; KBNODE keyblock = NULL; KBPOS kbpos; + int oldmode = set_packet_list_mode(0); rc = enum_keyblocks( 0, &kbpos, &keyblock ); if( rc ) { @@ -655,6 +656,7 @@ lookup( PKT_public_cert *pkc, int mode, u32 *keyid, const char *name ) leave: enum_keyblocks( 2, &kbpos, &keyblock ); /* close */ release_kbnode( keyblock ); + set_packet_list_mode(oldmode); return rc; } @@ -667,11 +669,12 @@ lookup_skc( PKT_secret_cert *skc, int mode, u32 *keyid, const char *name ) int rc; KBNODE keyblock = NULL; KBPOS kbpos; + int oldmode = set_packet_list_mode(0); rc = enum_keyblocks( 5 /* open secret */, &kbpos, &keyblock ); if( rc ) { if( rc == -1 ) - rc = G10ERR_NO_PUBKEY; + rc = G10ERR_NO_SECKEY; else if( rc ) log_error("enum_keyblocks(open secret) failed: %s\n", g10_errstr(rc) ); goto leave; @@ -761,13 +764,14 @@ lookup_skc( PKT_secret_cert *skc, int mode, u32 *keyid, const char *name ) keyblock = NULL; } if( rc == -1 ) - rc = G10ERR_NO_PUBKEY; + rc = G10ERR_NO_SECKEY; else if( rc ) log_error("enum_keyblocks(read) failed: %s\n", g10_errstr(rc)); leave: enum_keyblocks( 2, &kbpos, &keyblock ); /* close */ release_kbnode( keyblock ); + set_packet_list_mode(oldmode); return rc; } diff --git a/g10/keygen.c b/g10/keygen.c index 293d70a58..003d54bbb 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -40,42 +40,6 @@ #endif -static u16 -checksum_u16( unsigned n ) -{ - u16 a; - - a = (n >> 8) & 0xff; - a |= n & 0xff; - return a; -} - -static u16 -checksum( byte *p, unsigned n ) -{ - u16 a; - - for(a=0; n; n-- ) - a += *p++; - return a; -} - -static u16 -checksum_mpi( MPI a ) -{ - u16 csum; - byte *buffer; - unsigned nbytes; - - buffer = mpi_get_buffer( a, &nbytes, NULL ); - csum = checksum_u16( nbytes*8 ); - csum += checksum( buffer, nbytes ); - m_free( buffer ); - return csum; -} - - - static void write_uid( KBNODE root, const char *s ) { diff --git a/g10/keyid.c b/g10/keyid.c index 9f4ccdfb8..02e706fc2 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -64,16 +64,10 @@ v3_elg_fingerprint_md( PKT_public_cert *pkc ) nb1 = mpi_get_nbits(pkc->d.elg.p); p1 = buf1 = mpi_get_buffer( pkc->d.elg.p, &n1, NULL ); - for( ; !*p1 && n1; p1++, n1-- ) /* skip leading null bytes */ - ; nb2 = mpi_get_nbits(pkc->d.elg.g); p2 = buf2 = mpi_get_buffer( pkc->d.elg.g, &n2, NULL ); - for( ; !*p2 && n2; p2++, n2-- ) /* skip leading null bytes */ - ; nb3 = mpi_get_nbits(pkc->d.elg.y); p3 = buf3 = mpi_get_buffer( pkc->d.elg.y, &n3, NULL ); - for( ; !*p3 && n3; p3++, n3-- ) /* skip leading null bytes */ - ; /* calculate length of packet (1+4+2+1+2+n1+2+n2+2+n3) */ n = 14 + n1 + n2 + n3; @@ -117,16 +111,10 @@ elg_fingerprint_md( PKT_public_cert *pkc ) nb1 = mpi_get_nbits(pkc->d.elg.p); p1 = buf1 = mpi_get_buffer( pkc->d.elg.p, &n1, NULL ); - for( ; !*p1 && n1; p1++, n1-- ) /* skip leading null bytes */ - ; nb3 = mpi_get_nbits(pkc->d.elg.g); p3 = buf3 = mpi_get_buffer( pkc->d.elg.g, &n3, NULL ); - for( ; !*p3 && n3; p3++, n3-- ) - ; nb4 = mpi_get_nbits(pkc->d.elg.y); p4 = buf4 = mpi_get_buffer( pkc->d.elg.y, &n4, NULL ); - for( ; !*p4 && n4; p4++, n4-- ) - ; /* calculate length of packet */ n = 12 + n1 + n3 +n4 ; @@ -167,20 +155,12 @@ dsa_fingerprint_md( PKT_public_cert *pkc ) nb1 = mpi_get_nbits(pkc->d.dsa.p); p1 = buf1 = mpi_get_buffer( pkc->d.dsa.p, &n1, NULL ); - for( ; !*p1 && n1; p1++, n1-- ) /* skip leading null bytes */ - ; nb2 = mpi_get_nbits(pkc->d.dsa.q); p2 = buf2 = mpi_get_buffer( pkc->d.dsa.q, &n2, NULL ); - for( ; !*p2 && n2; p2++, n2-- ) - ; nb3 = mpi_get_nbits(pkc->d.dsa.g); p3 = buf3 = mpi_get_buffer( pkc->d.dsa.g, &n3, NULL ); - for( ; !*p3 && n3; p3++, n3-- ) - ; nb4 = mpi_get_nbits(pkc->d.dsa.y); p4 = buf4 = mpi_get_buffer( pkc->d.dsa.y, &n4, NULL ); - for( ; !*p4 && n4; p4++, n4-- ) - ; /* calculate length of packet */ n = 14 + n1 + n2 + n3 +n4 ; @@ -510,13 +490,9 @@ fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len ) md = md_open( DIGEST_ALGO_MD5, 0); p = buf = mpi_get_buffer( pkc->d.rsa.rsa_n, &n, NULL ); - for( ; !*p && n; p++, n-- ) - ; md_write( md, p, n ); m_free(buf); p = buf = mpi_get_buffer( pkc->d.rsa.rsa_e, &n, NULL ); - for( ; !*p && n; p++, n-- ) - ; md_write( md, p, n ); m_free(buf); md_final(md); diff --git a/g10/main.h b/g10/main.h index c162fd9cd..82f2373d7 100644 --- a/g10/main.h +++ b/g10/main.h @@ -21,6 +21,7 @@ #define G10_MAIN_H #include "types.h" #include "iobuf.h" +#include "mpi.h" #include "cipher.h" #include "keydb.h" @@ -39,6 +40,11 @@ typedef struct { void g10_exit(int rc); #endif +/*-- misc.c --*/ +u16 checksum_u16( unsigned n ); +u16 checksum( byte *p, unsigned n ); +u16 checksum_mpi( MPI a ); + /*-- encode.c --*/ int encode_symmetric( const char *filename ); int encode_store( const char *filename ); diff --git a/g10/misc.c b/g10/misc.c new file mode 100644 index 000000000..7424039bd --- /dev/null +++ b/g10/misc.c @@ -0,0 +1,63 @@ +/* misc.c - miscellaneous functions + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG 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 +#include +#include +#include +#include "util.h" +#include "main.h" + + +u16 +checksum_u16( unsigned n ) +{ + u16 a; + + a = (n >> 8) & 0xff; + a |= n & 0xff; + return a; +} + +u16 +checksum( byte *p, unsigned n ) +{ + u16 a; + + for(a=0; n; n-- ) + a += *p++; + return a; +} + +u16 +checksum_mpi( MPI a ) +{ + u16 csum; + byte *buffer; + unsigned nbytes; + + buffer = mpi_get_buffer( a, &nbytes, NULL ); + csum = checksum_u16( mpi_get_nbits(a) ); + csum += checksum( buffer, nbytes ); + m_free( buffer ); + return csum; +} + + diff --git a/g10/parse-packet.c b/g10/parse-packet.c index fe2c63c5b..26c112244 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -61,19 +61,6 @@ static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ); -#if 0 -static u16 -checksum( byte *p ) -{ - u16 n, a; - - n = *p++ << 8; - n |= *p++; - for(a=0; n; n-- ) - a += *p++; - return a; -} -#endif static unsigned short read_16(IOBUF inp) @@ -944,6 +931,9 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen, cert->csum = read_16(inp); pktlen -= 2; if( list_mode ) { + printf("\telg x: "); + mpi_print(stdout, cert->d.elg.x, mpi_print_mode ); + putchar('\n'); printf("\t[secret value x is not shown]\n" "\tchecksum: %04hx\n", cert->csum); } diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index f19af2189..7fd3101bd 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -100,6 +100,8 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) * * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) * + * (mpi_get_buffer already removed the leading zero). + * * RND are non-zero randow bytes. * A is the cipher algorithm * DEK is the encryption key (session key) with length k @@ -107,8 +109,7 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) */ if( DBG_CIPHER ) log_hexdump("DEK frame:", frame, nframe ); - for(n=0; n < nframe && !frame[n]; n++ ) /* skip leading zeroes */ - ; + n=0; if( n + 7 > nframe ) { rc = G10ERR_WRONG_SECKEY; goto leave; } if( frame[n] == 1 && frame[nframe-1] == 2 ) { diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index dada0fd20..a4ce96206 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -29,34 +29,8 @@ #include "mpi.h" #include "keydb.h" #include "cipher.h" - -#if BLOWFISH_BLOCKSIZE != 8 - #error unsupported blocksize -#endif -#if CAST5_BLOCKSIZE != 8 - #error unsupported blocksize -#endif - -static u16 -checksum_u16( unsigned n ) -{ - u16 a; - - a = (n >> 8) & 0xff; - a |= n & 0xff; - return a; -} - -static u16 -checksum( byte *p, unsigned n ) -{ - u16 a; - - for(a=0; n; n-- ) - a += *p++; - return a; -} - +#include "main.h" +#include "options.h" static int @@ -73,8 +47,7 @@ check_elg( PKT_secret_cert *cert ) if( cert->is_protected ) { /* remove the protection */ DEK *dek = NULL; MPI test_x; - BLOWFISH_context *blowfish_ctx=NULL; - CAST5_context *cast5_ctx=NULL; + CIPHER_HANDLE cipher_hd=NULL; switch( cert->protect.algo ) { case CIPHER_ALGO_NONE: BUG(); break; @@ -87,47 +60,37 @@ check_elg( PKT_secret_cert *cert ) else dek = get_passphrase_hash( keyid, NULL, NULL ); - if( cert->protect.algo == CIPHER_ALGO_CAST ) - cast5_ctx = m_alloc_secure( sizeof *cast5_ctx ); - else - blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx ); - - if( blowfish_ctx ) { - blowfish_setkey( blowfish_ctx, dek->key, dek->keylen ); - blowfish_setiv( blowfish_ctx, NULL ); - } - else { - cast5_setkey( cast5_ctx, dek->key, dek->keylen ); - cast5_setiv( cast5_ctx, NULL ); - } + cipher_hd = cipher_open( cert->protect.algo, + CIPHER_MODE_AUTO_CFB, 1); + cipher_setkey( cipher_hd, dek->key, dek->keylen ); + cipher_setiv( cipher_hd, NULL ); m_free(dek); /* pw is in secure memory, so m_free() burns it */ memcpy(save_iv, cert->protect.iv, 8 ); - if( blowfish_ctx ) - blowfish_decode_cfb( blowfish_ctx, cert->protect.iv, - cert->protect.iv, 8 ); - else - cast5_decode_cfb( cast5_ctx, cert->protect.iv, - cert->protect.iv, 8 ); + cipher_decrypt( cipher_hd, cert->protect.iv, cert->protect.iv, 8 ); mpi_set_secure(cert->d.elg.x ); /*fixme: maybe it is better to set the buffer secure with a * new get_buffer_secure() function */ buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL ); - csum = checksum_u16( nbytes*8 ); - if( blowfish_ctx ) - blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes ); - else - cast5_decode_cfb( cast5_ctx, buffer, buffer, nbytes ); - csum += checksum( buffer, nbytes ); + cipher_decrypt( cipher_hd, buffer, buffer, nbytes ); test_x = mpi_alloc_secure( mpi_get_nlimbs(cert->d.elg.x) ); mpi_set_buffer( test_x, buffer, nbytes, 0 ); + csum = checksum_mpi( test_x ); m_free( buffer ); - m_free( cast5_ctx ); - m_free( blowfish_ctx ); + cipher_close( cipher_hd ); /* now let's see wether we have used the right passphrase */ if( csum != cert->csum ) { - mpi_free(test_x); - memcpy( cert->protect.iv, save_iv, 8 ); - return G10ERR_BAD_PASS; + /* very bad kludge to work around an early bug */ + csum -= checksum_u16( mpi_get_nbits(test_x) ); + nbytes = mpi_get_nlimbs(test_x) * 4; + csum += checksum_u16( nbytes*8 ); + if( csum != cert->csum ) { + mpi_free(test_x); + memcpy( cert->protect.iv, save_iv, 8 ); + return G10ERR_BAD_PASS; + } + if( !opt.batch ) + log_info("Probably you have an old key - use " + "\"--change-passphrase\" to convert.\n"); } skey.p = cert->d.elg.p; @@ -151,12 +114,18 @@ check_elg( PKT_secret_cert *cert ) } } else { /* not protected */ - buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL ); - csum = checksum_u16( nbytes*8 ); - csum += checksum( buffer, nbytes ); - m_free( buffer ); - if( csum != cert->csum ) - return G10ERR_CHECKSUM; + csum = checksum_mpi( cert->d.elg.x ); + if( csum != cert->csum ) { + /* very bad kludge to work around an early bug */ + csum -= checksum_u16( mpi_get_nbits(cert->d.elg.x) ); + nbytes = mpi_get_nlimbs(cert->d.elg.x) * 4; + csum += checksum_u16( nbytes*8 ); + if( csum != cert->csum ) + return G10ERR_CHECKSUM; + if( !opt.batch ) + log_info("Probably you have an old key - use " + "\"--change-passphrase\" to convert.\n"); + } } return 0; @@ -177,8 +146,7 @@ check_dsa( PKT_secret_cert *cert ) if( cert->is_protected ) { /* remove the protection */ DEK *dek = NULL; MPI test_x; - BLOWFISH_context *blowfish_ctx=NULL; - CAST5_context *cast5_ctx=NULL; + CIPHER_HANDLE cipher_hd=NULL; switch( cert->protect.algo ) { case CIPHER_ALGO_NONE: BUG(); break; @@ -191,39 +159,23 @@ check_dsa( PKT_secret_cert *cert ) else dek = get_passphrase_hash( keyid, NULL, NULL ); - if( cert->protect.algo == CIPHER_ALGO_CAST ) { - cast5_ctx = m_alloc_secure( sizeof *cast5_ctx ); - cast5_setkey( cast5_ctx, dek->key, dek->keylen ); - cast5_setiv( cast5_ctx, NULL ); - } - else { - blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx ); - blowfish_setkey( blowfish_ctx, dek->key, dek->keylen ); - blowfish_setiv( blowfish_ctx, NULL ); - } + cipher_hd = cipher_open( cert->protect.algo, + CIPHER_MODE_AUTO_CFB, 1); + cipher_setkey( cipher_hd, dek->key, dek->keylen ); + cipher_setiv( cipher_hd, NULL ); m_free(dek); /* pw is in secure memory, so m_free() burns it */ memcpy(save_iv, cert->protect.iv, 8 ); - if( blowfish_ctx ) - blowfish_decode_cfb( blowfish_ctx, cert->protect.iv, - cert->protect.iv, 8 ); - else - cast5_decode_cfb( cast5_ctx, cert->protect.iv, - cert->protect.iv, 8 ); + cipher_decrypt( cipher_hd, cert->protect.iv, cert->protect.iv, 8 ); mpi_set_secure(cert->d.dsa.x ); /*fixme: maybe it is better to set the buffer secure with a * new get_buffer_secure() function */ buffer = mpi_get_buffer( cert->d.dsa.x, &nbytes, NULL ); - csum = checksum_u16( nbytes*8 ); - if( blowfish_ctx ) - blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes ); - else - cast5_decode_cfb( cast5_ctx, buffer, buffer, nbytes ); - csum += checksum( buffer, nbytes ); + cipher_decrypt( cipher_hd, buffer, buffer, nbytes ); test_x = mpi_alloc_secure( mpi_get_nlimbs(cert->d.dsa.x) ); mpi_set_buffer( test_x, buffer, nbytes, 0 ); + csum = checksum_mpi( test_x ); m_free( buffer ); - m_free( cast5_ctx ); - m_free( blowfish_ctx ); + cipher_close( cipher_hd ); /* now let's see wether we have used the right passphrase */ if( csum != cert->csum ) { mpi_free(test_x); @@ -253,10 +205,7 @@ check_dsa( PKT_secret_cert *cert ) } } else { /* not protected */ - buffer = mpi_get_buffer( cert->d.dsa.x, &nbytes, NULL ); - csum = checksum_u16( nbytes*8 ); - csum += checksum( buffer, nbytes ); - m_free( buffer ); + csum = checksum_mpi( cert->d.dsa.x ); if( csum != cert->csum ) return G10ERR_CHECKSUM; } @@ -267,6 +216,9 @@ check_dsa( PKT_secret_cert *cert ) #ifdef HAVE_RSA_CIPHER +/**************** + * FIXME: fix checksum stuff + */ static int check_rsa( PKT_secret_cert *cert ) { @@ -398,23 +350,29 @@ is_secret_key_protected( PKT_secret_cert *cert ) static int -do_protect( void (*fnc)(void *, byte *, byte *, unsigned), - void *fncctx, PKT_secret_cert *cert ) +do_protect( void (*fnc)(CIPHER_HANDLE, byte *, byte *, unsigned), + CIPHER_HANDLE fnc_hd, PKT_secret_cert *cert ) { byte *buffer; unsigned nbytes; switch( cert->pubkey_algo ) { case PUBKEY_ALGO_ELGAMAL: + /* recalculate the checksum, so that --change-passphrase + * can be used to convert from the faulty to the correct one + * wk 06.04.98: + * fixme: remove this some time in the future. + */ + cert->csum = checksum_mpi( cert->d.elg.x ); buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL ); - (*fnc)( fncctx, buffer, buffer, nbytes ); + (*fnc)( fnc_hd, buffer, buffer, nbytes ); mpi_set_buffer( cert->d.elg.x, buffer, nbytes, 0 ); m_free( buffer ); break; case PUBKEY_ALGO_DSA: buffer = mpi_get_buffer( cert->d.dsa.x, &nbytes, NULL ); - (*fnc)( fncctx, buffer, buffer, nbytes ); + (*fnc)( fnc_hd, buffer, buffer, nbytes ); mpi_set_buffer( cert->d.dsa.x, buffer, nbytes, 0 ); m_free( buffer ); break; @@ -437,33 +395,20 @@ protect_secret_key( PKT_secret_cert *cert, DEK *dek ) return 0; if( !cert->is_protected ) { /* okay, apply the protection */ - BLOWFISH_context *blowfish_ctx=NULL; - CAST5_context *cast5_ctx=NULL; + CIPHER_HANDLE cipher_hd=NULL; switch( cert->protect.algo ) { case CIPHER_ALGO_NONE: BUG(); break; case CIPHER_ALGO_BLOWFISH: - blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx ); - blowfish_setkey( blowfish_ctx, dek->key, dek->keylen ); - blowfish_setiv( blowfish_ctx, NULL ); - blowfish_encode_cfb( blowfish_ctx, cert->protect.iv, - cert->protect.iv, 8 ); - if( !do_protect( (void (*)(void*,byte*,byte*,unsigned)) - &blowfish_encode_cfb, blowfish_ctx, cert ) ) - cert->is_protected = 1; - m_free( blowfish_ctx ); - break; - case CIPHER_ALGO_CAST: - cast5_ctx = m_alloc_secure( sizeof *cast5_ctx ); - cast5_setkey( cast5_ctx, dek->key, dek->keylen ); - cast5_setiv( cast5_ctx, NULL ); - cast5_encode_cfb( cast5_ctx, cert->protect.iv, - cert->protect.iv, 8 ); - if( !do_protect( (void (*)(void*,byte*,byte*,unsigned)) - &cast5_encode_cfb, cast5_ctx, cert ) ) + cipher_hd = cipher_open( cert->protect.algo, + CIPHER_MODE_AUTO_CFB, 1 ); + cipher_setkey( cipher_hd, dek->key, dek->keylen ); + cipher_setiv( cipher_hd, NULL ); + cipher_encrypt( cipher_hd, cert->protect.iv, cert->protect.iv, 8 ); + if( !do_protect( &cipher_encrypt, cipher_hd, cert ) ) cert->is_protected = 1; - m_free( cast5_ctx ); + cipher_close( cipher_hd ); break; default: diff --git a/g10/seskey.c b/g10/seskey.c index b17302ea5..4ce8fe03b 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -78,6 +78,9 @@ encode_session_key( DEK *dek, unsigned nbits ) * * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) * + * (But how can we store the leading 0 - the external representaion + * of MPIs don't allow leading zeroes =:-) + * * RND are non-zero random bytes. * A is the cipher algorithm * DEK is the encryption key (session key) length k depends on the diff --git a/include/cipher.h b/include/cipher.h index 6135929cf..0dfcf3e17 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -32,8 +32,6 @@ #ifdef HAVE_RSA_CIPHER #include "../cipher/rsa.h" #endif -#include "../cipher/blowfish.h" -#include "../cipher/cast5.h" #include "../cipher/elgamal.h" #include "../cipher/dsa.h" #include "../cipher/random.h" @@ -66,22 +64,41 @@ typedef struct { byte key[20]; /* this is the largest used keylen */ } DEK; +typedef struct cipher_handle_s *CIPHER_HANDLE; + +#ifndef DEFINES_CIPHER_HANDLE +struct cipher_handle_s { char does_not_matter[1]; }; +#endif + +#define CIPHER_MODE_ECB 1 +#define CIPHER_MODE_CFB 2 +#define CIPHER_MODE_PHILS_CFB 3 +#define CIPHER_MODE_AUTO_CFB 4 + int cipher_debug_mode; +/*-- cipher.c --*/ +int string_to_cipher_algo( const char *string ); +const char * cipher_algo_to_string( int algo ); +int check_cipher_algo( int algo ); +CIPHER_HANDLE cipher_open( int algo, int mode, int secure ); +void cipher_close( CIPHER_HANDLE c ); +void cipher_setkey( CIPHER_HANDLE c, byte *key, unsigned keylen ); +void cipher_setiv( CIPHER_HANDLE c, const byte *iv ); +void cipher_encrypt( CIPHER_HANDLE c, byte *out, byte *in, unsigned nbytes ); +void cipher_decrypt( CIPHER_HANDLE c, byte *out, byte *in, unsigned nbytes ); +void cipher_sync( CIPHER_HANDLE c ); + /*-- misc.c --*/ -int string_to_cipher_algo( const char *string ); int string_to_pubkey_algo( const char *string ); int string_to_digest_algo( const char *string ); -const char * cipher_algo_to_string( int algo ); const char * pubkey_algo_to_string( int algo ); const char * digest_algo_to_string( int algo ); -int check_cipher_algo( int algo ); int check_pubkey_algo( int algo ); int check_digest_algo( int algo ); - /*-- smallprime.c --*/ extern ushort small_prime_numbers[]; diff --git a/mpi/ChangeLog b/mpi/ChangeLog index 5a2f03997..ca01cb4d8 100644 --- a/mpi/ChangeLog +++ b/mpi/ChangeLog @@ -1,3 +1,8 @@ +Mon Apr 6 12:38:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpicoder.c (mpi_get_buffer): Removed returned leading zeroes + and changed all callers. + Tue Mar 10 13:40:34 1998 Werner Koch (wk@isil.d.shuttle.de) * mpi-bit.c (mpi_clear_highbit): New. diff --git a/mpi/mpicoder.c b/mpi/mpicoder.c index 4d3f454ac..9362aff65 100644 --- a/mpi/mpicoder.c +++ b/mpi/mpicoder.c @@ -54,8 +54,6 @@ mpi_write( IOBUF out, MPI a ) iobuf_put(out, (nbits) ); p = buf = mpi_get_buffer( a, &n, NULL ); - for( ; !*p && n; p++, n-- ) - ; rc = iobuf_write( out, p, n ); m_free(buf); return rc; @@ -302,6 +300,13 @@ mpi_get_buffer( MPI a, unsigned *nbytes, int *sign ) #error please implement for this limb size. #endif } + + /* this is sub-optimal but we need to do the shift oepration because + * the caller has to free the returned buffer */ + for(p=buffer; !*p && *nbytes; p++, --*nbytes ) + ; + if( p != buffer ) + memmove(buffer,p, *nbytes); return buffer; } diff --git a/tools/ChangeLog b/tools/ChangeLog index e69de29bb..ccea6da89 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -0,0 +1,5 @@ +Tue Apr 7 19:50:41 1998 Werner Koch (wk@isil.d.shuttle.de) + + * bftest.c: Now supports all availabe ciphers. + + diff --git a/tools/Makefile.am b/tools/Makefile.am index e9bf4782e..2a33a0adb 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -4,20 +4,17 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl -I../intl needed_libs = ../cipher/libcipher.a ../util/libutil.a \ ../mpi/libmpi.a ../util/libutil.a -noinst_PROGRAMS = mpicalc bftest cast5test clean-sat +noinst_PROGRAMS = mpicalc bftest clean-sat mpicalc_SOURCES = mpicalc.c bftest_SOURCES = bftest.c -cast5test_SOURCES = cast5test.c - clean_sat_SOURCES = clean-sat.c mpicalc_LDADD = @INTLLIBS@ $(needed_libs) bftest_LDADD = @INTLLIBS@ $(needed_libs) -cast5test_LDADD = @INTLLIBS@ $(needed_libs) -mpicalc bftest cast5test: $(needed_libs) +mpicalc bftest: $(needed_libs) diff --git a/tools/Makefile.in b/tools/Makefile.in index 9b99174e0..6920c4cbe 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -96,19 +96,16 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl -I../intl needed_libs = ../cipher/libcipher.a ../util/libutil.a \ ../mpi/libmpi.a ../util/libutil.a -noinst_PROGRAMS = mpicalc bftest cast5test clean-sat +noinst_PROGRAMS = mpicalc bftest clean-sat mpicalc_SOURCES = mpicalc.c bftest_SOURCES = bftest.c -cast5test_SOURCES = cast5test.c - clean_sat_SOURCES = clean-sat.c mpicalc_LDADD = @INTLLIBS@ $(needed_libs) bftest_LDADD = @INTLLIBS@ $(needed_libs) -cast5test_LDADD = @INTLLIBS@ $(needed_libs) mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs CONFIG_HEADER = ../config.h CONFIG_CLEAN_FILES = @@ -127,10 +124,6 @@ bftest_OBJECTS = bftest.o bftest_DEPENDENCIES = ../cipher/libcipher.a ../util/libutil.a \ ../mpi/libmpi.a ../util/libutil.a bftest_LDFLAGS = -cast5test_OBJECTS = cast5test.o -cast5test_DEPENDENCIES = ../cipher/libcipher.a ../util/libutil.a \ -../mpi/libmpi.a ../util/libutil.a -cast5test_LDFLAGS = clean_sat_OBJECTS = clean-sat.o clean_sat_LDADD = $(LDADD) clean_sat_DEPENDENCIES = @@ -145,10 +138,9 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = tar GZIP = --best -DEP_FILES = .deps/bftest.P .deps/cast5test.P .deps/clean-sat.P \ -.deps/mpicalc.P -SOURCES = $(mpicalc_SOURCES) $(bftest_SOURCES) $(cast5test_SOURCES) $(clean_sat_SOURCES) -OBJECTS = $(mpicalc_OBJECTS) $(bftest_OBJECTS) $(cast5test_OBJECTS) $(clean_sat_OBJECTS) +DEP_FILES = .deps/bftest.P .deps/clean-sat.P .deps/mpicalc.P +SOURCES = $(mpicalc_SOURCES) $(bftest_SOURCES) $(clean_sat_SOURCES) +OBJECTS = $(mpicalc_OBJECTS) $(bftest_OBJECTS) $(clean_sat_OBJECTS) default: all @@ -195,10 +187,6 @@ bftest: $(bftest_OBJECTS) $(bftest_DEPENDENCIES) @rm -f bftest $(LINK) $(bftest_LDFLAGS) $(bftest_OBJECTS) $(bftest_LDADD) $(LIBS) -cast5test: $(cast5test_OBJECTS) $(cast5test_DEPENDENCIES) - @rm -f cast5test - $(LINK) $(cast5test_LDFLAGS) $(cast5test_OBJECTS) $(cast5test_LDADD) $(LIBS) - clean-sat: $(clean_sat_OBJECTS) $(clean_sat_DEPENDENCIES) @rm -f clean-sat $(LINK) $(clean_sat_LDFLAGS) $(clean_sat_OBJECTS) $(clean_sat_LDADD) $(LIBS) @@ -333,7 +321,7 @@ installdirs mostlyclean-generic distclean-generic clean-generic \ maintainer-clean-generic clean mostlyclean distclean maintainer-clean -mpicalc bftest cast5test: $(needed_libs) +mpicalc bftest: $(needed_libs) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/tools/bftest.c b/tools/bftest.c index 9657be350..a6816e19f 100644 --- a/tools/bftest.c +++ b/tools/bftest.c @@ -34,7 +34,7 @@ static void my_usage(void) { - fprintf(stderr, "usage: bftest [-e][-d] key\n"); + fprintf(stderr, "usage: bftest [-e][-d] algo key\n"); exit(1); } @@ -62,10 +62,10 @@ int main(int argc, char **argv) { int encode=0; - BLOWFISH_context ctx; + CIPHER_HANDLE hd; char buf[100]; - char iv[BLOWFISH_BLOCKSIZE]; int n, size=8; + int algo; #ifdef __MINGW32__ setmode( fileno(stdin), O_BINARY ); @@ -89,22 +89,24 @@ main(int argc, char **argv) argc--; argv++; size = 10; } - if( argc != 2 ) + if( argc != 3 ) my_usage(); argc--; argv++; + algo = string_to_cipher_algo( *argv ); + argc--; argv++; - blowfish_setkey( &ctx, *argv, strlen(*argv) ); - memset(iv,0, BLOWFISH_BLOCKSIZE); - blowfish_setiv( &ctx, iv ); + hd = cipher_open( algo, CIPHER_MODE_CFB, 0 ); + cipher_setkey( hd, *argv, strlen(*argv) ); + cipher_setiv( hd, NULL ); while( (n = fread( buf, 1, size, stdin )) > 0 ) { if( encode ) - blowfish_encode_cfb( &ctx, buf, buf, n ); + cipher_encrypt( hd, buf, buf, n ); else - blowfish_decode_cfb( &ctx, buf, buf, n ); + cipher_decrypt( hd, buf, buf, n ); if( fwrite( buf, 1, n, stdout) != n ) log_fatal("write error\n"); } - + cipher_close(hd); return 0; } diff --git a/tools/cast5test.c b/tools/cast5test.c deleted file mode 100644 index 04e24d7e5..000000000 --- a/tools/cast5test.c +++ /dev/null @@ -1,108 +0,0 @@ -/* cast5test.c - CAST5 test program - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * This file is part of GNUPG. - * - * GNUPG 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. - * - * GNUPG 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 -#include -#include -#include -#ifdef __MINGW32__ - #include - #include -#endif - -#include "util.h" -#include "cipher.h" -#include "i18n.h" - -static void -my_usage(void) -{ - fprintf(stderr, "usage: cast5test [-e][-d] key\n"); - exit(1); -} - -const char * -strusage( int level ) -{ - return default_strusage(level); -} - -static void -i18n_init(void) -{ - #ifdef ENABLE_NLS - #ifdef HAVE_LC_MESSAGES - setlocale( LC_MESSAGES, "" ); - #else - setlocale( LC_ALL, "" ); - #endif - bindtextdomain( PACKAGE, G10_LOCALEDIR ); - textdomain( PACKAGE ); - #endif -} - -int -main(int argc, char **argv) -{ - int encode=0; - CAST5_context ctx; - char buf[100]; - int n, size=100; - - #ifdef __MINGW32__ - setmode( fileno(stdin), O_BINARY ); - setmode( fileno(stdout), O_BINARY ); - #endif - - i18n_init(); - if( argc > 1 && !strcmp(argv[1], "-e") ) { - encode++; - argc--; argv++; - } - else if( argc > 1 && !strcmp(argv[1], "-E") ) { - encode++; - argc--; argv++; - size = 10; - } - else if( argc > 1 && !strcmp(argv[1], "-d") ) { - argc--; argv++; - } - else if( argc > 1 && !strcmp(argv[1], "-D") ) { - argc--; argv++; - size = 10; - } - if( argc != 2 ) - my_usage(); - argc--; argv++; - - cast5_setkey( &ctx, *argv, strlen(*argv) ); - cast5_setiv( &ctx, NULL ); - while( (n = fread( buf, 1, size, stdin )) > 0 ) { - if( encode ) - cast5_encode_cfb( &ctx, buf, buf, n ); - else - cast5_decode_cfb( &ctx, buf, buf, n ); - if( fwrite( buf, 1, n, stdout) != n ) - log_fatal("write error\n"); - } - - return 0; -} -