From: Richard Levitte Date: Mon, 14 Sep 2020 06:29:45 +0000 (+0200) Subject: ENCODER: Redefine the libcrypto <-> provider interface X-Git-Tag: openssl-3.0.0-alpha7~182 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5a6d6fe66614ee5ff5976ca6e90bd156c8143553;p=thirdparty%2Fopenssl.git 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 (Merged from https://github.com/openssl/openssl/pull/12873) --- diff --git a/crypto/property/property_parse.c b/crypto/property/property_parse.c index 6d6ca9b266e..d53961daeaa 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 99787e70407..8048458b947 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-E provider functions +provider-encoder - The OSSL_ENCODER library E-E provider functions =head1 SYNOPSIS @@ -14,6 +14,10 @@ provider-encoder - The ENCODER library E-E 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-E 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 -The ENCODER is a generic method to encode any set of object data -in L 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. +The ENCODER operation is a generic method to encode a provider-native +object (I) or an object abstraction (I, see +L) 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. -The encoder doesn't need to know more about the B pointer than -being able to pass it to the appropriate BIO upcalls (see +The encoder doesn't need to know more about the B +pointer than being able to pass it to the appropriate BIO upcalls (see L). +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), and another one +that encodes DER to PEM (that one would receive the DER encoding via +I). + +=begin comment + +Having the DER encoding passed via I 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 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 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. 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 arrays are indexed by numbers that are provided as macros in L, 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 commands. +An implementation with that output type outputs human readable text, making +that implementation suitable for C<-text> output in diverse L +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, 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 that are passed in an B. -=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 (see L) 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 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, if it was created by OSSL_FUNC_encoder_newctx(). -OSSL_FUNC_encoder_set_ctx_params() sets context data according to -parameters from I that it recognises. Unrecognised parameters -should be ignored. +OSSL_FUNC_encoder_set_ctx_params() sets context data according to parameters +from I that it recognises. Unrecognised parameters should be +ignored. OSSL_FUNC_encoder_settable_ctx_params() returns a constant B array describing the parameters that OSSL_FUNC_encoder_set_ctx_params() can handle. -See L for further details on the parameters structure used -by OSSL_FUNC_encoder_set_ctx_params() and OSSL_FUNC_encoder_settable_ctx_params(). +See L 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 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. + +OSSL_FUNC_encoder_import_object() should import the subset of I +given with I to create a provider-native object that can be +passed as I 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, -I, 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_FUNC_encoder_encode() should take an provider-native object (in +I) or an object abstraction (in I), and should output +the object in encoded form to the B. The I bits, +if relevant, should determine in greater detail what will be output. +The encoding functions also take an B function +pointer along with a pointer to application data I, 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. The caller I 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 -function pointer along with a pointer to application data I, -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) + +This is used to specify a distinct type name for the object passed as +I 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) -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. + +=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 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) - -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 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 5c6a4f4848a..63105d6629a 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 0fc2868d5b7..e3d3d27a7f3 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