DECODER: Add support for specifying the outermost input structure
authorRichard Levitte <levitte@openssl.org>
Mon, 26 Oct 2020 12:06:01 +0000 (13:06 +0100)
committerRichard Levitte <levitte@openssl.org>
Wed, 11 Nov 2020 10:42:06 +0000 (11:42 +0100)
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/13248)

crypto/encode_decode/decoder_lib.c
crypto/encode_decode/encoder_local.h
include/openssl/core_names.h
include/openssl/decoder.h
util/libcrypto.num

index 20350a8cd61c7af67fdfec6bec39c2a5d3107779..64e6bcc1855983b2f32a7482960fc1b89f480689 100644 (file)
@@ -98,6 +98,21 @@ int OSSL_DECODER_from_data(OSSL_DECODER_CTX *ctx, const unsigned char **pdata,
     return ret;
 }
 
+int OSSL_DECODER_CTX_set_selection(OSSL_DECODER_CTX *ctx, int selection)
+{
+    if (!ossl_assert(ctx != NULL)) {
+        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+
+    /*
+     * 0 is a valid selection, and means that the caller leaves
+     * it to code to discover what the selection is.
+     */
+    ctx->selection = selection;
+    return 1;
+}
+
 int OSSL_DECODER_CTX_set_input_type(OSSL_DECODER_CTX *ctx,
                                     const char *input_type)
 {
@@ -114,11 +129,27 @@ int OSSL_DECODER_CTX_set_input_type(OSSL_DECODER_CTX *ctx,
     return 1;
 }
 
+int OSSL_DECODER_CTX_set_input_structure(OSSL_DECODER_CTX *ctx,
+                                         const char *input_structure)
+{
+    if (!ossl_assert(ctx != NULL)) {
+        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+
+    /*
+     * NULL is a valid starting input type, and means that the caller leaves
+     * it to code to discover what the starting input type is.
+     */
+    ctx->input_structure = input_structure;
+    return 1;
+}
+
 OSSL_DECODER_INSTANCE *ossl_decoder_instance_new(OSSL_DECODER *decoder,
                                                  void *decoderctx)
 {
     OSSL_DECODER_INSTANCE *decoder_inst = NULL;
-    OSSL_PARAM params[2];
+    OSSL_PARAM params[3];
 
     if (!ossl_assert(decoder != NULL)) {
         ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
@@ -140,16 +171,22 @@ OSSL_DECODER_INSTANCE *ossl_decoder_instance_new(OSSL_DECODER *decoder,
         goto err;
     }
 
-    /* Cache the input type for this encoder */
+    /* Cache the input type for this decoder */
     params[0] =
         OSSL_PARAM_construct_utf8_ptr(OSSL_DECODER_PARAM_INPUT_TYPE,
                                       (char **)&decoder_inst->input_type, 0);
-    params[1] = OSSL_PARAM_construct_end();
+    params[1] =
+        OSSL_PARAM_construct_utf8_ptr(OSSL_DECODER_PARAM_INPUT_STRUCTURE,
+                                      (char **)&decoder_inst->input_structure,
+                                      0);
+    params[2] = OSSL_PARAM_construct_end();
 
     if (!decoder->get_params(params)
         || !OSSL_PARAM_modified(&params[0]))
         goto err;
 
+    decoder_inst->flag_input_structure_was_set =
+        OSSL_PARAM_modified(&params[1]);
     decoder_inst->decoder = decoder;
     decoder_inst->decoderctx = decoderctx;
     return decoder_inst;
@@ -171,7 +208,7 @@ void ossl_decoder_instance_free(OSSL_DECODER_INSTANCE *decoder_inst)
 }
 
 int ossl_decoder_ctx_add_decoder_inst(OSSL_DECODER_CTX *ctx,
-                                         OSSL_DECODER_INSTANCE *di)
+                                      OSSL_DECODER_INSTANCE *di)
 {
     if (ctx->decoder_insts == NULL
         && (ctx->decoder_insts =
@@ -225,7 +262,7 @@ int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx,
      * what the existing ones want as input, and push those newly fetched
      * decoders on top of the same stack.
      * Then it does the same again, but looping over the newly fetched
-     * decoders, until there are no more encoders to be fetched, or
+     * decoders, until there are no more decoders to be fetched, or
      * when we have done this 10 times.
      *
      * we do this with sliding windows on the stack by keeping track of indexes
@@ -439,6 +476,16 @@ OSSL_DECODER_INSTANCE_get_input_type(OSSL_DECODER_INSTANCE *decoder_inst)
     return decoder_inst->input_type;
 }
 
+const char *
+OSSL_DECODER_INSTANCE_get_input_structure(OSSL_DECODER_INSTANCE *decoder_inst,
+                                          int *was_set)
+{
+    if (decoder_inst == NULL)
+        return NULL;
+    *was_set = decoder_inst->flag_input_structure_was_set;
+    return decoder_inst->input_structure;
+}
+
 static int decoder_process(const OSSL_PARAM params[], void *arg)
 {
     struct decoder_process_data_st *data = arg;
@@ -564,6 +611,7 @@ static int decoder_process(const OSSL_PARAM params[], void *arg)
         /* Recurse */
         new_data.current_decoder_inst_index = i;
         ok = new_decoder->decode(new_decoderctx, (OSSL_CORE_BIO *)bio,
+                                 new_data.ctx->selection,
                                  decoder_process, &new_data,
                                  ossl_pw_passphrase_callback_dec,
                                  &new_data.ctx->pwdata);
index a57d0cd16c50b900448473bc7ecc612535740e05..9378393a42789170cb9a36c403109d21dd52b455 100644 (file)
@@ -96,6 +96,9 @@ struct ossl_decoder_instance_st {
     OSSL_DECODER *decoder;       /* Never NULL */
     void *decoderctx;            /* Never NULL */
     const char *input_type;      /* Never NULL */
+    const char *input_structure; /* May be NULL */
+
+    unsigned int flag_input_structure_was_set : 1;
 };
 
 DEFINE_STACK_OF(OSSL_DECODER_INSTANCE)
@@ -108,6 +111,25 @@ struct ossl_decoder_ctx_st {
      * regardless of their respective input type.
      */
     const char *start_input_type;
+    /*
+     * The desired input structure, if that's relevant for the type of
+     * object being encoded.  It may be used for selection of the ending
+     * decoder implementations in a chain, i.e. those chosen using the
+     * expected output data type.
+     */
+    const char *input_structure;
+    /*
+     * Select what parts of an object are expected.  This may affect what
+     * decoder implementations are selected, because there are structures
+     * that look different depending on this selection; for example, EVP_PKEY
+     * objects often have different encoding structures for private keys,
+     * public keys and key parameters.
+     * This selection is bit encoded, and the bits correspond to selection
+     * bits available with the provider side operation.  For example, when
+     * encoding an EVP_PKEY, the OSSL_KEYMGMT_SELECT_ macros are used for
+     * this.
+     */
+    int selection;
 
     /*
      * Decoders that are components of any current decoding path.
index 43be4ae145be0b409324893d391c8f615cfa557d..11a4168cc16335ecaf69b29a388f82ea2af3def2 100644 (file)
@@ -457,8 +457,9 @@ extern "C" {
 #define OSSL_ENCODER_PARAM_INPUT_TYPE   "input-type"
 #define OSSL_ENCODER_PARAM_OUTPUT_TYPE  "output-type"
 
-#define OSSL_DECODER_PARAM_PROPERTIES   OSSL_ALG_PARAM_PROPERTIES
-#define OSSL_DECODER_PARAM_INPUT_TYPE   "input-type"
+#define OSSL_DECODER_PARAM_PROPERTIES       OSSL_ALG_PARAM_PROPERTIES
+#define OSSL_DECODER_PARAM_INPUT_TYPE       "input-type"
+#define OSSL_DECODER_PARAM_INPUT_STRUCTURE  "input-structure"
 
 /* Passphrase callback parameters */
 #define OSSL_PASSPHRASE_PARAM_INFO      "info"
index 1c6bc8e4984e777058dc9889ac54bbedd8d3616a..8b360e6198f9d9fcfa853fdc3a58d45ae164d608 100644 (file)
@@ -68,8 +68,11 @@ int OSSL_DECODER_CTX_set_passphrase_ui(OSSL_DECODER_CTX *ctx,
  * These will discover all provided methods
  */
 
+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,
                                OSSL_LIB_CTX *libctx, const char *propq);
@@ -82,6 +85,9 @@ void *
 OSSL_DECODER_INSTANCE_get_decoder_ctx(OSSL_DECODER_INSTANCE *decoder_inst);
 const char *
 OSSL_DECODER_INSTANCE_get_input_type(OSSL_DECODER_INSTANCE *decoder_inst);
+const char *
+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 *params,
index 9437e30e851f0aa6e439155f23e619b5447da5ea..40e1fcb43afa83ae9126711982c475a334cc2504 100644 (file)
@@ -5285,3 +5285,6 @@ EVP_PKEY_CTX_get0_libctx                ? 3_0_0   EXIST::FUNCTION:
 EVP_PKEY_CTX_get0_propq                 ?      3_0_0   EXIST::FUNCTION:
 EVP_PKEY_set1_encoded_public_key        ?      3_0_0   EXIST::FUNCTION:
 EVP_PKEY_get1_encoded_public_key        ?      3_0_0   EXIST::FUNCTION:
+OSSL_DECODER_CTX_set_selection          ?      3_0_0   EXIST::FUNCTION:
+OSSL_DECODER_CTX_set_input_structure    ?      3_0_0   EXIST::FUNCTION:
+OSSL_DECODER_INSTANCE_get_input_structure ?    3_0_0   EXIST::FUNCTION: