diff --git a/crypto/asn1/ameth_lib.c b/crypto/asn1/ameth_lib.c index 7c385f6dd3a2dcb803f0788d5ebc482239ddce7a..cfaef87555892cb11fd6d569227b90428c9d8d52 100644 --- a/crypto/asn1/ameth_lib.c +++ b/crypto/asn1/ameth_lib.c @@ -203,20 +203,17 @@ const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe, { #ifndef OPENSSL_NO_ENGINE ENGINE *e; - for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) + ameth = ENGINE_pkey_asn1_find_str(&e, str, len); + if (ameth) { - ameth = ENGINE_get_pkey_asn1_meth_str(e, str, len); - if (ameth) - { - /* Convert structural into - * functional reference - */ - if (!ENGINE_init(e)) - ameth = NULL; - ENGINE_free(e); - *pe = e; - return ameth; - } + /* Convert structural into + * functional reference + */ + if (!ENGINE_init(e)) + ameth = NULL; + ENGINE_free(e); + *pe = e; + return ameth; } #endif *pe = NULL; diff --git a/crypto/engine/eng_int.h b/crypto/engine/eng_int.h index 8bee5962c510f639fcf2c13adacc105c35326102..f7c382c37ecc614387a6f5d59167896d2c0612da 100644 --- a/crypto/engine/eng_int.h +++ b/crypto/engine/eng_int.h @@ -127,6 +127,8 @@ ENGINE *engine_table_select(ENGINE_TABLE **table, int nid); ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f, int l); #define engine_table_select(t,n) engine_table_select_tmp(t,n,__FILE__,__LINE__) #endif +typedef void (engine_table_doall_cb)(int nid, STACK_OF(ENGINE) *sk, ENGINE *def, void *arg); +void engine_table_doall(ENGINE_TABLE *table, engine_table_doall_cb *cb, void *arg); /* Internal versions of API functions that have control over locking. These are * used between C files when functionality needs to be shared but the caller may diff --git a/crypto/engine/eng_table.c b/crypto/engine/eng_table.c index 0c1656168d50d60ed45a8bfdd6889eb4e089f6f4..3e892c8a621d62a9658fce4fb35eb3b0fc52ce6f 100644 --- a/crypto/engine/eng_table.c +++ b/crypto/engine/eng_table.c @@ -76,6 +76,14 @@ struct st_engine_table LHASH piles; }; /* ENGINE_TABLE */ + +typedef struct st_engine_pile_doall + { + engine_table_doall_cb *cb; + void *arg; + } ENGINE_PILE_DOALL; + + /* Global flags (ENGINE_TABLE_FLAG_***). */ static unsigned int table_flags = 0; @@ -313,3 +321,21 @@ end: ERR_clear_error(); return ret; } + +/* Table enumeration */ + +static void int_doall_cb(ENGINE_PILE *pile, ENGINE_PILE_DOALL *dall) + { + dall->cb(pile->nid, pile->sk, pile->funct, dall->arg); + } + +static IMPLEMENT_LHASH_DOALL_ARG_FN(int_doall_cb,ENGINE_PILE *,ENGINE_PILE_DOALL *) +void engine_table_doall(ENGINE_TABLE *table, engine_table_doall_cb *cb, + void *arg) + { + ENGINE_PILE_DOALL dall; + dall.cb = cb; + dall.arg = arg; + lh_doall_arg(&table->piles, + LHASH_DOALL_ARG_FN(int_doall_cb), &dall); + } diff --git a/crypto/engine/engine.h b/crypto/engine/engine.h index 56aaa594ed762a42445722c40e93909e7a191e25..ed966a82c563244b7a6715566046c964d330e771 100644 --- a/crypto/engine/engine.h +++ b/crypto/engine/engine.h @@ -520,6 +520,8 @@ const EVP_PKEY_METHOD *ENGINE_get_pkey_meth(ENGINE *e, int nid); const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid); const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e, const char *str, int len); +const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe, + const char *str, int len); const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e); int ENGINE_get_flags(const ENGINE *e); diff --git a/crypto/engine/tb_asnmth.c b/crypto/engine/tb_asnmth.c index b3a4fd533cc0245f92bc76466ea51e2e3a50ab9b..0972813a0251fa1c4b68bda4745da57aafad9822 100644 --- a/crypto/engine/tb_asnmth.c +++ b/crypto/engine/tb_asnmth.c @@ -193,3 +193,53 @@ const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e, } return NULL; } + +typedef struct + { + ENGINE *e; + const EVP_PKEY_ASN1_METHOD *ameth; + const char *str; + int len; + } ENGINE_FIND_STR; + +static void look_str_cb(int nid, STACK_OF(ENGINE) *sk, ENGINE *def, void *arg) + { + ENGINE_FIND_STR *lk = arg; + int i; + if (lk->ameth) + return; + for (i = 0; i < sk_ENGINE_num(sk); i++) + { + ENGINE *e = sk_ENGINE_value(sk, i); + EVP_PKEY_ASN1_METHOD *ameth; + e->pkey_asn1_meths(e, &ameth, NULL, nid); + if (((int)strlen(ameth->pem_str) == lk->len) && + !strncasecmp(ameth->pem_str, lk->str, lk->len)) + { + lk->e = e; + lk->ameth = ameth; + return; + } + } + } + +const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe, + const char *str, int len) + { + ENGINE_FIND_STR fstr; + fstr.e = NULL; + fstr.ameth = NULL; + fstr.str = str; + fstr.len = len; + CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); + engine_table_doall(pkey_asn1_meth_table, look_str_cb, &fstr); + /* If found obtain a structural reference to engine */ + if (fstr.e) + { + fstr.e->struct_ref++; + engine_ref_debug(fstr.e, 0, 1) + } + *pe = fstr.e; + CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + return fstr.ameth; + }