struct algorithm_data_st {
OPENSSL_CTX *libctx;
int operation_id; /* May be zero for finding them all */
+ int (*pre)(OSSL_PROVIDER *, int operation_id, void *data, int *result);
void (*fn)(OSSL_PROVIDER *, const OSSL_ALGORITHM *, int no_store,
void *data);
+ int (*post)(OSSL_PROVIDER *, int operation_id, int no_store, void *data,
+ int *result);
void *data;
};
for (cur_operation = first_operation;
cur_operation <= last_operation;
cur_operation++) {
- const OSSL_ALGORITHM *map =
- ossl_provider_query_operation(provider, cur_operation,
- &no_store);
+ const OSSL_ALGORITHM *map = NULL;
+ int ret;
+ /* Do we fulfill pre-conditions? */
+ if (data->pre == NULL) {
+ /* If there is no pre-condition function, assume "yes" */
+ ret = 1;
+ } else {
+ if (!data->pre(provider, cur_operation, data->data, &ret))
+ /* Error, bail out! */
+ return 0;
+ }
+
+ /* If pre-condition not fulfilled, go to the next operation */
+ if (!ret)
+ continue;
+
+ map = ossl_provider_query_operation(provider, cur_operation,
+ &no_store);
if (map == NULL)
continue;
- ok = 1; /* As long as we've found *something* */
while (map->algorithm_names != NULL) {
const OSSL_ALGORITHM *thismap = map++;
data->fn(provider, thismap, no_store, data->data);
}
+
+ /* Do we fulfill post-conditions? */
+ if (data->post == NULL) {
+ /* If there is no post-condition function, assume "yes" */
+ ret = 1;
+ } else {
+ if (!data->post(provider, cur_operation, no_store, data->data,
+ &ret))
+ /* Error, bail out! */
+ return 0;
+ }
+
+ /* If post-condition fulfilled, set general success */
+ if (ret)
+ ok = 1;
}
return ok;
void ossl_algorithm_do_all(OPENSSL_CTX *libctx, int operation_id,
OSSL_PROVIDER *provider,
+ int (*pre)(OSSL_PROVIDER *, int operation_id,
+ void *data, int *result),
void (*fn)(OSSL_PROVIDER *provider,
const OSSL_ALGORITHM *algo,
int no_store, void *data),
+ int (*post)(OSSL_PROVIDER *, int operation_id,
+ int no_store, void *data, int *result),
void *data)
{
- struct algorithm_data_st cbdata;
+ struct algorithm_data_st cbdata = { 0, };
cbdata.libctx = libctx;
cbdata.operation_id = operation_id;
+ cbdata.pre = pre;
cbdata.fn = fn;
+ cbdata.post = post;
cbdata.data = data;
if (provider == NULL)
void *mcm_data;
};
+static int ossl_method_construct_precondition(OSSL_PROVIDER *provider,
+ int operation_id, void *cbdata,
+ int *result)
+{
+ if (!ossl_assert(result != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (!ossl_provider_test_operation_bit(provider, operation_id, result))
+ return 0;
+
+ /*
+ * The result we get tells if methods have already been constructed.
+ * However, we want to tell whether construction should happen (true)
+ * or not (false), which is the opposite of what we got.
+ */
+ *result = !*result;
+
+ return 1;
+}
+
+static int ossl_method_construct_postcondition(OSSL_PROVIDER *provider,
+ int operation_id, int no_store,
+ void *cbdata, int *result)
+{
+ if (!ossl_assert(result != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ *result = 1;
+ return no_store != 0
+ || ossl_provider_set_operation_bit(provider, operation_id);
+}
+
static void ossl_method_construct_this(OSSL_PROVIDER *provider,
const OSSL_ALGORITHM *algo,
int no_store, void *cbdata)
cbdata.mcm = mcm;
cbdata.mcm_data = mcm_data;
ossl_algorithm_do_all(libctx, operation_id, NULL,
- ossl_method_construct_this, &cbdata);
+ ossl_method_construct_precondition,
+ ossl_method_construct_this,
+ ossl_method_construct_postcondition,
+ &cbdata);
method = mcm->get(libctx, cbdata.store, mcm_data);
mcm->dealloc_tmp_store(cbdata.store);
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);
+
+ /*
+ * No pre- or post-condition for this call, as this only creates methods
+ * temporarly and then promptly destroys them.
+ */
+ ossl_algorithm_do_all(libctx, operation_id, NULL, NULL, do_one, NULL,
+ &data);
}
const char *evp_first_name(const OSSL_PROVIDER *prov, int name_id)
OSSL_provider_get_params_fn *get_params;
OSSL_provider_query_operation_fn *query_operation;
+ /*
+ * Cache of bit to indicate of query_operation() has been called on
+ * a specific operation or not.
+ */
+ unsigned char *operation_bits;
+ size_t operation_bits_sz;
+
/* Provider side data */
void *provctx;
};
}
# endif
#endif
+ OPENSSL_free(prov->operation_bits);
+ prov->operation_bits = NULL;
+ prov->operation_bits_sz = 0;
prov->flag_initialized = 0;
}
return prov->query_operation(prov->provctx, operation_id, no_cache);
}
+int ossl_provider_set_operation_bit(OSSL_PROVIDER *provider, size_t bitnum)
+{
+ size_t byte = bitnum / 8;
+ unsigned char bit = (1 << (bitnum % 8)) & 0xFF;
+
+ if (provider->operation_bits_sz <= byte) {
+ provider->operation_bits = OPENSSL_realloc(provider->operation_bits,
+ byte + 1);
+ if (provider->operation_bits == NULL) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ memset(provider->operation_bits + provider->operation_bits_sz,
+ '\0', byte + 1 - provider->operation_bits_sz);
+ }
+ provider->operation_bits[byte] |= bit;
+ return 1;
+}
+
+int ossl_provider_test_operation_bit(OSSL_PROVIDER *provider, size_t bitnum,
+ int *result)
+{
+ size_t byte = bitnum / 8;
+ unsigned char bit = (1 << (bitnum % 8)) & 0xFF;
+
+ if (!ossl_assert(result != NULL)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ *result = 0;
+ if (provider->operation_bits_sz > byte)
+ *result = ((provider->operation_bits[byte] & bit) != 0);
+ return 1;
+}
+
/*-
* Core functions for the provider
* ===============================
data.user_fn = (void (*)(void *, void *))fn;
data.user_arg = arg;
- ossl_algorithm_do_all(libctx, OSSL_OP_SERIALIZER, NULL,
- serializer_do_one, &data);
+
+ /*
+ * No pre- or post-condition for this call, as this only creates methods
+ * temporarly and then promptly destroys them.
+ */
+ ossl_algorithm_do_all(libctx, OSSL_OP_SERIALIZER, NULL, NULL,
+ serializer_do_one, NULL, &data);
}
void OSSL_SERIALIZER_names_do_all(const OSSL_SERIALIZER *ser,
ossl_provider_module_name, ossl_provider_module_path,
ossl_provider_library_context,
ossl_provider_teardown, ossl_provider_gettable_params,
-ossl_provider_get_params, ossl_provider_query_operation
+ossl_provider_get_params, ossl_provider_query_operation,
+ossl_provider_set_operation_bit, ossl_provider_test_operation_bit
- internal provider routines
=head1 SYNOPSIS
int operation_id,
int *no_cache);
+ int ossl_provider_set_operation_bit(OSSL_PROVIDER *provider, size_t bitnum);
+ int ossl_provider_test_operation_bit(OSSL_PROVIDER *provider, size_t bitnum,
+ int *result);
+
=head1 DESCRIPTION
I<OSSL_PROVIDER> is a type that holds all the necessary information
It should return an array of I<OSSL_ALGORITHM> for the given
I<operation_id>.
+ossl_provider_set_operation_bit() registers a 1 for operation I<bitnum>
+in a bitstring that's internal to I<provider>.
+
+ossl_provider_tests_operation_bit() checks if the bit operation I<bitnum>
+is set (1) or not (0) in the internal I<provider> bitstring, and sets
+I<*result> to 1 or 0 accorddingly.
+
=head1 NOTES
Locating a provider module happens as follows:
ossl_provider_get_params() returns 1 on success, or 0 on error.
If this function isn't available in the provider, 0 is returned.
+ossl_provider_set_operation_bit() and ossl_provider_test_operation_bit()
+return 1 on success, or 0 on error.
+
=head1 SEE ALSO
L<OSSL_PROVIDER(3)>, L<provider(7)>, L<openssl(1)>
void ossl_algorithm_do_all(OPENSSL_CTX *libctx, int operation_id,
OSSL_PROVIDER *provider,
+ int (*pre)(OSSL_PROVIDER *, int operation_id,
+ void *data, int *result),
void (*fn)(OSSL_PROVIDER *provider,
const OSSL_ALGORITHM *algo,
int no_store, void *data),
+ int (*post)(OSSL_PROVIDER *, int operation_id,
+ int no_store, void *data, int *result),
void *data);
#endif
int operation_id,
int *no_cache);
+/* Cache of bits to see if we already queried an operation */
+int ossl_provider_set_operation_bit(OSSL_PROVIDER *provider, size_t bitnum);
+int ossl_provider_test_operation_bit(OSSL_PROVIDER *provider, size_t bitnum,
+ int *result);
+
/* Configuration */
void ossl_provider_add_conf_module(void);