| =pod |
| |
| =head1 NAME |
| |
| provider-base |
| - The basic OpenSSL library E<lt>-E<gt> provider functions |
| |
| =head1 SYNOPSIS |
| |
| #include <openssl/core_dispatch.h> |
| |
| /* |
| * None of these are actual functions, but are displayed like this for |
| * the function signatures for functions that are offered as function |
| * pointers in OSSL_DISPATCH arrays. |
| */ |
| |
| /* Functions offered by libcrypto to the providers */ |
| const OSSL_ITEM *core_gettable_params(const OSSL_CORE_HANDLE *handle); |
| int core_get_params(const OSSL_CORE_HANDLE *handle, OSSL_PARAM params[]); |
| int core_thread_start(const OSSL_CORE_HANDLE *handle, |
| OSSL_thread_stop_handler_fn handfn); |
| OPENSSL_CORE_CTX *core_get_libctx(const OSSL_CORE_HANDLE *handle); |
| void core_new_error(const OSSL_CORE_HANDLE *handle); |
| void core_set_error_debug(const OSSL_CORE_HANDLE *handle, |
| const char *file, int line, const char *func); |
| void core_vset_error(const OSSL_CORE_HANDLE *handle, |
| uint32_t reason, const char *fmt, va_list args); |
| |
| /* |
| * Some OpenSSL functionality is directly offered to providers via |
| * dispatch |
| */ |
| void *CRYPTO_malloc(size_t num, const char *file, int line); |
| void *CRYPTO_zalloc(size_t num, const char *file, int line); |
| void *CRYPTO_memdup(const void *str, size_t siz, |
| const char *file, int line); |
| char *CRYPTO_strdup(const char *str, const char *file, int line); |
| char *CRYPTO_strndup(const char *str, size_t s, |
| const char *file, int line); |
| void CRYPTO_free(void *ptr, const char *file, int line); |
| void CRYPTO_clear_free(void *ptr, size_t num, |
| const char *file, int line); |
| void *CRYPTO_realloc(void *addr, size_t num, |
| const char *file, int line); |
| void *CRYPTO_clear_realloc(void *addr, size_t old_num, size_t num, |
| const char *file, int line); |
| void *CRYPTO_secure_malloc(size_t num, const char *file, int line); |
| void *CRYPTO_secure_zalloc(size_t num, const char *file, int line); |
| void CRYPTO_secure_free(void *ptr, const char *file, int line); |
| void CRYPTO_secure_clear_free(void *ptr, size_t num, |
| const char *file, int line); |
| int CRYPTO_secure_allocated(const void *ptr); |
| void OPENSSL_cleanse(void *ptr, size_t len); |
| |
| OSSL_CORE_BIO * BIO_new_file(const char *filename, const char *mode) |
| OSSL_CORE_BIO * BIO_new_membuf(const void *buf, int len) |
| int BIO_read_ex(OSSL_CORE_BIO *bio, void *data, size_t data_len, |
| size_t *bytes_read)) |
| int BIO_write_ex(OSSL_CORE_BIO *bio, const void *data, size_t data_len, |
| size_t *written) |
| int BIO_free(OSSL_CORE_BIO *bio)) |
| int BIO_vprintf(OSSL_CORE_BIO *bio, const char *format, va_list args) |
| int BIO_vsnprintf(char *buf, size_t n, const char *fmt, va_list args) |
| |
| void self_test_cb(OPENSSL_CORE_CTX *ctx, OSSL_CALLBACK **cb, void **cbarg) |
| |
| size_t get_entropy(const OSSL_CORE_HANDLE *handle, |
| unsigned char **pout, int entropy, |
| size_t min_len, size_t max_len) |
| void cleanup_entropy(const OSSL_CORE_HANDLE *handle, |
| unsigned char *buf, size_t len) |
| size_t get_nonce(const OSSL_CORE_HANDLE *handle, |
| unsigned char **pout, size_t min_len, size_t max_len, |
| const void *salt, size_t salt_len) |
| void cleanup_nonce(const OSSL_CORE_HANDLE *handle, |
| unsigned char *buf, size_t len) |
| |
| /* Functions offered by the provider to libcrypto */ |
| void provider_teardown(void *provctx); |
| const OSSL_ITEM *provider_gettable_params(void *provctx); |
| int provider_get_params(void *provctx, OSSL_PARAM params[]); |
| const OSSL_ALGORITHM *provider_query_operation(void *provctx, |
| int operation_id, |
| const int *no_store); |
| const OSSL_ITEM *provider_get_reason_strings(void *provctx); |
| int provider_get_capabilities(void *provctx, const char *capability, |
| OSSL_CALLBACK *cb, void *arg); |
| |
| =head1 DESCRIPTION |
| |
| All "functions" mentioned here are passed as function pointers between |
| F<libcrypto> and the provider in B<OSSL_DISPATCH> arrays, in the call |
| of the provider initialization function. See L<provider(7)/Provider> |
| for a description of the initialization function. |
| |
| All these "functions" have a corresponding function type definition |
| named B<OSSL_{name}_fn>, and a helper function to retrieve the |
| function pointer from a B<OSSL_DISPATCH> element named |
| B<OSSL_FUNC_{name}>. |
| For example, the "function" core_gettable_params() has these: |
| |
| typedef OSSL_PARAM * |
| (OSSL_FUNC_core_gettable_params_fn)(const OSSL_CORE_HANDLE *handle); |
| static ossl_inline OSSL_NAME_core_gettable_params_fn |
| OSSL_FUNC_core_gettable_params(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: |
| |
| For I<in> (the B<OSSL_DISPATCH> array passed from F<libcrypto> to the |
| provider): |
| |
| core_gettable_params OSSL_FUNC_CORE_GETTABLE_PARAMS |
| core_get_params OSSL_FUNC_CORE_GET_PARAMS |
| core_thread_start OSSL_FUNC_CORE_THREAD_START |
| core_get_libctx OSSL_FUNC_CORE_GET_LIBCTX |
| core_new_error OSSL_FUNC_CORE_NEW_ERROR |
| core_set_error_debug OSSL_FUNC_CORE_SET_ERROR_DEBUG |
| core_set_error OSSL_FUNC_CORE_SET_ERROR |
| CRYPTO_malloc OSSL_FUNC_CRYPTO_MALLOC |
| CRYPTO_zalloc OSSL_FUNC_CRYPTO_ZALLOC |
| CRYPTO_memdup OSSL_FUNC_CRYPTO_MEMDUP |
| CRYPTO_strdup OSSL_FUNC_CRYPTO_STRDUP |
| CRYPTO_strndup OSSL_FUNC_CRYPTO_STRNDUP |
| CRYPTO_free OSSL_FUNC_CRYPTO_FREE |
| CRYPTO_clear_free OSSL_FUNC_CRYPTO_CLEAR_FREE |
| CRYPTO_realloc OSSL_FUNC_CRYPTO_REALLOC |
| CRYPTO_clear_realloc OSSL_FUNC_CRYPTO_CLEAR_REALLOC |
| CRYPTO_secure_malloc OSSL_FUNC_CRYPTO_SECURE_MALLOC |
| CRYPTO_secure_zalloc OSSL_FUNC_CRYPTO_SECURE_ZALLOC |
| CRYPTO_secure_free OSSL_FUNC_CRYPTO_SECURE_FREE |
| CRYPTO_secure_clear_free OSSL_FUNC_CRYPTO_SECURE_CLEAR_FREE |
| CRYPTO_secure_allocated OSSL_FUNC_CRYPTO_SECURE_ALLOCATED |
| BIO_new_file OSSL_FUNC_BIO_NEW_FILE |
| BIO_new_mem_buf OSSL_FUNC_BIO_NEW_MEMBUF |
| BIO_read_ex OSSL_FUNC_BIO_READ_EX |
| BIO_free OSSL_FUNC_BIO_FREE |
| BIO_vprintf OSSL_FUNC_BIO_VPRINTF |
| OPENSSL_cleanse OSSL_FUNC_OPENSSL_CLEANSE |
| OSSL_SELF_TEST_set_callback OSSL_FUNC_SELF_TEST_CB |
| ossl_rand_get_entropy OSSL_FUNC_GET_ENTROPY |
| ossl_rand_cleanup_entropy OSSL_FUNC_CLEANUP_ENTROPY |
| ossl_rand_get_nonce OSSL_FUNC_GET_NONCE |
| ossl_rand_cleanup_nonce OSSL_FUNC_CLEANUP_NONCE |
| |
| For I<*out> (the B<OSSL_DISPATCH> array passed from the provider to |
| F<libcrypto>): |
| |
| provider_teardown OSSL_FUNC_PROVIDER_TEARDOWN |
| provider_gettable_params OSSL_FUNC_PROVIDER_GETTABLE_PARAMS |
| provider_get_params OSSL_FUNC_PROVIDER_GET_PARAMS |
| provider_query_operation OSSL_FUNC_PROVIDER_QUERY_OPERATION |
| provider_get_reason_strings OSSL_FUNC_PROVIDER_GET_REASON_STRINGS |
| provider_get_capabilities OSSL_FUNC_PROVIDER_GET_CAPABILITIES |
| provider_self_test OSSL_FUNC_PROVIDER_SELF_TEST |
| |
| =head2 Core functions |
| |
| core_gettable_params() returns a constant array of descriptor |
| B<OSSL_PARAM>, for parameters that core_get_params() can handle. |
| |
| core_get_params() retrieves parameters from the core for the given I<handle>. |
| See L</Core parameters> below for a description of currently known |
| parameters. |
| |
| =for comment core_thread_start() TBA |
| |
| core_get_libctx() retrieves the library context in which the library |
| object for the current provider is stored, accessible through the I<handle>. |
| This may sometimes be useful if the provider wishes to store a |
| reference to its context in the same library context. |
| |
| core_new_error(), core_set_error_debug() and core_set_error() are |
| building blocks for reporting an error back to the core, with |
| reference to the I<handle>. |
| |
| =over 4 |
| |
| =item core_new_error() |
| |
| allocates a new thread specific error record. |
| |
| This corresponds to the OpenSSL function L<ERR_new(3)>. |
| |
| =item core_set_error_debug() |
| |
| sets debugging information in the current thread specific error |
| record. |
| The debugging information includes the name of the file I<file>, the |
| line I<line> and the function name I<func> where the error occurred. |
| |
| This corresponds to the OpenSSL function L<ERR_set_debug(3)>. |
| |
| =item core_set_error() |
| |
| sets the I<reason> for the error, along with any addition data. |
| The I<reason> is a number defined by the provider and used to index |
| the reason strings table that's returned by |
| provider_get_reason_strings(). |
| The additional data is given as a format string I<fmt> and a set of |
| arguments I<args>, which are treated in the same manner as with |
| BIO_vsnprintf(). |
| I<file> and I<line> may also be passed to indicate exactly where the |
| error occurred or was reported. |
| |
| This corresponds to the OpenSSL function L<ERR_vset_error(3)>. |
| |
| =back |
| |
| CRYPTO_malloc(), CRYPTO_zalloc(), CRYPTO_memdup(), CRYPTO_strdup(), |
| CRYPTO_strndup(), CRYPTO_free(), CRYPTO_clear_free(), |
| CRYPTO_realloc(), CRYPTO_clear_realloc(), CRYPTO_secure_malloc(), |
| CRYPTO_secure_zalloc(), CRYPTO_secure_free(), |
| CRYPTO_secure_clear_free(), CRYPTO_secure_allocated(), |
| BIO_new_file(), BIO_new_mem_buf(), BIO_read_ex(), BIO_free(), |
| BIO_vprintf(), OPENSSL_cleanse(), and OPENSSL_hexstr2buf() |
| correspond exactly to the public functions with the same name. |
| As a matter of fact, the pointers in the B<OSSL_DISPATCH> array are |
| direct pointers to those public functions. Note that the BIO functions take an |
| B<OSSL_CORE_BIO> type rather than the standard B<BIO> type. This is to ensure |
| that a provider does not mix BIOs from the core with BIOs used on the provider |
| side (the two are not compatible). |
| OSSL_SELF_TEST_set_callback() is used to set an optional callback that can be |
| passed into a provider. This may be ignored by a provider. |
| |
| get_entropy() retrieves seeding material from the operating system. |
| The seeding material will have at least I<entropy> bytes of randomness and the |
| output will have at least I<min_len> and at most I<max_len> bytes. |
| The buffer address is stored in I<*pout> and the buffer length is |
| returned to the caller. On error, zero is returned. |
| |
| cleanup_entropy() is used to clean up and free the buffer returned by |
| get_entropy(). The entropy pointer returned by get_entropy() is passed in |
| B<buf> and its length in B<len>. |
| |
| get_nonce() retrieves a nonce using the passed I<salt> parameter |
| of length I<salt_len> and operating system specific information. |
| The I<salt> should contain uniquely identifying information and this is |
| included, in an unspecified manner, as part of the output. |
| The output is stored in a buffer which contrains at least I<min_len> and at |
| most I<max_len> bytes. The buffer address is stored in I<*pout> and the |
| buffer length returned to the caller. On error, zero is returned. |
| |
| cleanup_nonce() is used to clean up and free the buffer returned by |
| get_nonce(). The nonce pointer returned by get_nonce() is passed in |
| B<buf> and its length in B<len>. |
| |
| =head2 Provider functions |
| |
| provider_teardown() is called when a provider is shut down and removed |
| from the core's provider store. |
| It must free the passed I<provctx>. |
| |
| provider_gettable_params() should return a constant array of |
| descriptor B<OSSL_PARAM>, for parameters that provider_get_params() |
| can handle. |
| |
| provider_get_params() should process the B<OSSL_PARAM> array |
| I<params>, setting the values of the parameters it understands. |
| |
| provider_query_operation() should return a constant B<OSSL_ALGORITHM> |
| that corresponds to the given I<operation_id>. |
| It should indicate if the core may store a reference to this array by |
| setting I<*no_store> to 0 (core may store a reference) or 1 (core may |
| not store a reference). |
| |
| provider_get_reason_strings() should return a constant B<OSSL_ITEM> |
| array that provides reason strings for reason codes the provider may |
| use when reporting errors using core_put_error(). |
| |
| The provider_get_capabilities() function should call the callback I<cb> passing |
| it a set of B<OSSL_PARAM>s and the caller supplied argument I<arg>. The |
| B<OSSL_PARAM>s should provide details about the capability with the name given |
| in the I<capability> argument relevant for the provider context I<provctx>. If a |
| provider supports multiple capabilities with the given name then it may call the |
| callback multiple times (one for each capability). Capabilities can be useful for |
| describing the services that a provider can offer. For further details see the |
| L</CAPABILITIES> section below. It should return 1 on success or 0 on error. |
| |
| The provider_self_test() function should perform known answer tests on a subset |
| of the algorithms that it uses, and may also verify the integrity of the |
| provider module. It should return 1 on success or 0 on error. It will return 1 |
| if this function is not used. |
| |
| None of these functions are mandatory, but a provider is fairly |
| useless without at least provider_query_operation(), and |
| provider_gettable_params() is fairly useless if not accompanied by |
| provider_get_params(). |
| |
| =head2 Provider parameters |
| |
| provider_get_params() can return the following provider parameters to the core: |
| |
| =over 4 |
| |
| =item "name" (B<OSSL_PROV_PARAM_NAME>) <UTF8_ptr> |
| |
| This points to a string that should give a unique name for the provider. |
| |
| =item "version" (B<OSSL_PROV_PARAM_VERSION>) <UTF8_ptr> |
| |
| This points to a string that is a version number associated with this provider. |
| OpenSSL in-built providers use OPENSSL_VERSION_STR, but this may be different |
| for any third party provider. This string is for informational purposes only. |
| |
| =item "buildinfo" (B<OSSL_PROV_PARAM_BUILDINFO>) <UTF8_ptr> |
| |
| This points to a string that is a build information associated with this provider. |
| OpenSSL in-built providers use OPENSSL_FULL_VERSION_STR, but this may be |
| different for any third party provider. |
| |
| =item "status" (B<OSSL_PROV_PARAM_STATUS>) <unsigned integer> |
| |
| This returns 0 if the provider has entered an error state, otherwise it returns |
| 1. |
| |
| =back |
| |
| provider_gettable_params() should return the above parameters. |
| |
| |
| =head2 Core parameters |
| |
| core_get_params() can retrieve the following core parameters for each provider: |
| |
| =over 4 |
| |
| =item "openssl-version" (B<OSSL_PROV_PARAM_CORE_VERSION>) <UTF8_ptr> |
| |
| This points to the OpenSSL libraries' full version string, i.e. the string |
| expanded from the macro B<OPENSSL_VERSION_STR>. |
| |
| =item "provider-name" (B<OSSL_PROV_PARAM_CORE_PROV_NAME>) <UTF8_ptr> |
| |
| This points to the OpenSSL libraries' idea of what the calling provider is named. |
| |
| =item "module-filename" (B<OSSL_PROV_PARAM_CORE_MODULE_FILENAME>) <UTF8_ptr> |
| |
| This points to a string containing the full filename of the providers |
| module file. |
| |
| =back |
| |
| Additionally, provider specific configuration parameters from the |
| config file are available, in dotted name form. |
| The dotted name form is a concatenation of section names and final |
| config command name separated by periods. |
| |
| For example, let's say we have the following config example: |
| |
| openssl_conf = openssl_init |
| |
| [openssl_init] |
| providers = providers_sect |
| |
| [providers_sect] |
| foo = foo_sect |
| |
| [foo_sect] |
| activate = 1 |
| data1 = 2 |
| data2 = str |
| more = foo_more |
| |
| [foo_more] |
| data3 = foo,bar |
| |
| The provider will have these additional parameters available: |
| |
| =over 4 |
| |
| =item "activate" |
| |
| pointing at the string "1" |
| |
| =item "data1" |
| |
| pointing at the string "2" |
| |
| =item "data2" |
| |
| pointing at the string "str" |
| |
| =item "more.data3" |
| |
| pointing at the string "foo,bar" |
| |
| =back |
| |
| For more information on handling parameters, see L<OSSL_PARAM(3)> as |
| L<OSSL_PARAM_int(3)>. |
| |
| =head1 CAPABILITIES |
| |
| Capabilities describe some of the services that a provider can offer. |
| Applications can query the capabilities to discover those services. |
| |
| =head3 "TLS-GROUP" Capability |
| |
| The "TLS-GROUP" capability can be queried by libssl to discover the list of |
| TLS groups that a provider can support. Each group supported can be used for |
| I<key exchange> (KEX) or I<key encapsulation method> (KEM) during a TLS |
| handshake. |
| TLS clients can advertise the list of TLS groups they support in the |
| supported_groups extension, and TLS servers can select a group from the offered |
| list that they also support. In this way a provider can add to the list of |
| groups that libssl already supports with additional ones. |
| |
| Each TLS group that a provider supports should be described via the callback |
| passed in through the provider_get_capabilities function. Each group should have |
| the following details supplied (all are mandatory, except |
| B<OSSL_CAPABILITY_TLS_GROUP_IS_KEM>): |
| |
| =over 4 |
| |
| =item "tls-group-name" (B<OSSL_CAPABILITY_TLS_GROUP_NAME>) <utf8 string> |
| |
| The name of the group as given in the IANA TLS Supported Groups registry |
| L<https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8>. |
| |
| =item "tls-group-name-internal" (B<OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL>) <utf8 string> |
| |
| The name of the group as known by the provider. This could be the same as the |
| "tls-group-name", but does not have to be. |
| |
| =item "tls-group-id" (B<OSSL_CAPABILITY_TLS_GROUP_ID>) <unsigned integer> |
| |
| The TLS group id value as given in the IANA TLS Supported Groups registry. |
| |
| =item "tls-group-alg" (B<OSSL_CAPABILITY_TLS_GROUP_ALG>) <utf8 string> |
| |
| The name of a Key Management algorithm that the provider offers and that should |
| be used with this group. Keys created should be able to support I<key exchange> |
| or I<key encapsulation method> (KEM), as implied by the optional |
| B<OSSL_CAPABILITY_TLS_GROUP_IS_KEM> flag. |
| The algorithm must support key and parameter generation as well as the |
| key/parameter generation parameter, B<OSSL_PKEY_PARAM_GROUP_NAME>. The group |
| name given via "tls-group-name-internal" above will be passed via |
| B<OSSL_PKEY_PARAM_GROUP_NAME> when libssl wishes to generate keys/parameters. |
| |
| =item "tls-group-sec-bits" (B<OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS>) <unsigned integer> |
| |
| The number of bits of security offered by keys in this group. The number of bits |
| should be comparable with the ones given in table 2 and 3 of the NIST SP800-57 |
| document. |
| |
| =item "tls-group-is-kem" (B<OSSL_CAPABILITY_TLS_GROUP_IS_KEM>) <unsigned integer> |
| |
| Boolean flag to describe if the group should be used in I<key exchange> (KEX) |
| mode (0, default) or in I<key encapsulation method> (KEM) mode (1). |
| |
| This parameter is optional: if not specified, KEX mode is assumed as the default |
| mode for the group. |
| |
| In KEX mode, in a typical Diffie-Hellman fashion, both sides execute I<keygen> |
| then I<derive> against the peer public key. To operate in KEX mode, the group |
| implementation must support the provider functions as described in |
| L<provider-keyexch(7)>. |
| |
| In KEM mode, the client executes I<keygen> and sends its public key, the server |
| executes I<encapsulate> using the client's public key and sends back the |
| resulting I<ciphertext>, finally the client executes I<decapsulate> to retrieve |
| the same I<shared secret> generated by the server's I<encapsulate>. To operate |
| in KEM mode, the group implementation must support the provider functions as |
| described in L<provider-kem(7)>. |
| |
| Both in KEX and KEM mode, the resulting I<shared secret> is then used according |
| to the protocol specification. |
| |
| =item "tls-min-tls" (B<OSSL_CAPABILITY_TLS_GROUP_MIN_TLS>) <integer> |
| |
| =item "tls-max-tls" (B<OSSL_CAPABILITY_TLS_GROUP_MAX_TLS>) <integer> |
| |
| =item "tls-min-dtls" (B<OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS>) <integer> |
| |
| =item "tls-max-dtls" (B<OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS>) <integer> |
| |
| These parameters can be used to describe the minimum and maximum TLS and DTLS |
| versions supported by the group. The values equate to the on-the-wire encoding |
| of the various TLS versions. For example TLSv1.3 is 0x0304 (772 decimal), and |
| TLSv1.2 is 0x0303 (771 decimal). A 0 indicates that there is no defined minimum |
| or maximum. A -1 indicates that the group should not be used in that protocol. |
| |
| =back |
| |
| =head1 EXAMPLES |
| |
| This is an example of a simple provider made available as a |
| dynamically loadable module. |
| It implements the fictitious algorithm C<FOO> for the fictitious |
| operation C<BAR>. |
| |
| #include <malloc.h> |
| #include <openssl/core.h> |
| #include <openssl/core_dispatch.h> |
| |
| /* Errors used in this provider */ |
| #define E_MALLOC 1 |
| |
| static const OSSL_ITEM reasons[] = { |
| { E_MALLOC, "memory allocation failure" }. |
| { 0, NULL } /* Termination */ |
| }; |
| |
| /* |
| * To ensure we get the function signature right, forward declare |
| * them using function types provided by openssl/core_dispatch.h |
| */ |
| OSSL_FUNC_bar_newctx_fn foo_newctx; |
| OSSL_FUNC_bar_freectx_fn foo_freectx; |
| OSSL_FUNC_bar_init_fn foo_init; |
| OSSL_FUNC_bar_update_fn foo_update; |
| OSSL_FUNC_bar_final_fn foo_final; |
| |
| OSSL_FUNC_provider_query_operation_fn p_query; |
| OSSL_FUNC_provider_get_reason_strings_fn p_reasons; |
| OSSL_FUNC_provider_teardown_fn p_teardown; |
| |
| OSSL_provider_init_fn OSSL_provider_init; |
| |
| OSSL_FUNC_core_put_error *c_put_error = NULL; |
| |
| /* Provider context */ |
| struct prov_ctx_st { |
| OSSL_CORE_HANDLE *handle; |
| } |
| |
| /* operation context for the algorithm FOO */ |
| struct foo_ctx_st { |
| struct prov_ctx_st *provctx; |
| int b; |
| }; |
| |
| static void *foo_newctx(void *provctx) |
| { |
| struct foo_ctx_st *fooctx = malloc(sizeof(*fooctx)); |
| |
| if (fooctx != NULL) |
| fooctx->provctx = provctx; |
| else |
| c_put_error(provctx->handle, E_MALLOC, __FILE__, __LINE__); |
| return fooctx; |
| } |
| |
| static void foo_freectx(void *fooctx) |
| { |
| free(fooctx); |
| } |
| |
| static int foo_init(void *vfooctx) |
| { |
| struct foo_ctx_st *fooctx = vfooctx; |
| |
| fooctx->b = 0x33; |
| } |
| |
| static int foo_update(void *vfooctx, unsigned char *in, size_t inl) |
| { |
| struct foo_ctx_st *fooctx = vfooctx; |
| |
| /* did you expect something serious? */ |
| if (inl == 0) |
| return 1; |
| for (; inl-- > 0; in++) |
| *in ^= fooctx->b; |
| return 1; |
| } |
| |
| static int foo_final(void *vfooctx) |
| { |
| struct foo_ctx_st *fooctx = vfooctx; |
| |
| fooctx->b = 0x66; |
| } |
| |
| static const OSSL_DISPATCH foo_fns[] = { |
| { OSSL_FUNC_BAR_NEWCTX, (void (*)(void))foo_newctx }, |
| { OSSL_FUNC_BAR_FREECTX, (void (*)(void))foo_freectx }, |
| { OSSL_FUNC_BAR_INIT, (void (*)(void))foo_init }, |
| { OSSL_FUNC_BAR_UPDATE, (void (*)(void))foo_update }, |
| { OSSL_FUNC_BAR_FINAL, (void (*)(void))foo_final }, |
| { 0, NULL } |
| }; |
| |
| static const OSSL_ALGORITHM bars[] = { |
| { "FOO", "provider=chumbawamba", foo_fns }, |
| { NULL, NULL, NULL } |
| }; |
| |
| static const OSSL_ALGORITHM *p_query(void *provctx, int operation_id, |
| int *no_store) |
| { |
| switch (operation_id) { |
| case OSSL_OP_BAR: |
| return bars; |
| } |
| return NULL; |
| } |
| |
| static const OSSL_ITEM *p_reasons(void *provctx) |
| { |
| return reasons; |
| } |
| |
| static void p_teardown(void *provctx) |
| { |
| free(provctx); |
| } |
| |
| static const OSSL_DISPATCH prov_fns[] = { |
| { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))p_teardown }, |
| { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))p_query }, |
| { OSSL_FUNC_PROVIDER_GET_REASON_STRINGS, (void (*)(void))p_reasons }, |
| { 0, NULL } |
| }; |
| |
| int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, |
| const OSSL_DISPATCH *in, |
| const OSSL_DISPATCH **out, |
| void **provctx) |
| { |
| struct prov_ctx_st *pctx = NULL; |
| |
| for (; in->function_id != 0; in++) |
| switch (in->function_id) { |
| case OSSL_FUNC_CORE_PUT_ERROR: |
| c_put_error = OSSL_FUNC_core_put_error(in); |
| break; |
| } |
| |
| *out = prov_fns; |
| |
| if ((pctx = malloc(sizeof(*pctx))) == NULL) { |
| /* |
| * ALEA IACTA EST, if the core retrieves the reason table |
| * regardless, that string will be displayed, otherwise not. |
| */ |
| c_put_error(handle, E_MALLOC, __FILE__, __LINE__); |
| return 0; |
| } |
| pctx->handle = handle; |
| return 1; |
| } |
| |
| This relies on a few things existing in F<openssl/core_dispatch.h>: |
| |
| #define OSSL_OP_BAR 4711 |
| |
| #define OSSL_FUNC_BAR_NEWCTX 1 |
| typedef void *(OSSL_FUNC_bar_newctx_fn)(void *provctx); |
| static ossl_inline OSSL_FUNC_bar_newctx(const OSSL_DISPATCH *opf) |
| { return (OSSL_FUNC_bar_newctx_fn *)opf->function; } |
| |
| #define OSSL_FUNC_BAR_FREECTX 2 |
| typedef void (OSSL_FUNC_bar_freectx_fn)(void *ctx); |
| static ossl_inline OSSL_FUNC_bar_newctx(const OSSL_DISPATCH *opf) |
| { return (OSSL_FUNC_bar_freectx_fn *)opf->function; } |
| |
| #define OSSL_FUNC_BAR_INIT 3 |
| typedef void *(OSSL_FUNC_bar_init_fn)(void *ctx); |
| static ossl_inline OSSL_FUNC_bar_init(const OSSL_DISPATCH *opf) |
| { return (OSSL_FUNC_bar_init_fn *)opf->function; } |
| |
| #define OSSL_FUNC_BAR_UPDATE 4 |
| typedef void *(OSSL_FUNC_bar_update_fn)(void *ctx, |
| unsigned char *in, size_t inl); |
| static ossl_inline OSSL_FUNC_bar_update(const OSSL_DISPATCH *opf) |
| { return (OSSL_FUNC_bar_update_fn *)opf->function; } |
| |
| #define OSSL_FUNC_BAR_FINAL 5 |
| typedef void *(OSSL_FUNC_bar_final_fn)(void *ctx); |
| static ossl_inline OSSL_FUNC_bar_final(const OSSL_DISPATCH *opf) |
| { return (OSSL_FUNC_bar_final_fn *)opf->function; } |
| |
| =head1 SEE ALSO |
| |
| L<provider(7)> |
| |
| =head1 HISTORY |
| |
| The concept of providers and everything surrounding them was |
| introduced in OpenSSL 3.0. |
| |
| =head1 COPYRIGHT |
| |
| Copyright 2019-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<https://www.openssl.org/source/license.html>. |
| |
| =cut |