Replumbing: give the possibility for the provider to create a context
authorRichard Levitte <levitte@openssl.org>
Tue, 30 Apr 2019 11:41:51 +0000 (13:41 +0200)
committerRichard Levitte <levitte@openssl.org>
Tue, 30 Apr 2019 13:34:23 +0000 (15:34 +0200)
OSSL_provider_init() gets another output parameter, holding a pointer
to a provider side context.  It's entirely up to the provider to
define the context and what it's being used for.  This pointer is
passed back to other provider functions, typically the provider global
get_params and set_params functions, and also the diverse algorithm
context creators, and of course, the teardown function.

With this, a provider can be instantiated more than once, or be
re-loaded as the case may be, while maintaining instance state.

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8848)

13 files changed:
crypto/evp/digest.c
crypto/evp/evp_enc.c
crypto/provider_core.c
doc/internal/man3/ossl_provider_new.pod
include/internal/provider.h
include/openssl/core.h
include/openssl/core_numbers.h
providers/common/ciphers/aes.c
providers/common/digests/sha2.c
providers/default/defltprov.c
providers/fips/fipsprov.c
providers/legacy/legacyprov.c
test/p_test.c

index 043e45629760eeba7fd24df9752fd9f4bed21269..9b10a7f3fe5cb99cb2df89aad8a712b0b8ba98ef 100644 (file)
@@ -172,7 +172,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
 
     ctx->digest = type;
     if (ctx->provctx == NULL) {
-        ctx->provctx = ctx->digest->newctx();
+        ctx->provctx = ctx->digest->newctx(ossl_provider_ctx(type->prov));
         if (ctx->provctx == NULL) {
             EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
             return 0;
index 676eaabbc4d187279369f199dd13cc7f7ea0bf43..d7ba7ddb85011fa647538d0e41977725f3032a92 100644 (file)
@@ -206,7 +206,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
 
     ctx->cipher = cipher;
     if (ctx->provctx == NULL) {
-        ctx->provctx = ctx->cipher->newctx();
+        ctx->provctx = ctx->cipher->newctx(ossl_provider_ctx(cipher->prov));
         if (ctx->provctx == NULL) {
             EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
             return 0;
index 9f4c0170457a956ea2cd615882ac872648d5d0fb..2d74f6dbb35f5e1dad26eab5a6f0d1bbb57d0769 100644 (file)
@@ -54,6 +54,9 @@ struct ossl_provider_st {
     OSSL_provider_get_param_types_fn *get_param_types;
     OSSL_provider_get_params_fn *get_params;
     OSSL_provider_query_operation_fn *query_operation;
+
+    /* Provider side data */
+    void *provctx;
 };
 DEFINE_STACK_OF(OSSL_PROVIDER)
 
@@ -275,7 +278,7 @@ void ossl_provider_free(OSSL_PROVIDER *prov)
          */
         if (ref < 2 && prov->flag_initialized) {
             if (prov->teardown != NULL)
-                prov->teardown();
+                prov->teardown(prov->provctx);
             prov->flag_initialized = 0;
         }
 
@@ -401,7 +404,8 @@ static int provider_activate(OSSL_PROVIDER *prov)
     }
 
     if (prov->init_function == NULL
-        || !prov->init_function(prov, core_dispatch, &provider_dispatch)) {
+        || !prov->init_function(prov, core_dispatch, &provider_dispatch,
+                                &prov->provctx)) {
         CRYPTOerr(CRYPTO_F_PROVIDER_ACTIVATE, ERR_R_INIT_FAIL);
         ERR_add_error_data(2, "name=", prov->name);
         DSO_free(prov->module);
@@ -448,6 +452,11 @@ int ossl_provider_activate(OSSL_PROVIDER *prov)
     return 0;
 }
 
+void *ossl_provider_ctx(const OSSL_PROVIDER *prov)
+{
+    return prov->provctx;
+}
+
 
 static int provider_forall_loaded(struct provider_store_st *store,
                                   int *found_activated,
@@ -573,18 +582,20 @@ const char *ossl_provider_module_path(OSSL_PROVIDER *prov)
 void ossl_provider_teardown(const OSSL_PROVIDER *prov)
 {
     if (prov->teardown != NULL)
-        prov->teardown();
+        prov->teardown(prov->provctx);
 }
 
 const OSSL_ITEM *ossl_provider_get_param_types(const OSSL_PROVIDER *prov)
 {
-    return prov->get_param_types == NULL ? NULL : prov->get_param_types(prov);
+    return prov->get_param_types == NULL
+        ? NULL : prov->get_param_types(prov->provctx);
 }
 
 int ossl_provider_get_params(const OSSL_PROVIDER *prov,
                              const OSSL_PARAM params[])
 {
-    return prov->get_params == NULL ? 0 : prov->get_params(prov, params);
+    return prov->get_params == NULL
+        ? 0 : prov->get_params(prov->provctx, params);
 }
 
 
@@ -592,7 +603,7 @@ const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov,
                                                     int operation_id,
                                                     int *no_cache)
 {
-    return prov->query_operation(prov, operation_id, no_cache);
+    return prov->query_operation(prov->provctx, operation_id, no_cache);
 }
 
 /*-
index aa984c93b894dd054b7a22548b0aa215a36ec870..04535086bedd1b6a0ba9951ea524a888b2431a0f 100644 (file)
@@ -5,7 +5,7 @@
 ossl_provider_find, ossl_provider_new, ossl_provider_upref,
 ossl_provider_free, ossl_provider_add_module_location,
 ossl_provider_set_fallback, ossl_provider_activate,
-ossl_provider_forall_loaded,
+ossl_provider_ctx, ossl_provider_forall_loaded,
 ossl_provider_name, ossl_provider_dso,
 ossl_provider_module_name, ossl_provider_module_path,
 ossl_provider_teardown, ossl_provider_get_param_types,
@@ -29,6 +29,9 @@ ossl_provider_get_params, ossl_provider_query_operation
  /* Load and initialize the Provider */
  int ossl_provider_activate(OSSL_PROVIDER *prov);
 
+ /* Return pointer to the provider's context */
+ void *ossl_provider_ctx(const OSSL_PROVIDER *prov);
+
  /* Iterate over all loaded providers */
  int ossl_provider_forall_loaded(OPENSSL_CTX *,
                                  int (*cb)(OSSL_PROVIDER *provider,
@@ -121,6 +124,10 @@ be located in that module, and called.
 
 =back
 
+ossl_provider_ctx() returns a context created by the provider.
+Outside of the provider, it's completely opaque, but it needs to be
+passed back to some of the provider functions.
+
 ossl_provider_forall_loaded() iterates over all the currently
 "activated" providers, and calls C<cb> for each of them.
 If no providers have been "activated" yet, it tries to activate all
index 4966cc25957c9d75a093ee8ee37502bdd5614c14..7b0531345d5969146db31de988064c311327a873 100644 (file)
@@ -45,6 +45,9 @@ int ossl_provider_add_parameter(OSSL_PROVIDER *prov, const char *name,
  */
 int ossl_provider_activate(OSSL_PROVIDER *prov);
 
+/* Return pointer to the provider's context */
+void *ossl_provider_ctx(const OSSL_PROVIDER *prov);
+
 /* Iterate over all loaded providers */
 int ossl_provider_forall_loaded(OPENSSL_CTX *,
                                 int (*cb)(OSSL_PROVIDER *provider,
index 2855b6d38581a954ed52528bca06e123a5f3443e..cf4d3f41de8c44da2bfde5f68a58cbb950472458 100644 (file)
@@ -157,10 +157,14 @@ struct ossl_param_st {
  * |in|         is the array of functions that the Core passes to the provider.
  * |out|        will be the array of base functions that the provider passes
  *              back to the Core.
+ * |provctx|    a provider side context object, optionally created if the
+ *              provider needs it.  This value is passed to other provider
+ *              functions, notably other context constructors.
  */
 typedef int (OSSL_provider_init_fn)(const OSSL_PROVIDER *provider,
                                     const OSSL_DISPATCH *in,
-                                    const OSSL_DISPATCH **out);
+                                    const OSSL_DISPATCH **out,
+                                    void **provctx);
 # ifdef __VMS
 #  pragma names save
 #  pragma names uppercase,truncated
index 74b3fdfda980aa27d7ff7930e7baa6be6da6c0f6..8ce00c3e6fe3b127bd99e1668c52fa531de9024a 100644 (file)
@@ -60,17 +60,16 @@ OSSL_CORE_MAKE_FUNC(int,core_get_params,(const OSSL_PROVIDER *prov,
 
 /* Functions provided by the provider to the Core, reserved numbers 1024-1535 */
 # define OSSL_FUNC_PROVIDER_TEARDOWN         1024
-OSSL_CORE_MAKE_FUNC(void,provider_teardown,(void))
+OSSL_CORE_MAKE_FUNC(void,provider_teardown,(void *provctx))
 # define OSSL_FUNC_PROVIDER_GET_PARAM_TYPES  1025
 OSSL_CORE_MAKE_FUNC(const OSSL_ITEM *,
-                    provider_get_param_types,(const OSSL_PROVIDER *prov))
+                    provider_get_param_types,(void *provctx))
 # define OSSL_FUNC_PROVIDER_GET_PARAMS       1026
-OSSL_CORE_MAKE_FUNC(int,provider_get_params,(const OSSL_PROVIDER *prov,
+OSSL_CORE_MAKE_FUNC(int,provider_get_params,(void *provctx,
                                              const OSSL_PARAM params[]))
 # define OSSL_FUNC_PROVIDER_QUERY_OPERATION  1027
 OSSL_CORE_MAKE_FUNC(const OSSL_ALGORITHM *,provider_query_operation,
-                    (const OSSL_PROVIDER *, int operation_id,
-                     const int *no_store))
+                    (void *provctx, int operation_id, const int *no_store))
 
 /* Digests */
 
@@ -87,19 +86,20 @@ OSSL_CORE_MAKE_FUNC(const OSSL_ALGORITHM *,provider_query_operation,
 # define OSSL_FUNC_DIGEST_BLOCK_SIZE        9
 
 
-OSSL_CORE_MAKE_FUNC(void *, OP_digest_newctx, (void))
-OSSL_CORE_MAKE_FUNC(int, OP_digest_init, (void *vctx))
+OSSL_CORE_MAKE_FUNC(void *, OP_digest_newctx, (void *provctx))
+OSSL_CORE_MAKE_FUNC(int, OP_digest_init, (void *dctx))
 OSSL_CORE_MAKE_FUNC(int, OP_digest_update,
-                    (void *, const unsigned char *in, size_t inl))
+                    (void *dctx, const unsigned char *in, size_t inl))
 OSSL_CORE_MAKE_FUNC(int, OP_digest_final,
-                    (void *, unsigned char *out, size_t *outl, size_t outsz))
+                    (void *dctx,
+                     unsigned char *out, size_t *outl, size_t outsz))
 OSSL_CORE_MAKE_FUNC(int, OP_digest_digest,
-                    (const unsigned char *in, size_t inl, unsigned char *out,
-                     size_t *out_l, size_t outsz))
+                    (void *provctx, const unsigned char *in, size_t inl,
+                     unsigned char *out, size_t *out_l, size_t outsz))
 
-OSSL_CORE_MAKE_FUNC(void, OP_digest_cleanctx, (void *vctx))
-OSSL_CORE_MAKE_FUNC(void, OP_digest_freectx, (void *vctx))
-OSSL_CORE_MAKE_FUNC(void *, OP_digest_dupctx, (void *vctx))
+OSSL_CORE_MAKE_FUNC(void, OP_digest_cleanctx, (void *dctx))
+OSSL_CORE_MAKE_FUNC(void, OP_digest_freectx, (void *dctx))
+OSSL_CORE_MAKE_FUNC(void *, OP_digest_dupctx, (void *dctx))
 OSSL_CORE_MAKE_FUNC(size_t, OP_digest_size, (void))
 OSSL_CORE_MAKE_FUNC(size_t, OP_digest_block_size, (void))
 
@@ -123,35 +123,37 @@ OSSL_CORE_MAKE_FUNC(size_t, OP_digest_block_size, (void))
 # define OSSL_FUNC_CIPHER_CTX_GET_PARAMS            13
 # define OSSL_FUNC_CIPHER_CTX_SET_PARAMS            14
 
-OSSL_CORE_MAKE_FUNC(void *, OP_cipher_newctx, (void))
-OSSL_CORE_MAKE_FUNC(int, OP_cipher_encrypt_init, (void *vctx,
+OSSL_CORE_MAKE_FUNC(void *, OP_cipher_newctx, (void *provctx))
+OSSL_CORE_MAKE_FUNC(int, OP_cipher_encrypt_init, (void *cctx,
                                                   const unsigned char *key,
                                                   size_t keylen,
                                                   const unsigned char *iv,
                                                   size_t ivlen))
-OSSL_CORE_MAKE_FUNC(int, OP_cipher_decrypt_init, (void *vctx,
+OSSL_CORE_MAKE_FUNC(int, OP_cipher_decrypt_init, (void *cctx,
                                                   const unsigned char *key,
                                                   size_t keylen,
                                                   const unsigned char *iv,
                                                   size_t ivlen))
 OSSL_CORE_MAKE_FUNC(int, OP_cipher_update,
-                    (void *, unsigned char *out, size_t *outl, size_t outsize,
+                    (void *cctx,
+                     unsigned char *out, size_t *outl, size_t outsize,
                      const unsigned char *in, size_t inl))
 OSSL_CORE_MAKE_FUNC(int, OP_cipher_final,
-                    (void *, unsigned char *out, size_t *outl, size_t outsize))
+                    (void *cctx,
+                     unsigned char *out, size_t *outl, size_t outsize))
 OSSL_CORE_MAKE_FUNC(int, OP_cipher_cipher,
-                    (void *,
+                    (void *cctx,
                      unsigned char *out, size_t *outl, size_t outsize,
                      const unsigned char *in, size_t inl))
-OSSL_CORE_MAKE_FUNC(void, OP_cipher_freectx, (void *vctx))
-OSSL_CORE_MAKE_FUNC(void *, OP_cipher_dupctx, (void *vctx))
+OSSL_CORE_MAKE_FUNC(void, OP_cipher_freectx, (void *cctx))
+OSSL_CORE_MAKE_FUNC(void *, OP_cipher_dupctx, (void *cctx))
 OSSL_CORE_MAKE_FUNC(size_t, OP_cipher_key_length, (void))
 OSSL_CORE_MAKE_FUNC(size_t, OP_cipher_iv_length, (void))
 OSSL_CORE_MAKE_FUNC(size_t, OP_cipher_block_size, (void))
 OSSL_CORE_MAKE_FUNC(int, OP_cipher_get_params, (const OSSL_PARAM params[]))
-OSSL_CORE_MAKE_FUNC(int, OP_cipher_ctx_get_params, (void *vctx,
+OSSL_CORE_MAKE_FUNC(int, OP_cipher_ctx_get_params, (void *cctx,
                                                     const OSSL_PARAM params[]))
-OSSL_CORE_MAKE_FUNC(int, OP_cipher_ctx_set_params, (void *vctx,
+OSSL_CORE_MAKE_FUNC(int, OP_cipher_ctx_set_params, (void *cctx,
                                                     const OSSL_PARAM params[]))
 
 
index 2e93461621c2b18d90b33297ab9e5e19cb6e6aea..8d91ff48044a8e2eee34937e4baacca469060e0b 100644 (file)
@@ -270,7 +270,7 @@ static int aes_cipher(void *vctx,
 
 #define IMPLEMENT_new_ctx(lcmode, UCMODE, len) \
     static OSSL_OP_cipher_newctx_fn aes_##len##_##lcmode##_newctx; \
-    static void *aes_##len##_##lcmode##_newctx(void) \
+    static void *aes_##len##_##lcmode##_newctx(void *provctx) \
     { \
         PROV_AES_KEY *ctx = OPENSSL_zalloc(sizeof(*ctx)); \
     \
index c9f616db68b6c09327815071cfc7401dcc833510..5b219ab7834d8ba9b9ec102b0c63118033ef9c93 100644 (file)
@@ -40,7 +40,7 @@ static int sha256_final(void *ctx,
     return 0;
 }
 
-static void *sha256_newctx(void)
+static void *sha256_newctx(void *provctx)
 {
     SHA256_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
 
index cba2dccf03517c7ca5a3e23dfccaa33c280bbcf3..95b2abfdb9d50a99b1d7f95ede9cd6977b0a4ff0 100644 (file)
@@ -106,7 +106,8 @@ OSSL_provider_init_fn ossl_default_provider_init;
 
 int ossl_default_provider_init(const OSSL_PROVIDER *provider,
                                const OSSL_DISPATCH *in,
-                               const OSSL_DISPATCH **out)
+                               const OSSL_DISPATCH **out,
+                               void **provctx)
 {
     for (; in->function_id != 0; in++) {
         switch (in->function_id) {
index d3671b5a36d851f157fcd1207fcb03e433cf7bcc..1b8316388b31ab422ec8e0c6dba14cc19869613b 100644 (file)
@@ -78,7 +78,8 @@ static const OSSL_DISPATCH fips_dispatch_table[] = {
 
 int OSSL_provider_init(const OSSL_PROVIDER *provider,
                        const OSSL_DISPATCH *in,
-                       const OSSL_DISPATCH **out)
+                       const OSSL_DISPATCH **out,
+                       void **provctx)
 {
     for (; in->function_id != 0; in++) {
         switch (in->function_id) {
index 48e89338d4b4f8fddc9b1d490896402747d36245..2d42229fea17f232459eafde7db2971c4a0eea82 100644 (file)
@@ -80,7 +80,8 @@ static const OSSL_DISPATCH legacy_dispatch_table[] = {
 
 int OSSL_provider_init(const OSSL_PROVIDER *provider,
                        const OSSL_DISPATCH *in,
-                       const OSSL_DISPATCH **out)
+                       const OSSL_DISPATCH **out,
+                       void **provctx)
 {
     for (; in->function_id != 0; in++) {
         switch (in->function_id) {
index bf13a0a070c70827a42d4b6ec15f8bb6bb8d8a40..93196f74c420c704fe0f4df9d86307f99d07d50f 100644 (file)
@@ -38,13 +38,18 @@ static const OSSL_ITEM p_param_types[] = {
     { 0, NULL }
 };
 
-static const OSSL_ITEM *p_get_param_types(const OSSL_PROVIDER *_)
+/* This is a trick to ensure we define the provider functions correctly */
+static OSSL_provider_get_param_types_fn p_get_param_types;
+static OSSL_provider_get_params_fn p_get_params;
+
+static const OSSL_ITEM *p_get_param_types(void *_)
 {
     return p_param_types;
 }
 
-static int p_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[])
+static int p_get_params(void *vprov, const OSSL_PARAM params[])
 {
+    const OSSL_PROVIDER *prov = vprov;
     const OSSL_PARAM *p = params;
     int ok = 1;
 
@@ -101,7 +106,8 @@ static const OSSL_DISPATCH p_test_table[] = {
 
 int OSSL_provider_init(const OSSL_PROVIDER *provider,
                        const OSSL_DISPATCH *in,
-                       const OSSL_DISPATCH **out)
+                       const OSSL_DISPATCH **out,
+                       void **provctx)
 {
     for (; in->function_id != 0; in++) {
         switch (in->function_id) {
@@ -117,6 +123,9 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
         }
     }
 
+    /* Because we use this in get_params, we need to pass it back */
+    *provctx = (void *)provider;
+
     *out = p_test_table;
     return 1;
 }