From bab40b52cd1b1408cbad1f74c18f5775ba415c94 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 30 Aug 2001 16:39:23 +0000 Subject: [PATCH] MDC feature support and other stuff --- NEWS | 6 +- TODO | 16 ++- checks/run-gpg.patterns | 5 + doc/ChangeLog | 5 + doc/DETAILS | 2 +- doc/FAQ | 88 +++++++------- doc/faq.raw | 39 +++--- g10/ChangeLog | 42 +++++++ g10/build-packet.c | 2 + g10/cipher.c | 24 +++- g10/delkey.c | 14 ++- g10/encode.c | 5 + g10/getkey.c | 70 ++++------- g10/kbnode.c | 5 +- g10/keydb.h | 8 +- g10/keyedit.c | 29 ++--- g10/keygen.c | 28 +++++ g10/packet.h | 11 +- g10/parse-packet.c | 34 ++++-- g10/pkclist.c | 25 ++++ g10/ringedit.c | 259 +++++++++++++++------------------------- g10/sig-check.c | 13 +- include/ChangeLog | 4 + include/cipher.h | 1 + 24 files changed, 404 insertions(+), 331 deletions(-) diff --git a/NEWS b/NEWS index dce7ba0dc..e7dcef3bb 100644 --- a/NEWS +++ b/NEWS @@ -24,7 +24,11 @@ * Merged Stefan's patches for RISC OS in. See comments in scripts/build-riscos. - * It is now possible to sign an convenional encrypt a message (-cs). + * It is now possible to sign and convenional encrypt a message (-cs). + + * The MDC feature flag is supported and can be set by using + the "updpref" edit command. + Noteworthy changes in version 1.0.6 (2001-05-29) ------------------------------------------------ diff --git a/TODO b/TODO index 920b43bf7..ee3998651 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,5 @@ + * need a BAD_PASSPHRASE status for -c * add listing of notation data @@ -9,11 +10,6 @@ * Show more info does not work from edit->trust - * keyedit_menu: We first look for a secret key and then for a public - key. This is bad we must match the keys. Better check all places - were we match keys. build_sig_packet: implement update for - sig-creation. - * set default charset from nl_langinfo. * check all mpi_read() for error returns. @@ -79,10 +75,18 @@ preferences is okay and make AES the default. * Concatenated encryption messages don't work corectly - only the - first one is processes. + first one is processed. * Add status message for reasons why a key was not selected. + * Add option to put the list of recipients (from the encryption + layer) into the signatures notation data. + + * v3 RSA keys do work but the user IDs are shown as [?] which + cheking the signatures. Reported by Dave Dykstra. Print + "[uncertain]" + user ID + + Scheduled for 1.1 ----------------- * export by user-IDs does only export the first matching name which leads diff --git a/checks/run-gpg.patterns b/checks/run-gpg.patterns index 9f5292e8a..a67b60411 100644 --- a/checks/run-gpg.patterns +++ b/checks/run-gpg.patterns @@ -18,3 +18,8 @@ secret key 9D266E0F expired at : expired at gpg: Note: This key has expired! gpg: Fingerprint: 0826 1CB7 C976 5344 E207 4184 3C6B BBE6 9D26 6E0F +gpg: 3DES encrypted data +gpg: CAST5 encrypted data +gpg: BLOWFISH encrypted data +gpg: TWOFISH encrypted data +gpg: RIJNDAEL encrypted data diff --git a/doc/ChangeLog b/doc/ChangeLog index b099702e7..64d043802 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,8 @@ +2001-08-29 Werner Koch + + * faq.raw: Described how to delete a secret key w/o a public key + and changed the entry on updating the preferences. + 2001-08-08 Werner Koch * gpg.sgml: Documented --print-mds and marked the --print-md * as diff --git a/doc/DETAILS b/doc/DETAILS index 49b7fb514..7386bed9e 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -227,7 +227,7 @@ more arguments in future versions. Mark the start and end of the actual decryption process. These are also emitted when in --list-only mode. - BEGIN_ENCRYPTION + BEGIN_ENCRYPTION END_ENCRYPTION Mark the start and end of the actual encryption process. diff --git a/doc/FAQ b/doc/FAQ index 5beb316ba..7f180db18 100644 --- a/doc/FAQ +++ b/doc/FAQ @@ -45,21 +45,22 @@ you could search in the mailing list archive. 4.4) What is the difference between options and commands? 4.5) I can't delete an user id because it is already deleted on my public keyring? - 4.6) What are trust, validity and ownertrust? - 4.7) How do I sign a patch file? - 4.8) Where is the "encrypt-to-self" option? - 4.9) How can I get rid of the Version and Comment headers in armored + 4.6) I can't delete the secret key because my public key disappeared? + 4.7) What are trust, validity and ownertrust? + 4.8) How do I sign a patch file? + 4.9) Where is the "encrypt-to-self" option? + 4.10) How can I get rid of the Version and Comment headers in armored messages? - 4.10) What does the "You are using the xxxx character set." mean? - 4.11) How can a get list of key IDs used to encrypt a message? - 4.12) I can't decrypt my symmetrical only (-c) encrypted message with + 4.11) What does the "You are using the xxxx character set." mean? + 4.12) How can a get list of key IDs used to encrypt a message? + 4.13) I can't decrypt my symmetrical only (-c) encrypted message with a new version of GnuPG. - 4.13) How can I used GnuPG in an automated environment? - 4.14) Which email-client can I use with GnuPG? - 4.15) Can't we have a gpg library? - 4.16) I have successfully generated a revocation certificate, but I don't + 4.14) How can I used GnuPG in an automated environment? + 4.15) Which email-client can I use with GnuPG? + 4.16) Can't we have a gpg library? + 4.17) I have successfully generated a revocation certificate, but I don't understand how to send it to the key servers. - 4.17) How do I put my keyring in a different directory? + 4.18) How do I put my keyring in a different directory? 5. COMPATIBILITY ISSUES 5.1) How can I encrypt a message with GnuPG so that PGP is able to decrypt it? @@ -330,7 +331,18 @@ keyring? ring. Now select this user id and delete it. Both user ids will be removed from the secret ring. -4.6) What are trust, validity and ownertrust? +4.6) I can't delete the secret key because my public key disappeared? + + To select a key a search is always done on the public keyring, + therefore it is not possible to select an secret key without + having the public key. Normally it shoud never happen that the + public key got lost but the secret key is still available. The + reality is different, so we GnuPG implements a special way to do + deal with it: Simply use the long keyid which you can figure out + by using the --with-colons options (it is the fifth field in the + lines beginning with "sec"). + +4.7) What are trust, validity and ownertrust? "ownertrust" is used instead of "trust" to make clear that this is the value you have assigned to a key to express how much you trust @@ -340,7 +352,7 @@ keyring? who claims to be the owner of the key). For more see the chapter "The Web of Trust" in the Manual. -4.7) How do I sign a patch file? +4.8) How do I sign a patch file? Use "gpg --clearsign --not-dash-escaped ...". The problem with --clearsign is that all lines starting with a dash are quoted with @@ -353,19 +365,19 @@ keyring? mailer may not preserve these. If you want to mail a file you can simply sign it using your MUA. -4.8) Where is the "encrypt-to-self" option? +4.9) Where is the "encrypt-to-self" option? Use "--encrypt-to your_keyid". You can use more than one of these options. To temporary override the use of this additional keys, you can use the option "--no-encrypt-to". -4.9) How can I get rid of the Version and Comment headers in armored +4.10) How can I get rid of the Version and Comment headers in armored messages? Use "--no-version --comment ''". Note that the left over blank line is required by the protocol. -4.10) What does the "You are using the xxxx character set." mean? +4.11) What does the "You are using the xxxx character set." mean? This note is printed when UTF8 mapping has to be done. Make sure that the displayed charset is the one you have activated on your @@ -375,12 +387,12 @@ messages? if not, restrict yourself to plain 7 bit ASCII and no mapping has to be done. -4.11) How can a get list of key IDs used to encrypt a message? +4.12) How can a get list of key IDs used to encrypt a message? gpg --batch --decrypt --list-only --status-fd 1 2>/dev/null | \ awk '/^\[GNUPG:\] ENC_TO / { print $3 }' -4.12) I can't decrypt my symmetrical only (-c) encrypted message with +4.13) I can't decrypt my symmetrical only (-c) encrypted message with a new version of GnuPG. There used to be a bug in GnuPG < 1.0.1 which happens only if 3DES @@ -391,7 +403,7 @@ messages? without this option. The option will be removed in 1.1, so better re-encrypt your message now. -4.13) How can I used GnuPG in an automated environment? +4.14) How can I used GnuPG in an automated environment? You should use the option --batch and don't use pass phrases as there is usually no way to store it more secure than the secret @@ -415,7 +427,7 @@ messages? turn can revoke all the subkeys installed on that machine and install new subkeys. -4.14) Which email-client can I use with GnuPG? +4.15) Which email-client can I use with GnuPG? Using GnuPG to encrypt email is one of the most popular uses. Several mail clients or mail user-agents (MUA) support GnuPG @@ -441,7 +453,7 @@ messages? may be possible to use a wrapper. -4.15) Can't we have a gpg library? +4.16) Can't we have a gpg library? This has been frequently requested. However, the current viewpoint of the GnuPG maintainers is that this would lead to several security @@ -451,7 +463,7 @@ messages? ftp://ftp.guug.de/pub/gcrypt/alpha/gpgme -4.16) I have successfully generated a revocation certificate, but I don't +4.17) I have successfully generated a revocation certificate, but I don't understand how to send it to the key servers. Most keyservers don't accept a 'bare' revocation certificate. You @@ -462,7 +474,7 @@ messages? (or use a keyserver web interface for this). -4.17) How do I put my keyring in a different directory? +4.18) How do I put my keyring in a different directory? GnuPG keeps several files in a special homedir directory. These include the options file, pubring.gpg, secring.gpg, the trustdb, and @@ -915,25 +927,15 @@ material? 7.8) How do I change the list of preferred algorithms? - Currently the default is hard-wired into the GnuPG source code. - You'll have to change g10/keygen.c and recompile. The - function you'll have to change is keygen_add_std_prefs. - The code is pretty self-explanatory. The constants used to - denote the algorithms are defined in include/cipher.h. - - After having done that, generate a new key pair (or a new encryption - subkey) with the modified executable. This new key will have the - modified preferences and can then be used with unmodified executables. - - To modify the preferences of an existing key, use a modified - executable (see above) to change the expiry date and then save the - key. The use your original expiry date and save the key again. Now - you've got the prefs changed and can use the key again with your - unmodified executable. - - Changing the list of preferences with an unmodified GnuPG - executable (possibly in the edit-key menu) is on the TODO list and - planned for future releases. + Use the edit menu and set the new list of preference using the + command "setpref"; the format of this command resembles the output + of the command "pref". The preference are not changes immediately + but the set preference will be used when a new user ID is + created. If you want to update the preferences for existing user + IDs, select those user IDs (or select none to update all) and + enter the command "updpref". Note that the timestamp of the + self-signaures is increaded by one second when running this + command. 8. ACKNOWLEDGEMENTS diff --git a/doc/faq.raw b/doc/faq.raw index 8d0d68ac0..03be7c822 100644 --- a/doc/faq.raw +++ b/doc/faq.raw @@ -279,6 +279,17 @@ keyring? ring. Now select this user id and delete it. Both user ids will be removed from the secret ring. + I can't delete the secret key because my public key disappeared? + + To select a key a search is always done on the public keyring, + therefore it is not possible to select an secret key without + having the public key. Normally it shoud never happen that the + public key got lost but the secret key is still available. The + reality is different, so we GnuPG implements a special way to do + deal with it: Simply use the long keyid which you can figure out + by using the --with-colons options (it is the fifth field in the + lines beginning with "sec"). + What are trust, validity and ownertrust? "ownertrust" is used instead of "trust" to make clear that this is @@ -887,25 +898,15 @@ material? How do I change the list of preferred algorithms? - Currently the default is hard-wired into the GnuPG source code. - You'll have to change [H pre]g10/keygen.c[H/pre] and recompile. The - function you'll have to change is [H pre]keygen_add_std_prefs[H /pre]. - The code is pretty self-explanatory. The constants used to - denote the algorithms are defined in [H pre]include/cipher.h[H /pre]. - - After having done that, generate a new key pair (or a new encryption - subkey) with the modified executable. This new key will have the - modified preferences and can then be used with unmodified executables. - - To modify the preferences of an existing key, use a modified - executable (see above) to change the expiry date and then save the - key. The use your original expiry date and save the key again. Now - you've got the prefs changed and can use the key again with your - unmodified executable. - - Changing the list of preferences with an unmodified GnuPG - executable (possibly in the edit-key menu) is on the TODO list and - planned for future releases. + Use the edit menu and set the new list of preference using the + command "setpref"; the format of this command resembles the output + of the command "pref". The preference are not changes immediately + but the set preference will be used when a new user ID is + created. If you want to update the preferences for existing user + IDs, select those user IDs (or select none to update all) and + enter the command "updpref". Note that the timestamp of the + self-signaures is increaded by one second when running this + command. ACKNOWLEDGEMENTS diff --git a/g10/ChangeLog b/g10/ChangeLog index 1499c0eaf..23fc5e3eb 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,45 @@ +2001-08-30 Werner Koch + + * packet.h (sigsubpkttype_t): Add SIGSUBPKT_FEATURES. + (PKT_public_key, PKT_user_id): Add a flag for it. + * parse-packet.c, build-packet.c: Add support for them. + * getkey.c (fixup_uidnode, merge_selfsigs): Set the MDC flags. + * keygen.c (add_feature_mdc): New. + (keygen_upd_std_prefs): Always set the MDC feature. + * keyedit.c (show_prefs): List the MDC flag + * pkclist.c (select_mdc_from_pklist): New. + * encode.c (encode_crypt, encrypt_filter): Test whether MDC + should be used. + * cipher.c (write_header): Set MDC use depending on the above test. + Print more status info. + + * delkey.c (do_delete_key): Kludge to delete a secret key with no + public key available. + + * ringedit.c (find_secret_keyblock_direct): New. + * getkey.c (seckey_available): Simplified. + + * ringedit.c (cmp_seckey): Now compares the secret key against the + public key while ignoring all secret parts. + (keyring_search): Use a public key packet as arg. Allow to search + for subnkeys + (search): Likewise. Changed all callers. + (find_secret_keyblock_bypk): New. + (find_secret_keyblock_byname): First locate the pubkey and then + find the correponding secret key. + * parse-packet.c (parse): Renamed pkttype arg to onlykeypkts and + changed code accordingly. Changed all callers. + (search_packet): Removed pkttype arg. + * keyedit.c (keyedit_menu): First locate the public key and then + try to locate a secret key. + + * ringedit.c (locate_keyblock_by_fpr): Removed. + (locate_keyblock_by_keyid): Removed. + (find_keyblock_bysk): Removed. + + * sig-check.c (check_key_signature2): Print the keyid along with + the wrong sig class errors. + 2001-08-24 Werner Koch * sign.c (sign_file): Stripped the disabled comment packet code. diff --git a/g10/build-packet.c b/g10/build-packet.c index 194ff16ce..1b7e0d838 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -747,6 +747,7 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, case SIGSUBPKT_PREF_SYM: case SIGSUBPKT_PREF_HASH: case SIGSUBPKT_PREF_COMPR: + case SIGSUBPKT_FEATURES: delete_sig_subpkt (sig->hashed, type); break; default: @@ -783,6 +784,7 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, case SIGSUBPKT_REVOC_REASON: case SIGSUBPKT_PRIMARY_UID: case SIGSUBPKT_KEY_FLAGS: + case SIGSUBPKT_FEATURES: hashed = 1; break; default: hashed = 0; break; } diff --git a/g10/cipher.c b/g10/cipher.c index fbee543be..c1cf226a8 100644 --- a/g10/cipher.c +++ b/g10/cipher.c @@ -47,16 +47,27 @@ write_header( cipher_filter_context_t *cfx, IOBUF a ) byte temp[18]; unsigned blocksize; unsigned nprefix; - int use_mdc = opt.force_mdc; + int use_mdc; blocksize = cipher_get_blocksize( cfx->dek->algo ); if( blocksize < 8 || blocksize > 16 ) log_fatal("unsupported blocksize %u\n", blocksize ); + + use_mdc = cfx->dek->use_mdc; + if( blocksize != 8 ) - use_mdc = 1; /* enable it for all modern ciphers */ + use_mdc = 1; /* Hack: enable it for all modern ciphers */ + /* Note: We should remove this hack as soon as a reasonable number of keys + are carrying the MDC flag. But always keep the hack for conventional + encryption */ + + if (opt.force_mdc) + use_mdc = 1; + if( opt.rfc2440 || opt.rfc1991 ) use_mdc = 0; /* override - rfc2440 does not know about MDC */ + memset( &ed, 0, sizeof ed ); ed.len = cfx->datalen; ed.extralen = blocksize+2; @@ -67,6 +78,14 @@ write_header( cipher_filter_context_t *cfx, IOBUF a ) if ( DBG_HASHING ) md_start_debug( cfx->mdc_hash, "creatmdc" ); } + + { + char buf[20]; + + sprintf (buf, "%d %d", ed.mdc_method, cfx->dek->algo); + write_status_text (STATUS_BEGIN_ENCRYPTION, buf); + } + init_packet( &pkt ); pkt.pkttype = use_mdc? PKT_ENCRYPTED_MDC : PKT_ENCRYPTED; pkt.pkt.encrypted = &ed; @@ -111,7 +130,6 @@ cipher_filter( void *opaque, int control, else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */ assert(a); if( !cfx->header ) { - write_status( STATUS_BEGIN_ENCRYPTION ); write_header( cfx, a ); } if( cfx->mdc_hash ) diff --git a/g10/delkey.c b/g10/delkey.c index 784fe03bf..777d4c174 100644 --- a/g10/delkey.c +++ b/g10/delkey.c @@ -61,8 +61,18 @@ do_delete_key( const char *username, int secret, int *r_sec_avail ) *r_sec_avail = 0; /* search the userid */ - rc = secret? find_secret_keyblock_byname( &kbpos, username ) - : find_keyblock_byname( &kbpos, username ); + if (secret + && classify_user_id (username, keyid, NULL, NULL, NULL) == 11) { + /* if the user supplied a long keyID we use the direct search + methods which allows us to delete a key if the + corresponding secret key is missing */ + rc = find_secret_keyblock_direct (&kbpos, keyid); + } + else if (secret) + rc = find_secret_keyblock_byname (&kbpos, username); + else + rc = find_keyblock_byname (&kbpos, username); + if( rc ) { log_error(_("%s: user not found\n"), username ); write_status_text( STATUS_DELETE_PROBLEM, "1" ); diff --git a/g10/encode.c b/g10/encode.c index 8cc44c152..7d9f0952f 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -299,6 +299,8 @@ encode_crypt( const char *filename, STRLIST remusr ) } else cfx.dek->algo = opt.def_cipher_algo; + cfx.dek->use_mdc = select_mdc_from_pklist (pk_list); + make_session_key( cfx.dek ); if( DBG_CIPHER ) log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen ); @@ -428,6 +430,9 @@ encrypt_filter( void *opaque, int control, } else efx->cfx.dek->algo = opt.def_cipher_algo; + + efx->cfx.dek->use_mdc = select_mdc_from_pklist (efx->pk_list); + make_session_key( efx->cfx.dek ); if( DBG_CIPHER ) log_hexdump("DEK is: ", diff --git a/g10/getkey.c b/g10/getkey.c index c9d1b874b..8293fc673 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -542,55 +542,8 @@ get_seckey( PKT_secret_key *sk, u32 *keyid ) int seckey_available( u32 *keyid ) { -#if 0 - int rc; - struct getkey_ctx_s ctx; - KBNODE kb = NULL; - - memset( &ctx, 0, sizeof ctx ); - ctx.exact = 1; /* use the key ID exactly as given */ - ctx.not_allocated = 1; - ctx.nitems = 1; - ctx.items[0].mode = 11; - ctx.items[0].keyid[0] = keyid[0]; - ctx.items[0].keyid[1] = keyid[1]; - rc = lookup( &ctx, &kb, 1 ); - get_seckey_end( &ctx ); - release_kbnode ( kb ); - return rc; -#endif - int rc; - int found = 0; - int oldmode = set_packet_list_mode (0); - KBNODE keyblock = NULL; - KBPOS kbpos; - - rc = enum_keyblocks ( 5, &kbpos, NULL ); - if ( !rc ) { - while ( !(rc = enum_keyblocks (1, &kbpos, &keyblock)) ) { - KBNODE k; - - for (k=keyblock; k; k = k->next ) { - if ( k->pkt->pkttype == PKT_SECRET_KEY - || k->pkt->pkttype == PKT_SECRET_SUBKEY ) { - u32 aki[2]; - keyid_from_sk (k->pkt->pkt.secret_key, aki ); - if( aki[1] == keyid[1] && aki[0] == keyid[0] ) { - found = 1; - goto leave; - } - } - } - release_kbnode (keyblock); keyblock = NULL; - } - } - if( rc && rc != -1 ) - log_error ("enum_keyblocks failed: %s\n", g10_errstr(rc)); - leave: - release_kbnode (keyblock); - enum_keyblocks ( 2, &kbpos, NULL ); - set_packet_list_mode (oldmode); - return found? 0 : G10ERR_NO_SECKEY; + KBPOS dummy_kbpos; + return find_secret_keyblock_direct (&dummy_kbpos, keyid)? G10ERR_NO_SECKEY:0; } @@ -1458,7 +1411,7 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) * from the hashed list but if there are no such preferences, we * try to get them from the unhashed list. There is no risk with * that, because our implementation comes only with strong - * algorithms and it woulkd be fruitless for an attacker to insert + * algorithms and it would be fruitless for an attacker to insert * an weak algorithm. */ p = parse_sig_subpkt2 ( sig, SIGSUBPKT_PREF_SYM, &n ); sym = p; nsym = p?n:0; @@ -1490,6 +1443,18 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) uid->prefs[n].value = 0; } + /* see whether we have the MDC feature */ + uid->mdc_feature = 0; + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_FEATURES, &n); + if (!p) + n=0; + for (; n; n--, p++) { + if (*p == 1) { + uid->mdc_feature = 1; + break; + } + } + } static void @@ -1846,6 +1811,7 @@ merge_selfsigs( KBNODE keyblock ) int revoked; PKT_public_key *main_pk; prefitem_t *prefs; + int mdc_feature; if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY ) { if (keyblock->pkt->pkttype == PKT_SECRET_KEY ) { @@ -1890,12 +1856,15 @@ merge_selfsigs( KBNODE keyblock ) * use reference counting to optimize the preference lists storage. * FIXME: it might be better to use the intersection of * all preferences. + * Do a similar thing for the MDC feature flag. */ prefs = NULL; + mdc_feature = 0; for (k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; k = k->next) { if (k->pkt->pkttype == PKT_USER_ID && k->pkt->pkt.user_id->is_primary) { prefs = k->pkt->pkt.user_id->prefs; + mdc_feature = k->pkt->pkt.user_id->mdc_feature; break; } } @@ -1906,6 +1875,7 @@ merge_selfsigs( KBNODE keyblock ) if (pk->prefs) m_free (pk->prefs); pk->prefs = copy_prefs (prefs); + pk->mdc_feature = mdc_feature; } } diff --git a/g10/kbnode.c b/g10/kbnode.c index 4a031a09c..6a5543f67 100644 --- a/g10/kbnode.c +++ b/g10/kbnode.c @@ -385,12 +385,13 @@ dump_kbnode( KBNODE node ) else if( node->pkt->pkttype == PKT_PUBLIC_KEY || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { PKT_public_key *pk = node->pkt->pkt.public_key; - fprintf(stderr, " keyid=%08lX a=%d u=%d %c%c%c\n", + fprintf(stderr, " keyid=%08lX a=%d u=%d %c%c%c%c\n", (ulong)keyid_from_pk( pk, NULL ), pk->pubkey_algo, pk->pubkey_usage, pk->has_expired? 'e':'.', pk->is_revoked? 'r':'.', - pk->is_valid? 'v':'.' ); + pk->is_valid? 'v':'.', + pk->mdc_feature? 'm':'.'); } else fputs("\n", stderr); diff --git a/g10/keydb.h b/g10/keydb.h index e0dc178d4..8438a3f9d 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -124,6 +124,7 @@ int check_signatures_trust( PKT_signature *sig ); void release_pk_list( PK_LIST pk_list ); int build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use ); int select_algo_from_prefs( PK_LIST pk_list, int preftype ); +int select_mdc_from_pklist (PK_LIST pk_list); /*-- skclist.c --*/ void release_sk_list( SK_LIST sk_list ); @@ -218,15 +219,12 @@ int add_keyblock_resource( const char *resname, int force, int secret ); const char *keyblock_resource_name( KBPOS *kbpos ); int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos ); char *get_writable_keyblock_file( int secret ); -int locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr, - int fprlen, int secret ); -int locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid, - int shortkid, int secret ); int find_keyblock( PUBKEY_FIND_INFO info, KBPOS *kbpos ); int find_keyblock_byname( KBPOS *kbpos, const char *username ); int find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk ); -int find_keyblock_bysk( KBPOS *kbpos, PKT_secret_key *sk ); +int find_secret_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk ); int find_secret_keyblock_byname( KBPOS *kbpos, const char *username ); +int find_secret_keyblock_direct (KBPOS *kbpos, u32 *keyid); int lock_keyblock( KBPOS *kbpos ); void unlock_keyblock( KBPOS *kbpos ); int read_keyblock( KBPOS *kbpos, KBNODE *ret_root ); diff --git a/g10/keyedit.c b/g10/keyedit.c index fed390d6e..875e229e0 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -650,10 +650,19 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, have_commands = 1; } + /* get the public key */ + rc = get_keyblock_byname( &keyblock, &keyblockpos, username ); + if( rc ) + goto leave; + if( fix_keyblock( keyblock ) ) + modified++; + if( collapse_uids( &keyblock ) ) + modified++; - if( !sign_mode ) { - /* first try to locate it as secret key */ - rc = find_secret_keyblock_byname( &sec_keyblockpos, username ); + if( !sign_mode ) {/* see whether we have a matching secret key */ + PKT_public_key *pk = keyblock->pkt->pkt.public_key; + + rc = find_secret_keyblock_bypk( &sec_keyblockpos, pk ); if( !rc ) { rc = read_keyblock( &sec_keyblockpos, &sec_keyblock ); if( rc ) { @@ -667,17 +676,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, } } - /* and now get the public key */ - rc = get_keyblock_byname( &keyblock, &keyblockpos, username ); - if( rc ) - goto leave; - if( fix_keyblock( keyblock ) ) - modified++; - if( collapse_uids( &keyblock ) ) - modified++; - - if( sec_keyblock ) { /* check that they match */ - /* fixme: check that they both match */ + if( sec_keyblock ) { tty_printf(_("Secret key is available.\n")); } @@ -1118,6 +1117,8 @@ show_prefs (PKT_user_id *uid, int verbose) prefs[i].type == PREFTYPE_ZIP ? 'Z':'?', prefs[i].value); } + if (uid->mdc_feature) + tty_printf (" [mdc]"); tty_printf("\n"); } } diff --git a/g10/keygen.c b/g10/keygen.c index ce9169be6..37d4a0740 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -280,6 +280,30 @@ keygen_get_std_prefs () } +static void +add_feature_mdc (PKT_signature *sig) +{ + const byte *s; + size_t i, n; + char *buf; + + s = parse_sig_subpkt (sig->hashed, SIGSUBPKT_FEATURES, &n ); + if (!s) + n = 0; + + for (i=0; i < n; i++ ) { + if (s[i] == 1) + return; /* already set */ + } + + buf = m_alloc (n+1); + buf[0] = 1; /* MDC feature */ + memcpy (buf+1, s, n); + build_sig_subpkt (sig, SIGSUBPKT_FEATURES, buf, n+1); + m_free (buf); +} + + int keygen_upd_std_prefs( PKT_signature *sig, void *opaque ) { @@ -298,6 +322,10 @@ keygen_upd_std_prefs( PKT_signature *sig, void *opaque ) build_sig_subpkt (sig, SIGSUBPKT_PREF_COMPR, zip_prefs, nzip_prefs); else delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_COMPR); + + /* Make sure that the MDC feature flag is set */ + add_feature_mdc (sig); + return 0; } diff --git a/g10/packet.h b/g10/packet.h index e80711759..5e4e89ea0 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -145,6 +145,7 @@ typedef struct { int is_primary; int is_revoked; prefitem_t *prefs; /* list of preferences (may be NULL)*/ + int mdc_feature; u32 created; /* according to the self-signature */ char name[1]; } PKT_user_id; @@ -172,6 +173,7 @@ typedef struct { u32 main_keyid[2]; /* keyid of the primary key */ u32 keyid[2]; /* calculated by keyid_from_pk() */ prefitem_t *prefs; /* list of preferences (may be NULL) */ + int mdc_feature; /* mdc feature set */ byte *namehash; /* if != NULL: found by this name */ PKT_user_id *user_id; /* if != NULL: found by that uid */ MPI pkey[PUBKEY_MAX_NPKEY]; @@ -303,6 +305,7 @@ typedef enum { SIGSUBPKT_KEY_FLAGS =27, /* key flags */ SIGSUBPKT_SIGNERS_UID =28, /* signer's user id */ SIGSUBPKT_REVOC_REASON =29, /* reason for revocation */ + SIGSUBPKT_FEATURES =30, /* feature flags */ SIGSUBPKT_PRIV_VERIFY_CACHE =101, /* cache verification result */ SIGSUBPKT_FLAG_CRITICAL=128 @@ -320,7 +323,7 @@ int list_packets( IOBUF a ); int set_packet_list_mode( int mode ); #if DEBUG_PARSE_PACKET -int dbg_search_packet( IOBUF inp, PACKET *pkt, int pkttype, off_t *retpos, +int dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, const char* file, int lineno ); int dbg_parse_packet( IOBUF inp, PACKET *ret_pkt, const char* file, int lineno ); @@ -330,8 +333,8 @@ int dbg_copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff, const char* file, int lineno ); int dbg_skip_some_packets( IOBUF inp, unsigned n, const char* file, int lineno ); -#define search_packet( a,b,c,d ) \ - dbg_search_packet( (a), (b), (c), (d), __FILE__, __LINE__ ) +#define search_packet( a,b,c ) \ + dbg_search_packet( (a), (b), (c), __FILE__, __LINE__ ) #define parse_packet( a, b ) \ dbg_parse_packet( (a), (b), __FILE__, __LINE__ ) #define copy_all_packets( a,b ) \ @@ -341,7 +344,7 @@ int dbg_skip_some_packets( IOBUF inp, unsigned n, #define skip_some_packets( a,b ) \ dbg_skip_some_packets((a),(b), __FILE__, __LINE__ ) #else -int search_packet( IOBUF inp, PACKET *pkt, int pkttype, off_t *retpos ); +int search_packet( IOBUF inp, PACKET *pkt, off_t *retpos ); int parse_packet( IOBUF inp, PACKET *ret_pkt); int copy_all_packets( IOBUF inp, IOBUF out ); int copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff ); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 5461664f0..50e293097 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -38,7 +38,7 @@ static int mpi_print_mode = 0; static int list_mode = 0; -static int parse( IOBUF inp, PACKET *pkt, int reqtype, +static int parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, int *skip, IOBUF out, int do_skip #ifdef DEBUG_PARSE_PACKET ,const char *dbg_w, const char *dbg_f, int dbg_l @@ -154,28 +154,28 @@ parse_packet( IOBUF inp, PACKET *pkt ) #endif /**************** - * Like parse packet, but only return packets of the given type. + * Like parse packet, but only return secret or public (sub)key packets. */ #ifdef DEBUG_PARSE_PACKET int -dbg_search_packet( IOBUF inp, PACKET *pkt, int pkttype, off_t *retpos, +dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, const char *dbg_f, int dbg_l ) { int skip, rc; do { - rc = parse( inp, pkt, pkttype, retpos, &skip, NULL, 0, "search", dbg_f, dbg_l ); + rc = parse( inp, pkt, 1, retpos, &skip, NULL, 0, "search", dbg_f, dbg_l ); } while( skip ); return rc; } #else int -search_packet( IOBUF inp, PACKET *pkt, int pkttype, off_t *retpos ) +search_packet( IOBUF inp, PACKET *pkt, off_t *retpos ) { int skip, rc; do { - rc = parse( inp, pkt, pkttype, retpos, &skip, NULL, 0 ); + rc = parse( inp, pkt, 1, retpos, &skip, NULL, 0 ); } while( skip ); return rc; } @@ -277,14 +277,14 @@ skip_some_packets( IOBUF inp, unsigned n ) /**************** - * Parse packet. Set the variable skip points to to 1 if the packet - * should be skipped; this is the case if either there is a - * requested packet type and the parsed packet doesn't match or the + * Parse packet. Set the variable skip points to 1 if the packet + * should be skipped; this is the case if either ONLYKEYPKTS is set + * and the parsed packet isn't one or the * packet-type is 0, indicating deleted stuff. * if OUT is not NULL, a special copymode is used. */ static int -parse( IOBUF inp, PACKET *pkt, int reqtype, off_t *retpos, +parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos, int *skip, IOBUF out, int do_skip #ifdef DEBUG_PARSE_PACKET ,const char *dbg_w, const char *dbg_f, int dbg_l @@ -375,7 +375,12 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, off_t *retpos, goto leave; } - if( do_skip || !pkttype || (reqtype && pkttype != reqtype) ) { + if( do_skip + || !pkttype + || (onlykeypkts && pkttype != PKT_PUBLIC_SUBKEY + && pkttype != PKT_PUBLIC_KEY + && pkttype != PKT_SECRET_SUBKEY + && pkttype != PKT_SECRET_KEY ) ) { skip_rest(inp, pktlen); *skip = 1; rc = 0; @@ -856,6 +861,11 @@ dump_sig_subpkt( int hashed, int type, int critical, printf("%02X", buffer[i] ); } break; + case SIGSUBPKT_FEATURES: + fputs ( "features:", stdout ); + for( i=0; i < length; i++ ) + printf(" %d", buffer[i] ); + break; case SIGSUBPKT_PRIV_VERIFY_CACHE: p = "verification cache"; break; @@ -903,6 +913,7 @@ parse_one_sig_subpkt( const byte *buffer, size_t n, int type ) case SIGSUBPKT_PREF_HASH: case SIGSUBPKT_PREF_COMPR: case SIGSUBPKT_POLICY: + case SIGSUBPKT_FEATURES: return 0; case SIGSUBPKT_PRIMARY_UID: if ( n != 1 ) @@ -944,6 +955,7 @@ can_handle_critical( const byte *buffer, size_t n, int type ) case SIGSUBPKT_PREF_COMPR: case SIGSUBPKT_KEY_FLAGS: case SIGSUBPKT_PRIMARY_UID: + case SIGSUBPKT_FEATURES: return 1; case SIGSUBPKT_POLICY: /* Is it enough to show the policy? */ diff --git a/g10/pkclist.c b/g10/pkclist.c index 61b2c8000..e4e0f38a3 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -1146,4 +1146,29 @@ select_algo_from_prefs( PK_LIST pk_list, int preftype ) return i; } +/* + * Select the MDC flag from the pk_list. We can only use MDC if all recipients + * support this feature + */ +int +select_mdc_from_pklist (PK_LIST pk_list) +{ + PK_LIST pkr; + + if( !pk_list ) + return 0; + + for (pkr = pk_list; pkr; pkr = pkr->next) { + int mdc; + + if (pkr->pk->user_id) /* selected by user ID */ + mdc = pkr->pk->user_id->mdc_feature; + else + mdc = pkr->pk->mdc_feature; + if (!mdc) + return 0; /* at least on recipeint does not support it */ + } + return 1; /* can be used */ +} + diff --git a/g10/ringedit.c b/g10/ringedit.c index b2193e7e2..5e610e583 100644 --- a/g10/ringedit.c +++ b/g10/ringedit.c @@ -84,11 +84,12 @@ static RESTBL resource_table[MAX_RESOURCES]; static int default_public_resource; static int default_secret_resource; -static int search( PACKET *pkt, KBPOS *kbpos, int secret ); +static int search (PKT_public_key *req_pk, u32 *req_keyid, + KBPOS *kbpos, int secret); -static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf, - const char *fname ); +static int keyring_search (PKT_public_key *req_pk, u32 *req_keyid, + KBPOS *kbpos, IOBUF iobuf, const char *fname ); static int keyring_read( KBPOS *kbpos, KBNODE *ret_root ); static int keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs ); static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root ); @@ -97,7 +98,7 @@ static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root ); static int do_gdbm_store( KBPOS *kbpos, KBNODE root, int update ); static int do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos, const byte *fpr, int fprlen ); -static int do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid ); +/*static int do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid );*/ static int do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root ); static int do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root ); #endif @@ -464,26 +465,31 @@ get_writable_keyblock_file( int secret ) * Returns: 0 if found, -1 if not found or an errorcode. */ static int -search( PACKET *pkt, KBPOS *kbpos, int secret ) +search (PKT_public_key *req_pk, u32 *req_keyid, KBPOS *kbpos, int secret) { int i, rc, last_rc=-1; for(i=0; i < MAX_RESOURCES; i++ ) { if( resource_table[i].used && !resource_table[i].secret == !secret ) { switch( resource_table[i].rt ) { - case rt_RING: - rc = keyring_search( pkt, kbpos, resource_table[i].iobuf, - resource_table[i].fname ); - break; - #ifdef HAVE_LIBGDBM + case rt_RING: + rc = keyring_search (req_pk, req_keyid, + kbpos, resource_table[i].iobuf, + resource_table[i].fname ); + + break; + #ifdef HAVE_LIBGDBM case rt_GDBM: { - PKT_public_key *req_pk = pkt->pkt.public_key; byte fpr[20]; size_t fprlen; - - fingerprint_from_pk( req_pk, fpr, &fprlen ); - rc = do_gdbm_locate( resource_table[i].dbf, - kbpos, fpr, fprlen ); + + if (!req_pk) + rc = G10ERR_UNSUPPORTED; + else { + fingerprint_from_pk( req_pk, fpr, &fprlen ); + rc = do_gdbm_locate( resource_table[i].dbf, + kbpos, fpr, fprlen ); + } } break; #endif @@ -514,20 +520,12 @@ search( PACKET *pkt, KBPOS *kbpos, int secret ) int find_keyblock_byname( KBPOS *kbpos, const char *username ) { - PACKET pkt; PKT_public_key *pk = m_alloc_clear( sizeof *pk ); int rc; rc = get_pubkey_byname( NULL, pk, username, NULL ); - if( rc ) { - free_public_key(pk); - return rc; - } - - init_packet( &pkt ); - pkt.pkttype = PKT_PUBLIC_KEY; - pkt.pkt.public_key = pk; - rc = search( &pkt, kbpos, 0 ); + if (!rc) + rc = search( pk, NULL, kbpos, 0 ); free_public_key(pk); return rc; } @@ -540,30 +538,22 @@ find_keyblock_byname( KBPOS *kbpos, const char *username ) int find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk ) { - PACKET pkt; int rc; - init_packet( &pkt ); - pkt.pkttype = PKT_PUBLIC_KEY; - pkt.pkt.public_key = pk; - rc = search( &pkt, kbpos, 0 ); + rc = search( pk, NULL, kbpos, 0 ); return rc; } /**************** - * Combined function to search for a key and get the position - * of the keyblock. + * Combined function to search for a secret key and get the position + * of the keyblock. */ int -find_keyblock_bysk( KBPOS *kbpos, PKT_secret_key *sk ) +find_secret_keyblock_bypk (KBPOS *kbpos, PKT_public_key *pk) { - PACKET pkt; int rc; - init_packet( &pkt ); - pkt.pkttype = PKT_SECRET_KEY; - pkt.pkt.secret_key = sk; - rc = search( &pkt, kbpos, 0 ); + rc = search (pk, NULL, kbpos, 1); return rc; } @@ -575,113 +565,27 @@ find_keyblock_bysk( KBPOS *kbpos, PKT_secret_key *sk ) int find_secret_keyblock_byname( KBPOS *kbpos, const char *username ) { - PACKET pkt; - PKT_secret_key *sk = m_alloc_clear( sizeof *sk ); + PKT_public_key *pk = m_alloc_clear( sizeof *pk ); int rc; - rc = get_seckey_byname( sk, username, 0 ); - if( rc ) { - free_secret_key(sk); - return rc; - } - - init_packet( &pkt ); - pkt.pkttype = PKT_SECRET_KEY; - pkt.pkt.secret_key = sk; - rc = search( &pkt, kbpos, 1 ); - free_secret_key(sk); + rc = get_pubkey_byname( NULL, pk, username, NULL ); + if (!rc) + rc = search (pk, NULL, kbpos, 1); + free_public_key (pk); return rc; } - -/**************** - * Locate a keyblock in a database which is capable of direct access - * Put all information into KBPOS, which can be later be to access this - * key block. - * This function looks into all registered keyblock sources. - * - * Returns: 0 if found, - * -1 if not found - * G10ERR_UNSUPPORTED if no resource is able to handle this - * or another errorcode. +/* + * This function locates the secret keyblock without doing a public + * keyring check fist. It is useful in certain situations and much + * faster than the generic solution. */ int -locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr, int fprlen, int secret ) +find_secret_keyblock_direct (KBPOS *kbpos, u32 *keyid) { - RESTBL *rentry; - int i, rc, any=0, last_rc=-1; - - - for(i=0, rentry = resource_table; i < MAX_RESOURCES; i++, rentry++ ) { - if( rentry->used && !rentry->secret == !secret ) { - kbpos->rt = rentry->rt; - switch( rentry->rt ) { - #ifdef HAVE_LIBGDBM - case rt_GDBM: - any = 1; - rc = do_gdbm_locate( rentry->dbf, kbpos, fpr, fprlen ); - break; - #endif - default: - rc = G10ERR_UNSUPPORTED; - break; - } - - if( !rc ) { - kbpos->resno = i; - kbpos->fp = NULL; - return 0; - } - else if( rc != -1 && rc != G10ERR_UNSUPPORTED ) { - log_error("error searching resource %d: %s\n", - i, g10_errstr(rc)); - last_rc = rc; - } - } - } - - return (last_rc == -1 && !any)? G10ERR_UNSUPPORTED : last_rc; -} - - -int -locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid, int shortkid, int secret ) -{ - RESTBL *rentry; - int i, rc, any=0, last_rc=-1; - - if( shortkid ) - return G10ERR_UNSUPPORTED; - - for(i=0, rentry = resource_table; i < MAX_RESOURCES; i++, rentry++ ) { - if( rentry->used && !rentry->secret == !secret ) { - kbpos->rt = rentry->rt; - switch( rentry->rt ) { - #ifdef HAVE_LIBGDBM - case rt_GDBM: - any = 1; - rc = do_gdbm_locate_by_keyid( rentry->dbf, kbpos, keyid ); - break; - #endif - default: - rc = G10ERR_UNSUPPORTED; - break; - } - - if( !rc ) { - kbpos->resno = i; - kbpos->fp = NULL; - return 0; - } - else if( rc != -1 && rc != G10ERR_UNSUPPORTED ) { - log_error("error searching resource %d: %s\n", - i, g10_errstr(rc)); - last_rc = rc; - } - } - } - - return (last_rc == -1 && !any)? G10ERR_UNSUPPORTED : last_rc; + int rc; + rc = search (NULL, keyid, kbpos, 1); + return rc; } @@ -1065,21 +969,16 @@ scan_user_file_read( SCAN_USER_HANDLE hd, byte *fpr ) ****************************************************************/ static int -cmp_seckey( PKT_secret_key *req_sk, PKT_secret_key *sk ) +cmp_seckey( PKT_public_key *req_pk, PKT_secret_key *sk ) { int n,i; - assert( req_sk->pubkey_algo == sk->pubkey_algo ); + if (req_pk->pubkey_algo != sk->pubkey_algo) + return -1; - n = pubkey_get_nskey( req_sk->pubkey_algo ); - for(i=0; i < n; i++ ) { - /* Note: becuase v4 protected keys have nothing in the - * mpis except for the first one, we skip all NULL MPIs. - * This might not be always correct in cases where the both - * keys do not match in their secret parts but we can ignore that - * because the need for this function is quite ugly. */ - if( req_sk->skey[1] && sk->skey[i] - && mpi_cmp( req_sk->skey[i], sk->skey[i] ) ) + n = pubkey_get_npkey (req_pk->pubkey_algo); + for (i=0; i < n; i++ ) { + if( mpi_cmp (req_pk->pkey[i], sk->skey[i]) ) return -1; } return 0; @@ -1104,16 +1003,15 @@ cmp_pubkey( PKT_public_key *req_pk, PKT_public_key *pk ) * search one keyring, return 0 if found, -1 if not found or an errorcode. */ static int -keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname ) +keyring_search( PKT_public_key *req_pk, u32 *req_keyid, + KBPOS *kbpos, IOBUF iobuf, const char *fname ) { int rc; PACKET pkt; int save_mode; - off_t offset; - int pkttype = req->pkttype; - PKT_public_key *req_pk = req->pkt.public_key; - PKT_secret_key *req_sk = req->pkt.secret_key; + off_t offset, main_offset; + assert (!!req_pk ^ !!req_keyid); /* exactly one must be specified */ init_packet(&pkt); save_mode = set_packet_list_mode(0); kbpos->rt = rt_RING; @@ -1135,29 +1033,57 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname ) } #endif - while( !(rc=search_packet(iobuf, &pkt, pkttype, &offset)) ) { - if( pkt.pkttype == PKT_SECRET_KEY ) { + main_offset = 0; + while ( !(rc=search_packet(iobuf, &pkt, &offset)) ) { + if (pkt.pkttype == PKT_PUBLIC_KEY || pkt.pkttype == PKT_SECRET_KEY) { + main_offset = offset; + } + + if (pkt.pkttype == PKT_SECRET_KEY || pkt.pkttype == PKT_SECRET_SUBKEY) { PKT_secret_key *sk = pkt.pkt.secret_key; - if( req_sk->timestamp == sk->timestamp - && req_sk->pubkey_algo == sk->pubkey_algo - && !cmp_seckey( req_sk, sk) ) - break; /* found */ + if (req_keyid) { + u32 aki[2]; + + keyid_from_sk (sk, aki); + if (aki[0] == req_keyid[0] && aki[1] == req_keyid[1]) + break; /* found */ + } + else { + /* We can't compare the timestamps here because they + might differ */ + if( !cmp_seckey (req_pk, sk) ) + break; /* found */ + } } - else if( pkt.pkttype == PKT_PUBLIC_KEY ) { + else if (pkt.pkttype == PKT_PUBLIC_KEY + || pkt.pkttype == PKT_PUBLIC_SUBKEY) { PKT_public_key *pk = pkt.pkt.public_key; - if( req_pk->timestamp == pk->timestamp - && req_pk->pubkey_algo == pk->pubkey_algo - && !cmp_pubkey( req_pk, pk ) ) - break; /* found */ + if (req_keyid) { + u32 aki[2]; + + keyid_from_pk (pk, aki); + if (aki[0] == req_keyid[0] && aki[1] == req_keyid[1]) + break; /* found */ + } + else { + if( req_pk->timestamp == pk->timestamp + && req_pk->pubkey_algo == pk->pubkey_algo + && !cmp_pubkey( req_pk, pk ) ) + break; /* found */ + } } else BUG(); free_packet(&pkt); } if( !rc ) { - kbpos->offset = offset; + if (pkt.pkttype == PKT_SECRET_SUBKEY + || pkt.pkttype == PKT_PUBLIC_SUBKEY) + kbpos->offset = main_offset; + else + kbpos->offset = offset; kbpos->valid = 1; } @@ -1710,6 +1636,7 @@ do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos, const byte *fpr, int fprlen ) * locate by keyid. * FIXME: we must have a way to enumerate thru the list opf fingerprints */ +#if 0 /* not used */ static int do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid ) { @@ -1752,7 +1679,7 @@ do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid ) free( content.dptr ); /* can't use m_free() here */ return rc; } - +#endif /* not used */ static int diff --git a/g10/sig-check.c b/g10/sig-check.c index e517e6478..fe63a1381 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -551,7 +551,8 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, } else { if (!opt.quiet) - log_info ("no subkey for subkey revocation packet\n"); + log_info ("key %08lX: no subkey for subkey revocation packet\n", + (ulong)keyid_from_pk (pk, NULL)); rc = G10ERR_SIG_CLASS; } } @@ -574,7 +575,9 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, md_close(md); } else { - log_info ("no subkey for key signature packet\n"); + if (!opt.quiet) + log_info ("key %08lX: no subkey for subkey binding packet\n", + (ulong)keyid_from_pk (pk, NULL)); rc = G10ERR_SIG_CLASS; } } @@ -607,8 +610,10 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, md_close(md); } else { - log_info ("no user ID for key signature packet of class %02x\n", - sig->sig_class ); + if (!opt.quiet) + log_info ("key %08lX: no user ID for key signature packet " + "of class %02x\n", + (ulong)keyid_from_pk (pk, NULL), sig->sig_class ); rc = G10ERR_SIG_CLASS; } } diff --git a/include/ChangeLog b/include/ChangeLog index 47323772f..a591c9136 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2001-08-30 Werner Koch + + * cipher.h (DEK): Added use_mdc. + 2001-08-24 Werner Koch * cipher.h (md_write): Made buf arg const. diff --git a/include/cipher.h b/include/cipher.h index 53279f958..3c1677cbf 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -64,6 +64,7 @@ typedef struct { int algo; int keylen; int algo_info_printed; + int use_mdc; byte key[32]; /* this is the largest used keylen (256 bit) */ } DEK;