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);
說明
在此提到的所有「函式」都以函式指標在 OSSL_DISPATCH(3) 陣列中,傳遞於 libcrypto 和提供者之間,在提供者初始化函式的呼叫中。請參閱 provider(7) 中的「提供者」,以取得初始化函式的說明。它們稱為「上呼叫」。
所有這些「函式」都有對應的函式類型定義,稱為 OSSL_FUNC_{name}_fn,以及一個輔助函式,用於從 OSSL_DISPATCH(3) 元素中擷取函式指標,稱為 OSSL_FUNC_{name}。例如,「函式」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()
-
設定錯誤的原因,以及任何附加資料。原因是由提供者定義的數字,用於索引由 provider_get_reason_strings() 回傳的錯誤字串表格。附加資料以格式字串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) 中的 "Random Configuration" 指定的種子來源收集種子素材。
cleanup_entropy() 用於清理並釋放 get_entropy() 傳回的緩衝區。get_entropy() 傳回的 entropy 指標傳遞到 buf 中,其長度傳遞到 len 中。
cleanup_user_entropy() 用於清理並釋放 get_user_entropy() 傳回的緩衝區。get_user_entropy() 傳回的 entropy 指標傳遞到 buf 中,其長度傳遞到 len 中。
get_nonce() 使用傳遞的長度為 salt_len 的 salt 參數和作業系統特定資訊擷取一次性密碼。salt 應包含唯一識別資訊,且此資訊會以未指定的方式包含在輸出中。輸出儲存在一個緩衝區中,該緩衝區至少包含 min_len 位元組,最多包含 max_len 位元組。緩衝區位址儲存在 *pout 中,緩衝區長度傳回給呼叫者。發生錯誤時,傳回零。
get_user_nonce() 與 get_nonce() 相同,但它會嘗試透過呼叫 RAND_set_seed_source_type(3) 或透過 config(5) 中的 "Random Configuration" 指定的種子來源收集種子素材。
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 識別的提供者在初始化時註冊的 dispatch 表格。
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() 應傳回常數 OSSL_ALGORITHM(3),對應於給定的 operation_id。它應透過將 *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() 報告錯誤時,原因代碼的原因字串。
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 ptr>
-
這指向一個字串,提供者應給予一個獨特的名稱。
- "version" (OSSL_PROV_PARAM_VERSION) <UTF8 ptr>
-
這指向一個字串,是與此提供者相關的版本號。OpenSSL 內建提供者使用 OPENSSL_VERSION_STR,但任何第三方提供者可能不同。此字串僅供資訊用途。
- "buildinfo" (OSSL_PROV_PARAM_BUILDINFO) <UTF8 ptr>
-
這指向一個字串,是與此提供者相關的建置資訊。OpenSSL 內建提供者使用 OPENSSL_FULL_VERSION_STR,但任何第三方提供者可能不同。
- "status" (OSSL_PROV_PARAM_STATUS) <unsigned integer>
-
如果提供者已進入錯誤狀態,這會傳回 0,否則傳回 1。
provider_gettable_params() 應傳回上述參數。
核心參數
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"
如需有關處理參數的更多資訊,請參閱 OSSL_PARAM(3) 作為 OSSL_PARAM_int(3)。
功能
功能描述提供者可以提供的部分服務。應用程式可以查詢功能以發現這些服務。
"TLS-GROUP" 功能
libssl 可以查詢「TLS-GROUP」功能,以找出供應商可以支援的 TLS 群組清單。在 TLS 交握期間,每個受支援的群組都可以用於金鑰交換 (KEX) 或金鑰封裝方法 (KEM)。TLS 伺服器可以在受支援群組延伸模組中宣告其支援的 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。當 libssl 希望產生金鑰/參數時,會透過 OSSL_PKEY_PARAM_GROUP_NAME 傳遞上面透過「tls-group-name-internal」提供的群組名稱。
- 「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 方式,雙方執行金鑰產生,然後針對對等公開金鑰衍生。若要以 KEX 模式操作,群組實作必須支援 provider-keyexch(7) 中所述的提供者函數。
在 KEM 模式中,用戶端執行金鑰產生並傳送其公開金鑰,伺服器使用用戶端的公開金鑰執行封裝並傳回產生的密文,最後用戶端執行解封以擷取伺服器的封裝所產生的相同共用密碼。若要以 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 簽章方案註冊表中 "說明" 所示:https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-signaturescheme。必須提供此值。
- "iana-code-point" (OSSL_CAPABILITY_TLS_SIGALG_CODE_POINT) <unsigned integer>
-
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() 將用於使用 "sigalg-name" 參數作為其 (簡短) 名稱,為此 OID 建立 OBJ 和 NID。否則,假設它已存在於物件資料庫中,可能是由供應商使用 core_obj_create() upcall 完成的。此值是選用的。
- "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() 將用於使用 "sig-name" 參數作為其 (簡短) 名稱,為此 OID 建立 OBJ 和 NID。否則,假設它已存在於物件資料庫中。供應商可以使用 core_obj_create() upcall 完成此動作。此值是選用的。
- "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() 將用於使用 "hash-name" 參數作為其 (簡短) 名稱,為此 OID 建立 OBJ 和 NID。否則,假設它已存在於物件資料庫中,可能是由供應商使用 core_obj_create() upcall 完成的。此值是選用的。
- "key-type" (OSSL_CAPABILITY_TLS_SIGALG_KEYTYPE) <UTF8 字串>
-
適用的憑證公鑰的類型。如果未提供此參數,則假設它與 "sig-name" 相同 (如果存在),否則為 "sigalg-name"。此值是選用的。
- "key-type-oid" (OSSL_CAPABILITY_TLS_SIGALG_KEYTYPE_OID) <UTF8 字串>
-
以標準數字文字格式顯示「金鑰類型」的 OID。如果提供此參數,OBJ_create() 將用於建立 OBJ 和此 OID 的 NID,並使用「金鑰類型」參數作為其(簡短)名稱。否則,假設它已存在於物件資料庫中,可能是由提供者透過 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 The OpenSSL Project Authors。保留所有權利。
在 Apache 授權 2.0(「授權」)下授權。您不得在不遵守授權的情況下使用此檔案。您可以在原始程式碼散佈中的 LICENSE 檔案或 https://www.openssl.org/source/license.html 取得副本。