DECODER: Allow precise result type for OSSL_DECODER_CTX_new_by_EVP_PKEY()

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)
This commit is contained in:
Richard Levitte 2020-10-02 14:21:51 +02:00
parent ecadfdadde
commit 70c06aafa6
7 changed files with 30 additions and 16 deletions

View 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;

View 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 */

View 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

View 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);

View 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

View 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)) {

View 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)))