From 1dbd67b96aec706b0cbb66840635becead8b3e44 Mon Sep 17 00:00:00 2001 From: David Shaw Date: Tue, 22 Jan 2002 20:39:10 +0000 Subject: [PATCH] Some compatibility polish for PGP2. Add a fake IDEA preference for v3 keys (this is in the RFC), so that they can be (sometimes) used along OpenPGP keys. Do not force using IDEA on an OpenPGP key, as this may violate its prefs. Also, revise the help text for the sig class explanation. --- g10/ChangeLog | 36 ++++++++++++++++++++++++++++++++++++ g10/encode.c | 21 ++++++++++++++++++--- g10/g10.c | 6 +++--- g10/getkey.c | 8 ++++++++ g10/helptext.c | 13 ++++++++----- g10/keygen.c | 11 +++++++++-- g10/packet.h | 1 + g10/pkclist.c | 11 +++++++++-- g10/sign.c | 4 ++-- 9 files changed, 94 insertions(+), 17 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 706f6b72f..de8d0d588 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,39 @@ +2002-01-22 David Shaw + + * packet.h, getkey.c (merge_selfsigs_main), pkclist.c + (select_algo_from_prefs): Implement the fake IDEA preference as + per RFC2440:12.1. This doesn't mean that IDEA will be used (the + plugin may not be present), but it does mean that a v3 key with a + v3 selfsig has an implicit IDEA preference instead of 3DES. v3 + keys with v4 selfsigs use preferences as normal. + + * encode.c (encode_crypt): if select_algo_from_prefs fails, this + means that we could not find a cipher that both keys like. Since + all v4 keys have an implicit 3DES preference, this means there is + a v3 key with a v3 selfsig in the list. Use 3DES in this case as + it is the safest option (we know the v4 key can handle it, and + we'll just hope the v3 key is being used in an implementation that + can handle it). If --pgp2 is on, warn the user what we're doing + since it'll probably break PGP2 compatibility. + + * g10.c (main): Do not force using IDEA for encrypted files in + --pgp2 mode - let the fake IDEA preference choose this for us for + better compatibility when encrypting to multiple keys, only some + of which are v3. + + * keygen.c (keygen_set_std_prefs): Put 3DES on the end of the + default cipher pref list (RFC2440: "...it is good form to place it + there explicitly."). If the user has the IDEA plugin installed, + put a preference for IDEA *after* 3DES to effectively disable its + use for everything except encrypting along with v3 keys. + + * encode.c, g10.c, sign.c: Change the PGP2 warning line from + "... will not be usable ..." to "... may not be usable ..." as the + user could be using one of the enhanced PGP2 variations. + + * helptext.c: Revise the sign_uid.class help text as suggested by + Stefan. + 2002-01-20 Werner Koch * passphrase.c (passphrase_to_dek): Add tryagain_text arg to be diff --git a/g10/encode.c b/g10/encode.c index b5a4c0678..a3ef51e34 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -284,7 +284,7 @@ encode_crypt( const char *filename, STRLIST remusr ) { log_info(_("you can only encrypt to RSA keys of 2048 bits or " "less in --pgp2 mode\n")); - log_info(_("this message will not be usable by PGP 2.x\n")); + log_info(_("this message may not be usable by PGP 2.x\n")); opt.pgp2=0; break; } @@ -333,8 +333,23 @@ encode_crypt( const char *filename, STRLIST remusr ) cfx.dek = m_alloc_secure_clear (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; + /* The only way select_algo_from_prefs can fail here is when + mixing v3 and v4 keys, as v4 keys have an implicit + preference entry for 3DES, and the pk_list cannot be empty. + In this case, use 3DES anyway as it's the safest choice - + perhaps the v3 key is being used in an OpenPGP + implementation and we know that the implementation behind + any v4 key can handle 3DES. */ + if( cfx.dek->algo == -1 ) { + cfx.dek->algo = CIPHER_ALGO_3DES; + + if( opt.pgp2 ) { + log_info(_("unable to use the IDEA cipher for all of the keys " + "you are encrypting to.\n")); + log_info(_("this message may not be usable by PGP 2.x\n")); + opt.pgp2=0; + } + } } else cfx.dek->algo = opt.def_cipher_algo; diff --git a/g10/g10.c b/g10/g10.c index 60997f38b..d2c010db3 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -1303,7 +1303,7 @@ main( int argc, char **argv ) "while in --pgp2 mode\n")); unusable=1; } - else if(cmd==aSignEncr) + else if(cmd==aSignEncr || cmd==aSignSym) { log_info(_("you can't sign and encrypt at the " "same time while in --pgp2 mode\n")); @@ -1329,7 +1329,7 @@ main( int argc, char **argv ) idea_cipher_warn(1); unusable=1; } - else + else if(cmd==aSym) { m_free(def_cipher_string); def_cipher_string = m_strdup("idea"); @@ -1338,7 +1338,7 @@ main( int argc, char **argv ) if(unusable) { - log_info(_("this message will not be usable by PGP 2.x\n")); + log_info(_("this message may not be usable by PGP 2.x\n")); opt.pgp2=0; } else diff --git a/g10/getkey.c b/g10/getkey.c index 298c117ae..3821264c9 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -1190,6 +1190,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) u32 keytimestamp = 0; u32 key_expire = 0; int key_expire_seen = 0; + byte sigversion = 0; *r_revoked = 0; if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY ) @@ -1242,6 +1243,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) else { sigdate = sig->timestamp; signode = k; + sigversion = sig->version; } } } @@ -1316,6 +1318,8 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) else { sigdate = sig->timestamp; signode = k; + if( sig->version > sigversion ) + sigversion = sig->version; } } } @@ -1328,6 +1332,10 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) if ( sigdate > uiddate ) uiddate = sigdate; + /* Record the highest selfsigversion so we know if this is a v3 + key through and through, or a v3 key with a v4 selfsig, which + means we can trust the preferences (if any). */ + pk->selfsigversion=sigversion; /* Now that we had a look at all user IDs we can now get some information * from those user IDs. diff --git a/g10/helptext.c b/g10/helptext.c index dcb164d30..973a905c6 100644 --- a/g10/helptext.c +++ b/g10/helptext.c @@ -165,9 +165,14 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = { " mean that you verified the key fingerprint and checked the user ID on the\n" " key against a photo ID.\n\n" "\"3\" means you did extensive verification of the key. For example, this could\n" -" mean that you verified the key fingerprint and checked the user ID on the\n" -" key against a photo ID, and also verified the email address on the key\n" -" belongs to the key owner.\n\n" +" mean that you verified the key fingerprint with the owner of the key in\n" +" person, and that you checked, by means of a hard to forge document with a\n" +" photo ID (such as a passport) that the name of the key owner matches the\n" +" name in the user ID on the key, and finally that you verified (by exchange\n" +" of email) that the email address on the key belongs to the key owner.\n\n" +"Note that the examples given above for levels 2 and 3 are *only* examples.\n" +"In the end, it is up to you to decide just what \"casual\" and \"extensive\"\n" +"mean to you when you sign other keys.\n\n" "If you don't know what the right answer is, answer \"0\"." )}, @@ -301,5 +306,3 @@ display_online_help( const char *keyword ) } tty_printf("\n"); } - - diff --git a/g10/keygen.c b/g10/keygen.c index 4625c8435..3d0dbb485 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -217,8 +217,15 @@ keygen_set_std_prefs (const char *string) const char *s, *s2; int rc = 0; - if (!string || !ascii_strcasecmp (string, "default")) - string = "S7 S10 S3 S4 H3 H2 Z2 Z1"; + if (!string || !ascii_strcasecmp (string, "default")) { + if ( !check_cipher_algo(CIPHER_ALGO_IDEA) ) + string = "S7 S10 S3 S4 S2 S1 H3 H2 Z2 Z1"; + else + string = "S7 S10 S3 S4 S2 H3 H2 Z2 Z1"; + + /* If we have it, IDEA goes *after* 3DES so it won't be used + unless we're encrypting along with a V3 key. */ + } else if (!ascii_strcasecmp (string, "none")) string = ""; diff --git a/g10/packet.h b/g10/packet.h index 110ed5e82..e55ca336a 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -182,6 +182,7 @@ typedef struct { u32 expiredate; /* expires at this date or 0 if not at all */ byte hdrbytes; /* number of header bytes */ byte version; + byte selfsigversion; /* highest version of all of the self-sigs */ byte pubkey_algo; /* algorithm used for public key scheme */ byte pubkey_usage; /* for now only used to pass it to getkey() */ byte req_usage; /* hack to pass a request to getkey() */ diff --git a/g10/pkclist.c b/g10/pkclist.c index 4a4cf633b..4c1ac50a2 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -966,8 +966,15 @@ select_algo_from_prefs( PK_LIST pk_list, int preftype ) u32 mask[8]; memset( mask, 0, 8 * sizeof *mask ); - if( preftype == PREFTYPE_SYM ) - mask[0] |= (1<<2); /* 3DES is implicitly there */ + if( preftype == PREFTYPE_SYM ) { + if( pkr->pk->version < 4 && pkr->pk->selfsigversion < 4 ) + mask[0] |= (1<<1); /* IDEA is implicitly there for v3 keys + with v3 selfsigs (rfc2440:12.1). + This doesn't mean it's actually + available, of course. */ + else + mask[0] |= (1<<2); /* 3DES is implicitly there for everyone else */ + } if (pkr->pk->user_id) /* selected by user ID */ prefs = pkr->pk->user_id->prefs; diff --git a/g10/sign.c b/g10/sign.c index 59c94a37d..7f79e8d90 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -577,7 +577,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, { log_info(_("you can only sign with PGP 2.x style keys " "while in --pgp2 mode\n")); - log_info(_("this message will not be usable by PGP 2.x\n")); + log_info(_("this message may not be usable by PGP 2.x\n")); opt.pgp2=0; } @@ -755,7 +755,7 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) { log_info(_("you can only clearsign with PGP 2.x style keys " "while in --pgp2 mode\n")); - log_info(_("this message will not be usable by PGP 2.x\n")); + log_info(_("this message may not be usable by PGP 2.x\n")); opt.pgp2=0; }