gpg: Cache a once computed fingerprint in PKT_public_key.

* g10/packet.h (PKT_public_key): Add fields fpr and fprlen.
* g10/keyid.c (do_fingerprint_md): Remove.
(compute_fingerprint): New.
(keyid_from_pk): Simplify.
(fingerprint_from_pk): Simplify.
(hexfingerprint): Avoid using extra array.
--

This is similar to what we are doing with the keyid for a long time.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2019-04-12 11:11:09 +02:00
parent 1b1f649dea
commit 60f3845921
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 50 additions and 71 deletions

View File

@ -253,20 +253,6 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
}
static gcry_md_hd_t
do_fingerprint_md( PKT_public_key *pk )
{
gcry_md_hd_t md;
if (gcry_md_open (&md, pk->version == 5 ? GCRY_MD_SHA256 : GCRY_MD_SHA1, 0))
BUG ();
hash_public_key (md,pk);
gcry_md_final (md);
return md;
}
/* fixme: Check whether we can replace this function or if not
describe why we need it. */
u32
@ -520,6 +506,37 @@ keystr_from_desc(KEYDB_SEARCH_DESC *desc)
}
/* Compute the fingerprint and keyid and store it in PK. */
static void
compute_fingerprint (PKT_public_key *pk)
{
const byte *dp;
gcry_md_hd_t md;
size_t len;
if (gcry_md_open (&md, pk->version == 5 ? GCRY_MD_SHA256 : GCRY_MD_SHA1, 0))
BUG ();
hash_public_key (md, pk);
gcry_md_final (md);
dp = gcry_md_read (md, 0);
len = gcry_md_get_algo_dlen (gcry_md_get_algo (md));
log_assert (len <= MAX_FINGERPRINT_LEN);
memcpy (pk->fpr, dp, len);
pk->fprlen = len;
if (pk->version == 5)
{
pk->keyid[0] = buf32_to_u32 (dp);
pk->keyid[1] = buf32_to_u32 (dp+4);
}
else
{
pk->keyid[0] = buf32_to_u32 (dp+12);
pk->keyid[1] = buf32_to_u32 (dp+16);
}
gcry_md_close( md);
}
/*
* Get the keyid from the public key PK and store it at KEYID unless
* this is NULL. Returns the 32 bit short keyid.
@ -532,37 +549,11 @@ keyid_from_pk (PKT_public_key *pk, u32 *keyid)
if (!keyid)
keyid = dummy_keyid;
if( pk->keyid[0] || pk->keyid[1] )
{
keyid[0] = pk->keyid[0];
keyid[1] = pk->keyid[1];
}
else
{
const byte *dp;
gcry_md_hd_t md;
if (!pk->fprlen)
compute_fingerprint (pk);
md = do_fingerprint_md(pk);
if(md)
{
dp = gcry_md_read ( md, 0 );
if (pk->version == 5)
{
keyid[0] = buf32_to_u32 (dp);
keyid[1] = buf32_to_u32 (dp+4);
}
else
{
keyid[0] = buf32_to_u32 (dp+12);
keyid[1] = buf32_to_u32 (dp+16);
}
gcry_md_close (md);
pk->keyid[0] = keyid[0];
pk->keyid[1] = keyid[1];
}
else
pk->keyid[0] = pk->keyid[1] = keyid[0]= keyid[1] = 0xFFFFFFFF;
}
keyid[0] = pk->keyid[0];
keyid[1] = pk->keyid[1];
return keyid[1]; /*FIXME:shortkeyid ist different for v5*/
}
@ -805,6 +796,7 @@ colon_expirestr_from_sig (PKT_signature *sig)
}
/*
* Return a byte array with the fingerprint for the given PK/SK
* The length of the array is returned in ret_len. Caller must free
@ -813,31 +805,15 @@ colon_expirestr_from_sig (PKT_signature *sig)
byte *
fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
{
const byte *dp;
size_t len;
gcry_md_hd_t md;
if (!pk->fprlen)
compute_fingerprint (pk);
md = do_fingerprint_md (pk);
dp = gcry_md_read (md, 0);
len = gcry_md_get_algo_dlen (gcry_md_get_algo (md));
log_assert (len <= MAX_FINGERPRINT_LEN);
if (!array)
array = xmalloc ( len );
memcpy (array, dp, len );
if (pk->version == 5)
{
pk->keyid[0] = buf32_to_u32 (dp);
pk->keyid[1] = buf32_to_u32 (dp+4);
}
else
{
pk->keyid[0] = buf32_to_u32 (dp+12);
pk->keyid[1] = buf32_to_u32 (dp+16);
}
gcry_md_close( md);
array = xmalloc (pk->fprlen);
memcpy (array, pk->fpr, pk->fprlen);
if (ret_len)
*ret_len = len;
*ret_len = pk->fprlen;
return array;
}
@ -852,19 +828,19 @@ fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
char *
hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen)
{
unsigned char fpr[MAX_FINGERPRINT_LEN];
size_t len;
if (!pk->fprlen)
compute_fingerprint (pk);
fingerprint_from_pk (pk, fpr, &len);
if (!buffer)
{
buffer = xtrymalloc (2 * len + 1);
buffer = xtrymalloc (2 * pk->fprlen + 1);
if (!buffer)
return NULL;
}
else if (buflen < 2*len+1)
else if (buflen < 2 * pk->fprlen + 1)
log_fatal ("%s: buffer too short (%zu)\n", __func__, buflen);
bin2hex (fpr, len, buffer);
bin2hex (pk->fpr, pk->fprlen, buffer);
return buffer;
}

View File

@ -394,6 +394,7 @@ typedef struct
byte pubkey_algo;
byte pubkey_usage; /* for now only used to pass it to getkey() */
byte req_usage; /* hack to pass a request to getkey() */
byte fprlen; /* 0 or length of FPR. */
u32 has_expired; /* set to the expiration date if expired */
/* keyid of the primary key. Never access this value directly.
Instead, use pk_main_keyid(). */
@ -401,6 +402,8 @@ typedef struct
/* keyid of this key. Never access this value directly! Instead,
use pk_keyid(). */
u32 keyid[2];
/* Fingerprint of the key. Only valid if FPRLEN is not 0. */
byte fpr[MAX_FINGERPRINT_LEN];
prefitem_t *prefs; /* list of preferences (may be NULL) */
struct
{