added revcation stuff and fixed a couple of bugs

This commit is contained in:
Werner Koch 1998-02-18 13:58:46 +00:00
parent c8bb57d05d
commit b758180325
24 changed files with 441 additions and 117 deletions

14
NEWS
View File

@ -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
-----------------------------------

View 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

View File

@ -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 );

View 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;

View 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.

View 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 .."

View 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

View 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;

View 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);
}

View 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;

View 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;
}

View File

@ -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. */

View 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 );
@ -361,6 +376,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.
@ -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;
/* 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) {
/* 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]);
}
}
}
/* 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 */

View 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;

View 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 0
KBNODE n1;
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( 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 )) ) {

View 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 {

View 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;
}

View 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:

View 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 );

View 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;

View 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 )

View 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 ) {

View File

@ -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 --*/

View 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