mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
gpgsm: Use a cache to speed up parent certificate lookup.
* sm/gpgsm.h (COMPAT_NO_CHAIN_CACHE): New. (struct cert_cache_item_s, cert_cache_item_t): New. (struct server_control_s): Add parent_cert_cache. * sm/gpgsm.c (compatibility_flags): Add "no-chain-cache". (parent_cache_stats): New. (gpgsm_exit): Print the stats with --debug=memstat. (gpgsm_deinit_default_ctrl): Release the cache. * sm/certchain.c (gpgsm_walk_cert_chain): Cache the certificates. (do_validate_chain): Ditto. -- This gives another boost of 30% (from 6.5 to 4.0 seconds in the test environment with ~1000 certs). do_validate_chain actually brings us the speedup becuase the gpgsm_walk_cert_chain is not used during a key listing. For the latter we actually cache all certificates because that was easier. GnuPG-bug-id: 7308
This commit is contained in:
parent
cb6c506e4e
commit
ce0580a599
@ -1056,15 +1056,10 @@ gpgsm_walk_cert_chain (ctrl_t ctrl, ksba_cert_t start, ksba_cert_t *r_next)
|
|||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
char *issuer = NULL;
|
char *issuer = NULL;
|
||||||
char *subject = NULL;
|
char *subject = NULL;
|
||||||
KEYDB_HANDLE kh = keydb_new (ctrl);
|
KEYDB_HANDLE kh = NULL;
|
||||||
|
cert_cache_item_t ci;
|
||||||
|
|
||||||
*r_next = NULL;
|
*r_next = NULL;
|
||||||
if (!kh)
|
|
||||||
{
|
|
||||||
log_error (_("failed to allocate keyDB handle\n"));
|
|
||||||
err = gpg_error (GPG_ERR_GENERAL);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
issuer = ksba_cert_get_issuer (start, 0);
|
issuer = ksba_cert_get_issuer (start, 0);
|
||||||
subject = ksba_cert_get_subject (start, 0);
|
subject = ksba_cert_get_subject (start, 0);
|
||||||
@ -1087,6 +1082,30 @@ gpgsm_walk_cert_chain (ctrl_t ctrl, ksba_cert_t start, ksba_cert_t *r_next)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(opt.compat_flags & COMPAT_NO_CHAIN_CACHE))
|
||||||
|
{
|
||||||
|
unsigned char fpr[20];
|
||||||
|
|
||||||
|
gpgsm_get_fingerprint (start, GCRY_MD_SHA1, fpr, NULL);
|
||||||
|
for (ci = ctrl->parent_cert_cache; ci; ci = ci->next)
|
||||||
|
{
|
||||||
|
if (!memcmp (fpr, ci->fpr, 20) && ci->result)
|
||||||
|
{
|
||||||
|
/* Found in the cache. */
|
||||||
|
ksba_cert_ref ((*r_next = ci->result));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kh = keydb_new (ctrl);
|
||||||
|
if (!kh)
|
||||||
|
{
|
||||||
|
log_error (_("failed to allocate keyDB handle\n"));
|
||||||
|
err = gpg_error (GPG_ERR_GENERAL);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
err = find_up (ctrl, kh, start, issuer, 0);
|
err = find_up (ctrl, kh, start, issuer, 0);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
@ -1105,6 +1124,22 @@ gpgsm_walk_cert_chain (ctrl_t ctrl, ksba_cert_t start, ksba_cert_t *r_next)
|
|||||||
log_error ("keydb_get_cert failed in %s: %s <%s>\n",
|
log_error ("keydb_get_cert failed in %s: %s <%s>\n",
|
||||||
__func__, gpg_strerror (err), gpg_strsource (err));
|
__func__, gpg_strerror (err), gpg_strsource (err));
|
||||||
err = gpg_error (GPG_ERR_GENERAL);
|
err = gpg_error (GPG_ERR_GENERAL);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cache it. */
|
||||||
|
if (!(opt.compat_flags & COMPAT_NO_CHAIN_CACHE))
|
||||||
|
{
|
||||||
|
ci = xtrycalloc (1, sizeof *ci);
|
||||||
|
if (!ci)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
gpgsm_get_fingerprint (start, GCRY_MD_SHA1, ci->fpr, NULL);
|
||||||
|
ksba_cert_ref ((ci->result = *r_next));
|
||||||
|
ci->next = ctrl->parent_cert_cache;
|
||||||
|
ctrl->parent_cert_cache = ci;
|
||||||
}
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
@ -1852,6 +1887,24 @@ do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Find the next cert up the tree. */
|
/* Find the next cert up the tree. */
|
||||||
|
if (!(opt.compat_flags & COMPAT_NO_CHAIN_CACHE))
|
||||||
|
{
|
||||||
|
cert_cache_item_t ci;
|
||||||
|
unsigned char fpr[20];
|
||||||
|
|
||||||
|
gpgsm_get_fingerprint (subject_cert, GCRY_MD_SHA1, fpr, NULL);
|
||||||
|
for (ci = ctrl->parent_cert_cache; ci; ci = ci->next)
|
||||||
|
{
|
||||||
|
if (!memcmp (fpr, ci->fpr, 20) && ci->result)
|
||||||
|
{
|
||||||
|
/* Found in the cache. */
|
||||||
|
ksba_cert_release (issuer_cert);
|
||||||
|
ksba_cert_ref ((issuer_cert = ci->result));
|
||||||
|
goto found_in_cache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
keydb_search_reset (kh);
|
keydb_search_reset (kh);
|
||||||
rc = find_up (ctrl, kh, subject_cert, issuer, 0);
|
rc = find_up (ctrl, kh, subject_cert, issuer, 0);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -1883,6 +1936,26 @@ do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg,
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Cache it. The chain->next is here so that the leaf
|
||||||
|
* certificates are not cached. */
|
||||||
|
if (!(opt.compat_flags & COMPAT_NO_CHAIN_CACHE) && chain->next)
|
||||||
|
{
|
||||||
|
cert_cache_item_t ci;
|
||||||
|
|
||||||
|
ci = xtrycalloc (1, sizeof *ci);
|
||||||
|
if (!ci)
|
||||||
|
{
|
||||||
|
rc = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
gpgsm_get_fingerprint (subject_cert, GCRY_MD_SHA1, ci->fpr, NULL);
|
||||||
|
ksba_cert_ref ((ci->result = issuer_cert));
|
||||||
|
ci->next = ctrl->parent_cert_cache;
|
||||||
|
ctrl->parent_cert_cache = ci;
|
||||||
|
}
|
||||||
|
|
||||||
|
found_in_cache:
|
||||||
|
|
||||||
try_another_cert:
|
try_another_cert:
|
||||||
if (DBG_X509)
|
if (DBG_X509)
|
||||||
{
|
{
|
||||||
|
18
sm/gpgsm.c
18
sm/gpgsm.c
@ -500,6 +500,7 @@ static struct debug_flags_s debug_flags [] =
|
|||||||
static struct compatibility_flags_s compatibility_flags [] =
|
static struct compatibility_flags_s compatibility_flags [] =
|
||||||
{
|
{
|
||||||
{ COMPAT_ALLOW_KA_TO_ENCR, "allow-ka-to-encr" },
|
{ COMPAT_ALLOW_KA_TO_ENCR, "allow-ka-to-encr" },
|
||||||
|
{ COMPAT_NO_CHAIN_CACHE, "no-chain-cache" },
|
||||||
{ 0, NULL }
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -536,6 +537,9 @@ static int default_include_certs = DEFAULT_INCLUDE_CERTS;
|
|||||||
/* Whether the chain mode shall be used for validation. */
|
/* Whether the chain mode shall be used for validation. */
|
||||||
static int default_validation_model;
|
static int default_validation_model;
|
||||||
|
|
||||||
|
/* Counter used to convey data from deinit_ctrl to gpgsm_exit. */
|
||||||
|
static unsigned int parent_cache_stats;
|
||||||
|
|
||||||
/* The default cipher algo. */
|
/* The default cipher algo. */
|
||||||
#define DEFAULT_CIPHER_ALGO "AES256"
|
#define DEFAULT_CIPHER_ALGO "AES256"
|
||||||
|
|
||||||
@ -2354,6 +2358,7 @@ gpgsm_exit (int rc)
|
|||||||
gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
|
gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
|
||||||
if (opt.debug & DBG_MEMSTAT_VALUE)
|
if (opt.debug & DBG_MEMSTAT_VALUE)
|
||||||
{
|
{
|
||||||
|
log_info ("cert_chain_cache: cached=%u\n", parent_cache_stats);
|
||||||
gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
|
gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
|
||||||
gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
|
gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
|
||||||
}
|
}
|
||||||
@ -2381,9 +2386,22 @@ gpgsm_init_default_ctrl (struct server_control_s *ctrl)
|
|||||||
void
|
void
|
||||||
gpgsm_deinit_default_ctrl (ctrl_t ctrl)
|
gpgsm_deinit_default_ctrl (ctrl_t ctrl)
|
||||||
{
|
{
|
||||||
|
unsigned int n;
|
||||||
|
|
||||||
gpgsm_keydb_deinit_session_data (ctrl);
|
gpgsm_keydb_deinit_session_data (ctrl);
|
||||||
xfree (ctrl->revocation_reason);
|
xfree (ctrl->revocation_reason);
|
||||||
ctrl->revocation_reason = NULL;
|
ctrl->revocation_reason = NULL;
|
||||||
|
n = 0;
|
||||||
|
while (ctrl->parent_cert_cache)
|
||||||
|
{
|
||||||
|
cert_cache_item_t next = ctrl->parent_cert_cache->next;
|
||||||
|
ksba_cert_release (ctrl->parent_cert_cache->result);
|
||||||
|
xfree (ctrl->parent_cert_cache);
|
||||||
|
ctrl->parent_cert_cache = next;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
if (n > parent_cache_stats)
|
||||||
|
parent_cache_stats = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
17
sm/gpgsm.h
17
sm/gpgsm.h
@ -220,7 +220,9 @@ struct
|
|||||||
* policies: 1.3.6.1.4.1.7924.1.1:N:
|
* policies: 1.3.6.1.4.1.7924.1.1:N:
|
||||||
*/
|
*/
|
||||||
#define COMPAT_ALLOW_KA_TO_ENCR 1
|
#define COMPAT_ALLOW_KA_TO_ENCR 1
|
||||||
|
/* Not actually a compatibiliy flag but useful to limit the
|
||||||
|
* required memory for a validated key listing. */
|
||||||
|
#define COMPAT_NO_CHAIN_CACHE 2
|
||||||
|
|
||||||
/* Forward declaration for an object defined in server.c */
|
/* Forward declaration for an object defined in server.c */
|
||||||
struct server_local_s;
|
struct server_local_s;
|
||||||
@ -230,6 +232,16 @@ struct keydb_local_s;
|
|||||||
typedef struct keydb_local_s *keydb_local_t;
|
typedef struct keydb_local_s *keydb_local_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* On object used to keep a track of already known certificates. */
|
||||||
|
struct cert_cache_item_s
|
||||||
|
{
|
||||||
|
struct cert_cache_item_s *next;
|
||||||
|
unsigned char fpr[20]; /* The certificate's fingerprint. */
|
||||||
|
ksba_cert_t result; /* The resulting certificate (ie. the issuer). */
|
||||||
|
};
|
||||||
|
typedef struct cert_cache_item_s *cert_cache_item_t;
|
||||||
|
|
||||||
|
|
||||||
/* Session control object. This object is passed down to most
|
/* Session control object. This object is passed down to most
|
||||||
functions. Note that the default values for it are set by
|
functions. Note that the default values for it are set by
|
||||||
gpgsm_init_default_ctrl(). */
|
gpgsm_init_default_ctrl(). */
|
||||||
@ -284,6 +296,9 @@ struct server_control_s
|
|||||||
/* The revocation info. Used as a helper inc ertchain.c */
|
/* The revocation info. Used as a helper inc ertchain.c */
|
||||||
gnupg_isotime_t revoked_at;
|
gnupg_isotime_t revoked_at;
|
||||||
char *revocation_reason;
|
char *revocation_reason;
|
||||||
|
|
||||||
|
/* The cache used to find the parent cert. */
|
||||||
|
cert_cache_item_t parent_cert_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user