From 60f384592144de53c9a5f5e11d7f73ce863aa94f Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 12 Apr 2019 11:11:09 +0200 Subject: [PATCH] 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 --- g10/keyid.c | 118 ++++++++++++++++++++------------------------------- g10/packet.h | 3 ++ 2 files changed, 50 insertions(+), 71 deletions(-) diff --git a/g10/keyid.c b/g10/keyid.c index 45454f056..7605cb386 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -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; } diff --git a/g10/packet.h b/g10/packet.h index 41dd1a95a..d05a8f0f2 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -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 {