From 2543f0ab9c7b4247347688863f898667bae31984 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 13 Oct 2014 11:45:34 +0200 Subject: [PATCH 1/5] tests: Speed up conventional encryption tests for gpg. * tests/openpgp/conventional-mdc.test: Add an s2k-count option. * tests/openpgp/conventional.test: Ditto. -- Due to measuring the iteration count for the passphrase hashing, the conventional encryption tests are running quite slow. This patch fixes it by using a fixed and lower value for the iteration count. Signed-off-by: Werner Koch --- tests/openpgp/conventional-mdc.test | 8 ++++++-- tests/openpgp/conventional.test | 12 ++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/tests/openpgp/conventional-mdc.test b/tests/openpgp/conventional-mdc.test index 15b525fa7..744e11ef3 100755 --- a/tests/openpgp/conventional-mdc.test +++ b/tests/openpgp/conventional-mdc.test @@ -10,6 +10,10 @@ . $srcdir/defs.inc || exit 3 +# We use use a lower than default value for the S2K count to run the +# tests faster. We used a fixed value of 65536 already the past. +s2k="--s2k-count=65536" + #info Checking conventional encryption for ciph in `all_cipher_algos`; do progress "$ciph" @@ -20,9 +24,9 @@ for ciph in `all_cipher_algos`; do else dd if=data-80000 of=z bs=1 count=$i 2>/dev/null fi - echo "Hier spricht HAL" | $GPG --passphrase-fd 0 \ + echo "Hier spricht HAL" | $GPG --passphrase-fd 0 $s2k \ --force-mdc --cipher $ciph -c -o x --yes z - echo "Hier spricht HAL" | $GPG --passphrase-fd 0 \ + echo "Hier spricht HAL" | $GPG --passphrase-fd 0 $s2k \ -o y --yes x cmp z y || error "$ciph/$i: mismatch" done diff --git a/tests/openpgp/conventional.test b/tests/openpgp/conventional.test index 5028b2934..30c9ba042 100755 --- a/tests/openpgp/conventional.test +++ b/tests/openpgp/conventional.test @@ -10,19 +10,23 @@ . $srcdir/defs.inc || exit 3 +# We use use a lower than default value for the S2K count to run the +# tests faster. We used a fixed value of 65536 already the past. +s2k="--s2k-count=65536" + #info Checking conventional encryption for i in plain-2 data-32000 ; do - echo "Hier spricht HAL" | $GPG --passphrase-fd 0 -c -o x --yes $i - echo "Hier spricht HAL" | $GPG --passphrase-fd 0 -o y --yes x + echo "Hier spricht HAL" | $GPG --passphrase-fd 0 $s2k -c -o x --yes $i + echo "Hier spricht HAL" | $GPG --passphrase-fd 0 $s2k -o y --yes x cmp $i y || error "$i: mismatch" done for a in `all_cipher_algos`; do progress "$a" for i in plain-1 data-80000 ; do - echo "Hier spricht HAL" | $GPG --passphrase-fd 0 \ + echo "Hier spricht HAL" | $GPG --passphrase-fd 0 $s2k \ --cipher-algo $a -c -o x --yes $i - echo "Hier spricht HAL" | $GPG --passphrase-fd 0 -o y --yes x + echo "Hier spricht HAL" | $GPG --passphrase-fd 0 $s2k -o y --yes x cmp $i y || error "$i: ($a) mismatch" done done From a2567225373a7e4e4a6eb0cba1d9ab6ff2d1330a Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 13 Oct 2014 13:56:47 +0200 Subject: [PATCH 2/5] tests: Add sample keys with colliding long keu ids. -- Thanks to David Leon Gil who posted these keys to openpgp@ietf.org on Fri, 13 Dec 2013 07:09:54 -0800 (PST). --- tests/openpgp/Makefile.am | 4 ++- tests/openpgp/samplekeys/README | 2 ++ .../openpgp/samplekeys/dda252ebb8ebe1af-1.asc | 29 +++++++++++++++++++ .../openpgp/samplekeys/dda252ebb8ebe1af-2.asc | 29 +++++++++++++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 tests/openpgp/samplekeys/dda252ebb8ebe1af-1.asc create mode 100644 tests/openpgp/samplekeys/dda252ebb8ebe1af-2.asc diff --git a/tests/openpgp/Makefile.am b/tests/openpgp/Makefile.am index cc28027e6..a6eda61c3 100644 --- a/tests/openpgp/Makefile.am +++ b/tests/openpgp/Makefile.am @@ -68,7 +68,9 @@ sample_keys = samplekeys/ecc-sample-1-pub.asc \ samplekeys/ecc-sample-2-sec.asc \ samplekeys/ecc-sample-3-sec.asc \ samplekeys/eddsa-sample-1-pub.asc \ - samplekeys/eddsa-sample-1-sec.asc + samplekeys/eddsa-sample-1-sec.asc \ + samplekeys/dda252ebb8ebe1af-1.asc \ + samplekeys/dda252ebb8ebe1af-2.asc EXTRA_DIST = defs.inc pinentry.sh $(TESTS) $(TEST_FILES) ChangeLog-2011 \ mkdemodirs signdemokey $(priv_keys) $(sample_keys) diff --git a/tests/openpgp/samplekeys/README b/tests/openpgp/samplekeys/README index c30345f91..6f8f916e0 100644 --- a/tests/openpgp/samplekeys/README +++ b/tests/openpgp/samplekeys/README @@ -8,3 +8,5 @@ ecc-sample-3-pub.asc A NIST P-521 ECC sample key. ecc-sample-3-sec.asc Ditto, but the secret keyblock. eddsa-sample-1-pub.asc An Ed25519 sample key. eddsa-sample-1-sec.asc Ditto, but as protected secret keyblock. +dda252ebb8ebe1af-1.asc rsa4096 key 1 +dda252ebb8ebe1af-2.asc rsa4096 key 2 with a long keyid collision. diff --git a/tests/openpgp/samplekeys/dda252ebb8ebe1af-1.asc b/tests/openpgp/samplekeys/dda252ebb8ebe1af-1.asc new file mode 100644 index 000000000..ddae954e8 --- /dev/null +++ b/tests/openpgp/samplekeys/dda252ebb8ebe1af-1.asc @@ -0,0 +1,29 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + + +mQINBFJtd/UBEACpw/psXoGNM8RHczviD7FnGdjMQPEJQ+nuWQ2AEGYouulg5hFv +0ChuSQVLiqQht2k5K2liyW1MeXoJ8tr9nSn/Zi9nttc0Wo6K7pvrDD40r2HNg305 +qLCzItr5st3x8cq2cIXvN4LOm2rqpBLZ/sqMmNiW2Y7/aAQqV1xtR35joHqamWHD +UPOmzBMs07YSUjXgC1EMx8kWQSV6cuARj93kxWj8R6eoYHHfrWCEGR313wov6QST +zIfVU7FqQqOmdLW3LaPHxcrI/TjsnkUN99qdlpjJH/YW925LDPJHAkliqPP5AvhU +F9KbY2F8mcIZBCDd8TH+xXynuN3BbIU4kCwVbdx/tcpO1npuJcKB1Go/udyow/Ei +Z3nHzJsCVkezvopek77wnwPaP0nAb7f4iIY3gJCoGirOx6N075TgF6MBe00q9oFE +y4rvnUnU9/QzOOes95eUMhM+9eK1cuLFEV5t47DfxRdq+fQip3FJ2l6v19sZvQ0G +j06pjYqg0of273rG8oXcDrFjb1Zqhj8x1mLl6u7d/ide5wTm9HylBWcYKQjIJJAi +WIScxEPIOINDJKgsKTuKtoyNvISJ3xUeS1yzxiIb3YGLIyPgFFx0vFyqJfbkXq70 +m1n2xnJlkTidfzbZvc6EA7vRGSDYK6FqqhlGhc7UypUEVW8FM/jZNAOS6QARAUGt +tCg5RTY2OTg2MTM2OEJDQTBCRTQyREFGN0REREEyNTJFQkI4RUJFMUFGiQI3BBMB +CgAhBQJSg/uTAhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAAoJEN2iUuu46+Gv ++Z0P+wQhkLwm+WGcEsS98Lei9O7hit/k4g/VkLUUQV7BOR3n8uRZIFkdOtpvrFU3 +aKf246uCy6GM48Oh+1U2cv5InX/WEuKaFo5uF6t79wyt18BUn1weDcU+DQdOSG4f +fSnNa55wkN0l0svW4fGIthjmDTz6HZFntYD+9A20wZAqpPIs+vyG9Jp+e9E9Y/W/ +EFQbNlxHHb9+BMT2+DtNP+HSl3MPFlQPKOLZxyLAU5uzT0Sa0LxhrQy5FgkW6Jog +sbAJVM9z0pZw+grzGPciM66ZW1rxeICvbYsdWLytRjqxpY8GS8XudyseUGd+dZim +ptarsrE5yfSMg2gW5Z1PTc0tEMXJLUwtpyzQjpFpbb7dPuo2TUp09LgZKX63WCbS +Nb1RTaGfkeYudOTo2rh4Jfg+Tb/JRpO6clo0rxAq8nPH2WmG+9TB8Zbb7YRzGWuV +/e5SeVNR+zY8tXZKnmUIH1HIprc+BtT6Bupdvd0CT14Mg9MmsFvUXofwHLa4gahr +8/iG9y3uHSA6Rhz++yOpyOmNvO1LDxsYNaRCIXQJbqgNwF5YNYlMPsEeY/CG7FOb +Afv7rHiYtRRQfz2P4OF900DJO7QL9gdNXJ1+Hajy/5Lvvl7qwqMG4GvVQEsgFc5O +jjFCUhE2i20j2kEMxvA5RLBH/fOoGARn87tiKSfb+pqLNZQb +=fDJ8 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/openpgp/samplekeys/dda252ebb8ebe1af-2.asc b/tests/openpgp/samplekeys/dda252ebb8ebe1af-2.asc new file mode 100644 index 000000000..854746323 --- /dev/null +++ b/tests/openpgp/samplekeys/dda252ebb8ebe1af-2.asc @@ -0,0 +1,29 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + + +mQINBFKD+38BEADSv5l4xOx9hCRJVcybq6yK5hTpGSFf3xo1bkhoMvyC62ehb4jD +MDLwwNRyzCBEWQJLbq/LLizPFN2qXFJpXJcsuqsHNYRtDqDBEjtriRQwSqHnqTXt +c0K46FYHldCJQ4/tBXxPI+WwtXjcNRWaV7n2BvR/Jk+B5e4Zz3LPnN0C4w5vORHs +hN1jil8A3Hs/F+OmlQYrU8ZtNwTpSo2EXxe2fVgSDCsKRyNsPZj++OyujPzW+yaN +lJ9I/q6s9gvX9o9o7nwZbqBETipWsdRK6RfBdTKpnyLNordbWwWTk6GxN8T5Ppit +P6a3UlQ71VuflcswCTmEQ1pEfZrlRFKa9psBOW+cZLNxT9h0jGFMh6/B3w48Sag+ +cFcPBFWParC+cAXBIURDxT9G6bzNLogg7YKoaPsyiXnLDH2VJUCXs27D2wPJL24Q +S7npvsg63MPPssWgG5cauLznmNR4y5pQi6oH/C10v0zrUJy6FPJzQhYRhWOvhtz6 +j88RGMrFNNCdB2VACtn699D+ixu3nRlXHIKCT+xLSfgslVYifmJOCNljBLGHOQ1e +FJxQuNVpmmxjvk/8kqK+pHLB9Qn6M1ZYzip7OyUL3OAWabCabgEw2bQmUhiBWD3u +buv0WAVOJEAFvBCAeYNQzrQMY+Rc3RnvynG4pI6Tbo8wC6/IJcDOw516JwARASB3 +tChBNTUxMjA0MjczNzRGM0Y3QUE1RjExNjZEREEyNTJFQkI4RUJFMUFGiQI3BBMB +CgAhBQJSg/uTAhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAAoJEN2iUuu46+Gv +9L0P/3tFu0LOZ/dAPjUNfKJCZqcIuVnD5xShMTsUbVx+QoXMy7rt4iRLD7ofGi/I +vTAZehxk3sk/Slx5nbews+3NItyw6mcaP9HlmwKNr6k7BC2kJHcCxH4DNzhmIx1H +3T/CggtHX42JBYKlGf22y+M8jAbvsPOUfTznx96mYNrOY6s1dJyn0kRleqJ8+tGj +/5+0y90iZnGCa0FtacQkKUPkXwVodeZVxk8z5OEipShYKc+8dl+5WsvOzHqLC/KY +xCGRb4JaqEMwouLNg8dTNAXXUvFGqJNDX4+andggogmI1hdD9xExfSU9cAGegg2t +vvveC4S+CCHd+zt88iK5ze6F61RxwYhhNbkuFGjdgNGCpHtG/BQhKnYJuKEbq3oi +mgNyxJERlfgaWXveiMG0AmACXN+jCkTtqZjQnsg2N2QDL3tjY7usmuiwRL1aVOFG +Kw5/Cc+2nDeANS3Xi1403Ni269b1c6kNSoLe4zd0WsbO3Kouds8F8EQfeheXQe97 +ZxuvBOMsR9wHC3f0sl/vfxCGdUC+khmKk5taKnUeUFJmVmh5ghlVy8FySHGB0QHO +zd8GUl59rFpQJNpNFQW2YKDhrcjxIr2AeJrdoDI6NsQ02+Qtep/bbq53hqtAD4jF +t3S8vBbTXtRk6g2qn4ojF4SOIc8SAiZcURgVFuSJX8ngFbO4 +=OEw/ +-----END PGP PUBLIC KEY BLOCK----- From c60814a5ce13932d933b363abc0c60c12783ae2f Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 13 Oct 2014 14:01:29 +0200 Subject: [PATCH 3/5] gpg: Allow importing keys with duplicated long key ids. * g10/keydb.c (keydb_handle): Add field no_caching. (keyblock_cache): Repalce field kid by fpr. (keydb_disable_caching): New. (keydb_search): Use the fingerprint as cache index. * g10/import.c (import_one): Use the fingerprint and not the kid to lookup the key. Call keydb_disable_caching beofre re-searching for update. * tests/openpgp/import.test: Add a test case. Signed-off-by: Werner Koch --- g10/import.c | 24 ++++++++++++------------ g10/keydb.c | 33 +++++++++++++++++++++++++-------- g10/keydb.h | 1 + tests/openpgp/import.test | 13 +++++++++++++ 4 files changed, 51 insertions(+), 20 deletions(-) diff --git a/g10/import.c b/g10/import.c index ca35ce1b9..be2fd6302 100644 --- a/g10/import.c +++ b/g10/import.c @@ -855,12 +855,15 @@ import_one (ctrl_t ctrl, PKT_public_key *pk_orig; KBNODE node, uidnode; KBNODE keyblock_orig = NULL; + byte fpr2[MAX_FINGERPRINT_LEN]; + size_t fpr2len; u32 keyid[2]; int rc = 0; int new_key = 0; int mod_key = 0; int same_key = 0; int non_self = 0; + size_t an; char pkstrbuf[PUBKEY_STRING_SIZE]; /* get the key and print some info about it */ @@ -870,6 +873,9 @@ import_one (ctrl_t ctrl, pk = node->pkt->pkt.public_key; + fingerprint_from_pk (pk, fpr2, &fpr2len); + for (an = fpr2len; an < MAX_FINGERPRINT_LEN; an++) + fpr2[an] = 0; keyid_from_pk( pk, keyid ); uidnode = find_next_kbnode( keyblock, PKT_USER_ID ); @@ -957,7 +963,7 @@ import_one (ctrl_t ctrl, /* do we have this key already in one of our pubrings ? */ pk_orig = xmalloc_clear( sizeof *pk_orig ); - rc = get_pubkey_fast ( pk_orig, keyid ); + rc = get_pubkey_byfprint_fast (pk_orig, fpr2, fpr2len); if( rc && rc != G10ERR_NO_PUBKEY && rc != G10ERR_UNU_PUBKEY ) { if (!silent) @@ -1033,17 +1039,11 @@ import_one (ctrl_t ctrl, goto leave; } - /* now read the original keyblock */ + /* Now read the original keyblock again so that we can use + that handle for updating the keyblock. */ hd = keydb_new (); - { - byte afp[MAX_FINGERPRINT_LEN]; - size_t an; - - fingerprint_from_pk (pk_orig, afp, &an); - while (an < MAX_FINGERPRINT_LEN) - afp[an++] = 0; - rc = keydb_search_fpr (hd, afp); - } + keydb_disable_caching (hd); + rc = keydb_search_fpr (hd, fpr2); if( rc ) { log_error (_("key %s: can't locate original keyblock: %s\n"), @@ -1051,7 +1051,7 @@ import_one (ctrl_t ctrl, keydb_release (hd); goto leave; } - rc = keydb_get_keyblock (hd, &keyblock_orig ); + rc = keydb_get_keyblock (hd, &keyblock_orig); if (rc) { log_error (_("key %s: can't read original keyblock: %s\n"), diff --git a/g10/keydb.c b/g10/keydb.c index a9a975378..c192e06b4 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -68,6 +68,7 @@ struct keydb_handle int locked; int found; unsigned long skipped_long_blobs; + int no_caching; int current; int used; /* Number of items in ACTIVE. */ struct resource_item active[MAX_KEYDB_RESOURCES]; @@ -75,7 +76,7 @@ struct keydb_handle /* This is a simple cache used to return the last result of a - successful long kid search. This works only for keybox resources + successful fingerprint search. This works only for keybox resources because (due to lack of a copy_keyblock function) we need to store an image of the keyblock which is fortunately instantly available for keyboxes. */ @@ -87,7 +88,7 @@ enum keyblock_cache_states { struct { enum keyblock_cache_states state; - u32 kid[2]; + byte fpr[MAX_FINGERPRINT_LEN]; iobuf_t iobuf; /* Image of the keyblock. */ u32 *sigstatus; int pk_no; @@ -570,6 +571,7 @@ keydb_new (void) return hd; } + void keydb_release (KEYDB_HANDLE hd) { @@ -600,6 +602,17 @@ keydb_release (KEYDB_HANDLE hd) } +/* Set a flag on handle to not use cached results. This is required + for updating a keyring. Fixme: Using a new parameter for keydb_new + might be a better solution. */ +void +keydb_disable_caching (KEYDB_HANDLE hd) +{ + if (hd) + hd->no_caching = 1; +} + + /* * Return the name of the current resource. This is function first * looks for the last found found, then for the current search @@ -1407,10 +1420,12 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, if (DBG_CACHE) dump_search_desc ("keydb_search", desc, ndesc); - if (ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID + if (!hd->no_caching + && ndesc == 1 + && (desc[0].mode == KEYDB_SEARCH_MODE_FPR20 + || desc[0].mode == KEYDB_SEARCH_MODE_FPR) && keyblock_cache.state == KEYBLOCK_CACHE_FILLED - && keyblock_cache.kid[0] == desc[0].u.kid[0] - && keyblock_cache.kid[1] == desc[0].u.kid[1]) + && !memcmp (keyblock_cache.fpr, desc[0].u.fpr, 20)) { /* (DESCINDEX is already set). */ if (DBG_CLOCK) @@ -1450,11 +1465,13 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, : rc); keyblock_cache_clear (); - if (!rc && ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID) + if (!hd->no_caching + && !rc + && ndesc == 1 && (desc[0].mode == KEYDB_SEARCH_MODE_FPR20 + || desc[0].mode == KEYDB_SEARCH_MODE_FPR)) { keyblock_cache.state = KEYBLOCK_CACHE_PREPARED; - keyblock_cache.kid[0] = desc[0].u.kid[0]; - keyblock_cache.kid[1] = desc[0].u.kid[1]; + memcpy (keyblock_cache.fpr, desc[0].u.fpr, 20); } if (DBG_CLOCK) diff --git a/g10/keydb.h b/g10/keydb.h index 78d151a51..55f8fc22b 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -135,6 +135,7 @@ gpg_error_t keydb_add_resource (const char *url, unsigned int flags); KEYDB_HANDLE keydb_new (void); void keydb_release (KEYDB_HANDLE hd); +void keydb_disable_caching (KEYDB_HANDLE hd); const char *keydb_get_resource_name (KEYDB_HANDLE hd); gpg_error_t keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb); gpg_error_t keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb); diff --git a/tests/openpgp/import.test b/tests/openpgp/import.test index eb6860e88..a58db40fe 100755 --- a/tests/openpgp/import.test +++ b/tests/openpgp/import.test @@ -31,3 +31,16 @@ if $GPG --list-keys --with-colons $keyid \ else error "$goodkey: import failed (bug 1223)" fi + + +key1=$srcdir/samplekeys/dda252ebb8ebe1af-1.asc +key2=$srcdir/samplekeys/dda252ebb8ebe1af-2.asc +fpr1=9E669861368BCA0BE42DAF7DDDA252EBB8EBE1AF +fpr2=A55120427374F3F7AA5F1166DDA252EBB8EBE1AF +info "Checking import of two keys with colliding long key ids." +$GPG --delete-key --batch --yes $fpr1 $fpr2 2>/dev/null || true +$GPG --import $key1 || true +$GPG --import $key2 || true +n=$($GPG --list-keys --with-colons $fpr1 $fpr2 2>/dev/null \ + | grep '^pub:.:4096:1:DDA252EBB8EBE1AF:' | wc -l) +[ $n -ne 2 ] && error "Importing keys with long id collision failed" From 21c0ea6bafafbcc4a2e07f0ac76275cc0229e9a0 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 13 Oct 2014 14:54:26 +0200 Subject: [PATCH 4/5] gpg: Fix informative printing of user ids. * g10/getkey.c (keyid_list): Add field "fpr". (cache_user_id): Store fpr and check for dups only by fpr. (get_pubkey_byfpr): New. (get_user_id_string): Make static and use xasprintf. (get_long_user_id_string): Use xasprintf. (get_user_id_byfpr): New. (get_user_id_byfpr_native): New. * g10/keyid.c (fingerprint_from_pk): Make arg RET_LEN optional. * g10/import.c (import_one): Use get_user_id_byfpr_native. -- We now cache the userids using the fingerprint. This allows to print the correct user id for keys with a duplicated key id. We should eventually start to retire the use of all the old keyid based functions. However, at some places we only have the keyid and thus some of them will need to be kept (maybe changed with an indication to show that more than several user ids are matching). Signed-off-by: Werner Koch --- g10/getkey.c | 111 +++++++++++++++++++++++++++++++++++++++++---------- g10/gpg.h | 3 +- g10/import.c | 10 ++--- g10/keydb.h | 4 +- g10/keyid.c | 3 +- 5 files changed, 103 insertions(+), 28 deletions(-) diff --git a/g10/getkey.c b/g10/getkey.c index 707a106e4..4f10c1821 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -74,6 +74,7 @@ static struct typedef struct keyid_list { struct keyid_list *next; + char fpr[MAX_FINGERPRINT_LEN]; u32 keyid[2]; } *keyid_list_t; @@ -263,6 +264,7 @@ cache_user_id (KBNODE keyblock) keyid_list_t a = xmalloc_clear (sizeof *a); /* Hmmm: For a long list of keyids it might be an advantage * to append the keys. */ + fingerprint_from_pk (k->pkt->pkt.public_key, a->fpr, NULL); keyid_from_pk (k->pkt->pkt.public_key, a->keyid); /* First check for duplicates. */ for (r = user_id_db; r; r = r->next) @@ -270,8 +272,7 @@ cache_user_id (KBNODE keyblock) keyid_list_t b = r->keyids; for (b = r->keyids; b; b = b->next) { - if (b->keyid[0] == a->keyid[0] - && b->keyid[1] == a->keyid[1]) + if (!memcmp (b->fpr, a->fpr, MAX_FINGERPRINT_LEN)) { if (DBG_CACHE) log_debug ("cache_user_id: already in cache\n"); @@ -950,6 +951,34 @@ get_pubkey_end (GETKEY_CTX ctx) } +/* Search for a key with the given standard fingerprint. In contrast + * to get_pubkey_byfprint we assume a right padded fingerprint of the + * standard length. PK may be NULL to only put the result into the + * internal caches. */ +gpg_error_t +get_pubkey_byfpr (PKT_public_key *pk, const byte *fpr) +{ + gpg_error_t err; + struct getkey_ctx_s ctx; + kbnode_t kb = NULL; + + memset (&ctx, 0, sizeof ctx); + ctx.exact = 1; + ctx.not_allocated = 1; + ctx.kr_handle = keydb_new (); + ctx.nitems = 1; + ctx.items[0].mode = KEYDB_SEARCH_MODE_FPR; + memcpy (ctx.items[0].u.fpr, fpr, MAX_FINGERPRINT_LEN); + err = lookup (&ctx, &kb, 0); + if (!err && pk) + pk_from_block (&ctx, pk, kb); + release_kbnode (kb); + get_pubkey_end (&ctx); + + return err; +} + + /* Search for a key with the given fingerprint. * FIXME: * We should replace this with the _byname function. This can be done @@ -2687,11 +2716,10 @@ enum_secret_keys (void **context, PKT_public_key *sk) /* Return a string with a printable representation of the user_id. * this string must be freed by xfree. */ -char * +static char * get_user_id_string (u32 * keyid) { user_id_db_t r; - char *p; int pass = 0; /* Try it two times; second pass reads from key resources. */ do @@ -2703,17 +2731,13 @@ get_user_id_string (u32 * keyid) { if (a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1]) { - p = xmalloc (keystrlen () + 1 + r->len + 1); - sprintf (p, "%s %.*s", keystr (keyid), r->len, r->name); - return p; + return xasprintf ("%s %.*s", keystr (keyid), r->len, r->name); } } } } while (++pass < 2 && !get_pubkey (NULL, keyid)); - p = xmalloc (keystrlen () + 5); - sprintf (p, "%s [?]", keystr (keyid)); - return p; + return xasprintf ("%s [?]", keystr (keyid)); } @@ -2731,33 +2755,30 @@ char * get_long_user_id_string (u32 * keyid) { user_id_db_t r; - char *p; + keyid_list_t a; int pass = 0; /* Try it two times; second pass reads from key resources. */ do { for (r = user_id_db; r; r = r->next) { - keyid_list_t a; for (a = r->keyids; a; a = a->next) { if (a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1]) { - p = xmalloc (r->len + 20); - sprintf (p, "%08lX%08lX %.*s", - (ulong) keyid[0], (ulong) keyid[1], - r->len, r->name); - return p; + return xasprintf ("%08lX%08lX %.*s", + (ulong) keyid[0], (ulong) keyid[1], + r->len, r->name); } } } } while (++pass < 2 && !get_pubkey (NULL, keyid)); - p = xmalloc (25); - sprintf (p, "%08lX%08lX [?]", (ulong) keyid[0], (ulong) keyid[1]); - return p; + return xasprintf ("%08lX%08lX [?]", (ulong) keyid[0], (ulong) keyid[1]); } + +/* Please try to use get_user_id_native instead of this one. */ char * get_user_id (u32 * keyid, size_t * rn) { @@ -2792,6 +2813,7 @@ get_user_id (u32 * keyid, size_t * rn) return p; } +/* Please try to use get_user_id_byfpr_native instead of this one. */ char * get_user_id_native (u32 * keyid) { @@ -2802,6 +2824,55 @@ get_user_id_native (u32 * keyid) return p2; } + +/* Return a user id from the caching by looking it up using the FPR + which mustbe of size MAX_FINGERPRINT_LEN. */ +char * +get_user_id_byfpr (const byte *fpr, size_t *rn) +{ + user_id_db_t r; + char *p; + int pass = 0; + + /* Try it two times; second pass reads from key resources. */ + do + { + for (r = user_id_db; r; r = r->next) + { + keyid_list_t a; + for (a = r->keyids; a; a = a->next) + { + if (!memcmp (a->fpr, fpr, MAX_FINGERPRINT_LEN)) + { + /* An empty string as user id is possible. Make + sure that the malloc allocates one byte and does + not bail out. */ + p = xmalloc (r->len? r->len : 1); + memcpy (p, r->name, r->len); + *rn = r->len; + return p; + } + } + } + } + while (++pass < 2 && !get_pubkey_byfpr (NULL, fpr)); + p = xstrdup (user_id_not_found_utf8 ()); + *rn = strlen (p); + return p; +} + +char * +get_user_id_byfpr_native (const byte *fpr) +{ + size_t rn; + char *p = get_user_id_byfpr (fpr, &rn); + char *p2 = utf8_to_native (p, rn, 0); + xfree (p); + return p2; +} + + + KEYDB_HANDLE get_ctx_handle (GETKEY_CTX ctx) { diff --git a/g10/gpg.h b/g10/gpg.h index 3251dd00f..ce4d253dc 100644 --- a/g10/gpg.h +++ b/g10/gpg.h @@ -37,7 +37,8 @@ /* Number of bits we accept when reading or writing MPIs. */ #define MAX_EXTERN_MPI_BITS 16384 -/* The maximum length of a binary fingerprints. */ +/* The maximum length of a binary fingerprints. + Warning: At some places we still use 20 instead of this macro. */ #define MAX_FINGERPRINT_LEN 20 diff --git a/g10/import.c b/g10/import.c index be2fd6302..8f7595c7f 100644 --- a/g10/import.c +++ b/g10/import.c @@ -1009,9 +1009,9 @@ import_one (ctrl_t ctrl, /* we are ready */ if( !opt.quiet && !silent) { - char *p=get_user_id_native (keyid); - log_info( _("key %s: public key \"%s\" imported\n"), - keystr(keyid),p); + char *p = get_user_id_byfpr_native (fpr2); + log_info (_("key %s: public key \"%s\" imported\n"), + keystr(keyid), p); xfree(p); } if( is_status_enabled() ) @@ -1094,7 +1094,7 @@ import_one (ctrl_t ctrl, /* we are ready */ if( !opt.quiet && !silent) { - char *p=get_user_id_native(keyid); + char *p = get_user_id_byfpr_native (fpr2); if( n_uids == 1 ) log_info( _("key %s: \"%s\" 1 new user ID\n"), keystr(keyid),p); @@ -1145,7 +1145,7 @@ import_one (ctrl_t ctrl, if( !opt.quiet && !silent) { - char *p=get_user_id_native(keyid); + char *p = get_user_id_byfpr_native (fpr2); log_info( _("key %s: \"%s\" not changed\n"),keystr(keyid),p); xfree(p); } diff --git a/g10/keydb.h b/g10/keydb.h index 55f8fc22b..c61e0ae18 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -222,6 +222,7 @@ int get_pubkey_bynames( GETKEY_CTX *rx, PKT_public_key *pk, int get_pubkey_next( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock ); void get_pubkey_end( GETKEY_CTX ctx ); gpg_error_t get_seckey (PKT_public_key *pk, u32 *keyid); +gpg_error_t get_pubkey_byfpr (PKT_public_key *pk, const byte *fpr); int get_pubkey_byfprint( PKT_public_key *pk, const byte *fprint, size_t fprint_len ); int get_pubkey_byfprint_fast (PKT_public_key *pk, @@ -252,11 +253,12 @@ gpg_error_t enum_secret_keys (void **context, PKT_public_key *pk); void setup_main_keyids (kbnode_t keyblock); void merge_keys_and_selfsig( KBNODE keyblock ); -char*get_user_id_string( u32 *keyid ); char*get_user_id_string_native( u32 *keyid ); char*get_long_user_id_string( u32 *keyid ); char*get_user_id( u32 *keyid, size_t *rn ); char*get_user_id_native( u32 *keyid ); +char *get_user_id_byfpr (const byte *fpr, size_t *rn); +char *get_user_id_byfpr_native (const byte *fpr); KEYDB_HANDLE get_ctx_handle(GETKEY_CTX ctx); void release_akl(void); int parse_auto_key_locate(char *options); diff --git a/g10/keyid.c b/g10/keyid.c index 3b4c10c65..8b4eeb1f2 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -767,7 +767,8 @@ fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len) gcry_md_close( md); } - *ret_len = len; + if (ret_len) + *ret_len = len; return array; } From fab89f159bcb36ea7285af661d5756eefa981822 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 13 Oct 2014 15:00:39 +0200 Subject: [PATCH 5/5] gpg: Remove extra RSA import status line. * g10/import.c (stats_s): Remove field "imported_rsa". (import_print_stats): Do not print separate value for RSA. (import_one): Remove the RSA counter. -- RSA is the standard key format and thus there is no more need to have a separate counter. This is a remain from the RSA patent times. Signed-off-by: Werner Koch --- doc/DETAILS | 2 +- g10/import.c | 10 ++-------- tests/openpgp/import.test | 4 +++- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/doc/DETAILS b/doc/DETAILS index 311dfe3a4..eafd312c3 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -739,7 +739,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB: - - - - - + - always 0 (formerly used for the number of RSA keys) - - - diff --git a/g10/import.c b/g10/import.c index 8f7595c7f..16e2b0b4b 100644 --- a/g10/import.c +++ b/g10/import.c @@ -45,7 +45,6 @@ struct stats_s { ulong count; ulong no_user_id; ulong imported; - ulong imported_rsa; ulong n_uids; ulong n_sigs; ulong n_subk; @@ -399,10 +398,8 @@ import_print_stats (void *hd) stats->skipped_new_keys ); if( stats->no_user_id ) log_info(_(" w/o user IDs: %lu\n"), stats->no_user_id ); - if( stats->imported || stats->imported_rsa ) { + if( stats->imported) { log_info(_(" imported: %lu"), stats->imported ); - if (stats->imported_rsa) - log_printf (" (RSA: %lu)", stats->imported_rsa ); log_printf ("\n"); } if( stats->unchanged ) @@ -431,11 +428,10 @@ import_print_stats (void *hd) if( is_status_enabled() ) { char buf[14*20]; - sprintf(buf, "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", + sprintf(buf, "%lu %lu %lu 0 %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", stats->count, stats->no_user_id, stats->imported, - stats->imported_rsa, stats->unchanged, stats->n_uids, stats->n_subk, @@ -1022,8 +1018,6 @@ import_one (ctrl_t ctrl, print_import_ok (pk, 1); } stats->imported++; - if( is_RSA( pk->pubkey_algo ) ) - stats->imported_rsa++; new_key = 1; } else { /* merge */ diff --git a/tests/openpgp/import.test b/tests/openpgp/import.test index a58db40fe..783d059bb 100755 --- a/tests/openpgp/import.test +++ b/tests/openpgp/import.test @@ -43,4 +43,6 @@ $GPG --import $key1 || true $GPG --import $key2 || true n=$($GPG --list-keys --with-colons $fpr1 $fpr2 2>/dev/null \ | grep '^pub:.:4096:1:DDA252EBB8EBE1AF:' | wc -l) -[ $n -ne 2 ] && error "Importing keys with long id collision failed" +if [ $n -ne 2 ] ; then + error "Importing keys with long id collision failed" +fi