provider-base
名称
provider-base - OpenSSL 库 <-> 提供程序函数的基本功能
概要
#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);
描述
此处提到的所有“函数”都作为函数指针在libcrypto和OSSL_DISPATCH(3)数组中的提供程序之间传递,在提供程序初始化函数的调用中。有关初始化函数的说明,请参阅provider(7)中的“提供程序”。它们被称为“上行调用”。
所有这些“函数”都有一个对应的函数类型定义,名为OSSL_FUNC_{name}_fn,以及一个从名为OSSL_FUNC_{name}的OSSL_DISPATCH(3)元素中检索函数指针的辅助函数。例如,“函数”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(3)数组由数字索引,这些数字作为宏在openssl-core_dispatch.h(7)中提供,如下所示
对于in(从libcrypto传递到提供程序的OSSL_DISPATCH(3)数组)
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_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
对于*out(从提供程序传递到libcrypto的OSSL_DISPATCH(3)数组)
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(3)的常量数组,用于core_get_params()可以处理的参数。
core_get_params()从核心为给定的handle检索参数。有关当前已知参数的说明,请参阅下面的“核心参数”。
core_thread_start()函数通知核心,提供程序已表示对当前线程感兴趣。核心将在线程最终停止时通知提供程序。它必须传递此提供程序的handle,以及一个回调handfn,该回调将在线程停止时被调用。随后将使用提供的参数arg从停止的线程调用回调,并将提供程序上下文作为参数传递。这可能有助于执行线程特定的清理,例如释放线程局部变量。
core_get_libctx()检索存储当前提供程序库对象的核心的上下文,可以通过handle访问。此函数仅对内置提供程序(如默认提供程序)有用。永远不要将其转换为非内置提供程序中的OSSL_LIB_CTX,因为加载提供程序的库的OSSL_LIB_CTX可能与提供程序链接到的库的OSSL_LIB_CTX完全不同的结构。请改用OSSL_LIB_CTX_new_child(3)获取与应用程序库上下文链接的正确库上下文。
core_new_error()、core_set_error_debug()和core_vset_error()是将错误报告回核心的构建块,并参考handle。
- core_new_error()
-
分配一个新的线程特定错误记录。
这对应于OpenSSL函数ERR_new(3)。
- core_set_error_debug()
-
在当前线程特定的错误记录中设置调试信息。调试信息包括发生错误的文件file、行line和函数名func。
这对应于OpenSSL函数ERR_set_debug(3)。
- core_vset_error()
-
设置错误的reason以及任何附加数据。reason是由提供程序定义的数字,用于索引由provider_get_reason_strings()返回的reason字符串表。附加数据作为格式字符串fmt和一组参数args给出,这些参数的处理方式与BIO_vsnprintf()相同。还可以传递file和line以指示错误发生或报告的确切位置。
这对应于OpenSSL函数ERR_vset_error(3)。
core_obj_create()函数为给定的handle注册一个新的OID以及关联的短名称sn和长名称ln。它类似于OpenSSL函数OBJ_create(3),不同之处在于它在成功时返回1,在失败时返回0。它将OID已存在的情况视为成功(即使作为参数提供的短名称sn或长名称ln与现有OID关联的名称不同,在这种情况下,新的名称不会关联)。
core_obj_add_sigid()函数为给定的handle注册一个新的复合签名算法(sign_name),该算法由一个底层签名算法(pkey_name)和摘要算法(digest_name)组成。它假设复合签名算法以及底层签名和摘要算法的OID要么已为OpenSSL所知,要么已通过调用core_obj_create()注册。它对应于OpenSSL函数OBJ_add_sigid(3),不同之处在于对象是通过名称而不是数字NID识别的。任何名称(OID、短名称或长名称)都可以用来识别对象。它将复合签名算法已存在的情况视为成功(即使针对不同的底层签名或摘要算法注册)。对于digest_name,对于不需要摘要才能正确运行的签名算法,允许使用NULL或空字符串。该函数在成功时返回1,在失败时返回0。
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()和OPENSSL_hexstr2buf()完全对应于具有相同名称的公共函数。事实上,OSSL_DISPATCH(3)数组中的指针通常是这些公共函数的直接指针。请注意,BIO函数采用OSSL_CORE_BIO类型而不是标准BIO类型。这是为了确保提供程序不会混合核心中的BIO与提供程序端使用的BIO(两者不兼容)。OSSL_SELF_TEST_set_callback()用于设置可选的回调,该回调可以传递到提供程序中。提供程序可能会忽略此回调。
get_entropy()从操作系统检索种子材料。种子材料将至少具有entropy字节的随机性,输出将至少具有min_len字节,最多具有max_len字节。缓冲区地址存储在*pout中,缓冲区长度返回给调用方。发生错误时,将返回零。
get_user_entropy()与get_entropy()相同,不同之处在于它将尝试通过对RAND_set_seed_source_type(3)的调用或通过config(5)中的“随机配置”指定的种子源收集种子材料。
cleanup_entropy()用于清理和释放get_entropy()返回的缓冲区。get_entropy()返回的熵指针在buf中传递,其长度在len中传递。
cleanup_user_entropy()用于清理和释放get_user_entropy()返回的缓冲区。get_user_entropy()返回的熵指针在buf中传递,其长度在len中传递。
get_nonce()使用传递的长度为salt_len的salt参数和操作系统特定的信息检索nonce。salt应包含唯一标识信息,并且以未指定的方式包含在输出中。输出存储在缓冲区中,该缓冲区至少包含min_len字节,最多包含max_len字节。缓冲区地址存储在*pout中,缓冲区长度返回给调用方。发生错误时,将返回零。
get_user_nonce()与get_nonce()相同,不同之处在于它将尝试通过对RAND_set_seed_source_type(3)的调用或通过config(5)中的“随机配置”指定的种子源收集种子材料。
cleanup_nonce()用于清理和释放get_nonce()返回的缓冲区。get_nonce()返回的nonce指针在buf中传递,其长度在len中传递。
cleanup_user_nonce()用于清理和释放get_user_nonce()返回的缓冲区。get_user_nonce()返回的nonce指针在buf中传递,其长度在len中传递。
provider_register_child_cb()注册回调,以便在应用程序的库上下文中加载和卸载提供程序时获得通知。handle是此提供程序的句柄,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()返回一个字符串,该字符串提供由handle标识的提供程序的名称。
provider_get0_provider_ctx()返回与由prov标识的提供程序关联的提供程序上下文。
provider_get0_dispatch()获取由prov标识的提供程序在初始化时注册的分派表。
provider_up_ref()增加提供程序prov的引用计数。如果activate非零,则如果提供程序尚未加载,则也会加载它。它在成功时返回1,在失败时返回0。
provider_free()减少提供程序prov的引用计数。如果deactivate非零,则如果提供程序尚未卸载,则也会卸载它。它在成功时返回1,在失败时返回0。
提供程序函数
provider_teardown()在提供程序关闭并从核心的提供程序存储中删除时被调用。它必须释放传递的provctx。
provider_gettable_params()应返回一个描述符OSSL_PARAM(3)的常量数组,用于provider_get_params()可以处理的参数。
provider_get_params()应处理OSSL_PARAM(3)数组params,设置其理解的参数的值。
provider_query_operation()应返回一个对应于给定operation_id的常量OSSL_ALGORITHM(3)。它应指示核心是否可以通过将*no_store设置为0(核心可以存储引用)或1(核心不能存储引用)来存储对该数组的引用。
provider_unquery_operation()通知提供程序不再直接需要provider_query_operation()的结果,并且已复制函数指针。operation_id应与传递给provider_query_operation()的匹配,algs应为其返回值。
provider_get_reason_strings()应返回一个常量OSSL_ITEM(3)数组,该数组提供提供程序在使用core_put_error()报告错误时可能使用的reason代码的reason字符串。
provider_get_capabilities() 函数应该调用回调函数 cb,并将一组 OSSL_PARAM(3) 和调用者提供的参数 arg 传递给它。这些 OSSL_PARAM(3) 应该提供与 capability 参数中给定的名称相关的功能详细信息,这些详细信息与提供程序上下文 provctx 相关。如果提供程序支持多个具有给定名称的功能,则它可以多次调用回调函数(每个功能一次)。功能可用于描述提供程序可以提供的服务。有关更多详细信息,请参阅下面的 “功能” 部分。成功时应返回 1,错误时应返回 0。
provider_self_test() 函数应在其使用的一部分算法上执行已知答案测试,并且还可以验证提供程序模块的完整性。成功时应返回 1,错误时应返回 0。如果未使用此函数,它将返回 1。
这些函数都不是强制性的,但如果没有至少 provider_query_operation(),提供程序几乎毫无用处,如果没有 provider_get_params() 则 provider_gettable_params() 几乎毫无用处。
提供程序参数
provider_get_params() 可以将以下提供程序参数返回给核心
- “name”(OSSL_PROV_PARAM_NAME)<UTF8 指针>
-
这指向一个字符串,该字符串应为提供程序提供唯一名称。
- “version”(OSSL_PROV_PARAM_VERSION)<UTF8 指针>
-
这指向一个字符串,该字符串是与此提供程序关联的版本号。OpenSSL 内置提供程序使用 OPENSSL_VERSION_STR,但对于任何第三方提供程序,这可能会有所不同。此字符串仅供参考。
- “buildinfo”(OSSL_PROV_PARAM_BUILDINFO)<UTF8 指针>
-
这指向一个字符串,该字符串是与此提供程序关联的构建信息。OpenSSL 内置提供程序使用 OPENSSL_FULL_VERSION_STR,但对于任何第三方提供程序,这可能会有所不同。
- “status”(OSSL_PROV_PARAM_STATUS)<无符号整数>
-
如果提供程序已进入错误状态,则返回 0,否则返回 1。
provider_gettable_params() 应返回上述参数。
核心参数
core_get_params() 可以为每个提供程序检索以下核心参数
- “openssl-version”(OSSL_PROV_PARAM_CORE_VERSION)<UTF8 字符串指针>
-
这指向 OpenSSL 库的完整版本字符串,即从宏 OPENSSL_VERSION_STR 展开的字符串。
- “provider-name”(OSSL_PROV_PARAM_CORE_PROV_NAME)<UTF8 字符串指针>
-
这指向 OpenSSL 库对调用提供程序名称的理解。
- “module-filename”(OSSL_PROV_PARAM_CORE_MODULE_FILENAME)<UTF8 字符串指针>
-
这指向一个包含提供程序模块文件完整文件名的字符串。
此外,配置文件中的提供程序特定配置参数以点分名称形式可用。点分名称形式是由点分隔的节名称和最终配置命令名称的串联。
例如,假设我们有以下配置示例
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”
有关处理参数的更多信息,请参阅 OSSL_PARAM(3) 和 OSSL_PARAM_int(3)。
功能
功能描述了提供程序可以提供的一些服务。应用程序可以查询功能以发现这些服务。
“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 字符串>
-
IANA TLS 支持组注册表中给出的组名称 https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8。
- “tls-group-name-internal”(OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL)<UTF8 字符串>
-
提供程序已知的组名称。这可能与“tls-group-name”相同,但不必相同。
- “tls-group-id”(OSSL_CAPABILITY_TLS_GROUP_ID)<无符号整数>
-
IANA TLS 支持组注册表中给出的 TLS 组 ID 值。
- “tls-group-alg”(OSSL_CAPABILITY_TLS_GROUP_ALG)<UTF8 字符串>
-
提供程序提供的密钥管理算法的名称,应与此组一起使用。创建的密钥应能够支持密钥交换或密钥封装方法(KEM),如可选的OSSL_CAPABILITY_TLS_GROUP_IS_KEM标志所示。该算法必须支持密钥和参数生成以及密钥/参数生成参数OSSL_PKEY_PARAM_GROUP_NAME。上面通过“tls-group-name-internal”给出的组名称将在 libssl 希望生成密钥/参数时通过OSSL_PKEY_PARAM_GROUP_NAME传递。
- “tls-group-sec-bits”(OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS)<无符号整数>
-
此组中密钥提供的安全位数。位数应与 NIST SP800-57 文档的表 2 和 3 中给出的位数相当。
- “tls-group-is-kem”(OSSL_CAPABILITY_TLS_GROUP_IS_KEM)<无符号整数>
-
布尔标志,用于描述是否应在密钥交换(KEX)模式(0,默认)或密钥封装方法(KEM)模式(1)下使用该组。
此参数是可选的:如果未指定,则假设 KEX 模式为该组的默认模式。
在 KEX 模式下,以典型的 Diffie-Hellman 方式,双方都执行keygen然后对对等方公钥执行derive。要在 KEX 模式下运行,组实现必须支持 provider-keyexch(7) 中描述的提供程序功能。
在 KEM 模式下,客户端执行keygen并发送其公钥,服务器使用客户端的公钥执行encapsulate并发送回生成的密文,最后客户端执行decapsulate以检索服务器的encapsulate生成的相同共享密钥。要在 KEM 模式下运行,组实现必须支持 provider-kem(7) 中描述的提供程序功能。
在 KEX 和 KEM 模式下,生成的共享密钥然后根据协议规范使用。
- “tls-min-tls”(OSSL_CAPABILITY_TLS_GROUP_MIN_TLS)<整数>
- “tls-max-tls”(OSSL_CAPABILITY_TLS_GROUP_MAX_TLS)<整数>
- “tls-min-dtls”(OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS)<整数>
- “tls-max-dtls”(OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS)<整数>
-
这些参数可用于描述组支持的最小和最大 TLS 和 DTLS 版本。这些值等同于各种 TLS 版本的线路上编码。例如,TLSv1.3 为 0x0304(十进制 772),TLSv1.2 为 0x0303(十进制 771)。0 表示没有定义的最小值或最大值。-1 表示不应在该协议中使用该组。
“TLS-SIGALG”功能
libssl 可以查询“TLS-SIGALG”功能以发现提供程序可以支持的 TLS 签名算法列表。除了内置的签名算法之外,每个支持的签名都可以用于客户端或服务器身份验证。TLS1.3 客户端可以在 signature_algorithms 扩展中宣传他们支持的 TLS 签名算法列表,而 TLS 服务器可以从提供的列表中选择他们也支持的算法。通过这种方式,提供程序可以将 libssl 已支持的签名算法列表添加到其他算法中。
提供程序支持的每个 TLS 签名算法都应通过 provider_get_capabilities 函数传递的回调函数进行描述。每个算法都可以提供以下详细信息
- “iana-name”(OSSL_CAPABILITY_TLS_SIGALG_IANA_NAME)<UTF8 字符串>
-
IANA TLS 签名方案注册表中给出的签名算法名称,作为“Description”:https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-signaturescheme。必须提供此值。
- “iana-code-point”(OSSL_CAPABILITY_TLS_SIGALG_CODE_POINT)<无符号整数>
-
IANA TLS SignatureScheme 注册表中给出的 TLS 算法 ID 值。必须提供此值。
- “sigalg-name”(OSSL_CAPABILITY_TLS_SIGALG_NAME)<UTF8 字符串>
-
完整(可能是复合哈希和签名)签名算法的名称。提供程序可以(但没有义务)为此名称提供签名实现;如果没有,则假定这是纯签名算法和哈希算法的组合,必须使用参数“sig-name”和“hash-name”给出。必须提供此值。
- “sigalg-oid”(OSSL_CAPABILITY_TLS_SIGALG_OID)<UTF8 字符串>
-
“sigalg-name”算法的 OID,采用规范数字文本形式。如果给出此参数,则将使用 OBJ_create() 为此 OID 创建 OBJ 和 NID,使用“sigalg-name”参数作为其(短)名称。否则,假定它已存在于对象数据库中,可能是提供程序使用 core_obj_create() 上行调用完成的。此值是可选的。
- “sig-name”(OSSL_CAPABILITY_TLS_SIGALG_SIG_NAME)<UTF8 字符串>
-
构成复合“sigalg-name”的纯签名算法的名称。如果提供程序实现了“sigalg-name”,则此参数是冗余的,不得给出。此值是可选的。
- “sig-oid”(OSSL_CAPABILITY_TLS_SIGALG_SIG_OID)<UTF8 字符串>
-
“sig-name”算法的 OID,采用规范数字文本形式。如果给出此参数,则将使用 OBJ_create() 为此 OID 创建 OBJ 和 NID,使用“sig-name”参数作为其(短)名称。否则,假定它已存在于对象数据库中。这可以通过提供程序使用 core_obj_create() 上行调用来完成。此值是可选的。
- “hash-name”(OSSL_CAPABILITY_TLS_SIGALG_HASH_NAME)<UTF8 字符串>
-
构成复合“sigalg-name”的哈希算法的名称。如果提供程序实现了“sigalg-name”,则此参数是冗余的,不得给出。此值是可选的。
- “hash-oid”(OSSL_CAPABILITY_TLS_SIGALG_HASH_OID)<UTF8 字符串>
-
“hash-name”算法的 OID,采用规范数字文本形式。如果给出此参数,则将使用 OBJ_create() 为此 OID 创建 OBJ 和 NID,使用“hash-name”参数作为其(短)名称。否则,假定它已存在于对象数据库中,可能是提供程序使用 core_obj_create() 上行调用完成的。此值是可选的。
- “key-type”(OSSL_CAPABILITY_TLS_SIGALG_KEYTYPE)<UTF8 字符串>
-
适用证书的公钥的密钥类型。如果此参数不存在,则假定它与“sig-name”(如果存在)相同,否则为“sigalg-name”。此值是可选的。
- “key-type-oid”(OSSL_CAPABILITY_TLS_SIGALG_KEYTYPE_OID)<UTF8 字符串>
-
“key-type” 的 OID,以规范数字文本形式表示。如果提供了此参数,则将使用 OBJ_create() 创建一个 OBJ 和一个 NID 用于此 OID,并使用“key-type”参数作为其(短)名称。否则,假设它已存在于对象数据库中,可能是由提供程序使用 core_obj_create() 上行调用完成的。此值是可选的。
- “sec-bits”(OSSL_CAPABILITY_TLS_SIGALG_SECURITY_BITS)<无符号整数>
-
此算法密钥提供的安全位数。位数应与 NIST SP800-57 文档表 2 和表 3 中给出的位数相当。如果没有注册其他定义安全强度的摘要算法,则此数字用于确定算法的安全强度。如果签名算法在内部实现了自己的摘要,则需要将此值设置为正确反映整体安全强度。必须提供此值。
- “tls-min-tls”(OSSL_CAPABILITY_TLS_SIGALG_MIN_TLS)<整数>
- “tls-max-tls”(OSSL_CAPABILITY_TLS_SIGALG_MAX_TLS)<整数>
-
这些参数可用于描述签名算法支持的最小和最大 TLS 版本。这些值等同于各种 TLS 版本的网络编码。例如,TLSv1.3 是 0x0304(十进制 772),TLSv1.2 是 0x0303(十进制 771)。0 表示没有定义最小值或最大值。-1 表示签名算法不应在该协议中使用。目前,表示 TLS1.3 以外的任何内容的值意味着整个算法将被忽略。
注释
在 OpenSSL 3.0 中,core_obj_create() 和 core_obj_add_sigid() 函数不是线程安全的。
示例
这是一个作为动态加载模块提供的简单提供程序的示例。它为虚拟操作 BAR
实现虚拟算法 FOO
。
#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;
}
这依赖于 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; }
另请参阅
历史
提供程序的概念及其周围的一切都在 OpenSSL 3.0 中引入。
版权
版权所有 2019-2023 OpenSSL 项目作者。保留所有权利。
根据 Apache 许可证 2.0(“许可证”)获得许可。除非符合许可证,否则您不得使用此文件。您可以在源代码分发中的 LICENSE 文件或 https://www.openssl.org/source/license.html 中获取副本。