summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2020-10-26 13:17:42 +0100
committerRichard Levitte <levitte@openssl.org>2020-11-11 11:42:06 +0100
commitdf65c06b59f0ccd06398c0ff3034371fdefd8e70 (patch)
tree35c564e2392d0b885b30ea7c6f8ff42ee5dc1f4e
parent67c91ca23eae175a08f0f0c60be6e6957334d25e (diff)
DECODER: Add input structure support for EVP_PKEY decoding
OSSL_DECODER_CTX_new_by_EVP_PKEY() takes one more argument to express the desired outermost structure for the input. Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/13248)
-rw-r--r--crypto/encode_decode/decoder_pkey.c64
-rw-r--r--doc/man3/OSSL_DECODER_CTX.pod28
-rw-r--r--include/openssl/decoder.h4
3 files changed, 86 insertions, 10 deletions
diff --git a/crypto/encode_decode/decoder_pkey.c b/crypto/encode_decode/decoder_pkey.c
index e9c0141804..1835106b95 100644
--- a/crypto/encode_decode/decoder_pkey.c
+++ b/crypto/encode_decode/decoder_pkey.c
@@ -9,6 +9,7 @@
#include <openssl/core_names.h>
#include <openssl/core_object.h>
+#include <openssl/provider.h>
#include <openssl/evp.h>
#include <openssl/ui.h>
#include <openssl/decoder.h>
@@ -16,6 +17,7 @@
#include "crypto/evp.h"
#include "crypto/decoder.h"
#include "encoder_local.h"
+#include "e_os.h" /* strcasecmp on Windows */
int OSSL_DECODER_CTX_set_passphrase(OSSL_DECODER_CTX *ctx,
const unsigned char *kstr,
@@ -231,10 +233,40 @@ static void collect_name(const char *name, void *arg)
data->error_occured = 0; /* All is good now */
}
+/*
+ * The input structure check is only done on the initial decoder
+ * implementations.
+ */
+static int collect_decoder_check_input_structure(OSSL_DECODER_CTX *ctx,
+ OSSL_DECODER_INSTANCE *di)
+{
+ int di_is_was_set = 0;
+ const char *di_is =
+ OSSL_DECODER_INSTANCE_get_input_structure(di, &di_is_was_set);
+
+ /*
+ * If caller didn't give an input structure name, the decoder is accepted
+ * unconditionally with regards to the input structure.
+ */
+ if (ctx->input_structure == NULL)
+ return 1;
+ /*
+ * If the caller did give an input structure name, the decoder must have
+ * a matching input structure to be accepted.
+ */
+ if (di_is != NULL
+ && strcasecmp(ctx->input_structure, di_is) == 0)
+ return 1;
+ return 0;
+}
+
static void collect_decoder(OSSL_DECODER *decoder, void *arg)
{
struct collected_data_st *data = arg;
size_t i, end_i;
+ const OSSL_PROVIDER *prov = OSSL_DECODER_provider(decoder);
+ void *provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
+ void *decoderctx = NULL;
if (data->error_occured)
return;
@@ -246,10 +278,30 @@ static void collect_decoder(OSSL_DECODER *decoder, void *arg)
end_i = sk_OPENSSL_CSTRING_num(data->names);
for (i = 0; i < end_i; i++) {
const char *name = sk_OPENSSL_CSTRING_value(data->names, i);
+ OSSL_DECODER_INSTANCE *di = NULL;
+
+ if (OSSL_DECODER_is_a(decoder, name)
+ /*
+ * Either the caller didn't give a selection, or if they did,
+ * the decoder must tell us if it supports that selection to
+ * be accepted. If the decoder doesn't have |does_selection|,
+ * it's seen as taking anything.
+ */
+ && (decoder->does_selection == NULL
+ || decoder->does_selection(provctx, data->ctx->selection))
+ && (decoderctx = decoder->newctx(provctx)) != NULL
+ && (di = ossl_decoder_instance_new(decoder, decoderctx)) != NULL) {
+ /* If successful so far, don't free these directly */
+ decoderctx = NULL;
+
+ if (collect_decoder_check_input_structure(data->ctx, di)
+ && ossl_decoder_ctx_add_decoder_inst(data->ctx, di))
+ di = NULL; /* If successfully added, don't free it */
+ }
- if (!OSSL_DECODER_is_a(decoder, name))
- continue;
- (void)OSSL_DECODER_CTX_add_decoder(data->ctx, decoder);
+ /* Free what can be freed */
+ ossl_decoder_instance_free(di);
+ decoder->freectx(decoderctx);
}
data->error_occured = 0; /* All is good now */
@@ -325,7 +377,9 @@ int ossl_decoder_ctx_setup_for_EVP_PKEY(OSSL_DECODER_CTX *ctx,
OSSL_DECODER_CTX *
OSSL_DECODER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey,
- const char *input_type, const char *keytype,
+ const char *input_type,
+ const char *input_structure,
+ const char *keytype, int selection,
OSSL_LIB_CTX *libctx, const char *propquery)
{
OSSL_DECODER_CTX *ctx = NULL;
@@ -335,6 +389,8 @@ 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_set_input_structure(ctx, input_structure)
+ && OSSL_DECODER_CTX_set_selection(ctx, selection)
&& ossl_decoder_ctx_setup_for_EVP_PKEY(ctx, pkey, keytype,
libctx, propquery)
&& OSSL_DECODER_CTX_add_extra(ctx, libctx, propquery))
diff --git a/doc/man3/OSSL_DECODER_CTX.pod b/doc/man3/OSSL_DECODER_CTX.pod
index 27e0a67a96..aa5dc90893 100644
--- a/doc/man3/OSSL_DECODER_CTX.pod
+++ b/doc/man3/OSSL_DECODER_CTX.pod
@@ -7,7 +7,9 @@ OSSL_DECODER_CTX_new,
OSSL_DECODER_settable_ctx_params,
OSSL_DECODER_CTX_set_params,
OSSL_DECODER_CTX_free,
+OSSL_DECODER_CTX_set_selection,
OSSL_DECODER_CTX_set_input_type,
+OSSL_DECODER_CTX_set_input_structure,
OSSL_DECODER_CTX_add_decoder,
OSSL_DECODER_CTX_add_extra,
OSSL_DECODER_CTX_get_num_decoders,
@@ -23,7 +25,8 @@ OSSL_DECODER_CTX_get_cleanup,
OSSL_DECODER_export,
OSSL_DECODER_INSTANCE_get_decoder,
OSSL_DECODER_INSTANCE_get_decoder_ctx,
-OSSL_DECODER_INSTANCE_get_input_type
+OSSL_DECODER_INSTANCE_get_input_type,
+OSSL_DECODER_INSTANCE_get_input_structure
- Decoder context routines
=head1 SYNOPSIS
@@ -38,8 +41,11 @@ OSSL_DECODER_INSTANCE_get_input_type
const OSSL_PARAM params[]);
void OSSL_DECODER_CTX_free(OSSL_DECODER_CTX *ctx);
+ int OSSL_DECODER_CTX_set_selection(OSSL_DECODER_CTX *ctx, int selection);
int OSSL_DECODER_CTX_set_input_type(OSSL_DECODER_CTX *ctx,
const char *input_type);
+ int OSSL_DECODER_CTX_set_input_structure(OSSL_DECODER_CTX *ctx,
+ const char *input_structure);
int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder);
int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx);
int OSSL_DECODER_CTX_get_num_decoders(OSSL_DECODER_CTX *ctx);
@@ -51,6 +57,8 @@ OSSL_DECODER_INSTANCE_get_input_type
OSSL_DECODER_INSTANCE_get_decoder_ctx(OSSL_DECODER_INSTANCE *decoder_inst);
const char *
OSSL_DECODER_INSTANCE_get_input_type(OSSL_DECODER_INSTANCE *decoder_inst);
+ OSSL_DECODER_INSTANCE_get_input_structure(OSSL_DECODER_INSTANCE *decoder_inst,
+ int *was_set);
typedef int OSSL_DECODER_CONSTRUCT(OSSL_DECODER_INSTANCE *decoder_inst,
const OSSL_PARAM *object,
@@ -128,6 +136,11 @@ OSSL_DECODER_CTX_set_input_type() sets the starting input type. This limits
the decoder chains to be considered, as explained in the general description
above.
+OSSL_DECODER_CTX_set_input_structure() sets the name of the structure that
+the input is expected to have. This may be used to determines what decoder
+implementations may be used. NULL is a valid input structure, when it's not
+relevant, or when the decoder implementations are expected to figure it out.
+
OSSL_DECODER_CTX_get_num_decoders() gets the number of decoders currently
added to the context I<ctx>.
@@ -179,14 +192,19 @@ constructed, otherwise 0.
These utility functions may be used by a constructor:
-OSSL_DECODER_INSTANCE_get_decoder() can be used to get the decoder method
-from a decoder instance I<decoder_inst>.
+OSSL_DECODER_INSTANCE_get_decoder() can be used to get the decoder
+implementation from a decoder instance I<decoder_inst>.
OSSL_DECODER_INSTANCE_get_decoder_ctx() can be used to get the decoder
-method's provider context from a decoder instance I<decoder_inst>.
+implementation's provider context from a decoder instance I<decoder_inst>.
OSSL_DECODER_INSTANCE_get_input_type() can be used to get the decoder
-method's input type from a decoder instance I<decoder_inst>.
+implementation's input type from a decoder instance I<decoder_inst>.
+
+OSSL_DECODER_INSTANCE_get_input_structure() can be used to get the input
+structure for the decoder implementation from a decoder instance
+I<decoder_inst>.
+This may be NULL.
=head1 RETURN VALUES
diff --git a/include/openssl/decoder.h b/include/openssl/decoder.h
index 8b360e6198..3c3a9a1ea2 100644
--- a/include/openssl/decoder.h
+++ b/include/openssl/decoder.h
@@ -121,7 +121,9 @@ int OSSL_DECODER_from_data(OSSL_DECODER_CTX *ctx, const unsigned char **pdata,
*/
OSSL_DECODER_CTX *
OSSL_DECODER_CTX_new_by_EVP_PKEY(EVP_PKEY **pkey,
- const char *input_type, const char *keytype,
+ const char *input_type,
+ const char *input_struct,
+ const char *keytype, int selection,
OSSL_LIB_CTX *libctx, const char *propquery);
# ifdef __cplusplus