From 9379bf943a12090de6280e88fb0d246e73658116 Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Tue, 1 Jun 2021 20:04:59 +0200 Subject: [PATCH] DECODER: use property definitions instead of getting implementation parameters 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 Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/15570) --- crypto/encode_decode/decoder_lib.c | 54 ++++++++------ crypto/encode_decode/decoder_meth.c | 15 ++++ crypto/encode_decode/encoder_local.h | 5 ++ crypto/err/err.c | 2 + doc/man7/provider-decoder.pod | 104 +++++++-------------------- include/openssl/err.h.in | 1 + 6 files changed, 81 insertions(+), 100 deletions(-) diff --git a/crypto/encode_decode/decoder_lib.c b/crypto/encode_decode/decoder_lib.c index ddfd90aae5..bf9b17f754 100644 --- a/crypto/encode_decode/decoder_lib.c +++ b/crypto/encode_decode/decoder_lib.c @@ -16,8 +16,8 @@ #include #include #include -#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(¶ms[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(¶ms[1]); decoder_inst->decoder = decoder; decoder_inst->decoderctx = decoderctx; return decoder_inst; diff --git a/crypto/encode_decode/decoder_meth.c b/crypto/encode_decode/decoder_meth.c index 7197b9090d..e203c5fe66 100644 --- a/crypto/encode_decode/decoder_meth.c +++ b/crypto/encode_decode/decoder_meth.c @@ -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)) { diff --git a/crypto/encode_decode/encoder_local.h b/crypto/encode_decode/encoder_local.h index d53f760379..0678fc2014 100644 --- a/crypto/encode_decode/encoder_local.h +++ b/crypto/encode_decode/encoder_local.h @@ -14,6 +14,7 @@ #include #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); diff --git a/crypto/err/err.c b/crypto/err/err.c index 84bb429c64..9b1a15d5bd 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -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 diff --git a/doc/man7/provider-decoder.pod b/doc/man7/provider-decoder.pod index 23b4fbc9df..2ac56cf1d1 100644 --- a/doc/man7/provider-decoder.pod +++ b/doc/man7/provider-decoder.pod @@ -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. + +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, 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. + +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) - -This is used to specify the input type for a decoder implementation. - -This parameter is I. - -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 property. - -=item "input-structure" (B) - -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. - -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 property. - -=back - =head2 Decoder operation parameters There are currently no operation parameters currently recognised by the diff --git a/include/openssl/err.h.in b/include/openssl/err.h.in index f7d5c174a1..4bc5d1eea5 100644 --- a/include/openssl/err.h.in +++ b/include/openssl/err.h.in @@ -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; -- 2.34.1