aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--g10/ChangeLog23
-rw-r--r--g10/build-packet.c79
-rw-r--r--g10/getkey.c17
-rw-r--r--g10/import.c4
-rw-r--r--g10/keydb.h5
-rw-r--r--g10/keyid.c112
-rw-r--r--g10/packet.h5
7 files changed, 105 insertions, 140 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 723196857..07cc6f5a2 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,26 @@
+2003-12-10 David Shaw <[email protected]>
+
+ * packet.h, build-packet.c (hash_public_key): Remove function ...
+
+ * keydb.h, keyid.c (hash_public_key, do_fingerprint_md): ... and
+ make a new one here that shares code with the fingerprint
+ calculations. This removes some duplicated functionality, and is
+ also around 14% faster. (Every bit helps).
+
+ * import.c (import_one): No longer need the Elgamal import
+ warning.
+
+ * getkey.c (get_pubkey_fast): This one is sort of obscure.
+ get_pubkey_fast returns the primary key when requesting a subkey,
+ so if a user has a key signed by a subkey (we don't do this, but
+ used to), AND that key is not self-signed, AND the algorithm of
+ the subkey in question is not present in GnuPG, AND the algorithm
+ of the primary key that owns the subkey in question is present in
+ GnuPG, then we will try and verify the subkey signature using the
+ primary key algorithm and hit a BUG(). The fix is to not return a
+ hit if the keyid is not the primary. All other users of
+ get_pubkey_fast already expect a primary only.
+
2003-12-09 David Shaw <[email protected]>
* keyid.c (do_fingerprint_md): Remove the rules to hash the old v3
diff --git a/g10/build-packet.c b/g10/build-packet.c
index cd0bb8a81..c1022fff5 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -254,85 +254,6 @@ do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
}
-/****************
- * Make a hash value from the public key certificate
- */
-void
-hash_public_key( MD_HANDLE md, PKT_public_key *pk )
-{
- PACKET pkt;
- int rc = 0;
- int ctb;
- ulong pktlen;
- int c;
- IOBUF a = iobuf_temp();
-#if 0
- FILE *fp = fopen("dump.pk", "a");
- int i=0;
-
- fprintf(fp, "\nHashing PK (v%d):\n", pk->version);
-#endif
-
- /* build the packet */
- init_packet(&pkt);
- pkt.pkttype = PKT_PUBLIC_KEY;
- pkt.pkt.public_key = pk;
- if( (rc = build_packet( a, &pkt )) )
- log_fatal("build public_key for hashing failed: %s\n", g10_errstr(rc));
-
- if( !(pk->version == 3 && pk->pubkey_algo == 16) ) {
- /* skip the constructed header but don't do this for our very old
- * v3 ElG keys */
- ctb = iobuf_get_noeof(a);
- pktlen = 0;
- if( (ctb & 0x40) ) {
- c = iobuf_get_noeof(a);
- if( c < 192 )
- pktlen = c;
- else if( c < 224 ) {
- pktlen = (c - 192) * 256;
- c = iobuf_get_noeof(a);
- pktlen += c + 192;
- }
- else if( c == 255 ) {
- pktlen = iobuf_get_noeof(a) << 24;
- pktlen |= iobuf_get_noeof(a) << 16;
- pktlen |= iobuf_get_noeof(a) << 8;
- pktlen |= iobuf_get_noeof(a);
- }
- }
- else {
- int lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
- for( ; lenbytes; lenbytes-- ) {
- pktlen <<= 8;
- pktlen |= iobuf_get_noeof(a);
- }
- }
- /* hash a header */
- md_putc( md, 0x99 );
- pktlen &= 0xffff; /* can't handle longer packets */
- md_putc( md, pktlen >> 8 );
- md_putc( md, pktlen & 0xff );
- }
- /* hash the packet body */
- while( (c=iobuf_get(a)) != -1 ) {
-#if 0
- fprintf( fp," %02x", c );
- if( (++i == 24) ) {
- putc('\n', fp);
- i=0;
- }
-#endif
- md_putc( md, c );
- }
-#if 0
- putc('\n', fp);
- fclose(fp);
-#endif
- iobuf_cancel(a);
-}
-
-
static int
do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
{
diff --git a/g10/getkey.c b/g10/getkey.c
index 72b80ba76..7d437a07a 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -374,13 +374,15 @@ get_pubkey( PKT_public_key *pk, u32 *keyid )
/* Get a public key and store it into the allocated pk. This function
differs from get_pubkey() in that it does not do a check of the key
- to avoid recursion. It should be used only in very certain cases. */
+ to avoid recursion. It should be used only in very certain cases.
+ It will only retrieve primary keys. */
int
get_pubkey_fast (PKT_public_key *pk, u32 *keyid)
{
int rc = 0;
KEYDB_HANDLE hd;
KBNODE keyblock;
+ u32 pkid[2];
assert (pk);
#if MAX_PK_CACHE_ENTRIES
@@ -413,20 +415,25 @@ get_pubkey_fast (PKT_public_key *pk, u32 *keyid)
log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc));
return G10ERR_NO_PUBKEY;
}
-
+
assert ( keyblock->pkt->pkttype == PKT_PUBLIC_KEY
|| keyblock->pkt->pkttype == PKT_PUBLIC_SUBKEY );
- copy_public_key (pk, keyblock->pkt->pkt.public_key );
+
+ keyid_from_pk(keyblock->pkt->pkt.public_key,pkid);
+ if(keyid[0]==pkid[0] && keyid[1]==pkid[1])
+ copy_public_key (pk, keyblock->pkt->pkt.public_key );
+ else
+ rc=G10ERR_NO_PUBKEY;
+
release_kbnode (keyblock);
/* Not caching key here since it won't have all of the fields
properly set. */
- return 0;
+ return rc;
}
-
KBNODE
get_pubkeyblock( u32 *keyid )
{
diff --git a/g10/import.c b/g10/import.c
index c5bcb595c..d13357b6a 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -559,10 +559,6 @@ import_one( const char *fname, KBNODE keyblock,
keyid_from_pk( pk, keyid );
uidnode = find_next_kbnode( keyblock, PKT_USER_ID );
- if(pk->pubkey_algo==PUBKEY_ALGO_ELGAMAL)
- log_info(_("key %08lX: Elgamal primary key -"
- " this may take some time to import\n"),(ulong)keyid[1]);
-
if( opt.verbose && !opt.interactive ) {
log_info( "pub %4u%c/%08lX %s ",
nbits_from_pk( pk ),
diff --git a/g10/keydb.h b/g10/keydb.h
index 900d0267c..0d2a143a0 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -1,5 +1,5 @@
/* keydb.h - Key database
- * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -237,6 +237,7 @@ KEYDB_HANDLE get_ctx_handle(GETKEY_CTX ctx);
/*-- keyid.c --*/
int pubkey_letter( int algo );
+void hash_public_key( MD_HANDLE md, PKT_public_key *pk );
u32 keyid_from_sk( PKT_secret_key *sk, u32 *keyid );
u32 keyid_from_pk( PKT_public_key *pk, u32 *keyid );
u32 keyid_from_sig( PKT_signature *sig, u32 *keyid );
@@ -250,13 +251,11 @@ const char *datestr_from_sig( PKT_signature *sig );
const char *expirestr_from_pk( PKT_public_key *pk );
const char *expirestr_from_sk( PKT_secret_key *sk );
const char *expirestr_from_sig( PKT_signature *sig );
-
const char *colon_strtime (u32 t);
const char *colon_datestr_from_pk (PKT_public_key *pk);
const char *colon_datestr_from_sk (PKT_secret_key *sk);
const char *colon_datestr_from_sig (PKT_signature *sig);
const char *colon_expirestr_from_sig (PKT_signature *sig);
-
byte *fingerprint_from_sk( PKT_secret_key *sk, byte *buf, size_t *ret_len );
byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
diff --git a/g10/keyid.c b/g10/keyid.c
index 8641f7d94..3648e0579 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -47,59 +47,80 @@ pubkey_letter( int algo )
}
}
-static MD_HANDLE
-do_fingerprint_md( PKT_public_key *pk )
+/* This function is useful for v4 fingerprints and v3 or v4 key
+ signing. */
+void
+hash_public_key( MD_HANDLE md, PKT_public_key *pk )
{
- MD_HANDLE md;
- unsigned n=6;
- unsigned nb[PUBKEY_MAX_NPKEY];
- unsigned nn[PUBKEY_MAX_NPKEY];
- byte *pp[PUBKEY_MAX_NPKEY];
- int i;
- int npkey = pubkey_get_npkey( pk->pubkey_algo );
+ unsigned n=6;
+ unsigned nb[PUBKEY_MAX_NPKEY];
+ unsigned nn[PUBKEY_MAX_NPKEY];
+ byte *pp[PUBKEY_MAX_NPKEY];
+ int i;
+ int npkey = pubkey_get_npkey( pk->pubkey_algo );
+
+ /* Two extra bytes for the expiration date in v3 */
+ if(pk->version<4)
+ n+=2;
+
+ if(npkey==0 && pk->pkey[0] && mpi_is_opaque(pk->pkey[0]))
+ {
+ pp[0]=mpi_get_opaque(pk->pkey[0],&nn[0]);
+ n+=nn[0];
+ }
+ else
+ for(i=0; i < npkey; i++ )
+ {
+ nb[i] = mpi_get_nbits(pk->pkey[i]);
+ pp[i] = mpi_get_buffer( pk->pkey[i], nn+i, NULL );
+ n += 2 + nn[i];
+ }
+
+ md_putc( md, 0x99 ); /* ctb */
+ /* What does it mean if n is greater than than 0xFFFF ? */
+ md_putc( md, n >> 8 ); /* 2 byte length header */
+ md_putc( md, n );
+ md_putc( md, pk->version );
- md = md_open( DIGEST_ALGO_SHA1, 0);
+ md_putc( md, pk->timestamp >> 24 );
+ md_putc( md, pk->timestamp >> 16 );
+ md_putc( md, pk->timestamp >> 8 );
+ md_putc( md, pk->timestamp );
- if(npkey==0 && pk->pkey[0] && mpi_is_opaque(pk->pkey[0]))
+ if(pk->version<4)
+ {
+ u16 days=0;
+ if(pk->expiredate)
+ days=(u16)((pk->expiredate - pk->timestamp) / 86400L);
+
+ md_putc( md, days >> 8 );
+ md_putc( md, days );
+ }
+
+ md_putc( md, pk->pubkey_algo );
+
+ if(npkey==0 && pk->pkey[0] && mpi_is_opaque(pk->pkey[0]))
+ md_write(md,pp[0],nn[0]);
+ else
+ for(i=0; i < npkey; i++ )
{
- pp[0]=mpi_get_opaque(pk->pkey[0],&nn[0]);
- n+=nn[0];
+ md_putc( md, nb[i]>>8);
+ md_putc( md, nb[i] );
+ md_write( md, pp[i], nn[i] );
+ m_free(pp[i]);
}
- else
- for(i=0; i < npkey; i++ )
- {
- nb[i] = mpi_get_nbits(pk->pkey[i]);
- pp[i] = mpi_get_buffer( pk->pkey[i], nn+i, NULL );
- n += 2 + nn[i];
- }
+}
- md_putc( md, 0x99 ); /* ctb */
- /* What does it mean if n is greater than than 0xFFFF ? */
- md_putc( md, n >> 8 ); /* 2 byte length header */
- md_putc( md, n );
- md_putc( md, 4 );
-
- md_putc( md, pk->timestamp >> 24 );
- md_putc( md, pk->timestamp >> 16 );
- md_putc( md, pk->timestamp >> 8 );
- md_putc( md, pk->timestamp );
-
- md_putc( md, pk->pubkey_algo );
-
- if(npkey==0 && pk->pkey[0] && mpi_is_opaque(pk->pkey[0]))
- md_write(md,pp[0],nn[0]);
- else
- for(i=0; i < npkey; i++ )
- {
- md_putc( md, nb[i]>>8);
- md_putc( md, nb[i] );
- md_write( md, pp[i], nn[i] );
- m_free(pp[i]);
- }
+static MD_HANDLE
+do_fingerprint_md( PKT_public_key *pk )
+{
+ MD_HANDLE md;
- md_final( md );
+ md = md_open( DIGEST_ALGO_SHA1, 0);
+ hash_public_key(md,pk);
+ md_final( md );
- return md;
+ return md;
}
static MD_HANDLE
@@ -122,7 +143,6 @@ do_fingerprint_md_sk( PKT_secret_key *sk )
return do_fingerprint_md( &pk );
}
-
/****************
* Get the keyid from the secret key and put it into keyid
* if this is not NULL. Return the 32 low bits of the keyid.
diff --git a/g10/packet.h b/g10/packet.h
index d75ff413a..57306e6e7 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -1,6 +1,6 @@
/* packet.h - packet definitions
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
- * Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002,
+ * 2003 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -424,7 +424,6 @@ PACKET *create_gpg_control ( ctrlpkttype_t type,
/*-- build-packet.c --*/
int build_packet( IOBUF inp, PACKET *pkt );
u32 calc_packet_length( PACKET *pkt );
-void hash_public_key( MD_HANDLE md, PKT_public_key *pk );
void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
const byte *buffer, size_t buflen );
void build_sig_subpkt_from_sig( PKT_signature *sig );