summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>1998-02-18 14:58:46 +0100
committerWerner Koch <wk@gnupg.org>1998-02-18 14:58:46 +0100
commitb758180325b90184f7ac66267141cb5465c07a9f (patch)
tree69767c83c2ad2afd85db3cdbcb7489cc13c76123
parentimport works (diff)
downloadgnupg2-b758180325b90184f7ac66267141cb5465c07a9f.tar.xz
gnupg2-b758180325b90184f7ac66267141cb5465c07a9f.zip
added revcation stuff and fixed a couple of bugs
-rw-r--r--NEWS14
-rw-r--r--cipher/ChangeLog4
-rw-r--r--cipher/md.c23
-rw-r--r--cipher/md.h2
-rw-r--r--doc/DETAILS61
-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
-rw-r--r--zlib/Makefile.am2
24 files changed, 442 insertions, 118 deletions
diff --git a/NEWS b/NEWS
index 882670e45..f875e3399 100644
--- a/NEWS
+++ b/NEWS
@@ -1,11 +1,21 @@
Noteworthy changes in version 0.2.7
-----------------------------------
- * new option --dearmot for g10maint
+ * New command "gen-revoke" to create a key revocation certificate.
- * option --version now conforming to the GNU standards and lists
+ * New option "homedir" to set the homedir (which defaults to "~/.g10").
+ This directory is created if it does not exists (only the last
+ part of the name and not the complete hierarchy)
+
+ * Command "import" works. (Try: "finger gcrypt@ftp.guug.de|g10 --import")
+
+ * New commands "dearmor/enarmor" for g10maint. These are mainly
+ used for internal test purposes.
+
+ * Option --version now conforming to the GNU standards and lists
the available ciphers, message digests and public key algorithms.
+ * Assembler code for m68k (not tested).
Noteworthy changes in version 0.2.6
-----------------------------------
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index e915c3bcc..29626e55e 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,7 @@
+Wed Feb 18 14:08:30 1998 Werner Koch (wk@isil.d.shuttle.de)
+
+ * md.c, md.h : New debugging support
+
Mon Feb 16 10:08:47 1998 Werner Koch (wk@isil.d.shuttle.de)
* misc.c (cipher_algo_to_string): New
diff --git a/cipher/md.c b/cipher/md.c
index 46083960f..fbae09765 100644
--- a/cipher/md.c
+++ b/cipher/md.c
@@ -27,10 +27,6 @@
#include "cipher.h"
#include "errors.h"
-
-
-/*static FILE *dumpfp;*/
-
/****************
* Open a message digest handle for use with algorithm ALGO.
* More algorithms may be added by md_enable(). The initial algorithm
@@ -41,13 +37,6 @@ md_open( int algo, int secure )
{
MD_HANDLE hd;
- #if 0
- if( !dumpfp )
- dumpfp = fopen("md.out", "w");
- if( !dumpfp )
- BUG();
- { int i; for(i=0; i < 16; i++ ) putc('\xff', dumpfp ); }
- #endif
hd = secure ? m_alloc_secure_clear( sizeof *hd )
: m_alloc_clear( sizeof *hd );
hd->secure = secure;
@@ -81,7 +70,6 @@ md_copy( MD_HANDLE a )
{
MD_HANDLE b;
- /*{ int i; for(i=0; i < 16; i++ ) putc('\xee', dumpfp ); }*/
b = a->secure ? m_alloc_secure( sizeof *b )
: m_alloc( sizeof *b );
memcpy( b, a, sizeof *a );
@@ -101,10 +89,12 @@ md_close(MD_HANDLE a)
void
md_write( MD_HANDLE a, byte *inbuf, size_t inlen)
{
- /* if( a->bufcount && fwrite(a->buffer, a->bufcount, 1, dumpfp ) != 1 )
- BUG();
- if( inlen && fwrite(inbuf, inlen, 1, dumpfp ) != 1 )
- BUG(); */
+ if( a->debug ) {
+ if( a->bufcount && fwrite(a->buffer, a->bufcount, 1, a->debug ) != 1 )
+ BUG();
+ if( inlen && fwrite(inbuf, inlen, 1, a->debug ) != 1 )
+ BUG();
+ }
if( a->use_rmd160 ) {
rmd160_write( &a->rmd160, a->buffer, a->bufcount );
rmd160_write( &a->rmd160, inbuf, inlen );
@@ -127,7 +117,6 @@ md_final(MD_HANDLE a)
{
if( a->bufcount )
md_write( a, NULL, 0 );
- /*{ int i; for(i=0; i < 16; i++ ) putc('\xcc', dumpfp ); }*/
if( a->use_rmd160 ) {
byte *p;
rmd160_final( &a->rmd160 );
diff --git a/cipher/md.h b/cipher/md.h
index fc5d28df6..5903946c2 100644
--- a/cipher/md.h
+++ b/cipher/md.h
@@ -20,6 +20,7 @@
#ifndef G10_MD_H
#define G10_MD_H
+#include <stdio.h>
#include "types.h"
#include "rmd.h"
#include "sha1.h"
@@ -37,6 +38,7 @@ typedef struct {
byte buffer[MD_BUFFER_SIZE]; /* primary buffer */
int bufcount;
int secure;
+ FILE *debug;
} *MD_HANDLE;
diff --git a/doc/DETAILS b/doc/DETAILS
index 7455a38bf..dc3e55421 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -6,6 +6,10 @@
a rmd160 hash value from it. This is used as the
fingerprint and the low 64 bits are the keyid.
+ * Revocation certificates consists only of the signature packet;
+ "import" knows how to handle this. The rationale behind it is
+ to keep them small.
+
@@ -162,7 +166,7 @@ Record Type 6 (hash table)
if this is not the correct dir record, we look at the next
dir record which is linked by the link field.
-Record type 7 (hast list)
+Record type 7 (hash list)
-------------
see hash table for an explanation.
@@ -175,3 +179,58 @@ Record type 7 (hast list)
For the current record length of 40, n is 6
+
+
+
+Packet Headers
+===============
+
+G10 uses PGP 2 packet headers and also understand OpenPGP packet header.
+There is one enhavement used ith the old style packet headers:
+
+ CTB bits 10, the "packet-length length bits", have values listed in
+ the following table:
+
+ 00 - 1-byte packet-length field
+ 01 - 2-byte packet-length field
+ 10 - 4-byte packet-length field
+ 11 - no packet length supplied, unknown packet length
+
+ As indicated in this table, depending on the packet-length length
+ bits, the remaining 1, 2, 4, or 0 bytes of the packet structure field
+ are a "packet-length field". The packet-length field is a whole
+ number field. The value of the packet-length field is defined to be
+ the value of the whole number field.
+
+ A value of 11 is currently used in one place: on compressed data.
+ That is, a compressed data block currently looks like <A3 01 . . .>,
+ where <A3>, binary 10 1000 11, is an indefinite-length packet. The
+ proper interpretation is "until the end of the enclosing structure",
+ although it should never appear outermost (where the enclosing
+ structure is a file).
+
++ This will be changed with another version, where the new meaning of
++ the value 11 (see below) will also take place.
++
++ A value of 11 for other packets enables a special length encoding,
++ which is used in case, where the length of the following packet can
++ not be determined prior to writing the packet; especially this will
++ be used if large amounts of data are processed in filter mode.
++
++ It works like this: After the CTB (with a length field of 11) a
++ marker field is used, which gives the length of the following datablock.
++ This is a simple 2 byte field (MSB first) containig the amount of data
++ following this field, not including this length field. After this datablock
++ another length field follows, which gives the size of the next datablock.
++ A value of 0 indicates the end of the packet. The maximum size of a
++ data block is limited to 65534, thereby reserving a value of 0xffff for
++ future extensions. These length markers must be insereted into the data
++ stream just before writing the data out.
++
++ This 2 byte filed is large enough, because the application must buffer
++ this amount of data to prepend the length marker before writing it out.
++ Data block sizes larger than about 32k doesn't make any sense. Note
++ that this may also be used for compressed data streams, but we must use
++ another packet version to tell the application that it can not assume,
++ that this is the last packet.
+
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 (wk@isil.d.shuttle.de)
+
+ * 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 (wk@isil.d.shuttle.de)
+
+ * trustdb.c (do_check): Add handling for revocation certificates.
+ (build_sigrecs): Ditto.
+ (check_sigs): Ditto.
+
+Wed Feb 18 09:31:04 1998 Werner Koch (wk@isil.d.shuttle.de)
+
+ * 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 (wk@isil.d.shuttle.de)
* 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 --*/
diff --git a/zlib/Makefile.am b/zlib/Makefile.am
index 2d2d749df..2f2f65a29 100644
--- a/zlib/Makefile.am
+++ b/zlib/Makefile.am
@@ -5,7 +5,7 @@
CFLAGS = -O -Wall
-EXTRA_DIST = README algorithm.doc ChangeLog example.c
+EXTRA_DIST = README algorithm.doc ChangeLog example.c
# I found no other easy way to use this only if zlib is neede
# doing this with SUBDIR = @xxx@ in the top Makefile.am does not