aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--g10/ChangeLog65
-rw-r--r--g10/export.c25
-rw-r--r--g10/free-packet.c9
-rw-r--r--g10/getkey.c115
-rw-r--r--g10/import.c61
-rw-r--r--g10/keyedit.c35
-rw-r--r--g10/keylist.c8
-rw-r--r--g10/packet.h15
-rw-r--r--g10/parse-packet.c27
9 files changed, 331 insertions, 29 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 4dbd64c12..ccdc0f98e 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,68 @@
+2002-02-28 David Shaw <[email protected]>
+
+ * 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 <[email protected]>
* export.c (do_export_stream): Do not include v3 keys in a
diff --git a/g10/export.c b/g10/export.c
index 2bfb9d018..a8ca9210c 100644
--- a/g10/export.c
+++ b/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 */
+ /* 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);
+ /* 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 ) {
diff --git a/g10/free-packet.c b/g10/free-packet.c
index f62c7ca03..4df3658d3 100644
--- a/g10/free-packet.c
+++ b/g10/free-packet.c
@@ -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;
}
diff --git a/g10/getkey.c b/g10/getkey.c
index fddb67ed3..5b8ac80ce 100644
--- a/g10/getkey.c
+++ b/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;
+}
diff --git a/g10/import.c b/g10/import.c
index 1daca680e..37147b40d 100644
--- a/g10/import.c
+++ b/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
diff --git a/g10/keyedit.c b/g10/keyedit.c
index db834cc74..3cfbf99ec 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -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)? '*':' ',
diff --git a/g10/keylist.c b/g10/keylist.c
index 8fc486c5d..4655e9adc 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -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 );
diff --git a/g10/packet.h b/g10/packet.h
index e55ca336a..e27a2c531 100644
--- a/g10/packet.h
+++ b/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;
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 60c45b56b..e27e22c85 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -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 ) {