From ce7d313333588adb653e3f791d24362bdc54e061 Mon Sep 17 00:00:00 2001 From: David Shaw Date: Tue, 13 Apr 2004 01:17:32 +0000 Subject: [PATCH] * keygen.c (make_backsig): New function to add a backsig to a binding sig of signing subkeys. Currently disabled. (write_keybinding): Call it here, for signing subkeys only. * sign.c (make_keysig_packet): Allow generating 0x19 signatures (same as 0x18 or 0x28, but used for backsigs). * packet.h, build-packet.c (build_sig_subpkt): Add new SIGSUBPKT_SIGNATURE type for embedded signatures. --- g10/ChangeLog | 12 +++++ g10/build-packet.c | 7 ++- g10/keygen.c | 118 +++++++++++++++++++++++++++++++++++++++++---- g10/packet.h | 1 + g10/sign.c | 20 +++++--- 5 files changed, 139 insertions(+), 19 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 39dfa1844..20195a169 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,15 @@ +2004-04-12 David Shaw + + * keygen.c (make_backsig): New function to add a backsig to a + binding sig of signing subkeys. Currently disabled. + (write_keybinding): Call it here, for signing subkeys only. + + * sign.c (make_keysig_packet): Allow generating 0x19 signatures + (same as 0x18 or 0x28, but used for backsigs). + + * packet.h, build-packet.c (build_sig_subpkt): Add new + SIGSUBPKT_SIGNATURE type for embedded signatures. + 2004-03-31 David Shaw * g10.c (main): --no-use-embedded-filename. diff --git a/g10/build-packet.c b/g10/build-packet.c index b3bb3f32a..2513b36a0 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -725,6 +725,7 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, case SIGSUBPKT_NOTATION: case SIGSUBPKT_POLICY: case SIGSUBPKT_REV_KEY: + case SIGSUBPKT_SIGNATURE: /* we do allow multiple subpackets */ break; @@ -781,18 +782,20 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, else nlen = 1; /* just a 1 byte length header */ - switch( type ) { + switch( type ) + { /* The issuer being unhashed is a historical oddity. It should work equally as well hashed. Of course, if even an unhashed issuer is tampered with, it makes it awfully hard to verify the sig... */ case SIGSUBPKT_ISSUER: + case SIGSUBPKT_SIGNATURE: hashed = 0; break; default: hashed = 1; break; - } + } if( critical ) type |= SIGSUBPKT_FLAG_CRITICAL; diff --git a/g10/keygen.c b/g10/keygen.c index ba5080b9d..c7df8ead4 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -524,6 +524,98 @@ keygen_add_revkey(PKT_signature *sig, void *opaque) return 0; } +static int +make_backsig(PKT_signature *sig, PKT_public_key *pk, + PKT_public_key *sub_pk, PKT_secret_key *sub_sk) +{ + PKT_signature *backsig; + int rc; + + /* This is not enabled yet, as I want to get a bit closer to RFC day + before enabling this. I've been burned before :) */ + + return 0; + + cache_public_key (sub_pk); + + rc=make_keysig_packet(&backsig,pk,NULL,sub_pk,sub_sk, 0x19, 0, 0, 0, 0, + NULL,NULL); + if( rc ) + log_error("make_keysig_packet failed for backsig: %s\n", g10_errstr(rc) ); + else + { + /* get it into a binary packed form. */ + IOBUF backsig_out=iobuf_temp(); + PACKET backsig_pkt; + byte *buf; + size_t pktlen=0; + + init_packet(&backsig_pkt); + backsig_pkt.pkttype=PKT_SIGNATURE; + backsig_pkt.pkt.signature=backsig; + build_packet(backsig_out,&backsig_pkt); + free_packet(&backsig_pkt); + buf=iobuf_get_temp_buffer(backsig_out); + + /* Remove the packet header */ + if(buf[0]&0x40) + { + if(buf[1]<192) + { + pktlen=buf[1]; + buf+=2; + } + else if(buf[1]<224) + { + pktlen=(buf[1]-192)*256; + pktlen+=buf[2]+192; + buf+=3; + } + else if(buf[1]==255) + { + pktlen =buf[2] << 24; + pktlen|=buf[3] << 16; + pktlen|=buf[4] << 8; + pktlen|=buf[5]; + buf+=6; + } + else + BUG(); + } + else + { + int mark=1; + + switch(buf[0]&3) + { + case 3: + BUG(); + break; + + case 2: + pktlen =buf[mark++] << 24; + pktlen|=buf[mark++] << 16; + + case 1: + pktlen|=buf[mark++] << 8; + + case 0: + pktlen|=buf[mark++]; + } + + buf+=mark; + } + + /* now make the binary blob into a subpacket */ + build_sig_subpkt(sig,SIGSUBPKT_SIGNATURE,buf,pktlen); + + iobuf_close(backsig_out); + } + + return rc; +} + + static int write_direct_sig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk, struct revocation_key *revkey ) @@ -616,7 +708,7 @@ write_keybinding( KBNODE root, KBNODE pub_root, PKT_signature *sig; int rc=0; KBNODE node; - PKT_public_key *pk, *subpk; + PKT_public_key *pri_pk, *sub_pk; struct opaque_data_usage_and_pk oduap; if( opt.verbose ) @@ -626,30 +718,38 @@ write_keybinding( KBNODE root, KBNODE pub_root, node = find_kbnode( pub_root, PKT_PUBLIC_KEY ); if( !node ) BUG(); - pk = node->pkt->pkt.public_key; + pri_pk = node->pkt->pkt.public_key; /* we have to cache the key, so that the verification of the signature * creation is able to retrieve the public key */ - cache_public_key (pk); + cache_public_key (pri_pk); /* find the last subkey */ - subpk = NULL; + sub_pk = NULL; for(node=pub_root; node; node = node->next ) { if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) - subpk = node->pkt->pkt.public_key; + sub_pk = node->pkt->pkt.public_key; } - if( !subpk ) + if( !sub_pk ) BUG(); /* and make the signature */ oduap.usage = use; - oduap.pk = subpk; - rc = make_keysig_packet( &sig, pk, NULL, subpk, pri_sk, 0x18, 0, 0, 0, 0, - keygen_add_key_flags_and_expire, &oduap ); + oduap.pk = sub_pk; + rc=make_keysig_packet(&sig, pri_pk, NULL, sub_pk, pri_sk, 0x18, 0, 0, 0, 0, + keygen_add_key_flags_and_expire, &oduap ); if( rc ) { log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) ); return rc; } + /* make a backsig */ + if(use&PUBKEY_USAGE_SIG) + { + rc=make_backsig(sig,pri_pk,sub_pk,sub_sk); + if(rc) + return rc; + } + pkt = m_alloc_clear( sizeof *pkt ); pkt->pkttype = PKT_SIGNATURE; pkt->pkt.signature = sig; diff --git a/g10/packet.h b/g10/packet.h index a9b3de5f8..d873c6ba7 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -352,6 +352,7 @@ typedef enum { SIGSUBPKT_SIGNERS_UID =28, /* signer's user id */ SIGSUBPKT_REVOC_REASON =29, /* reason for revocation */ SIGSUBPKT_FEATURES =30, /* feature flags */ + SIGSUBPKT_SIGNATURE =32, /* embedded signature */ SIGSUBPKT_FLAG_CRITICAL=128 } sigsubpkttype_t; diff --git a/g10/sign.c b/g10/sign.c index f3343e387..1824060c2 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -1164,7 +1164,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, MD_HANDLE md; assert( (sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F - || sigclass == 0x20 || sigclass == 0x18 + || sigclass == 0x20 || sigclass == 0x18 || sigclass == 0x19 || sigclass == 0x30 || sigclass == 0x28 ); if (opt.force_v4_certs) @@ -1203,14 +1203,19 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, md = md_open( digest_algo, 0 ); - /* hash the public key certificate and the user id */ + /* hash the public key certificate */ hash_public_key( md, pk ); - if( sigclass == 0x18 || sigclass == 0x28 ) { /* subkey binding/revocation*/ + + if( sigclass == 0x18 || sigclass == 0x19 || sigclass == 0x28 ) + { + /* hash the subkey binding/backsig/revocation */ hash_public_key( md, subpk ); - } - else if( sigclass != 0x1F && sigclass != 0x20 ) { + } + else if( sigclass != 0x1F && sigclass != 0x20 ) + { + /* hash the user id */ hash_uid (md, sigversion, uid); - } + } /* and make the signature packet */ sig = m_alloc_clear( sizeof *sig ); sig->version = sigversion; @@ -1266,8 +1271,7 @@ update_keysig_packet( PKT_signature **ret_sig, PKT_public_key *subpk, PKT_secret_key *sk, int (*mksubpkt)(PKT_signature *, void *), - void *opaque - ) + void *opaque ) { PKT_signature *sig; int rc=0;