diff options
author | Werner Koch <wk@gnupg.org> | 2000-10-04 13:16:19 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2000-10-04 13:16:19 +0200 |
commit | 9c20f65cbe9d3d806b02f0f90a2051a20f3857db (patch) | |
tree | 6c784f870b191b2a1b3f16f86cff3a5af59ff2f6 /g10 | |
parent | See ChangeLog: Mon Sep 18 16:35:45 CEST 2000 Werner Koch (diff) | |
download | gnupg2-9c20f65cbe9d3d806b02f0f90a2051a20f3857db.tar.xz gnupg2-9c20f65cbe9d3d806b02f0f90a2051a20f3857db.zip |
See ChangeLog: Wed Oct 4 13:16:18 CEST 2000 Werner Koch
Diffstat (limited to 'g10')
-rw-r--r-- | g10/ChangeLog | 15 | ||||
-rw-r--r-- | g10/encode.c | 135 | ||||
-rw-r--r-- | g10/export.c | 2 | ||||
-rw-r--r-- | g10/getkey.c | 58 | ||||
-rw-r--r-- | g10/gpg.c | 4 | ||||
-rw-r--r-- | g10/keydb.h | 1 | ||||
-rw-r--r-- | g10/keygen.c | 3 | ||||
-rw-r--r-- | g10/keyid.c | 2 | ||||
-rw-r--r-- | g10/misc.c | 1 | ||||
-rw-r--r-- | g10/pkclist.c | 12 | ||||
-rw-r--r-- | g10/seckey-cert.c | 7 | ||||
-rw-r--r-- | g10/sign.c | 300 | ||||
-rw-r--r-- | g10/skclist.c | 13 | ||||
-rw-r--r-- | g10/status.c | 3 |
14 files changed, 263 insertions, 293 deletions
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 <wk@openit.de> + + * 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 <wk@openit.de> * 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; - - 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 */ + /* 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 ); + + /* 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; @@ -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" ); |