summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorslontis <shane.lontis@oracle.com>2022-10-05 09:57:51 +1000
committerHugo Landau <hlandau@openssl.org>2022-10-13 13:23:25 +0100
commitc3b46409559c18f103ebb2221c6f8af3cd7db00d (patch)
tree033dd2aaa9f0c8c9ea481a5c711a4e5c3db75522
parent9eaf07ffe39e76aca2dfb8e22b8060c75fcbd8e0 (diff)
downloadopenssl-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.c80
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);