mirror of https://github.com/openssl/openssl.git
				
				
				
			
		
			
				
	
	
		
			1027 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			1027 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| =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[]);
 | |
| 
 | |
|  typedef void (*OSSL_thread_stop_handler_fn)(void *arg);
 | |
|  int core_thread_start(const OSSL_CORE_HANDLE *handle,
 | |
|                        OSSL_thread_stop_handler_fn handfn,
 | |
|                        void *arg);
 | |
| 
 | |
|  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);
 | |
| 
 | |
|  int core_obj_add_sigid(const OSSL_CORE_HANDLE *prov, const char  *sign_name,
 | |
|                         const char *digest_name, const char *pkey_name);
 | |
|  int core_obj_create(const OSSL_CORE_HANDLE *handle, const char *oid,
 | |
|                      const char *sn, const char *ln);
 | |
| 
 | |
|  /*
 | |
|   * 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_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);
 | |
| 
 | |
|  unsigned char *OPENSSL_hexstr2buf(const char *str, long *buflen);
 | |
| 
 | |
|  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_up_ref(OSSL_CORE_BIO *bio);
 | |
|  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 OSSL_SELF_TEST_set_callback(OSSL_LIB_CTX *libctx, 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);
 | |
|  size_t get_user_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);
 | |
|  void cleanup_user_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);
 | |
|  size_t get_user_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);
 | |
|  void cleanup_user_nonce(const OSSL_CORE_HANDLE *handle,
 | |
|                          unsigned char *buf, size_t len);
 | |
| 
 | |
|  /* Functions for querying the providers in the application library context */
 | |
|  int provider_register_child_cb(const OSSL_CORE_HANDLE *handle,
 | |
|                      int (*create_cb)(const OSSL_CORE_HANDLE *provider,
 | |
|                                       void *cbdata),
 | |
|                      int (*remove_cb)(const OSSL_CORE_HANDLE *provider,
 | |
|                                       void *cbdata),
 | |
|                      int (*global_props_cb)(const char *props, void *cbdata),
 | |
|                      void *cbdata);
 | |
|  void provider_deregister_child_cb(const OSSL_CORE_HANDLE *handle);
 | |
|  const char *provider_name(const OSSL_CORE_HANDLE *prov);
 | |
|  void *provider_get0_provider_ctx(const OSSL_CORE_HANDLE *prov);
 | |
|  const OSSL_DISPATCH *provider_get0_dispatch(const OSSL_CORE_HANDLE *prov);
 | |
|  int provider_up_ref(const OSSL_CORE_HANDLE *prov, int activate);
 | |
|  int provider_free(const OSSL_CORE_HANDLE *prov, int deactivate);
 | |
| 
 | |
