added revcation stuff and fixed a couple of bugs
authorWerner Koch <wk@gnupg.org>
Wed, 18 Feb 1998 13:58:46 +0000 (13:58 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 18 Feb 1998 13:58:46 +0000 (13:58 +0000)
24 files changed:
NEWS
cipher/ChangeLog
cipher/md.c
cipher/md.h
doc/DETAILS
g10/ChangeLog
g10/Makefile.in
g10/armor.c
g10/build-packet.c
g10/filter.h
g10/free-packet.c
g10/g10.c
g10/import.c
g10/keygen.c
g10/mainproc.c
g10/packet.h
g10/parse-packet.c
g10/pkclist.c
g10/revoke.c
g10/sig-check.c
g10/sign.c
g10/trustdb.c
g10/trustdb.h
zlib/Makefile.am

diff --git a/NEWS b/NEWS
index 882670e..f875e33 100644 (file)
--- 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
 -----------------------------------
index e915c3b..29626e5 100644 (file)
@@ -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
index 4608396..fbae097 100644 (file)
 #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 );
index fc5d28d..5903946 100644 (file)
@@ -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;
 
 
index 7455a38..dc3e554 100644 (file)
@@ -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.
+
index 414b051..6be3105 100644 (file)
@@ -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 .."
index 953b13b..318423c 100644 (file)
@@ -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
index 03a393b..1fc8ae0 100644 (file)
@@ -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;
index 2e1a483..b032a67 100644 (file)
@@ -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);
 }
 
index 93e72ce..965b75b 100644 (file)
@@ -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;
 
 
index f2467a7..9152f90 100644 (file)
@@ -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;
 }
 
index f9ae0fc..4339557 100644 (file)
--- 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. */
index 43e6423..fa08e86 100644 (file)
@@ -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 */
index f0cbda3..96a867c 100644 (file)
@@ -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;
index f2b50ac..2bbe741 100644 (file)
@@ -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 )) ) {
index 98015a3..c41f320 100644 (file)
@@ -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 {
index 0e13f6d..b50c584 100644 (file)
@@ -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;
 }
index f123fc0..cd45332 100644 (file)
@@ -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:
index 2a8c5fc..59d866b 100644 (file)
@@ -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 );
index 4615c46..360a184 100644 (file)
@@ -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;
index 2bf3045..0cbcbd3 100644 (file)
@@ -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 )
index 0c2620a..836f980 100644 (file)
@@ -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 ) {
index 5eb52c9..48f006e 100644 (file)
 #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 --*/
index 2d2d749..2f2f65a 100644 (file)
@@ -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