DECODER: Allow precise result type for OSSL_DECODER_CTX_new_by_EVP_PKEY()
authorRichard Levitte <levitte@openssl.org>
Fri, 2 Oct 2020 12:21:51 +0000 (14:21 +0200)
committerRichard Levitte <levitte@openssl.org>
Sun, 4 Oct 2020 11:01:47 +0000 (13:01 +0200)
There is some data that is very difficult to guess.  For example, DSA
parameters and X9.42 DH parameters look exactly the same, a SEQUENCE
of 3 INTEGER.  Therefore, callers may need the possibility to select
the exact keytype that they expect to get.

This will also allow use to translate d2i_TYPEPrivateKey(),
d2i_TYPEPublicKey() and d2i_TYPEParams() into OSSL_DECODER terms much
more smoothly.

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

crypto/encode_decode/decoder_pkey.c
crypto/store/store_result.c
doc/man3/OSSL_DECODER_CTX_new_by_EVP_PKEY.pod
include/crypto/decoder.h
include/openssl/decoder.h
providers/implementations/storemgmt/file_store.c
test/endecode_test.c

index 2e07d0d7cc9152beb69f35bc205d16d8913b6437..75c491f4acb65434e6ba9a2db0015443b44a72a3 100644 (file)
@@ -188,6 +188,7 @@ static void decoder_clean_EVP_PKEY_construct_arg(void *construct_data)
 
 struct collected_data_st {
     struct decoder_EVP_PKEY_data_st *process_data;
+    const char *keytype;
     STACK_OF(OPENSSL_CSTRING) *names;
     OSSL_DECODER_CTX *ctx;
 
@@ -198,6 +199,8 @@ static void collect_keymgmt(EVP_KEYMGMT *keymgmt, void *arg)
 {
     struct collected_data_st *data = arg;
 
+    if (data->keytype != NULL && !EVP_KEYMGMT_is_a(keymgmt, data->keytype))
+        return;
     if (data->error_occured)
         return;
 
@@ -253,7 +256,7 @@ static void collect_decoder(OSSL_DECODER *decoder, void *arg)
 }
 
 int ossl_decoder_ctx_setup_for_EVP_PKEY(OSSL_DECODER_CTX *ctx,
-                                        EVP_PKEY **pkey,
+                                        EVP_PKEY **pkey, const char *keytype,
                                         OPENSSL_CTX *libctx,
                                         const char *propquery)
 {
@@ -264,14 +267,14 @@ int ossl_decoder_ctx_setup_for_EVP_PKEY(OSSL_DECODER_CTX *ctx,
     if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL
         || (data->process_data =
             OPENSSL_zalloc(sizeof(*data->process_data))) == NULL
-        || (data->process_data->keymgmts
-            = sk_EVP_KEYMGMT_new_null()) == NULL
+        || (data->process_data->keymgmts = sk_EVP_KEYMGMT_new_null()) == NULL
         || (data->names = sk_OPENSSL_CSTRING_new_null()) == NULL) {
         ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     data->process_data->object = (void **)pkey;
     data->ctx = ctx;
+    data->keytype = keytype;
 
     /* First, find all keymgmts to form goals */
     EVP_KEYMGMT_do_all_provided(libctx, collect_keymgmt, data);
@@ -320,10 +323,10 @@ int ossl_decoder_ctx_setup_for_EVP_PKEY(OSSL_DECODER_CTX *ctx,
     return ok;
 }
 
-OSSL_DECODER_CTX *OSSL_DECODER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey,
-                                                   const char *input_type,
-                                                   OPENSSL_CTX *libctx,
-                                                   const char *propquery)
+OSSL_DECODER_CTX *
+OSSL_DECODER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey,
+                                 const char *input_type, const char *keytype,
+                                 OPENSSL_CTX *libctx, const char *propquery)
 {
     OSSL_DECODER_CTX *ctx = NULL;
 
@@ -332,7 +335,8 @@ OSSL_DECODER_CTX *OSSL_DECODER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey,
         return NULL;
     }
     if (OSSL_DECODER_CTX_set_input_type(ctx, input_type)
-        && ossl_decoder_ctx_setup_for_EVP_PKEY(ctx, pkey, libctx, propquery)
+        && ossl_decoder_ctx_setup_for_EVP_PKEY(ctx, pkey, keytype,
+                                               libctx, propquery)
         && OSSL_DECODER_CTX_add_extra(ctx, libctx, propquery))
         return ctx;
 
index a591ef23ecf0e6851a7870df283a57f7e6ac215d..8ba4f8880c3bec72f59629ae4e0b417c23d2bc1f 100644 (file)
@@ -257,7 +257,8 @@ static EVP_PKEY *try_key_value(struct extracted_param_data_st *data,
     if (membio == NULL)
         return 0;
 
-    decoderctx = OSSL_DECODER_CTX_new_by_EVP_PKEY(&pk, "DER", libctx, propq);
+    decoderctx =
+        OSSL_DECODER_CTX_new_by_EVP_PKEY(&pk, "DER", NULL, libctx, propq);
     (void)OSSL_DECODER_CTX_set_passphrase_cb(decoderctx, cb, cbarg);
 
     /* No error if this couldn't be decoded */
index 4190c4232bf8deccaaa53f2b6e203193dbbd9972..c57438072b4863119581f7f2ab0b64d4eaa94346 100644 (file)
@@ -14,7 +14,8 @@ OSSL_DECODER_CTX_set_passphrase_cb
  #include <openssl/decoder.h>
 
  OSSL_DECODER_CTX *
- OSSL_DECODER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey, const char *input_type,
+ OSSL_DECODER_CTX_new_by_EVP_PKEY(const EVP_PKEY *pkey,
+                                  const char *input_type, const char *keytype,
                                   OPENSSL_CTX *libctx, const char *propquery);
 
  int OSSL_DECODER_CTX_set_passphrase(OSSL_DECODER_CTX *ctx,
@@ -44,8 +45,14 @@ data suitable for B<EVP_PKEY>s.  All these implementations are implicitly
 fetched using I<libctx> and I<propquery>.
 
 The search of decoder implementations can be limited with I<input_type>,
-which specifies a starting input type.  This is further explained in
-L<OSSL_DECODER_CTX_set_input_type(3)>.
+which specifies a starting input type.  NULL is valid input and signifies
+that the decoder implementations will find out the input type on their own.
+This is further explained in L<OSSL_DECODER_CTX_set_input_type(3)>.
+
+The search of decoder implementations can also be limited with I<keytype>,
+which specifies the expected resulting keytype.  NULL is valid input and
+signifies that the decoder implementations will find out the keytype on
+their own from the input they get.
 
 If no suitable decoder implementation is found,
 OSSL_DECODER_CTX_new_by_EVP_PKEY() still creates a B<OSSL_DECODER_CTX>, but
index b46575297193082bda489b9ff1b139bff2824d74..f025b3ec3766235b9887b2ebcd09ae7470855cdc 100644 (file)
@@ -32,7 +32,7 @@ int ossl_decoder_ctx_add_decoder_inst(OSSL_DECODER_CTX *ctx,
                                       OSSL_DECODER_INSTANCE *di);
 
 int ossl_decoder_ctx_setup_for_EVP_PKEY(OSSL_DECODER_CTX *ctx,
-                                        EVP_PKEY **pkey,
+                                        EVP_PKEY **pkey, const char *keytype,
                                         OPENSSL_CTX *libctx,
                                         const char *propquery);
 
index 3da457743708a87e1250b6830fede7ecf3a7681c..66790f43c8b5e04a51113b4c9b2affcd2d9b93f2 100644 (file)
@@ -112,7 +112,8 @@ int OSSL_DECODER_from_fp(OSSL_DECODER_CTX *ctx, FILE *in);
  * an implicit OSSL_DECODER_fetch(), suitable for the object of that type.
  */
 OSSL_DECODER_CTX *
-OSSL_DECODER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey, const char *input_type,
+OSSL_DECODER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey,
+                                 const char *input_type, const char *keytype,
                                  OPENSSL_CTX *libctx, const char *propquery);
 
 # ifdef __cplusplus
index c19457893721b05ada740dd20f4bc61b0350feb6..c4b1de40d17e55b06bd94bb6c440369ebea77a44 100644 (file)
@@ -582,7 +582,8 @@ static int file_setup_decoders(struct file_ctx_st *ctx)
          * Since we're setting up our own constructor, we don't need to care
          * more than that...
          */
-        if (!ossl_decoder_ctx_setup_for_EVP_PKEY(ctx->_.file.decoderctx, &dummy,
+        if (!ossl_decoder_ctx_setup_for_EVP_PKEY(ctx->_.file.decoderctx,
+                                                 &dummy, NULL,
                                                  libctx, ctx->_.file.propq)
             || !OSSL_DECODER_CTX_add_extra(ctx->_.file.decoderctx,
                                            libctx, ctx->_.file.propq)) {
index 7f37a99a6d570e25ffa0a84812878dac684262c7..70258afcc0b7044695c942d3d7c55ee58cb2d03e 100644 (file)
@@ -201,7 +201,7 @@ static int decode_EVP_PKEY_prov(void **object, void *encoded, long encoded_len,
     const unsigned char *upass = (const unsigned char *)pass;
     int ok = 0;
 
-    if (!TEST_ptr(dctx = OSSL_DECODER_CTX_new_by_EVP_PKEY(&pkey, NULL,
+    if (!TEST_ptr(dctx = OSSL_DECODER_CTX_new_by_EVP_PKEY(&pkey, NULL, NULL,
                                                           NULL, NULL))
         || (pass != NULL
             && !OSSL_DECODER_CTX_set_passphrase(dctx, upass, strlen(pass)))