|  /* 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);
 | |
|  void provider_unquery_operation(void *provctx, int operation_id,
 | |
|                                  const OSSL_ALGORITHM *algs);
 | |
|  const OSSL_ITEM *provider_get_reason_strings(void *provctx);
 | |
|  int provider_get_capabilities(void *provctx, const char *capability,
 | |
|                                OSSL_CALLBACK *cb, void *arg);
 | |
|  int provider_self_test(void *provctx);
 | |
| 
 | |
| =head1 DESCRIPTION
 | |
| 
 | |
| All "functions" mentioned here are passed as function pointers between
 | |
| F<libcrypto> and the provider in L<OSSL_DISPATCH(3)> arrays, in the call
 | |
| of the provider initialization function.  See L<provider(7)/Provider>
 | |
| for a description of the initialization function. They are known as "upcalls".
 | |
| 
 | |
| All these "functions" have a corresponding function type definition
 | |
| named B<OSSL_FUNC_{name}_fn>, and a helper function to retrieve the
 | |
| function pointer from a L<OSSL_DISPATCH(3)> 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);
 | |
| 
 | |
| L<OSSL_DISPATCH(3)> arrays are indexed by numbers that are provided as
 | |
| macros in L<openssl-core_dispatch.h(7)>, as follows:
 | |
| 
 | |
| For I<in> (the L<OSSL_DISPATCH(3)> 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_vset_error                OSSL_FUNC_CORE_VSET_ERROR
 | |
|  core_set_error_mark            OSSL_FUNC_CORE_SET_ERROR_MARK
 | |
|  core_clear_last_error_mark     OSSL_FUNC_CORE_CLEAR_LAST_ERROR_MARK
 | |
|  core_pop_error_to_mark         OSSL_FUNC_CORE_POP_ERROR_TO_MARK
 | |
|  core_count_to_mark             OSSL_FUNC_CORE_COUNT_TO_MARK
 | |
|  core_obj_add_sigid             OSSL_FUNC_CORE_OBJ_ADD_SIGID
 | |
|  core_obj_create                OSSL_FUNC_CORE_OBJ_CREATE
 | |
|  CRYPTO_malloc                  OSSL_FUNC_CRYPTO_MALLOC
 | |
|  CRYPTO_zalloc                  OSSL_FUNC_CRYPTO_ZALLOC
 | |
|  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_write_ex                   OSSL_FUNC_BIO_WRITE_EX
 | |
|  BIO_up_ref                     OSSL_FUNC_BIO_UP_REF
 | |
|  BIO_free                       OSSL_FUNC_BIO_FREE
 | |
|  BIO_vprintf                    OSSL_FUNC_BIO_VPRINTF
 | |
|  BIO_vsnprintf                  OSSL_FUNC_BIO_VSNPRINTF
 | |
|  BIO_puts                       OSSL_FUNC_BIO_PUTS
 | |
|  BIO_gets                       OSSL_FUNC_BIO_GETS
 | |
|  BIO_ctrl                       OSSL_FUNC_BIO_CTRL
 | |
|  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_get_user_entropy     OSSL_FUNC_GET_USER_ENTROPY
 | |
|  ossl_rand_cleanup_entropy      OSSL_FUNC_CLEANUP_ENTROPY
 | |
|  ossl_rand_cleanup_user_entropy OSSL_FUNC_CLEANUP_USER_ENTROPY
 | |
|  ossl_rand_get_nonce            OSSL_FUNC_GET_NONCE
 | |
|  ossl_rand_get_user_nonce       OSSL_FUNC_GET_USER_NONCE
 | |
|  ossl_rand_cleanup_nonce        OSSL_FUNC_CLEANUP_NONCE
 | |
|  ossl_rand_cleanup_user_nonce   OSSL_FUNC_CLEANUP_USER_NONCE
 | |
|  provider_register_child_cb     OSSL_FUNC_PROVIDER_REGISTER_CHILD_CB
 | |
|  provider_deregister_child_cb   OSSL_FUNC_PROVIDER_DEREGISTER_CHILD_CB
 | |
|  provider_name                  OSSL_FUNC_PROVIDER_NAME
 | |
|  provider_get0_provider_ctx     OSSL_FUNC_PROVIDER_GET0_PROVIDER_CTX
 | |
|  provider_get0_dispatch         OSSL_FUNC_PROVIDER_GET0_DISPATCH
 | |
|  provider_up_ref                OSSL_FUNC_PROVIDER_UP_REF
 | |
|  provider_free                  OSSL_FUNC_PROVIDER_FREE
 | |
| 
 | |
| For I<*out> (the L<OSSL_DISPATCH(3)> 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_unquery_operation     OSSL_FUNC_PROVIDER_UNQUERY_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
 | |
| L<OSSL_PARAM(3)>, 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.
 | |
| 
 | |
| The core_thread_start() function informs the core that the provider has stated
 | |
| an interest in the current thread. The core will inform the provider when the
 | |
| thread eventually stops. It must be passed the I<handle> for this provider, as
 | |
| well as a callback I<handfn> which will be called when the thread stops. The
 | |
| callback will subsequently be called, with the supplied argument I<arg>, from
 | |
| the thread that is stopping and gets passed the provider context as an
 | |
| argument. This may be useful to perform thread specific clean up such as
 | |
| freeing thread local variables.
 | |
| 
 | |
| core_get_libctx() retrieves the core context in which the library
 | |
| object for the current provider is stored, accessible through the I<handle>.
 | |
| This function is useful only for built-in providers such as the default
 | |
| provider. Never cast this to OSSL_LIB_CTX in a provider that is not
 | |
| built-in as the OSSL_LIB_CTX of the library loading the provider might be
 | |
| a completely different structure than the OSSL_LIB_CTX of the library the
 | |
| provider is linked to. Use  L<OSSL_LIB_CTX_new_child(3)> instead to obtain
 | |
| a proper library context that is linked to the application library context.
 | |
| 
 | |
| core_new_error(), core_set_error_debug() and core_vset_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_vset_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)>.
 | |
| 
 | |
| =item core_set_error_mark()
 | |
| 
 | |
| sets a mark on the current topmost error record if there is one.
 | |
| 
 | |
| This corresponds to the OpenSSL function L<ERR_set_mark(3)>.
 | |
| 
 | |
| =item core_clear_last_error_mark()
 | |
| 
 | |
| removes the last mark added if there is one.
 | |
| 
 | |
| This corresponds to the OpenSSL function L<ERR_clear_last_mark(3)>.
 | |
| 
 | |
| =item core_pop_error_to_mark()
 | |
| 
 | |
| pops the top of the error stack until a mark is found. The mark is then removed.
 | |
| If there is no mark, the whole stack is removed.
 | |
| 
 | |
| This corresponds to the OpenSSL function L<ERR_pop_to_mark(3)>.
 | |
| 
 | |
| =item core_count_to_mark()
 | |
| 
 | |
| returns the number of entries on the error stack above the most recently
 | |
| marked entry, not including that entry. If there is no mark in the error stack,
 | |
| the number of entries in the error stack is returned.
 | |
| 
 | |
| This corresponds to the OpenSSL function L<ERR_count_to_mark(3)>.
 | |
| 
 | |
| =back
 | |
| 
 | |
| The core_obj_create() function registers a new OID and associated short name
 | |
| I<sn> and long name I<ln> for the given I<handle>. It is similar to the OpenSSL
 | |
| function L<OBJ_create(3)> except that it returns 1 on success or 0 on failure.
 | |
| It will treat as success the case where the OID already exists (even if the
 | |
| short name I<sn> or long name I<ln> provided as arguments differ from those
 | |
| associated with the existing OID, in which case the new names are not
 | |
| associated).
 | |
| 
 | |
| The core_obj_add_sigid() function registers a new composite signature algorithm
 | |
| (I<sign_name>) consisting of an underlying signature algorithm (I<pkey_name>)
 | |
| and digest algorithm (I<digest_name>) for the given I<handle>. It assumes that
 | |
| the OIDs for the composite signature algorithm as well as for the underlying
 | |
| signature and digest algorithms are either already known to OpenSSL or have been
 | |
| registered via a call to core_obj_create(). It corresponds to the OpenSSL
 | |
| function L<OBJ_add_sigid(3)>, except that the objects are identified by name
 | |
| rather than a numeric NID. Any name (OID, short name or long name) can be used
 | |
| to identify the object. It will treat as success the case where the composite
 | |
| signature algorithm already exists (even if registered against a different
 | |
| underlying signature or digest algorithm). For I<digest_name>, NULL or an
 | |
| empty string is permissible for signature algorithms that do not need a digest
 | |
| to operate correctly. The function returns 1 on success or 0 on failure.
 | |
| 
 | |
| CRYPTO_malloc(), CRYPTO_zalloc(), 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_write_ex(), BIO_up_ref(),
 | |
| BIO_free(), BIO_vprintf(), BIO_vsnprintf(), BIO_gets(), BIO_puts(),
 | |
| BIO_ctrl(), OPENSSL_cleanse() and
 | |
| OPENSSL_hexstr2buf() correspond exactly to the public functions with
 | |
| the same name.  As a matter of fact, the pointers in the L<OSSL_DISPATCH(3)>
 | |
| array are typically 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.
 | |
| 
 | |
| get_user_entropy() is the same as get_entropy() except that it will
 | |
| attempt to gather seed material via the seed source specified by a call to
 | |
| L<RAND_set_seed_source_type(3)> or via L<config(5)/Random Configuration>.
 | |
| 
 | |
| 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>.
 | |
| 
 | |
| cleanup_user_entropy() is used to clean up and free the buffer returned by
 | |
| get_user_entropy().  The entropy pointer returned by get_user_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 contains 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.
 | |
| 
 | |
| get_user_nonce() is the same as get_nonce() except that it will attempt
 | |
| to gather seed material via the seed source specified by a call to
 | |
| L<RAND_set_seed_source_type(3)> or via L<config(5)/Random Configuration>.
 | |
| 
 | |
| 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>.
 | |
| 
 | |
| cleanup_user_nonce() is used to clean up and free the buffer returned by
 | |
| get_user_nonce().  The nonce pointer returned by get_user_nonce()
 | |
| is passed in B<buf> and its length in B<len>.
 | |
| 
 | |
| provider_register_child_cb() registers callbacks for being informed about the
 | |
| loading and unloading of providers in the application's library context.
 | |
| I<handle> is this provider's handle and I<cbdata> is this provider's data
 | |
| that will be passed back to the callbacks. It returns 1 on success or 0
 | |
| otherwise. These callbacks may be called while holding locks in libcrypto. In
 | |
| order to avoid deadlocks the callback implementation must not be long running
 | |
| and must not call other OpenSSL API functions or upcalls.
 | |
| 
 | |
| I<create_cb> is a callback that will be called when a new provider is loaded
 | |
| into the application's library context. It is also called for any providers that
 | |
| are already loaded at the point that this callback is registered. The callback
 | |
| is passed the handle being used for the new provider being loadded and this
 | |
| provider's data in I<cbdata>. It should return 1 on success or 0 on failure.
 | |
| 
 | |
| I<remove_cb> is a callback that will be called when a new provider is unloaded
 | |
| from the application's library context. It is passed the handle being used for
 | |
| the provider being unloaded and this provider's data in I<cbdata>. It should
 | |
| return 1 on success or 0 on failure.
 | |
| 
 | |
| I<global_props_cb> is a callback that will be called when the global properties
 | |
| from the parent library context are changed. It should return 1 on success
 | |
| or 0 on failure.
 | |
| 
 | |
| provider_deregister_child_cb() unregisters callbacks previously registered via
 | |
| provider_register_child_cb(). If provider_register_child_cb() has been called
 | |
| then provider_deregister_child_cb() should be called at or before the point that
 | |
| this provider's teardown function is called.
 | |
| 
 | |
| provider_name() returns a string giving the name of the provider identified by
 | |
| I<handle>.
 | |
| 
 | |
| provider_get0_provider_ctx() returns the provider context that is associated
 | |
| with the provider identified by I<prov>.
 | |
| 
 | |
| provider_get0_dispatch() gets the dispatch table registered by the provider
 | |
| identified by I<prov> when it initialised.
 | |
| 
 | |
| provider_up_ref() increments the reference count on the provider I<prov>. If
 | |
| I<activate> is nonzero then the provider is also loaded if it is not already
 | |
| loaded. It returns 1 on success or 0 on failure.
 | |
| 
 | |
| provider_free() decrements the reference count on the provider I<prov>. If
 | |
| I<deactivate> is nonzero then the provider is also unloaded if it is not
 | |
| already loaded. It returns 1 on success or 0 on failure.
 | |
| 
 | |
| =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 L<OSSL_PARAM(3)>, for parameters that provider_get_params()
 | |
| can handle.
 | |
| 
 | |
| provider_get_params() should process the L<OSSL_PARAM(3)> array
 | |
| I<params>, setting the values of the parameters it understands.
 | |
| 
 | |
| provider_query_operation() should return a constant L<OSSL_ALGORITHM(3)>
 | |
| 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_unquery_operation() informs the provider that the result of a
 | |
| provider_query_operation() is no longer directly required and that the function
 | |
| pointers have been copied.  The I<operation_id> should match that passed to
 | |
| provider_query_operation() and I<algs> should be its return value.
 | |
| 
 | |
| provider_get_reason_strings() should return a constant L<OSSL_ITEM(3)>
 | |
| 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 L<OSSL_PARAM(3)>s and the caller supplied argument I<arg>. The
 | |
| L<OSSL_PARAM(3)>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>) <signed 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 string 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 string 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 string 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:
 | |
| 
 | |
|  config_diagnostics = 1
 | |
|  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.
 | |
| 
 | |
| It is possible to register the same group id from within different
 | |
| providers. Users should note that if no property query is specified, or
 | |
| more than one implementation matches the property query then it is
 | |
| unspecified which implementation for a particular group id will be used.
 | |
| 
 | |
| =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
 | |
| 
 | |
| =head3 "TLS-SIGALG" Capability
 | |
| 
 | |
| The "TLS-SIGALG" capability can be queried by libssl to discover the list of
 | |
| TLS signature algorithms that a provider can support. Each signature supported
 | |
| can be used for client- or server-authentication in addition to the built-in
 | |
| signature algorithms.
 | |
| TLS1.3 clients can advertise the list of TLS signature algorithms they support
 | |
| in the signature_algorithms extension, and TLS servers can select an algorithm
 | |
| from the offered list that they also support. In this way a provider can add
 | |
| to the list of signature algorithms that libssl already supports with
 | |
| additional ones.
 | |
| 
 | |
| Each TLS signature algorithm that a provider supports should be described via
 | |
| the callback passed in through the provider_get_capabilities function. Each
 | |
| algorithm can have the following details supplied:
 | |
| 
 | |
| =over 4
 | |
| 
 | |
| =item "iana-name" (B<OSSL_CAPABILITY_TLS_SIGALG_IANA_NAME>) <UTF8 string>
 | |
| 
 | |
| The name of the signature algorithm as given in the IANA TLS Signature Scheme
 | |
| registry as "Description":
 | |
| L<https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-signaturescheme>.
 | |
| This value must be supplied.
 | |
| 
 | |
| =item "iana-code-point" (B<OSSL_CAPABILITY_TLS_SIGALG_CODE_POINT>) <unsigned integer>
 | |
| 
 | |
| The TLS algorithm ID value as given in the IANA TLS SignatureScheme registry.
 | |
| This value must be supplied.
 | |
| 
 | |
| It is possible to register the same code point from within different
 | |
| providers. Users should note that if no property query is specified, or
 | |
| more than one implementation matches the property query then it is
 | |
| unspecified which implementation for a particular code point will be used.
 | |
| 
 | |
| =item "sigalg-name" (B<OSSL_CAPABILITY_TLS_SIGALG_NAME>) <UTF8 string>
 | |
| 
 | |
| A name for the full (possibly composite hash-and-signature) signature
 | |
| algorithm.
 | |
| The provider may, but is not obligated to, provide a signature implementation
 | |
| with this name; if it doesn't, this is assumed to be a composite of a pure
 | |
| signature algorithm and a hash algorithm, which must be given with the
 | |
| parameters "sig-name" and "hash-name".
 | |
| This value must be supplied.
 | |
| 
 | |
| =item "sigalg-oid" (B<OSSL_CAPABILITY_TLS_SIGALG_OID>) <UTF8 string>
 | |
| 
 | |
| The OID of the "sigalg-name" algorithm in canonical numeric text form. If
 | |
| this parameter is given, OBJ_create() will be used to create an OBJ and
 | |
| a NID for this OID, using the "sigalg-name" parameter for its (short) name.
 | |
| Otherwise, it's assumed to already exist in the object database, possibly
 | |
| done by the provider with the core_obj_create() upcall.
 | |
| This value is optional.
 | |
| 
 | |
| =item "sig-name" (B<OSSL_CAPABILITY_TLS_SIGALG_SIG_NAME>) <UTF8 string>
 | |
| 
 | |
| The name of the pure signature algorithm that is part of a composite
 | |
| "sigalg-name". If "sigalg-name" is implemented by the provider, this
 | |
| parameter is redundant and must not be given.
 | |
| This value is optional.
 | |
| 
 | |
| =item "sig-oid" (B<OSSL_CAPABILITY_TLS_SIGALG_SIG_OID>) <UTF8 string>
 | |
| 
 | |
| The OID of the "sig-name" algorithm in canonical numeric text form. If
 | |
| this parameter is given, OBJ_create() will be used to create an OBJ and
 | |
| a NID for this OID, using the "sig-name" parameter for its (short) name.
 | |
| Otherwise, it is assumed to already exist in the object database. This
 | |
| can be done by the provider using the core_obj_create() upcall.
 | |
| This value is optional.
 | |
| 
 | |
| =item "hash-name" (B<OSSL_CAPABILITY_TLS_SIGALG_HASH_NAME>) <UTF8 string>
 | |
| 
 | |
| The name of the hash algorithm that is part of a composite "sigalg-name".
 | |
| If "sigalg-name" is implemented by the provider, this parameter is redundant
 | |
| and must not be given.
 | |
| This value is optional.
 | |
| 
 | |
| =item "hash-oid" (B<OSSL_CAPABILITY_TLS_SIGALG_HASH_OID>) <UTF8 string>
 | |
| 
 | |
| The OID of the "hash-name" algorithm in canonical numeric text form. If
 | |
| this parameter is given, OBJ_create() will be used to create an OBJ and
 | |
| a NID for this OID, using the "hash-name" parameter for its (short) name.
 | |
| Otherwise, it's assumed to already exist in the object database, possibly
 | |
| done by the provider with the core_obj_create() upcall.
 | |
| This value is optional.
 | |
| 
 | |
| =item "key-type" (B<OSSL_CAPABILITY_TLS_SIGALG_KEYTYPE>) <UTF8 string>
 | |
| 
 | |
| The key type of the public key of applicable certificates. If this parameter
 | |
| isn't present, it's assumed to be the same as "sig-name" if that's present,
 | |
| otherwise "sigalg-name".
 | |
| This value is optional.
 | |
| 
 | |
| =item "key-type-oid" (B<OSSL_CAPABILITY_TLS_SIGALG_KEYTYPE_OID>) <UTF8 string>
 | |
| 
 | |
| The OID of the "key-type" in canonical numeric text form. If
 | |
| this parameter is given, OBJ_create() will be used to create an OBJ and
 | |
| a NID for this OID, using the "key-type" parameter for its (short) name.
 | |
| Otherwise, it's assumed to already exist in the object database, possibly
 | |
| done by the provider with the core_obj_create() upcall.
 | |
| This value is optional.
 | |
| 
 | |
| =item "sec-bits" (B<OSSL_CAPABILITY_TLS_SIGALG_SECURITY_BITS>) <unsigned integer>
 | |
| 
 | |
| The number of bits of security offered by keys of this algorithm. The number
 | |
| of bits should be comparable with the ones given in table 2 and 3 of the NIST
 | |
| SP800-57 document. This number is used to determine the security strength of
 | |
| the algorithm if no digest algorithm has been registered that otherwise
 | |
| defines the security strength. If the signature algorithm implements its own
 | |
| digest internally, this value needs to be set to properly reflect the overall
 | |
| security strength.
 | |
| This value must be supplied.
 | |
| 
 | |
| =item "tls-min-tls" (B<OSSL_CAPABILITY_TLS_SIGALG_MIN_TLS>) <integer>
 | |
| 
 | |
| =item "tls-max-tls" (B<OSSL_CAPABILITY_TLS_SIGALG_MAX_TLS>) <integer>
 | |
| 
 | |
| =item "tls-min-dtls" (B<OSSL_CAPABILITY_TLS_SIGALG_MIN_DTLS>) <integer>
 | |
| 
 | |
| =item "tls-max-dtls" (B<OSSL_CAPABILITY_TLS_SIGALG_MAX_DTLS>) <integer>
 | |
| 
 | |
| These parameters can be used to describe the minimum and maximum TLS and DTLS
 | |
| versions supported by the signature algorithm. 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 in either the min or max field
 | |
| indicates that the signature algorithm should not be used in that protocol.
 | |
| Presently, provider signature algorithms are used only with TLS 1.3, if
 | |
| that's enclosed in the specified range.
 | |
| 
 | |
| =back
 | |
| 
 | |
| =head1 NOTES
 | |
| 
 | |
| The core_obj_create() and core_obj_add_sigid() functions were not thread safe
 | |
| in OpenSSL 3.0.
 | |
| 
 | |
| =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" }.
 | |
|      OSSL_DISPATCH_END
 | |
|  };
 | |
| 
 | |
|  /*
 | |
|   * 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 },
 | |
|      OSSL_DISPATCH_END
 | |
|  };
 | |
| 
 | |
|  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 },
 | |
|      OSSL_DISPATCH_END
 | |
|  };
 | |
| 
 | |
|  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_freectx(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.
 | |
| 
 | |
| Definitions for
 | |
| B<OSSL_CAPABILITY_TLS_SIGALG_MIN_DTLS>
 | |
| and
 | |
| B<OSSL_CAPABILITY_TLS_SIGALG_MAX_DTLS>
 | |
| were added in OpenSSL 3.5.
 | |
| 
 | |
| =head1 COPYRIGHT
 | |
| 
 | |
| Copyright 2019-2025 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
 |