aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
Diffstat (limited to 'g10')
-rw-r--r--g10/ChangeLog24
-rw-r--r--g10/Makefile.in2
-rw-r--r--g10/armor.c5
-rw-r--r--g10/build-packet.c20
-rw-r--r--g10/filter.h2
-rw-r--r--g10/free-packet.c2
-rw-r--r--g10/g10.c2
-rw-r--r--g10/import.c195
-rw-r--r--g10/keygen.c1
-rw-r--r--g10/mainproc.c58
-rw-r--r--g10/packet.h1
-rw-r--r--g10/parse-packet.c10
-rw-r--r--g10/pkclist.c21
-rw-r--r--g10/revoke.c1
-rw-r--r--g10/sig-check.c44
-rw-r--r--g10/sign.c1
-rw-r--r--g10/trustdb.c58
-rw-r--r--g10/trustdb.h7
18 files changed, 357 insertions, 97 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 414b051f0..6be310564 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,27 @@
+Wed Feb 18 13:35:58 1998 Werner Koch ([email protected])
+
+ * mainproc.c (do_check_sig): Now uses hash_public_cert.
+ * parse-packet.c (parse_certificate): Removed hashing.
+ * packet.h (public_cert): Removed hash variable.
+ * free-packet.c (copy_public_cert, free_public_cert): Likewise.
+
+ * sig-check.c (check_key_signatures): Changed semantics.
+
+Wed Feb 18 12:11:28 1998 Werner Koch ([email protected])
+
+ * trustdb.c (do_check): Add handling for revocation certificates.
+ (build_sigrecs): Ditto.
+ (check_sigs): Ditto.
+
+Wed Feb 18 09:31:04 1998 Werner Koch ([email protected])
+
+ * armor.c (armor_filter): Add afx->hdrlines.
+ * revoke.c (gen_revoke): Add comment line.
+ * dearmor.c (enarmor_file): Ditto.
+
+ * sig-check.c (check_key_signature): Add handling for class 0x20.
+ * mainproc.c : Ditto.
+
Tue Feb 17 21:24:17 1998 Werner Koch ([email protected])
* armor.c : Add header lines "...ARMORED FILE .."
diff --git a/g10/Makefile.in b/g10/Makefile.in
index 953b13b6b..318423c56 100644
--- a/g10/Makefile.in
+++ b/g10/Makefile.in
@@ -87,7 +87,7 @@ VERSION = @VERSION@
ZLIBS = @ZLIBS@
INCLUDES = -I$(top_srcdir)/include
-EXTRA_DIST = OPTIONS pubring.g10
+EXTRA_DIST = OPTIONS pubring.asc
needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a
bin_PROGRAMS = g10 g10maint
diff --git a/g10/armor.c b/g10/armor.c
index 03a393b35..1fc8ae0b0 100644
--- a/g10/armor.c
+++ b/g10/armor.c
@@ -944,7 +944,10 @@ armor_filter( void *opaque, int control,
iobuf_writestr(a, "-----\n");
iobuf_writestr(a, "Version: G10 v" VERSION " ("
PRINTABLE_OS_NAME ")\n");
- iobuf_writestr(a, "Comment: This is an alpha version!\n\n");
+ iobuf_writestr(a, "Comment: This is an alpha version!\n");
+ if( afx->hdrlines )
+ iobuf_writestr(a, afx->hdrlines);
+ iobuf_put(a, '\n');
afx->status++;
afx->idx = 0;
afx->idx2 = 0;
diff --git a/g10/build-packet.c b/g10/build-packet.c
index 2e1a48337..b032a67b0 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -211,7 +211,12 @@ hash_public_cert( MD_HANDLE md, PKT_public_cert *pkc )
int rc = 0;
int c;
IOBUF a = iobuf_temp();
- /* FILE *fp = fopen("dump.pkc", "a");*/
+ #if 1
+ FILE *fp = fopen("dump.pkc", "a");
+ int i=0;
+
+ fprintf(fp, "\nHashing PKC:\n");
+ #endif
/* build the packet */
init_packet(&pkt);
@@ -220,10 +225,19 @@ hash_public_cert( MD_HANDLE md, PKT_public_cert *pkc )
if( (rc = build_packet( a, &pkt )) )
log_fatal("build public_cert for hashing failed: %s\n", g10_errstr(rc));
while( (c=iobuf_get(a)) != -1 ) {
- /* putc( c, fp);*/
+ #if 1
+ fprintf( fp," %02x", c );
+ if( (++i == 24) ) {
+ putc('\n', fp);
+ i=0;
+ }
+ #endif
md_putc( md, c );
}
- /*fclose(fp);*/
+ #if 1
+ putc('\n', fp);
+ fclose(fp);
+ #endif
iobuf_cancel(a);
}
diff --git a/g10/filter.h b/g10/filter.h
index 93e72ce9c..965b75bd0 100644
--- a/g10/filter.h
+++ b/g10/filter.h
@@ -20,6 +20,7 @@
#ifndef G10_FILTER_H
#define G10_FILTER_H
+#include "types.h"
#include "cipher.h"
typedef struct {
@@ -41,6 +42,7 @@ typedef struct {
int inp_checked; /* set if inp has been checked */
int inp_bypass; /* set if the input is not armored */
int inp_eof;
+ const char *hdrlines;
} armor_filter_context_t;
diff --git a/g10/free-packet.c b/g10/free-packet.c
index f2467a78b..9152f9051 100644
--- a/g10/free-packet.c
+++ b/g10/free-packet.c
@@ -87,7 +87,6 @@ release_public_cert_parts( PKT_public_cert *cert )
mpi_free( cert->d.rsa.rsa_n ); cert->d.rsa.rsa_n = NULL;
mpi_free( cert->d.rsa.rsa_e ); cert->d.rsa.rsa_e = NULL;
}
- md_close( cert->mfx.md ); cert->mfx.md = NULL;
}
void
@@ -112,7 +111,6 @@ copy_public_cert( PKT_public_cert *d, PKT_public_cert *s )
d->d.rsa.rsa_n = mpi_copy( s->d.rsa.rsa_n );
d->d.rsa.rsa_e = mpi_copy( s->d.rsa.rsa_e );
}
- d->mfx.md = NULL;
return d;
}
diff --git a/g10/g10.c b/g10/g10.c
index f9ae0fc69..433955717 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -474,7 +474,7 @@ main( int argc, char **argv )
if( greeting ) {
tty_printf("%s %s; %s\n", strusage(11), strusage(13), strusage(14) );
- tty_printf("%s", strusage(15) );
+ tty_printf("%s\n", strusage(15) );
}
/* initialize the secure memory. */
diff --git a/g10/import.c b/g10/import.c
index 43e64239f..fa08e8657 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -38,6 +38,7 @@
static int read_block( IOBUF a, compress_filter_context_t *cfx,
PACKET **pending_pkt, KBNODE *ret_root );
static int import_one( const char *fname, KBNODE keyblock );
+static int import_revoke_cert( const char *fname, KBNODE node );
static int chk_self_sigs( const char *fname, KBNODE keyblock,
PKT_public_cert *pkc, u32 *keyid );
static int delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid );
@@ -56,7 +57,6 @@ static int merge_sigs( KBNODE dst, KBNODE src, int *n_sigs,
* Other signatures are not not checked.
*
* Actually this functtion does a merge. It works like this:
- * FIXME: add handling for revocation certs
*
* - get the keyblock
* - check self-signatures and remove all userids and their signatures
@@ -78,6 +78,8 @@ static int merge_sigs( KBNODE dst, KBNODE src, int *n_sigs,
* is used.
* - Proceed with next signature.
*
+ * Key revocation certificates have a special handling.
+ *
*/
int
import_pubkeys( const char *fname )
@@ -107,6 +109,9 @@ import_pubkeys( const char *fname )
while( !(rc = read_block( inp, &cfx, &pending_pkt, &keyblock) )) {
if( keyblock->pkt->pkttype == PKT_PUBLIC_CERT )
rc = import_one( fname, keyblock );
+ else if( keyblock->pkt->pkttype == PKT_SIGNATURE
+ && keyblock->pkt->pkt.signature->sig_class == 0x20 )
+ rc = import_revoke_cert( fname, keyblock );
else
log_info("%s: skipping block of type %d\n",
fname, keyblock->pkt->pkttype );
@@ -159,6 +164,16 @@ read_block( IOBUF a, compress_filter_context_t *cfx,
init_packet(pkt);
continue;
}
+
+ if( !root && pkt->pkttype == PKT_SIGNATURE
+ && pkt->pkt.signature->sig_class == 0x20 ) {
+ /* this is a revocation certificate which is handled
+ * in a special way */
+ root = new_kbnode( pkt );
+ pkt = NULL;
+ goto ready;
+ }
+
/* make a linked list of all packets */
switch( pkt->pkttype ) {
case PKT_COMPRESSED:
@@ -332,7 +347,7 @@ import_one( const char *fname, KBNODE keyblock )
if( (rc=lock_keyblock( &kbpos )) )
log_error("can't lock public keyring '%s': %s\n",
keyblock_resource_name(&kbpos), g10_errstr(rc) );
- else if( (rc=insert_keyblock( &kbpos, keyblock )) )
+ else if( (rc=update_keyblock( &kbpos, keyblock )) )
log_error("%s: can't write to '%s': %s\n", fname,
keyblock_resource_name(&kbpos), g10_errstr(rc) );
unlock_keyblock( &kbpos );
@@ -362,6 +377,105 @@ import_one( const char *fname, KBNODE keyblock )
/****************
+ * Import a revocation certificate, this is a single signature packet.
+ */
+static int
+import_revoke_cert( const char *fname, KBNODE node )
+{
+ PKT_public_cert *pkc=NULL;
+ KBNODE onode, keyblock = NULL;
+ KBPOS kbpos;
+ u32 keyid[2];
+ int rc = 0;
+
+ assert( !node->next );
+ assert( node->pkt->pkttype == PKT_SIGNATURE );
+ assert( node->pkt->pkt.signature->sig_class == 0x20 );
+
+ keyid[0] = node->pkt->pkt.signature->keyid[0];
+ keyid[1] = node->pkt->pkt.signature->keyid[1];
+
+ pkc = m_alloc_clear( sizeof *pkc );
+ rc = get_pubkey( pkc, keyid );
+ if( rc == G10ERR_NO_PUBKEY ) {
+ log_info("%s: key %08lX, no public key - "
+ "can't apply revocation certificate\n",
+ fname, (ulong)keyid[1]);
+ rc = 0;
+ goto leave;
+ }
+ else if( rc ) {
+ log_error("%s: key %08lX, public key not found: %s\n",
+ fname, (ulong)keyid[1], g10_errstr(rc));
+ goto leave;
+ }
+
+ /* read the original keyblock */
+ rc = find_keyblock_bypkc( &kbpos, pkc );
+ if( rc ) {
+ log_error("%s: key %08lX, can't locate original keyblock: %s\n",
+ fname, (ulong)keyid[1], g10_errstr(rc));
+ goto leave;
+ }
+ rc = read_keyblock( &kbpos, &keyblock );
+ if( rc ) {
+ log_error("%s: key %08lX, can't read original keyblock: %s\n",
+ fname, (ulong)keyid[1], g10_errstr(rc));
+ goto leave;
+ }
+
+
+ /* it is okay, that node is not in keyblock because
+ * check_key_signature works fine for sig_class 0x20 in this
+ * special case. */
+ rc = check_key_signature( keyblock, node, NULL);
+ if( rc ) {
+ log_error("%s: key %08lX, invalid revocation certificate"
+ ": %s - rejected\n",
+ fname, (ulong)keyid[1], g10_errstr(rc));
+ }
+
+
+ /* check wether we already have this */
+ for(onode=keyblock->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 == 0x20
+ && keyid[0] == onode->pkt->pkt.signature->keyid[0]
+ && keyid[1] == onode->pkt->pkt.signature->keyid[1] ) {
+ rc = 0;
+ goto leave; /* yes, we already know about it */
+ }
+ }
+
+
+ /* insert it */
+ insert_kbnode( keyblock, clone_kbnode(node), 0 );
+
+ /* and write the keyblock back */
+ if( opt.verbose > 1 )
+ log_info("%s: writing to '%s'\n",
+ fname, keyblock_resource_name(&kbpos) );
+ if( (rc=lock_keyblock( &kbpos )) )
+ log_error("can't lock public keyring '%s': %s\n",
+ keyblock_resource_name(&kbpos), g10_errstr(rc) );
+ else if( (rc=update_keyblock( &kbpos, keyblock )) )
+ log_error("%s: can't write to '%s': %s\n", fname,
+ keyblock_resource_name(&kbpos), g10_errstr(rc) );
+ unlock_keyblock( &kbpos );
+ /* we are ready */
+ log_info("%s: key %08lX, added revocation certificate\n",
+ fname, (ulong)keyid[1]);
+
+ leave:
+ release_kbnode( keyblock );
+ free_public_cert( pkc );
+ return rc;
+}
+
+
+/****************
* loop over the keyblock an check all self signatures.
* Mark all user-ids with a self-signature by setting flag bit 0.
* Mark all user-ids with an invalid self-signature by setting bit 1.
@@ -408,10 +522,11 @@ static int
delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
{
KBNODE node;
- int nvalid=0;
+ int nvalid=0, uid_seen=0;
for(node=keyblock->next; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
+ uid_seen = 1;
if( (node->flag & 2) || !(node->flag & 1) ) {
if( opt.verbose ) {
log_info("%s: key %08lX, removed userid '",
@@ -434,6 +549,23 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
&& check_pubkey_algo( node->pkt->pkt.signature->pubkey_algo)
&& node->pkt->pkt.signature->pubkey_algo != PUBKEY_ALGO_RSA )
delete_kbnode( node ); /* build_packet() can't handle this */
+ else if( node->pkt->pkttype == PKT_SIGNATURE
+ && node->pkt->pkt.signature->sig_class == 0x20 ) {
+ if( uid_seen ) {
+ log_error("%s: key %08lX, revocation certificate at wrong "
+ "place - removed\n", fname, (ulong)keyid[1]);
+ delete_kbnode( node );
+ }
+ else {
+ int rc = check_key_signature( keyblock, node, NULL);
+ if( rc ) {
+ log_error("%s: key %08lX, invalid revocation certificate"
+ ": %s - removed\n",
+ fname, (ulong)keyid[1], g10_errstr(rc));
+ delete_kbnode( node );
+ }
+ }
+ }
}
/* note: because keyblock is the public key, it is never marked
@@ -460,36 +592,67 @@ static int
merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock,
u32 *keyid, int *n_uids, int *n_sigs )
{
- KBNODE node_orig, node;
- int rc;
+ KBNODE onode, node;
+ int rc, found;
+
+ /* 1st: handle revocation certificates */
+ 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 == 0x20 ) {
+ /* check wether 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 == 0x20
+ && node->pkt->pkt.signature->keyid[0]
+ == onode->pkt->pkt.signature->keyid[0]
+ && node->pkt->pkt.signature->keyid[1]
+ == onode->pkt->pkt.signature->keyid[1] ) {
+ found = 1;
+ break;
+ }
+ }
+ if( !found ) {
+ KBNODE n2 = clone_kbnode(node);
+ insert_kbnode( keyblock_orig, n2, 0 );
+ n2->flag |= 1;
+ node->flag |= 1;
+ log_info("%s: key %08lX, added revocation certificate\n",
+ fname, (ulong)keyid[1]);
+ }
+ }
+ }
- /* first, try to merge new ones in */
- for(node_orig=keyblock_orig->next; node_orig; node_orig=node_orig->next ) {
- if( !(node_orig->flag & 1) && node_orig->pkt->pkttype == PKT_USER_ID) {
+ /* 2nd: try to merge new ones 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 */
for(node=keyblock->next; node; node=node->next )
if( !(node->flag & 1)
&& node->pkt->pkttype == PKT_USER_ID
- && !cmp_user_ids( node_orig->pkt->pkt.user_id,
+ && !cmp_user_ids( onode->pkt->pkt.user_id,
node->pkt->pkt.user_id ) )
break;
if( node ) { /* found: merge */
- rc = merge_sigs( node_orig, node, n_sigs, fname, keyid );
+ rc = merge_sigs( onode, node, n_sigs, fname, keyid );
if( rc )
return rc;
}
}
}
- /* second, add new user-ids */
+ /* 3rd: add new user-ids */
for(node=keyblock->next; node; node=node->next ) {
if( !(node->flag & 1) && node->pkt->pkttype == PKT_USER_ID) {
/* do we have this in the original keyblock */
- for(node_orig=keyblock_orig->next; node_orig;
- node_orig=node_orig->next )
- if( !(node_orig->flag & 1)
- && node_orig->pkt->pkttype == PKT_USER_ID
- && cmp_user_ids( node_orig->pkt->pkt.user_id,
+ for(onode=keyblock_orig->next; onode; onode=onode->next )
+ if( !(onode->flag & 1)
+ && onode->pkt->pkttype == PKT_USER_ID
+ && cmp_user_ids( onode->pkt->pkt.user_id,
node->pkt->pkt.user_id ) )
break;
if( !node ) { /* this is a new user id: append */
diff --git a/g10/keygen.c b/g10/keygen.c
index f0cbda3d0..96a867c1e 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -154,7 +154,6 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
skc->timestamp = pkc->timestamp = make_timestamp();
skc->valid_days = pkc->valid_days = 0; /* fixme: make it configurable*/
skc->pubkey_algo = pkc->pubkey_algo = PUBKEY_ALGO_ELGAMAL;
- memset(&pkc->mfx, 0, sizeof pkc->mfx);
pkc->d.elg.p = pk.p;
pkc->d.elg.g = pk.g;
pkc->d.elg.y = pk.y;
diff --git a/g10/mainproc.c b/g10/mainproc.c
index f2b50ac9d..2bbe7418c 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -265,11 +265,8 @@ do_check_sig( CTX c, KBNODE node )
assert( node->pkt->pkttype == PKT_SIGNATURE );
sig = node->pkt->pkt.signature;
- if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
- algo = sig->d.elg.digest_algo;
- else if(sig->pubkey_algo == PUBKEY_ALGO_RSA )
- algo = sig->d.rsa.digest_algo;
- else
+ algo = digest_algo_from_sig( sig );
+ if( !algo )
return G10ERR_PUBKEY_ALGO;
if( (rc=check_digest_algo(algo)) )
return rc;
@@ -282,24 +279,36 @@ do_check_sig( CTX c, KBNODE node )
* in canonical mode ??? (calculating both modes???) */
md = md_copy( c->mfx.md );
}
- else if( (sig->sig_class&~3) == 0x10 ) { /* classes 0x10 .. 0x13 */
+ else if( (sig->sig_class&~3) == 0x10
+ || sig->sig_class == 0x20
+ || sig->sig_class == 0x30 ) { /* classes 0x10..0x13,0x20,0x30 */
if( c->list->pkt->pkttype == PKT_PUBLIC_CERT ) {
- KBNODE n1 = find_prev_kbnode( c->list, node, PKT_USER_ID );
-
- if( n1 ) {
- if( c->list->pkt->pkt.public_cert->mfx.md )
- md = md_copy( c->list->pkt->pkt.public_cert->mfx.md );
- else
- BUG();
- md_write( md, n1->pkt->pkt.user_id->name, n1->pkt->pkt.user_id->len);
+ #if 0
+ KBNODE n1;
+
+ if( sig->sig_class == 0x20 ) {
+ md = md_open( algo, 0 );
+ hash_public_cert( md, c->list->pkt->pkt.public_cert );
+ }
+ else if( (n1=find_prev_kbnode( c->list, node, PKT_USER_ID )) ) {
+ md = md_open( algo, 0 );
+ hash_public_cert( md, c->list->pkt->pkt.public_cert );
+ if( sig->sig_class != 0x20 )
+ md_write( md, n1->pkt->pkt.user_id->name,
+ n1->pkt->pkt.user_id->len);
}
else {
- log_error("invalid parent packet for sigclass 0x10\n");
+ log_error("invalid parent packet for sigclass %02x\n",
+ sig->sig_class);
return G10ERR_SIG_CLASS;
}
+ #endif
+
+ return check_key_signature( c->list, node, NULL );
}
else {
- log_error("invalid root packet for sigclass 0x10\n");
+ log_error("invalid root packet for sigclass %02x\n",
+ sig->sig_class);
return G10ERR_SIG_CLASS;
}
}
@@ -374,7 +383,13 @@ list_node( CTX c, KBNODE node )
datestr_from_pkc( pkc ) );
/* and now list all userids with their signatures */
for( node = node->next; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_USER_ID ) {
+ if( any != 2 && node->pkt->pkttype == PKT_SIGNATURE ) {
+ if( !any )
+ putchar('\n');
+ list_node(c, node );
+ any = 1;
+ }
+ else if( node->pkt->pkttype == PKT_USER_ID ) {
KBNODE n;
if( any )
@@ -389,10 +404,10 @@ list_node( CTX c, KBNODE node )
if( n->pkt->pkttype == PKT_SIGNATURE )
list_node(c, n );
}
- any=1;
+ any=2;
}
}
- if( !any )
+ if( any != 2 )
printf("ERROR: no user id!\n");
}
else if( node->pkt->pkttype == PKT_SECRET_CERT ) {
@@ -423,7 +438,10 @@ list_node( CTX c, KBNODE node )
if( !opt.list_sigs )
return;
- fputs("sig", stdout);
+ if( sig->sig_class == 0x20 || sig->sig_class == 0x30 )
+ fputs("rev", stdout);
+ else
+ fputs("sig", stdout);
if( opt.check_sigs ) {
fflush(stdout);
switch( (rc2=do_check_sig( c, node )) ) {
diff --git a/g10/packet.h b/g10/packet.h
index 98015a365..c41f32006 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -99,7 +99,6 @@ typedef struct {
byte hdrbytes; /* number of header bytes */
byte version;
byte pubkey_algo; /* algorithm used for public key scheme */
- md_filter_context_t mfx;
ulong local_id; /* internal use, valid if > 0 */
union {
struct {
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 0e13f6d18..b50c584bd 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -592,14 +592,6 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
unsigned short valid_period;
int is_v4=0;
- if( pkttype == PKT_PUBLIC_CERT ) {
- pkt->pkt.public_cert->mfx.md = md_open(DIGEST_ALGO_MD5, 0);
- md_enable(pkt->pkt.public_cert->mfx.md, DIGEST_ALGO_RMD160);
- md_enable(pkt->pkt.public_cert->mfx.md, DIGEST_ALGO_SHA1);
- pkt->pkt.public_cert->mfx.maxbuf_size = 1;
- md_write(pkt->pkt.public_cert->mfx.md, hdr, hdrlen);
- iobuf_push_filter( inp, md_filter, &pkt->pkt.public_cert->mfx );
- }
if( pktlen < 12 ) {
log_error("packet(%d) too short\n", pkttype);
@@ -765,8 +757,6 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
leave:
- if( pkttype == PKT_PUBLIC_CERT )
- iobuf_pop_filter( inp, md_filter, &pkt->pkt.public_cert->mfx );
skip_rest(inp, pktlen);
return 0;
}
diff --git a/g10/pkclist.c b/g10/pkclist.c
index f123fc0d8..cd453323f 100644
--- a/g10/pkclist.c
+++ b/g10/pkclist.c
@@ -167,7 +167,24 @@ do_we_trust( PKT_public_cert *pkc, int trustlevel )
{
int rc;
- switch( trustlevel ) {
+ if( (trustlevel & TRUST_FLAG_REVOKED) ) {
+ char *answer;
+ int yes;
+
+ log_info("key has beed revoked!\n");
+ if( opt.batch )
+ return 0;
+
+ answer = tty_get("Use this key anyway? ");
+ tty_kill_prompt();
+ yes = answer_is_yes(answer);
+ m_free(answer);
+ if( !yes )
+ return 0;
+ }
+
+
+ switch( (trustlevel & TRUST_MASK) ) {
case TRUST_UNKNOWN: /* No pubkey in trustDB: Insert and check again */
rc = insert_trust_record( pkc );
if( rc ) {
@@ -184,7 +201,7 @@ do_we_trust( PKT_public_cert *pkc, int trustlevel )
return do_we_trust( pkc, trustlevel );
case TRUST_EXPIRED:
- log_error("trust has expired: NOT yet implemented\n");
+ log_info("trust has expired: NOT yet implemented\n");
return 0; /* no */
case TRUST_UNDEFINED:
diff --git a/g10/revoke.c b/g10/revoke.c
index 2a8c5fc5c..59d866b92 100644
--- a/g10/revoke.c
+++ b/g10/revoke.c
@@ -152,6 +152,7 @@ gen_revoke( const char *uname )
}
afx.what = 1;
+ afx.hdrlines = "Comment: A revocation certificate should follow\n";
iobuf_push_filter( out, armor_filter, &afx );
if( opt.compress )
iobuf_push_filter( out, compress_filter, &zfx );
diff --git a/g10/sig-check.c b/g10/sig-check.c
index 4615c46e0..360a184c8 100644
--- a/g10/sig-check.c
+++ b/g10/sig-check.c
@@ -183,7 +183,9 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest )
/****************
- * check the signature pointed to by NODE. This is a key signatures
+ * check the signature pointed to by NODE. This is a key signatures.
+ * If the function detects a elf signature, it uses the PKC from
+ * NODE and does not read the any public key.
*/
int
check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
@@ -198,7 +200,6 @@ check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
if( is_selfsig )
*is_selfsig = 0;
assert( node->pkt->pkttype == PKT_SIGNATURE );
- assert( (node->pkt->pkt.signature->sig_class&~3) == 0x10 );
assert( root->pkt->pkttype == PKT_PUBLIC_CERT );
pkc = root->pkt->pkt.public_cert;
@@ -213,27 +214,36 @@ check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
if( (rc=check_digest_algo(algo)) )
return rc;
- unode = find_prev_kbnode( root, node, PKT_USER_ID );
-
- if( unode ) {
- PKT_user_id *uid = unode->pkt->pkt.user_id;
-
- if( is_selfsig ) {
- u32 keyid[2];
-
- keyid_from_pkc( pkc, keyid );
- if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
- *is_selfsig = 1;
- }
+ if( sig->sig_class == 0x20 ) {
md = md_open( algo, 0 );
hash_public_cert( md, pkc );
- md_write( md, uid->name, uid->len );
rc = do_check( pkc, sig, md );
md_close(md);
}
else {
- log_error("no user id for key signature packet\n");
- rc = G10ERR_SIG_CLASS;
+ unode = find_prev_kbnode( root, node, PKT_USER_ID );
+
+ if( unode ) {
+ PKT_user_id *uid = unode->pkt->pkt.user_id;
+ u32 keyid[2];
+
+ keyid_from_pkc( pkc, keyid );
+ md = md_open( algo, 0 );
+ hash_public_cert( md, pkc );
+ md_write( md, uid->name, uid->len );
+ if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) {
+ if( is_selfsig )
+ *is_selfsig = 1;
+ rc = do_check( pkc, sig, md );
+ }
+ else
+ rc = signature_check( sig, md );
+ md_close(md);
+ }
+ else {
+ log_error("no user id for key signature packet\n");
+ rc = G10ERR_SIG_CLASS;
+ }
}
return rc;
diff --git a/g10/sign.c b/g10/sign.c
index 2bf3045fc..0cbcbd3a2 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -987,6 +987,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc,
assert( (sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x20 );
md = md_open( digest_algo, 0 );
+
/* hash the public key certificate and the user id */
hash_public_cert( md, pkc );
if( sigclass != 0x20 )
diff --git a/g10/trustdb.c b/g10/trustdb.c
index 0c2620a95..836f9806d 100644
--- a/g10/trustdb.c
+++ b/g10/trustdb.c
@@ -380,8 +380,10 @@ dump_record( ulong rnum, TRUSTREC *rec, FILE *fp )
fputs(", (none)", fp );
else if( rec->r.dir.no_sigs == 2 )
fputs(", (invalid)", fp );
- else if( rec->r.dir.no_sigs )
+ else if( rec->r.dir.no_sigs == 3 )
fputs(", (revoked)", fp );
+ else if( rec->r.dir.no_sigs )
+ fputs(", (??)", fp );
putc('\n', fp);
break;
case RECTYPE_KEY: fprintf(fp, "key keyid=%08lX, own=%lu, ownertrust=%02x\n",
@@ -1084,17 +1086,19 @@ do_list_path( TRUST_INFO *stack, int depth, int max_depth,
* some of them are bad?
*/
static int
-check_sigs( KBNODE keyblock, int *selfsig_okay )
+check_sigs( KBNODE keyblock, int *selfsig_okay, int *revoked )
{
- KBNODE kbctx;
KBNODE node;
int rc;
LOCAL_ID_INFO *dups = NULL;
*selfsig_okay = 0;
- for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx,0)) ; ) {
+ *revoked = 0;
+ for( node=keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_SIGNATURE
- && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
+ && ( (node->pkt->pkt.signature->sig_class&~3) == 0x10
+ || node->pkt->pkt.signature->sig_class == 0x20
+ || node->pkt->pkt.signature->sig_class == 0x30) ) {
int selfsig;
rc = check_key_signature( keyblock, node, &selfsig );
if( !rc ) {
@@ -1106,13 +1110,18 @@ check_sigs( KBNODE keyblock, int *selfsig_okay )
node->flag |= 2; /* mark signature valid */
*selfsig_okay = 1;
}
+ else if( node->pkt->pkt.signature->sig_class == 0x20 )
+ *revoked = 1;
else
node->flag |= 1; /* mark signature valid */
- if( !dups )
- dups = new_lid_table();
- if( ins_lid_table_item( dups,
- node->pkt->pkt.signature->local_id, 0) )
- node->flag |= 4; /* mark as duplicate */
+
+ if( node->pkt->pkt.signature->sig_class != 0x20 ) {
+ if( !dups )
+ dups = new_lid_table();
+ if( ins_lid_table_item( dups,
+ node->pkt->pkt.signature->local_id, 0) )
+ node->flag |= 4; /* mark as duplicate */
+ }
}
if( DBG_TRUST )
log_debug("trustdb: sig from %08lX(%lu): %s%s\n",
@@ -1138,10 +1147,9 @@ build_sigrecs( ulong pubkeyid )
PUBKEY_FIND_INFO finfo=NULL;
KBPOS kbpos;
KBNODE keyblock = NULL;
- KBNODE kbctx;
KBNODE node;
int rc=0;
- int i, selfsig;
+ int i, selfsig, revoked;
ulong rnum, rnum2;
ulong first_sigrec = 0;
@@ -1173,7 +1181,7 @@ build_sigrecs( ulong pubkeyid )
goto leave;
}
/* check all key signatures */
- rc = check_sigs( keyblock, &selfsig );
+ rc = check_sigs( keyblock, &selfsig, &revoked );
if( rc ) {
log_error("build_sigrecs: check_sigs failed\n" );
goto leave;
@@ -1184,7 +1192,12 @@ build_sigrecs( ulong pubkeyid )
rc = G10ERR_BAD_CERT;
goto leave;
}
- update_no_sigs( pubkeyid, 0 ); /* assume we have sigs */
+ if( revoked ) {
+ log_info("build_sigrecs: key has been revoked\n" );
+ update_no_sigs( pubkeyid, 3 );
+ }
+ else
+ update_no_sigs( pubkeyid, 0 ); /* assume we have sigs */
/* valid key signatures are now marked; we can now build the
* sigrecs */
@@ -1192,7 +1205,7 @@ build_sigrecs( ulong pubkeyid )
rec.rectype = RECTYPE_SIG;
i = 0;
rnum = rnum2 = 0;
- for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
+ for( node=keyblock; node; node = node->next ) {
/* insert sigs which are not a selfsig nor a duplicate */
if( (node->flag & 1) && !(node->flag & 4) ) {
assert( node->pkt->pkttype == PKT_SIGNATURE );
@@ -1272,7 +1285,7 @@ build_sigrecs( ulong pubkeyid )
}
}
else
- update_no_sigs( pubkeyid, 1 ); /* no signatures */
+ update_no_sigs( pubkeyid, revoked? 3:1 ); /* no signatures */
leave:
m_free( finfo );
@@ -1385,6 +1398,7 @@ do_check( ulong pubkeyid, TRUSTREC *dr, unsigned *trustlevel )
int marginal, fully;
int fully_needed = opt.completes_needed;
int marginal_needed = opt.marginals_needed;
+ unsigned tflags = 0;
assert( fully_needed > 0 && marginal_needed > 1 );
@@ -1400,10 +1414,14 @@ do_check( ulong pubkeyid, TRUSTREC *dr, unsigned *trustlevel )
if( !rc ) /* and read again */
rc = read_record( pubkeyid, dr, RECTYPE_DIR );
}
+
+ if( dr->r.dir.no_sigs == 3 )
+ tflags |= TRUST_FLAG_REVOKED;
+
if( !rc && !dr->r.dir.sigrec ) {
/* See wether this is our own key */
if( !qry_lid_table_flag( ultikey_table, pubkeyid, NULL ) ) {
- *trustlevel = TRUST_ULTIMATE;
+ *trustlevel = tflags | TRUST_ULTIMATE;
return 0;
}
else
@@ -1442,7 +1460,7 @@ do_check( ulong pubkeyid, TRUSTREC *dr, unsigned *trustlevel )
if( tsl->dup )
continue;
if( tsl->seg[0].trust == TRUST_ULTIMATE ) {
- *trustlevel = TRUST_ULTIMATE; /* our own key */
+ *trustlevel = tflags | TRUST_ULTIMATE; /* our own key */
break;
}
if( tsl->seg[0].trust == TRUST_FULLY ) {
@@ -1453,12 +1471,12 @@ do_check( ulong pubkeyid, TRUSTREC *dr, unsigned *trustlevel )
marginal++;
if( fully >= fully_needed ) {
- *trustlevel = TRUST_FULLY;
+ *trustlevel = tflags | TRUST_FULLY;
break;
}
}
if( !tsl && marginal >= marginal_needed )
- *trustlevel = TRUST_MARGINAL;
+ *trustlevel = tflags | TRUST_MARGINAL;
/* cache the tslist */
if( last_trust_web_key ) {
diff --git a/g10/trustdb.h b/g10/trustdb.h
index 5eb52c9a2..48f006e76 100644
--- a/g10/trustdb.h
+++ b/g10/trustdb.h
@@ -22,14 +22,17 @@
#define G10_TRUSTDB_H
-/* Trust values mus be sorted in ascending order */
+/* Trust values must be sorted in ascending order */
+#define TRUST_MASK 15
#define TRUST_UNKNOWN 0 /* not yet calculated */
#define TRUST_EXPIRED 1 /* calculation may be invalid */
#define TRUST_UNDEFINED 2 /* not enough informations for calculation */
-#define TRUST_NEVER 3 /* never trusted this pubkey */
+#define TRUST_NEVER 3 /* never trust this pubkey */
#define TRUST_MARGINAL 4 /* marginally trusted */
#define TRUST_FULLY 5 /* fully trusted */
#define TRUST_ULTIMATE 6 /* ultimately trusted */
+/* trust values not covered by the mask */
+#define TRUST_FLAG_REVOKED 32
/*-- trustdb.c --*/