diff --git a/NEWS b/NEWS index d4dcdc070..6d40bb91f 100644 --- a/NEWS +++ b/NEWS @@ -1,14 +1,17 @@ -Noteworthy changes in version 0.2.?? +Noteworthy changes in version 0.2.17 ------------------------------------ * Comment packets are now of private type 61. - * passphrase code still used a 160 bit blowfish key, add a + * Passphrase code still used a 160 bit blowfish key, added a silly workaround. Please change your passphrase again - sorry. * Conventional encryption now uses a type 3 packet to describe the used algorithms. + * The new algorithm number for Blowfish is 20, 16 is still used for + encryption only; for signing it is only used when it is in a v3 packet, + so that GNUPG keys are still valid. Noteworthy changes in version 0.2.16 diff --git a/README b/README index a13192c70..ebfa2c1a4 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ GNUPG - The GNU Privacy Guard ------------------------------- - THIS IS ALPHA SOFTWARE, YOU MAY ENCOUNTER SOOME BUGS. + THIS IS ALPHA SOFTWARE, YOU MAY ENCOUNTER SOME BUGS. On a Linux box (version 2.x.x, alpha or x86 CPU) it should work reliably. You may create your key on such a machine and diff --git a/TODO b/TODO index 3e39c0886..bc817672f 100644 --- a/TODO +++ b/TODO @@ -47,5 +47,3 @@ * add readline support (but how can we allcoate it in secure memory?) - * add multi-user-id-sigs handling to import.c - diff --git a/VERSION b/VERSION index 8459e5aa5..0fcb3bba7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.16a +0.2.17 diff --git a/checks/Makefile.am b/checks/Makefile.am index b4a830b42..8de908cca 100644 --- a/checks/Makefile.am +++ b/checks/Makefile.am @@ -8,7 +8,8 @@ TESTS = version.test \ armsigs.test armencrypt.test armencryptp.test \ signencrypt.test signencrypt-dsa.test \ armsignencrypt.test armdetach.test \ - armdetachm.test detachm.test genkey1024.test + armdetachm.test detachm.test genkey1024.test \ + conventional.test TEST_FILES = pubring.asc secring.asc gnupg.asc plain-1 plain-2 plain-3o.asc \ diff --git a/checks/conventional.test b/checks/conventional.test new file mode 100755 index 000000000..295db822b --- /dev/null +++ b/checks/conventional.test @@ -0,0 +1,17 @@ +#!/bin/sh + +. defs.inc || exit 3 + +#info Checking conventional encryption +for i in plain-2 data-32000 ; do + echo "Hier spricht HAL" | ./run-gpg --passphrase-fd 0 -c -o x --yes $i + echo "Hier spricht HAL" | ./run-gpg --passphrase-fd 0 -o y --yes x + cmp $i y || error "$i: mismatch" +done +for i in plain-1 data-80000 ; do + echo "Hier spricht HAL" | ./run-gpg --passphrase-fd 0 \ + --cipher-algo cast -c -o x --yes $i + echo "Hier spricht HAL" | ./run-gpg --passphrase-fd 0 -o y --yes x + cmp $i y || error "$i: mismatch" +done + diff --git a/checks/sigs.test b/checks/sigs.test index 15c464f1e..4b3894c28 100755 --- a/checks/sigs.test +++ b/checks/sigs.test @@ -9,3 +9,13 @@ for i in $plain_files $data_files; do cmp $i y || error "$i: mismatch" done +for da in rmd160 sha1 md5 tiger; do + for i in $plain_files; do + echo "$usrpass1" | ./run-gpg --passphrase-fd 0 --digest-algo $da \ + -s -o x --yes $i + ./run-gpg -o y --yes x + cmp $i y || error "$i: mismatch" + # process only the first one + break + done +done diff --git a/cipher/misc.c b/cipher/misc.c index 339b3bc52..cadaad563 100644 --- a/cipher/misc.c +++ b/cipher/misc.c @@ -136,6 +136,7 @@ check_pubkey_algo2( int algo, unsigned usage ) return 0; case PUBKEY_ALGO_ELGAMAL: + case PUBKEY_ALGO_ELGAMAL_E: return 0; #ifdef HAVE_RSA_CIPHER diff --git a/g10/ChangeLog b/g10/ChangeLog index 3ddb311e3..b61ea5cda 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,20 @@ +Mon May 4 19:01:25 1998 Werner Koch (wk@isil.d.shuttle.de) + + * compress.c: doubled buffer sizes + * parse-packet.c (do_plaintext): now uses iobuf_read/write. + +Mon May 4 09:35:53 1998 Werner Koch (wk@isil.d.shuttle.de) + + * seskey.c (encode_md_value): Add optional argument hash_algo, + changed all callers. + + * passphrase.c (make_dek_from_passphrase): Removed + * (get_passhrase_hash): Changed name to passphrase_to_dek, add arg, + changed all callers. + + * all: Introduced the new ELG identifier and added support for the + encryption only one (which is okay to use by GNUPG for signatures). + Sun May 3 17:50:26 1998 Werner Koch (wk@isil.d.shuttle.de) * packet.h (PKT_OLD_COMMENT): New name for type 16. diff --git a/g10/build-packet.c b/g10/build-packet.c index eff3314a5..07aaf0676 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -185,7 +185,7 @@ do_public_cert( IOBUF out, int ctb, PKT_public_cert *pkc ) if( pkc->version < 4 ) write_16(a, pkc->valid_days ); iobuf_put(a, pkc->pubkey_algo ); - if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(pkc->pubkey_algo) ) { mpi_write(a, pkc->d.elg.p ); mpi_write(a, pkc->d.elg.g ); mpi_write(a, pkc->d.elg.y ); @@ -196,7 +196,7 @@ do_public_cert( IOBUF out, int ctb, PKT_public_cert *pkc ) mpi_write(a, pkc->d.dsa.g ); mpi_write(a, pkc->d.dsa.y ); } - else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(pkc->pubkey_algo) ) { mpi_write(a, pkc->d.rsa.n ); mpi_write(a, pkc->d.rsa.e ); } @@ -270,7 +270,7 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc ) if( skc->version < 4 ) write_16(a, skc->valid_days ); iobuf_put(a, skc->pubkey_algo ); - if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(skc->pubkey_algo) ) { mpi_write(a, skc->d.elg.p ); mpi_write(a, skc->d.elg.g ); mpi_write(a, skc->d.elg.y ); @@ -292,7 +292,7 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc ) mpi_write(a, skc->d.elg.x ); write_16(a, skc->csum ); } - else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(skc->pubkey_algo) ) { mpi_write(a, skc->d.rsa.n ); mpi_write(a, skc->d.rsa.e ); if( skc->is_protected ) { @@ -362,11 +362,11 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) write_32(a, enc->keyid[0] ); write_32(a, enc->keyid[1] ); iobuf_put(a,enc->pubkey_algo ); - if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(enc->pubkey_algo) ) { mpi_write(a, enc->d.elg.a ); mpi_write(a, enc->d.elg.b ); } - else if( enc->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(enc->pubkey_algo) ) { mpi_write(a, enc->d.rsa.rsa_integer ); } else { @@ -395,8 +395,10 @@ calc_plaintext( PKT_plaintext *pt ) static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ) { - int c, i, rc = 0; + int i, rc = 0; u32 n; + byte buf[1000]; /* FIXME: this buffer has the plaintext! */ + int nbytes; write_header(out, ctb, calc_plaintext( pt ) ); iobuf_put(out, pt->mode ); @@ -407,13 +409,14 @@ do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ) rc = G10ERR_WRITE_FILE; n = 0; - while( (c=iobuf_get(pt->buf)) != -1 ) { - if( iobuf_put(out, c) ) { + while( (nbytes=iobuf_read(pt->buf, buf, 1000)) != -1 ) { + if( iobuf_write(out, buf, nbytes) == -1 ) { rc = G10ERR_WRITE_FILE; break; } - n++; + n += nbytes; } + memset(buf,0,1000); /* at least burn the buffer */ if( !pt->len ) iobuf_set_block_mode(out, 0 ); /* write end marker */ else if( n != pt->len ) @@ -480,7 +483,7 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig ) } iobuf_put(a, sig->digest_start[0] ); iobuf_put(a, sig->digest_start[1] ); - if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(sig->pubkey_algo) ) { mpi_write(a, sig->d.elg.a ); mpi_write(a, sig->d.elg.b ); } @@ -488,7 +491,7 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig ) mpi_write(a, sig->d.dsa.r ); mpi_write(a, sig->d.dsa.s ); } - else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(sig->pubkey_algo) ) { mpi_write(a, sig->d.rsa.rsa_integer ); } else { diff --git a/g10/compress.c b/g10/compress.c index 8f547dffa..4bf1a87f8 100644 --- a/g10/compress.c +++ b/g10/compress.c @@ -59,7 +59,7 @@ init_compress( compress_filter_context_t *zfx, z_stream *zs ) "unknown error" ); } - zfx->outbufsize = 4096; + zfx->outbufsize = 8192; zfx->outbuf = m_alloc( zfx->outbufsize ); } @@ -112,7 +112,7 @@ init_uncompress( compress_filter_context_t *zfx, z_stream *zs ) "unknown error" ); } - zfx->inbufsize = 1024; + zfx->inbufsize = 2048; zfx->inbuf = m_alloc( zfx->inbufsize ); zs->avail_in = 0; } diff --git a/g10/elg.c b/g10/elg.c index bf6bf4361..2ced92723 100644 --- a/g10/elg.c +++ b/g10/elg.c @@ -39,7 +39,7 @@ g10_elg_encrypt( PKT_public_cert *pkc, PKT_pubkey_enc *enc, DEK *dek ) { MPI frame; - assert( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ); + assert( is_ELGAMAL(enc->pubkey_algo) ); enc->d.elg.a = mpi_alloc( mpi_get_nlimbs(pkc->d.elg.p) ); enc->d.elg.b = mpi_alloc( mpi_get_nlimbs(pkc->d.elg.p) ); @@ -68,7 +68,7 @@ g10_elg_sign( PKT_secret_cert *skc, PKT_signature *sig, MPI frame; byte *dp; - assert( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ); + assert( is_ELGAMAL(sig->pubkey_algo) ); if( !digest_algo ) digest_algo = md_get_algo(md); @@ -79,7 +79,9 @@ g10_elg_sign( PKT_secret_cert *skc, PKT_signature *sig, sig->digest_start[1] = dp[1]; sig->d.elg.a = mpi_alloc( mpi_get_nlimbs(skc->d.elg.p) ); sig->d.elg.b = mpi_alloc( mpi_get_nlimbs(skc->d.elg.p) ); - frame = encode_md_value( md, mpi_get_nbits(skc->d.elg.p)); + frame = encode_md_value( md, digest_algo, mpi_get_nbits(skc->d.elg.p)); + if( DBG_CIPHER ) + log_mpidump("calc sig frame (elg): ", frame); elg_sign( sig->d.elg.a, sig->d.elg.b, frame, &skc->d.elg ); mpi_free(frame); if( opt.verbose ) { diff --git a/g10/encode.c b/g10/encode.c index 4852f6e60..1871c3476 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -68,6 +68,7 @@ encode_simple( const char *filename, int mode ) IOBUF inp, out; PACKET pkt; PKT_plaintext *pt; + STRING2KEY *s2k = NULL; int rc = 0; u32 filesize; cipher_filter_context_t cfx; @@ -87,10 +88,14 @@ encode_simple( const char *filename, int mode ) cfx.dek = NULL; if( mode ) { - cfx.dek = m_alloc_secure( sizeof *cfx.dek ); - cfx.dek->algo = opt.def_cipher_algo; - if( (rc = make_dek_from_passphrase( cfx.dek , 2, NULL )) ) { + s2k = m_alloc_clear( sizeof *s2k ); + s2k->mode = 1; + s2k->hash_algo = opt.def_digest_algo; + cfx.dek = passphrase_to_dek( NULL, opt.def_cipher_algo, s2k, 2 ); + if( !cfx.dek || !cfx.dek->keylen ) { + rc = G10ERR_PASSPHRASE; m_free(cfx.dek); + m_free(s2k); iobuf_close(inp); log_error("error creating passphrase: %s\n", g10_errstr(rc) ); return rc; @@ -100,6 +105,7 @@ encode_simple( const char *filename, int mode ) if( !(out = open_outfile( filename, opt.armor? 1:0 )) ) { iobuf_close(inp); m_free(cfx.dek); + m_free(s2k); return G10ERR_CREATE_FILE; /* or user said: do not overwrite */ } @@ -112,6 +118,17 @@ encode_simple( const char *filename, int mode ) if( opt.compress ) iobuf_push_filter( out, compress_filter, &zfx ); + if( s2k ) { + PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc ); + enc->version = 4; + enc->cipher_algo = cfx.dek->algo; + enc->s2k = *s2k; + pkt.pkttype = PKT_SYMKEY_ENC; + pkt.pkt.symkey_enc = enc; + if( (rc = build_packet( out, &pkt )) ) + log_error("build symkey packet failed: %s\n", g10_errstr(rc) ); + m_free(enc); + } /* setup the inner packet */ if( filename ) { @@ -148,6 +165,7 @@ encode_simple( const char *filename, int mode ) pt->buf = NULL; free_packet(&pkt); m_free(cfx.dek); + m_free(s2k); return rc; } @@ -314,9 +332,9 @@ write_pubkey_enc_from_list( PKC_LIST pkc_list, DEK *dek, IOBUF out ) pkc = pkc_list->pkc; enc = m_alloc_clear( sizeof *enc ); enc->pubkey_algo = pkc->pubkey_algo; - if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) + if( is_ELGAMAL(enc->pubkey_algo) ) g10_elg_encrypt( pkc, enc, dek ); - else if( enc->pubkey_algo == PUBKEY_ALGO_RSA ) + else if( is_RSA(enc->pubkey_algo) ) g10_rsa_encrypt( pkc, enc, dek ); else BUG(); diff --git a/g10/free-packet.c b/g10/free-packet.c index d998ce29d..3cf82c8ac 100644 --- a/g10/free-packet.c +++ b/g10/free-packet.c @@ -40,11 +40,11 @@ free_symkey_enc( PKT_symkey_enc *enc ) void free_pubkey_enc( PKT_pubkey_enc *enc ) { - if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(enc->pubkey_algo) ) { mpi_free( enc->d.elg.a ); mpi_free( enc->d.elg.b ); } - else if( enc->pubkey_algo == PUBKEY_ALGO_RSA ) + else if( is_RSA(enc->pubkey_algo) ) mpi_free( enc->d.rsa.rsa_integer ); m_free(enc); } @@ -52,7 +52,7 @@ free_pubkey_enc( PKT_pubkey_enc *enc ) void free_seckey_enc( PKT_signature *sig ) { - if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(sig->pubkey_algo) ) { mpi_free( sig->d.elg.a ); mpi_free( sig->d.elg.b ); } @@ -60,7 +60,7 @@ free_seckey_enc( PKT_signature *sig ) mpi_free( sig->d.dsa.r ); mpi_free( sig->d.dsa.s ); } - else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) + else if( is_RSA(sig->pubkey_algo) ) mpi_free( sig->d.rsa.rsa_integer ); m_free(sig->hashed_data); m_free(sig->unhashed_data); @@ -68,32 +68,11 @@ free_seckey_enc( PKT_signature *sig ) } -/**************** - * Return the digest algorithm from the signature packet. - * We need this function because the digest algo depends on the - * used pubkey algorithm. - */ -int -digest_algo_from_sig( PKT_signature *sig ) -{ - #if 0 /* not used anymore */ - switch( sig->pubkey_algo ) { - case PUBKEY_ALGO_ELGAMAL: return sig->d.elg.digest_algo; - case PUBKEY_ALGO_DSA: return sig->d.dsa.digest_algo; - case PUBKEY_ALGO_RSA: return sig->d.rsa.digest_algo; - default: return 0; - } - #endif - return sig->digest_algo; -} - - - void release_public_cert_parts( PKT_public_cert *cert ) { - if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(cert->pubkey_algo) ) { mpi_free( cert->d.elg.p ); cert->d.elg.p = NULL; mpi_free( cert->d.elg.g ); cert->d.elg.g = NULL; mpi_free( cert->d.elg.y ); cert->d.elg.y = NULL; @@ -104,7 +83,7 @@ release_public_cert_parts( PKT_public_cert *cert ) mpi_free( cert->d.dsa.g ); cert->d.dsa.g = NULL; mpi_free( cert->d.dsa.y ); cert->d.dsa.y = NULL; } - else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(cert->pubkey_algo) ) { mpi_free( cert->d.rsa.n ); cert->d.rsa.n = NULL; mpi_free( cert->d.rsa.e ); cert->d.rsa.e = NULL; } @@ -123,7 +102,7 @@ copy_public_cert( PKT_public_cert *d, PKT_public_cert *s ) if( !d ) d = m_alloc(sizeof *d); memcpy( d, s, sizeof *d ); - if( s->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(s->pubkey_algo) ) { d->d.elg.p = mpi_copy( s->d.elg.p ); d->d.elg.g = mpi_copy( s->d.elg.g ); d->d.elg.y = mpi_copy( s->d.elg.y ); @@ -134,7 +113,7 @@ copy_public_cert( PKT_public_cert *d, PKT_public_cert *s ) d->d.dsa.g = mpi_copy( s->d.dsa.g ); d->d.dsa.y = mpi_copy( s->d.dsa.y ); } - else if( s->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(s->pubkey_algo) ) { d->d.rsa.n = mpi_copy( s->d.rsa.n ); d->d.rsa.e = mpi_copy( s->d.rsa.e ); } @@ -144,7 +123,7 @@ copy_public_cert( PKT_public_cert *d, PKT_public_cert *s ) void release_secret_cert_parts( PKT_secret_cert *cert ) { - if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(cert->pubkey_algo) ) { mpi_free( cert->d.elg.p ); cert->d.elg.p = NULL; mpi_free( cert->d.elg.g ); cert->d.elg.g = NULL; mpi_free( cert->d.elg.y ); cert->d.elg.y = NULL; @@ -157,7 +136,7 @@ release_secret_cert_parts( PKT_secret_cert *cert ) mpi_free( cert->d.dsa.y ); cert->d.dsa.y = NULL; mpi_free( cert->d.dsa.x ); cert->d.dsa.x = NULL; } - else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(cert->pubkey_algo) ) { mpi_free( cert->d.rsa.n ); cert->d.rsa.n = NULL; mpi_free( cert->d.rsa.e ); cert->d.rsa.e = NULL; mpi_free( cert->d.rsa.d ); cert->d.rsa.d = NULL; @@ -180,7 +159,7 @@ copy_secret_cert( PKT_secret_cert *d, PKT_secret_cert *s ) if( !d ) d = m_alloc(sizeof *d); memcpy( d, s, sizeof *d ); - if( s->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(s->pubkey_algo) ) { d->d.elg.p = mpi_copy( s->d.elg.p ); d->d.elg.g = mpi_copy( s->d.elg.g ); d->d.elg.y = mpi_copy( s->d.elg.y ); @@ -193,7 +172,7 @@ copy_secret_cert( PKT_secret_cert *d, PKT_secret_cert *s ) d->d.dsa.y = mpi_copy( s->d.dsa.y ); d->d.dsa.x = mpi_copy( s->d.dsa.x ); } - else if( s->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(s->pubkey_algo) ) { d->d.rsa.n = mpi_copy( s->d.rsa.n ); d->d.rsa.e = mpi_copy( s->d.rsa.e ); d->d.rsa.d = mpi_copy( s->d.rsa.d ); @@ -326,7 +305,7 @@ cmp_public_certs( PKT_public_cert *a, PKT_public_cert *b ) if( a->pubkey_algo != b->pubkey_algo ) return -1; - if( a->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(a->pubkey_algo) ) { if( mpi_cmp( a->d.elg.p , b->d.elg.p ) ) return -1; if( mpi_cmp( a->d.elg.g , b->d.elg.g ) ) @@ -344,7 +323,7 @@ cmp_public_certs( PKT_public_cert *a, PKT_public_cert *b ) if( mpi_cmp( a->d.dsa.y , b->d.dsa.y ) ) return -1; } - else if( a->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(a->pubkey_algo) ) { if( mpi_cmp( a->d.rsa.n , b->d.rsa.n ) ) return -1; if( mpi_cmp( a->d.rsa.e , b->d.rsa.e ) ) @@ -367,7 +346,7 @@ cmp_public_secret_cert( PKT_public_cert *pkc, PKT_secret_cert *skc ) if( pkc->pubkey_algo != skc->pubkey_algo ) return -1; - if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(pkc->pubkey_algo) ) { if( mpi_cmp( pkc->d.elg.p , skc->d.elg.p ) ) return -1; if( mpi_cmp( pkc->d.elg.g , skc->d.elg.g ) ) @@ -385,7 +364,7 @@ cmp_public_secret_cert( PKT_public_cert *pkc, PKT_secret_cert *skc ) if( mpi_cmp( pkc->d.dsa.y , skc->d.dsa.y ) ) return -1; } - else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(pkc->pubkey_algo) ) { if( mpi_cmp( pkc->d.rsa.n , skc->d.rsa.n ) ) return -1; if( mpi_cmp( pkc->d.rsa.e , skc->d.rsa.e ) ) diff --git a/g10/getkey.c b/g10/getkey.c index 3edadfe92..9591502e3 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -164,9 +164,9 @@ cache_public_cert( PKT_public_cert *pkc ) pkc_cache_entry_t ce; u32 keyid[2]; - if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL + if( is_ELGAMAL(pkc->pubkey_algo) || pkc->pubkey_algo == PUBKEY_ALGO_DSA - || pkc->pubkey_algo == PUBKEY_ALGO_RSA ) { + || is_RSA(pkc->pubkey_algo) ) { keyid_from_pkc( pkc, keyid ); } else diff --git a/g10/keydb.h b/g10/keydb.h index d2b64ea19..968ee692a 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -97,8 +97,7 @@ int build_skc_list( STRLIST locusr, SKC_LIST *ret_skc_list, /*-- passphrase.h --*/ void set_passphrase_fd( int fd ); int get_passphrase_fd(void); -DEK *get_passphrase_hash( u32 *keyid, int cipher_algo, STRING2KEY *s2k ); -int make_dek_from_passphrase( DEK *dek, int mode, STRING2KEY *s2k ); +DEK *passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode); /*-- getkey.c --*/ void add_keyring( const char *name ); diff --git a/g10/keyedit.c b/g10/keyedit.c index 37824d84d..0a4afbf43 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -624,35 +624,29 @@ change_passphrase( const char *username ) if( rc ) tty_printf("Can't edit this key: %s\n", g10_errstr(rc)); else { - DEK *dek = m_alloc_secure( sizeof *dek ); + DEK *dek = NULL; STRING2KEY *s2k = m_alloc_secure( sizeof *s2k ); - tty_printf( "Enter the new passphrase for this secret key.\n\n" ); + tty_printf(_("Enter the new passphrase for this secret key.\n\n") ); for(;;) { - dek->algo = CIPHER_ALGO_BLOWFISH; s2k->mode = 1; s2k->hash_algo = DIGEST_ALGO_RMD160; - rc = make_dek_from_passphrase( dek , 2, s2k ); - if( rc == -1 ) { + dek = passphrase_to_dek( NULL, CIPHER_ALGO_BLOWFISH, s2k, 2 ); + if( !dek ) { + tty_printf(_("passphrase not correctly repeated; try again.\n")); + } + else if( !dek->keylen ) { rc = 0; - tty_printf( "You don't want a passphrase -" - " this is probably a *bad* idea!\n\n"); - answer = tty_get("Do you really want to do this? "); + tty_printf(_( "You don't want a passphrase -" + " this is probably a *bad* idea!\n\n")); + answer = tty_get(_("Do you really want to do this? ")); tty_kill_prompt(); if( answer_is_yes(answer) ) changed++; m_free(answer); break; } - else if( rc == G10ERR_PASSPHRASE ) { - tty_printf("passphrase not correctly repeated; try again.\n"); - } - else if( rc ) { - m_free(dek); dek = NULL; - log_error("Error getting the passphrase: %s\n", g10_errstr(rc)); - break; - } else { /* okay */ skc->protect.algo = dek->algo; skc->protect.s2k = *s2k; diff --git a/g10/keygen.c b/g10/keygen.c index bcef7528a..e714c1605 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -527,14 +527,15 @@ generate_keypair() tty_printf(_("You need a Passphrase to protect your secret key.\n\n") ); - dek = m_alloc_secure( sizeof *dek ); s2k = m_alloc_secure( sizeof *s2k ); for(;;) { - dek->algo = CIPHER_ALGO_BLOWFISH; s2k->mode = 1; s2k->hash_algo = DIGEST_ALGO_RMD160; - rc = make_dek_from_passphrase( dek , 2, s2k ); - if( rc == -1 ) { + dek = passphrase_to_dek( NULL, CIPHER_ALGO_BLOWFISH, s2k, 2 ); + if( !dek ) { + tty_printf(_("passphrase not correctly repeated; try again.\n")); + } + else if( !dek->keylen ) { m_free(dek); dek = NULL; m_free(s2k); s2k = NULL; tty_printf(_( @@ -543,16 +544,6 @@ generate_keypair() "using this program with the option \"--change-passphrase\"\n\n")); break; } - else if( rc == G10ERR_PASSPHRASE ) { - tty_printf(_("passphrase not correctly repeated; try again.\n")); - } - else if( rc ) { - m_free(dek); dek = NULL; - m_free(s2k); s2k = NULL; - m_free(uid); - log_error("Error getting the passphrase: %s\n", g10_errstr(rc) ); - return; - } else break; /* okay */ } diff --git a/g10/keyid.c b/g10/keyid.c index 5bbf6477a..55c0c49ae 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -40,6 +40,7 @@ pubkey_letter( int algo ) case PUBKEY_ALGO_RSA: return 'R' ; case PUBKEY_ALGO_RSA_E: return 'r' ; case PUBKEY_ALGO_RSA_S: return 's' ; + case PUBKEY_ALGO_ELGAMAL_E: case PUBKEY_ALGO_ELGAMAL: return 'G' ; case PUBKEY_ALGO_DSA: return 'D' ; default: return '?'; @@ -238,7 +239,7 @@ keyid_from_skc( PKT_secret_cert *skc, u32 *keyid ) if( !keyid ) keyid = dummy_keyid; - if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(skc->pubkey_algo) ) { const byte *dp; MD_HANDLE md; md = elg_fingerprint_md_skc(skc); @@ -261,7 +262,7 @@ keyid_from_skc( PKT_secret_cert *skc, u32 *keyid ) lowbits = keyid[1]; md_close(md); } - else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(skc->pubkey_algo) ) { lowbits = mpi_get_keyid( skc->d.rsa.n, keyid ); } else { @@ -284,7 +285,7 @@ keyid_from_pkc( PKT_public_cert *pkc, u32 *keyid ) if( !keyid ) keyid = dummy_keyid; - if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(pkc->pubkey_algo) ) { const byte *dp; MD_HANDLE md; if( pkc->version < 4 ) { @@ -310,7 +311,7 @@ keyid_from_pkc( PKT_public_cert *pkc, u32 *keyid ) lowbits = keyid[1]; md_close(md); } - else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(pkc->pubkey_algo) ) { lowbits = mpi_get_keyid( pkc->d.rsa.n, keyid ); } else { @@ -337,13 +338,13 @@ keyid_from_sig( PKT_signature *sig, u32 *keyid ) unsigned nbits_from_pkc( PKT_public_cert *pkc ) { - if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(pkc->pubkey_algo) ) { return mpi_get_nbits( pkc->d.elg.p ); } else if( pkc->pubkey_algo == PUBKEY_ALGO_DSA ) { return mpi_get_nbits( pkc->d.dsa.p ); } - else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(pkc->pubkey_algo) ) { return mpi_get_nbits( pkc->d.rsa.n ); } else @@ -356,13 +357,13 @@ nbits_from_pkc( PKT_public_cert *pkc ) unsigned nbits_from_skc( PKT_secret_cert *skc ) { - if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(skc->pubkey_algo) ) { return mpi_get_nbits( skc->d.elg.p ); } else if( skc->pubkey_algo == PUBKEY_ALGO_DSA ) { return mpi_get_nbits( skc->d.dsa.p ); } - else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(skc->pubkey_algo) ) { return mpi_get_nbits( skc->d.rsa.n ); } else @@ -424,7 +425,7 @@ fingerprint_from_skc( PKT_secret_cert *skc, size_t *ret_len ) pkc.pubkey_algo = skc->pubkey_algo; pkc.version = skc->version; - if( pkc.pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(pkc.pubkey_algo) ) { pkc.timestamp = skc->timestamp; pkc.valid_days = skc->valid_days; pkc.pubkey_algo = skc->pubkey_algo; @@ -441,7 +442,7 @@ fingerprint_from_skc( PKT_secret_cert *skc, size_t *ret_len ) pkc.d.dsa.g = skc->d.dsa.g; pkc.d.dsa.y = skc->d.dsa.y; } - else if( pkc.pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(pkc.pubkey_algo) ) { pkc.d.rsa.n = skc->d.rsa.n; pkc.d.rsa.e = skc->d.rsa.e; } @@ -461,7 +462,7 @@ fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len ) size_t len; unsigned n; - if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(pkc->pubkey_algo) ) { MD_HANDLE md; if( pkc->version < 4 ) { md = v3_elg_fingerprint_md(pkc); @@ -485,7 +486,7 @@ fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len ) memcpy(array, dp, 20 ); md_close(md); } - else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(pkc->pubkey_algo) ) { MD_HANDLE md; md = md_open( DIGEST_ALGO_MD5, 0); diff --git a/g10/main.h b/g10/main.h index 4450849d6..9a1ae4ddb 100644 --- a/g10/main.h +++ b/g10/main.h @@ -79,7 +79,7 @@ IOBUF open_sigfile( const char *iname ); /*-- seskey.c --*/ void make_session_key( DEK *dek ); MPI encode_session_key( DEK *dek, unsigned nbits ); -MPI encode_md_value( MD_HANDLE md, unsigned nbits ); +MPI encode_md_value( MD_HANDLE md, int hash_algo, unsigned nbits ); /*-- comment.c --*/ KBNODE make_comment_node( const char *s ); diff --git a/g10/mainproc.c b/g10/mainproc.c index 7e0ba18b7..fa2291bc0 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -148,36 +148,16 @@ add_signature( CTX c, PACKET *pkt ) static void proc_symkey_enc( CTX c, PACKET *pkt ) { - /* FIXME: NOT READY */ - #if 0 PKT_symkey_enc *enc; - int result = 0; - c->last_was_session_key = 1; enc = pkt->pkt.symkey_enc; - if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL - || enc->pubkey_algo == PUBKEY_ALGO_DSA - || enc->pubkey_algo == PUBKEY_ALGO_RSA ) { - m_free(c->dek ); /* paranoid: delete a pending DEK */ - c->dek = m_alloc_secure( sizeof *c->dek ); - if( (result = get_session_key( enc, c->dek )) ) { - /* error: delete the DEK */ - m_free(c->dek); c->dek = NULL; - } + if( enc->seskeylen ) + log_error( "symkey_enc packet with session keys are not supported!\n"); + else { + c->last_was_session_key = 2; + c->dek = passphrase_to_dek( NULL, enc->cipher_algo, &enc->s2k, 0 ); } - else - result = G10ERR_PUBKEY_ALGO; - - if( result == -1 ) - ; - else if( !result ) { - if( opt.verbose > 1 ) - log_info( "pubkey_enc packet: Good DEK\n" ); - } - else - log_error( "pubkey_enc packet: %s\n", g10_errstr(result)); free_packet(pkt); - #endif } static void @@ -189,9 +169,9 @@ proc_pubkey_enc( CTX c, PACKET *pkt ) c->last_was_session_key = 1; enc = pkt->pkt.pubkey_enc; /*printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] );*/ - if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL + if( is_ELGAMAL(enc->pubkey_algo) || enc->pubkey_algo == PUBKEY_ALGO_DSA - || enc->pubkey_algo == PUBKEY_ALGO_RSA ) { + || is_RSA(enc->pubkey_algo) ) { m_free(c->dek ); /* paranoid: delete a pending DEK */ c->dek = m_alloc_secure( sizeof *c->dek ); if( (result = get_session_key( enc, c->dek )) ) { @@ -222,9 +202,7 @@ proc_encrypted( CTX c, PACKET *pkt ) /*printf("dat: %sencrypted data\n", c->dek?"":"conventional ");*/ if( !c->dek && !c->last_was_session_key ) { /* assume this is old conventional encrypted data */ - c->dek = m_alloc_secure( sizeof *c->dek ); - c->dek->algo = opt.def_cipher_algo; - result = make_dek_from_passphrase( c->dek, 0, NULL ); + c->dek = passphrase_to_dek( NULL, opt.def_cipher_algo, NULL, 0 ); } else if( !c->dek ) result = G10ERR_NO_SECKEY; @@ -254,7 +232,7 @@ proc_plaintext( CTX c, PACKET *pkt ) if( opt.verbose ) log_info("original file name='%.*s'\n", pt->namelen, pt->name); free_md_filter_context( &c->mfx ); - /* fixme: take the digest algo(s) to use from the + /* FIXME: take the digest algo(s) to use from the * onepass_sig packet (if we have these) * And look at the sigclass to check whether we should use the * textmode filter (sigclass 0x01) @@ -262,6 +240,7 @@ proc_plaintext( CTX c, PACKET *pkt ) c->mfx.md = md_open( DIGEST_ALGO_RMD160, 0); md_enable( c->mfx.md, DIGEST_ALGO_SHA1 ); md_enable( c->mfx.md, DIGEST_ALGO_MD5 ); + md_enable( c->mfx.md, DIGEST_ALGO_TIGER ); rc = handle_plaintext( pt, &c->mfx ); if( rc ) log_error( "handle plaintext failed: %s\n", g10_errstr(rc)); @@ -318,7 +297,7 @@ do_check_sig( CTX c, KBNODE node ) assert( node->pkt->pkttype == PKT_SIGNATURE ); sig = node->pkt->pkt.signature; - algo = digest_algo_from_sig( sig ); + algo = sig->digest_algo; if( !algo ) return G10ERR_PUBKEY_ALGO; if( (rc=check_digest_algo(algo)) ) @@ -790,8 +769,7 @@ proc_tree( CTX c, KBNODE node ) c->mfx.md = md_open(0, 0); /* fixme: why looking for the signature packet and not 1passpacket*/ for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) { - md_enable( c->mfx.md, - digest_algo_from_sig(n1->pkt->pkt.signature)); + md_enable( c->mfx.md, n1->pkt->pkt.signature->digest_algo); } /* ask for file and hash it */ if( c->sigs_only ) @@ -814,7 +792,7 @@ proc_tree( CTX c, KBNODE node ) if( !c->have_data ) { free_md_filter_context( &c->mfx ); - c->mfx.md = md_open(digest_algo_from_sig(sig), 0); + c->mfx.md = md_open(sig->digest_algo, 0); if( c->sigs_only ) rc = hash_datafiles( c->mfx.md, c->signed_data, sig->sig_class == 0x01 ); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 0f54d3a86..76e1a7a35 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -423,7 +423,7 @@ parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) goto leave; } version = iobuf_get_noeof(inp); pktlen--; - if( k->version != 4 ) { + if( version != 4 ) { log_error("packet(%d) with unknown version %d\n", pkttype, version); goto leave; } @@ -480,6 +480,7 @@ parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) printf("%02x", k->s2k.salt[i]); if( s2kmode == 4 ) printf(", count %lu\n", (ulong)k->s2k.count ); + printf("\n"); } } @@ -508,9 +509,9 @@ parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) k->keyid[1] = read_32(inp); pktlen -= 4; k->pubkey_algo = iobuf_get_noeof(inp); pktlen--; if( list_mode ) - printf(":pubkey enc packet: version %d, keyid %08lX%08lX\n", - k->version, (ulong)k->keyid[0], (ulong)k->keyid[1]); - if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + printf(":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n", + k->version, k->pubkey_algo, (ulong)k->keyid[0], (ulong)k->keyid[1]); + if( is_ELGAMAL(k->pubkey_algo) ) { n = pktlen; k->d.elg.a = mpi_read(inp, &n, 0); pktlen -=n; n = pktlen; @@ -523,7 +524,7 @@ parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) putchar('\n'); } } - else if( k->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(k->pubkey_algo) ) { n = pktlen; k->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n; if( list_mode ) { @@ -732,9 +733,10 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, } if( list_mode ) { - printf(":signature packet: keyid %08lX%08lX\n" + printf(":signature packet: algo %d, keyid %08lX%08lX\n" "\tversion %d, created %lu, md5len %d, sigclass %02x\n" "\tdigest algo %d, begin of digest %02x %02x\n", + sig->pubkey_algo, (ulong)sig->keyid[0], (ulong)sig->keyid[1], sig->version, (ulong)sig->timestamp, md5_len, sig->sig_class, sig->digest_algo, @@ -744,7 +746,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, parse_subpkt( sig->unhashed_data, -2 ); } } - if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(sig->pubkey_algo) ) { n = pktlen; sig->d.elg.a = mpi_read(inp, &n, 0 ); pktlen -=n; n = pktlen; @@ -770,7 +772,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, putchar('\n'); } } - else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_RSA(sig->pubkey_algo) ) { n = pktlen; sig->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n; if( list_mode ) { @@ -877,12 +879,12 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen, algorithm = iobuf_get_noeof(inp); pktlen--; if( list_mode ) printf(":%s key packet:\n" - "\tversion %d, created %lu, valid for %hu days\n", + "\tversion %d, algo %d, created %lu, valid for %hu days\n", pkttype == PKT_PUBLIC_CERT? "public" : pkttype == PKT_SECRET_CERT? "secret" : pkttype == PKT_PUBKEY_SUBCERT? "public sub" : pkttype == PKT_SECKEY_SUBCERT? "secret sub" : "??", - version, timestamp, valid_period ); + version, algorithm, timestamp, valid_period ); if( pkttype == PKT_SECRET_CERT || pkttype == PKT_SECKEY_SUBCERT ) { pkt->pkt.secret_cert->timestamp = timestamp; pkt->pkt.secret_cert->valid_days = valid_period; @@ -898,7 +900,7 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen, pkt->pkt.public_cert->pubkey_algo = algorithm; } - if( algorithm == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(algorithm) ) { MPI elg_p, elg_g, elg_y; n = pktlen; elg_p = mpi_read(inp, &n, 0 ); pktlen -=n; n = pktlen; elg_g = mpi_read(inp, &n, 0 ); pktlen -=n; @@ -1159,7 +1161,7 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen, log_mpidump("dsa x=", cert->d.dsa.x ); */ } } - else if( algorithm == PUBKEY_ALGO_RSA ) { + else if( is_RSA(algorithm) ) { MPI rsa_pub_mod, rsa_pub_exp; n = pktlen; rsa_pub_mod = mpi_read(inp, &n, 0); pktlen -=n; diff --git a/g10/passphrase.c b/g10/passphrase.c index 9711f5aff..5bd3eacbd 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -51,13 +51,29 @@ get_passphrase_fd() /**************** * Get a passphrase for the secret key with KEYID, display TEXT * if the user needs to enter the passphrase. - * Returns: m_alloced md5 passphrase hash; caller must free + * mode 0 = standard, 2 = create new passphrase + * Returns: a DEK with a session key; caller must free + * or NULL if the passphrase was not correctly repeated. + * (only for mode 2) + * a dek->keylen of 0 means: no passphrase entered. + * (only for mode 2) */ DEK * -get_passphrase_hash( u32 *keyid, int cipher_algo, STRING2KEY *s2k ) +passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode ) { char *pw; DEK *dek; + STRING2KEY help_s2k; + + if( !s2k ) { + s2k = &help_s2k; + s2k->mode = 0; + /* this should be MD5 if cipher is IDEA, but because we do + * not have IDEA, we use the default one, the the user + * can select it from the commandline + */ + s2k->hash_algo = opt.def_digest_algo; + } if( keyid && !opt.batch ) { char *ustr; @@ -95,44 +111,25 @@ get_passphrase_hash( u32 *keyid, int cipher_algo, STRING2KEY *s2k ) else { pw = tty_get_hidden("Enter pass phrase: " ); tty_kill_prompt(); + if( mode == 2 ) { + char *pw2 = tty_get_hidden("Repeat pass phrase: " ); + tty_kill_prompt(); + if( strcmp(pw, pw2) ) { + m_free(pw2); + m_free(pw); + return NULL; + } + m_free(pw2); + } } dek = m_alloc_secure( sizeof *dek ); dek->algo = cipher_algo; - hash_passphrase( dek, pw, s2k, 0 ); - m_free(pw); /* is allocated in secure memory, so it will be burned */ - return dek; -} - - -/**************** - * This function is used to construct a DEK from a user input. - * It uses the default CIPHER. - * Returns: 0 = okay, -1 No passphrase entered, > 0 error - */ -int -make_dek_from_passphrase( DEK *dek, int mode, STRING2KEY *s2k ) -{ - char *pw, *pw2; - int rc=0; - - pw = tty_get_hidden("Enter pass phrase: " ); - tty_kill_prompt(); - if( mode == 2 ) { - pw2 = tty_get_hidden("Repeat pass phrase: " ); - tty_kill_prompt(); - if( strcmp(pw, pw2) ) { - m_free(pw2); - m_free(pw); - return G10ERR_PASSPHRASE; - } - m_free(pw2); - } - if( !*pw ) - rc = -1; + if( !*pw && mode == 2 ) + dek->keylen = 0; else hash_passphrase( dek, pw, s2k, mode==2 ); - m_free(pw); - return rc; + m_free(pw); /* is allocated in secure memory, so it will be burned */ + return dek; } diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index b0d82bf68..5cdf9f484 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -49,7 +49,7 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) if( (rc = get_seckey( skc, k->keyid )) ) goto leave; - if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(k->pubkey_algo) ) { if( DBG_CIPHER ) { log_mpidump("Encr DEK a:", k->d.elg.a ); log_mpidump(" DEK b:", k->d.elg.b ); @@ -58,7 +58,7 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) elg_decrypt( plain_dek, k->d.elg.a, k->d.elg.b, &skc->d.elg ); } #ifdef HAVE_RSA_CIPHER - else if( k->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( is_ELGAMAL(k->pubkey_algo) ) { if( DBG_CIPHER ) log_mpidump("Encr DEK frame:", k->d.rsa.rsa_integer ); diff --git a/g10/ringedit.c b/g10/ringedit.c index def4a4306..28faeddc1 100644 --- a/g10/ringedit.c +++ b/g10/ringedit.c @@ -489,7 +489,7 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname ) if( req_skc->timestamp == skc->timestamp && req_skc->valid_days == skc->valid_days && req_skc->pubkey_algo == skc->pubkey_algo - && ( ( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL + && ( ( is_ELGAMAL(skc->pubkey_algo) && !mpi_cmp( req_skc->d.elg.p, skc->d.elg.p ) && !mpi_cmp( req_skc->d.elg.g, skc->d.elg.g ) && !mpi_cmp( req_skc->d.elg.y, skc->d.elg.y ) @@ -502,7 +502,7 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname ) && !mpi_cmp( req_skc->d.dsa.y, skc->d.dsa.y ) && !mpi_cmp( req_skc->d.dsa.x, skc->d.dsa.x ) ) - || ( skc->pubkey_algo == PUBKEY_ALGO_RSA + || ( is_RSA(skc->pubkey_algo) && !mpi_cmp( req_skc->d.rsa.n, skc->d.rsa.n ) && !mpi_cmp( req_skc->d.rsa.e, skc->d.rsa.e ) && !mpi_cmp( req_skc->d.rsa.d, skc->d.rsa.d ) @@ -517,7 +517,7 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname ) if( req_pkc->timestamp == pkc->timestamp && req_pkc->valid_days == pkc->valid_days && req_pkc->pubkey_algo == pkc->pubkey_algo - && ( ( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL + && ( ( is_ELGAMAL(pkc->pubkey_algo) && !mpi_cmp( req_pkc->d.elg.p, pkc->d.elg.p ) && !mpi_cmp( req_pkc->d.elg.g, pkc->d.elg.g ) && !mpi_cmp( req_pkc->d.elg.y, pkc->d.elg.y ) @@ -528,7 +528,7 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname ) && !mpi_cmp( req_pkc->d.dsa.g, pkc->d.dsa.g ) && !mpi_cmp( req_pkc->d.dsa.y, pkc->d.dsa.y ) ) - || ( pkc->pubkey_algo == PUBKEY_ALGO_RSA + || ( is_RSA(pkc->pubkey_algo) && !mpi_cmp( req_pkc->d.rsa.n, pkc->d.rsa.n ) && !mpi_cmp( req_pkc->d.rsa.e, pkc->d.rsa.e ) ) diff --git a/g10/rsa.c b/g10/rsa.c index edecdfb1c..251f6198c 100644 --- a/g10/rsa.c +++ b/g10/rsa.c @@ -38,7 +38,7 @@ void g10_rsa_encrypt( PKT_public_cert *pkc, PKT_pubkey_enc *enc, DEK *dek ) { #ifdef HAVE_RSA_CIPHER - assert( enc->pubkey_algo == PUBKEY_ALGO_RSA ); + assert( is_RSA(enc->pubkey_algo) ); keyid_from_pkc( pkc, enc->keyid ); enc->d.rsa.rsa_integer = encode_session_key( dek, @@ -66,7 +66,7 @@ g10_rsa_sign( PKT_secret_cert *skc, PKT_signature *sig, #ifdef HAVE_RSA_CIPHER byte *dp; - assert( sig->pubkey_algo == PUBKEY_ALGO_RSA ); + assert( is_RSA(sig->pubkey_algo) ); if( !digest_algo ) digest_algo = md_get_algo(md); @@ -76,7 +76,7 @@ g10_rsa_sign( PKT_secret_cert *skc, PKT_signature *sig, sig->digest_start[0] = dp[0]; sig->digest_start[1] = dp[1]; sig->d.rsa.rsa_integer = - encode_md_value( md, mpi_get_nbits(skc->d.rsa.rsa_n)); + encode_md_value( md, digest_algo, mpi_get_nbits(skc->d.rsa.rsa_n)); rsa_secret( sig->d.rsa.rsa_integer, sig->d.rsa.rsa_integer, &skc->d.rsa ); if( opt.verbose ) { char *ustr = get_user_id_string( sig->keyid ); diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 23ba0314b..a265a3713 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -54,8 +54,8 @@ do_check( PKT_secret_cert *cert ) case CIPHER_ALGO_BLOWFISH: case CIPHER_ALGO_CAST: keyid_from_skc( cert, keyid ); - dek = get_passphrase_hash( keyid, cert->protect.algo, - &cert->protect.s2k ); + dek = passphrase_to_dek( keyid, cert->protect.algo, + &cert->protect.s2k, 0 ); cipher_hd = cipher_open( cert->protect.algo, CIPHER_MODE_AUTO_CFB, 1); cipher_setkey( cipher_hd, dek->key, dek->keylen ); @@ -66,6 +66,7 @@ do_check( PKT_secret_cert *cert ) cipher_decrypt( cipher_hd, cert->protect.iv, cert->protect.iv, 8 ); switch( cert->pubkey_algo ) { case PUBKEY_ALGO_ELGAMAL: + case PUBKEY_ALGO_ELGAMAL_E: buffer = mpi_get_secure_buffer( cert->d.elg.x, &nbytes, NULL ); cipher_decrypt( cipher_hd, buffer, buffer, nbytes ); mpi_set_buffer( cert->d.elg.x, buffer, nbytes, 0 ); @@ -81,6 +82,8 @@ do_check( PKT_secret_cert *cert ) break; #ifdef HAVE_RSA_CIPHER case PUBKEY_ALGO_RSA: + case PUBKEY_ALGO_RSA_E: + case PUBKEY_ALGO_RSA_S: csum = 0; #define X(a) do { \ buffer = mpi_get_secure_buffer( cert->d.rsa.##a, \ @@ -104,7 +107,7 @@ do_check( PKT_secret_cert *cert ) cipher_close( cipher_hd ); /* now let's see whether we have used the right passphrase */ if( csum != cert->csum ) { - if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) { /* 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; @@ -122,6 +125,7 @@ do_check( PKT_secret_cert *cert ) } switch( cert->pubkey_algo ) { + case PUBKEY_ALGO_ELGAMAL_E: case PUBKEY_ALGO_ELGAMAL: res = elg_check_secret_key( &cert->d.elg ); break; @@ -130,6 +134,8 @@ do_check( PKT_secret_cert *cert ) break; #ifdef HAVE_RSA_CIPHER case PUBKEY_ALGO_RSA: + case PUBKEY_ALGO_RSA_E: + case PUBKEY_ALGO_RSA_S: res = rsa_check_secret_key( &cert->d.rsa ); break; #endif @@ -151,6 +157,7 @@ do_check( PKT_secret_cert *cert ) } else { /* not protected */ switch( cert->pubkey_algo ) { + case PUBKEY_ALGO_ELGAMAL_E: case PUBKEY_ALGO_ELGAMAL: csum = checksum_mpi( cert->d.elg.x ); break; @@ -158,6 +165,8 @@ do_check( PKT_secret_cert *cert ) csum = checksum_mpi( cert->d.dsa.x ); break; #ifdef HAVE_RSA_CIPHER + case PUBKEY_ALGO_RSA_E: + case PUBKEY_ALGO_RSA_S: case PUBKEY_ALGO_RSA: csum =0; buffer = mpi_get_buffer( cert->d.rsa.rsa_d, &nbytes, NULL ); @@ -181,7 +190,7 @@ do_check( PKT_secret_cert *cert ) default: BUG(); } if( csum != cert->csum ) { - if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) { /* 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; @@ -214,20 +223,25 @@ check_secret_key( PKT_secret_cert *cert ) if( i ) log_error("Invalid passphrase; please try again ...\n\n"); switch( cert->pubkey_algo ) { + case PUBKEY_ALGO_ELGAMAL_E: case PUBKEY_ALGO_ELGAMAL: case PUBKEY_ALGO_DSA: rc = do_check( cert ); + #if 1 /* set to 0 to disable the workaround */ if( rc == G10ERR_BAD_PASS && cert->is_protected - && cert->protect.algo == CIPHER_ALGO_BLOWFISH ) { + && cert->protect.algo == CIPHER_ALGO_BLOWFISH + && cert->pubkey_algo != PUBKEY_ALGO_ELGAMAL ) { /* Workaround for a bug in 0.2.16 which still used * a 160 bit key for BLOWFISH. */ - log_info("trying workaround for 0.2.16 passphrase bug ...\n"); + log_info("trying workaround for 0.2.16 passphrase bug ...\n"); + log_info("If you don't need this, uncomment it in g10/seckey-cert.c\n\n"); cert->protect.algo = CIPHER_ALGO_BLOWFISH160; rc = do_check( cert ); if( rc ) rc = G10ERR_BAD_PASS; cert->protect.algo = CIPHER_ALGO_BLOWFISH; } + #endif break; default: rc = G10ERR_PUBKEY_ALGO; } @@ -256,13 +270,14 @@ do_protect( void (*fnc)(CIPHER_HANDLE, byte *, byte *, unsigned), unsigned nbytes; switch( cert->pubkey_algo ) { - case PUBKEY_ALGO_ELGAMAL: + case PUBKEY_ALGO_ELGAMAL_E: /* 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 ); + case PUBKEY_ALGO_ELGAMAL: buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL ); (*fnc)( fnc_hd, buffer, buffer, nbytes ); mpi_set_buffer( cert->d.elg.x, buffer, nbytes, 0 ); diff --git a/g10/seskey.c b/g10/seskey.c index 500dc8457..25819909c 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -144,9 +144,9 @@ do_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits, MPI -encode_md_value( MD_HANDLE md, unsigned nbits ) +encode_md_value( MD_HANDLE md, int hash_algo, unsigned nbits ) { - int algo = md_get_algo(md); + int algo = hash_algo? hash_algo : md_get_algo(md); const byte *asn; size_t asnlen, mdlen; diff --git a/g10/sig-check.c b/g10/sig-check.c index 7051b3be4..1af891d44 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -63,14 +63,16 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest ) MPI result = NULL; int rc=0; - if( pkc->version == 4 && pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) - log_info("WARNING: This is probably a PGP generated " + if( pkc->version == 4 && pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) { + log_info("this is a PGP generated " "ElGamal key which is NOT secure for signatures!\n"); + return G10ERR_PUBKEY_ALGO; + } if( pkc->timestamp > sig->timestamp ) return G10ERR_TIME_CONFLICT; /* pubkey newer that signature */ - if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( is_ELGAMAL(pkc->pubkey_algo) ) { if( (rc=check_digest_algo(sig->digest_algo)) ) goto leave; /* make sure the digest algo is enabled (in case of a detached @@ -85,7 +87,10 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest ) md_putc( digest, a & 0xff ); } md_final( digest ); - result = encode_md_value( digest, mpi_get_nbits(pkc->d.elg.p)); + result = encode_md_value( digest, sig->digest_algo, + mpi_get_nbits(pkc->d.elg.p)); + if( DBG_CIPHER ) + log_mpidump("calc sig frame (elg): ", result); if( !elg_verify( sig->d.elg.a, sig->d.elg.b, result, &pkc->d.elg ) ) rc = G10ERR_BAD_SIGN; } @@ -139,7 +144,8 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest ) rc = G10ERR_BAD_SIGN; } #ifdef HAVE_RSA_CIPHER - else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) { + else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA + || pkc->pubkey_algo == PUBKEY_ALGO_RSA_S ) { int i, j, c, old_enc; byte *dp; const byte *asn; diff --git a/g10/sign.c b/g10/sign.c index ddcded7f1..4dbb8aee1 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -46,11 +46,11 @@ complete_sig( PKT_signature *sig, PKT_secret_cert *skc, MD_HANDLE md ) if( (rc=check_secret_key( skc )) ) ; - else if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) + else if( is_ELGAMAL(sig->pubkey_algo) ) g10_elg_sign( skc, sig, md, 0 ); else if( sig->pubkey_algo == PUBKEY_ALGO_DSA ) g10_dsa_sign( skc, sig, md, 0 ); - else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) + else if( is_RSA(sig->pubkey_algo) ) g10_rsa_sign( skc, sig, md, 0 ); else BUG(); @@ -281,11 +281,11 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, } md_final( md ); - if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) + if( is_ELGAMAL(sig->pubkey_algo) ) g10_elg_sign( skc, sig, md, opt.def_digest_algo ); else if( sig->pubkey_algo == PUBKEY_ALGO_DSA ) g10_dsa_sign( skc, sig, md, opt.def_digest_algo ); - else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) + else if( is_RSA(sig->pubkey_algo) ) g10_rsa_sign( skc, sig, md, opt.def_digest_algo ); else BUG(); @@ -446,11 +446,11 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) } md_final( md ); - if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) + if( is_ELGAMAL(sig->pubkey_algo) ) g10_elg_sign( skc, sig, md, opt.def_digest_algo ); else if( sig->pubkey_algo == PUBKEY_ALGO_DSA ) g10_dsa_sign( skc, sig, md, opt.def_digest_algo ); - else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) + else if( is_RSA(sig->pubkey_algo) ) g10_rsa_sign( skc, sig, md, opt.def_digest_algo ); else BUG(); diff --git a/g10/skclist.c b/g10/skclist.c index 6d34b05bf..53fd2e985 100644 --- a/g10/skclist.c +++ b/g10/skclist.c @@ -63,14 +63,18 @@ build_skc_list( STRLIST locusr, SKC_LIST *ret_skc_list, int unlock, else if( !(rc=check_pubkey_algo2(skc->pubkey_algo, usage)) ) { SKC_LIST r; if( skc->version == 4 && (usage & 1) - && skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) - log_info("WARNING: This is probably a PGP generated " + && skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) { + log_error("this is a PGP generated " "ElGamal key which is NOT secure for signatures!\n"); - r = m_alloc( sizeof *r ); - r->skc = skc; skc = NULL; - r->next = skc_list; - r->mark = 0; - skc_list = r; + free_secret_cert( skc ); skc = NULL; + } + else { + r = m_alloc( sizeof *r ); + r->skc = skc; skc = NULL; + r->next = skc_list; + r->mark = 0; + skc_list = r; + } } else { free_secret_cert( skc ); skc = NULL; @@ -89,14 +93,19 @@ build_skc_list( STRLIST locusr, SKC_LIST *ret_skc_list, int unlock, else if( !(rc=check_pubkey_algo2(skc->pubkey_algo, usage)) ) { SKC_LIST r; if( skc->version == 4 && (usage & 1) - && skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) - log_info("WARNING: This is probably a PGP generated " - "ElGamal key which is NOT secure for signatures!\n"); - r = m_alloc( sizeof *r ); - r->skc = skc; skc = NULL; - r->next = skc_list; - r->mark = 0; - skc_list = r; + && skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) { + log_info("skipped '%s': this is a PGP generated " + "ElGamal key which is not secure for signatures!\n", + locusr->d ); + free_secret_cert( skc ); skc = NULL; + } + else { + r = m_alloc( sizeof *r ); + r->skc = skc; skc = NULL; + r->next = skc_list; + r->mark = 0; + skc_list = r; + } } else { free_secret_cert( skc ); skc = NULL; diff --git a/include/ChangeLog b/include/ChangeLog index 94d967df3..9470baee4 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,9 @@ +Mon May 4 16:37:17 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.h (PUBKEY_ALGO_ELGAMAL_E): New, with value of the + old one. + * (is_ELGAMAL, is_RSA): New macros + Sun Apr 26 14:35:24 1998 Werner Koch (wk@isil.d.shuttle.de) * types.h: New type u64 diff --git a/include/cipher.h b/include/cipher.h index c82d35140..b64d234db 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -50,9 +50,9 @@ #define PUBKEY_ALGO_RSA 1 #define PUBKEY_ALGO_RSA_E 2 /* RSA encrypt only */ #define PUBKEY_ALGO_RSA_S 3 /* RSA sign only */ -#define PUBKEY_ALGO_ELGAMAL 16 +#define PUBKEY_ALGO_ELGAMAL_E 16 /* encrypt only ElGamal (but not vor v3)*/ #define PUBKEY_ALGO_DSA 17 -/*#define PUBKEY_ALGO_ELGAMAL 20 sign and encrypt elgamal */ +#define PUBKEY_ALGO_ELGAMAL 20 /* sign and encrypt elgamal */ #define DIGEST_ALGO_MD5 1 #define DIGEST_ALGO_SHA1 2 @@ -61,6 +61,10 @@ #define DIGEST_ALGO_TIGER 101 #endif +#define is_RSA(a) ((a)==PUBKEY_ALGO_RSA || (a)==PUBKEY_ALGO_RSA_E \ + || (a)==PUBKEY_ALGO_RSA_S ) +#define is_ELGAMAL(a) ((a)==PUBKEY_ALGO_ELGAMAL || (a)==PUBKEY_ALGO_ELGAMAL_E) + typedef struct { int algo; int keylen; diff --git a/scripts/mkdiff b/scripts/mkdiff index 659768374..6bf79ca72 100755 --- a/scripts/mkdiff +++ b/scripts/mkdiff @@ -16,7 +16,9 @@ echo "Removing old directories" echo "Unpacking previous and current tar" tar xzf "gnupg-$curr_ver.tar.gz" +rm -f gnupg-${curr_ver}/po/*.gmo tar xzf "gnupg-$prev_ver.tar.gz" +rm -f gnupg-${prev_ver}/po/*.gmo echo "Diffing" diff --git a/tools/bftest.c b/tools/bftest.c index a6816e19f..551e8e55d 100644 --- a/tools/bftest.c +++ b/tools/bftest.c @@ -63,8 +63,8 @@ main(int argc, char **argv) { int encode=0; CIPHER_HANDLE hd; - char buf[100]; - int n, size=8; + char buf[4096]; + int n, size=4096; int algo; #ifdef __MINGW32__ diff --git a/util/ChangeLog b/util/ChangeLog index 89eedb0c1..31312c7eb 100644 --- a/util/ChangeLog +++ b/util/ChangeLog @@ -1,3 +1,8 @@ +Mon May 4 19:48:03 1998 Werner Koch (wk@isil.d.shuttle.de) + + * iobuf.c (iobuf_read): Code is now faster. + * (iobuf_write): ditto. + Mon Apr 27 11:01:32 1998 Werner Koch (wk@isil.d.shuttle.de) * strgutil.c (memicmp): New. diff --git a/util/iobuf.c b/util/iobuf.c index 3940f1034..1578d565b 100644 --- a/util/iobuf.c +++ b/util/iobuf.c @@ -728,15 +728,38 @@ iobuf_read(IOBUF a, byte *buf, unsigned buflen ) { int c, n; - for(n=0 ; n < buflen; n++, buf++ ) { - if( (c = iobuf_readbyte(a)) == -1 ) { - if( !n ) - return -1; /* eof */ - break; + if( a->unget.buf || a->nlimit ) { + /* handle special cases */ + for(n=0 ; n < buflen; n++, buf++ ) { + if( (c = iobuf_readbyte(a)) == -1 ) { + if( !n ) + return -1; /* eof */ + break; + } + else + *buf = c; } - else - *buf = c; + return n; } + + if( a->filter_eof ) { + if( DBG_IOBUF ) + log_debug("iobuf-%d.%d: filter eof in iobuf_read\n", a->no, a->subno ); + return -1; + } + n = 0; + do { + for( ; n < buflen && a->d.start < a->d.len; n++ ) + *buf++ = a->d.buf[a->d.start++]; + if( n < buflen ) { + if( (c=underflow(a)) == -1 ) { + a->nbytes += n; + return n? n : -1/*EOF*/; + } + *buf++ = c; n++; + } + } while( n < buflen ); + a->nbytes += n; return n; } @@ -782,12 +805,18 @@ iobuf_writebyte(IOBUF a, unsigned c) int iobuf_write(IOBUF a, byte *buf, unsigned buflen ) { - for( ; buflen; buflen--, buf++ ) - if( iobuf_writebyte(a, *buf) ) - return -1; + do { + for( ; buflen && a->d.len < a->d.size; buflen--, buf++ ) + a->d.buf[a->d.len++] = *buf; + if( buflen ) { + if( iobuf_flush(a) ) + return -1; + } + } while( buflen ); return 0; } + int iobuf_writestr(IOBUF a, const char *buf ) { diff --git a/zlib/Makefile b/zlib/Makefile index a060f7842..8ae5caf9d 100644 --- a/zlib/Makefile +++ b/zlib/Makefile @@ -93,7 +93,7 @@ POSUB = po RANLIB = ranlib USE_INCLUDED_LIBINTL = yes USE_NLS = yes -VERSION = 0.2.16a +VERSION = 0.2.17 ZLIBS = l =