Skip to content

Commit

Permalink
Optimise PKEY decoders
Browse files Browse the repository at this point in the history
The most expensive part of using a PKEY decoder is the
OSSL_DECODER_CTX_new_for_pkey() call. This builds up all of the decoder
chains, which is a complex and time consuming operation. However, if no
new providers have been loaded/unloaded since the last time it was called
we can expect the same results for the same parameters. Note that this
operation takes place *before* we event parse the data for decoding so it
is not dependent on the parsed data at all.

We introduce a cache for OSSL_DECODER_CTX objects. If we have been called
with the same parameters then we just duplicate an existing
OSSL_DECODER_CTX. This should be significantly faster than creating a new
one every time.

Partially addressed the issue in #15199

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from #21426)
  • Loading branch information
mattcaswell authored and paulidale committed Jul 16, 2023
1 parent 1e398be commit 32d3c3a
Show file tree
Hide file tree
Showing 9 changed files with 479 additions and 34 deletions.
22 changes: 20 additions & 2 deletions crypto/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "internal/core.h"
#include "internal/bio.h"
#include "internal/provider.h"
#include "internal/decoder.h"
#include "crypto/context.h"

struct ossl_lib_ctx_st {
Expand All @@ -33,6 +34,7 @@ struct ossl_lib_ctx_st {
void *bio_core;
void *child_provider;
OSSL_METHOD_STORE *decoder_store;
void *decoder_cache;
OSSL_METHOD_STORE *encoder_store;
OSSL_METHOD_STORE *store_loader_store;
void *self_test_cb;
Expand Down Expand Up @@ -110,10 +112,16 @@ static int context_init(OSSL_LIB_CTX *ctx)
goto err;

#ifndef FIPS_MODULE
/* P2. We want decoder_store to be cleaned up before the provider store */
/*
* P2. We want decoder_store/decoder_cache to be cleaned up before the
* provider store
*/
ctx->decoder_store = ossl_method_store_new(ctx);
if (ctx->decoder_store == NULL)
goto err;
ctx->decoder_cache = ossl_decoder_cache_new(ctx);
if (ctx->decoder_cache == NULL)
goto err;

/* P2. We want encoder_store to be cleaned up before the provider store */
ctx->encoder_store = ossl_method_store_new(ctx);
Expand Down Expand Up @@ -226,11 +234,19 @@ static void context_deinit_objs(OSSL_LIB_CTX *ctx)
ctx->provider_conf = NULL;
}

/* P2. We want decoder_store to be cleaned up before the provider store */
/*
* P2. We want decoder_store/decoder_cache to be cleaned up before the
* provider store
*/
if (ctx->decoder_store != NULL) {
ossl_method_store_free(ctx->decoder_store);
ctx->decoder_store = NULL;
}
if (ctx->decoder_cache != NULL) {
ossl_decoder_cache_free(ctx->decoder_cache);
ctx->decoder_cache = NULL;
}


/* P2. We want encoder_store to be cleaned up before the provider store */
if (ctx->encoder_store != NULL) {
Expand Down Expand Up @@ -559,6 +575,8 @@ void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index)
return ctx->child_provider;
case OSSL_LIB_CTX_DECODER_STORE_INDEX:
return ctx->decoder_store;
case OSSL_LIB_CTX_DECODER_CACHE_INDEX:
return ctx->decoder_cache;
case OSSL_LIB_CTX_ENCODER_STORE_INDEX:
return ctx->encoder_store;
case OSSL_LIB_CTX_STORE_LOADER_STORE_INDEX:
Expand Down
31 changes: 31 additions & 0 deletions crypto/encode_decode/decoder_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,37 @@ void ossl_decoder_instance_free(OSSL_DECODER_INSTANCE *decoder_inst)
}
}

OSSL_DECODER_INSTANCE *ossl_decoder_instance_dup(const OSSL_DECODER_INSTANCE *src)
{
OSSL_DECODER_INSTANCE *dest;
const OSSL_PROVIDER *prov;
void *provctx;

if ((dest = OPENSSL_zalloc(sizeof(*dest))) == NULL)
return NULL;

*dest = *src;
if (!OSSL_DECODER_up_ref(dest->decoder)) {
ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR);
goto err;
}
prov = OSSL_DECODER_get0_provider(dest->decoder);
provctx = OSSL_PROVIDER_get0_provider_ctx(prov);

dest->decoderctx = dest->decoder->newctx(provctx);
if (dest->decoderctx == NULL) {
ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR);
OSSL_DECODER_free(dest->decoder);
goto err;
}

return dest;

err:
OPENSSL_free(dest);
return NULL;
}

int ossl_decoder_ctx_add_decoder_inst(OSSL_DECODER_CTX *ctx,
OSSL_DECODER_INSTANCE *di)
{
Expand Down

0 comments on commit 32d3c3a

Please sign in to comment.