DECODER: use property definitions instead of getting implementation parameters
authorRichard Levitte <levitte@openssl.org>
Tue, 1 Jun 2021 18:04:59 +0000 (20:04 +0200)
committerPauli <pauli@openssl.org>
Sat, 5 Jun 2021 10:30:11 +0000 (20:30 +1000)
The OSSL_DECODER library used to ask each decoder implementation for
certain data in form of parameters to place them correctly in the
decoder chain, if at all.  These parameters were duplicates of
properties of those same implementations, and therefore unnecessarily
redundant.

Now that we have functionality to query property definition values,
those duplicates are no longer needed, and are therefore not looked at
any more.

This adds the "global" error reason ERR_R_INVALID_PROPERTY_DEFINITION,
which can be re-used elsewhere.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15570)

crypto/encode_decode/decoder_lib.c
crypto/encode_decode/decoder_meth.c
crypto/encode_decode/encoder_local.h
crypto/err/err.c
doc/man7/provider-decoder.pod
include/openssl/err.h.in

index ddfd90aae5515dba1401dfc7a25db190fed89ce9..bf9b17f754aed9811891bd2e433d1893075a14ea 100644 (file)
@@ -16,8 +16,8 @@
 #include <openssl/pkcs12err.h>
 #include <openssl/x509err.h>
 #include <openssl/trace.h>
-#include "internal/passphrase.h"
 #include "internal/bio.h"
+#include "internal/provider.h"
 #include "crypto/decoder.h"
 #include "encoder_local.h"
 #include "e_os.h"
