From c3e4c1f325e6fc829a5b00a19a6019249cac781a Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Wed, 8 Jul 2020 23:04:08 +0200 Subject: DESERIALIZER: Add foundation for deserializers This adds a method OSSL_DESERIALIZER, a deserializer context and basic support to use a set of serializers to get a desired type of data, as well as deserializer chains. The idea is that the caller can call OSSL_DESERIALIZER_CTX_add_serializer() to set up the set of desired results, and to add possible chains, call OSSL_DESERIALIZER_CTX_add_extra(). All these deserializers are pushed on an internal stack. The actual deserialization is then performed using functions like OSSL_DESERIALIZER_from_bio(). When performing deserialization, the inernal stack is walked backwards, keeping track of the deserialized data and its type along the way, until the data kan be processed into the desired type of data. Reviewed-by: Matt Caswell Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/12410) --- doc/man3/OSSL_DESERIALIZER.pod | 146 ++++++++++++++++++ doc/man3/OSSL_DESERIALIZER_CTX.pod | 74 ++++++++++ doc/man3/OSSL_DESERIALIZER_from_bio.pod | 253 ++++++++++++++++++++++++++++++++ 3 files changed, 473 insertions(+) create mode 100644 doc/man3/OSSL_DESERIALIZER.pod create mode 100644 doc/man3/OSSL_DESERIALIZER_CTX.pod create mode 100644 doc/man3/OSSL_DESERIALIZER_from_bio.pod (limited to 'doc/man3') diff --git a/doc/man3/OSSL_DESERIALIZER.pod b/doc/man3/OSSL_DESERIALIZER.pod new file mode 100644 index 0000000000..5562a8122b --- /dev/null +++ b/doc/man3/OSSL_DESERIALIZER.pod @@ -0,0 +1,146 @@ +=pod + +=head1 NAME + +OSSL_DESERIALIZER, +OSSL_DESERIALIZER_fetch, +OSSL_DESERIALIZER_up_ref, +OSSL_DESERIALIZER_free, +OSSL_DESERIALIZER_provider, +OSSL_DESERIALIZER_properties, +OSSL_DESERIALIZER_is_a, +OSSL_DESERIALIZER_number, +OSSL_DESERIALIZER_do_all_provided, +OSSL_DESERIALIZER_names_do_all, +OSSL_DESERIALIZER_gettable_params, +OSSL_DESERIALIZER_get_params +- Deserializer method routines + +=head1 SYNOPSIS + + #include + + typedef struct ossl_deserializer_st OSSL_DESERIALIZER; + + OSSL_DESERIALIZER *OSSL_DESERIALIZER_fetch(OPENSSL_CTX *ctx, const char *name, + const char *properties); + int OSSL_DESERIALIZER_up_ref(OSSL_DESERIALIZER *deserializer); + void OSSL_DESERIALIZER_free(OSSL_DESERIALIZER *deserializer); + const OSSL_PROVIDER *OSSL_DESERIALIZER_provider(const OSSL_DESERIALIZER + *deserializer); + const char *OSSL_DESERIALIZER_properties(const OSSL_DESERIALIZER *deser); + int OSSL_DESERIALIZER_is_a(const OSSL_DESERIALIZER *deserializer, + const char *name); + int OSSL_DESERIALIZER_number(const OSSL_DESERIALIZER *deserializer); + void OSSL_DESERIALIZER_do_all_provided(OPENSSL_CTX *libctx, + void (*fn)(OSSL_DESERIALIZER *deserializer, + void *arg), + void *arg); + void OSSL_DESERIALIZER_names_do_all(const OSSL_DESERIALIZER *deserializer, + void (*fn)(const char *name, void *data), + void *data); + const OSSL_PARAM *OSSL_DESERIALIZER_gettable_params(OSSL_DESERIALIZER *deser); + int OSSL_DESERIALIZER_get_params(OSSL_DESERIALIZER_CTX *ctx, + const OSSL_PARAM params[]); + +=head1 DESCRIPTION + +B is a method for deserializers, which know how to +deserialize serialized data into an object of some type that the rest +of OpenSSL knows how to handle. + +OSSL_DESERIALIZER_fetch() looks for an algorithm within the provider that +has been loaded into the B given by I, having the +name given by I and the properties given by I. +The I determines what type of object the fetched deserializer +method is expected to be able to deserialize, and the properties are +used to determine the expected output type. +For known properties and the values they may have, please have a look +in L. + +OSSL_DESERIALIZER_up_ref() increments the reference count for the given +I. + +OSSL_DESERIALIZER_free() decrements the reference count for the given +I, and when the count reaches zero, frees it. + +OSSL_DESERIALIZER_provider() returns the provider of the given +I. + +OSSL_DESERIALIZER_properties() returns the property definition associated +with the given I. + +OSSL_DESERIALIZER_is_a() checks if I is an implementation +of an algorithm that's identifiable with I. + +OSSL_DESERIALIZER_number() returns the internal dynamic number assigned +to the given I. + +OSSL_DESERIALIZER_names_do_all() traverses all names for the given +I, and calls I with each name and I. + +OSSL_DESERIALIZER_do_all_provided() traverses all serializer +implementations by all activated providers in the library context +I, and for each of the implementations, calls I with the +implementation method and I as arguments. + +OSSL_DESERIALIZER_gettable_params() returns an L +array of parameter descriptors. + +OSSL_DESERIALIZER_get_params() attempts to get parameters specified +with an L array I. Parameters that the +implementation doesn't recognise should be ignored. + +=head1 RETURN VALUES + +OSSL_DESERIALIZER_fetch() returns a pointer to an OSSL_DESERIALIZER object, +or NULL on error. + +OSSL_DESERIALIZER_up_ref() returns 1 on success, or 0 on error. + +OSSL_DESERIALIZER_free() doesn't return any value. + +OSSL_DESERIALIZER_provider() returns a pointer to a provider object, or +NULL on error. + +OSSL_DESERIALIZER_properties() returns a pointer to a property +definition string, or NULL on error. + +OSSL_DESERIALIZER_is_a() returns 1 if I was identifiable, +otherwise 0. + +OSSL_DESERIALIZER_number() returns an integer. + +=head1 NOTES + +OSSL_DESERIALIZER_fetch() may be called implicitly by other fetching +functions, using the same library context and properties. +Any other API that uses keys will typically do this. + +=begin comment TODO(3.0) Add examples! + +=head1 EXAMPLES + +Text, because pod2xxx doesn't like empty sections + +=end comment + +=head1 SEE ALSO + +L, L, L, +L, L + +=head1 HISTORY + +The functions described here were added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/OSSL_DESERIALIZER_CTX.pod b/doc/man3/OSSL_DESERIALIZER_CTX.pod new file mode 100644 index 0000000000..413584f8dc --- /dev/null +++ b/doc/man3/OSSL_DESERIALIZER_CTX.pod @@ -0,0 +1,74 @@ +=pod + +=head1 NAME + +OSSL_DESERIALIZER_CTX, +OSSL_DESERIALIZER_CTX_new, +OSSL_DESERIALIZER_settable_ctx_params, +OSSL_DESERIALIZER_CTX_set_params, +OSSL_DESERIALIZER_CTX_free +- Serializer context routines + +=head1 SYNOPSIS + + #include + + typedef struct ossl_deserializer_ctx_st OSSL_DESERIALIZER_CTX; + + OSSL_DESERIALIZER_CTX *OSSL_DESERIALIZER_CTX_new(OPENSSL_CTX *libctx); + const OSSL_PARAM *OSSL_DESERIALIZER_settable_ctx_params(OSSL_DESERIALIZER *deser); + int OSSL_DESERIALIZER_CTX_set_params(OSSL_DESERIALIZER_CTX *ctx, + const OSSL_PARAM params[]); + void OSSL_DESERIALIZER_CTX_free(OSSL_DESERIALIZER_CTX *ctx); + +=head1 DESCRIPTION + +B is a context with which B +operations are performed. The context typically holds values, both +internal and supplied by the application, which are useful for the +implementations supplied by providers. + +OSSL_DESERIALIZER_CTX_new() creates a new empty B. + +OSSL_DESERIALIZER_settable_ctx_params() returns an L +array of parameter descriptors. + +OSSL_DESERIALIZER_CTX_set_params() attempts to set parameters specified +with an L array I. These parameters are passed +to all deserializers that have been added to the I so far. +Parameters that an implementation doesn't recognise should be ignored +by it. + +OSSL_DESERIALIZER_CTX_free() frees the given context I. + +=head1 RETURN VALUES + +OSSL_DESERIALIZER_CTX_new() returns a pointer to a +B, or NULL if the context structure couldn't be +allocated. + +OSSL_DESERIALIZER_settable_ctx_params() returns an L +array, or NULL if none is available. + +OSSL_DESERIALIZER_CTX_set_params() returns 1 if all recognised +parameters were valid, or 0 if one of them was invalid or caused some +other failure in the implementation. + +=head1 SEE ALSO + +L, L, L + +=head1 HISTORY + +The functions described here were added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/OSSL_DESERIALIZER_from_bio.pod b/doc/man3/OSSL_DESERIALIZER_from_bio.pod new file mode 100644 index 0000000000..8c372a6cf6 --- /dev/null +++ b/doc/man3/OSSL_DESERIALIZER_from_bio.pod @@ -0,0 +1,253 @@ +=pod + +=head1 NAME + +OSSL_DESERIALIZER_from_bio, +OSSL_DESERIALIZER_from_fp, +OSSL_DESERIALIZER_CTX_set_input_type, +OSSL_DESERIALIZER_CTX_add_deserializer, +OSSL_DESERIALIZER_CTX_add_extra, +OSSL_DESERIALIZER_CTX_num_deserializers, +OSSL_DESERIALIZER_INSTANCE, +OSSL_DESERIALIZER_FINALIZER, +OSSL_DESERIALIZER_CLEANER, +OSSL_DESERIALIZER_CTX_set_finalizer, +OSSL_DESERIALIZER_export, +OSSL_DESERIALIZER_INSTANCE_deserializer, +OSSL_DESERIALIZER_INSTANCE_deserializer_ctx +- Routines to perform a deserialization + +=head1 SYNOPSIS + + #include + + int OSSL_DESERIALIZER_from_bio(OSSL_DESERIALIZER_CTX *ctx, BIO *in); + int OSSL_DESERIALIZER_from_fp(OSSL_DESERIALIZER_CTX *ctx, FILE *fp); + + int OSSL_DESERIALIZER_CTX_set_input_type(OSSL_DESERIALIZER_CTX *ctx, + const char *input_type); + int OSSL_DESERIALIZER_CTX_add_deserializer(OSSL_DESERIALIZER_CTX *ctx, + OSSL_DESERIALIZER *deser); + int OSSL_DESERIALIZER_CTX_add_extra(OSSL_DESERIALIZER_CTX *ctx); + int OSSL_DESERIALIZER_CTX_num_deserializers(OSSL_DESERIALIZER_CTX *ctx); + + typedef struct ossl_deserializer_instance_st OSSL_DESERIALIZER_INSTANCE; + typedef int (OSSL_DESERIALIZER_FINALIZER) + (OSSL_DESERIALIZER_INSTANCE *deser_inst, + const OSSL_PARAM *params, void *finalize_arg); + typedef void (OSSL_DESERIALIZER_CLEANER)(void *finalize_arg); + + int OSSL_DESERIALIZER_CTX_set_finalizer(OSSL_DESERIALIZER_CTX *ctx, + OSSL_DESRIALIZER_FINALIZER *finalizer, + OSSL_DESERIALIZER_CLEANER *cleaner, + void *finalize_arg); + + int OSSL_DESERIALIZER_export(OSSL_DESERIALIZER_INSTANCE *deser_inst, + void *reference, size_t reference_sz, + OSSL_CALLBACK *export_cb, void *export_cbarg); + + OSSL_DESERIALIZER *OSSL_DESERIALIZER_INSTANCE_deserializer + (OSSL_DESERIALIZER_INSTANCE *deser_inst); + void *OSSL_DESERIALIZER_INSTANCE_deserializer_ctx + (OSSL_DESERIALIZER_INSTANCE *deser_inst); + +Feature availability macros: + +=over 4 + +=item OSSL_DESERIALIZER_from_fp() is only available when B +is undefined. + +=back + +=head1 DESCRIPTION + +The B holds data about multiple deserializers, as +needed to figure out what the input data is and to attempt to unpack it into +one of several possible related results. This also includes chaining +deserializers, so the output from one can become the input for another. +This allows having generic format deserializers such as PEM to DER, as well +as more specialized deserializers like DER to RSA. + +The chains may be limited by specifying an input type, which is considered a +starting point. +This is both considered by OSSL_DESERIALIZER_CTX_add_extra(), which will +stop adding on more deserializer implementations when it has already added +those that take the specified input type, and OSSL_DESERIALIZER_from_bio(), +which will only start the deserializing process with the deserializer +implementations that take that input type. For example, if the input type +is set to C, a PEM to DER deserializer will be ignored. + +The input type can also be NULL, which means that the caller doesn't know +what type of input they have. In this case, OSSL_DESERIALIZER_from_bio() +will simply try with one deserializer implementation after the other, and +thereby discover what kind of input the caller gave it. + +For every deserialization done, even intermediary, a I +provided by the caller is used to attempt to "finalize" the current +deserialization output, which is always a provider side object of some +sort, by "wrapping" it into some appropriate type or structure that +the caller knows how to handle. Exactly what this "wrapping" consists +of is entirely at the discretion of the I. + +B is an opaque structure that contains +data about the deserializer that was just used, and that may be +useful for the I. There are some functions to extract data +from this type, described further down. + +=head2 Functions + +OSSL_DESERIALIZER_from_bio() runs the deserialization process for the +context I, with the input coming from the B I. The +application is required to set up the B properly, for example to +have it in text or binary mode if that's appropriate. + +=for comment Know your deserializer! + +OSSL_DESERIALIZER_from_fp() does the same thing as OSSL_DESERIALIZER_from_bio(), +except that the input is coming from the B I. + +OSSL_DESERIALIZER_CTX_add_deserializer() populates the B +I with a deserializer, to be used to attempt to deserialize some +serialized input. + +OSSL_DESERIALIZER_CTX_add_extra() finds deserializers that generate +input for already added deserializers, and adds them as well. This is +used to build deserializer chains. + +OSSL_DESERIALIZER_CTX_set_input_type() sets the starting input type. This +limits the deserializer chains to be considered, as explained in the general +description above. + +OSSL_DESERIALIZER_CTX_num_deserializers() gets the number of +deserializers currently added to the context I. + +OSSL_DESERIALIZER_CTX_set_finalizer() sets the I function +together with the caller argument for the finalizer, I, +as well as I, the function to clean up I when +the deserialization has concluded. + +OSSL_DESERIALIZER_export() is a fallback function for I +that can't use the data they get directly for diverse reasons. It +takes the same deserialize instance I that the +I got and an object I, unpacks the object that +refers to, and exports it by creating an L array that +it then passes to I, along with I. + +OSSL_DESERIALIZER_INSTANCE_deserializer() can be used to get the +deserializer method from a deserializer instance I. + +OSSL_DESERIALIZER_INSTANCE_deserializer-ctx() can be used to get the +deserializer method's provider context from a deserializer instance +I. + +=head2 Finalizer + +The I gets the following arguments: + +=over 4 + +=item I + +The B for the deserializer from which +I gets its data. + +=item I + +The data produced by the deserializer, further described below. + +=item I + +The pointer that was set with OSSL_DESERIALIZE_CTX_set_finalizer() as +I. + +=back + +The I is expected to return 1 when the data it receives can +be "finalized", otherwise 0. + +The globally known parameters that I can get in I +are: + +=over 4 + +=item "data-type" (B) + +This is a detected content type that some deserializers may provide. +For example, PEM input sometimes has a type specified in its header, +and some deserializers may add that information as this parameter. +This is an optional parameter, but may be useful for extra checks in +the I. + +=item "data" (B) + +The deserialized data itself, as an octet string. This is produced by +deserializers when it's possible to pass an object in this form. Most +often, this is simply meant to be passed to the next deserializer in a +chain, but could be considered final data as well, at the discretion +of the I. + +=item "reference" (B) + +The deserialized data itself, as a reference to an object. The +reference itself is an octet string, and can be passed to other +operations and functions within the same provider as the one that +provides I. + +=back + +At least one of "data" or "reference" must be present, and it's +possible that both can be. A I should choose to use the +"reference" parameter if possible, otherwise the "data" parameter. + +If it's not possible to use the "reference" parameter, but that's +still what a I wants to do, it is possible to use +OSSL_DESERIALIZER_export() as a fallback. + +=head1 RETURN VALUES + +OSSL_DESERIALIZER_from_bio() and OSSL_DESERIALIZER_from_fp() return 1 on +success, or 0 on failure. + +OSSL_DESERIALIZER_CTX_add_deserializer(), +OSSL_DESERIALIZER_CTX_add_extra(), and +OSSL_DESERIALIZER_CTX_set_finalizer() return 1 on success, or 0 on +failure. + +OSSL_DESERIALIZER_CTX_num_deserializers() returns the current +number of deserializers. It returns 0 if I is NULL. + +OSSL_DESERIALIZER_export() returns 1 on success, or 0 on failure. + +OSSL_DESERIALIZER_INSTANCE_deserializer() returns an +B pointer on success, or NULL on failure. + +OSSL_DESERIALIZER_INSTANCE_deserializer_ctx() returns a provider +context pointer on success, or NULL on failure.> + +=begin comment TODO(3.0) Add examples! + +=head1 EXAMPLES + +Text, because pod2xxx doesn't like empty sections + +=end comment + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +The functions described here were added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut -- cgit v1.2.3