From 9c20f65cbe9d3d806b02f0f90a2051a20f3857db Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 4 Oct 2000 11:16:19 +0000 Subject: [PATCH] See ChangeLog: Wed Oct 4 13:16:18 CEST 2000 Werner Koch --- NEWS | 2 + TODO | 7 - checks/ChangeLog | 4 + checks/run-gpg | 4 +- checks/run-gpg.patterns | 3 + cipher/ChangeLog | 14 ++ cipher/Makefile.am | 1 + cipher/cipher.c | 50 +++++-- cipher/md.c | 19 ++- cipher/random.h | 2 + cipher/rsa.c | 5 +- cipher/sha1.c | 2 +- doc/gcryptref-digest.sgml | 7 +- doc/gcryptref-misc.sgml | 289 ++++++++++++++++++++++++++++++++++-- g10/ChangeLog | 15 ++ g10/encode.c | 133 ++++++++--------- g10/export.c | 2 +- g10/getkey.c | 58 +++++--- g10/gpg.c | 4 + g10/keydb.h | 1 + g10/keygen.c | 3 - g10/keyid.c | 2 +- g10/misc.c | 1 + g10/pkclist.c | 12 +- g10/seckey-cert.c | 7 +- g10/sign.c | 300 ++++++++++++++++---------------------- g10/skclist.c | 13 +- g10/status.c | 3 +- include/ttyio.h | 1 + 29 files changed, 629 insertions(+), 335 deletions(-) diff --git a/NEWS b/NEWS index d5367ae1c..66d650a2a 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ Noteworthy changes in the current CVS HEAD THIS IS A DEVELOPMENT VERSION; see README-alpha + * Add Rijndael (AES) support. + * Fixed problems with piping to/from other MS-Windows software * Expiration time of the primary key can be changed again. diff --git a/TODO b/TODO index 45d066797..da49089d7 100644 --- a/TODO +++ b/TODO @@ -7,11 +7,6 @@ * Use --output for keylistings too. - * Add to the (EGD) docs that ~/.gnupg/entropy should be a symlink to the - real socket. - - * Add a way to generate keys in batch mode with arbitrary parameters. - * Never allocate packet memory with a m-alloc, but use a specific function. * Should we change names like mpi_write in g10/ so that we don't @@ -28,8 +23,6 @@ * Speed up calculation of key validation. - * print a warning when a revoked/expired _secret_ key is used. - * --disable-asm should still assemble _udiv_qrnnd when needed * Skip RO keyrings when importing a key. diff --git a/checks/ChangeLog b/checks/ChangeLog index 9be8600e9..b5c810bfd 100644 --- a/checks/ChangeLog +++ b/checks/ChangeLog @@ -1,3 +1,7 @@ +Wed Oct 4 13:16:18 CEST 2000 Werner Koch + + * run-gpg: redirect fgrep output to stderr + Sat Nov 13 17:44:23 CET 1999 Werner Koch * genkey1024.test: Does not use --quick-random anymore. diff --git a/checks/run-gpg b/checks/run-gpg index a9e0e31cc..28d575e95 100755 --- a/checks/run-gpg +++ b/checks/run-gpg @@ -1,6 +1,6 @@ #!/bin/sh -[ -n "$show_cmds" ] && echo "../g10/gpg --homedir . $*" +[ -n "$show_cmds" ] && echo "../g10/gpg --homedir . $*" >&2 if ../g10/gpg --homedir . $* 2>err.tmp.$$ ; then : @@ -10,6 +10,6 @@ else rm err.tmp.$$ exit 1 fi -fgrep -v -f $srcdir/run-gpg.patterns err.tmp.$$ +fgrep -v -f $srcdir/run-gpg.patterns err.tmp.$$ >&2 rm err.tmp.$$ diff --git a/checks/run-gpg.patterns b/checks/run-gpg.patterns index 9eb355e5b..fde7bbbe7 100644 --- a/checks/run-gpg.patterns +++ b/checks/run-gpg.patterns @@ -9,3 +9,6 @@ gpg: NOTE: secret key 439F02CA is NOT protected. gpg: WARNING: using insecure random number generator gpg: NOTE: signature key expired NOTE: this is a development version! +secret key without public key - skipped +gpg: using secondary key CB879DE9 instead of primary key 439F02CA + diff --git a/cipher/ChangeLog b/cipher/ChangeLog index 2e4ebe53e..1d793ec34 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,17 @@ +Wed Oct 4 13:16:18 CEST 2000 Werner Koch + + * sha1.c (transform): Use rol() macro. Actually this is not needed + for a newer gcc but there are still aoter compilers. + + * rsa.c (test_keys): Use new random function. + + * md.c (gcry_md_setkey): New function to overcome problems with + const conflics. + (gcry_md_ctl): Pass set key to the new functions. + + * rijndael.c: New. + * cipher.c: Add Rijndael support. + Mon Sep 18 16:35:45 CEST 2000 Werner Koch * rndlinux.c (open_device): Loose random device checking. diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 26de92520..6feea1563 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -36,6 +36,7 @@ libcipher_la_SOURCES = cipher.c \ bithelp.h \ des.c \ des.h \ + rijndael.c \ twofish.c \ blowfish.c \ blowfish.h \ diff --git a/cipher/cipher.c b/cipher/cipher.c index 7808d8769..d36db6652 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -33,7 +33,7 @@ #include "dynload.h" #define MAX_BLOCKSIZE 16 -#define TABLE_SIZE 10 +#define TABLE_SIZE 12 #define CTX_MAGIC_NORMAL 0x24091964 #define CTX_MAGIC_SECURE 0x46919042 @@ -82,11 +82,43 @@ dummy_decrypt_block( void *c, byte *outbuf, byte *inbuf ) { BUG(); } static void setup_cipher_table(void) { - int i; i = 0; - cipher_table[i].algo = CIPHER_ALGO_TWOFISH; + cipher_table[i].algo = GCRY_CIPHER_RIJNDAEL; + cipher_table[i].name = rijndael_get_info( cipher_table[i].algo, + &cipher_table[i].keylen, + &cipher_table[i].blocksize, + &cipher_table[i].contextsize, + &cipher_table[i].setkey, + &cipher_table[i].encrypt, + &cipher_table[i].decrypt ); + if( !cipher_table[i].name ) + BUG(); + i++; + cipher_table[i].algo = GCRY_CIPHER_RIJNDAEL192; + cipher_table[i].name = rijndael_get_info( cipher_table[i].algo, + &cipher_table[i].keylen, + &cipher_table[i].blocksize, + &cipher_table[i].contextsize, + &cipher_table[i].setkey, + &cipher_table[i].encrypt, + &cipher_table[i].decrypt ); + if( !cipher_table[i].name ) + BUG(); + i++; + cipher_table[i].algo = GCRY_CIPHER_RIJNDAEL256; + cipher_table[i].name = rijndael_get_info( cipher_table[i].algo, + &cipher_table[i].keylen, + &cipher_table[i].blocksize, + &cipher_table[i].contextsize, + &cipher_table[i].setkey, + &cipher_table[i].encrypt, + &cipher_table[i].decrypt ); + if( !cipher_table[i].name ) + BUG(); + i++; + cipher_table[i].algo = GCRY_CIPHER_TWOFISH; cipher_table[i].name = twofish_get_info( cipher_table[i].algo, &cipher_table[i].keylen, &cipher_table[i].blocksize, @@ -97,7 +129,7 @@ setup_cipher_table(void) if( !cipher_table[i].name ) BUG(); i++; - cipher_table[i].algo = CIPHER_ALGO_BLOWFISH; + cipher_table[i].algo = GCRY_CIPHER_BLOWFISH; cipher_table[i].name = blowfish_get_info( cipher_table[i].algo, &cipher_table[i].keylen, &cipher_table[i].blocksize, @@ -108,7 +140,7 @@ setup_cipher_table(void) if( !cipher_table[i].name ) BUG(); i++; - cipher_table[i].algo = CIPHER_ALGO_CAST5; + cipher_table[i].algo = GCRY_CIPHER_CAST5; cipher_table[i].name = cast5_get_info( cipher_table[i].algo, &cipher_table[i].keylen, &cipher_table[i].blocksize, @@ -119,7 +151,7 @@ setup_cipher_table(void) if( !cipher_table[i].name ) BUG(); i++; - cipher_table[i].algo = CIPHER_ALGO_3DES; + cipher_table[i].algo = GCRY_CIPHER_3DES; cipher_table[i].name = des_get_info( cipher_table[i].algo, &cipher_table[i].keylen, &cipher_table[i].blocksize, @@ -455,7 +487,7 @@ do_ecb_encrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblo unsigned n; for(n=0; n < nblocks; n++ ) { - (*c->encrypt)( &c->context.c, outbuf, inbuf ); + (*c->encrypt)( &c->context.c, outbuf, (byte*)/*arggg*/inbuf ); inbuf += c->blocksize; outbuf += c->blocksize; } @@ -467,7 +499,7 @@ do_ecb_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblo unsigned n; for(n=0; n < nblocks; n++ ) { - (*c->decrypt)( &c->context.c, outbuf, inbuf ); + (*c->decrypt)( &c->context.c, outbuf, (byte*)/*arggg*/inbuf ); inbuf += c->blocksize; outbuf += c->blocksize; } @@ -507,7 +539,7 @@ do_cbc_decrypt( GCRY_CIPHER_HD c, byte *outbuf, const byte *inbuf, unsigned nblo * to save the original ciphertext block. We use lastiv * for this here because it is not used otherwise */ memcpy(c->lastiv, inbuf, blocksize ); - (*c->decrypt)( &c->context.c, outbuf, inbuf ); + (*c->decrypt)( &c->context.c, outbuf, (char*)/*argggg*/inbuf ); for(ivp=c->iv,i=0; i < blocksize; i++ ) outbuf[i] ^= *ivp++; memcpy(c->iv, c->lastiv, blocksize ); diff --git a/cipher/md.c b/cipher/md.c index e8ac8ac24..29d6afed8 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -557,10 +557,7 @@ gcry_md_ctl( GCRY_MD_HD hd, int cmd, byte *buffer, size_t buflen) if( cmd == GCRYCTL_FINALIZE ) md_final( hd ); else if( cmd == GCRYCTL_SET_KEY ) { - if( !(hd->ctx->macpads ) ) - rc = GCRYERR_CONFLICT; - else if ( !(rc = prepare_macpads( hd, buffer, buflen )) ) - gcry_md_reset( hd ); + rc = gcry_md_setkey ( hd, buffer, buflen ); } else if( cmd == GCRYCTL_START_DUMP ) { md_start_debug( hd, buffer ); @@ -574,6 +571,20 @@ gcry_md_ctl( GCRY_MD_HD hd, int cmd, byte *buffer, size_t buflen) } +int +gcry_md_setkey( GCRY_MD_HD hd, const char *key, size_t keylen ) +{ + int rc = 0; + + if( !(hd->ctx->macpads ) ) + rc = GCRYERR_CONFLICT; + else if ( !(rc = prepare_macpads( hd, key, keylen )) ) + gcry_md_reset( hd ); + + return rc; +} + + /**************** * if ALGO is null get the digest for the used algo (which should be only one) */ diff --git a/cipher/random.h b/cipher/random.h index 9a7dd8f68..d96cea7f3 100644 --- a/cipher/random.h +++ b/cipher/random.h @@ -27,6 +27,8 @@ void random_dump_stats(void); void secure_random_alloc(void); int quick_random_gen( int onoff ); int random_is_faked(void); +void secure_random_alloc(void); +void random_dump_stats(void); byte *get_random_bits( size_t nbits, int level, int secure ); void fast_random_poll( void ); diff --git a/cipher/rsa.c b/cipher/rsa.c index 2bb451002..f342e3c35 100644 --- a/cipher/rsa.c +++ b/cipher/rsa.c @@ -67,10 +67,7 @@ test_keys( RSA_secret_key *sk, unsigned nbits ) pk.n = sk->n; pk.e = sk->e; - { char *p = get_random_bits( nbits, 0, 0 ); - mpi_set_buffer( test, p, (nbits+7)/8, 0 ); - g10_free(p); - } + gcry_mpi_randomize( test, nbits, GCRY_WEAK_RANDOM ); public( out1, test, &pk ); secret( out2, out1, sk ); diff --git a/cipher/sha1.c b/cipher/sha1.c index aa3ac092f..a0438dbd6 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -108,7 +108,7 @@ transform( SHA1_CONTEXT *hd, byte *data ) #define M(i) ( tm = x[i&0x0f] ^ x[(i-14)&0x0f] \ ^ x[(i-8)&0x0f] ^ x[(i-3)&0x0f] \ - , (x[i&0x0f] = (tm << 1) | (tm >> 31)) ) + , (x[i&0x0f] = rol(tm, 1)) ) #define R(a,b,c,d,e,f,k,m) do { e += rol( a, 5 ) \ + f( b, c, d ) \ diff --git a/doc/gcryptref-digest.sgml b/doc/gcryptref-digest.sgml index a123c9b25..3b4dcd7e8 100644 --- a/doc/gcryptref-digest.sgml +++ b/doc/gcryptref-digest.sgml @@ -68,7 +68,8 @@ specified. It is possible to use these functions as MAC functons; therefore the flag gcry_md_setkey function. gcry_md_close releases all resources associated with the context. gcry_md_enable may be used to enable hash @@ -194,6 +195,7 @@ hash functions into MAC functions. The key may be any string of the speicified length. The type of the MAC is determined by special flags set with the open function. + NEW: There is now a function to do this @@ -479,3 +481,6 @@ + + - + + diff --git a/g10/ChangeLog b/g10/ChangeLog index 7cb0f17b7..fb25e7fdc 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,18 @@ +Wed Oct 4 13:16:18 CEST 2000 Werner Koch + + * getkey.c (merge_selfsigs_main): Fixed for v3 keys. + + * sign.c (hash_for): New arg to take packet version in account. Changed + all callers. + (write_one_sig): New. Moved the shared code from sign_file and + clearsign_file to here. + * skclist.c (build_sk_list): Fixed usage check. + * pkclist.c (build_pk_list): Ditto. + + * encode.c (encode_crypt): Removed duplicated stuff by using + encrypt_filter as sign.c already did. Removed already disabled + comment-packet code. + Mon Sep 18 16:35:45 CEST 2000 Werner Koch * parse-packet.c (dump_sig_subpkt): Dump key flags. diff --git a/g10/encode.c b/g10/encode.c index a817f9094..f033c76ae 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -293,18 +293,17 @@ encode_crypt( const char *filename, STRLIST remusr ) PKT_plaintext *pt = NULL; int rc = 0; u32 filesize; - cipher_filter_context_t cfx; armor_filter_context_t afx; compress_filter_context_t zfx; text_filter_context_t tfx; + encrypt_filter_context_t efx; PK_LIST pk_list; int do_compress = opt.compress && !opt.rfc1991; - - memset( &cfx, 0, sizeof cfx); memset( &afx, 0, sizeof afx); memset( &zfx, 0, sizeof zfx); memset( &tfx, 0, sizeof tfx); + memset( &efx, 0, sizeof efx); init_packet(&pkt); if( (rc=build_pk_list( remusr, &pk_list, GCRY_PK_USAGE_ENCR)) ) @@ -320,83 +319,67 @@ encode_crypt( const char *filename, STRLIST remusr ) else if( opt.verbose ) log_info(_("reading from `%s'\n"), filename? filename: "[stdin]"); + /* If the user selected textmode, push the text filter onto the input */ if( opt.textmode ) iobuf_push_filter( inp, text_filter, &tfx ); + /* Now we can create the outputfile */ if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) goto leave; - + /* The first thing we have to push on the output stream + * is the armor filter */ if( opt.armor ) iobuf_push_filter( out, armor_filter, &afx ); - #ifdef ENABLE_COMMENT_PACKETS - else { - write_comment( out, "#created by GNUPG v" VERSION " (" - PRINTABLE_OS_NAME ")"); - if( opt.comment_string ) - write_comment( out, opt.comment_string ); - } - #endif - /* create a session key */ - cfx.dek = gcry_xmalloc_secure( sizeof *cfx.dek ); - if( !opt.def_cipher_algo ) { /* try to get it from the prefs */ - cfx.dek->algo = select_algo_from_prefs( pk_list, PREFTYPE_SYM ); - if( cfx.dek->algo == -1 ) - cfx.dek->algo = DEFAULT_CIPHER_ALGO; - } - else - cfx.dek->algo = opt.def_cipher_algo; - make_session_key( cfx.dek ); - if( DBG_CIPHER ) - log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen ); - rc = write_pubkey_enc_from_list( pk_list, cfx.dek, out ); - if( rc ) - goto leave; + /* Prepare the plaintext packet */ + { + if (!opt.no_literal) { + if( filename || opt.set_filename ) { + char *s = make_basename( opt.set_filename ? + opt.set_filename : filename ); + pt = gcry_xmalloc( sizeof *pt + strlen(s) - 1 ); + pt->namelen = strlen(s); + memcpy(pt->name, s, pt->namelen ); + gcry_free(s); + } + else { /* no filename */ + pt = gcry_xmalloc( sizeof *pt - 1 ); + pt->namelen = 0; + } + } + + if( filename && !opt.textmode ) { + if( !(filesize = iobuf_get_filelength(inp)) ) + log_info(_("%s: WARNING: empty file\n"), filename ); + /* we can't yet encode the length of very large files, + * so we switch to partial lengthn encoding in this case */ + if ( filesize >= IOBUF_FILELENGTH_LIMIT ) + filesize = 0; + } + else + filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */ + + if (!opt.no_literal) { + pt->timestamp = make_timestamp(); + pt->mode = opt.textmode ? 't' : 'b'; + pt->len = filesize; + pt->new_ctb = !pt->len && !opt.rfc1991; + pt->buf = inp; + pkt.pkttype = PKT_PLAINTEXT; + pkt.pkt.plaintext = pt; + efx.cfx.datalen = filesize && !do_compress? + calc_packet_length( &pkt ) : 0; + } + else + efx.cfx.datalen = filesize && !do_compress ? filesize : 0; + } /* end preparation of plaintext packet */ + + /* push in the actual encryption filter */ + efx.pk_list = pk_list; + iobuf_push_filter( out, encrypt_filter, &efx ); - if (!opt.no_literal) { - /* setup the inner packet */ - if( filename || opt.set_filename ) { - char *s = make_basename( opt.set_filename ? opt.set_filename : filename ); - pt = gcry_xmalloc( sizeof *pt + strlen(s) - 1 ); - pt->namelen = strlen(s); - memcpy(pt->name, s, pt->namelen ); - gcry_free(s); - } - else { /* no filename */ - pt = gcry_xmalloc( sizeof *pt - 1 ); - pt->namelen = 0; - } - } - - if( filename && !opt.textmode ) { - if( !(filesize = iobuf_get_filelength(inp)) ) - log_info(_("%s: WARNING: empty file\n"), filename ); - /* we can't yet encode the length of very large files, - * so we switch to partial lengthn encoding in this case */ - if ( filesize >= IOBUF_FILELENGTH_LIMIT ) - filesize = 0; - } - else - filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */ - - if (!opt.no_literal) { - pt->timestamp = make_timestamp(); - pt->mode = opt.textmode ? 't' : 'b'; - pt->len = filesize; - pt->new_ctb = !pt->len && !opt.rfc1991; - pt->buf = inp; - pkt.pkttype = PKT_PLAINTEXT; - pkt.pkt.plaintext = pt; - cfx.datalen = filesize && !do_compress? calc_packet_length( &pkt ) : 0; - } - else - cfx.datalen = filesize && !do_compress ? filesize : 0; - - /* register the cipher filter */ - iobuf_push_filter( out, cipher_filter, &cfx ); - - /* register the compress filter */ + /* register the compress filter (so that it is done before encryption) */ if( do_compress ) { int compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_COMPR ); if( !compr_algo ) @@ -414,7 +397,8 @@ encode_crypt( const char *filename, STRLIST remusr ) log_error("build_packet failed: %s\n", gpg_errstr(rc) ); } else { - /* user requested not to create a literal packet, so we copy the plain data */ + /* user requested not to create a literal packet, + * so we copy the plain data */ byte copy_buffer[4096]; int bytes_copied; while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1) @@ -423,7 +407,7 @@ encode_crypt( const char *filename, STRLIST remusr ) log_error("copying input to output failed: %s\n", gpg_errstr(rc) ); break; } - memset(copy_buffer, 0, 4096); /* burn buffer */ + memset(copy_buffer, 0, DIM(copy_buffer)); /* burn buffer */ } /* finish the stuff */ @@ -436,7 +420,8 @@ encode_crypt( const char *filename, STRLIST remusr ) if( pt ) pt->buf = NULL; free_packet(&pkt); - gcry_free(cfx.dek); + gcry_free(efx.cfx.dek); /* Hmmm, why does the encrypt filter does not + * take care about this? */ release_pk_list( pk_list ); return rc; } @@ -445,7 +430,7 @@ encode_crypt( const char *filename, STRLIST remusr ) /**************** - * Filter to do a complete public key encryption. + * Filter to handle the entire public key encryption. */ int encrypt_filter( void *opaque, int control, diff --git a/g10/export.c b/g10/export.c index 2de9f91bf..ddcc971d9 100644 --- a/g10/export.c +++ b/g10/export.c @@ -162,7 +162,7 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any ) log_error(_("certificate read problem: %s\n"), gpg_errstr(rc)); goto leave; } - + /* do not export keys which are incompatible with rfc2440 */ if( onlyrfc && (node = find_kbnode( keyblock, PKT_PUBLIC_KEY )) ) { diff --git a/g10/getkey.c b/g10/getkey.c index 17dc6fafb..aa32dff74 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -795,12 +795,19 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist, ctx->nitems = n; for(n=0, r=namelist; r; r = r->next, n++ ) { - ctx->items[n].mode = classify_user_id( r->d, - ctx->items[n].keyid, - ctx->items[n].fprint, - &ctx->items[n].name, - NULL ); - if( !ctx->items[n].mode ) { + int mode = classify_user_id( r->d, + ctx->items[n].keyid, + ctx->items[n].fprint, + &ctx->items[n].name, + NULL ); + + /* if we don't use one of the exact key specifications, we assume that + * the primary key is requested */ + if ( mode != 10 && mode != 11 && mode != 16 && mode == 20 ) + ctx->primary = 1; + + ctx->items[n].mode = mode; + if( !ctx->items[n].mode ) { gcry_free( ctx ); return GPGERR_INV_USER_ID; } @@ -810,8 +817,7 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist, } } - /* and call the lookup function */ - ctx->primary = 1; /* we want to look for the primary key only */ + if ( !ret_kb ) ret_kb = &help_kb; @@ -1337,8 +1343,13 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) pk->main_keyid[0] = kid[0]; pk->main_keyid[1] = kid[1]; - if ( pk->version < 4 ) - return; /* nothing to do for old keys FIXME: This is wrong!!!!*/ + if ( pk->version < 4 ) { + /* before v4 the key packet itself contains the expiration date + * and there was noway to change it. So we also use only the + * one from the key packet */ + key_expire = pk->expiredate; + key_expire_seen = 1; + } /* first pass: find the latest direct key self-signature. * We assume that the newest one overrides all others @@ -1394,12 +1405,14 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) key_usage |= GCRY_PK_USAGE_ENCR; } - p = parse_sig_subpkt ( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL); - if ( p ) { - key_expire = sig->timestamp + buffer_to_u32(p); - key_expire_seen = 1; + if ( pk->version > 3 ) { + p = parse_sig_subpkt ( sig->hashed_data, + SIGSUBPKT_KEY_EXPIRE, NULL); + if ( p ) { + key_expire = sig->timestamp + buffer_to_u32(p); + key_expire_seen = 1; + } } - /* and set the created field */ pk->created = sigdate; /* and mark that key as valid: one direct key signature should @@ -1518,8 +1531,8 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) } } } - if ( key_expire >= curtime ) - pk->has_expired = key_expire; + + pk->has_expired = key_expire >= curtime? 0 : key_expire; /* FIXME: we should see how to get rid of the expiretime fields */ @@ -1651,7 +1664,7 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode ) key_expire = sig->timestamp + buffer_to_u32(p); else key_expire = 0; - subpk->has_expired = key_expire >= curtime? key_expire : 0; + subpk->has_expired = key_expire >= curtime? 0 : key_expire; } @@ -1711,7 +1724,7 @@ merge_selfsigs( KBNODE keyblock ) * keys at all and have a way to store just the real secret parts * from the key. */ -static void +void merge_public_with_secret ( KBNODE pubblock, KBNODE secblock ) { KBNODE pub; @@ -1942,8 +1955,8 @@ finish_lookup( GETKEY_CTX ctx, KBNODE foundk ) } if (DBG_CACHE) - log_debug( "\tconsidering key created %lu\n", - (ulong)pk->created); + log_debug( "\tconsidering key %08lX\n", + (ulong)keyid_from_pk( pk, NULL)); if ( pk->created > latest_date ) { latest_date = pk->created; latest_key = k; @@ -1989,7 +2002,8 @@ finish_lookup( GETKEY_CTX ctx, KBNODE foundk ) } if (DBG_CACHE) - log_debug( "\tusing key created %lu\n", (ulong)latest_date ); + log_debug( "\tusing key %08lX\n", + (ulong)keyid_from_pk( latest_key->pkt->pkt.public_key, NULL) ); ctx->found_key = latest_key; diff --git a/g10/gpg.c b/g10/gpg.c index be4ec98a7..6faeb0721 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -509,6 +509,10 @@ static void register_extension( const char *mainpgm, const char *fname ) { #warning fixme add register cipher extension + /* Before we do so, we should design a beter API for this. + * I am currently thinking about using S-Exp to pass everything we + * need from the module to gcrypt. I hope we are not going to + * implement my-own-lisp-library-no-17000 */ #if 0 if( *fname != '/' ) { /* do tilde expansion etc */ char *tmp; diff --git a/g10/keydb.h b/g10/keydb.h index 830a7db3c..43c36e719 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -166,6 +166,7 @@ int get_seckey_next( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock ); void get_seckey_end( GETKEY_CTX ctx ); int enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys ); void merge_keys_and_selfsig( KBNODE keyblock ); +void merge_public_with_secret ( KBNODE pubblock, KBNODE secblock ); char*get_user_id_string( u32 *keyid ); char*get_user_id_string_native( u32 *keyid ); char*get_long_user_id_string( u32 *keyid ); diff --git a/g10/keygen.c b/g10/keygen.c index fc3b2cf8c..ef0064fc7 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -294,7 +294,6 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) { int rc; - int i; PACKET *pkt; PKT_secret_key *sk; PKT_public_key *pk; @@ -407,7 +406,6 @@ gen_dsa(unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval ) { int rc; - int i; PACKET *pkt; PKT_secret_key *sk; PKT_public_key *pk; @@ -948,7 +946,6 @@ ask_user_id( int mode ) /* append a warning if we do not have dev/random * or it is switched into quick testmode */ - #warning quick_random_gen() not available #if 0 if( quick_random_gen(-1) ) strcpy(p, " (INSECURE!)" ); diff --git a/g10/keyid.c b/g10/keyid.c index fb652e7b2..a4acb16d5 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -454,7 +454,7 @@ fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len ) int rc; size_t nbytes; - #warning Why is the hash sequence for secret keys different + /* FIXME: Why is the hash sequence for secret keys different */ rc = gcry_mpi_print( GCRYMPI_FMT_USG, NULL, &nbytes, sk->skey[1] ); assert( !rc ); /* fixme: allocate it on the stack */ diff --git a/g10/misc.c b/g10/misc.c index a62a04766..2348e46f0 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -330,6 +330,7 @@ print_cipher_algo_note( int algo ) else if( algo == GCRY_CIPHER_3DES || algo == GCRY_CIPHER_CAST5 || algo == GCRY_CIPHER_BLOWFISH + || algo == GCRY_CIPHER_RIJNDAEL || algo == GCRY_CIPHER_TWOFISH ) ; diff --git a/g10/pkclist.c b/g10/pkclist.c index d827ce653..d585880ea 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -819,7 +819,8 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use ) free_public_key( pk ); pk = NULL; log_error(_("%s: skipped: %s\n"), rov->d, gpg_errstr(rc) ); } - else if( !(rc=openpgp_pk_test_algo(pk->pubkey_algo, use )) ) { + else if( !(rc=openpgp_pk_test_algo(pk->pubkey_algo, + pk->pubkey_usage)) ) { /* Skip the actual key if the key is already present * in the list */ if (key_present_in_pk_list(pk_list, pk) == 0) { @@ -874,7 +875,8 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use ) rc = get_pubkey_byname( NULL, pk, answer, NULL ); if( rc ) tty_printf(_("No such user ID.\n")); - else if( !(rc=openpgp_pk_test_algo(pk->pubkey_algo, use)) ) { + else if( !(rc=openpgp_pk_test_algo(pk->pubkey_algo, + pk->pubkey_usage)) ) { if( have_def_rec ) { if (key_present_in_pk_list(pk_list, pk) == 0) { free_public_key(pk); pk = NULL; @@ -940,7 +942,8 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use ) rc = get_pubkey_byname( NULL, pk, def_rec, NULL ); if( rc ) log_error(_("unknown default recipient `%s'\n"), def_rec ); - else if( !(rc=openpgp_pk_test_algo(pk->pubkey_algo, use)) ) { + else if( !(rc=openpgp_pk_test_algo(pk->pubkey_algo, + pk->pubkey_usage)) ) { PK_LIST r = gcry_xmalloc( sizeof *r ); r->pk = pk; pk = NULL; r->next = pk_list; @@ -966,7 +969,8 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use ) free_public_key( pk ); pk = NULL; log_error(_("%s: skipped: %s\n"), remusr->d, gpg_errstr(rc) ); } - else if( !(rc=openpgp_pk_test_algo(pk->pubkey_algo, use )) ) { + else if( !(rc=openpgp_pk_test_algo(pk->pubkey_algo, + pk->pubkey_usage)) ) { int trustlevel; rc = check_trust( pk, &trustlevel, pk->namehash, NULL, NULL ); diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index 0be514eb3..2adb9ef4c 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -75,7 +75,6 @@ pk_check_secret_key( int algo, MPI *skey ) static int do_check( PKT_secret_key *sk ) { - byte *buffer; u16 csum=0; int i, res; unsigned nbytes; @@ -324,7 +323,7 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) GCRY_STRONG_RANDOM); gcry_cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen ); - #warning FIXME: replace set/get buffer + /* FIXME: replace set/get buffer */ if( sk->version >= 4 ) { byte *bufarr[GNUPG_MAX_NSKEY]; unsigned narr[GNUPG_MAX_NSKEY]; @@ -336,7 +335,7 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) i < pubkey_get_nskey(sk->pubkey_algo); i++, j++ ) { assert( !gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) ); - if( gcry_mpi_aprint( GCRYMPI_FMT_USG, (char*)bufarr+j, + if( gcry_mpi_aprint( GCRYMPI_FMT_USG, (void**)bufarr+j, narr+j, sk->skey[i])) BUG(); @@ -374,7 +373,7 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek ) else { /* NOTE: we always recalculate the checksum because there * are some test releases which calculated it wrong */ - #warning FIXME: Replace this code + /* FIXME: Replace this code -- Hmmm: why */ csum = 0; for(i=pubkey_get_npkey(sk->pubkey_algo); i < pubkey_get_nskey(sk->pubkey_algo); i++ ) { diff --git a/g10/sign.c b/g10/sign.c index b53444b7c..bdc5b8afe 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -40,6 +40,8 @@ #include "i18n.h" +#define ENABLE_BETTER_PGP2_COMPAT 1 + #ifdef HAVE_DOSISH_SYSTEM #define LF "\r\n" #else @@ -217,13 +219,13 @@ complete_sig( PKT_signature *sig, PKT_secret_key *sk, GCRY_MD_HD md ) } static int -hash_for(int pubkey_algo ) +hash_for(int pubkey_algo, int packet_version ) { if( opt.def_digest_algo ) return opt.def_digest_algo; if( pubkey_algo == GCRY_PK_DSA ) return GCRY_MD_SHA1; - if( pubkey_algo == GCRY_PK_RSA ) + if( pubkey_algo == GCRY_PK_RSA && packet_version < 4 ) return GCRY_MD_MD5; return DEFAULT_DIGEST_ALGO; } @@ -265,6 +267,94 @@ print_status_sig_created ( PKT_secret_key *sk, PKT_signature *sig, int what ) write_status_text( STATUS_SIG_CREATED, buf ); } +static int +write_one_signature( IOBUF out, PKT_secret_key *sk, int old_style, + const char *outfile, + GCRY_MD_HD datamd, + int sig_class, + int status_char ) +{ + PKT_signature *sig; + GCRY_MD_HD md; + int rc; + + /* build the signature packet */ + /* fixme: this code is partly duplicated in make_keysig_packet */ + sig = gcry_xcalloc( 1, sizeof *sig ); + sig->version = old_style || opt.force_v3_sigs ? 3 : sk->version; + keyid_from_sk( sk, sig->keyid ); + sig->digest_algo = hash_for(sk->pubkey_algo, sk->version); + sig->pubkey_algo = sk->pubkey_algo; + sig->timestamp = make_timestamp(); + sig->sig_class = sig_class; + + md = gcry_md_copy( datamd ); + if( !md ) + BUG(); + if( sig->version >= 4 ) { + build_sig_subpkt_from_sig( sig ); + gcry_md_putc( md, sig->version ); + } + + mk_notation_and_policy( sig ); + + gcry_md_putc( md, sig->sig_class ); + if( sig->version < 4 ) { + u32 a = sig->timestamp; + gcry_md_putc( md, (a >> 24) & 0xff ); + gcry_md_putc( md, (a >> 16) & 0xff ); + gcry_md_putc( md, (a >> 8) & 0xff ); + gcry_md_putc( md, a & 0xff ); + } + else { + byte buf[6]; + size_t n; + + gcry_md_putc( md, sig->pubkey_algo ); + gcry_md_putc( md, sig->digest_algo ); + if( sig->hashed_data ) { + n = (sig->hashed_data[0] << 8) | sig->hashed_data[1]; + gcry_md_write( md, sig->hashed_data, n+2 ); + n += 6; + } + else { + gcry_md_putc( md, 0 );/* always hash the length of the subpacket*/ + gcry_md_putc( md, 0 ); + n = 6; + } + /* add some magic */ + buf[0] = sig->version; + buf[1] = 0xff; + buf[2] = n >> 24; /* hmmm, n is only 16 bit, so this is always 0 */ + buf[3] = n >> 16; + buf[4] = n >> 8; + buf[5] = n; + gcry_md_write( md, buf, 6 ); + } + gcry_md_final( md ); + + rc = do_sign( sk, sig, md, hash_for(sig->pubkey_algo, sk->version) ); + gcry_md_close( md ); + /* Hmmm: Do we release sig in case of rc != 0? */ + + if( !rc ) { /* and write it */ + PACKET pkt; + + init_packet(&pkt); + pkt.pkttype = PKT_SIGNATURE; + pkt.pkt.signature = sig; + rc = build_packet( out, &pkt ); + if( !rc && is_status_enabled() ) { + print_status_sig_created ( sk, sig, status_char ); + } + free_packet( &pkt ); + if( rc ) + log_error("build signature packet failed: %s\n", gpg_errstr(rc) ); + } + + return rc; +} + /**************** * Sign the files whose names are in FILENAME. @@ -360,7 +450,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { PKT_secret_key *sk = sk_rover->sk; - gcry_md_enable(mfx.md, hash_for(sk->pubkey_algo)); + gcry_md_enable(mfx.md, hash_for(sk->pubkey_algo, sk->version )); } if( !multifile ) @@ -385,6 +475,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, iobuf_push_filter( out, encrypt_filter, &efx ); } + /* Select a compress algorithm */ if( opt.compress && !outfile && ( !detached || opt.compress_sigs) ) { if( !compr_algo ) ; /* don't use compression */ @@ -397,6 +488,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, } } + /* Build one-pass signature packets when needed */ if( !detached && !old_style ) { int skcount=0; /* loop over the secret certificates and build headers @@ -417,7 +509,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, sk = sk_rover->sk; ops = gcry_xcalloc( 1, sizeof *ops ); ops->sig_class = opt.textmode && !outfile ? 0x01 : 0x00; - ops->digest_algo = hash_for(sk->pubkey_algo); + ops->digest_algo = hash_for(sk->pubkey_algo, sk->version); ops->pubkey_algo = sk->pubkey_algo; keyid_from_sk( sk, ops->keyid ); ops->last = skcount == 1; @@ -437,6 +529,8 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, /* setup the inner packet */ if( detached ) { + /* this is pretty much the same for old and new PGP. So no + * need to cope with different packet ordering */ if( multifile ) { STRLIST sl; @@ -468,9 +562,11 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, } } else { + /* get the filename to be stored into the literal datapacket */ if (!opt.no_literal) { if( fname || opt.set_filename ) { - char *s = make_basename( opt.set_filename ? opt.set_filename : fname ); + char *s = make_basename( opt.set_filename ? + opt.set_filename : fname ); pt = gcry_xmalloc( sizeof *pt + strlen(s) - 1 ); pt->namelen = strlen(s); memcpy(pt->name, s, pt->namelen ); @@ -490,7 +586,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, if ( filesize >= IOBUF_FILELENGTH_LIMIT ) filesize = 0; - /* because the text_filter modifies the length of the + /* Because the text_filter modifies the length of the * data, it is not possible to know the used length * without a double read of the file - to avoid that * we simple use partial length packets. @@ -511,7 +607,8 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, pkt.pkt.plaintext = pt; /*cfx.datalen = filesize? calc_packet_length( &pkt ) : 0;*/ if( (rc = build_packet( out, &pkt )) ) - log_error("build_packet(PLAINTEXT) failed: %s\n", gpg_errstr(rc) ); + log_error("build_packet(PLAINTEXT) failed: %s\n", + gpg_errstr(rc) ); pt->buf = NULL; } else { @@ -520,100 +617,24 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1) if (iobuf_write(out, copy_buffer, bytes_copied) == -1) { rc = GPGERR_WRITE_FILE; - log_error("copying input to output failed: %s\n", gpg_errstr(rc)); + log_error("copying input to output failed: %s\n", + gpg_errstr(rc)); break; } memset(copy_buffer, 0, 4096); /* burn buffer */ } } - /* catch errors from above blocks */ + /* catch errors from above */ if (rc) goto leave; - /* loop over the secret certificates */ - for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - PKT_secret_key *sk; - PKT_signature *sig; - GCRY_MD_HD md; - - sk = sk_rover->sk; - - /* build the signature packet */ - /* fixme: this code is partly duplicated in make_keysig_packet */ - sig = gcry_xcalloc( 1, sizeof *sig ); - sig->version = old_style || opt.force_v3_sigs ? 3 : sk->version; - keyid_from_sk( sk, sig->keyid ); - sig->digest_algo = hash_for(sk->pubkey_algo); - sig->pubkey_algo = sk->pubkey_algo; - sig->timestamp = make_timestamp(); - sig->sig_class = opt.textmode && !outfile? 0x01 : 0x00; - - md = gcry_md_copy( mfx.md ); - if( !md ) - BUG(); - - if( sig->version >= 4 ) { - build_sig_subpkt_from_sig( sig ); - gcry_md_putc( md, sig->version ); - } - - mk_notation_and_policy( sig ); - - gcry_md_putc( md, sig->sig_class ); - if( sig->version < 4 ) { - u32 a = sig->timestamp; - gcry_md_putc( md, (a >> 24) & 0xff ); - gcry_md_putc( md, (a >> 16) & 0xff ); - gcry_md_putc( md, (a >> 8) & 0xff ); - gcry_md_putc( md, a & 0xff ); - } - else { - byte buf[6]; - size_t n; - - gcry_md_putc( md, sig->pubkey_algo ); - gcry_md_putc( md, sig->digest_algo ); - if( sig->hashed_data ) { - n = (sig->hashed_data[0] << 8) | sig->hashed_data[1]; - gcry_md_write( md, sig->hashed_data, n+2 ); - n += 6; - } - else { - gcry_md_putc( md, 0 ); /* always hash the length of the subpacket*/ - gcry_md_putc( md, 0 ); - n = 6; - } - /* add some magic */ - buf[0] = sig->version; - buf[1] = 0xff; - buf[2] = n >> 24; /* hmmm, n is only 16 bit, so this is always 0 */ - buf[3] = n >> 16; - buf[4] = n >> 8; - buf[5] = n; - gcry_md_write( md, buf, 6 ); - - } - gcry_md_final( md ); - - rc = do_sign( sk, sig, md, hash_for(sig->pubkey_algo) ); - gcry_md_close( md ); - - if( !rc ) { /* and write it */ - init_packet(&pkt); - pkt.pkttype = PKT_SIGNATURE; - pkt.pkt.signature = sig; - rc = build_packet( out, &pkt ); - if( !rc && is_status_enabled() ) { - print_status_sig_created ( sk, sig, detached ? 'D':'S'); - } - free_packet( &pkt ); - if( rc ) - log_error("build signature packet failed: %s\n", gpg_errstr(rc) ); - } - if( rc ) - goto leave; - + /* write all the signature packets */ + for( sk_rover = sk_list; sk_rover && !rc ; sk_rover = sk_rover->next ) { + rc = write_one_signature( out, sk_rover->sk, + old_style, outfile, mfx.md, + opt.textmode && !outfile? 0x01 : 0x00, + detached ? 'D':'S' ); } @@ -626,6 +647,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, gcry_md_close( mfx.md ); release_sk_list( sk_list ); release_pk_list( pk_list ); + /* FIXME: Did we release the efx.cfx.dek ? */ return rc; } @@ -679,7 +701,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { PKT_secret_key *sk = sk_rover->sk; - if( hash_for(sk->pubkey_algo) == GCRY_MD_MD5 ) + if( hash_for(sk->pubkey_algo, sk->version) == GCRY_MD_MD5 ) only_md5 = 1; else { only_md5 = 0; @@ -697,7 +719,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) iobuf_writestr(out, "Hash: " ); for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { PKT_secret_key *sk = sk_rover->sk; - int i = hash_for(sk->pubkey_algo); + int i = hash_for(sk->pubkey_algo, sk->version); if( !hashs_seen[ i & 0xff ] ) { if( !openpgp_md_test_algo( i ) ) { @@ -723,7 +745,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) BUG(); for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { PKT_secret_key *sk = sk_rover->sk; - gcry_md_enable(textmd, hash_for(sk->pubkey_algo)); + gcry_md_enable(textmd, hash_for(sk->pubkey_algo, sk->version)); } if ( DBG_HASHING ) gcry_md_start_debug( textmd, "clearsign" ); @@ -735,90 +757,14 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) afx.what = 2; iobuf_push_filter( out, armor_filter, &afx ); - /* loop over the secret certificates */ - for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - PKT_secret_key *sk; - PKT_signature *sig; - GCRY_MD_HD md; - - sk = sk_rover->sk; - - /* build the signature packet */ - /* fixme: this code is duplicated above */ - sig = gcry_xcalloc( 1, sizeof *sig ); - sig->version = old_style || opt.force_v3_sigs ? 3 : sk->version; - keyid_from_sk( sk, sig->keyid ); - sig->digest_algo = hash_for(sk->pubkey_algo); - sig->pubkey_algo = sk->pubkey_algo; - sig->timestamp = make_timestamp(); - sig->sig_class = 0x01; - - md = gcry_md_copy( textmd ); - if( !md ) - BUG(); - if( sig->version >= 4 ) { - build_sig_subpkt_from_sig( sig ); - gcry_md_putc( md, sig->version ); - } - - mk_notation_and_policy( sig ); - - gcry_md_putc( md, sig->sig_class ); - if( sig->version < 4 ) { - u32 a = sig->timestamp; - gcry_md_putc( md, (a >> 24) & 0xff ); - gcry_md_putc( md, (a >> 16) & 0xff ); - gcry_md_putc( md, (a >> 8) & 0xff ); - gcry_md_putc( md, a & 0xff ); - } - else { - byte buf[6]; - size_t n; - - gcry_md_putc( md, sig->pubkey_algo ); - gcry_md_putc( md, sig->digest_algo ); - if( sig->hashed_data ) { - n = (sig->hashed_data[0] << 8) | sig->hashed_data[1]; - gcry_md_write( md, sig->hashed_data, n+2 ); - n += 6; - } - else { - gcry_md_putc( md, 0 ); /* always hash the length of the subpacket*/ - gcry_md_putc( md, 0 ); - n = 6; - } - /* add some magic */ - buf[0] = sig->version; - buf[1] = 0xff; - buf[2] = n >> 24; /* hmmm, n is only 16 bit, so this is always 0 */ - buf[3] = n >> 16; - buf[4] = n >> 8; - buf[5] = n; - gcry_md_write( md, buf, 6 ); - - } - gcry_md_final( md ); - - rc = do_sign( sk, sig, md, hash_for(sig->pubkey_algo) ); - gcry_md_close( md ); - - if( !rc ) { /* and write it */ - init_packet(&pkt); - pkt.pkttype = PKT_SIGNATURE; - pkt.pkt.signature = sig; - rc = build_packet( out, &pkt ); - if( !rc && is_status_enabled() ) { - print_status_sig_created ( sk, sig, 'C'); - } - free_packet( &pkt ); - if( rc ) - log_error("build signature packet failed: %s\n", gpg_errstr(rc) ); - } - if( rc ) - goto leave; + /* write all the signature packets */ + for( sk_rover = sk_list; sk_rover && !rc ; sk_rover = sk_rover->next ) { + rc = write_one_signature( out, sk_rover->sk, + old_style, outfile, textmd, + 0x01, + 'C' ); } - leave: if( rc ) iobuf_cancel(out); diff --git a/g10/skclist.c b/g10/skclist.c index 5c6d6fbd7..dceba71f8 100644 --- a/g10/skclist.c +++ b/g10/skclist.c @@ -50,7 +50,7 @@ release_sk_list( SK_LIST sk_list ) int build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock, - unsigned use ) + unsigned int use ) { SK_LIST sk_list = NULL; int rc; @@ -64,9 +64,11 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock, free_secret_key( sk ); sk = NULL; log_error("no default secret key: %s\n", gpg_errstr(rc) ); } - else if( !(rc=openpgp_pk_test_algo(sk->pubkey_algo, use)) ) { + else if( !(rc=openpgp_pk_test_algo(sk->pubkey_algo, + sk->pubkey_usage)) ) { SK_LIST r; - if( sk->version == 4 && (use & GCRY_PK_USAGE_SIGN ) + + if( sk->version == 4 && (sk->pubkey_usage & GCRY_PK_USAGE_SIGN ) && sk->pubkey_algo == GCRY_PK_ELG_E ) { log_info("this is a PGP generated " "ElGamal key which is NOT secure for signatures!\n"); @@ -95,9 +97,10 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock, free_secret_key( sk ); sk = NULL; log_error(_("skipped `%s': %s\n"), locusr->d, gpg_errstr(rc) ); } - else if( !(rc=openpgp_pk_test_algo(sk->pubkey_algo, use)) ) { + else if( !(rc=openpgp_pk_test_algo(sk->pubkey_algo, + sk->pubkey_usage)) ) { SK_LIST r; - if( sk->version == 4 && (use & GCRY_PK_USAGE_SIGN) + if( sk->version == 4 && (sk->pubkey_usage & GCRY_PK_USAGE_SIGN) && sk->pubkey_algo == GCRY_PK_ELG_E ) { log_info(_("skipped `%s': this is a PGP generated " "ElGamal key which is not secure for signatures!\n"), diff --git a/g10/status.c b/g10/status.c index 2eb6724f3..d336ae3b0 100644 --- a/g10/status.c +++ b/g10/status.c @@ -74,8 +74,9 @@ set_status_fd ( int newfd ) { fd = newfd; if ( fd != -1 ) { - #if 0 #warning fixme - progress functions + /* Has to be fixed in libgcrypt */ + #if 0 register_primegen_progress ( progress_cb, "primegen" ); register_pk_dsa_progress ( progress_cb, "pk_dsa" ); register_pk_elg_progress ( progress_cb, "pk_elg" ); diff --git a/include/ttyio.h b/include/ttyio.h index 0b447066f..e81c659c4 100644 --- a/include/ttyio.h +++ b/include/ttyio.h @@ -24,6 +24,7 @@ int tty_batchmode( int onoff ); void tty_printf( const char *fmt, ... ); void tty_print_string( byte *p, size_t n ); void tty_print_utf8_string( byte *p, size_t n ); +void tty_print_utf8_string2( byte *p, size_t n, size_t max_n ); char *tty_get( const char *prompt ); char *tty_get_hidden( const char *prompt ); void tty_kill_prompt(void);