• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Provider Development Guide
2
3This document serves as a development guide for OpenHiTLS providers, providing developers with interface introductions, key feature descriptions, and comprehensive usage examples.
4
5## 1. Overview
6
7The provider management framework in OpenHiTLS supports dynamic loading, management, and usage of cryptographic providers. Each "Provider" encapsulates a specific set of cryptographic operations and exposes them to external users through standardized interfaces.
8
9### Core Concepts:
10- **Library Context (`CRYPT_EAL_LibCtx`)**: Manages the lifecycle and resources of all loaded providers.
11- **Provider Manager Context (`CRYPT_EAL_ProvMgrCtx`)**: Represents a single provider, including its loaded library handle and implemented functionalities.
12- **Functional Interfaces**: Standardized functions used for querying and invoking specific operations of providers.
13
14---
15
16## 2. Interface Introduction
17
18### 2.1 Library Context Management
19
20#### **`CRYPT_EAL_LibCtxNew`**
21- **Description**: Creates a new library context for managing providers.
22- **Function Prototype**:
23    ```c
24    CRYPT_EAL_LibCtx *CRYPT_EAL_LibCtxNew(void);
25    ```
26- **Return Value**: A pointer to the newly created library context.
27
28#### **`CRYPT_EAL_LibCtxFree`**
29- **Description**: Frees the library context and releases all associated resources.
30- **Function Prototype**:
31    ```c
32    void CRYPT_EAL_LibCtxFree(CRYPT_EAL_LibCtx *libCtx);
33    ```
34- **Parameters**:
35    - `libCtx`: The library context to be freed.
36
37---
38
39### 2.2 Path Configuration
40
41#### **`CRYPT_EAL_ProviderSetLoadPath`**
42- **Description**: Configures the path for loading providers.
43- **Function Prototype**:
44    ```c
45    int32_t CRYPT_EAL_ProviderSetLoadPath(
46        CRYPT_EAL_LibCtx *libCtx,
47        const char *searchPath
48    );
49    ```
50- **Parameters**:
51    - `libCtx`: The library context.
52    - `searchPath`: The search path for providers.
53- **Return Value**: Returns `CRYPT_SUCCESS` on success, otherwise an error code.
54
55---
56
57### 2.3 Provider Loading and Unloading
58
59#### **`CRYPT_EAL_ProviderLoad`**
60- **Description**: Dynamically loads a provider and initializes it.
61- **Function Prototype**:
62    ```c
63    int32_t CRYPT_EAL_ProviderLoad(
64        CRYPT_EAL_LibCtx *libCtx,
65        BSL_SAL_ConverterCmd cmd,
66        const char *providerName,
67        BSL_Param *param,
68        CRYPT_EAL_ProvMgrCtx **mgrCtx
69    );
70    ```
71- **Parameters**:
72    - `libCtx`: The library context.
73    - `cmd`: The command specifying the library format (e.g., `.so`, `lib*.so`).
74    - `providerName`: The name of the provider to load.
75    - `param`: Additional parameters for provider initialization.
76    - `mgrCtx`: Output pointer to the provider manager context. If not `NULL`, the manager context of the loaded provider will be returned upon successful loading.
77- **Return Value**: Returns `CRYPT_SUCCESS` on success, otherwise an error code.
78
79#### **`CRYPT_EAL_ProviderUnload`**
80- **Description**: Unloads the specified provider and releases associated resources.
81- **Function Prototype**:
82    ```c
83    int32_t CRYPT_EAL_ProviderUnload(
84        CRYPT_EAL_LibCtx *libCtx,
85        BSL_SAL_ConverterCmd cmd,
86        const char *providerName
87    );
88    ```
89- **Parameters**:
90    - `libCtx`: The library context.
91    - `cmd`: The command specifying the library format.
92    - `providerName`: The name of the provider to unload.
93- **Return Value**: Returns `CRYPT_SUCCESS` on success, otherwise an error code.
94
95---
96
97### 2.4 Algorithm Query and Invocation
98
99**EAL Layer Wrapper Interfaces**:
100
101These interfaces wrap the provider's exposed APIs, automatically initializing algorithms after querying suitable algorithms. See the corresponding headers for each algorithm for more details.
102
103- **Symmetric Interface: `CRYPT_EAL_ProviderCipherNewCtx`**
104- **Asymmetric Interface: `CRYPT_EAL_ProviderPkeyNewCtx`**
105- **KDF Interface: `CRYPT_EAL_ProviderKdfNewCtx`**
106- **MAC Interface: `CRYPT_EAL_ProviderMacNewCtx`**
107- **Message Digest Interface: `CRYPT_EAL_ProviderMdNewCtx`**
108- **Random Number Interfaces: `CRYPT_EAL_ProviderRandInitCtx`, `CRYPT_EAL_ProviderDrbgNewCtx`**
109
110**Provider Layer Exposed Interfaces**:
111
112#### **`CRYPT_EAL_ProviderGetFuncs`**
113- **Description**: Queries algorithms matching the criteria from all loaded providers.
114- **Function Prototype**:
115    ```c
116    int32_t CRYPT_EAL_ProviderGetFuncs(
117        CRYPT_EAL_LibCtx *libCtx,
118        int32_t operaId,
119        int32_t algId,
120        const char *attribute,
121        const CRYPT_EAL_Func **funcs,
122        void **provCtx
123    );
124    ```
125- **Parameters**:
126    - `libCtx`: The library context.
127    - `operaId`: Algorithm category ID (see "crypt_eal_implprovider.h").
128    - `algId`: Algorithm ID (see "crypt_eal_implprovider.h").
129    - `attribute`: Attribute string for filtering providers.
130    - `funcs`: Output pointer to an array of algorithms.
131    - `provCtx`: Optional parameter. If not `NULL`, it retrieves the `provCtx` from the provider manager context where the algorithm resides.
132- **Return Value**: Returns `CRYPT_SUCCESS` on success, otherwise an error code.
133
134#### **`CRYPT_EAL_ProviderCtrl`**
135- **Description**: Controls the `provCtx` in the provider manager context.
136- **Function Prototype**:
137    ```c
138    int32_t CRYPT_EAL_ProviderCtrl(
139        CRYPT_EAL_ProvMgrCtx *ctx,
140        int32_t cmd,
141        void *val,
142        uint32_t valLen
143    );
144    ```
145- **Parameters**:
146    - `ctx`: Provider manager context.
147    - `cmd`: Control command.
148    - `val`: The value associated with the command.
149    - `valLen`: The length of the value.
150### 2.5 Capabilities
151
152Capabilities provide a mechanism for applications to obtain the set of capabilities supported by a provider. Through capabilities, providers can indicate their supported capabilities to users.
153
154#### 2.5.1 "CRYPT_EAL_GET_GROUP_CAP"
155
156`"CRYPT_EAL_GET_GROUP_CAP"` is used to obtain the list of `groups` supported in TLS handshakes. When creating a `HITLS_Config`, it queries and collects the list of `groups` supported by all providers. These `groups` are used for key negotiation during handshakes. Each `group` must support either a `kex` or `kem` algorithm. Through this mechanism, providers can add new `groups` to TLS handshakes.
157
158Each `group` supported by a provider can be declared through the callback passed to `CRYPT_EAL_PROVCB_GETCAPS`. Each `group` can have the following fields:
159
160- `CRYPT_PARAM_CAP_TLS_GROUP_IANA_GROUP_NAME`: Type `BSL_PARAM_TYPE_OCTETS_PTR`, TLS supported groups registered in IANA. See [IANA](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8)
161- `CRYPT_PARAM_CAP_TLS_GROUP_IANA_GROUP_ID`: Type `BSL_PARAM_TYPE_UINT16`, corresponding ID of TLS supported groups registered in IANA.
162- `CRYPT_PARAM_CAP_TLS_GROUP_PARA_ID`: Type `BSL_PARAM_TYPE_INT32`, parameter ID for the group, passed to `CRYPT_EAL_PkeySetParaById` interface.
163- `CRYPT_PARAM_CAP_TLS_GROUP_ALG_ID`: Type `BSL_PARAM_TYPE_INT32`, algorithm ID for the group, passed to `CRYPT_EAL_ProviderPkeyNewCtx` interface.
164- `CRYPT_PARAM_CAP_TLS_GROUP_SEC_BITS`: Type `BSL_PARAM_TYPE_INT32`, security strength provided by the group.
165- `CRYPT_PARAM_CAP_TLS_GROUP_VERSION_BITS`: Type `BSL_PARAM_TYPE_UINT32`, TLS version bitmap supported by the group. See `*_VERSION_BIT` in `hitls_type.h`
166- `CRYPT_PARAM_CAP_TLS_GROUP_IS_KEM`: Type `BSL_PARAM_TYPE_BOOL`, indicates whether the group is a KEM algorithm.
167- `CRYPT_PARAM_CAP_TLS_GROUP_PUBKEY_LEN`: Type `BSL_PARAM_TYPE_INT32`, public key length for the group.
168- `CRYPT_PARAM_CAP_TLS_GROUP_SHAREDKEY_LEN`: Type `BSL_PARAM_TYPE_INT32`, shared key length for the group.
169- `CRYPT_PARAM_CAP_TLS_GROUP_CIPHERTEXT_LEN`: Type `BSL_PARAM_TYPE_INT32`, ciphertext length for KEM algorithms.
170
171For example code, refer to `crypt_default_provider.c:CryptGetGroupCaps`
172
173#### 2.5.2 "CRYPT_EAL_GET_SIGALG_CAP"
174
175`"CRYPT_EAL_GET_SIGALG_CAP"` is used to obtain the list of `signature algorithms` supported in TLS handshakes. When creating a `HITLS_Config`, it queries and collects the list of `signature algorithms` supported by all providers. These `signature algorithms` are used for authentication during handshakes. Through this mechanism, providers can add new `signature algorithms` to TLS handshakes.
176
177Each `signature algorithm` supported by a provider can be declared through the callback passed to `CRYPT_EAL_PROVCB_GETCAPS`. Each `signature algorithm` can have the following fields:
178
179- `CRYPT_PARAM_CAP_TLS_SIGNALG_IANA_SIGN_NAME`: Type `BSL_PARAM_TYPE_OCTETS_PTR`, TLS signature scheme name registered in IANA. See [IANA](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-signaturescheme)
180- `CRYPT_PARAM_CAP_TLS_SIGNALG_IANA_SIGN_ID`: Type `BSL_PARAM_TYPE_UINT16`, corresponding ID of TLS signature scheme registered in IANA.
181- `CRYPT_PARAM_CAP_TLS_SIGNALG_KEY_TYPE`: Type `BSL_PARAM_TYPE_INT32`, key type used by the signature algorithm.
182- `CRYPT_PARAM_CAP_TLS_SIGNALG_KEY_TYPE_OID`: Type `BSL_PARAM_TYPE_OCTETS_PTR`, OID corresponding to the key type.
183- `CRYPT_PARAM_CAP_TLS_SIGNALG_KEY_TYPE_NAME`: Type `BSL_PARAM_TYPE_OCTETS_PTR`, name of the key type.
184- `CRYPT_PARAM_CAP_TLS_SIGNALG_PARA_ID`: Type `BSL_PARAM_TYPE_INT32`, parameter ID for the signature algorithm.
185- `CRYPT_PARAM_CAP_TLS_SIGNALG_PARA_OID`: Type `BSL_PARAM_TYPE_OCTETS_PTR`, OID corresponding to the signature algorithm parameter.
186- `CRYPT_PARAM_CAP_TLS_SIGNALG_PARA_NAME`: Type `BSL_PARAM_TYPE_OCTETS_PTR`, name of the signature algorithm parameter.
187- `CRYPT_PARAM_CAP_TLS_SIGNALG_SIGNWITHMD_ID`: Type `BSL_PARAM_TYPE_INT32`, ID for the combination of signature and digest algorithms.
188- `CRYPT_PARAM_CAP_TLS_SIGNALG_SIGNWITHMD_OID`: Type `BSL_PARAM_TYPE_OCTETS_PTR`, OID corresponding to the combination of signature and digest algorithms.
189- `CRYPT_PARAM_CAP_TLS_SIGNALG_SIGNWITHMD_NAME`: Type `BSL_PARAM_TYPE_OCTETS_PTR`, name of the combination of signature and digest algorithms.
190- `CRYPT_PARAM_CAP_TLS_SIGNALG_SIGN_ID`: Type `BSL_PARAM_TYPE_INT32`, signature algorithm ID.
191- `CRYPT_PARAM_CAP_TLS_SIGNALG_MD_ID`: Type `BSL_PARAM_TYPE_INT32`, digest algorithm ID.
192- `CRYPT_PARAM_CAP_TLS_SIGNALG_MD_OID`: Type `BSL_PARAM_TYPE_OCTETS_PTR`, OID corresponding to the digest algorithm.
193- `CRYPT_PARAM_CAP_TLS_SIGNALG_MD_NAME`: Type `BSL_PARAM_TYPE_OCTETS_PTR`, name of the digest algorithm.
194- `CRYPT_PARAM_CAP_TLS_SIGNALG_SEC_BITS`: Type `BSL_PARAM_TYPE_INT32`, security strength provided by the signature algorithm.
195- `CRYPT_PARAM_CAP_TLS_SIGNALG_CHAIN_VERSION_BITS`: Type `BSL_PARAM_TYPE_UINT32`, certificate chain version bitmap supported by the signature algorithm. See `*_VERSION_BIT` in `hitls_type.h`
196- `CRYPT_PARAM_CAP_TLS_SIGNALG_CERT_VERSION_BITS`: Type `BSL_PARAM_TYPE_UINT32`, certificate version bitmap supported by the signature algorithm. See `*_VERSION_BIT` in `hitls_type.h`
197
198For example code, refer to `crypt_default_provider.c:CryptGetSignAlgCaps`
199
200---
201
202## 3. Provider Management Module Usage Instructions
203
204### 3.1 Loading and Unloading
205
206- **Feature Descriptions**:
207    - Providers are uniquely identified by their names. Different providers must have unique names. Providers with the same name but located in different paths are treated as the same provider.
208    - The framework supports repeated loading and unloading of providers. Repeated loading does not create additional provider manager contexts. To remove a provider manager context from the library context, the number of unloads must match the number of loads.
209    - When releasing the library context, all loaded providers are automatically unloaded.
210    - The default provider loading path is empty. If no path is set, the framework searches for providers in various locations based on the runtime environment and the behavior of the `dlopen` function.
211    - Currently, OpenHiTLS's built-in algorithm library is loaded into a globally initialized library context during startup. If `libCtx` is `NULL` during provider loading, unloading, or searching, this global library context is used.
212
213- **Usage Example**:
214    ```c
215    ...
216    // Create a library context
217    CRYPT_EAL_LibCtx *libCtx = CRYPT_EAL_LibCtxNew();
218    assert(libCtx != NULL);
219
220    // Set the provider loading path
221    int ret = CRYPT_EAL_ProviderSetLoadPath(libCtx, "/path/to/providers");
222    assert(ret == CRYPT_SUCCESS);
223
224    // Load a provider
225    CRYPT_EAL_ProvMgrCtx *mgrCtx = NULL;
226    ret = CRYPT_EAL_ProviderLoad(libCtx, BSL_SAL_CONVERTER_SO, "provider_name", NULL, &mgrCtx);
227    assert(ret == CRYPT_SUCCESS);
228
229    ...
230
231    // Unload the provider
232    ret = CRYPT_EAL_ProviderUnload(libCtx, BSL_SAL_CONVERTER_SO, "provider_name");
233    assert(ret == CRYPT_SUCCESS);
234
235    // Free the library context
236    CRYPT_EAL_LibCtxFree(libCtx);
237    ...
238    ```
239
240---
241
242### 3.2 Attribute Query and Provider Scoring Mechanism
243
244- **Attribute Mechanism**:
245    When querying algorithms, the framework first searches for algorithms matching the algorithm ID. If the search string is not `NULL`, it further selects the best-matching algorithm from all loaded providers based on the search string.
246    Provider algorithm attributes are composed of a `name` and a `value`, separated by `=`. Multiple attributes are separated by `,`. Within a provider, each algorithm can define one or more sets of attributes based on its implementation purpose. Even the same algorithm can have different implementations distinguished by attributes.
247
248- **Provider Scoring Mechanism**:
249    Queries can consist of multiple query statements, separated by `,`. Within a statement, `name` and `value` are separated by the following **comparison characters**:
250    - `=`: Must be equal (mandatory condition).
251    - `!=`: Must not be equal (mandatory condition).
252    - `?`: Optional condition. If `value` matches, it is prioritized. Each match adds +1 to the score.
253
254    Mandatory conditions must be satisfied. Among providers that meet the mandatory conditions, the framework selects the best match based on optional conditions. If there are multiple best matches, one is randomly selected.
255    Repeated conditions are allowed within query statements:
256    - Repeated mandatory conditions have no effect.
257    - Repeated optional conditions increase the score proportionally.
258
259- **Usage Example**:
260    ```c
261    ...
262    // Query with a NULL attribute string, searching by algorithm ID
263    ret = CRYPT_EAL_ProviderGetFuncs(libCtx, CRYPT_EAL_OPERAID_HASH, CRYPT_MD_MD5, NULL, &funcs, &provCtx);
264    assert(ret == CRYPT_SUCCESS);
265    ...
266    // Query with a non-NULL attribute string, matching based on rules
267    ret = CRYPT_EAL_ProviderGetFuncs(libCtx, CRYPT_EAL_OPERAID_HASH, CRYPT_MD_MD5, "name=md5,type=hash,version=1.0", &funcs, &provCtx);
268    assert(ret == CRYPT_SUCCESS);
269    ...
270    // Query with provider scoring mechanism
271    ret = CRYPT_EAL_ProviderGetFuncs(libCtx, CRYPT_EAL_OPERAID_HASH, CRYPT_MD_MD5, "name=md5,feature?attr_good,feature?attr_good,feature?attr_bad", &funcs, &provCtx);
272    assert(ret == CRYPT_SUCCESS);
273    ...
274    // For actual use, it is recommended to use EAL layer wrapping interfaces for each algorithm,
275    // which automatically locate and initialize the algorithm.
276    CRYPT_EAL_MdCTX *ctx = CRYPT_EAL_ProviderMdNewCtx(libCtx, CRYPT_MD_MD5, "provider=no_hitls,type=hash");
277    assert(ctx != NULL);
278    ...
279    ```
280
281---
282
283## 4. Provider Construction Instructions
284
285This section describes the commands and function prototypes, which are fully defined in the `crypt_eal_implprovider.h` header file.
286
287### 4.1 Initialization Function
288
289For each provider, an initialization function named `CRYPT_EAL_ProviderInit` must be implemented. This function is called when loading the provider:
290- **Function Prototype**:
291    ```c
292    int32_t CRYPT_EAL_ProviderInit(
293        CRYPT_EAL_ProvMgrCtx *mgrCtx,
294        BSL_Param *param,
295        CRYPT_EAL_Func *capFuncs,
296        CRYPT_EAL_Func **outFuncs,
297        void **provCtx
298    );
299    ```
300    - **Parameters**:
301        - `mgrCtx`: [in] Provider manager context.
302        - `param`: [in] Additional parameters for provider initialization.
303        - `capFuncs`: [in] Algorithm array pointer provided by the management framework, allowing users to optionally use HITLS's default entropy source.
304        - `outFuncs`: [out] Array pointer for algorithms exposed by the provider. Details are described below.
305        - `provCtx`: [out] Provider-specific structure. If needed, private data can be saved in the provider manager context. Details on its operation are below (optional).
306    - **Return Value**: Returns `CRYPT_SUCCESS` on success, otherwise an error code.
307
308- **Description of the `outFuncs` Array**:
309    This array is used to pass the three types of algorithm arrays provided by the provider. **The algorithm query function must be returned**, while the other two functions are optional:
310    - **Algorithm Query Function**: Used to retrieve the algorithm array provided by the provider based on the algorithm category during a search:
311    **`typedef int32_t (*)(void *provCtx, int32_t operaId, CRYPT_EAL_AlgInfo **algInfos);`**
312        - **Parameters**:
313            - `provCtx`: [in] Provider-specific structure (optional).
314            - `operaId`: [in] Algorithm category ID.
315            - `algInfos`: [out] Pointer to the array of all algorithms under the category. The array ends when the algorithm ID is 0.
316        - **Return Value**: Returns `CRYPT_SUCCESS` on success, otherwise an error code.
317    - **`provCtx` Control Function**: If the provider uses `provCtx`, this function is used for its control. It can be invoked using the `CRYPT_EAL_ProviderCtrl` function.
318    **`typedef int32_t (*)(void *provCtx, int32_t cmd, void *val, uint32_t valLen);`**
319        - **Parameters**: Omitted.
320        - **Return Value**: Omitted.
321    - **`provCtx` Release Function**: If the provider uses `provCtx`, this function releases `provCtx`. It is called during resource release.
322    **`typedef void (*)(void *provCtx);`**
323    - **Parameters**:
324        - `provCtx`: [in] Provider-specific structure.
325        - **Return Value**: None.
326
327---
328
329### 4.2 Provider Construction Example
330
331- **Initialization Function Example**:
332```c
333static CRYPT_EAL_Func defProvOutFuncs[] = {
334    {CRYPT_EAL_PROVCB_QUERY, CRYPT_EAL_DefaultProvQuery},
335    {CRYPT_EAL_PROVCB_FREE, NULL},
336    {CRYPT_EAL_PROVCB_CTRL, NULL},
337    CRYPT_EAL_FUNC_END
338};
339
340int32_t CRYPT_EAL_ProviderInit(CRYPT_EAL_ProvMgrCtx *mgrCtx,
341    BSL_Param *param, CRYPT_EAL_Func *capFuncs, CRYPT_EAL_Func **outFuncs, void **provCtx)
342{
343    CRYPT_RandSeedMethod entroy = {0};
344    CRYPT_EAL_ProvMgrCtrlCb mgrCtrl = NULL;
345    int32_t index = 0;
346    while (capFuncs[index].id != 0) {
347        switch (capFuncs[index].id) {
348            case CRYPT_EAL_CAP_GETENTROPY:
349                entroy.getEntropy = capFuncs[index].func;
350                break;
351            case CRYPT_EAL_CAP_CLEANENTROPY:
352                entroy.cleanEntropy = capFuncs[index].func;
353                break;
354            case CRYPT_EAL_CAP_GETNONCE:
355                entroy.getNonce = capFuncs[index].func;
356                break;
357            case CRYPT_EAL_CAP_CLEANNONCE:
358                entroy.cleanNonce = capFuncs[index].func;
359                break;
360            case CRYPT_EAL_CAP_MGRCTXCTRL:
361                mgrCtrl = capFuncs[index].func;
362                break;
363            default:
364                return CRYPT_PROVIDER_ERR_UNEXPECTED_IMPL;
365        }
366        index++;
367    }
368    void *seedCtx = NULL;
369    void *libCtx = NULL;
370    if (entroy.getEntropy == NULL || entroy.cleanEntropy == NULL || entroy.getNonce == NULL ||
371        entroy.cleanNonce == NULL || mgrCtrl == NULL) {
372        return CRYPT_NULL_INPUT;
373    }
374    int32_t ret = mgrCtrl(mgrCtx, CRYPT_EAL_MGR_GETSEEDCTX, &seedCtx, 0);
375    if (ret != CRYPT_SUCCESS) {
376        return ret;
377    }
378    ret = mgrCtrl(mgrCtx, CRYPT_EAL_MGR_GETLIBCTX, &libCtx, 0);
379    if (ret != CRYPT_SUCCESS) {
380        return ret;
381    }
382    CRYPT_Data entropy = {NULL, 0};
383    CRYPT_Range entropyRange = {32, 2147483632};
384    ret = entroy.getEntropy(seedCtx, &entropy, 256, &entropyRange);
385    if (ret != CRYPT_SUCCESS) {
386        return CRYPT_DRBG_FAIL_GET_ENTROPY;
387    }
388    entroy.cleanEntropy(seedCtx, &entropy);
389    // check libCtx
390    if (param != NULL) {
391        if (param[0].value != libCtx) {
392            return CRYPT_INVALID_ARG;
393        }
394    }
395    *outFuncs = defProvOutFuncs;
396    return 0;
397}
398```
399- **Algorithm query function example**:
400```c
401const CRYPT_EAL_Func defMdMd5[] = {
402    {CRYPT_EAL_IMPLMD_NEWCTX, ...},
403    {CRYPT_EAL_IMPLMD_INITCTX, ...},
404    {CRYPT_EAL_IMPLMD_UPDATE, ...},
405    {CRYPT_EAL_IMPLMD_FINAL, ...},
406    {CRYPT_EAL_IMPLMD_DEINITCTX, ...},
407    {CRYPT_EAL_IMPLMD_DUPCTX, ...},
408    {CRYPT_EAL_IMPLMD_CTRL, ...},
409    {CRYPT_EAL_IMPLMD_FREECTX, ...},
410    CRYPT_EAL_FUNC_END,
411};
412
413static const CRYPT_EAL_AlgInfo defMds[] = {
414    ...
415    {CRYPT_MD_MD5, defMdMd5, "attr1=temp_attr1,attr2=temp_attr2"},
416    ...
417    CRYPT_EAL_ALGINFO_END
418};
419
420static int32_t CRYPT_EAL_DefaultProvQuery(void *provCtx, int32_t operaId, const CRYPT_EAL_AlgInfo **algInfos)
421{
422    (void) provCtx;
423    int32_t ret = CRYPT_SUCCESS;
424    switch (operaId) {
425        ...
426        case CRYPT_EAL_OPERAID_HASH:
427            *algInfos = defMds;
428            break;
429        ...
430        default:
431            ret = CRYPT_NOT_SUPPORT;
432            break;
433    }
434    return ret;
435}
436```
437
438---
439
440## 5. Comprehensive Usage Example
441
442```c
443#include "bsl_sal.h"
444#include "crypt_eal_provider.h"
445#include "crypt_eal_implprovider.h"
446#include "crypt_eal_md.h"
447
448/* Using the SM3 algorithm */
449
450int main() {
451
452------------------------------------------------------------------------------------------------------
453
454// Using the built-in HITLS algorithm library:
455    // Step 1: Directly initialize using EAL layer MD interface
456    CRYPT_EAL_MdCTX *ctx = CRYPT_EAL_ProviderMdNewCtx(NULL, CRYPT_MD_SM3, "provider=default");
457    ASSERT_TRUE(ctx != NULL);
458
459-----------------------------------------------
460
461// Searching and initializing with a matching algorithm library in a third-party provider:
462    // Step 1: Create a library context
463    CRYPT_EAL_LibCtx *libCtx = CRYPT_EAL_LibCtxNew();
464    ASSERT_TRUE(libCtx != NULL);
465
466    // Step 2: Set the provider loading path
467    int ret = CRYPT_EAL_ProviderSetLoadPath(libCtx, "/path/to/providers");
468    ASSERT_TRUE(ret == CRYPT_SUCCESS);
469
470    // Step 3: Load the provider
471    ret = CRYPT_EAL_ProviderLoad(libCtx, BSL_SAL_LIB_FMT_SO, "provider_name", NULL, NULL);
472    ASSERT_TRUE(ret == CRYPT_SUCCESS);
473
474    // Step 4: Directly initialize using EAL layer MD interface
475    CRYPT_EAL_MdCTX *ctx = CRYPT_EAL_ProviderMdNewCtx(libCtx, CRYPT_MD_SM3, "attr1=temp_attr1,attr2=temp_attr2");
476    ASSERT_TRUE(ctx != NULL);
477
478-----------------------------------------------
479
480// Mixed usage of third-party providers and HITLS libraries:
481    // Step 1: Set the provider loading path
482    int ret = CRYPT_EAL_ProviderSetLoadPath(NULL, "/path/to/providers");
483    ASSERT_TRUE(ret == CRYPT_SUCCESS);
484
485    // Step 2: Load the provider
486    ret = CRYPT_EAL_ProviderLoad(NULL, BSL_SAL_LIB_FMT_SO, "provider_name", NULL, NULL);
487    ASSERT_TRUE(ret == CRYPT_SUCCESS);
488
489    // Step 3: Directly initialize using EAL layer MD interface
490    CRYPT_EAL_MdCTX *ctx = CRYPT_EAL_ProviderMdNewCtx(NULL, CRYPT_MD_SM3, "attr1=temp_attr1,attr2=temp_attr2");
491    ASSERT_TRUE(ctx != NULL);
492
493------------------------------------------------------------------------------------------------------
494
495// After initialization, a series of algorithm operations can be performed:
496    ASSERT_EQ(CRYPT_EAL_MdInit(ctx), CRYPT_SUCCESS);
497    ASSERT_EQ(CRYPT_EAL_MdUpdate(ctx, msg->x, msg->len), CRYPT_SUCCESS);
498    ASSERT_EQ(CRYPT_EAL_MdFinal(ctx, output, &outLen), CRYPT_SUCCESS);
499
500------------------------------------------------------------------------------------------------------
501
502// If a library context was created or a third-party provider was loaded during initialization, they need to be released:
503    // Unload the provider
504    ret = CRYPT_EAL_ProviderUnload(libCtx, BSL_SAL_CONVERTER_SO, "provider_name");
505    ASSERT_TRUE(ret == CRYPT_SUCCESS);
506
507    // Free the library context
508    CRYPT_EAL_LibCtxFree(libCtx);
509
510    return 0;
511}
512```