1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

card: Cache the results from gpg and gpgsm.

* tools/card-tool-keys.c (keyblock_cache): New var.
(release_keyblock): Factor code out to a new do_release_keyblock.  Add
a cache.
(flush_keyblock_cache): New.
(get_matching_keys): Use the cache.
* tools/gpg-card-tool.c (cmds): Add command "reset".
(interactive_loop): Implement reset.
--

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2019-01-30 17:48:41 +01:00
parent 833f27a6a7
commit 0107984f9f
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
3 changed files with 90 additions and 3 deletions

View file

@ -30,9 +30,22 @@
#include "../common/openpgpdefs.h"
#include "card-tool.h"
/* Release a keyblocm object. */
void
release_keyblock (keyblock_t keyblock)
/* It is quite common that all keys of an OpenPGP card belong to the
* the same OpenPGP keyblock. To avoid running several queries
* despite that we already got the information with the previous
* keyblock, we keep a small cache of of previous done queries. */
static struct
{
unsigned int lru;
keyblock_t keyblock;
} keyblock_cache[5];
/* Helper for release_keyblock. */
static void
do_release_keyblock (keyblock_t keyblock)
{
pubkey_t pubkey;
userid_t uid;
@ -61,6 +74,62 @@ release_keyblock (keyblock_t keyblock)
}
/* Release a keyblock object. */
void
release_keyblock (keyblock_t keyblock)
{
static unsigned int lru_counter;
unsigned int lru;
int i, lru_idx;
if (!keyblock)
return;
lru = (unsigned int)(-1);
lru_idx = 0;
for (i=0; i < DIM (keyblock_cache); i++)
{
if (!keyblock_cache[i].keyblock)
{
keyblock_cache[i].keyblock = keyblock;
keyblock_cache[i].lru = ++lru_counter;
goto leave;
}
if (keyblock_cache[i].lru < lru)
{
lru = keyblock_cache[i].lru;
lru_idx = i;
}
}
/* No free slot. Replace one. */
do_release_keyblock (keyblock_cache[lru_idx].keyblock);
keyblock_cache[lru_idx].keyblock = keyblock;
keyblock_cache[lru_idx].lru = ++lru_counter;
leave:
if (!lru_counter)
{
/* Wrapped around. We simply clear the entire cache. */
flush_keyblock_cache ();
}
}
/* Flush the enire keyblock cache. */
void
flush_keyblock_cache (void)
{
int i;
for (i=0; i < DIM (keyblock_cache); i++)
{
do_release_keyblock (keyblock_cache[i].keyblock);
keyblock_cache[i].keyblock = NULL;
}
}
/* Object to communicate with the status_cb. */
struct status_cb_s
@ -127,6 +196,7 @@ get_matching_keys (const unsigned char *keygrip, int protocol,
char **fields = NULL;
int nfields;
int first_seen;
int i;
keyblock_t keyblock_head, *keyblock_tail, kb;
pubkey_t pubkey, pk;
size_t n;
@ -168,6 +238,18 @@ get_matching_keys (const unsigned char *keygrip, int protocol,
if (protocol != GNUPG_PROTOCOL_OPENPGP && protocol != GNUPG_PROTOCOL_CMS)
return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
/* Try to get it from our cache. */
for (i=0; i < DIM (keyblock_cache); i++)
for (kb = keyblock_cache[i].keyblock; kb; kb = kb->next)
if (kb->protocol == protocol)
for (pk = kb->keys; pk; pk = pk->next)
if (pk->grip_valid && !memcmp (pk->grip, keygrip, KEYGRIP_LEN))
{
*r_keyblock = keyblock_cache[i].keyblock;
keyblock_cache[i].keyblock = NULL;
return 0;
}
/* Open a memory stream. */
listing = es_fopenmem (0, "w+b");
if (!listing)