diff --git a/g10/keydb.h b/g10/keydb.h index a6c70d682..5ef837be8 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -553,6 +553,7 @@ const char *colon_datestr_from_pk (PKT_public_key *pk); const char *colon_datestr_from_sig (PKT_signature *sig); const char *colon_expirestr_from_sig (PKT_signature *sig); byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len ); +void fpr20_from_pk (PKT_public_key *pk, byte array[20]); char *hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen); char *format_hexfingerprint (const char *fingerprint, char *buffer, size_t buflen); diff --git a/g10/keyid.c b/g10/keyid.c index 23712e2a4..caf2e4f6f 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -867,6 +867,38 @@ fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len) } +/* + * Get FPR20 for the given PK/SK into ARRAY. + * + * FPR20 is special form of fingerprint of length 20 for the record of + * trustdb. For v4key, having fingerprint with SHA-1, FPR20 is the + * same one. For v5key, FPR20 is constructed from its fingerprint + * with SHA-2, so that its kid of last 8-byte can be as same as + * kid of v5key fingerprint. + * + */ +void +fpr20_from_pk (PKT_public_key *pk, byte array[20]) +{ + if (!pk->fprlen) + compute_fingerprint (pk); + + if (!array) + array = xmalloc (pk->fprlen); + + if (pk->fprlen == 32) /* v5 fingerprint */ + { + memcpy (array + 0, pk->fpr + 20, 4); + memcpy (array + 4, pk->fpr + 24, 4); + memcpy (array + 8, pk->fpr + 28, 4); + memcpy (array + 12, pk->fpr + 0, 4); /* kid[0] */ + memcpy (array + 16, pk->fpr + 4, 4); /* kid[1] */ + } + else /* v4 fingerprint */ + memcpy (array, pk->fpr, 20); +} + + /* Return an allocated buffer with the fingerprint of PK formatted as * a plain hexstring. If BUFFER is NULL the result is a malloc'd * string. If BUFFER is not NULL the result will be copied into this diff --git a/g10/tdbio.c b/g10/tdbio.c index bfeede991..9f01667b4 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -1909,12 +1909,9 @@ tdbio_search_trust_byfpr (ctrl_t ctrl, const byte *fingerprint, TRUSTREC *rec) gpg_error_t tdbio_search_trust_bypk (ctrl_t ctrl, PKT_public_key *pk, TRUSTREC *rec) { - byte fingerprint[MAX_FINGERPRINT_LEN]; - size_t fingerlen; + byte fingerprint[20]; - fingerprint_from_pk( pk, fingerprint, &fingerlen ); - for (; fingerlen < 20; fingerlen++) - fingerprint[fingerlen] = 0; + fpr20_from_pk (pk, fingerprint); return tdbio_search_trust_byfpr (ctrl, fingerprint, rec); } diff --git a/g10/trustdb.c b/g10/trustdb.c index c4b996a96..4669ac0e8 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -39,6 +39,49 @@ #include "tofu.h" #include "key-clean.h" +static u32 +keyid_from_fpr20 (ctrl_t ctrl, const byte *fpr, u32 *keyid) +{ + u32 dummy_keyid[2]; + int fprlen; + + if( !keyid ) + keyid = dummy_keyid; + + /* Problem: We do only use fingerprints in the trustdb but + * we need the keyID here to indetify the key; we can only + * use that ugly hack to distinguish between 16 and 20 + * bytes fpr - it does not work always so we better change + * the whole validation code to only work with + * fingerprints */ + fprlen = (!fpr[16] && !fpr[17] && !fpr[18] && !fpr[19])? 16:20; + + if (fprlen != 20) + { + /* This is special as we have to lookup the key first. */ + PKT_public_key pk; + int rc; + + memset (&pk, 0, sizeof pk); + rc = get_pubkey_byfprint (ctrl, &pk, NULL, fpr, fprlen); + if (rc) + { + log_printhex (fpr, fprlen, + "Oops: keyid_from_fingerprint: no pubkey; fpr:"); + keyid[0] = 0; + keyid[1] = 0; + } + else + keyid_from_pk (&pk, keyid); + } + else + { + keyid[0] = buf32_to_u32 (fpr+12); + keyid[1] = buf32_to_u32 (fpr+16); + } + + return keyid[1]; +} typedef struct key_item **KeyHashTable; /* see new_key_hash_table() */ @@ -277,24 +320,15 @@ verify_own_keys (ctrl_t ctrl) /* scan the trustdb to find all ultimately trusted keys */ for (recnum=1; !tdbio_read_record (recnum, &rec, 0); recnum++ ) { - if ( rec.rectype == RECTYPE_TRUST - && (rec.r.trust.ownertrust & TRUST_MASK) == TRUST_ULTIMATE) + if (rec.rectype == RECTYPE_TRUST + && (rec.r.trust.ownertrust & TRUST_MASK) == TRUST_ULTIMATE) { - byte *fpr = rec.r.trust.fingerprint; - int fprlen; - u32 kid[2]; + u32 kid[2]; - /* Problem: We do only use fingerprints in the trustdb but - * we need the keyID here to indetify the key; we can only - * use that ugly hack to distinguish between 16 and 20 - * butes fpr - it does not work always so we better change - * the whole validation code to only work with - * fingerprints */ - fprlen = (!fpr[16] && !fpr[17] && !fpr[18] && !fpr[19])? 16:20; - keyid_from_fingerprint (ctrl, fpr, fprlen, kid); - if (!add_utk (kid)) - log_info(_("key %s occurs more than once in the trustdb\n"), - keystr(kid)); + keyid_from_fpr20 (ctrl, rec.r.trust.fingerprint, kid); + if (!add_utk (kid)) + log_info (_("key %s occurs more than once in the trustdb\n"), + keystr(kid)); } } @@ -779,15 +813,13 @@ tdb_update_ownertrust (ctrl_t ctrl, PKT_public_key *pk, unsigned int new_trust ) } else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) { /* no record yet - create a new one */ - size_t dummy; - if (DBG_TRUST) log_debug ("insert ownertrust %u\n", new_trust ); memset (&rec, 0, sizeof rec); rec.recnum = tdbio_new_recnum (ctrl); rec.rectype = RECTYPE_TRUST; - fingerprint_from_pk (pk, rec.r.trust.fingerprint, &dummy); + fpr20_from_pk (pk, rec.r.trust.fingerprint); rec.r.trust.ownertrust = new_trust; write_record (ctrl, &rec); tdb_revalidation_mark (ctrl); @@ -837,15 +869,13 @@ update_min_ownertrust (ctrl_t ctrl, u32 *kid, unsigned int new_trust) } else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) { /* no record yet - create a new one */ - size_t dummy; - if (DBG_TRUST) log_debug ("insert min_ownertrust %u\n", new_trust ); memset (&rec, 0, sizeof rec); rec.recnum = tdbio_new_recnum (ctrl); rec.rectype = RECTYPE_TRUST; - fingerprint_from_pk (pk, rec.r.trust.fingerprint, &dummy); + fpr20_from_pk (pk, rec.r.trust.fingerprint); rec.r.trust.min_ownertrust = new_trust; write_record (ctrl, &rec); tdb_revalidation_mark (ctrl); @@ -925,12 +955,10 @@ update_validity (ctrl_t ctrl, PKT_public_key *pk, PKT_user_id *uid, if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) { /* No record yet - create a new one. */ - size_t dummy; - memset (&trec, 0, sizeof trec); trec.recnum = tdbio_new_recnum (ctrl); trec.rectype = RECTYPE_TRUST; - fingerprint_from_pk (pk, trec.r.trust.fingerprint, &dummy); + fpr20_from_pk (pk, trec.r.trust.fingerprint); trec.r.trust.ownertrust = 0; }