ENCODER: Don't pass libctx to OSSL_ENCODER_CTX_new_by_EVP_PKEY()
authorRichard Levitte <levitte@openssl.org>
Fri, 27 Nov 2020 06:59:02 +0000 (07:59 +0100)
committerRichard Levitte <levitte@openssl.org>
Wed, 2 Dec 2020 12:36:49 +0000 (13:36 +0100)
The passed 'pkey' already contains a library context, and the encoder
implementations should be found within the same context, so passing an
explicit library context seems unnecessary, and potentially dangerous.

It should be noted that it's possible to pass an EVP_PKEY with a
legacy internal key.  The condition there is that it doesn't have a
library context assigned to it, so the NULL library context is used
automatically, thus requiring that appropriate encoders are available
through that context.

Fixes #13544

Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/13545)

crypto/encode_decode/encoder_pkey.c
doc/man3/OSSL_ENCODER_CTX_new_by_EVP_PKEY.pod
include/openssl/encoder.h

index 594543b19ee78c0f886b7e792bd9e3a5cec5c38b..e8e1c77b5f159a919b8b5814b2823a68f208def1 100644 (file)
@@ -210,10 +210,10 @@ static void encoder_destruct_EVP_PKEY(void *arg)
 static int ossl_encoder_ctx_setup_for_EVP_PKEY(OSSL_ENCODER_CTX *ctx,
                                                const EVP_PKEY *pkey,
                                                int selection,
-                                               OSSL_LIB_CTX *libctx,
                                                const char *propquery)
 {
     struct construct_data_st *data = NULL;
+    OSSL_LIB_CTX *libctx = NULL;
     int ok = 0;
 
     if (!ossl_assert(ctx != NULL) || !ossl_assert(pkey != NULL)) {
@@ -221,6 +221,12 @@ static int ossl_encoder_ctx_setup_for_EVP_PKEY(OSSL_ENCODER_CTX *ctx,
         return 0;
     }
 
+    if (evp_pkey_is_provided(pkey)) {
+        const OSSL_PROVIDER *prov = EVP_KEYMGMT_provider(pkey->keymgmt);
+
+        libctx = ossl_provider_libctx(prov);
+    }
+
     if (pkey->keymgmt != NULL) {
         struct collected_encoder_st encoder_data;
         struct collected_names_st keymgmt_data;
@@ -280,16 +286,33 @@ OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey,
                                                    int selection,
                                                    const char *output_type,
                                                    const char *output_struct,
-                                                   OSSL_LIB_CTX *libctx,
                                                    const char *propquery)
 {
     OSSL_ENCODER_CTX *ctx = NULL;
+    OSSL_LIB_CTX *libctx = NULL;
+
+    if (pkey == NULL) {
+        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
+        return NULL;
+    }
+
+    if (!evp_pkey_is_assigned(pkey)) {
+        ERR_raise_data(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_INVALID_ARGUMENT,
+                       "The passed EVP_PKEY must be assigned a key");
+        return NULL;
+    }
 
     if ((ctx = OSSL_ENCODER_CTX_new()) == NULL) {
         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
 
+    if (evp_pkey_is_provided(pkey)) {
+        const OSSL_PROVIDER *prov = EVP_KEYMGMT_provider(pkey->keymgmt);
+
+        libctx = ossl_provider_libctx(prov);
+    }
+
     OSSL_TRACE_BEGIN(ENCODER) {
         BIO_printf(trc_out,
                    "(ctx %p) Looking for %s encoders with selection %d\n",
@@ -302,8 +325,7 @@ OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey,
         && (output_struct == NULL
             || OSSL_ENCODER_CTX_set_output_structure(ctx, output_struct))
         && OSSL_ENCODER_CTX_set_selection(ctx, selection)
-        && ossl_encoder_ctx_setup_for_EVP_PKEY(ctx, pkey, selection,
-                                               libctx, propquery)
+        && ossl_encoder_ctx_setup_for_EVP_PKEY(ctx, pkey, selection, propquery)
         && OSSL_ENCODER_CTX_add_extra(ctx, libctx, propquery)) {
         OSSL_TRACE_BEGIN(ENCODER) {
             BIO_printf(trc_out, "(ctx %p) Got %d encoders\n",
index 97ffaa56cdc1f98ad26e0149ed9753a7abfedbaa..403d7a00befa314029877487b5667cd89f067f0f 100644 (file)
@@ -18,7 +18,7 @@ OSSL_ENCODER_CTX_set_passphrase_ui
  OSSL_ENCODER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey, int selection,
                                   const char *output_type,
                                   const char *output_structure,
-                                  OSSL_LIB_CTX *libctx, const char *propquery);
+                                  const char *propquery);
 
  int OSSL_ENCODER_CTX_set_cipher(OSSL_ENCODER_CTX *ctx,
                                  const char *cipher_name,
@@ -51,7 +51,7 @@ L<EVP_KEYMGMT(3)> implementation associated with I<pkey> to build a list of
 applicable encoder implementations that are used to process the I<pkey> into
 the encoding named by I<output_type>, with the outermost structure named by
 I<output_structure> if that's relevant.  All these implementations are
-implicitly fetched using I<libctx> and I<propquery>.
+implicitly fetched, with I<propquery> for finer selection.
 
 If no suitable encoder implementation is found,
 OSSL_ENCODER_CTX_new_by_EVP_PKEY() still creates a B<OSSL_ENCODER_CTX>, but
index f50d16517edf5d5fbd71541354b35e34c1a20ab1..122a46bac952e7a2ed5a9af304862f72c1fe62af 100644 (file)
@@ -117,7 +117,6 @@ OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey,
                                                    int selection,
                                                    const char *output_type,
                                                    const char *output_struct,
-                                                   OSSL_LIB_CTX *libctx,
                                                    const char *propquery);
 
 # ifdef __cplusplus