EVP_R_NO_CIPHER_SET:131:no cipher set
EVP_R_NO_DEFAULT_DIGEST:158:no default digest
EVP_R_NO_DIGEST_SET:139:no digest set
+EVP_R_NO_KEYMGMT_AVAILABLE:199:no keymgmt available
EVP_R_NO_KEYMGMT_PRESENT:196:no keymgmt present
EVP_R_NO_KEY_SET:154:no key set
EVP_R_NO_OPERATION_SET:149:no operation set
}
static void *evp_md_from_dispatch(const char *name, const OSSL_DISPATCH *fns,
- OSSL_PROVIDER *prov)
+ OSSL_PROVIDER *prov, void *unused)
{
EVP_MD *md = NULL;
int fncnt = 0;
{
EVP_MD *md =
evp_generic_fetch(ctx, OSSL_OP_DIGEST, algorithm, properties,
- evp_md_from_dispatch, evp_md_up_ref,
+ evp_md_from_dispatch, NULL, evp_md_up_ref,
evp_md_free);
return md;
{
evp_generic_do_all(libctx, OSSL_OP_DIGEST,
(void (*)(void *, void *))fn, arg,
- evp_md_from_dispatch, evp_md_free);
+ evp_md_from_dispatch, NULL, evp_md_free);
}
static void *evp_cipher_from_dispatch(const char *name,
const OSSL_DISPATCH *fns,
- OSSL_PROVIDER *prov)
+ OSSL_PROVIDER *prov,
+ void *unused)
{
EVP_CIPHER *cipher = NULL;
int fnciphcnt = 0, fnctxcnt = 0;
{
EVP_CIPHER *cipher =
evp_generic_fetch(ctx, OSSL_OP_CIPHER, algorithm, properties,
- evp_cipher_from_dispatch, evp_cipher_up_ref,
+ evp_cipher_from_dispatch, NULL, evp_cipher_up_ref,
evp_cipher_free);
return cipher;
{
evp_generic_do_all(libctx, OSSL_OP_CIPHER,
(void (*)(void *, void *))fn, arg,
- evp_cipher_from_dispatch, evp_cipher_free);
+ evp_cipher_from_dispatch, NULL, evp_cipher_free);
}
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_CIPHER_SET), "no cipher set"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_DEFAULT_DIGEST), "no default digest"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_DIGEST_SET), "no digest set"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEYMGMT_AVAILABLE),
+ "no keymgmt available"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEYMGMT_PRESENT), "no keymgmt present"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEY_SET), "no key set"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_OPERATION_SET), "no operation set"},
const char *name;
OSSL_METHOD_CONSTRUCT_METHOD *mcm;
void *(*method_from_dispatch)(const char *, const OSSL_DISPATCH *,
- OSSL_PROVIDER *);
+ OSSL_PROVIDER *, void *);
+ void *method_data;
int (*refcnt_up_method)(void *method);
void (*destruct_method)(void *method);
};
{
struct method_data_st *methdata = data;
- return methdata->method_from_dispatch(name, fns, prov);
+ return methdata->method_from_dispatch(name, fns, prov,
+ methdata->method_data);
}
static void destruct_method(void *method, void *data)
const char *name, const char *properties,
void *(*new_method)(const char *name,
const OSSL_DISPATCH *fns,
- OSSL_PROVIDER *prov),
+ OSSL_PROVIDER *prov,
+ void *method_data),
+ void *method_data,
int (*up_ref_method)(void *),
void (*free_method)(void *))
{
mcmdata.destruct_method = free_method;
mcmdata.refcnt_up_method = up_ref_method;
mcmdata.destruct_method = free_method;
+ mcmdata.method_data = method_data;
if ((method = ossl_method_construct(libctx, operation_id, name,
properties, 0 /* !force_cache */,
&mcm, &mcmdata)) != NULL) {
void (*user_fn)(void *method, void *arg);
void *user_arg;
void *(*new_method)(const char *name, const OSSL_DISPATCH *fns,
- OSSL_PROVIDER *prov);
+ OSSL_PROVIDER *prov, void *method_data);
void (*free_method)(void *);
};
{
struct do_all_data_st *data = vdata;
void *method = data->new_method(algo->algorithm_name,
- algo->implementation, provider);
+ algo->implementation, provider, NULL);
if (method != NULL) {
data->user_fn(method, data->user_arg);
void *user_arg,
void *(*new_method)(const char *name,
const OSSL_DISPATCH *fns,
- OSSL_PROVIDER *prov),
+ OSSL_PROVIDER *prov,
+ void *method_data),
+ void *method_data,
void (*free_method)(void *))
{
struct do_all_data_st data;
data.free_method = free_method;
data.user_fn = user_fn;
data.user_arg = user_arg;
- ossl_algorithm_do_all(libctx, operation_id, NULL, do_one, &data);
+ ossl_algorithm_do_all(libctx, operation_id, method_data, do_one, &data);
}
const char *algorithm, const char *properties,
void *(*new_method)(const char *name,
const OSSL_DISPATCH *fns,
- OSSL_PROVIDER *prov),
+ OSSL_PROVIDER *prov,
+ void *method_data),
+ void *method_data,
int (*up_ref_method)(void *),
void (*free_method)(void *));
void evp_generic_do_all(OPENSSL_CTX *libctx, int operation_id,
void *user_arg,
void *(*new_method)(const char *name,
const OSSL_DISPATCH *fns,
- OSSL_PROVIDER *prov),
+ OSSL_PROVIDER *prov,
+ void *method_data),
+ void *method_data,
void (*free_method)(void *));
/* Helper functions to avoid duplicating code */
return exchange;
}
+struct keymgmt_data_st {
+ OPENSSL_CTX *ctx;
+ const char *properties;
+};
+
static void *evp_keyexch_from_dispatch(const char *name,
const OSSL_DISPATCH *fns,
- OSSL_PROVIDER *prov)
+ OSSL_PROVIDER *prov,
+ void *vkeymgmt_data)
{
+ /*
+ * Key exchange cannot work without a key, and key management
+ * from the same provider to manage its keys. We therefore fetch
+ * a key management method using the same algorithm and properties
+ * and pass that down to evp_generic_fetch to be passed on to our
+ * evp_keyexch_from_dispatch, which will attach the key management
+ * method to the newly created key exchange method as long as the
+ * provider matches.
+ */
+ struct keymgmt_data_st *keymgmt_data = vkeymgmt_data;
+ EVP_KEYMGMT *keymgmt = EVP_KEYMGMT_fetch(keymgmt_data->ctx, name,
+ keymgmt_data->properties);
EVP_KEYEXCH *exchange = NULL;
int fncnt = 0;
+ if (keymgmt == NULL || EVP_KEYMGMT_provider(keymgmt) != prov) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEYMGMT_AVAILABLE);
+ goto err;
+ }
+
if ((exchange = evp_keyexch_new(prov)) == NULL
|| (exchange->name = OPENSSL_strdup(name)) == NULL) {
- EVP_KEYEXCH_free(exchange);
- EVPerr(0, ERR_R_MALLOC_FAILURE);
- return NULL;
+ ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
+ goto err;
}
+ exchange->keymgmt = keymgmt;
+ keymgmt = NULL; /* avoid double free on failure below */
+
for (; fns->function_id != 0; fns++) {
switch (fns->function_id) {
case OSSL_FUNC_KEYEXCH_NEWCTX:
* and freectx. The dupctx, set_peer and set_params functions are
* optional.
*/
- EVP_KEYEXCH_free(exchange);
EVPerr(EVP_F_EVP_KEYEXCH_FROM_DISPATCH,
EVP_R_INVALID_PROVIDER_FUNCTIONS);
- return NULL;
+ goto err;
}
return exchange;
+
+ err:
+ EVP_KEYEXCH_free(exchange);
+ EVP_KEYMGMT_free(keymgmt);
+ return NULL;
}
void EVP_KEYEXCH_free(EVP_KEYEXCH *exchange)
EVP_KEYEXCH *EVP_KEYEXCH_fetch(OPENSSL_CTX *ctx, const char *algorithm,
const char *properties)
{
- /*
- * Key exchange cannot work without a key, and we key management
- * from the same provider to manage its keys.
- */
- EVP_KEYEXCH *keyexch =
- evp_generic_fetch(ctx, OSSL_OP_KEYEXCH, algorithm, properties,
- evp_keyexch_from_dispatch,
- (int (*)(void *))EVP_KEYEXCH_up_ref,
- (void (*)(void *))EVP_KEYEXCH_free);
-
- /* If the method is newly created, there's no keymgmt attached */
- if (keyexch->keymgmt == NULL) {
- EVP_KEYMGMT *keymgmt = EVP_KEYMGMT_fetch(ctx, algorithm, properties);
-
- if (keymgmt == NULL
- || (EVP_KEYEXCH_provider(keyexch)
- != EVP_KEYMGMT_provider(keymgmt))) {
- EVP_KEYEXCH_free(keyexch);
- EVP_KEYMGMT_free(keymgmt);
- EVPerr(EVP_F_EVP_KEYEXCH_FETCH, EVP_R_NO_KEYMGMT_PRESENT);
- return NULL;
- }
+ EVP_KEYEXCH *keyexch = NULL;
+ struct keymgmt_data_st keymgmt_data;
+
+ keymgmt_data.ctx = ctx;
+ keymgmt_data.properties = properties;
+ keyexch = evp_generic_fetch(ctx, OSSL_OP_KEYEXCH, algorithm, properties,
+ evp_keyexch_from_dispatch, &keymgmt_data,
+ (int (*)(void *))EVP_KEYEXCH_up_ref,
+ (void (*)(void *))EVP_KEYEXCH_free);
- keyexch->keymgmt = keymgmt;
- }
return keyexch;
}
}
static void *keymgmt_from_dispatch(const char *name, const OSSL_DISPATCH *fns,
- OSSL_PROVIDER *prov)
+ OSSL_PROVIDER *prov, void *unused)
{
EVP_KEYMGMT *keymgmt = NULL;
{
EVP_KEYMGMT *keymgmt =
evp_generic_fetch(ctx, OSSL_OP_KEYMGMT, algorithm, properties,
- keymgmt_from_dispatch,
+ keymgmt_from_dispatch, NULL,
(int (*)(void *))EVP_KEYMGMT_up_ref,
(void (*)(void *))EVP_KEYMGMT_free);
}
static void *evp_mac_from_dispatch(const char *name, const OSSL_DISPATCH *fns,
- OSSL_PROVIDER *prov)
+ OSSL_PROVIDER *prov, void *unused)
{
EVP_MAC *mac = NULL;
int fnmaccnt = 0, fnctxcnt = 0;
const char *properties)
{
return evp_generic_fetch(libctx, OSSL_OP_MAC, algorithm, properties,
- evp_mac_from_dispatch, evp_mac_up_ref,
+ evp_mac_from_dispatch, NULL, evp_mac_up_ref,
evp_mac_free);
}
{
evp_generic_do_all(libctx, OSSL_OP_MAC,
(void (*)(void *, void *))fn, arg,
- evp_mac_from_dispatch, evp_mac_free);
+ evp_mac_from_dispatch, NULL, evp_mac_free);
}
void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
const char *name, const char *properties,
- void *(*new_method)(const OSSL_DISPATCH *fns,
- OSSL_PROVIDER *prov),
+ void *(*new_method)(const char *name,
+ const OSSL_DISPATCH *fns,
+ OSSL_PROVIDER *prov,
+ void *method_data),
+ void *method_data,
int (*up_ref_method)(void *),
void (*free_method)(void *));
creates an internal method from function pointers found in the
dispatch table C<fns>.
+The algorithm I<name>, provider I<prov>, and I<method_data> are
+also passed to be used as new_method() sees fit.
=item up_ref_method()
# define EVP_F_ARIA_GCM_INIT_KEY 0
# define EVP_F_ARIA_INIT_KEY 0
# define EVP_F_B64_NEW 0
-# define EVP_F_BLAKE2B_MAC_CTRL 0
-# define EVP_F_BLAKE2B_MAC_INIT 0
-# define EVP_F_BLAKE2S_MAC_CTRL 0
-# define EVP_F_BLAKE2S_MAC_INIT 0
# define EVP_F_CAMELLIA_INIT_KEY 0
# define EVP_F_CHACHA20_POLY1305_CTRL 0
# define EVP_F_CMLL_T4_INIT_KEY 0
# define EVP_R_NO_CIPHER_SET 131
# define EVP_R_NO_DEFAULT_DIGEST 158
# define EVP_R_NO_DIGEST_SET 139
+# define EVP_R_NO_KEYMGMT_AVAILABLE 199
# define EVP_R_NO_KEYMGMT_PRESENT 196
# define EVP_R_NO_KEY_SET 154
# define EVP_R_NO_OPERATION_SET 149