From a51cca90b6c8d3628d9b97a08f9370b3e249a9b6 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 24 Nov 1997 11:04:11 +0000 Subject: [PATCH] IDEA removed, signing works --- TODO | 7 +- cipher/Makefile.am | 2 - cipher/Makefile.in | 11 +- cipher/idea.c | 352 -------------------------------- cipher/idea.h | 51 ----- g10/Makefile.am | 4 +- g10/Makefile.in | 21 +- g10/build-packet.c | 38 ++++ g10/compress.c | 7 +- g10/encode.c | 59 +----- g10/filter.h | 1 + g10/free-packet.c | 15 ++ g10/g10.c | 47 +++-- g10/getkey.c | 150 ++++++++++---- g10/keydb.h | 1 + g10/keygen.c | 15 -- g10/main.h | 7 +- g10/mainproc.c | 35 +++- g10/mdfilter.c | 15 +- g10/{overwrite.c => openfile.c} | 42 +++- g10/packet.h | 10 +- g10/parse-packet.c | 10 +- g10/passphrase.c | 12 +- g10/plaintext.c | 16 +- g10/pubkey-enc.c | 3 +- g10/seckey-cert.c | 38 +--- g10/seskey.c | 41 +++- g10/sig-check.c | 64 +++--- include/cipher.h | 4 +- mpi/mpiutil.c | 4 + 30 files changed, 428 insertions(+), 654 deletions(-) delete mode 100644 cipher/idea.c delete mode 100644 cipher/idea.h rename g10/{overwrite.c => openfile.c} (66%) diff --git a/TODO b/TODO index 2a0365b8b..3698c1833 100644 --- a/TODO +++ b/TODO @@ -5,14 +5,12 @@ * add a way to difference between errors and eof in the underflow/flush function of iobuf. * filter all output read from the input when displaying it to the user. - * remove idea. * keyring editing * improve the prime number generator * remove some debugging stuff (e.g. the listing mode in mainproc) * add trust stuff * make ttyio.c work (hide passwords etc..) - * add signal handling - * add writing of signatures and checking of detached signatures. + * add detached signatures * add option file handling. * use correct ASN values for DEK encoding * add checking of armor trailers @@ -20,11 +18,12 @@ * add real secure memory * look for a way to reuse RSA signatures * add ElGamal and make it the default one. - * find a way to remove the arnor filter after it + * find a way to remove the armor filter after it has detected, that the data is not armored. * Use the Chines Remainder Theorem to speed up RSA calculations. * remove all "Fixmes" * add credits for the MPI lib. * speed up the RIPE-MD-160 + * add signal handling * enable a SIGSEGV handler while using zlib functions diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 8a543e380..becf3a104 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -11,8 +11,6 @@ cipher_SOURCES = blowfish.c \ elgamal.h \ gost.c \ gost.h \ - idea.c \ - idea.h \ md5.c \ md5.h \ primegen.c \ diff --git a/cipher/Makefile.in b/cipher/Makefile.in index faee770be..16da11089 100644 --- a/cipher/Makefile.in +++ b/cipher/Makefile.in @@ -48,8 +48,6 @@ cipher_SOURCES = blowfish.c \ elgamal.h \ gost.c \ gost.h \ - idea.c \ - idea.h \ md5.c \ md5.h \ primegen.c \ @@ -79,8 +77,8 @@ LIBS = @LIBS@ COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) LINK = $(CC) $(LDFLAGS) -o $@ cipher_LIBADD = -cipher_OBJECTS = blowfish.o elgamal.o gost.o idea.o md5.o primegen.o \ -random.o rmd160.o rsa.o smallprime.o +cipher_OBJECTS = blowfish.o elgamal.o gost.o md5.o primegen.o random.o \ +rmd160.o rsa.o smallprime.o EXTRA_cipher_SOURCES = LIBFILES = libcipher.a AR = ar @@ -98,9 +96,8 @@ DEP_DISTFILES = $(DIST_COMMON) $(SOURCES) $(BUILT_SOURCES) $(HEADERS) \ TAR = tar DEP_FILES = $(srcdir)/.deps/blowfish.P $(srcdir)/.deps/elgamal.P \ -$(srcdir)/.deps/gost.P $(srcdir)/.deps/idea.P $(srcdir)/.deps/md5.P \ -$(srcdir)/.deps/primegen.P $(srcdir)/.deps/random.P \ -$(srcdir)/.deps/rmd160.P $(srcdir)/.deps/rsa.P \ +$(srcdir)/.deps/gost.P $(srcdir)/.deps/md5.P $(srcdir)/.deps/primegen.P \ +$(srcdir)/.deps/random.P $(srcdir)/.deps/rmd160.P $(srcdir)/.deps/rsa.P \ $(srcdir)/.deps/smallprime.P SOURCES = $(cipher_SOURCES) OBJECTS = $(cipher_OBJECTS) diff --git a/cipher/idea.c b/cipher/idea.c deleted file mode 100644 index 3d1b01a98..000000000 --- a/cipher/idea.c +++ /dev/null @@ -1,352 +0,0 @@ -/* idea.c - IDEA function - * Copyright (c) 1997 by Werner Koch (dd9jn) - * - * ATTENTION: This code patented and needs a license for any commercial use. - * - * The code herin is take from: - * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. - * ISBN 0-471-11709-9. . - * - * This file is part of G10. - * - * G10 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. - * - * G10 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 "types.h" -#include "idea.h" - - - -static u16 -mul_inv( u16 x ) -{ - u16 t0, t1; - u16 q, y; - - if( x < 2 ) - return x; - t1 = 0x10001L / x; - y = 0x10001L % x; - if( y == 1 ) - return (1-t1) & 0xffff; - - t0 = 1; - do { - q = x / y; - x = x % y; - t0 += q * t1; - if( x == 1 ) - return t0; - q = y / x; - y = y % x; - t1 += q * t0; - } while( y != 1 ); - return (1-t1) & 0xffff; -} - - - -static void -expand_key( byte *userkey, u16 *ek ) -{ - int i,j; - - for(j=0; j < 8; j++ ) { - ek[j] = (*userkey << 8) + userkey[1]; - userkey += 2; - } - for(i=0; j < IDEA_KEYLEN; j++ ) { - i++; - ek[i+7] = ek[i&7] << 9 | ek[(i+1)&7] >> 7; - ek += i & 8; - i &= 7; - } -} - - -static void -invert_key( u16 *ek, u16 dk[IDEA_KEYLEN] ) -{ - int i; - u16 t1, t2, t3; - u16 temp[IDEA_KEYLEN]; - u16 *p = temp + IDEA_KEYLEN; - - t1 = mul_inv( *ek++ ); - t2 = -*ek++; - t3 = -*ek++; - *--p = mul_inv( *ek++ ); - *--p = t3; - *--p = t2; - *--p = t1; - - for(i=0; i < IDEA_ROUNDS-1; i++ ) { - t1 = *ek++; - *--p = *ek++; - *--p = t1; - - t1 = mul_inv( *ek++ ); - t2 = -*ek++; - t3 = -*ek++; - *--p = mul_inv( *ek++ ); - *--p = t3; - *--p = t2; - *--p = t1; - } - t1 = *ek++; - *--p = *ek++; - *--p = t1; - - t1 = mul_inv( *ek++ ); - t2 = -*ek++; - t3 = -*ek++; - *--p = mul_inv( *ek++ ); - *--p = t3; - *--p = t2; - *--p = t1; - memcpy(dk, temp, sizeof(temp) ); - memset(temp, 0, sizeof(temp) ); /* burn temp */ -} - - -static void -cipher( byte *outbuf, byte *inbuf, u16 *key ) -{ - u16 x1, x2, x3,x4, s2, s3; - u16 *in, *out; - int r = IDEA_ROUNDS; - #define MUL(x,y) \ - do {u16 _t16; u32 _t32; \ - if( (_t16 = (y)) ) { \ - if( (x = (x)&0xffff) ) { \ - _t32 = (u32)x * _t16; \ - x = _t32 & 0xffff; \ - _t16 = _t32 >> 16; \ - x = ((x)-_t16) + (x<_t16?1:0); \ - } \ - else { \ - x = 1 - _t16; \ - } \ - } \ - else { \ - x = 1 - x; \ - } \ - } while(0) - - in = (u16*)inbuf; - x1 = *in++; - x2 = *in++; - x3 = *in++; - x4 = *in; - #ifdef HAVE_LITTLE_ENDIAN - x1 = (x1>>8) | (x1<<8); - x2 = (x2>>8) | (x2<<8); - x3 = (x3>>8) | (x3<<8); - x4 = (x4>>8) | (x4<<8); - #endif - do { - MUL(x1, *key++); - x2 += *key++; - x3 += *key++; - MUL(x4, *key++ ); - - s3 = x3; - x3 ^= x1; - MUL(x3, *key++); - s2 = x2; - x2 ^=x4; - x2 += x3; - MUL(x2, *key++); - x3 += x2; - - x1 ^= x2; - x4 ^= x3; - - x2 ^= s3; - x3 ^= s2; - } while( --r ); - MUL(x1, *key++); - x3 += *key++; - x2 += *key++; - MUL(x4, *key); - - out = (u16*)outbuf; - #ifdef HAVE_LITTLE_ENDIAN - *out++ = (x1>>8) | (x1<<8); - *out++ = (x3>>8) | (x3<<8); - *out++ = (x2>>8) | (x2<<8); - *out = (x4>>8) | (x4<<8); - #else - *out++ = x1; - *out++ = x3; - *out++ = x2; - *out = x4; - #endif - #undef MUL -} - - -void -idea_setkey( IDEA_context *c, byte *key ) -{ - expand_key( key, c->ek ); - invert_key( c->ek, c->dk ); -} - -void -idea_setiv( IDEA_context *c, byte *iv ) -{ - if( iv ) - memcpy( c->iv, iv, IDEA_BLOCKSIZE ); - else - memset( c->iv, 0, IDEA_BLOCKSIZE ); - c->nleft = 0; -} - - -void -idea_encode( IDEA_context *c, byte *outbuf, byte *inbuf, unsigned nblocks ) -{ - unsigned n; - - for(n=0; n < nblocks; n++ ) { - cipher( outbuf, inbuf, c->ek ); - inbuf += 8; - outbuf += 8; - } -} - - -void -idea_decode( IDEA_context *c, byte *outbuf, byte *inbuf, unsigned nblocks ) -{ - unsigned n; - - for(n=0; n < nblocks; n++ ) { - cipher( outbuf, inbuf, c->dk ); - inbuf += 8; - outbuf += 8; - } -} - - -static void -cfbshift( byte *iv, byte *buf, unsigned count) -{ - unsigned n; - - if( count ) { - for( n = IDEA_BLOCKSIZE - count; n; n-- ) - *iv++ = iv[count]; - for( ; count; count-- ) - *iv++ = *buf++; - } -} - - -/**************** - * FIXME: Make use of bigger chunks - */ -static void -xorblock( byte *out, byte *a, byte *b, unsigned count ) -{ - for( ; count ; count--, a++, b++ ) - *out++ = *a ^ *b ; -} - - -void -idea_encode_cfb( IDEA_context *c, byte *outbuf, byte *inbuf, unsigned nbytes) -{ - byte temp[IDEA_BLOCKSIZE]; - - while( nbytes >= IDEA_BLOCKSIZE ) { - cipher( temp, c->iv, c->ek ); - xorblock( outbuf, inbuf, temp, IDEA_BLOCKSIZE); - cfbshift( c->iv, outbuf, IDEA_BLOCKSIZE ); - nbytes -= IDEA_BLOCKSIZE; - inbuf += IDEA_BLOCKSIZE; - outbuf += IDEA_BLOCKSIZE; - } - if( nbytes ) { - cipher( temp, c->iv, c->ek ); - xorblock( outbuf, inbuf, temp, nbytes ); - cfbshift( c->iv, outbuf, nbytes ); - } -} - - -void -idea_decode_cfb( IDEA_context *c, byte *outbuf, byte *inbuf, unsigned nbytes) -{ - byte t, *ivptr; - - ivptr = c->iv + IDEA_BLOCKSIZE - c->nleft; - if( nbytes <= c->nleft ) { - c->nleft -= nbytes; - for( ; nbytes ; nbytes--, ivptr++, inbuf++ ) { - t = *ivptr; - *outbuf++ = t ^ (*ivptr = *inbuf) ; - } - return; - } - - nbytes -= c->nleft; - for( ; c->nleft ; c->nleft--, ivptr++, inbuf++ ) { - t = *ivptr; - *outbuf++ = t ^ (*ivptr = *inbuf) ; - } - - while( nbytes >= IDEA_BLOCKSIZE ) { - memcpy(c->lastcipher, c->iv, IDEA_BLOCKSIZE); - cipher( c->iv, c->iv, c->ek ); - c->nleft = IDEA_BLOCKSIZE; - nbytes -= IDEA_BLOCKSIZE; - ivptr = c->iv; - for( ; c->nleft; c->nleft--, ivptr++, inbuf++ ) { - t = *ivptr; - *outbuf++ = t ^ (*ivptr = *inbuf) ; - } - } - memcpy(c->lastcipher, c->iv, IDEA_BLOCKSIZE); - cipher( c->iv, c->iv, c->ek ); - c->nleft = IDEA_BLOCKSIZE - nbytes; - ivptr = c->iv; - for( ; nbytes; nbytes--, ivptr++, inbuf++ ) { - t = *ivptr; - *outbuf++ = t ^ (*ivptr = *inbuf) ; - } -} - - -/**************** - * This is used for the special way IDEA CFB is used in PGP - */ -void -idea_sync_cfb( IDEA_context *c ) -{ - if( c->nleft ) { - memmove(c->iv + c->nleft, c->iv, IDEA_BLOCKSIZE - c->nleft ); - memcpy(c->iv, c->lastcipher + IDEA_BLOCKSIZE - c->nleft, c->nleft); - c->nleft = 0; - } -} - - diff --git a/cipher/idea.h b/cipher/idea.h deleted file mode 100644 index efebf5a56..000000000 --- a/cipher/idea.h +++ /dev/null @@ -1,51 +0,0 @@ -/* idea.h - * Copyright (c) 1997 by Werner Koch (dd9jn) - * - * ATTENTION: This code patented and needs a license for any commercial use. - * - * This file is part of G10. - * - * G10 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. - * - * G10 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 - */ -#ifndef G10_IDEA_H -#define G10_IDEA_H - -#include "types.h" - -#define IDEA_KEYSIZE 16 -#define IDEA_BLOCKSIZE 8 -#define IDEA_ROUNDS 8 -#define IDEA_KEYLEN (6*IDEA_ROUNDS+4) - -typedef struct { - u16 ek[IDEA_KEYLEN]; - u16 dk[IDEA_KEYLEN]; - byte iv[IDEA_BLOCKSIZE]; - byte lastcipher[IDEA_BLOCKSIZE]; - int nleft; -} IDEA_context; - -void idea_setkey( IDEA_context *c, byte *key ); -void idea_setiv( IDEA_context *c, byte *iv ); -void idea_encode( IDEA_context *c, byte *out, byte *in, unsigned nblocks ); -void idea_decode( IDEA_context *c, byte *out, byte *in, unsigned nblocks ); -void idea_encode_cfb( IDEA_context *c, byte *outbuf, - byte *inbuf, unsigned nbytes); -void idea_decode_cfb( IDEA_context *c, byte *outbuf, - byte *inbuf, unsigned nbytes); -void idea_sync_cfb( IDEA_context *c ); - - -#endif /*G10_IDEA_H*/ diff --git a/g10/Makefile.am b/g10/Makefile.am index 22a38898c..a8d13eaec 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -20,7 +20,7 @@ g10_SOURCES = g10.c \ mdfilter.c \ cipher.c \ options.h \ - overwrite.c \ + openfile.c \ packet.h \ parse-packet.c \ passphrase.c \ @@ -28,6 +28,8 @@ g10_SOURCES = g10.c \ pubkey-enc.c \ seckey-cert.c \ seskey.c \ + sign.c \ + comment.c \ sig-check.c diff --git a/g10/Makefile.in b/g10/Makefile.in index ed387218a..d7b08551d 100644 --- a/g10/Makefile.in +++ b/g10/Makefile.in @@ -58,7 +58,7 @@ g10_SOURCES = g10.c \ mdfilter.c \ cipher.c \ options.h \ - overwrite.c \ + openfile.c \ packet.h \ parse-packet.c \ passphrase.c \ @@ -66,6 +66,8 @@ g10_SOURCES = g10.c \ pubkey-enc.c \ seckey-cert.c \ seskey.c \ + sign.c \ + comment.c \ sig-check.c LDADD = -L ../cipher -L ../mpi -L ../util -lcipher -lmpi -lutil -lz @@ -88,8 +90,8 @@ COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) LINK = $(CC) $(LDFLAGS) -o $@ g10_OBJECTS = g10.o build-packet.o compress.o encode.o encr-data.o \ free-packet.o getkey.o keygen.o mainproc.o armor.o mdfilter.o cipher.o \ -overwrite.o parse-packet.o passphrase.o plaintext.o pubkey-enc.o \ -seckey-cert.o seskey.o sig-check.o +openfile.o parse-packet.o passphrase.o plaintext.o pubkey-enc.o \ +seckey-cert.o seskey.o sign.o comment.o sig-check.o EXTRA_g10_SOURCES = g10_LDADD = $(LDADD) DIST_COMMON = Makefile.am Makefile.in @@ -105,15 +107,16 @@ DEP_DISTFILES = $(DIST_COMMON) $(SOURCES) $(BUILT_SOURCES) $(HEADERS) \ TAR = tar DEP_FILES = $(srcdir)/.deps/armor.P $(srcdir)/.deps/build-packet.P \ -$(srcdir)/.deps/cipher.P $(srcdir)/.deps/compress.P \ -$(srcdir)/.deps/encode.P $(srcdir)/.deps/encr-data.P \ -$(srcdir)/.deps/free-packet.P $(srcdir)/.deps/g10.P \ -$(srcdir)/.deps/getkey.P $(srcdir)/.deps/keygen.P \ +$(srcdir)/.deps/cipher.P $(srcdir)/.deps/comment.P \ +$(srcdir)/.deps/compress.P $(srcdir)/.deps/encode.P \ +$(srcdir)/.deps/encr-data.P $(srcdir)/.deps/free-packet.P \ +$(srcdir)/.deps/g10.P $(srcdir)/.deps/getkey.P $(srcdir)/.deps/keygen.P \ $(srcdir)/.deps/mainproc.P $(srcdir)/.deps/mdfilter.P \ -$(srcdir)/.deps/overwrite.P $(srcdir)/.deps/parse-packet.P \ +$(srcdir)/.deps/openfile.P $(srcdir)/.deps/parse-packet.P \ $(srcdir)/.deps/passphrase.P $(srcdir)/.deps/plaintext.P \ $(srcdir)/.deps/pubkey-enc.P $(srcdir)/.deps/seckey-cert.P \ -$(srcdir)/.deps/seskey.P $(srcdir)/.deps/sig-check.P +$(srcdir)/.deps/seskey.P $(srcdir)/.deps/sig-check.P \ +$(srcdir)/.deps/sign.P SOURCES = $(g10_SOURCES) OBJECTS = $(g10_OBJECTS) diff --git a/g10/build-packet.c b/g10/build-packet.c index 945758e98..5bda607b9 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -43,6 +43,7 @@ static u32 calc_plaintext( PKT_plaintext *pt ); static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ); static int do_encr_data( IOBUF out, int ctb, PKT_encr_data *ed ); static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd ); +static int do_signature( IOBUF out, int ctb, PKT_signature *sig ); static int calc_header_length( u32 len ); static int write_16(IOBUF inp, u16 a); @@ -92,6 +93,8 @@ build_packet( IOBUF out, PACKET *pkt ) rc = do_compressed( out, ctb, pkt->pkt.compressed ); break; case PKT_SIGNATURE: + rc = do_signature( out, ctb, pkt->pkt.signature ); + break; case PKT_RING_TRUST: default: log_bug("invalid packet type in build_packet()"); @@ -255,6 +258,9 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) } + + + static u32 calc_plaintext( PKT_plaintext *pt ) { @@ -323,6 +329,38 @@ do_compressed( IOBUF out, int ctb, PKT_compressed *cd ) } +static int +do_signature( IOBUF out, int ctb, PKT_signature *sig ) +{ + int rc = 0; + IOBUF a = iobuf_temp(); + + write_version( a, ctb ); + iobuf_put(a, 5 ); /* constant */ + iobuf_put(a, sig->sig_class ); + write_32(a, sig->timestamp ); + write_32(a, sig->keyid[0] ); + write_32(a, sig->keyid[1] ); + iobuf_put(a, sig->pubkey_algo ); + if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) { + iobuf_put(a, sig->d.rsa.digest_algo ); + iobuf_put(a, sig->d.rsa.digest_start[0] ); + iobuf_put(a, sig->d.rsa.digest_start[1] ); + mpi_encode(a, sig->d.rsa.rsa_integer ); + } + else { + rc = G10ERR_PUBKEY_ALGO; + goto leave; + } + + write_header(out, ctb, iobuf_get_temp_length(a) ); + if( iobuf_write_temp( out, a ) ) + rc = G10ERR_WRITE_FILE; + + leave: + iobuf_close(a); + return rc; +} static int diff --git a/g10/compress.c b/g10/compress.c index a4fc48f88..980f5f976 100644 --- a/g10/compress.c +++ b/g10/compress.c @@ -124,6 +124,7 @@ do_uncompress( compress_filter_context_t *zfx, z_stream *zs, IOBUF a, size_t *ret_len ) { int zrc; + int rc=0; size_t n; byte *p; int c; @@ -147,7 +148,9 @@ do_uncompress( compress_filter_context_t *zfx, z_stream *zs, if( DBG_FILTER ) log_debug("inflate returned: avail_in=%u, avail_out=%u, zrc=%d\n", (unsigned)zs->avail_in, (unsigned)zs->avail_out, zrc); - if( zrc != Z_OK && zrc != Z_STREAM_END ) { + if( zrc == Z_STREAM_END ) + rc = -1; /* eof */ + else if( zrc != Z_OK ) { if( zs->msg ) log_fatal("zlib inflate problem: %s\n", zs->msg ); else @@ -157,7 +160,7 @@ do_uncompress( compress_filter_context_t *zfx, z_stream *zs, *ret_len = zfx->outbufsize - zs->avail_out; if( DBG_FILTER ) log_debug("do_uncompress: returning %u bytes\n", (unsigned)*ret_len ); - return 0; + return rc; } diff --git a/g10/encode.c b/g10/encode.c index 272462d47..9ef2c1099 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -1,4 +1,4 @@ -/* encode.c - encode/sign data +/* encode.c - encode data * Copyright (c) 1997 by Werner Koch (dd9jn) * * This file is part of G10. @@ -39,7 +39,6 @@ static int encode_simple( const char *filename, int mode ); -static IOBUF open_outfile( const char *iname ); /**************** @@ -62,22 +61,6 @@ encode_store( const char *filename ) return encode_simple( filename, 0 ); } -static void -write_comment( IOBUF out, const char *s ) -{ - PACKET pkt; - size_t n = strlen(s); - int rc; - - pkt.pkttype = PKT_COMMENT; - pkt.pkt.comment = m_alloc( sizeof *pkt.pkt.comment + n - 1 ); - pkt.pkt.comment->len = n; - strcpy(pkt.pkt.comment->data, s); - if( (rc = build_packet( out, &pkt )) ) - log_error("build_packet(comment) failed: %s\n", g10_errstr(rc) ); - free_packet( &pkt ); -} - static int encode_simple( const char *filename, int mode ) @@ -335,44 +318,4 @@ encode_crypt( const char *filename, STRLIST remusr ) } -/**************** - * Make an output filename for the inputfile INAME. - * Returns an - */ -static IOBUF -open_outfile( const char *iname ) -{ - IOBUF a = NULL; - int rc; - - if( (!iname && !opt.outfile) || opt.outfile_is_stdout ) { - if( !(a = iobuf_create(NULL)) ) - log_error("can't open [stdout]: %s\n", strerror(errno) ); - else if( opt.verbose ) - log_info("writing to stdout\n"); - } - else { - char *buf=NULL; - const char *name; - - if( opt.outfile ) - name = opt.outfile; - else { - buf = m_alloc(strlen(iname)+4+1); - strcpy(stpcpy(buf,iname), ".g10"); - name = buf; - } - if( !(rc=overwrite_filep( name )) ) { - if( !(a = iobuf_create( name )) ) - log_error("can't create %s: %s\n", name, strerror(errno) ); - else if( opt.verbose ) - log_info("writing to '%s'\n", name ); - } - else if( rc != -1 ) - log_error("oops: overwrite_filep(%s): %s\n", name, g10_errstr(rc) ); - m_free(buf); - } - return a; -} - diff --git a/g10/filter.h b/g10/filter.h index 3ca222186..acbb4ca25 100644 --- a/g10/filter.h +++ b/g10/filter.h @@ -61,6 +61,7 @@ typedef struct { /*-- mdfilter.c --*/ int md_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len); +void free_md_filter_context( md_filter_context_t *mfx ); /*-- armor.c --*/ int armor_filter( void *opaque, int control, diff --git a/g10/free-packet.c b/g10/free-packet.c index f4f38baa4..7d6eb4aaa 100644 --- a/g10/free-packet.c +++ b/g10/free-packet.c @@ -89,6 +89,21 @@ free_seckey_cert( PKT_seckey_cert *cert ) m_free(cert); } +PKT_seckey_cert * +copy_seckey_cert( PKT_seckey_cert *d, PKT_seckey_cert *s ) +{ + if( !d ) + d = m_alloc(sizeof *d); + memcpy( d, s, sizeof *d ); + d->d.rsa.rsa_n = mpi_copy( s->d.rsa.rsa_n ); + d->d.rsa.rsa_e = mpi_copy( s->d.rsa.rsa_e ); + d->d.rsa.rsa_d = mpi_copy( s->d.rsa.rsa_d ); + d->d.rsa.rsa_p = mpi_copy( s->d.rsa.rsa_p ); + d->d.rsa.rsa_q = mpi_copy( s->d.rsa.rsa_q ); + d->d.rsa.rsa_u = mpi_copy( s->d.rsa.rsa_u ); + return d; +} + void free_comment( PKT_comment *rem ) { diff --git a/g10/g10.c b/g10/g10.c index 89f0c84a3..496fda348 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -77,6 +77,8 @@ set_debug(void) mpi_debug_mode = 1; if( opt.debug & DBG_CIPHER_VALUE ) cipher_debug_mode = 1; + if( opt.debug & DBG_IOBUF_VALUE ) + iobuf_debug_mode = 1; } @@ -116,10 +118,10 @@ main( int argc, char **argv ) ARGPARSE_ARGS pargs = { &argc, &argv, 0 }; IOBUF a; int rc; - enum { aNull, aSym, aStore, aEncr, aPrimegen, aKeygen, + enum { aNull, aSym, aStore, aEncr, aPrimegen, aKeygen, aSign, aSignEncr, } action = aNull; const char *fname, *fname_print; - STRLIST sl, remusr= NULL; + STRLIST sl, remusr= NULL, locusr=NULL; int nrings=0; armor_filter_context_t afx; @@ -131,13 +133,26 @@ main( int argc, char **argv ) opt.compress = pargs.r.ret_int; break; case 'a': opt.armor = 1; break; + case 'b': opt.batch = 1; break; case 'c': action = aSym; break; - case 'e': action = aEncr; break; case 'o': opt.outfile = pargs.r.ret_str; if( opt.outfile[0] == '-' && !opt.outfile[1] ) opt.outfile_is_stdout = 1; break; - case 'b': opt.batch = 1; break; + case 'e': action = action == aSign? aSignEncr : aEncr; break; + case 's': action = action == aEncr? aSignEncr : aSign; break; + case 'l': /* store the local users */ + sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str)); + strcpy(sl->d, pargs.r.ret_str); + sl->next = locusr; + locusr = sl; + break; + case 'r': /* store the remote users */ + sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str)); + strcpy(sl->d, pargs.r.ret_str); + sl->next = remusr; + remusr = sl; + break; case 501: opt.answer_yes = 1; break; case 502: opt.answer_no = 1; break; case 507: action = aStore; break; @@ -146,12 +161,6 @@ main( int argc, char **argv ) case 510: opt.debug |= pargs.r.ret_ulong; break; case 511: opt.debug = ~0; break; case 512: opt.cache_all = 1; break; - case 'r': /* store the remote users */ - sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str)); - strcpy(sl->d, pargs.r.ret_str); - sl->next = remusr; - remusr = sl; - break; case 513: action = aPrimegen; break; case 514: action = aKeygen; break; default : pargs.err = 2; break; @@ -187,16 +196,25 @@ main( int argc, char **argv ) if( argc > 1 ) usage(1); if( (rc = encode_symmetric(fname)) ) - log_error("encode_symmetric('%s'): %s\n", - fname_print, g10_errstr(rc) ); + log_error("encode_symmetric('%s'): %s\n", fname_print, g10_errstr(rc) ); break; case aEncr: /* encrypt the given file */ if( argc > 1 ) usage(1); if( (rc = encode_crypt(fname,remusr)) ) - log_error("encode_crypt('%s'): %s\n", - fname_print, g10_errstr(rc) ); + log_error("encode_crypt('%s'): %s\n", fname_print, g10_errstr(rc) ); + break; + + case aSign: /* sign the given file */ + if( argc > 1 ) + usage(1); + if( (rc = sign_file(fname, 0, locusr)) ) + log_error("sign_file('%s'): %s\n", fname_print, g10_errstr(rc) ); + break; + + case aSignEncr: /* sign and encrypt the given file */ + usage(1); /* FIXME */ break; case aPrimegen: @@ -227,6 +245,7 @@ main( int argc, char **argv ) /* cleanup */ FREE_STRLIST(remusr); + FREE_STRLIST(locusr); return 0; } diff --git a/g10/getkey.c b/g10/getkey.c index 0e3c3b2f3..8ca462210 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -61,7 +61,8 @@ static int pkc_cache_entries; /* number of entries in pkc cache */ static int scan_keyring( PKT_pubkey_cert *pkc, u32 *keyid, const char *name, const char *filename ); -static int scan_secret_keyring( PACKET *pkt, u32 *keyid, const char *filename); +static int scan_secret_keyring( PKT_seckey_cert *skc, u32 *keyid, + const char *name, const char *filename); void @@ -254,10 +255,10 @@ int get_seckey( RSA_secret_key *skey, u32 *keyid ) { int rc=0; - PACKET pkt; + PKT_seckey_cert skc; - init_packet( &pkt ); - if( !(rc=scan_secret_keyring( &pkt, keyid, "../keys/secring.g10" ) ) ) + memset( &skc, 0, sizeof skc ); + if( !(rc=scan_secret_keyring( &skc, keyid, NULL, "../keys/secring.g10" ) ) ) goto found; /* fixme: look at other places */ goto leave; @@ -266,30 +267,46 @@ get_seckey( RSA_secret_key *skey, u32 *keyid ) /* get the secret key (this may prompt for a passprase to * unlock the secret key */ - if( (rc = check_secret_key( pkt.pkt.seckey_cert )) ) + if( (rc = check_secret_key( &skc )) ) goto leave; - if( pkt.pkt.seckey_cert->pubkey_algo != PUBKEY_ALGO_RSA ) { + if( skc.pubkey_algo != PUBKEY_ALGO_RSA ) { rc = G10ERR_PUBKEY_ALGO; /* unsupport algorithm */ goto leave; } /* copy the stuff to SKEY. skey is then the owner */ - skey->e = pkt.pkt.seckey_cert->d.rsa.rsa_e; - skey->n = pkt.pkt.seckey_cert->d.rsa.rsa_n; - skey->p = pkt.pkt.seckey_cert->d.rsa.rsa_p; - skey->q = pkt.pkt.seckey_cert->d.rsa.rsa_q; - skey->d = pkt.pkt.seckey_cert->d.rsa.rsa_d; - skey->u = pkt.pkt.seckey_cert->d.rsa.rsa_u; - /* set all these to NULL, so that free_packet will not destroy - * these integers. */ - pkt.pkt.seckey_cert->d.rsa.rsa_e = NULL; - pkt.pkt.seckey_cert->d.rsa.rsa_n = NULL; - pkt.pkt.seckey_cert->d.rsa.rsa_p = NULL; - pkt.pkt.seckey_cert->d.rsa.rsa_q = NULL; - pkt.pkt.seckey_cert->d.rsa.rsa_d = NULL; - pkt.pkt.seckey_cert->d.rsa.rsa_u = NULL; + skey->e = skc.d.rsa.rsa_e; + skey->n = skc.d.rsa.rsa_n; + skey->p = skc.d.rsa.rsa_p; + skey->q = skc.d.rsa.rsa_q; + skey->d = skc.d.rsa.rsa_d; + skey->u = skc.d.rsa.rsa_u; + + leave: + memset( &skc, 0, sizeof skc ); + return rc; +} + +/**************** + * Get a secret key by name and store it into skc + */ +int +get_seckey_by_name( PKT_seckey_cert *skc, const char *name ) +{ + int rc=0; + + if( !(rc=scan_secret_keyring( skc, NULL, name, "../keys/secring.g10" ) ) ) + goto found; + /* fixme: look at other places */ + goto leave; + + found: + /* get the secret key (this may prompt for a passprase to + * unlock the secret key + */ + if( (rc = check_secret_key( skc )) ) + goto leave; leave: - free_packet(&pkt); return rc; } @@ -416,11 +433,18 @@ scan_keyring( PKT_pubkey_cert *pkc, u32 *keyid, * PKT returns the secret key certificate. */ static int -scan_secret_keyring( PACKET *pkt, u32 *keyid, const char *filename ) +scan_secret_keyring( PKT_seckey_cert *skc, u32 *keyid, + const char *name, const char *filename ) { + int rc=0; + int found = 0; IOBUF a; - int save_mode, rc; + PACKET pkt; + int save_mode; u32 akeyid[2]; + PKT_seckey_cert *last_pk = NULL; + + assert( !keyid || !name ); if( !(a = iobuf_open( filename ) ) ) { log_debug("scan_secret_keyring: can't open '%s'\n", filename ); @@ -428,28 +452,84 @@ scan_secret_keyring( PACKET *pkt, u32 *keyid, const char *filename ) } save_mode = set_packet_list_mode(0); - init_packet(pkt); - while( (rc=parse_packet(a, pkt)) != -1 ) { + init_packet(&pkt); + while( (rc=parse_packet(a, &pkt)) != -1 ) { if( rc ) - ; - else if( pkt->pkttype == PKT_SECKEY_CERT ) { - mpi_get_keyid( pkt->pkt.seckey_cert->d.rsa.rsa_n , akeyid ); - if( akeyid[0] == keyid[0] && akeyid[1] == keyid[1] ) { - iobuf_close(a); - set_packet_list_mode(save_mode); - return 0; /* got it */ + ; /* e.g. unknown packet */ + else if( keyid && found && pkt.pkttype == PKT_SECKEY_CERT ) { + log_error("Hmmm, seckey without an user id in '%s'\n", filename); + goto leave; + } + else if( keyid && pkt.pkttype == PKT_SECKEY_CERT ) { + switch( pkt.pkt.seckey_cert->pubkey_algo ) { + case PUBKEY_ALGO_RSA: + mpi_get_keyid( pkt.pkt.seckey_cert->d.rsa.rsa_n , akeyid ); + if( akeyid[0] == keyid[0] && akeyid[1] == keyid[1] ) { + copy_seckey_cert( skc, pkt.pkt.seckey_cert ); + found++; + } + break; + default: + log_error("cannot handle pubkey algo %d\n", + pkt.pkt.seckey_cert->pubkey_algo); } } - free_packet(pkt); + else if( keyid && found && pkt.pkttype == PKT_USER_ID ) { + goto leave; + } + else if( name && pkt.pkttype == PKT_SECKEY_CERT ) { + if( last_pk ) + free_seckey_cert(last_pk); + last_pk = pkt.pkt.seckey_cert; + pkt.pkt.seckey_cert = NULL; + } + else if( name && pkt.pkttype == PKT_USER_ID ) { + if( memistr( pkt.pkt.user_id->name, pkt.pkt.user_id->len, name )) { + if( !last_pk ) + log_error("Ooops: no seckey for userid '%.*s'\n", + pkt.pkt.user_id->len, pkt.pkt.user_id->name); + else if( skc->pubkey_algo && + skc->pubkey_algo != last_pk->pubkey_algo ) + log_info("skipping id '%.*s': want algo %d, found %d\n", + pkt.pkt.user_id->len, pkt.pkt.user_id->name, + skc->pubkey_algo, last_pk->pubkey_algo ); + else { + copy_seckey_cert( skc, last_pk ); + goto leave; + } + } + } + else if( !keyid && !name && pkt.pkttype == PKT_SECKEY_CERT ) { + if( last_pk ) + free_seckey_cert(last_pk); + last_pk = pkt.pkt.seckey_cert; + pkt.pkt.seckey_cert = NULL; + } + else if( !keyid && !name && pkt.pkttype == PKT_USER_ID ) { + if( !last_pk ) + log_error("Ooops: no seckey for userid '%.*s'\n", + pkt.pkt.user_id->len, pkt.pkt.user_id->name); + else { + if( last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) { + mpi_get_keyid( last_pk->d.rsa.rsa_n , akeyid ); + cache_user_id( pkt.pkt.user_id, akeyid ); + } + } + } + free_packet(&pkt); } + rc = G10ERR_NO_SECKEY; + leave: + if( last_pk ) + free_seckey_cert(last_pk); + free_packet(&pkt); iobuf_close(a); set_packet_list_mode(save_mode); - return G10ERR_NO_SECKEY; + return rc; } - /**************** * Return a string with a printable representation of the user_id. * this string must be freed by m_free. diff --git a/g10/keydb.h b/g10/keydb.h index 641cd4cbc..62c6abe36 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -36,6 +36,7 @@ void cache_user_id( PKT_user_id *uid, u32 *keyid ); int get_pubkey( PKT_pubkey_cert *pkc, u32 *keyid ); int get_pubkey_by_name( PKT_pubkey_cert *pkc, const char *name ); int get_seckey( RSA_secret_key *skey, u32 *keyid ); +int get_seckey_by_name( PKT_seckey_cert *skc, const char *name ); char*get_user_id_string( u32 *keyid ); diff --git a/g10/keygen.c b/g10/keygen.c index 1f174498c..866824c1c 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -44,21 +44,6 @@ answer_is_yes( const char *s ) } -static void -write_comment( IOBUF out, const char *s ) -{ - PACKET pkt; - size_t n = strlen(s); - int rc; - - pkt.pkttype = PKT_COMMENT; - pkt.pkt.comment = m_alloc( sizeof *pkt.pkt.comment + n - 1 ); - pkt.pkt.comment->len = n; - strcpy(pkt.pkt.comment->data, s); - if( (rc = build_packet( out, &pkt )) ) - log_error("build_packet(comment) failed: %s\n", g10_errstr(rc) ); - free_packet( &pkt ); -} static void write_uid( IOBUF out, const char *s ) diff --git a/g10/main.h b/g10/main.h index 398dc40f1..9d0f07a89 100644 --- a/g10/main.h +++ b/g10/main.h @@ -20,16 +20,21 @@ #ifndef G10_MAIN_H #define G10_MAIN_H #include "types.h" +#include "iobuf.h" /*-- encode.c --*/ int encode_symmetric( const char *filename ); int encode_store( const char *filename ); int encode_crypt( const char *filename, STRLIST remusr ); +/*-- sign.c --*/ +int sign_file( const char *filename, int detached, STRLIST locusr ); + /*-- keygen.c --*/ void generate_keypair(void); -/*-- overwrite.c --*/ +/*-- openfile.c --*/ int overwrite_filep( const char *fname ); +IOBUF open_outfile( const char *fname ); #endif /*G10_MAIN_H*/ diff --git a/g10/mainproc.c b/g10/mainproc.c index 0055200b4..45cb8fbbd 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -29,7 +29,7 @@ #include "util.h" #include "cipher.h" #include "keydb.h" - +#include "filter.h" static int opt_list=1; /* and list the data packets to stdout */ @@ -48,7 +48,9 @@ proc_packets( IOBUF a ) int lvl0, lvl1; int last_was_pubkey_enc = 0; u32 keyid[2]; + md_filter_context_t mfx; + memset( &mfx, 0, sizeof mfx ); lvl0 = opt.check_sigs? 1:0; /* stdout or /dev/null */ lvl1 = opt.check_sigs? 1:3; /* stdout or error */ pkt = m_alloc( sizeof *pkt ); @@ -135,7 +137,14 @@ proc_packets( IOBUF a ) sig = pkt->pkt.signature; ustr = get_user_id_string(sig->keyid); result = -1; - if( sig->sig_class != 0x10 ) + if( sig->sig_class == 0x00 ) { + if( mfx.rmd160 ) + result = 0; + else + printstr(lvl1,"sig?: %s: no plaintext for signature\n", + ustr); + } + else if( sig->sig_class != 0x10 ) printstr(lvl1,"sig?: %s: unknown signature class %02x\n", ustr, sig->sig_class); else if( !pkt->pkc_parent || !pkt->user_parent ) @@ -145,20 +154,25 @@ proc_packets( IOBUF a ) if( result ) ; - else if( !opt.check_sigs ) { + else if( !opt.check_sigs && sig->sig_class != 0x00 ) { result = -1; printstr(lvl0, "sig: from %s\n", ustr ); } else if(sig->pubkey_algo == PUBKEY_ALGO_RSA ) { md_handle.algo = sig->d.rsa.digest_algo; if( sig->d.rsa.digest_algo == DIGEST_ALGO_RMD160 ) { - md_handle.u.rmd = rmd160_copy(pkt->pkc_parent->mfx.rmd160); - rmd160_write(md_handle.u.rmd, pkt->user_parent->name, - pkt->user_parent->len); + if( sig->sig_class == 0x00 ) + md_handle.u.rmd = rmd160_copy( mfx.rmd160 ); + else { + md_handle.u.rmd = rmd160_copy(pkt->pkc_parent->mfx.rmd160); + rmd160_write(md_handle.u.rmd, pkt->user_parent->name, + pkt->user_parent->len); + } result = signature_check( sig, md_handle ); rmd160_close(md_handle.u.rmd); } - else if( sig->d.rsa.digest_algo == DIGEST_ALGO_MD5 ) { + else if( sig->d.rsa.digest_algo == DIGEST_ALGO_MD5 + && sig->sig_class != 0x00 ) { md_handle.u.md5 = md5_copy(pkt->pkc_parent->mfx.md5); md5_write(md_handle.u.md5, pkt->user_parent->name, pkt->user_parent->len); @@ -173,6 +187,8 @@ proc_packets( IOBUF a ) if( result == -1 ) ; + else if( !result && sig->sig_class == 0x00 ) + printstr(1, "sig: good signature from %s\n", ustr ); else if( !result ) printstr(lvl0, "sig: good signature from %s\n", ustr ); else @@ -235,7 +251,9 @@ proc_packets( IOBUF a ) else if( pkt->pkttype == PKT_PLAINTEXT ) { PKT_plaintext *pt = pkt->pkt.plaintext; printf("txt: plain text data name='%.*s'\n", pt->namelen, pt->name); - result = handle_plaintext( pt ); + free_md_filter_context( &mfx ); + mfx.rmd160 = rmd160_open(0); + result = handle_plaintext( pt, &mfx ); if( !result ) fputs( " okay",stdout); else @@ -269,6 +287,7 @@ proc_packets( IOBUF a ) m_free(dek); free_packet( pkt ); m_free( pkt ); + free_md_filter_context( &mfx ); return 0; } diff --git a/g10/mdfilter.c b/g10/mdfilter.c index b6cd86110..5a77c9012 100644 --- a/g10/mdfilter.c +++ b/g10/mdfilter.c @@ -45,7 +45,7 @@ md_filter( void *opaque, int control, int i, c, rc=0; if( control == IOBUFCTRL_UNDERFLOW ) { - if( size > mfx->maxbuf_size ) + if( mfx->maxbuf_size && size > mfx->maxbuf_size ) size = mfx->maxbuf_size; for(i=0; i < size; i++ ) { if( (c = iobuf_get(a)) == -1 ) @@ -68,3 +68,16 @@ md_filter( void *opaque, int control, return rc; } + +void +free_md_filter_context( md_filter_context_t *mfx ) +{ + if( mfx->md5 ) + md5_close(mfx->md5); + mfx->md5 = NULL; + if( mfx->rmd160 ) + rmd160_close(mfx->rmd160); + mfx->rmd160 = NULL; + mfx->maxbuf_size = 0; +} + diff --git a/g10/overwrite.c b/g10/openfile.c similarity index 66% rename from g10/overwrite.c rename to g10/openfile.c index a98dd3be7..1a840f19c 100644 --- a/g10/overwrite.c +++ b/g10/openfile.c @@ -1,4 +1,4 @@ -/* overwrite.c +/* openfile.c * Copyright (c) 1997 by Werner Koch (dd9jn) * * This file is part of G10. @@ -77,3 +77,43 @@ overwrite_filep( const char *fname ) } +/**************** + * Make an output filename for the inputfile INAME. + * Returns an IOBUF + */ +IOBUF +open_outfile( const char *iname ) +{ + IOBUF a = NULL; + int rc; + + if( (!iname && !opt.outfile) || opt.outfile_is_stdout ) { + if( !(a = iobuf_create(NULL)) ) + log_error("can't open [stdout]: %s\n", strerror(errno) ); + else if( opt.verbose ) + log_info("writing to stdout\n"); + } + else { + char *buf=NULL; + const char *name; + + if( opt.outfile ) + name = opt.outfile; + else { + buf = m_alloc(strlen(iname)+4+1); + strcpy(stpcpy(buf,iname), ".g10"); + name = buf; + } + if( !(rc=overwrite_filep( name )) ) { + if( !(a = iobuf_create( name )) ) + log_error("can't create %s: %s\n", name, strerror(errno) ); + else if( opt.verbose ) + log_info("writing to '%s'\n", name ); + } + else if( rc != -1 ) + log_error("oops: overwrite_filep(%s): %s\n", name, g10_errstr(rc) ); + m_free(buf); + } + return a; +} + diff --git a/g10/packet.h b/g10/packet.h index 93336bcb4..f57dce172 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -103,9 +103,6 @@ typedef struct { byte iv[8]; /* initialization vector for CFB mode */ /* when protected, the MPIs above are pointers * to plain storage */ - } idea; - struct { - byte iv[8]; } blowfish; } protect; } rsa; @@ -190,6 +187,7 @@ void free_user_id( PKT_user_id *uid ); void free_comment( PKT_comment *rem ); void free_packet( PACKET *pkt ); PKT_pubkey_cert *copy_pubkey_cert( PKT_pubkey_cert *d, PKT_pubkey_cert *s ); +PKT_seckey_cert *copy_seckey_cert( PKT_seckey_cert *d, PKT_seckey_cert *s ); /*-- sig-check.c --*/ @@ -209,6 +207,10 @@ int decrypt_data( PKT_encr_data *ed, DEK *dek ); int encrypt_data( PKT_encr_data *ed, DEK *dek ); /*-- plaintext.c --*/ -int handle_plaintext( PKT_plaintext *pt ); +int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx ); + +/*-- comment.c --*/ +int write_comment( IOBUF out, const char *s ); + #endif /*G10_PACKET_H*/ diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 33cfda38f..35fc6d766 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -157,7 +157,6 @@ parse_packet( IOBUF inp, PACKET *pkt ) case PKT_SIGNATURE: pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature ); rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature ); - m_check(pkt->pkt.signature); break; case PKT_USER_ID: rc = parse_user_id(inp, pkttype, pktlen, pkt ); @@ -266,14 +265,12 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, log_error("packet(%d) with unknown version %d\n", pkttype, version); goto leave; } - m_check(sig); md5_len = iobuf_get_noeof(inp); pktlen--; sig->sig_class = iobuf_get_noeof(inp); pktlen--; sig->timestamp = read_32(inp); pktlen -= 4; sig->keyid[0] = read_32(inp); pktlen -= 4; sig->keyid[1] = read_32(inp); pktlen -= 4; sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--; - m_check(sig); if( list_mode ) printf(":signature packet: keyid %08lX%08lX\n" "\tversion %d, created %lu, md5len %d, sigclass %02x\n", @@ -284,11 +281,9 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, log_error("packet(%d) too short\n", pkttype); goto leave; } - m_check(sig); sig->d.rsa.digest_algo = iobuf_get_noeof(inp); pktlen--; sig->d.rsa.digest_start[0] = iobuf_get_noeof(inp); pktlen--; sig->d.rsa.digest_start[1] = iobuf_get_noeof(inp); pktlen--; - m_check(sig); n = pktlen; sig->d.rsa.rsa_integer = mpi_decode(inp, &n ); pktlen -=n; if( list_mode ) { @@ -302,7 +297,6 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, } else if( list_mode ) printf("\tunknown algorithm %d\n", sig->pubkey_algo ); - m_check(sig); leave: @@ -395,9 +389,7 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen, printf(" %02x", temp[i] ); putchar('\n'); } - if( cert->d.rsa.protect_algo == CIPHER_ALGO_IDEA ) - memcpy(cert->d.rsa.protect.idea.iv, temp, 8 ); - else if( cert->d.rsa.protect_algo == CIPHER_ALGO_BLOWFISH ) + if( cert->d.rsa.protect_algo == CIPHER_ALGO_BLOWFISH ) memcpy(cert->d.rsa.protect.blowfish.iv, temp, 8 ); } else diff --git a/g10/passphrase.c b/g10/passphrase.c index c95b27bbd..5a45f49bd 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -100,17 +100,7 @@ hash_passphrase( DEK *dek, char *pw ) int rc = 0; dek->keylen = 0; - if( dek->algo == CIPHER_ALGO_IDEA ) { - MD5HANDLE md5; - - md5 = md5_open(1); - md5_write( md5, pw, strlen(pw) ); - md5_final( md5 ); - dek->keylen = 16; - memcpy( dek->key, md5_read(md5), dek->keylen ); - md5_close(md5); - } - else if( dek->algo == CIPHER_ALGO_BLOWFISH ) { + if( dek->algo == CIPHER_ALGO_BLOWFISH ) { RMDHANDLE rmd; rmd = rmd160_open(1); diff --git a/g10/plaintext.c b/g10/plaintext.c index be8047bd0..d317fd789 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -28,13 +28,17 @@ #include "options.h" #include "packet.h" #include "ttyio.h" +#include "filter.h" /**************** - * Handle a plaintext packet + * Handle a plaintext packet. If MFX is not NULL, update the MDs + * Note: we should use the filter stuff here, but we have to add some + * easy mimic to set a read limit, so we calculate only the + * bytes from the plaintext. */ int -handle_plaintext( PKT_plaintext *pt ) +handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx ) { char *fname; FILE *fp = NULL; @@ -78,6 +82,10 @@ handle_plaintext( PKT_plaintext *pt ) rc = G10ERR_READ_FILE; goto leave; } + if( mfx->rmd160 ) + rmd160_putchar(mfx->rmd160, c ); + if( mfx->md5 ) + md5_putchar(mfx->md5, c ); if( putc( c, fp ) == EOF ) { log_error("Error writing to '%s': %s\n", fname, strerror(errno) ); rc = G10ERR_WRITE_FILE; @@ -87,6 +95,10 @@ handle_plaintext( PKT_plaintext *pt ) } else { while( (c = iobuf_get(pt->buf)) != -1 ) { + if( mfx->rmd160 ) + rmd160_putchar(mfx->rmd160, c ); + if( mfx->md5 ) + md5_putchar(mfx->md5, c ); if( putc( c, fp ) == EOF ) { log_error("Error writing to '%s': %s\n", fname, strerror(errno) ); diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 18c737c2d..93bdff9da 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -68,9 +68,8 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) * * RND are non-zero randow bytes. - * A is the cipher algorithm ( 1 for IDEA, 42 for blowfish ) + * A is the cipher algorithm * DEK is the encryption key (session key) with length k - * (16 for idea, 42 for blowfish) * CSUM */ if( DBG_CIPHER ) diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 3cae571ab..c103de5c7 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -50,7 +50,6 @@ checksum( byte *p ) int check_secret_key( PKT_seckey_cert *cert ) { - IDEA_context idea_ctx; /* FIXME: allocate this in secure space ! */ byte iv[8]; byte *mpibuf; u16 n; @@ -58,7 +57,7 @@ check_secret_key( PKT_seckey_cert *cert ) int res; u32 keyid[2]; -#if IDEA_BLOCKSIZE != 8 || BLOWFISH_BLOCKSIZE != 8 +#if BLOWFISH_BLOCKSIZE != 8 #error unsupportted blocksize #endif @@ -73,37 +72,23 @@ check_secret_key( PKT_seckey_cert *cert ) case CIPHER_ALGO_NONE: log_bug("unprotect seckey_cert is flagged protected\n"); break; - case CIPHER_ALGO_IDEA: case CIPHER_ALGO_BLOWFISH: mpi_get_keyid( cert->d.rsa.rsa_n , keyid ); dek = get_passphrase_hash( keyid, NULL ); - /* idea_setkey( &idea_ctx, dpw );*/ m_free(dek); /* pw is in secure memory, so m_free() burns it */ memset( iv, 0, BLOWFISH_BLOCKSIZE ); - if( cert->d.rsa.protect_algo == CIPHER_ALGO_IDEA ) { - idea_setiv( &idea_ctx, iv ); - /* fixme: is it save to leave the IV unencrypted in the - * certificate or should we move it to secure storage? */ - idea_decode_cfb( &idea_ctx, cert->d.rsa.protect.idea.iv, - cert->d.rsa.protect.idea.iv, 8 ); - } - else { - blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx ); - blowfish_setiv( blowfish_ctx, iv ); - blowfish_decode_cfb( blowfish_ctx, - cert->d.rsa.protect.blowfish.iv, - cert->d.rsa.protect.blowfish.iv, 8 ); - } + blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx ); + blowfish_setiv( blowfish_ctx, iv ); + blowfish_decode_cfb( blowfish_ctx, + cert->d.rsa.protect.blowfish.iv, + cert->d.rsa.protect.blowfish.iv, 8 ); cert->d.rsa.calc_csum = 0; #define X(a) do { \ mpibuf = (byte*)cert->d.rsa.rsa_##a; \ n = ((mpibuf[0] << 8) | mpibuf[1])-2; \ - if( blowfish_ctx ) \ - blowfish_decode_cfb( blowfish_ctx, \ - mpibuf+4, mpibuf+4, n ); \ - else \ - idea_decode_cfb( &idea_ctx, mpibuf+4, mpibuf+4, n );\ + blowfish_decode_cfb( blowfish_ctx, \ + mpibuf+4, mpibuf+4, n ); \ cert->d.rsa.calc_csum += checksum( mpibuf ); \ cert->d.rsa.rsa_##a = mpi_decode_buffer( mpibuf ); \ m_free( mpibuf ); \ @@ -120,12 +105,7 @@ check_secret_key( PKT_seckey_cert *cert ) mpi_print(stdout, cert->d.rsa.rsa_##a, 1 ); \ putchar('\n'); \ } while(0) - X(n); - X(e); - X(d); - X(p); - X(q); - X(u); + X(n); X(e); X(d); X(p); X(q); X(u); #undef X #endif /* now let's see wether we have used the right passphrase */ diff --git a/g10/seskey.c b/g10/seskey.c index d81697296..317623ec8 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -1,4 +1,4 @@ -/* seskey.c - make sesssion keys +/* seskey.c - make sesssion keys etc. * Copyright (c) 1997 by Werner Koch (dd9jn) * * This file is part of G10. @@ -99,3 +99,42 @@ encode_session_key( DEK *dek, unsigned nbits ) return frame; } +/**************** + * Encode a ripemd160 message digest of LEN bytes into NBITS. + * returns: A mpi with the session key (caller must free) + */ +MPI +encode_rmd160_value( byte *md, unsigned len, unsigned nbits ) +{ + static byte asn[18] = /* stored reverse FIXME: need other values*/ + { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48, + 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; + int nframe = (nbits+7) / 8; + byte *p; + MPI frame; + int i,n,c; + + if( (nbits % BITS_PER_MPI_LIMB) || nframe < 42 || len != 20 ) + log_bug("can't encode a %d bit MD into a %d bits frame\n",len*8, nbits); + + /* We encode the MD in this way: + * + * 0 42 PAD(n bytes) 0 ASN(18 bytes) MD(20 bytes) + * + * PAD consists of FF bytes. + */ + frame = mpi_alloc_secure( nframe / BYTES_PER_MPI_LIMB ); + n = 0; + for(i=20-1; i >= 0; i--, n++ ) + mpi_putbyte(frame, n, md[i] ); + for( i=18-1; i >= 0; i--, n++ ) + mpi_putbyte(frame, n, asn[i] ); + mpi_putbyte(frame, n++, 0 ); + while( n < nframe-2 ) + mpi_putbyte(frame, n++, 0xff ); + mpi_putbyte(frame, n++, DIGEST_ALGO_RMD160 ); + mpi_putbyte(frame, n++, 0 ); + assert( n == nframe ); + return frame; +} + diff --git a/g10/sig-check.c b/g10/sig-check.c index 41ac89341..75e800693 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -115,28 +115,27 @@ signature_check( PKT_signature *sig, MD_HANDLE digest ) { 0x10, 0x04, 0x00, 0x05, 0x05, 0x02, 0x0d, 0xf7, 0x86, 0x48, 0x86, 0x2a, 0x08, 0x06, 0x0c, 0x30, 0x20, 0x30 }; - for(i=20,j=0; j < 18 && (c=mpi_getbyte(result, i)) != -1; i++, j++ ) + for(i=20,j=0; (c=mpi_getbyte(result, i)) != -1 && j < 18; i++, j++ ) if( asn[j] != c ) break; - if( j != 18 ) { /* ASN is wrong */ + if( j != 18 || c ) { /* ASN is wrong */ rc = G10ERR_BAD_PUBKEY; goto leave; } - if( !c ) { - for(; (c=mpi_getbyte(result, i)) != -1; i++ ) - if( c != 0xff ) - break; - if( c != 42 || mpi_getbyte(result, i) ) { - /* Padding or leading bytes in signature is wrong */ - rc = G10ERR_BAD_PUBKEY; - goto leave; - } - if( mpi_getbyte(result, 19) != sig->d.rsa.digest_start[0] - || mpi_getbyte(result, 18) != sig->d.rsa.digest_start[1] ) { - /* Wrong key used to check the signature */ - rc = G10ERR_BAD_PUBKEY; - goto leave; - } + for(i++; (c=mpi_getbyte(result, i)) != -1; i++ ) + if( c != 0xff ) + break; + i++; + if( c != DIGEST_ALGO_RMD160 || mpi_getbyte(result, i) ) { + /* Padding or leading bytes in signature is wrong */ + rc = G10ERR_BAD_PUBKEY; + goto leave; + } + if( mpi_getbyte(result, 19) != sig->d.rsa.digest_start[0] + || mpi_getbyte(result, 18) != sig->d.rsa.digest_start[1] ) { + /* Wrong key used to check the signature */ + rc = G10ERR_BAD_PUBKEY; + goto leave; } /* complete the digest */ @@ -162,25 +161,24 @@ signature_check( PKT_signature *sig, MD_HANDLE digest ) for(i=16,j=0; j < 18 && (c=mpi_getbyte(result, i)) != -1; i++, j++ ) if( asn[j] != c ) break; - if( j != 18 ) { /* ASN is wrong */ + if( j != 18 || c ) { /* ASN is wrong */ rc = G10ERR_BAD_PUBKEY; goto leave; } - if( !c ) { - for(; (c=mpi_getbyte(result, i)) != -1; i++ ) - if( c != 0xff ) - break; - if( c != 1 || mpi_getbyte(result, i) ) { - /* Padding or leading bytes in signature is wrong */ - rc = G10ERR_BAD_PUBKEY; - goto leave; - } - if( mpi_getbyte(result, 15) != sig->d.rsa.digest_start[0] - || mpi_getbyte(result, 14) != sig->d.rsa.digest_start[1] ) { - /* Wrong key used to check the signature */ - rc = G10ERR_BAD_PUBKEY; - goto leave; - } + for(i++; (c=mpi_getbyte(result, i)) != -1; i++ ) + if( c != 0xff ) + break; + i++; + if( c != DIGEST_ALGO_MD5 || mpi_getbyte(result, i) ) { + /* Padding or leading bytes in signature is wrong */ + rc = G10ERR_BAD_PUBKEY; + goto leave; + } + if( mpi_getbyte(result, 15) != sig->d.rsa.digest_start[0] + || mpi_getbyte(result, 14) != sig->d.rsa.digest_start[1] ) { + /* Wrong key used to check the signature */ + rc = G10ERR_BAD_PUBKEY; + goto leave; } /* complete the digest */ diff --git a/include/cipher.h b/include/cipher.h index a19fcfdb7..e178b5f4e 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -33,14 +33,13 @@ #ifdef HAVE_RSA_CIPHER #include "../cipher/rsa.h" #endif -#include "../cipher/idea.h" #include "../cipher/blowfish.h" #include "../cipher/gost.h" #include "../cipher/elgamal.h" #define CIPHER_ALGO_NONE 0 -#define CIPHER_ALGO_IDEA 1 +#define CIPHER_ALGO_IDEA 1 /* used only for documentation */ #define CIPHER_ALGO_BLOWFISH 42 #define CIPHER_ALGO_GOST 43 @@ -84,6 +83,7 @@ MPI generate_random_prime( unsigned nbits ); /*-- seskey.c --*/ void make_session_key( DEK *dek ); MPI encode_session_key( DEK *dek, unsigned nbits ); +MPI encode_rmd160_value( byte *md, unsigned len, unsigned nbits ); #endif /*G10_CIPHER_H*/ diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c index 4e2a09056..15833d3f1 100644 --- a/mpi/mpiutil.c +++ b/mpi/mpiutil.c @@ -248,6 +248,10 @@ mpi_free( MPI a ) } +/**************** + * Note: This copy function shpould not interpret the MPI + * but copy it transparently. + */ MPI #ifdef M_DEBUG mpi_debug_copy( MPI a, const char *info )