From dca608ab9dee64c7397d8c50fafb2b48df2e2eb8 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 16 Mar 2000 15:16:15 +0000 Subject: [PATCH] See ChangeLog: Thu Mar 16 16:20:23 CET 2000 Werner Koch --- NEWS | 2 ++ THANKS | 1 + TODO | 6 +++- g10/ChangeLog | 18 ++++++++++++ g10/getkey.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++-- g10/keygen.c | 5 +++- g10/keylist.c | 22 +++++++++------ g10/mainproc.c | 5 ++++ g10/pubkey-enc.c | 10 ++++++- 9 files changed, 127 insertions(+), 14 deletions(-) diff --git a/NEWS b/NEWS index ac2723890..9429a9797 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ Noteworthy changes in the current test release ---------------------------------------------- + * Fixed expiration handling of encryption keys. + * Add an experimental feature to do unattended key generation. * The user is now asked for the reason of revocation as required diff --git a/THANKS b/THANKS index 087be4380..bdd2f9614 100644 --- a/THANKS +++ b/THANKS @@ -35,6 +35,7 @@ Felix von Leitner leitner@amdiv.de Frank Donahoe fdonahoe@wilkes1.wilkes.edu Frank Heckenbach heckenb@mi.uni-erlangen.de Frank Stajano frank.stajano@cl.cam.ac.uk +Frank Tobin ftobin@uiuc.edu Gaël Quéri gqueri@mail.dotcom.fr Greg Louis glouis@dynamicro.on.ca Greg Troxel gdt@ir.bbn.com diff --git a/TODO b/TODO index 72cc36438..1498ef93e 100644 --- a/TODO +++ b/TODO @@ -2,9 +2,13 @@ * Print the reason for revocation at certain places. * at least an option to prefer DSA keys over RSA when selecting the key to - use. Depending on creatin time would be nice too. I thing this is + use. Depending on creation time would be nice too. I thing this is already done for the subkeys. + * Rework the whole key selection stuff: Compile a list of valid + candidates for a keyblock first and the select one from it. + The current code is too ugly (getkey.c). + Scheduled for 1.1 ----------------- * With option -i prompt before adding a key to the keyring and show some diff --git a/g10/ChangeLog b/g10/ChangeLog index 56e8f7007..1c7d94043 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,21 @@ +Thu Mar 16 16:20:23 CET 2000 Werner Koch + + * keylist.c (print_key_data): Handle a NULL pk gracefully. + + * getkey.c (merge_one_pk_and_selfsig): Fixed silly code for + getting the primary keys keyID but kept using the one from the + subkey. + * pubkey-enc.c (get_it): Print a note for expired subkeys. + + * getkey.c (has_expired): New. + (subkeys_expiretime): New. + (finish_lookup): Check for expired subkeys needed for encryption. + (merge_keys_and_selfsig): Fixed expiration date merging for subkeys. + + * keylist.c (list_keyblock): Print expiration time for "sub". + (list_one): Add missing merging for public keys. + * mainproc.c (list_node): Ditto. + 2000-03-14 13:49:38 Werner Koch (wk@habibti.openit.de) * keygen.c (keyedit_menu): Do not allow to use certain commands diff --git a/g10/getkey.c b/g10/getkey.c index 2a6c76aa3..1dae1a3cd 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -154,6 +154,7 @@ static int uid_cache_entries; /* number of entries in uid cache */ static char* prepare_word_match( const byte *name ); static int lookup_pk( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_kb ); static int lookup_sk( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_kb ); +static u32 subkeys_expiretime( KBNODE node, u32 *mainkid ); #if 0 @@ -1150,7 +1151,7 @@ merge_one_pk_and_selfsig( KBNODE keyblock, KBNODE knode, k = find_kbnode( keyblock, PKT_PUBLIC_KEY ); if( !k ) BUG(); /* keyblock without primary key!!! */ - keyid_from_pk( knode->pkt->pkt.public_key, kid ); + keyid_from_pk( k->pkt->pkt.public_key, kid ); } else keyid_from_pk( pk, kid ); @@ -1208,6 +1209,10 @@ merge_keys_and_selfsig( KBNODE keyblock ) pk = NULL; /* not needed for old keys */ else if( k->pkt->pkttype == PKT_PUBLIC_KEY ) keyid_from_pk( pk, kid ); + else if( !pk->expiredate ) { /* and subkey */ + /* insert the expiration date here */ + pk->expiredate = subkeys_expiretime( k, kid ); + } sigdate = 0; } else if( k->pkt->pkttype == PKT_SECRET_KEY @@ -1222,8 +1227,11 @@ merge_keys_and_selfsig( KBNODE keyblock ) else if( (pk || sk ) && k->pkt->pkttype == PKT_SIGNATURE && (sig=k->pkt->pkt.signature)->sig_class >= 0x10 && sig->sig_class <= 0x30 && sig->version > 3 + && !(sig->sig_class == 0x18 || sig->sig_class == 0x28) && sig->keyid[0] == kid[0] && sig->keyid[1] == kid[1] ) { /* okay this is a self-signature which can be used. + * This is not used for subkey binding signature, becuase this + * is done above. * FIXME: We should only use this if the signature is valid * but this is time consuming - we must provide another * way to handle this @@ -1521,6 +1529,56 @@ find_by_fpr_sk( KBNODE keyblock, PKT_secret_key *sk, } +/**************** + * Return the expiretime of a subkey. + */ +static u32 +subkeys_expiretime( KBNODE node, u32 *mainkid ) +{ + KBNODE k; + PKT_signature *sig; + u32 expires = 0, sigdate = 0; + + assert( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ); + for(k=node->next; k; k = k->next ) { + if( k->pkt->pkttype == PKT_SIGNATURE + && (sig=k->pkt->pkt.signature)->sig_class == 0x18 + && sig->keyid[0] == mainkid[0] + && sig->keyid[1] == mainkid[1] + && sig->version > 3 + && sig->timestamp > sigdate ) { + /* okay this is a key-binding which can be used. + * We use the latest self-signature. + * FIXME: We should only use this if the binding signature is valid + * but this is time consuming - we must provide another + * way to handle this + */ + const byte *p; + u32 ed; + + p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL ); + ed = p? node->pkt->pkt.public_key->timestamp + buffer_to_u32(p):0; + sigdate = sig->timestamp; + expires = ed; + } + else if( k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + break; /* stop at the next subkey */ + } + + return expires; +} + + +/**************** + * Check whether the subkey has expired. Node must point to the subkey + */ +static int +has_expired( KBNODE node, u32 *mainkid, u32 cur_time ) +{ + u32 expires = subkeys_expiretime( node, mainkid ); + return expires && expires <= cur_time; +} + static void finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash, int use_namehash, int primary ) @@ -1539,6 +1597,10 @@ finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash, pk->pubkey_usage ) == G10ERR_WR_PUBKEY_ALGO ) { /* if the usage is not correct, try to use a subkey */ KBNODE save_k = k; + u32 mainkid[2]; + u32 cur_time = make_timestamp(); + + keyid_from_pk( keyblock->pkt->pkt.public_key, mainkid ); k = NULL; /* kludge for pgp 5: which doesn't accept type 20: @@ -1550,7 +1612,8 @@ finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash, == PUBKEY_ALGO_ELGAMAL_E && !check_pubkey_algo2( k->pkt->pkt.public_key->pubkey_algo, - pk->pubkey_usage ) ) + pk->pubkey_usage ) + && !has_expired(k, mainkid, cur_time) ) break; } } @@ -1560,7 +1623,10 @@ finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash, if( k->pkt->pkttype == PKT_PUBLIC_SUBKEY && !check_pubkey_algo2( k->pkt->pkt.public_key->pubkey_algo, - pk->pubkey_usage ) ) + pk->pubkey_usage ) + && ( pk->pubkey_usage != PUBKEY_USAGE_ENC + || !has_expired( k, mainkid, cur_time ) ) + ) break; } } diff --git a/g10/keygen.c b/g10/keygen.c index ead51cbc2..f65d92b2f 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -274,11 +274,14 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek, sk = m_alloc_clear( sizeof *sk ); pk = m_alloc_clear( sizeof *pk ); - sk->timestamp = pk->timestamp = make_timestamp(); + sk->timestamp = pk->timestamp = 948668400; +#warning FIXME: make_timestamp(); sk->version = pk->version = 4; if( expireval ) { sk->expiredate = pk->expiredate = sk->timestamp + expireval; } + sk->expiredate = pk->expiredate = 949705200; +#warning remove the above line sk->pubkey_algo = pk->pubkey_algo = algo; pk->pkey[0] = mpi_copy( skey[0] ); pk->pkey[1] = mpi_copy( skey[1] ); diff --git a/g10/keylist.c b/g10/keylist.c index dba2dcc42..ff44408b8 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -135,6 +135,7 @@ list_one( STRLIST names, int secret ) return; } do { + merge_keys_and_selfsig( keyblock ); list_keyblock( keyblock, 0 ); release_kbnode( keyblock ); } while( !get_pubkey_next( ctx, NULL, &keyblock ) ); @@ -145,7 +146,7 @@ list_one( STRLIST names, int secret ) static void print_key_data( PKT_public_key *pk, u32 *keyid ) { - int n = pubkey_get_npkey( pk->pubkey_algo ); + int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0; int i; for(i=0; i < n; i++ ) { @@ -308,11 +309,16 @@ list_keyblock( KBNODE keyblock, int secret ) putchar(':'); putchar('\n'); } - else - printf("sub %4u%c/%08lX %s\n", nbits_from_pk( pk2 ), + else { + printf("sub %4u%c/%08lX %s", nbits_from_pk( pk2 ), pubkey_letter( pk2->pubkey_algo ), (ulong)keyid2[1], datestr_from_pk( pk2 ) ); + if( pk2->expiredate ) { + printf(_(" [expires: %s]"), expirestr_from_pk( pk2 ) ); + } + putchar('\n'); + } if( opt.fingerprint > 1 ) fingerprint( pk2, NULL ); if( opt.with_key_data ) @@ -351,7 +357,7 @@ list_keyblock( KBNODE keyblock, int secret ) else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) { PKT_signature *sig = node->pkt->pkt.signature; int sigrc; - char *sigstr; + char *sigstr; if( !any ) { /* no user id, (maybe a revocation follows)*/ if( sig->sig_class == 0x20 ) @@ -369,11 +375,11 @@ list_keyblock( KBNODE keyblock, int secret ) if( sig->sig_class == 0x20 || sig->sig_class == 0x28 || sig->sig_class == 0x30 ) - sigstr = "rev"; + sigstr = "rev"; else if( (sig->sig_class&~3) == 0x10 ) - sigstr = "sig"; + sigstr = "sig"; else if( sig->sig_class == 0x18 ) - sigstr = "sig"; + sigstr = "sig"; else { if( opt.with_colons ) printf("sig::::::::::%02x:\n",sig->sig_class ); @@ -396,7 +402,7 @@ list_keyblock( KBNODE keyblock, int secret ) rc = 0; sigrc = ' '; } - fputs( sigstr, stdout ); + fputs( sigstr, stdout ); if( opt.with_colons ) { putchar(':'); if( sigrc != ' ' ) diff --git a/g10/mainproc.c b/g10/mainproc.c index 21cad8262..99bf05ab3 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -689,6 +689,7 @@ list_node( CTX c, KBNODE node ) pubkey_letter( pk->pubkey_algo ), (ulong)keyid_from_pk( pk, NULL ), datestr_from_pk( pk ) ); + if( mainkey ) { /* and now list all userids with their signatures */ for( node = node->next; node; node = node->next ) { @@ -731,6 +732,10 @@ list_node( CTX c, KBNODE node ) } } } + else if( pk->expiredate ) { /* of subkey */ + printf(_(" [expires: %s]"), expirestr_from_pk( pk ) ); + } + if( !any ) putchar('\n'); if( !mainkey && opt.fingerprint > 1 ) diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 77bdc4b19..c3241eb21 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -176,7 +176,7 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid ) } if( DBG_CIPHER ) log_hexdump("DEK is:", dek->key, dek->keylen ); - /* check that the algo is in the preferences */ + /* check that the algo is in the preferences and whether it has expired */ { PKT_public_key *pk = m_alloc_clear( sizeof *pk ); if( (rc = get_pubkey( pk, keyid )) ) @@ -195,10 +195,18 @@ get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid ) "NOTE: cipher algorithm %d not found in preferences\n"), dek->algo ); } + + + if( !rc && pk->expiredate && pk->expiredate <= make_timestamp() ) { + log_info(_("NOTE: secret key %08lX expired at %s\n"), + (ulong)keyid[1], asctimestamp( pk->expiredate) ); + } + free_public_key( pk ); rc = 0; } + leave: mpi_free(plain_dek); m_free(frame);