aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--g10/ChangeLog16
-rw-r--r--g10/getkey.c45
-rw-r--r--g10/keygen.c2
-rw-r--r--g10/main.h2
-rw-r--r--g10/packet.h4
-rw-r--r--g10/parse-packet.c4
-rw-r--r--g10/sig-check.c54
7 files changed, 121 insertions, 6 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 485d2c19d..ebdbfb2f8 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,19 @@
+2004-04-22 David Shaw <[email protected]>
+
+ * keygen.c (make_backsig): If DO_BACKSIGS is not defined, do not
+ create backsigs.
+
+ * getkey.c (merge_selfsigs_subkey): Find 0x19 backsigs on subkey
+ selfsigs and verify they are valid. If DO_BACKSIGS is not
+ defined, fake this as always valid.
+
+ * packet.h, parse-packet.c (parse_signature): Make parse_signature
+ non-static so we can parse 0x19s in self-sigs.
+
+ * main.h, sig-check.c (check_backsig): Check a 0x19 signature.
+ (signature_check2): Give a backsig warning if there is no or a bad
+ 0x19 with signatures from a subkey.
+
2004-04-21 David Shaw <[email protected]>
* parse-packet.c (dump_sig_subpkt, parse_one_sig_subpkt,
diff --git a/g10/getkey.c b/g10/getkey.c
index 381b2f5ab..d24253ada 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -1934,8 +1934,51 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode )
return;
subpk->is_valid = 1;
-}
+#ifndef DO_BACKSIGS
+ /* Pretend the backsig is present and accounted for. */
+ subpk->backsig=2;
+#else
+ /* Find the first 0x19 embedded signature on our self-sig. */
+ if(subpk->backsig==0)
+ {
+ int seq=0;
+
+ while((p=enum_sig_subpkt(sig->hashed,
+ SIGSUBPKT_SIGNATURE,&n,&seq,NULL)))
+ if(n>3 && ((p[0]==3 && p[2]==0x19) || (p[0]==4 && p[1]==0x19)))
+ break;
+
+ if(p==NULL)
+ {
+ seq=0;
+ /* It is safe to have this in the unhashed area since the
+ 0x19 is located here for convenience, not security. */
+ while((p=enum_sig_subpkt(sig->unhashed,SIGSUBPKT_SIGNATURE,
+ &n,&seq,NULL)))
+ if(n>3 && ((p[0]==3 && p[2]==0x19) || (p[0]==4 && p[1]==0x19)))
+ break;
+ }
+
+ if(p)
+ {
+ PKT_signature *backsig=m_alloc_clear(sizeof(PKT_signature));
+ IOBUF backsig_buf=iobuf_temp_with_content(p,n);
+
+ if(parse_signature(backsig_buf,PKT_SIGNATURE,n,backsig)==0)
+ {
+ if(check_backsig(mainpk,subpk,backsig)==0)
+ subpk->backsig=2;
+ else
+ subpk->backsig=1;
+ }
+
+ iobuf_close(backsig_buf);
+ free_seckey_enc(backsig);
+ }
+ }
+#endif
+}
/*
diff --git a/g10/keygen.c b/g10/keygen.c
index 5d319c73b..a5c749f3e 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -630,10 +630,12 @@ make_backsig(PKT_signature *sig, PKT_public_key *pk,
PKT_signature *backsig;
int rc;
+#ifndef DO_BACKSIGS
/* 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;
+#endif
cache_public_key (sub_pk);
diff --git a/g10/main.h b/g10/main.h
index 500d45d4f..0bb8a2df9 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -135,6 +135,8 @@ int sign_symencrypt_file (const char *fname, STRLIST locusr);
/*-- sig-check.c --*/
int check_revocation_keys (PKT_public_key *pk, PKT_signature *sig);
+int check_backsig(PKT_public_key *main_pk,PKT_public_key *sub_pk,
+ PKT_signature *backsig);
int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig );
int check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
PKT_public_key *ret_pk, int *is_selfsig,
diff --git a/g10/packet.h b/g10/packet.h
index 558a6030a..0449c7d5f 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -212,6 +212,7 @@ typedef struct {
without the key to check it */
int is_valid; /* key (especially subkey) is valid */
int dont_cache; /* do not cache this */
+ byte backsig; /* 0=none, 1=bad, 2=good */
u32 main_keyid[2]; /* keyid of the primary key */
u32 keyid[2]; /* calculated by keyid_from_pk() */
byte is_primary;
@@ -364,6 +365,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
@@ -409,6 +411,8 @@ int copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff );
int skip_some_packets( IOBUF inp, unsigned n );
#endif
+int parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
+ PKT_signature *sig );
const byte *enum_sig_subpkt ( const subpktarea_t *subpkts,
sigsubpkttype_t reqtype,
size_t *ret_n, int *start, int *critical );
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 4faf27f18..56a717725 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -56,8 +56,6 @@ static int parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
static int parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
-static int parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
- PKT_signature *sig );
static int parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
PKT_onepass_sig *ops );
static int parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
@@ -1223,7 +1221,7 @@ void parse_revkeys(PKT_signature *sig)
}
}
-static int
+int
parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
PKT_signature *sig )
{
diff --git a/g10/sig-check.c b/g10/sig-check.c
index eb3664134..09dc5a2fc 100644
--- a/g10/sig-check.c
+++ b/g10/sig-check.c
@@ -80,11 +80,29 @@ signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate,
else if(!pk->is_valid && !pk->is_primary)
rc=G10ERR_BAD_PUBKEY; /* you cannot have a good sig from an
invalid subkey */
- else {
+ else
+ {
if(r_expiredate)
*r_expiredate = pk->expiredate;
+
rc = do_check( pk, sig, digest, r_expired, r_revoked, ret_pk );
- }
+
+ /* Check the backsig. This is a 0x19 signature from the
+ subkey on the primary key. The idea here is that it should
+ not be possible for someone to "steal" subkeys and claim
+ them as their own. The attacker couldn't actually use the
+ subkey, but they could try and claim ownership of any
+ signaures issued by it. */
+ if(rc==0 && !pk->is_primary && pk->backsig<2)
+ {
+ if(pk->backsig==0)
+ log_info(_("WARNING: signing subkey %s is not"
+ " cross-certified\n"),keystr_from_pk(pk));
+ else
+ log_info(_("WARNING: signing subkey %s has an invalid"
+ " cross-certification\n"),keystr_from_pk(pk));
+ }
+ }
free_public_key( pk );
@@ -387,6 +405,38 @@ check_revocation_keys(PKT_public_key *pk,PKT_signature *sig)
return rc;
}
+/* Backsigs (0x19) have the same format as binding sigs (0x18), but
+ this function is simpler than check_key_signature in a few ways.
+ For example, there is no support for expiring backsigs since it is
+ questionable what such a thing actually means. Note also that the
+ sig cache check here, unlike other sig caches in GnuPG, is not
+ persistent. */
+int
+check_backsig(PKT_public_key *main_pk,PKT_public_key *sub_pk,
+ PKT_signature *backsig)
+{
+ MD_HANDLE md;
+ int rc;
+
+ if(!opt.no_sig_cache && backsig->flags.checked)
+ {
+ if((rc=check_digest_algo(backsig->digest_algo)))
+ return rc;
+
+ return backsig->flags.valid? 0 : G10ERR_BAD_SIGN;
+ }
+
+ md=md_open(backsig->digest_algo,0);
+ hash_public_key(md,main_pk);
+ hash_public_key(md,sub_pk);
+ rc=do_check(sub_pk,backsig,md,NULL,NULL,NULL);
+ cache_sig_result(backsig,rc);
+ md_close(md);
+
+ return rc;
+}
+
+
/****************
* check the signature pointed to by NODE. This is a key signature.
* If the function detects a self-signature, it uses the PK from