@@ -204,19 +204,16 @@ OSSL_DECODER_INSTANCE *ossl_decoder_instance_new(OSSL_DECODER *decoder,
                                                  void *decoderctx)
 {
     OSSL_DECODER_INSTANCE *decoder_inst = NULL;
-    OSSL_PARAM params[3];
+    const OSSL_PROVIDER *prov;
+    OSSL_LIB_CTX *libctx;
+    const OSSL_PROPERTY_LIST *props;
+    const OSSL_PROPERTY_DEFINITION *prop;
 
     if (!ossl_assert(decoder != NULL)) {
         ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
 
-    if (decoder->get_params == NULL) {
-        ERR_raise(ERR_LIB_OSSL_DECODER,
-                  OSSL_DECODER_R_MISSING_GET_PARAMS);
-        return 0;
-    }
-
     if ((decoder_inst = OPENSSL_zalloc(sizeof(*decoder_inst))) == NULL) {
         ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
         return 0;
@@ -226,22 +223,35 @@ OSSL_DECODER_INSTANCE *ossl_decoder_instance_new(OSSL_DECODER *decoder,
         goto err;
     }
 
-    /* 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_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]))
+    prov = OSSL_DECODER_get0_provider(decoder);
+    libctx = ossl_provider_libctx(prov);
+    props = ossl_decoder_parsed_properties(decoder);
+    if (props == NULL) {
+        ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION,
+                       "there are no property definitions with decoder %s",
+                       OSSL_DECODER_get0_name(decoder));
+        goto err;
+    }
+
+    /* The "input" property is mandatory */
+    prop = ossl_property_find_property(props, libctx, "input");
+    decoder_inst->input_type = ossl_property_get_string_value(libctx, prop);
+    if (decoder_inst->input_type == NULL) {
+        ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION,
+                       "the mandatory 'input' property is missing "
+                       "for decoder %s (properties: %s)",
+                       OSSL_DECODER_get0_name(decoder),
+                       OSSL_DECODER_get0_properties(decoder));
         goto err;
+    }
+
+    /* The "structure" property is optional */
+    prop = ossl_property_find_property(props, libctx, "structure");
+    if (prop != NULL) {
+        decoder_inst->input_structure
+            = ossl_property_get_string_value(libctx, prop);
+    }
 
-    decoder_inst->flag_input_structure_was_set =
-        OSSL_PARAM_modified(&params[1]);
     decoder_inst->decoder = decoder;
     decoder_inst->decoderctx = decoderctx;
     return decoder_inst;
index 7197b9090db91dc48cbf6be10610924633a608a4..e203c5fe660f1633d7e82801f27970284302cfc4 100644 (file)
@@ -59,6 +59,7 @@ void OSSL_DECODER_free(OSSL_DECODER *decoder)
     if (ref > 0)
         return;
     OPENSSL_free(decoder->base.name);
+    ossl_property_free(decoder->base.parsed_propdef);
     ossl_provider_free(decoder->base.prov);
     CRYPTO_THREAD_lock_free(decoder->base.lock);
     OPENSSL_free(decoder);
@@ -166,6 +167,7 @@ void *ossl_decoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef,
 {
     OSSL_DECODER *decoder = NULL;
     const OSSL_DISPATCH *fns = algodef->implementation;
+    OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
 
     if ((decoder = ossl_decoder_new()) == NULL)
         return NULL;
@@ -176,6 +178,8 @@ void *ossl_decoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef,
     }
     decoder->base.propdef = algodef->property_definition;
     decoder->base.description = algodef->algorithm_description;
+    decoder->base.parsed_propdef
+        = ossl_parse_property(libctx, algodef->property_definition);
 
     for (; fns->function_id != 0; fns++) {
         switch (fns->function_id) {
@@ -421,6 +425,17 @@ const char *OSSL_DECODER_get0_properties(const OSSL_DECODER *decoder)
     return decoder->base.propdef;
 }
 
+const OSSL_PROPERTY_LIST *
+ossl_decoder_parsed_properties(const OSSL_DECODER *decoder)
+{
+    if (!ossl_assert(decoder != NULL)) {
+        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+
+    return decoder->base.parsed_propdef;
+}
+
 int ossl_decoder_get_number(const OSSL_DECODER *decoder)
 {
     if (!ossl_assert(decoder != NULL)) {
index d53f760379413a2676f37b038f78371cb2788bc3..0678fc201418dce49e827e2dc80019b19c8dc447 100644 (file)
@@ -14,6 +14,7 @@
 #include <openssl/decoder.h>
 #include "internal/cryptlib.h"
 #include "internal/passphrase.h"
+#include "internal/property.h"
 #include "internal/refcount.h"
 
 struct ossl_endecode_base_st {
@@ -22,6 +23,7 @@ struct ossl_endecode_base_st {
     char *name;
     const char *propdef;
     const char *description;
+    OSSL_PROPERTY_LIST *parsed_propdef;
 
     CRYPTO_REF_COUNT refcnt;
     CRYPTO_RWLOCK *lock;
@@ -157,3 +159,6 @@ struct ossl_decoder_ctx_st {
     /* For any function that needs a passphrase reader */
     struct ossl_passphrase_data_st pwdata;
 };
+
+const OSSL_PROPERTY_LIST *
+ossl_decoder_parsed_properties(const OSSL_DECODER *decoder);
index 84bb429c6408abc04f8cb08b56ee3fbf6f59827f..9b1a15d5bdf8bb6ec8f65691a777ad17520e840b 100644 (file)
@@ -125,6 +125,8 @@ static ERR_STRING_DATA ERR_str_reasons[] = {
      * unsupported.
      */
     {ERR_R_FETCH_FAILED, "fetch failed"},
+
+    {ERR_R_INVALID_PROPERTY_DEFINITION, "invalid property definition"},
     {0, NULL},
 };
 #endif
index 23b4fbc9df797476aa6810f4e7723c8b33405c38..2ac56cf1d125c0d8533d548cfed0338c565d8ab6 100644 (file)
@@ -117,7 +117,11 @@ Properties can be used to further specify details about an implementation:
 =item input
 
 This property is used to specify what format of input the implementation
-can decode.  OpenSSL providers recognize the following input types:
+can decode.
+
+This property is I<mandatory>.
+
+OpenSSL providers recognize the following input types:
 
 =over 4
 
@@ -142,9 +146,27 @@ An implementation with that input type decodes PVK formatted data.
 =item structure
 
 This property is used to specify the structure that the decoded data is
-expected to have. An example could be C<pkcs8>, to specify explicitly that
-the object to be decoded (presumably an asymmetric key pair, in this case)
-is wrapped in a PKCS#8 structure.
+expected to have.
+
+This property is I<optional>.
+
+Structures currently recognised by built-in decoders:
+
+=over 4
+
+=item "type-specific"
+
+Type specific structure.
+
+=item "pkcs8"
+
+Structure according to the PKCS#8 specification.
+
+=item "SubjectPublicKeyInfo"
+
+Encoding of public keys according to the Subject Public Key Info of RFC 5280.
+
+=back
 
 =back
 
@@ -236,80 +258,6 @@ possible for some other decoder implementation to get a different result.
 The conditions to stop the decoding process are at the discretion of the
 implementation.
 
-=head2 Decoder parameters
-
-The decoder implementation itself has parameters that can be used to
-determine how it fits in a chain of decoders:
-
-=over 4
-
-=item "input-type" (B<OSSL_DECODER_PARAM_INPUT_TYPE>) <UTF8 string>
-
-This is used to specify the input type for a decoder implementation.
-
-This parameter is I<mandatory>.
-
-Input types currently recognized by built-in decoders:
-
-=over 4
-
-=item "DER"
-
-ASN.1 DER encoded binary data
-
-=item "PEM"
-
-Base64 encoded data with PEM headers
-
-=item "MSBLOB"
-
-Private or public key encoding according to Microsoft specification
-
-=item "PVK"
-
-Encrypted private key encoding according to Microsoft specification
-
-=back
-
-=for comment If we had functionality to get the value of a specific property
-in a set of properties, it would be possible to determine the input type
-from the C<input> property.
-
-=item "input-structure" (B<OSSL_ENCODER_PARAM_INPUT_STRUCTURE>) <UTF8 string>
-
-This is used to specify the outermost input structure for a decoder
-implementation.
-
-For example, an input of type "DER" for a key pair could be structured
-using PKCS#8, or a key type specific structure, such as PKCS#1 for RSA
-keys.
-
-This parameter is I<optional>.
-
-Input structures currently recognized by built-in decoders:
-
-=over 4
-
-=item "type-specific"
-
-Type specific structure.
-
-=item "PKCS8"
-
-Structure according to the PKCS#8 specification.
-
-=item "SubjectPublicKeyInfo"
-
-Encoding of public keys according to the Subject Public Key Info of RFC 5280.
-
-=back
-
-=for comment If we had functionality to get the value of a specific property
-in a set of properties, it would be possible to determine the input
-structure from the C<structure> property.
-
-=back
-
 =head2 Decoder operation parameters
 
 There are currently no operation parameters currently recognised by the
index f7d5c174a17da1e0d4e4cc88a386d603f0818097..4bc5d1eea56e02eaa300cf4173d7f3b85ae781a9 100644 (file)
@@ -357,6 +357,7 @@ static ossl_unused ossl_inline int ERR_COMMON_ERROR(unsigned long errcode)
 # define ERR_R_MISSING_ASN1_EOS                  (267|ERR_RFLAG_COMMON)
 # define ERR_R_UNSUPPORTED                       (268|ERR_RFLAG_COMMON)
 # define ERR_R_FETCH_FAILED                      (269|ERR_RFLAG_COMMON)
+# define ERR_R_INVALID_PROPERTY_DEFINITION       (270|ERR_RFLAG_COMMON)
 
 typedef struct ERR_string_data_st {
     unsigned long error;