mirror of
git://git.gnupg.org/gnupg.git
synced 2024-11-04 20:38:50 +01: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:
parent
6be293e24b
commit
fbc66185f8
@ -1,3 +1,68 @@
|
||||
2002-02-28 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* getkey.c (check_revocation_keys): New function to check a
|
||||
revocation against a list of potential revocation keys. Note the
|
||||
loop-breaking code here. This is to prevent blowing up if A is
|
||||
B's revocation key, while B is also A's. Note also 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.
|
||||
|
||||
* getkey.c (merge_selfsigs_main): 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 marked "sensitive" and hence in a
|
||||
different signature). Also, if a pk has a revocation key set,
|
||||
check for revocation sigs that were not made by us - if made by a
|
||||
valid revocation key, mark the pk revoked.
|
||||
|
||||
* packet.h, getkey.c (cache_public_key): do not cache key if
|
||||
"dont_cache" is set. This allows the revocation key code to look
|
||||
up a key and return information that may be inaccurate to prevent
|
||||
loops without caching the fake data.
|
||||
|
||||
* packet.h, sig-check.c (do_signature_check): Record if a
|
||||
signature was made by a revoked pk.
|
||||
|
||||
* packet.h, parse-packet.c (parse_one_sig_subpkt,
|
||||
can_handle_critical, parse_signature): Get revocation key
|
||||
information out of direct sigs.
|
||||
|
||||
* keylist.c (list_keyblock_print): don't assume that the presence
|
||||
of a 0x20 signature means the key is revoked. With revocation
|
||||
keys, this may not be true if the revocation key is not around to
|
||||
verify it or if verification failed. Also, 0x1F should get listed
|
||||
as "sig", and not "unexpected signature class".
|
||||
|
||||
* keyedit.c (show_key_with_all_names): Add a flag for printing
|
||||
revoker information and change all callers.
|
||||
|
||||
* import.c (merge_blocks): merge in any new direct key (0x1F)
|
||||
sigs.
|
||||
|
||||
* import.c (import_revoke_cert): don't keep processing after a
|
||||
revocation is rejected.
|
||||
|
||||
* import.c (delete_inv_parts): Allow importing a revocation
|
||||
signature even if it was not issued by the key. This allows a
|
||||
revocation key to issue it. Of course, the sig still needs to be
|
||||
checked before we trust it.
|
||||
|
||||
* free-packet.c (copy_public_key): Include a new copy of the
|
||||
revocation keys when duping a pk.
|
||||
|
||||
* free-packet.c (free_seckey_enc, release_public_key_parts): Free
|
||||
any revocation keys that are attached to a sig or pk.
|
||||
|
||||
* export.c (do_export_stream): Do not export signatures with
|
||||
"sensitive" revocation keys in them.
|
||||
|
||||
2002-02-27 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* export.c (do_export_stream): Do not include v3 keys in a
|
||||
|
27
g10/export.c
27
g10/export.c
@ -200,14 +200,27 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
|
||||
/* make sure that ring_trust packets never get exported */
|
||||
if (node->pkt->pkttype == PKT_RING_TRUST)
|
||||
continue;
|
||||
/* do not export packets which are marked as not exportable */
|
||||
if( node->pkt->pkttype == PKT_SIGNATURE ) {
|
||||
if( !node->pkt->pkt.signature->flags.exportable )
|
||||
continue; /* not exportable */
|
||||
|
||||
/* delete our verification cache */
|
||||
delete_sig_subpkt (node->pkt->pkt.signature->unhashed,
|
||||
SIGSUBPKT_PRIV_VERIFY_CACHE);
|
||||
if( node->pkt->pkttype == PKT_SIGNATURE ) {
|
||||
/* do not export packets which are marked as not exportable */
|
||||
if( !node->pkt->pkt.signature->flags.exportable )
|
||||
continue; /* not exportable */
|
||||
|
||||
/* do not export packets with a "sensitive" revocation
|
||||
key. This will need revisiting when we start
|
||||
supporting creating revocation keys and not just
|
||||
reading them. */
|
||||
if( node->pkt->pkt.signature->revkey ) {
|
||||
int i;
|
||||
|
||||
for(i=0;i<node->pkt->pkt.signature->numrevkeys;i++)
|
||||
if(node->pkt->pkt.signature->revkey[i]->class & 0x40)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* delete our verification cache */
|
||||
delete_sig_subpkt (node->pkt->pkt.signature->unhashed,
|
||||
SIGSUBPKT_PRIV_VERIFY_CACHE);
|
||||
}
|
||||
|
||||
if( secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY ) {
|
||||
|
@ -59,6 +59,8 @@ free_seckey_enc( PKT_signature *sig )
|
||||
mpi_free(sig->data[0]);
|
||||
for(i=0; i < n; i++ )
|
||||
mpi_free( sig->data[i] );
|
||||
|
||||
m_free(sig->revkey);
|
||||
m_free(sig->hashed);
|
||||
m_free(sig->unhashed);
|
||||
m_free(sig);
|
||||
@ -89,6 +91,11 @@ release_public_key_parts( PKT_public_key *pk )
|
||||
free_user_id (pk->user_id);
|
||||
pk->user_id = NULL;
|
||||
}
|
||||
if (pk->revkey) {
|
||||
m_free(pk->revkey);
|
||||
pk->revkey=NULL;
|
||||
pk->numrevkeys=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -157,6 +164,8 @@ copy_public_key ( PKT_public_key *d, PKT_public_key *s)
|
||||
for(i=0; i < n; i++ )
|
||||
d->pkey[i] = mpi_copy( s->pkey[i] );
|
||||
}
|
||||
d->revkey=m_alloc(sizeof(struct revocation_key)*s->numrevkeys);
|
||||
memcpy(d->revkey,s->revkey,sizeof(struct revocation_key)*s->numrevkeys);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
115
g10/getkey.c
115
g10/getkey.c
@ -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;
|
||||
}
|
||||
|
61
g10/import.c
61
g10/import.c
@ -743,6 +743,7 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats )
|
||||
if( rc ) {
|
||||
log_error( _("key %08lX: invalid revocation certificate"
|
||||
": %s - rejected\n"), (ulong)keyid[1], g10_errstr(rc));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
|
||||
@ -954,12 +955,22 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
|
||||
delete_kbnode( node );
|
||||
}
|
||||
else {
|
||||
int rc = check_key_signature( keyblock, node, NULL);
|
||||
if( rc ) {
|
||||
log_error( _("key %08lX: invalid revocation "
|
||||
"certificate: %s - skipped\n"),
|
||||
(ulong)keyid[1], g10_errstr(rc));
|
||||
delete_kbnode( node );
|
||||
/* If the revocation cert is from a different key than
|
||||
the one we're working on don't check it - it's
|
||||
probably from a revocation key and won't be
|
||||
verifiable with this key anyway. */
|
||||
|
||||
if(node->pkt->pkt.signature->keyid[0]==keyid[0] &&
|
||||
node->pkt->pkt.signature->keyid[1]==keyid[1])
|
||||
{
|
||||
int rc = check_key_signature( keyblock, node, NULL);
|
||||
if( rc )
|
||||
{
|
||||
log_error( _("key %08lX: invalid revocation "
|
||||
"certificate: %s - skipped\n"),
|
||||
(ulong)keyid[1], g10_errstr(rc));
|
||||
delete_kbnode( node );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1114,7 +1125,37 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock,
|
||||
}
|
||||
}
|
||||
|
||||
/* 2nd: try to merge new certificates in */
|
||||
/* 2nd: merge in any direct key (0x1F) sigs */
|
||||
for(node=keyblock->next; node; node=node->next ) {
|
||||
if( node->pkt->pkttype == PKT_USER_ID )
|
||||
break;
|
||||
else if( node->pkt->pkttype == PKT_SIGNATURE
|
||||
&& node->pkt->pkt.signature->sig_class == 0x1F ) {
|
||||
/* check whether we already have this */
|
||||
found = 0;
|
||||
for(onode=keyblock_orig->next; onode; onode=onode->next ) {
|
||||
if( onode->pkt->pkttype == PKT_USER_ID )
|
||||
break;
|
||||
else if( onode->pkt->pkttype == PKT_SIGNATURE
|
||||
&& onode->pkt->pkt.signature->sig_class == 0x1F
|
||||
&& !cmp_signatures(onode->pkt->pkt.signature,
|
||||
node->pkt->pkt.signature)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !found ) {
|
||||
KBNODE n2 = clone_kbnode(node);
|
||||
insert_kbnode( keyblock_orig, n2, 0 );
|
||||
n2->flag |= 1;
|
||||
++*n_sigs;
|
||||
log_info( _("key %08lX: direct key signature added\n"),
|
||||
(ulong)keyid[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 3rd: try to merge new certificates in */
|
||||
for(onode=keyblock_orig->next; onode; onode=onode->next ) {
|
||||
if( !(onode->flag & 1) && onode->pkt->pkttype == PKT_USER_ID) {
|
||||
/* find the user id in the imported keyblock */
|
||||
@ -1131,7 +1172,7 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock,
|
||||
}
|
||||
}
|
||||
|
||||
/* 3rd: add new user-ids */
|
||||
/* 4th: add new user-ids */
|
||||
for(node=keyblock->next; node; node=node->next ) {
|
||||
if( node->pkt->pkttype == PKT_USER_ID) {
|
||||
/* do we have this in the original keyblock */
|
||||
@ -1149,7 +1190,7 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock,
|
||||
}
|
||||
}
|
||||
|
||||
/* add new subkeys */
|
||||
/* 5th: add new subkeys */
|
||||
for(node=keyblock->next; node; node=node->next ) {
|
||||
onode = NULL;
|
||||
if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
|
||||
@ -1182,7 +1223,7 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock,
|
||||
}
|
||||
}
|
||||
|
||||
/* merge subkey certificates */
|
||||
/* 6th: merge subkey certificates */
|
||||
for(onode=keyblock_orig->next; onode; onode=onode->next ) {
|
||||
if( !(onode->flag & 1)
|
||||
&& ( onode->pkt->pkttype == PKT_PUBLIC_SUBKEY
|
||||
|
@ -42,8 +42,8 @@
|
||||
#include "i18n.h"
|
||||
|
||||
static void show_prefs( PKT_user_id *uid, int verbose );
|
||||
static void show_key_with_all_names( KBNODE keyblock,
|
||||
int only_marked, int with_fpr, int with_subkeys, int with_prefs );
|
||||
static void show_key_with_all_names( KBNODE keyblock, int only_marked,
|
||||
int with_revoker, int with_fpr, int with_subkeys, int with_prefs );
|
||||
static void show_key_and_fingerprint( KBNODE keyblock );
|
||||
static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock, int photo );
|
||||
static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock );
|
||||
@ -390,7 +390,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
|
||||
}
|
||||
/* Ask whether we really should sign these user id(s) */
|
||||
tty_printf("\n");
|
||||
show_key_with_all_names( keyblock, 1, 1, 0, 0 );
|
||||
show_key_with_all_names( keyblock, 1, 0, 1, 0, 0 );
|
||||
tty_printf("\n");
|
||||
|
||||
if(primary_pk->expiredate)
|
||||
@ -894,7 +894,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
|
||||
|
||||
tty_printf("\n");
|
||||
if( redisplay ) {
|
||||
show_key_with_all_names( cur_keyblock, 0, 0, 1, 0 );
|
||||
show_key_with_all_names( cur_keyblock, 0, 1, 0, 1, 0 );
|
||||
tty_printf("\n");
|
||||
redisplay = 0;
|
||||
}
|
||||
@ -1167,7 +1167,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
|
||||
break;
|
||||
|
||||
case cmdTRUST:
|
||||
show_key_with_all_names( keyblock, 0, 0, 1, 0 );
|
||||
show_key_with_all_names( keyblock, 0, 0, 0, 1, 0 );
|
||||
tty_printf("\n");
|
||||
if( edit_ownertrust( find_kbnode( keyblock,
|
||||
PKT_PUBLIC_KEY )->pkt->pkt.public_key, 1 ) )
|
||||
@ -1175,11 +1175,11 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
|
||||
break;
|
||||
|
||||
case cmdPREF:
|
||||
show_key_with_all_names( keyblock, 0, 0, 0, 1 );
|
||||
show_key_with_all_names( keyblock, 0, 0, 0, 0, 1 );
|
||||
break;
|
||||
|
||||
case cmdSHOWPREF:
|
||||
show_key_with_all_names( keyblock, 0, 0, 0, 2 );
|
||||
show_key_with_all_names( keyblock, 0, 0, 0, 0, 2 );
|
||||
break;
|
||||
|
||||
case cmdSETPREF:
|
||||
@ -1389,7 +1389,7 @@ show_prefs (PKT_user_id *uid, int verbose)
|
||||
* so for user ids with mark A flag set and dont display the index number
|
||||
*/
|
||||
static void
|
||||
show_key_with_all_names( KBNODE keyblock, int only_marked,
|
||||
show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
|
||||
int with_fpr, int with_subkeys, int with_prefs )
|
||||
{
|
||||
KBNODE node;
|
||||
@ -1410,6 +1410,25 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
|
||||
otrust = get_ownertrust_info (pk);
|
||||
}
|
||||
|
||||
if(with_revoker)
|
||||
for(i=0;i<pk->numrevkeys;i++)
|
||||
{
|
||||
u32 r_keyid[2];
|
||||
char *user;
|
||||
|
||||
keyid_from_fingerprint(pk->revkey[i].fpr,
|
||||
MAX_FINGERPRINT_LEN,r_keyid);
|
||||
|
||||
user=get_user_id_string(r_keyid);
|
||||
|
||||
tty_printf(_("This key may be revoked by %s key %s%s\n"),
|
||||
pubkey_algo_to_string(pk->revkey[i].algid),
|
||||
user,
|
||||
pk->revkey[i].class&0x40?_(" (sensitive)"):"");
|
||||
|
||||
m_free(user);
|
||||
}
|
||||
|
||||
tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"),
|
||||
node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
|
||||
(node->flag & NODFLG_SELKEY)? '*':' ',
|
||||
|
@ -417,7 +417,11 @@ list_keyblock_print ( KBNODE keyblock, int secret )
|
||||
char *sigstr;
|
||||
|
||||
if( !any ) { /* no user id, (maybe a revocation follows)*/
|
||||
if( sig->sig_class == 0x20 )
|
||||
/* Check if the pk is really revoked - there could be a
|
||||
0x20 sig packet there even if we are not revoked
|
||||
(say, if a revocation key issued the packet, but the
|
||||
revocation key isn't present to verify it.) */
|
||||
if( sig->sig_class == 0x20 && pk->is_revoked )
|
||||
puts("[revoked]");
|
||||
else if( sig->sig_class == 0x18 )
|
||||
puts("[key binding]");
|
||||
@ -437,6 +441,8 @@ list_keyblock_print ( KBNODE keyblock, int secret )
|
||||
sigstr = "sig";
|
||||
else if( sig->sig_class == 0x18 )
|
||||
sigstr = "sig";
|
||||
else if( sig->sig_class == 0x1F )
|
||||
sigstr = "sig";
|
||||
else {
|
||||
printf("sig "
|
||||
"[unexpected signature class 0x%02x]\n",sig->sig_class );
|
||||
|
15
g10/packet.h
15
g10/packet.h
@ -26,6 +26,7 @@
|
||||
#include "mpi.h"
|
||||
#include "cipher.h"
|
||||
#include "filter.h"
|
||||
#include "global.h"
|
||||
|
||||
#define DEBUG_PARSE_PACKET 1
|
||||
|
||||
@ -113,6 +114,11 @@ typedef struct {
|
||||
byte data[1];
|
||||
} subpktarea_t;
|
||||
|
||||
struct revocation_key {
|
||||
byte class;
|
||||
byte algid;
|
||||
byte fpr[MAX_FINGERPRINT_LEN];
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
ulong local_id; /* internal use, valid if > 0 */
|
||||
@ -133,7 +139,9 @@ typedef struct {
|
||||
byte sig_class; /* sig classification, append for MD calculation*/
|
||||
byte pubkey_algo; /* algorithm used for public key scheme */
|
||||
/* (PUBKEY_ALGO_xxx) */
|
||||
byte digest_algo; /* algorithm used for digest (DIGEST_ALGO_xxxx) */
|
||||
byte digest_algo; /* algorithm used for digest (DIGEST_ALGO_xxxx) */
|
||||
struct revocation_key **revkey;
|
||||
int numrevkeys;
|
||||
subpktarea_t *hashed; /* all subpackets with hashed data (v4 only) */
|
||||
subpktarea_t *unhashed; /* ditto for unhashed data */
|
||||
byte digest_start[2]; /* first 2 bytes of the digest */
|
||||
@ -190,13 +198,16 @@ typedef struct {
|
||||
u32 has_expired; /* set to the expiration date if expired */
|
||||
int is_revoked; /* key has been revoked */
|
||||
int is_valid; /* key (especially subkey) is valid */
|
||||
int dont_cache; /* do not cache this */
|
||||
ulong local_id; /* internal use, valid if > 0 */
|
||||
u32 main_keyid[2]; /* keyid of the primary key */
|
||||
u32 keyid[2]; /* calculated by keyid_from_pk() */
|
||||
prefitem_t *prefs; /* list of preferences (may be NULL) */
|
||||
int mdc_feature; /* mdc feature set */
|
||||
int mdc_feature; /* mdc feature set */
|
||||
byte *namehash; /* if != NULL: found by this name */
|
||||
PKT_user_id *user_id; /* if != NULL: found by that uid */
|
||||
struct revocation_key *revkey;
|
||||
int numrevkeys;
|
||||
MPI pkey[PUBKEY_MAX_NPKEY];
|
||||
} PKT_public_key;
|
||||
|
||||
|
@ -922,6 +922,10 @@ parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
|
||||
if( n < 8 ) /* minimum length needed */
|
||||
break;
|
||||
return 0;
|
||||
case SIGSUBPKT_REV_KEY:
|
||||
if(n < 22)
|
||||
break;
|
||||
return 0;
|
||||
case SIGSUBPKT_REVOC_REASON:
|
||||
if( !n )
|
||||
break;
|
||||
@ -969,6 +973,7 @@ can_handle_critical( const byte *buffer, size_t n, int type )
|
||||
case SIGSUBPKT_KEY_EXPIRE:
|
||||
case SIGSUBPKT_EXPORTABLE:
|
||||
case SIGSUBPKT_REVOCABLE:
|
||||
case SIGSUBPKT_REV_KEY:
|
||||
case SIGSUBPKT_ISSUER:/* issuer key ID */
|
||||
case SIGSUBPKT_PREF_SYM:
|
||||
case SIGSUBPKT_PREF_HASH:
|
||||
@ -1248,6 +1253,28 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
p=parse_sig_subpkt2(sig,SIGSUBPKT_EXPORTABLE,NULL);
|
||||
if(p && *p==0)
|
||||
sig->flags.exportable=0;
|
||||
|
||||
/* Find all revokation keys */
|
||||
if(sig->sig_class==0x1F)
|
||||
{
|
||||
struct revocation_key *revkey;
|
||||
int len,seq=0;
|
||||
|
||||
while((revkey=
|
||||
(struct revocation_key *)enum_sig_subpkt(sig->hashed,
|
||||
SIGSUBPKT_REV_KEY,
|
||||
&len,&seq)))
|
||||
{
|
||||
if(len==sizeof(struct revocation_key) &&
|
||||
revkey->class&0x80) /* 0x80 bit must be set */
|
||||
{
|
||||
sig->revkey=m_realloc(sig->revkey,
|
||||
sizeof(struct revocation_key *)*(sig->numrevkeys+1));
|
||||
sig->revkey[sig->numrevkeys]=revkey;
|
||||
sig->numrevkeys++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( list_mode ) {
|
||||
|
Loading…
Reference in New Issue
Block a user