1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

This is the first half of revocation key / designated revoker

support.  That is, it handles all the data to mark a key as revoked if it
has been revoked by a designated revoker.  The second half (coming
later) will contain the code to make someones key your designated revoker
and to issue revocations for someone else.

Note that this is written so that a revoked revoker can still issue
revocations: i.e. If A revokes B, but A is revoked, B is still revoked.
I'm not completely convinced this is the proper behavior, but it matches
how PGP does it.  It does at least have the advantage of much simpler code
- my first version of this had lots of loop maintaining code so you could
chain revokers many levels deep and if D was revoked, C was not, which
meant that B was, and so on. It was sort of scary, actually.

This also changes importing to allow bringing in more revocation keys, and
exporting to not export revocation keys marked "sensitive".

The --edit menu information will show if a revocation key is present.
This commit is contained in:
David Shaw 2002-02-28 21:01:25 +00:00
parent 6be293e24b
commit fbc66185f8
9 changed files with 332 additions and 30 deletions

View file

@ -96,7 +96,7 @@ static int uid_cache_entries; /* number of entries in uid cache */
static void merge_selfsigs( KBNODE keyblock );
static int lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode );
static int check_revocation_keys(PKT_public_key *pk,PKT_signature *sig);
#if 0
static void
@ -126,6 +126,9 @@ cache_public_key( PKT_public_key *pk )
if( pk_cache_disabled )
return;
if( pk->dont_cache )
return;
if( is_ELGAMAL(pk->pubkey_algo)
|| pk->pubkey_algo == PUBKEY_ALGO_DSA
|| is_RSA(pk->pubkey_algo) ) {
@ -1176,7 +1179,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked )
if ( pk->version < 4 ) {
/* before v4 the key packet itself contains the expiration date
* and there was noway to change it. So we also use only the
* and there was no way to change it. So we also use only the
* one from the key packet */
key_expire = pk->expiredate;
key_expire_seen = 1;
@ -1216,6 +1219,29 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked )
sigdate = sig->timestamp;
signode = k;
sigversion = sig->version;
/* Add any revocation keys onto the pk. This
is particularly interesting since we
normally only get data from the most recent
1F signature, but you need multiple 1F sigs
to properly handle revocation keys (PGP
does it this way, and a revocation key
could be sensitive and hence in a different
signature). */
if(sig->revkey) {
int i;
pk->revkey=
m_realloc(pk->revkey,sizeof(struct revocation_key)*
(pk->numrevkeys+sig->numrevkeys));
for(i=0;i<sig->numrevkeys;i++)
memcpy(&pk->revkey[pk->numrevkeys],
sig->revkey[i],
sizeof(struct revocation_key));
pk->numrevkeys+=sig->numrevkeys;
}
}
}
}
@ -1246,11 +1272,37 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked )
key_expire_seen = 1;
}
}
/* mark that key as valid: one direct key signature should
* render a key as valid */
pk->is_valid = 1;
}
/* pass 1.5: look for key revocation signatures that were not made
by the key (i.e. did a revocation key issue a revocation for
us?). Only bother to do this if there is a revocation key in
the first place. */
if(pk->revkey)
for(k=keyblock; k && k->pkt->pkttype != PKT_USER_ID; k = k->next )
{
if ( k->pkt->pkttype == PKT_SIGNATURE )
{
PKT_signature *sig = k->pkt->pkt.signature;
if(IS_KEY_REV(sig) &&
(sig->keyid[0]!=kid[0] || sig->keyid[1]!=kid[1]))
{
if(check_revocation_keys(pk,sig))
; /* did not verify, or loop broken */
else
*r_revoked=1;
/* In the future handle subkey and cert revocations?
PGP doesn't, but it's in 2440. */
}
}
}
/* second pass: look at the self-signature of all user IDs */
signode = uidnode = NULL;
@ -2189,3 +2241,62 @@ get_ctx_handle(GETKEY_CTX ctx)
{
return ctx->kr_handle;
}
/* Check the revocation keys to see if any of them have revoked our
pk. sig is the revocation sig. pk is the key it is on. This code
will need to be modified if gpg ever becomes multi-threaded. Note
that this is written so that a revoked revoker can still issue
revocations: i.e. If A revokes B, but A is revoked, B is still
revoked. I'm not completely convinced this is the proper behavior,
but it matches how PGP does it. -dms */
/* Return 0 if pk is revoked, non-0 if not revoked */
static int
check_revocation_keys(PKT_public_key *pk,PKT_signature *sig)
{
static int busy=0;
int i,rc=-1;
assert(IS_KEY_REV(sig));
assert((sig->keyid[0]!=pk->keyid[0]) || (sig->keyid[0]!=pk->keyid[1]));
if(busy)
{
/* return -1 (i.e. not revoked), but mark the pk as uncacheable
as we don't really know its revocation status until it is
checked directly. */
pk->dont_cache=1;
return -1;
}
busy=1;
/* printf("looking at %08lX with a sig from %08lX\n",(ulong)pk->keyid[1],
(ulong)sig->keyid[1]); */
/* is the issuer of the sig one of our revokers? */
for(i=0;i<pk->numrevkeys;i++)
{
u32 keyid[2];
keyid_from_fingerprint(pk->revkey[i].fpr,MAX_FINGERPRINT_LEN,keyid);
if(keyid[0]==sig->keyid[0] && keyid[1]==sig->keyid[1])
{
MD_HANDLE md;
md=md_open(sig->digest_algo,0);
hash_public_key(md,pk);
if(signature_check(sig,md)==0)
{
rc=0;
break;
}
}
}
busy=0;
return rc;
}