diff options
author | Richard Levitte <levitte@openssl.org> | 2020-09-14 08:29:45 +0200 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2020-09-20 17:29:31 +0200 |
commit | 5a6d6fe66614ee5ff5976ca6e90bd156c8143553 (patch) | |
tree | c00404fca24246dc9d7ef442f8915a6dc95e9b62 | |
parent | 4a71bee6cf84d0e6daa9857586ffcebf42aa1842 (diff) |
ENCODER: Redefine the libcrypto <-> provider interface
This is part of an effort to make OSSL_ENCODER work more like OSSL_DECODER.
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/12873)
-rw-r--r-- | crypto/property/property_parse.c | 6 | ||||
-rw-r--r-- | doc/man7/provider-encoder.pod | 231 | ||||
-rw-r--r-- | include/openssl/core_dispatch.h | 31 | ||||
-rw-r--r-- | include/openssl/core_names.h | 4 |
4 files changed, 171 insertions, 101 deletions
diff --git a/crypto/property/property_parse.c b/crypto/property/property_parse.c index 6d6ca9b266..d53961daea 100644 --- a/crypto/property/property_parse.c +++ b/crypto/property/property_parse.c @@ -596,9 +596,9 @@ int ossl_property_parse_init(OPENSSL_CTX *ctx) "provider", /* Name of provider (default, legacy, fips) */ "version", /* Version number of this provider */ "fips", /* FIPS validated or FIPS supporting algorithm */ - "format", /* output format for encoders */ - "type", /* output type for encoders */ - "input", /* input type for decoders */ + "output", /* Output type for encoders */ + "input", /* Input type for decoders */ + "structure", /* Structure name for encoders and decoders */ }; size_t i; diff --git a/doc/man7/provider-encoder.pod b/doc/man7/provider-encoder.pod index 99787e7040..8048458b94 100644 --- a/doc/man7/provider-encoder.pod +++ b/doc/man7/provider-encoder.pod @@ -2,7 +2,7 @@ =head1 NAME -provider-encoder - The ENCODER library E<lt>-E<gt> provider functions +provider-encoder - The OSSL_ENCODER library E<lt>-E<gt> provider functions =head1 SYNOPSIS @@ -14,6 +14,10 @@ provider-encoder - The ENCODER library E<lt>-E<gt> provider functions * pointers in OSSL_DISPATCH arrays. */ + /* Encoder parameter accessor and descriptor */ + const OSSL_PARAM *OSSL_FUNC_encoder_gettable_params(void *provctx); + int encoder_get_params(OSSL_PARAM params[]); + /* Functions to construct / destruct / manipulate the encoder context */ void *OSSL_FUNC_encoder_newctx(void *provctx); void OSSL_FUNC_encoder_freectx(void *ctx); @@ -21,29 +25,51 @@ provider-encoder - The ENCODER library E<lt>-E<gt> provider functions const OSSL_PARAM *OSSL_FUNC_encoder_settable_ctx_params(void *provctx) /* Functions to encode object data */ - int OSSL_FUNC_encoder_encode_data(void *ctx, const OSSL_PARAM *data, - OSSL_CORE_BIO *out, - OSSL_PASSPHRASE_CALLBACK *cb, - void *cbarg); - int OSSL_FUNC_encoder_encode_object(void *ctx, void *obj, OSSL_CORE_BIO *out, - OSSL_PASSPHRASE_CALLBACK *cb, - void *cbarg); + int OSSL_FUNC_encoder_encode(void *ctx, OSSL_CORE_BIO *out, + const void *obj_raw, + const OSSL_PARAM obj_abstract[], + int selection, + OSSL_PASSPHRASE_CALLBACK *cb, + void *cbarg); + + /* Functions to import and free a temporary object to be encoded */ + void *encoder_import_object(void *ctx, int selection, + const OSSL_PARAM params[]); + void encoder_free_object(void *obj); + =head1 DESCRIPTION I<We use the wide term "encode" in this manual. This includes but is not limited to serialization.> -The ENCODER is a generic method to encode any set of object data -in L<OSSL_PARAM(3)> array form, or any provider side object into -encoded form, and write it to the given OSSL_CORE_BIO. If the caller wants -to get the encoded stream to memory, it should provide a -L<BIO_s_membuf(3)>. +The ENCODER operation is a generic method to encode a provider-native +object (I<obj_raw>) or an object abstraction (I<object_abstract>, see +L<provider-object(7)>) into an encoded form, and write the result to +the given OSSL_CORE_BIO. If the caller wants to get the encoded +stream to memory, it should provide a L<BIO_s_membuf(3)>. -The encoder doesn't need to know more about the B<OSSL_CORE_BIO> pointer than -being able to pass it to the appropriate BIO upcalls (see +The encoder doesn't need to know more about the B<OSSL_CORE_BIO> +pointer than being able to pass it to the appropriate BIO upcalls (see L<provider-base(7)/Core functions>). +The ENCODER implementation may be part of a chain, where data is +passed from one to the next. For example, there may be an +implementation to encode an object to DER (that object is assumed to +be provider-native and thereby passed via I<obj_raw>), and another one +that encodes DER to PEM (that one would receive the DER encoding via +I<obj_abstract>). + +=begin comment + +Having the DER encoding passed via I<obj_abstract> may seem +complicated. However, there may be associated meta-data, such as the +original data type, that need to be passed alongside it, and since +L<provider-object(7)> already defines a way to pass such data, +inventing another way to do it makes things even more complicated. + +=end comment + The encoding using the L<OSSL_PARAM(3)> array form allows a encoder to be used for data that's been exported from another provider, and thereby allow them to exist independently of each @@ -66,90 +92,91 @@ B<OSSL_FUNC_{name}>. For example, the "function" OSSL_FUNC_encoder_encode_data() has these: typedef int - (OSSL_FUNC_encoder_encode_data_fn)(void *provctx, - const OSSL_PARAM params[], - OSSL_CORE_BIO *out); - static ossl_inline OSSL_FUNC_encoder_encode_data_fn + (OSSL_FUNC_encoder_encode_fn)(void *ctx, OSSL_CORE_BIO *out, + const void *obj_raw, + const OSSL_PARAM obj_abstract[], + int selection, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg); + static ossl_inline OSSL_FUNC_encoder_encode_fn OSSL_FUNC_encoder_encode_data(const OSSL_DISPATCH *opf); B<OSSL_DISPATCH> arrays are indexed by numbers that are provided as macros in L<openssl-core_dispatch.h(7)>, as follows: + OSSL_FUNC_encoder_get_params OSSL_FUNC_ENCODER_GET_PARAMS + OSSL_FUNC_encoder_gettable_params OSSL_FUNC_ENCODER_GETTABLE_PARAMS + OSSL_FUNC_encoder_newctx OSSL_FUNC_ENCODER_NEWCTX OSSL_FUNC_encoder_freectx OSSL_FUNC_ENCODER_FREECTX OSSL_FUNC_encoder_set_ctx_params OSSL_FUNC_ENCODER_SET_CTX_PARAMS OSSL_FUNC_encoder_settable_ctx_params OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS - OSSL_FUNC_encoder_encode_data OSSL_FUNC_ENCODER_ENCODE_DATA - OSSL_FUNC_encoder_encode_object OSSL_FUNC_ENCODER_ENCODE_OBJECT + OSSL_FUNC_encoder_encode OSSL_FUNC_ENCODER_ENCODE_DATA + + OSSL_FUNC_encoder_import_object OSSL_FUNC_ENCODER_IMPORT_OBJECT + OSSL_FUNC_encoder_free_object OSSL_FUNC_ENCODER_FREE_OBJECT =head2 Names and properties -The name of an implementation should match the type of object it -handles. For example, an implementation that encodes an RSA key -should be named accordingly. +The name of an implementation should match the type of object it handles. +For example, an implementation that encodes an RSA key should be named "RSA". +Likewise, an implementation that further encodes DER should be named "DER". -To be able to specify exactly what encoding format and what type -of data a encoder implementation is expected to handle, two -additional properties may be given: +Properties can be use to further specify details about an implementation: =over 4 -=item format +=item output -This property is used to specify what kind of output format the -implementation produces. Currently known formats are: +This property is used to specify what type of output implementation +produces. Currently known output types are: =over 4 =item text -An implementation with that format property value outputs human -readable text, making that implementation suitable for C<-text> output -in diverse L<openssl(1)> commands. +An implementation with that output type outputs human readable text, making +that implementation suitable for C<-text> output in diverse L<openssl(1)> +commands. =item pem -An implementation with that format property value outputs PEM -formatted data. +An implementation with that output type outputs PEM formatted data. =item der -An implementation with that format property value outputs DER -formatted data. +An implementation with that output type outputs DER formatted data. =back -=item type +=item structure -With objects that have multiple purposes, this can be used to specify -the purpose type. The currently known use cases are asymmetric keys -and key parameters, where the type can be one of: +This property is used to specify the structure that is used for the encoded +object. An example could be C<pkcs8>, to specify explicitly that an object +(presumably an asymmetric key pair, in this case) will be wrapped in a +PKCS#8 structure as part of the encoding. -=over 4 - -=item private +=back -An implementation with that format property value outputs a private -key. +The possible values of both these properties is open ended. A provider may +very well specify output types and structures that libcrypto doesn't know +anything about. -=item public +=head2 Subset selections -An implementation with that format property value outputs a public -key. +Sometimes, an object has more than one subset of data that is interesting to +treat separately or together. It's possible to specify what subsets are to +be encoded, with a set of bits I<selection> that are passed in an B<int>. -=item parameters +This set of bits depend entirely on what kind of provider-side object is +passed. For example, those bits are assumed to be the same as those used +with L<provider-keymgmt(7)> (see L<provider-keymgmt(7)/Key Objects>) when +the object is an asymmetric key. -An implementation with that format property value outputs key -parameters. - -=back - -=back - -The possible values of both these properties is open ended. A -provider may very well specify other formats that libcrypto doesn't -know anything about. +ENCODER implementations are free to regard the I<selection> as a set of +hints, but must do so with care. In the end, the output must make sense, +and if there's a corresponding decoder, the resulting decoded object must +match the original object that was encoded. =head2 Context functions @@ -159,40 +186,76 @@ the functions. OSSL_FUNC_encoder_freectx() frees the given I<ctx>, if it was created by OSSL_FUNC_encoder_newctx(). -OSSL_FUNC_encoder_set_ctx_params() sets context data according to -parameters from I<params> that it recognises. Unrecognised parameters -should be ignored. +OSSL_FUNC_encoder_set_ctx_params() sets context data according to parameters +from I<params> that it recognises. Unrecognised parameters should be +ignored. OSSL_FUNC_encoder_settable_ctx_params() returns a constant B<OSSL_PARAM> array describing the parameters that OSSL_FUNC_encoder_set_ctx_params() can handle. -See L<OSSL_PARAM(3)> for further details on the parameters structure used -by OSSL_FUNC_encoder_set_ctx_params() and OSSL_FUNC_encoder_settable_ctx_params(). +See L<OSSL_PARAM(3)> for further details on the parameters structure used by +OSSL_FUNC_encoder_set_ctx_params() and OSSL_FUNC_encoder_settable_ctx_params(). + +=head2 Import functions + +A provider-native object may be associated with a foreign provider, and may +therefore be unsuitable for direct use with a given ENCODER implementation. +Provided that the foreign provider's implementation to handle the object has +a function to export that object in L<OSSL_PARAM(3)> array form, the ENCODER +implementation should be able to import that array and create a suitable +object to be passed to OSSL_FUNC_encoder_encode()'s I<obj_raw>. + +OSSL_FUNC_encoder_import_object() should import the subset of I<params> +given with I<selection> to create a provider-native object that can be +passed as I<obj_raw> to OSSL_FUNC_encoder_encode(). + +OSSL_FUNC_encoder_free_object() should free the object that was created with +OSSL_FUNC_encoder_import_object(). =head2 Encoding functions =for comment There will be a "Decoding functions" title as well -OSSL_FUNC_encoder_encode_data() should take an array of B<OSSL_PARAM>, -I<data>, and if it contains the data necessary for the object type -that the implementation handles, it should output the object in -encoded form to the B<OSSL_CORE_BIO>. +OSSL_FUNC_encoder_encode() should take an provider-native object (in +I<obj_raw>) or an object abstraction (in I<obj_abstract>), and should output +the object in encoded form to the B<OSSL_CORE_BIO>. The I<selection> bits, +if relevant, should determine in greater detail what will be output. +The encoding functions also take an B<OSSL_PASSPHRASE_CALLBACK> function +pointer along with a pointer to application data I<cbarg>, which should be +used when a pass phrase prompt is needed. -OSSL_FUNC_encoder_encode_object() should take a pointer to an object -that it knows intimately, and output that object in encoded form to -the B<OSSL_CORE_BIO>. The caller I<must> ensure that this function is called -with a pointer that the provider of this function is familiar with. -It is not suitable to use with object pointers coming from other -providers. +=head2 Encoder parameters -Both encoding functions also take an B<OSSL_PASSPHRASE_CALLBACK> -function pointer along with a pointer to application data I<cbarg>, -which should be used when a pass phrase prompt is needed. +The ENCODER implementation itself has parameters that can be used to +determine how it fits in a chain of encoders: -=head2 Encoder parameters +=over 4 + +=item "input-type" (B<OSSL_ENCODER_PARAM_INPUT_TYPE>) <UTF8 string> + +This is used to specify a distinct type name for the object passed as +I<obj_raw> to OSSL_FUNC_encoder_encode. + +This parameter is an optional parameter, to be used if the name of the +implementation can be ambiguous because of aliases, and something more +deterministic is needed. + +=item "output-type" (B<OSSL_ENCODER_PARAM_OUTPUT_TYPE>) <UTF8 string> -Parameters currently recognised by built-in encoders are as +This is used to specify the output type for an ENCODER implementation. + +This parameter is I<mandatory>. + +=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 output type +from the C<output> property. + +=back + +=head2 Encoder operation parameters + +Operation parameters currently recognised by built-in encoders are as follows: =over 4 @@ -220,11 +283,6 @@ However, it is recommended that implementations that do not handle property strings return an error on receiving this parameter unless its value NULL or the empty string. -=item "passphrase" (B<OSSL_ENCODER_PARAM_PASS>) <octet string> - -A pass phrase provided by the application. When this is given, the -built-in encoders will not attempt to use the passphrase callback. - =back Parameters currently recognised by the built-in pass phrase callback: @@ -250,8 +308,7 @@ parameters was invalid or caused an error, for which 0 is returned. OSSL_FUNC_encoder_settable_ctx_params() returns a pointer to an array of constant B<OSSL_PARAM> elements. -OSSL_FUNC_encoder_encode_data() and OSSL_FUNC_encoder_encode_object() -return 1 on success, or 0 on failure. +OSSL_FUNC_encoder_encode() return 1 on success, or 0 on failure. =head1 SEE ALSO diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h index 5c6a4f4848..63105d6629 100644 --- a/include/openssl/core_dispatch.h +++ b/include/openssl/core_dispatch.h @@ -752,24 +752,37 @@ OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, kem_settable_ctx_params, (void *provctx) /* Encoders and decoders */ # define OSSL_FUNC_ENCODER_NEWCTX 1 # define OSSL_FUNC_ENCODER_FREECTX 2 -# define OSSL_FUNC_ENCODER_SET_CTX_PARAMS 3 -# define OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS 4 -# define OSSL_FUNC_ENCODER_ENCODE_DATA 10 -# define OSSL_FUNC_ENCODER_ENCODE_OBJECT 11 +# define OSSL_FUNC_ENCODER_GET_PARAMS 3 +# define OSSL_FUNC_ENCODER_GETTABLE_PARAMS 4 +# define OSSL_FUNC_ENCODER_SET_CTX_PARAMS 5 +# define OSSL_FUNC_ENCODER_SETTABLE_CTX_PARAMS 6 +# define OSSL_FUNC_ENCODER_ENCODE 10 +# define OSSL_FUNC_ENCODER_IMPORT_OBJECT 20 +# define OSSL_FUNC_ENCODER_FREE_OBJECT 21 OSSL_CORE_MAKE_FUNC(void *, encoder_newctx, (void *provctx)) OSSL_CORE_MAKE_FUNC(void, encoder_freectx, (void *ctx)) +OSSL_CORE_MAKE_FUNC(int, encoder_get_params, (OSSL_PARAM params[])) +OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, encoder_gettable_params, + (void *provctx)) OSSL_CORE_MAKE_FUNC(int, encoder_set_ctx_params, (void *ctx, const OSSL_PARAM params[])) OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, encoder_settable_ctx_params, (void *provctx)) -OSSL_CORE_MAKE_FUNC(int, encoder_encode_data, - (void *ctx, const OSSL_PARAM[], OSSL_CORE_BIO *out, - OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)) -OSSL_CORE_MAKE_FUNC(int, encoder_encode_object, - (void *ctx, const void *obj, OSSL_CORE_BIO *out, +/* + * TODO(3.0) investigate if this should be two functions, one that takes a + * raw object and one that takes an object abstraction. + */ +OSSL_CORE_MAKE_FUNC(int, encoder_encode, + (void *ctx, OSSL_CORE_BIO *out, + const void *obj_raw, const OSSL_PARAM obj_abstract[], + int selection, OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)) +OSSL_CORE_MAKE_FUNC(void *, encoder_import_object, + (void *ctx, int selection, const OSSL_PARAM params[])) +OSSL_CORE_MAKE_FUNC(void, encoder_free_object, (void *obj)) + # define OSSL_FUNC_DECODER_NEWCTX 1 # define OSSL_FUNC_DECODER_FREECTX 2 # define OSSL_FUNC_DECODER_GET_PARAMS 3 diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h index 0fc2868d5b..e3d3d27a7f 100644 --- a/include/openssl/core_names.h +++ b/include/openssl/core_names.h @@ -445,10 +445,10 @@ extern "C" { /* * Encoder / decoder parameters */ -/* The passphrase may be passed as a utf8 string or an octet string */ #define OSSL_ENCODER_PARAM_CIPHER OSSL_ALG_PARAM_CIPHER #define OSSL_ENCODER_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES -#define OSSL_ENCODER_PARAM_PASS "passphrase" +#define OSSL_ENCODER_PARAM_INPUT_TYPE "input-type" +#define OSSL_ENCODER_PARAM_OUTPUT_TYPE "output-type" #define OSSL_DECODER_PARAM_CIPHER OSSL_ALG_PARAM_CIPHER #define OSSL_DECODER_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES |