diff options
Diffstat (limited to 'g10/keyedit.c')
-rw-r--r-- | g10/keyedit.c | 62 |
1 files changed, 57 insertions, 5 deletions
diff --git a/g10/keyedit.c b/g10/keyedit.c index a475ed813..271e26d46 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -191,8 +191,10 @@ remove_keysigs( KBNODE keyblock, u32 *keyid, int all ) else if( node->flag & 4 ) tty_printf("The signature could not be checked!\n"); - if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) + if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) { + tty_printf("Skipped self-signature\n"); continue; /* do not remove self-signatures */ + } answer = tty_get("\nRemove this signature? "); tty_kill_prompt(); @@ -348,8 +350,7 @@ sign_key( const char *username, STRLIST locusr ) rc = make_keysig_packet( &sig, pkc, node->pkt->pkt.user_id, skc_rover->skc, - 0x10, - DIGEST_ALGO_RMD160 ); + 0x10, 0 ); if( rc ) { log_error("make_keysig_packet failed: %s\n", g10_errstr(rc)); goto leave; @@ -684,6 +685,7 @@ change_passphrase( const char *username ) * Create a signature packet for the given public key certificate * and the user id and return it in ret_sig. User signature class SIGCLASS * user-id is not used (and may be NULL if sigclass is 0x20) + * If digest_algo is 0 the function selects an appropriate one. */ int make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc, @@ -695,25 +697,75 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc, MD_HANDLE md; assert( (sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x20 ); + if( !digest_algo ) { + switch( skc->pubkey_algo ) { + case PUBKEY_ALGO_DSA: digest_algo = DIGEST_ALGO_SHA1; break; + case PUBKEY_ALGO_RSA_S: + case PUBKEY_ALGO_RSA: digest_algo = DIGEST_ALGO_MD5; break; + default: digest_algo = DIGEST_ALGO_RMD160; break; + } + } md = md_open( digest_algo, 0 ); + md_start_debug( md, "make" ); /* hash the public key certificate and the user id */ hash_public_cert( md, pkc ); - if( sigclass != 0x20 ) + if( sigclass != 0x20 ) { + if( skc->version >=4 ) { + byte buf[5]; + buf[0] = 0xb4; /* indicates a userid packet */ + buf[1] = uid->len >> 24; /* always use 4 length bytes */ + buf[2] = uid->len >> 16; + buf[3] = uid->len >> 8; + buf[4] = uid->len; + md_write( md, buf, 5 ); + } md_write( md, uid->name, uid->len ); + } /* and make the signature packet */ sig = m_alloc_clear( sizeof *sig ); + sig->version = skc->version; + keyid_from_skc( skc, sig->keyid ); sig->pubkey_algo = skc->pubkey_algo; + sig->digest_algo = digest_algo; sig->timestamp = make_timestamp(); sig->sig_class = sigclass; + if( sig->version >= 4 ) { + build_sig_subpkt_from_sig( sig ); + md_putc( md, sig->version ); + } md_putc( md, sig->sig_class ); - { u32 a = sig->timestamp; + if( sig->version < 4 ) { + u32 a = sig->timestamp; md_putc( md, (a >> 24) & 0xff ); md_putc( md, (a >> 16) & 0xff ); md_putc( md, (a >> 8) & 0xff ); md_putc( md, a & 0xff ); } + else { + byte buf[6]; + size_t n; + + md_putc( md, sig->pubkey_algo ); + md_putc( md, sig->digest_algo ); + if( sig->hashed_data ) { + n = (sig->hashed_data[0] << 8) | sig->hashed_data[1]; + md_write( md, sig->hashed_data, n+2 ); + n += 6; + } + else + n = 6; + /* add some magic */ + buf[0] = sig->version; + buf[1] = 0xff; + buf[2] = n >> 24; /* hmmm, n is only 16 bit, so tthis is always 0 */ + buf[3] = n >> 16; + buf[4] = n >> 8; + buf[5] = n; + md_write( md, buf, 6 ); + + } md_final(md); rc = complete_sig( sig, skc, md ); |