diff options
author | slontis <shane.lontis@oracle.com> | 2022-10-05 09:57:51 +1000 |
---|---|---|
committer | Hugo Landau <hlandau@openssl.org> | 2022-10-13 13:23:25 +0100 |
commit | c3b46409559c18f103ebb2221c6f8af3cd7db00d (patch) | |
tree | 033dd2aaa9f0c8c9ea481a5c711a4e5c3db75522 | |
parent | 9eaf07ffe39e76aca2dfb8e22b8060c75fcbd8e0 (diff) | |
download | openssl-new-c3b46409559c18f103ebb2221c6f8af3cd7db00d.tar.gz |
Improve performance of the encoder collection
Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Hugo Landau <hlandau@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19344)
-rw-r--r-- | crypto/encode_decode/encoder_pkey.c | 80 |
1 files changed, 51 insertions, 29 deletions
diff --git a/crypto/encode_decode/encoder_pkey.c b/crypto/encode_decode/encoder_pkey.c index 38239f810f..1a09b01f49 100644 --- a/crypto/encode_decode/encoder_pkey.c +++ b/crypto/encode_decode/encoder_pkey.c @@ -17,6 +17,7 @@ #include <openssl/trace.h> #include "internal/provider.h" #include "internal/property.h" +#include "internal/namemap.h" #include "crypto/evp.h" #include "encoder_local.h" @@ -72,6 +73,7 @@ int OSSL_ENCODER_CTX_set_passphrase_cb(OSSL_ENCODER_CTX *ctx, struct collected_encoder_st { STACK_OF(OPENSSL_CSTRING) *names; + int *id_names; const char *output_structure; const char *output_type; @@ -85,41 +87,41 @@ struct collected_encoder_st { static void collect_encoder(OSSL_ENCODER *encoder, void *arg) { struct collected_encoder_st *data = arg; - size_t i, end_i; + const OSSL_PROVIDER *prov; if (data->error_occurred) return; data->error_occurred = 1; /* Assume the worst */ - if (data->names == NULL) - return; - - end_i = sk_OPENSSL_CSTRING_num(data->names); - for (i = 0; i < end_i; i++) { - const char *name = sk_OPENSSL_CSTRING_value(data->names, i); - const OSSL_PROVIDER *prov = OSSL_ENCODER_get0_provider(encoder); + prov = OSSL_ENCODER_get0_provider(encoder); + /* + * collect_encoder() is called in two passes, one where the encoders + * from the same provider as the keymgmt are looked up, and one where + * the other encoders are looked up. |data->flag_find_same_provider| + * tells us which pass we're in. + */ + if ((data->keymgmt_prov == prov) == data->flag_find_same_provider) { void *provctx = OSSL_PROVIDER_get0_provider_ctx(prov); - - /* - * collect_encoder() is called in two passes, one where the encoders - * from the same provider as the keymgmt are looked up, and one where - * the other encoders are looked up. |data->flag_find_same_provider| - * tells us which pass we're in. - */ - if ((data->keymgmt_prov == prov) != data->flag_find_same_provider) - continue; - - if (!OSSL_ENCODER_is_a(encoder, name) - || (encoder->does_selection != NULL - && !encoder->does_selection(provctx, data->ctx->selection)) - || (data->keymgmt_prov != prov - && encoder->import_object == NULL)) - continue; - - /* Only add each encoder implementation once */ - if (OSSL_ENCODER_CTX_add_encoder(data->ctx, encoder)) - break; + size_t i, end_i = sk_OPENSSL_CSTRING_num(data->names); + int match; + + for (i = 0; i < end_i; i++) { + if (data->flag_find_same_provider) + match = (data->id_names[i] == encoder->base.id); + else + match = OSSL_ENCODER_is_a(encoder, sk_OPENSSL_CSTRING_value(data->names, i)); + if (!match + || (encoder->does_selection != NULL + && !encoder->does_selection(provctx, data->ctx->selection)) + || (data->keymgmt_prov != prov + && encoder->import_object == NULL)) + continue; + + /* Only add each encoder implementation once */ + if (OSSL_ENCODER_CTX_add_encoder(data->ctx, encoder)) + break; + } } data->error_occurred = 0; /* All is good now */ @@ -227,7 +229,8 @@ static int ossl_encoder_ctx_setup_for_pkey(OSSL_ENCODER_CTX *ctx, struct construct_data_st *data = NULL; const OSSL_PROVIDER *prov = NULL; OSSL_LIB_CTX *libctx = NULL; - int ok = 0; + int ok = 0, i, end; + OSSL_NAMEMAP *namemap; if (!ossl_assert(ctx != NULL) || !ossl_assert(pkey != NULL)) { ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); @@ -269,8 +272,26 @@ static int ossl_encoder_ctx_setup_for_pkey(OSSL_ENCODER_CTX *ctx, encoder_data.error_occurred = 0; encoder_data.keymgmt_prov = prov; encoder_data.ctx = ctx; + encoder_data.id_names = NULL; /* + * collect_encoder() is called many times, and for every call it converts all encoder_data.names + * into namemap ids if it calls OSSL_ENCODER_is_a(). We cache the ids here instead, + * and can use them for encoders with the same provider as the keymgmt. + */ + namemap = ossl_namemap_stored(libctx); + end = sk_OPENSSL_CSTRING_num(encoder_data.names); + if (end > 0) { + encoder_data.id_names = OPENSSL_malloc(end * sizeof(int)); + if (encoder_data.id_names == NULL) + goto err; + for (i = 0; i < end; ++i) { + const char *name = sk_OPENSSL_CSTRING_value(keymgmt_data.names, i); + + encoder_data.id_names[i] = ossl_namemap_name2num(namemap, name); + } + } + /* * Place the encoders with the a different provider as the keymgmt * last (the chain is processed in reverse order) */ @@ -284,6 +305,7 @@ static int ossl_encoder_ctx_setup_for_pkey(OSSL_ENCODER_CTX *ctx, encoder_data.flag_find_same_provider = 1; OSSL_ENCODER_do_all_provided(libctx, collect_encoder, &encoder_data); + OPENSSL_free(encoder_data.id_names); sk_OPENSSL_CSTRING_free(keymgmt_data.names); if (encoder_data.error_occurred) { ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_CRYPTO_LIB); |