文章目录
🍺概要
#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_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);
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);
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 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);
🍻描述
这里提到的所有“函数”都在调用提供程序初始化函数时,作为函数指针在libcrypto和OSSL_DISPATCH数组中的提供程序之间传递。它们被称为"向上调用"。
所有这些“函数”都有一个对应的名为OSSL_FUNC_{name}_fn的函数类型定义,以及一个帮助函数,用于从一个名为OSSL_FUNC_{name} 的 OSSL_DISPATCH元素中检索函数指针。例如,"函数"core_gettable_params() 具有以下功能:
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);
OSSL_DISPATCH数组由openssl-core_dispatch.h作为宏提供的数字索引,如下所示:
对于in(从libcrypto传递到提供程序的OSSL_DISPATCH数组):
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_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_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_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_cleanup_entropy OSSL_FUNC_CLEANUP_ENTROPY
ossl_rand_get_nonce OSSL_FUNC_GET_NONCE
ossl_rand_cleanup_nonce OSSL_FUNC_CLEANUP_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
对于*out(从提供程序传递到libcrypto的OSSL_DISPATCH数组):
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
🍷内核参数
-
core_gettable_params() 返回一个描述符OSSL_PARAM的常量数组,用于core_get_params() 可以处理的参数。
-
core_get_params() 从给定句柄的内核检索参数。有关当前已知参数的说明,请参阅下面的内核参数。
-
core_thread_start() 函数通知内核,提供程序已声明对当前线程感兴趣。当线程最终停止时,内核将通知提供程序。它必须传递给此提供程序的句柄,以及一个回调handfn,该调用将在线程停止时调用。随后将调用回调,并提供参数arg,从正在停止的线程中调用,并将该线程作为参数传递给提供程序上下文。这对于执行特定于线程的清理(如释放线程局部变量)可能很有用。
-
core_get_libctx() 检索存储当前提供程序的库对象的库上下文,可通过句柄访问。如果提供程序希望在同一库上下文中存储对其上下文的引用,这有时可能很有用。
-
core_new_error()、core_set_error_debug() 和 core_vset_error() 是参考句柄向核心报告错误的构建块。
-
core_new_error()
分配新的特定于线程的错误记录。
这对应于 OpenSSL 函数ERR_new。 -
core_set_error_debug()
在当前线程特定的错误记录中设置调试信息。调试信息包括文件文件的名称、行和发生错误的函数名称func。
这对应于 OpenSSL 函数ERR_set_debug。 -
core_vset_error()
设置错误的原因以及任何添加的数据。原因是提供程序定义的数字,用于索引 provider_get_reason_strings() 返回的原因字符串表。附加数据被给出为一个格式字符串fmt和一组参数args,它们的处理方式与BIO_vsnprintf()相同。文件和行也可以传递以准确指示错误发生或报告的位置。
这对应于 OpenSSL 函数ERR_vset_error。 -
core_obj_create() 函数为给定句柄注册一个新的 OID 和关联的短名称sn和长名称ln。它类似于 openSSL 函数OBJ_create,不同之处在于它在成功时返回 1,在失败时返回 0。如果 OID 已存在,它将被视为成功(即使作为参数提供的短名称sn或长名称ln与与现有 OID 关联的参数不同,在这种情况下,新名称不会关联)。此函数不是线程安全的。
-
core_obj_add_sigid() 函数注册一个新的复合签名算法(sign_name),该算法由给定句柄的基础签名算法(pkey_name)和摘要算法(digest_name)组成。它假设复合签名算法以及基础签名和摘要算法的 OID 要么已被 OpenSSL 知道,要么已通过调用 core_obj_create() 进行注册。它对应于 OpenSSL 函数OBJ_add_sigid,只不过这些对象是用名称而不是数字 NID 来标识的。任何名称(OID、短名称或长名称)都可用于标识对象。如果复合签名算法已存在(即使针对不同的基础签名或摘要算法进行了注册),它将被视为成功。成功时返回 1,失败时返回 0。此函数不是线程安全的。
-
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_write_ex(), BIO_up_ref(), BIO_free(), BIO_vprintf(), BIO_vsnprintf()、BIO_gets()、BIO_puts()、BIO_ctrl()、OPENSSL_cleanse() 和OPENSSL_hexstr2buf()正好对应于同名的公共函数。事实上,OSSL_DISPATCH数组中的指针通常是指向这些公共函数的直接指针。请注意,BIO 函数采用OSSL_CORE_BIO类型,而不是标准BIO类型。这是为了确保提供程序不会将内核中的 BIO 与提供商端使用的 BIO 混合在一起(两者不兼容)。OSSL_SELF_TEST_set_callback() 用于设置可传递到提供程序的可选回调。这可能会被提供程序忽略。
-
get_entropy() 从操作系统中检索种子设定材料。种子设定材料将至少具有随机性的熵字节,输出将至少具有min_len,最多max_len字节。缓冲区地址存储在*pout中,缓冲区长度将返回给调用方。出错时,返回零。
-
cleanup_entropy() 用于清理和释放 get_entropy() 返回的缓冲区。get_entropy() 返回的函数指针以buf为单位传递,其长度以len 为单位传递。
-
get_nonce() 使用传递的长度salt_len和操作系统特定信息的salt参数检索随机数。salt应包含唯一标识信息,并以未指定的方式将其作为输出的一部分包括在内。输出存储在至少min_len且最多max_len字节的缓冲区中。缓冲区地址存储在*pout中,缓冲区长度返回给调用方。出错时,返回零。
-
cleanup_nonce() 用于清理和释放 get_nonce() 返回的缓冲区。get_nonce() 返回的随机数指针以buf为单位传递,其长度以len 为单位传递。
-
provider_register_child_cb() 注册回调,以便在应用程序的库上下文中获取有关提供程序的加载和卸载的通知。句柄是此提供程序的句柄,cbdata是此提供程序的数据,将传递回调。成功时返回 1,否则返回 0。这些回调可以在libcrypto中持有锁时调用。为了避免死锁,回调实现的运行时间不得过长,并且不得调用其他 OpenSSL API 函数或向上调用。
-
create_cb是一个回调,当将新提供程序加载到应用程序的库上下文中时,将调用该回调。对于在注册此回调时已加载的任何提供程序,也会调用它。回调传递用于正在加载的新提供程序的句柄以及cbdata中此提供程序的数据。成功时应返回 1,失败时应返回 0。
-
remove_cb是从应用程序的库上下文中卸载新提供程序时调用的回调。它被传递给用于卸载的提供程序的句柄以及cbdata中该提供程序的数据。成功时应返回 1,失败时应返回 0。
-
global_props_cb是一个回调,当父库上下文中的全局属性发生更改时,将调用该回调。成功时应返回 1,失败时应返回 0。
-
provider_deregister_child_cb() 取消注册以前通过 provider_register_child_cb() 注册的回调。如果已调用 provider_register_child_cb(),则应在调用此提供程序的拆解函数时或之前调用 provider_deregister_child_cb()。
-
provider_name() 返回一个字符串,该字符串提供由句柄标识的提供程序的名称。
-
provider_get0_provider_ctx() 返回与prov标识的提供程序关联的提供程序上下文。
-
provider_get0_dispatch() 获取由prov在初始化时标识的提供程序注册的调度表。
-
provider_up_ref() 递增提供程序prov上的引用计数。如果激活不为零,则如果提供程序尚未加载,则也会加载提供程序。成功时返回 1,失败时返回 0。
-
provider_free() 递减了提供程序prov上的引用计数。如果停用为非零,则如果提供程序尚未加载,则也会卸载提供程序。成功时返回 1,失败时返回 0。
🍸提供程序函数
-
provider_teardown() 在关闭提供程序并从核心的提供程序存储中删除时调用。它必须释放传递的provctx。
-
provider_gettable_params() 应该返回一个描述符OSSL_PARAM的常量数组,用于provider_get_params() 可以处理的参数。
-
provider_get_params() 应该处理OSSL_PARAM数组参数,设置它理解的参数的值。
-
provider_query_operation() 应返回与给定operation_id相对应的常量OSSL_ALGORITHM。它应该通过将*no_store设置为 0(核心可能存储引用)或 1(核心可能不存储引用)来指示内核是否可以存储对此数组的引用。
-
provider_unquery_operation() 通知提供程序不再直接需要provider_query_operation() 的结果,并且已复制函数指针。传递给 provider_query_operation()的operation_id应匹配,并且algs应为其返回值。
-
provider_get_reason_strings() 应返回一个常量OSSL_ITEM数组,该数组为提供程序在使用 core_put_error() 报告错误时可能使用的原因代码提供原因字符串。
-
provider_get_capabilities() 函数应调用回调cb,向其传递一组OSSL_PARAMs 和调用方提供的参数arg。OSSL_PARAM应提供有关功能的详细信息,并在与提供程序上下文provctx相关的功能参数中给出的名称。如果提供程序支持具有给定名称的多个功能,则它可能会多次调用回调(每个功能一个)。功能可用于描述提供程序可以提供的服务。有关更多详细信息,请参阅下面的功能部分。成功时应返回 1,出错时应返回 0。
-
provider_self_test() 函数应对它使用的算法子集执行已知的答案测试,还可以验证提供程序模块的完整性。成功时应返回 1,出错时应返回 0。如果未使用此函数,它将返回 1。
🍹内核参数
core_get_params() 可以检索每个提供程序的以下内核参数:
-
“openssl-version” (OSSL_PROV_PARAM_CORE_VERSION) < UTF8 string ptr >
这指向OpenSSL库的完整版本字符串,即从宏扩展OPENSSL_VERSION_STR的字符串。 -
“provider-name” (OSSL_PROV_PARAM_CORE_PROV_NAME) < UTF8 string ptr >
这指向了OpenSSL库对调用提供程序的名称的想法。 -
“module-filename” (OSSL_PROV_PARAM_CORE_MODULE_FILENAME) < UTF8 string ptr >
这指向包含提供程序模块文件的完整文件名的字符串。
此外,还可以从配置文件中获得提供程序特定的配置参数,以点命名的形式。带点的名称形式是部分名称和由句号分隔的最终配置命令名称的连接。
例如,假设我们有以下配置示例:
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
提供程序将具有以下可用附加参数:
-
“activate”
指向字符串"1" -
“data1”
指向字符串"2" -
“data2”
指向字符串"str" -
“more.data3”
指向字符串"foo,bar"
☕️提供程序参数
provider_get_params() 可以将以下提供程序参数返回到内核:
-
“name” (OSSL_PROV_PARAM_NAME) < UTF8 string ptr >
这指向一个字符串,该字符串应为提供程序提供唯一的名称。 -
“version” (OSSL_PROV_PARAM_VERSION) < UTF8 string ptr >
这指向一个字符串,该字符串是与此提供程序关联的版本号。OpenSSL内置提供商使用OPENSSL_VERSION_STR,但对于任何第三方提供商来说,这可能有所不同。此字符串仅供参考。 -
“buildinfo” (OSSL_PROV_PARAM_BUILDINFO)< UTF8 string ptr >
这指向一个字符串,该字符串是与此提供程序关联的生成信息。OpenSSL 内置提供程序使用OPENSSL_FULL_VERSION_STR,但对于任何第三方提供程序,这可能有所不同。 -
“status” (OSSL_PROV_PARAM_STATUS) < unsigned int >
如果提供程序已进入错误状态,则返回 0,否则返回 1。
provider_gettable_params() 应返回上述参数。
🍾功能
功能描述了提供程序可以提供的一些服务。应用程序可以查询功能以发现这些服务。
🍵"TLS-GROUP"功能
libssl 可以查询"TLS-GROUP"功能,以发现提供商可以支持的 TLS 组列表。在 TLS 握手期间,支持的每个组都可用于密钥交换(KEX) 或密钥封装方法(KEM)。TLS 客户端可以在supported_groups扩展中公布它们支持的 TLS 组的列表,并且 TLS 服务器可以从提供的列表中选择它们也支持的组。通过这种方式,提供程序可以将 libssl 已经支持的组添加到其他组的列表中。
提供程序支持的每个 TLS 组都应通过通过 provider_get_capabilities 函数传入的回调进行描述。每个组应提供以下详细信息(除OSSL_CAPABILITY_TLS_GROUP_IS_KEM外,所有组都是强制性的):
-
“tls-group-name” (OSSL_CAPABILITY_TLS_GROUP_NAME) < UTF8 string >
IANA TLS 支持的组注册表中给出的组名称 -
“tls-group-name-internal” (OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL) < UTF8 string >
提供程序已知的组的名称。这可以与"tls-group-name"相同,但不一定是。 -
“tls-group-id” (OSSL_CAPABILITY_TLS_GROUP_ID) < unsigned integer >
IANA TLS 支持的组注册表中给出的 TLS 组 ID 值。 -
“tls-group-alg” (OSSL_CAPABILITY_TLS_GROUP_ALG) < UTF8 string >
提供程序提供的密钥管理算法的名称,该算法应与此组一起使用。创建的密钥应能够支持密钥交换或密钥封装方法(KEM),如可选OSSL_CAPABILITY_TLS_GROUP_IS_KEM标志所示。该算法必须支持键和参数生成以及键/参数生成参数,OSSL_PKEY_PARAM_GROUP_NAME。当libssl希望生成键/参数时,通过上面的"tls-group-name-internal"给出的组名将通过OSSL_PKEY_PARAM_GROUP_NAME传递。 -
“tls-group-sec-bits” (OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS) < unsigned integer >
此组中的密钥提供的安全位数。位数应与 NIST SP800-57 文档表 2 和表 3 中给出的位数相当。 -
“tls-group-is-kem” (OSSL_CAPABILITY_TLS_GROUP_IS_KEM) < unsigned integer >
布尔标志,用于描述是否应在密钥交换(KEX) 模式(0,默认值)或密钥封装方法(KEM) 模式 (1) 中使用组。
此参数是可选的:如果未指定,则假定 KEX 模式为组的默认模式。
在 KEX 模式下,以典型的 Diffie-Hellman 方式,双方执行keygen,然后针对对等公钥派生。要在 KEX 模式下运行,组实现必须支持提供程序-keyexch中所述的提供程序函数。
在 KEM 模式下,客户端执行keygen并发送其公钥,服务器使用客户端的公钥执行封装并发回生成的密文,最后客户端执行解封装以检索服务器的封装生成的相同共享密钥。要在 KEM 模式下运行,组实现必须支持提供程序函数,如提供程序-kem中所述。
在 KEX 和 KEM 模式下,然后根据协议规范使用生成的共享密钥。 -
“tls-min-tls” (OSSL_CAPABILITY_TLS_GROUP_MIN_TLS) < integer >
“tls-max-tls” (OSSL_CAPABILITY_TLS_GROUP_MAX_TLS) < integer >
“tls-min-dtls” (OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS) < integer >
“tls-max-dtls” (OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS) < integer >
这些参数可用于描述组支持的最小和最大 TLS 和 DTLS 版本。这些值等同于各种 TLS 版本的在线编码。例如,TLSv1.3 是0x0304(772 位十进制),TLSv1.2 是0x0303(771 位十进制)。0 表示没有定义的最小值或最大值。-1 表示不应在该协议中使用该组。
🍶举例
这是一个简单的提供程序示例,它可以作为一个动态加载模块使用。它实现了虚拟操作的虚拟算法。
#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;
}
这取决于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; }