• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# HUKS Development (Native)
2
3## When to Use
4
5The OpenHarmony Universal KeyStore (HUKS) provides full lifecycle management capability for keys. The keys managed by the HUKS can be imported by an application or generated by calling the HUKS APIs. For a key generated by the HUKS, the plaintext will never be exposed outside throughout the lifecycle. No one can obtain the key in plaintext. Even the service itself can call APIs provided by the HUKS to perform operations on the key and obtain the operation result, but cannot access the key.
6
7With the Native APIs provided by the HUKS, you can:
8
9* Generate a key.
10* Import an external key to the HUKS.
11* Encrypt and decrypt data by using a key.
12* Generate a digital signature and verify a signature.
13* Generate a shared secrete through key agreement.
14* Derive a key.
15* Provide key attestation.
16
17## Available APIs
18
19### APIs for Key Use
20
21| API| Description|
22| -------- | -------- |
23| [OH_Huks_GetSdkVersion](../reference/native-apis/_huks_key_api.md#oh_huks_getsdkversion) (struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*sdkVersion) | Obtains the current HUKS SDK version. |
24| [OH_Huks_GenerateKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_generatekeyitem) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSetIn, struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSetOut) | Generates a key. |
25| [OH_Huks_ImportKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_importkeyitem) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*key) | Imports a key in plaintext. |
26| [OH_Huks_ImportWrappedKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_importwrappedkeyitem) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*wrappingKeyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*wrappedKeyData) | Imports a wrapped (encrypted) key. |
27| [OH_Huks_ExportPublicKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_exportpublickeyitem) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*key) | Exports a public key. |
28| [OH_Huks_DeleteKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_deletekeyitem) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet) | Deletes a key. |
29| [OH_Huks_GetKeyItemParamSet](../reference/native-apis/_huks_key_api.md#oh_huks_getkeyitemparamset) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSetIn, struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSetOut) | Obtains the parameter set of a key. |
30| [OH_Huks_IsKeyItemExist](../reference/native-apis/_huks_key_api.md#oh_huks_iskeyitemexist) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet) | Checks whether a key exists. |
31| [OH_Huks_AttestKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_attestkeyitem) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, struct [OH_Huks_CertChain](../reference/native-apis/_o_h___huks___cert_chain.md) \*certChain) | Obtains the key certificate chain. |
32| [OH_Huks_InitSession](../reference/native-apis/_huks_key_api.md#oh_huks_initsession) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*handle, struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*token) | Initializes the key session to obtain a handle (mandatory) and a challenge value (optional). |
33| [OH_Huks_UpdateSession](../reference/native-apis/_huks_key_api.md#oh_huks_updatesession) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*handle, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*inData, struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*outData) | Adds data by segment for the key operation, performs the related key operation, and outputs the processed data. |
34| [OH_Huks_FinishSession](../reference/native-apis/_huks_key_api.md#oh_huks_finishsession) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*handle, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*inData, struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*outData) | Finishes the key session. |
35| [OH_Huks_AbortSession](../reference/native-apis/_huks_key_api.md#oh_huks_abortsession) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*handle, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet) | Aborts a key session. |
36
37### APIs for Key Parameters
38
39| API| Description|
40| -------- | -------- |
41| [OH_Huks_InitParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_initparamset) (struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*\*paramSet) | Initializes a parameter set. |
42| [OH_Huks_AddParams](../reference/native-apis/_huks_param_set_api.md#oh_huks_addparams) (struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, const struct [OH_Huks_Param](../reference/native-apis/_o_h___huks___param.md) \*params, uint32_t paramCnt) | Adds parameters to a parameter set. |
43| [OH_Huks_BuildParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_buildparamset) (struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*\*paramSet) | Builds a formal parameter set. |
44| [OH_Huks_FreeParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_freeparamset) (struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*\*paramSet) | Destroys a parameter set. |
45| [OH_Huks_CopyParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_copyparamset) (const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*fromParamSet, uint32_t fromParamSetSize, struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*\*paramSet) | Copies a parameter set (deep copy). |
46| [OH_Huks_GetParam](../reference/native-apis/_huks_param_set_api.md#oh_huks_getparam) (const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, uint32_t tag, struct [OH_Huks_Param](../reference/native-apis/_o_h___huks___param.md) \*\*param) | Obtains parameters from a parameter set. |
47| [OH_Huks_FreshParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_freshparamset) (struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, bool isCopy) | Refreshes data of the **Blob** type in a parameter set. |
48| [OH_Huks_IsParamSetTagValid](../reference/native-apis/_huks_param_set_api.md#oh_huks_isparamsettagvalid) (const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet) | Checks whether the parameters in a parameter set are valid. |
49| [OH_Huks_IsParamSetValid](../reference/native-apis/_huks_param_set_api.md#oh_huks_isparamsetvalid) (const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, uint32_t size) | Checks whether a parameter set is of the valid size. |
50| [OH_Huks_CheckParamMatch](../reference/native-apis/_huks_param_set_api.md#oh_huks_checkparammatch) (const struct [OH_Huks_Param](../reference/native-apis/_o_h___huks___param.md) \*baseParam, const struct [OH_Huks_Param](../reference/native-apis/_o_h___huks___param.md) \*param) | Compares whether two parameters are the same. |
51
52## How to Develop
53
54### Key Generation
55The HUKS provides the capability of randomly generating keys for services. For a key generated by the HUKS, the plaintext will never be exposed outside throughout the lifecycle. No one can obtain the key in plaintext. Even the service itself can call APIs provided by the HUKS to perform operations on the key and obtain the operation result, but cannot access the key.
56
57**How to Develop**
58
59Use [OH_Huks_GenerateKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_generatekeyitem) to generate a key. You need to pass in **keyAlias** and **paramSetIn**.
60
611. Set the key alias.
622. Initialize the key parameter set. Use [OH_Huks_InitParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_initparamset), [OH_Huks_AddParams](../reference/native-apis/_huks_param_set_api.md#oh_huks_addparams), and [OH_Huks_BuildParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_buildparamset) to construct **paramSet**, which must contain the [OH_Huks_KeyAlg](../reference/native-apis/_huks_type_api.md#oh_huks_keyalg), [OH_Huks_KeySize](../reference/native-apis/_huks_type_api.md#oh_huks_keysize), and [OH_Huks_KeyPurpose](../reference/native-apis/_huks_type_api.md#oh_huks_keypurpose).
633. Pass in the key alias and key parameter set to generate a key.
64
65> **NOTE**
66>
67> The key alias cannot exceed 64 bytes.
68
69**C++ Code Example**
70
71```C++
72#include "huks/native_huks_api.h"
73#include "huks/native_huks_param.h"
74#include <string.h>
75OH_Huks_Result InitParamSet(
76    struct OH_Huks_ParamSet **paramSet,
77    const struct OH_Huks_Param *params,
78    uint32_t paramCount)
79{
80    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
81    if (ret.errorCode != OH_HUKS_SUCCESS) {
82        return ret;
83    }
84
85    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
86    if (ret.errorCode != OH_HUKS_SUCCESS) {
87        OH_Huks_FreeParamSet(paramSet);
88        return ret;
89    }
90
91    ret = OH_Huks_BuildParamSet(paramSet);
92    if (ret.errorCode != OH_HUKS_SUCCESS) {
93        OH_Huks_FreeParamSet(paramSet);
94        return ret;
95    }
96
97    return ret;
98}
99
100struct OH_Huks_Param g_testGenerateKeyParam[] = {
101    {
102        .tag = OH_HUKS_TAG_ALGORITHM,
103        .uint32Param = OH_HUKS_ALG_ECC
104    }, {
105        .tag = OH_HUKS_TAG_PURPOSE,
106        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
107    }, {
108        .tag = OH_HUKS_TAG_KEY_SIZE,
109        .uint32Param = OH_HUKS_ECC_KEY_SIZE_256
110    }, {
111        .tag = OH_HUKS_TAG_DIGEST,
112        .uint32Param = OH_HUKS_DIGEST_NONE
113    }
114};
115
116static napi_value GenerateKey(napi_env env, napi_callback_info info)
117{
118    const char *alias = "test_generate";
119    struct OH_Huks_Blob aliasBlob = { .size = (uint32_t)strlen(alias), .data = (uint8_t *)alias };
120    struct OH_Huks_ParamSet *testGenerateKeyParamSet = nullptr;
121    struct OH_Huks_Result ohResult;
122    do {
123        ohResult = InitParamSet(&testGenerateKeyParamSet, g_testGenerateKeyParam,
124        sizeof(g_testGenerateKeyParam) / sizeof(OH_Huks_Param));
125        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
126            break;
127        }
128        ohResult = OH_Huks_GenerateKeyItem(&aliasBlob, testGenerateKeyParamSet, nullptr);
129    } while (0);
130    OH_Huks_FreeParamSet(&testGenerateKeyParamSet);
131    napi_value ret;
132    napi_create_int32(env, ohResult.errorCode, &ret);
133    return ret;
134}
135```
136
137
138### Key Import
139
140A key generated outside the HUKS (for example, generated through key agreement or by a server) can be imported to the HUKS for management. The HUKS supports import of keys in plaintext. However, if a key is imported in plaintext, the key is exposed in the Rich Execution Environment (REE) memory. This type of import applies to lightweight devices or security-insensitive services. For security-sensitive services, use the secure import feature provided by the HUKS. Secure import allows the keys generated for services to be transferred to the HUKS through an end-to-end encrypted transmission channel.
141
142Once a key is imported to the HUKS, its plaintext will not be exposed outside the HUKS throughout the lifecycle of the key.
143
144#### Importing a Key in Plaintext
145
146Use [OH_Huks_ImportKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_importkeyitem) to import a key in plaintext. You need to pass in the key alias and **paramSetIn**, which must contain the key material and key property set.
147
1481. Set the key alias.
1492. Encapsulate the key material and key property set. The key material must comply with the HUKS key material formats (huks-appendix.md#key-material-formats) and assign a value to the key field. In addition, use [OH_Huks_InitParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_initparamset), [OH_Huks_AddParams](../reference/native-apis/_huks_param_set_api.md#oh_huks_addparams), and [OH_Huks_BuildParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_buildparamset) to construct **paramSet**, which must contain [OH_Huks_KeyAlg](../reference/native-apis/_huks_type_api.md#oh_huks_keyalg), [OH_Huks_KeySize](../reference/native-apis/_huks_type_api.md#oh_huks_keysize), and [OH_Huks_KeyPurpose](../reference/native-apis/_huks_type_api.md#oh_huks_keypurpose).
1503. Import the key.
151
152**C++ Code Example**
153
154```C++
155#include "huks/native_huks_api.h"
156#include "huks/native_huks_param.h"
157#include <string.h>
158OH_Huks_Result InitParamSet(
159    struct OH_Huks_ParamSet **paramSet,
160    const struct OH_Huks_Param *params,
161    uint32_t paramCount)
162{
163    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
164    if (ret.errorCode != OH_HUKS_SUCCESS) {
165        return ret;
166    }
167
168    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
169    if (ret.errorCode != OH_HUKS_SUCCESS) {
170        OH_Huks_FreeParamSet(paramSet);
171        return ret;
172    }
173
174    ret = OH_Huks_BuildParamSet(paramSet);
175    if (ret.errorCode != OH_HUKS_SUCCESS) {
176        OH_Huks_FreeParamSet(paramSet);
177        return ret;
178    }
179
180    return ret;
181}
182
183static napi_value ImportKey(napi_env env, napi_callback_info info)
184{
185    (void)GenerateKey(env, info);
186    const char *alias = "test_generate";
187    struct OH_Huks_Blob aliasBlob = { .size = (uint32_t)strlen(alias), .data = (uint8_t *)alias };
188    uint8_t pubKey[OH_HUKS_ECC_KEY_SIZE_256] = {0};
189    struct OH_Huks_Blob publicKey = { OH_HUKS_ECC_KEY_SIZE_256, pubKey };
190    struct OH_Huks_ParamSet *testImportKeyParamSet = nullptr;
191    struct OH_Huks_Result ohResult;
192    do {
193        ohResult = InitParamSet(&testImportKeyParamSet, g_testGenerateKeyParam,
194            sizeof(g_testGenerateKeyParam) / sizeof(OH_Huks_Param));
195        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
196            break;
197        }
198        ohResult = OH_Huks_ExportPublicKeyItem(&aliasBlob, testImportKeyParamSet, &publicKey);
199        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
200            break;
201        }
202        /* 4. Import Key */
203        char newKey[] = "test_import";
204        struct OH_Huks_Blob newKeyAlias = { .size = (uint32_t)strlen(newKey), .data = (uint8_t *)newKey };
205        ohResult = OH_Huks_ImportKeyItem(&newKeyAlias, testImportKeyParamSet, &publicKey);
206    } while (0);
207    OH_Huks_FreeParamSet(&testImportKeyParamSet);
208    napi_value ret;
209    napi_create_int32(env, ohResult.errorCode, &ret);
210    return ret;
211}
212```
213
214#### Importing a Wrapped Key
215
216Compared with import of a key in plaintext, the import of a wrapped key involves more complex key material and operations. The following figure illustrates the basic development process.
217
218**Figure 2** Development process for importing a wrapped key
219
220![huks_import_wrapped_key](figures/huks_import_wrapped_key.png)
221
222**Available APIs**
223
224During the development process, you need to use the APIs for key generation, export, import, and deletion in sequence.
225
226>**NOTE**<br>The public key plaintext material returned by **exportKeyItem()** is encapsulated in X.509 format, and the key material to be imported by **importWrappedKeyItem()** must be encapsulated in **Length<sub>Data</sub>-Data** format. Specifically, the application needs to encapsulate the wrapped key material in sequence according to the sequence in the following table.
227
228**Table 2** Format of the wrapped key material
229
230| **Content**| Public Key Length (L<sub>pk2</sub>)| Public Key (pk2)| k2 AAD Length (L<sub>AAD2</sub>)| k2 AAD (AAD2)|  k2 Nonce Length (L<sub>Nonce2</sub>)| k2 Nonce (Nonce2)|
231| :--: |:----:|:----: |:----: | :----:  | :----:|:----:|
232|Length| 4 bytes|L<sub>pk2</sub> bytes| 4 bytes| L<sub>AAD2</sub> bytes| 4 bytes| L<sub>Nonce2</sub> bytes|
233| **Content**| k2 AEAD Length (L<sub>AEAD2</sub>)| k2 AEAD (AEAD2)| k3 Ciphertext Length (L<sub>k3_enc</sub>)| k3 Ciphertext (k3_enc)|  k3 AAD Length (L<sub>AAD3</sub>)| k3 AAD (AAD3)|
234|Length| 4 bytes|L<sub>AEAD2</sub> bytes| 4 bytes| L<sub>k3_enc</sub> bytes| 4 bytes| L<sub>AAD3</sub> bytes|
235| Content| k3 Nonce Length (L<sub>Nonce3</sub>)| k3 Nonce (Nonce3)| k3 AEAD Length (L<sub>AEAD3</sub>)| k3 AEAD (AEAD3)|  Length of **k1'_size** (L<sub>k1'_size</sub>)| Key Plaintext Material Length (k1'_size)|
236|Length| 4 bytes|L<sub>Nonce3</sub> bytes| 4 bytes| L<sub>AEAD3</sub> bytes| 4 bytes| L<sub>k1'_size</sub> bytes|
237|Content|k1' Ciphertext Length L<sub>k1'_enc</sub>| k1' ciphertext k1'_enc| | | | |
238|Length| 4 bytes|L<sub>k1'_enc</sub> bytes| | | | |
239
240**How to Develop**
241
242The following example provides the development involving HUKS APIs (using the ECDH key agreement suite). The operations performed by the service are not included. In the following example, a key is imported from device A to device B.
243
2441. Convert the key to be imported from device A into the key material in HUKS format **To_Import_Key**.
2452. Generate an asymmetric key pair **Caller_Key** for device A.
2463. Generate an asymmetric key pair **Wrapping_Key**, with key purpose of **unwrap**, for device B.
2474. Generate a symmetric key **Caller_Kek** for device A.
2485. Export the public key material from the asymmetric key pairs of devices A and B.
2496. Use the private key of **Caller_Key** (device A) and the public key of **Wrapping_Key** (device B) to perform key agreement, and obtain an **Agree_Key**.
2507. Use the **Caller_Kek** to encrypt the **To_Import_Key** of device A and generate **To_Import_Key_Enc**.
2518. Use **Agree_Key** to encrypt the **Caller_Kek** of device A and generate **Caller_Kek_Enc**.
2529. Send the public key of **Caller_Key**, **Caller_Kek_Enc**, and **To_Import_Key_Enc** from device A to device B.
25310. Encapsulate and encrypt the key materials to be imported to device B.
25411. Import the encrypted key material to device B.
25512. Delete the keys, which are used for encrypting the key to import, from devices A and B.
256
257**C++ Code Example**
258
259```C++
260#include "napi/native_api.h"
261#include "huks/native_huks_api.h"
262#include "huks/native_huks_param.h"
263#include <algorithm>
264
265OH_Huks_Result InitParamSet(
266    struct OH_Huks_ParamSet **paramSet,
267    const struct OH_Huks_Param *params,
268    uint32_t paramCount)
269{
270    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
271    if (ret.errorCode != OH_HUKS_SUCCESS) {
272        return ret;
273    }
274
275    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
276    if (ret.errorCode != OH_HUKS_SUCCESS) {
277        OH_Huks_FreeParamSet(paramSet);
278        return ret;
279    }
280
281    ret = OH_Huks_BuildParamSet(paramSet);
282    if (ret.errorCode != OH_HUKS_SUCCESS) {
283        OH_Huks_FreeParamSet(paramSet);
284        return ret;
285    }
286
287    return ret;
288}
289
290/**
291 * Securely import a key from device A to the HUKS of device B.
292 * wrappingKey is a key pair of device B.
293 * callerKey is a key pair of device A.
294 * callerAgreeKey is generated through key agreement based on the private key of the key pair of device A and the public key of device B .
295 */
296struct HksImportWrappedKeyTestParams {
297    // server key, for real
298    struct OH_Huks_Blob *wrappingKeyAlias;
299    struct OH_Huks_ParamSet *genWrappingKeyParamSet;
300    uint32_t publicKeySize;
301
302    struct OH_Huks_Blob *callerKeyAlias;
303    struct OH_Huks_ParamSet *genCallerKeyParamSet;
304
305    struct OH_Huks_Blob *callerKekAlias;
306    struct OH_Huks_Blob *callerKek;
307    struct OH_Huks_ParamSet *importCallerKekParamSet;
308
309    struct OH_Huks_Blob *callerAgreeKeyAlias;
310    struct OH_Huks_ParamSet *agreeParamSet;
311
312    struct OH_Huks_ParamSet *importWrappedKeyParamSet;
313    struct OH_Huks_Blob *importedKeyAlias;
314    struct OH_Huks_Blob *importedPlainKey;
315    uint32_t keyMaterialLen;
316};
317
318static const uint32_t WRAPPED_KEY_IV_SIZE = 16;
319static uint8_t WRAPPED_KEY_IV[IV_SIZE] = "bababababababab";  // This is a test value. For real use, the IV should be different each time.
320
321static const uint32_t AAD_SIZE = 16;
322static uint8_t AAD[AAD_SIZE] = "abababababababa";  // This is a test value. For real use, the AAD should be different each time.
323
324static const uint32_t NONCE_SIZE = 12;
325static uint8_t NONCE[NONCE_SIZE] = "hahahahahah";  // This is a test value. For real use, the nonce should be different each time.
326
327static const uint32_t AEAD_TAG_SIZE = 16;
328
329static const uint32_t X25519_256_SIZE = 256;
330static struct OH_Huks_Blob g_wrappingKeyAliasAes256 = {
331    .size = (uint32_t)strlen("test_wrappingKey_x25519_aes256"),
332    .data = (uint8_t *)"test_wrappingKey_x25519_aes256"};
333
334static struct OH_Huks_Blob g_callerKeyAliasAes256 = {
335    .size = (uint32_t)strlen("test_caller_key_x25519_aes256"),
336    .data = (uint8_t *)"test_caller_key_x25519_aes256"};
337
338static struct OH_Huks_Blob g_callerKekAliasAes256 = {
339    .size = (uint32_t)strlen("test_caller_kek_x25519_aes256"),
340    .data = (uint8_t *)"test_caller_kek_x25519_aes256"};
341
342static struct OH_Huks_Blob g_callerAes256Kek = {
343    .size = (uint32_t)strlen("This is kek to encrypt plain key"),
344    .data = (uint8_t *)"This is kek to encrypt plain key"};
345
346static struct OH_Huks_Blob g_callerAgreeKeyAliasAes256 = {
347    .size = (uint32_t)strlen("test_caller_agree_key_x25519_aes256"),
348    .data = (uint8_t *)"test_caller_agree_key_x25519_aes256"};
349
350static struct OH_Huks_Blob g_importedKeyAliasAes256 = {
351    .size = (uint32_t)strlen("test_import_key_x25519_aes256"),
352    .data = (uint8_t *)"test_import_key_x25519_aes256"};
353
354static struct OH_Huks_Blob g_importedAes256PlainKey = {
355    .size = (uint32_t)strlen("This is plain key to be imported"),
356    .data = (uint8_t *)"This is plain key to be imported"};
357
358static struct OH_Huks_Param g_importWrappedAes256Params[] = {
359    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
360    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT | OH_HUKS_KEY_PURPOSE_DECRYPT},
361    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
362    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE},
363    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM},
364    {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE},
365    {.tag = OH_HUKS_TAG_UNWRAP_ALGORITHM_SUITE, .uint32Param = OH_HUKS_UNWRAP_SUITE_X25519_AES_256_GCM_NOPADDING},
366    {.tag = OH_HUKS_TAG_ASSOCIATED_DATA, .blob = {.size = AAD_SIZE, .data = (uint8_t *)AAD}}, // this is a test value, for real use the aad should be info associated with caller
367    {.tag = OH_HUKS_TAG_NONCE, .blob = {.size = NONCE_SIZE, .data = (uint8_t *)NONCE}}}; // this is a test value, for real use the nonce should be different every time
368
369static const uint32_t g_x25519PubKeySize = 32;
370
371static struct OH_Huks_Param g_genWrappingKeyParams[] = {
372    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519},
373    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_UNWRAP},
374    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}};
375
376static struct OH_Huks_Param g_genCallerX25519Params[] = {
377    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519},
378    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE},
379    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}};
380
381static struct OH_Huks_Param g_importParamsCallerKek[] = {
382    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
383    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT},
384    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
385    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE},
386    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM},
387    {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE},
388    {.tag = OH_HUKS_TAG_IV, .blob = {.size = WRAPPED_KEY_IV_SIZE, .data = (uint8_t *)WRAPPED_KEY_IV }}};  // this is a test value, for real use the iv should be different every time
389
390static struct OH_Huks_Param g_callerAgreeParams[] = {
391    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519},
392    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE},
393    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}
394};
395
396static struct OH_Huks_Param g_aesKekEncryptParams[] = {
397    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
398    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT},
399    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
400    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE},
401    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM},
402    {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE},
403    {.tag = OH_HUKS_TAG_ASSOCIATED_DATA, .blob = {.size = AAD_SIZE, .data = (uint8_t *)AAD}}, // this is a test value, for real use the aad should be info associated with caller
404    {.tag = OH_HUKS_TAG_NONCE, .blob = {.size = NONCE_SIZE, .data = (uint8_t *)NONCE}}}; // this is a test value, for real use the nonce should be different every time
405
406static struct OH_Huks_Param g_importAgreeKeyParams[] = {
407    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
408    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT},
409    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
410    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE},
411    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM},
412    {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE},
413    {.tag = OH_HUKS_TAG_IV, .blob = {.size = IV_SIZE, .data = (uint8_t *)IV}}};  // this is a test value, for real use the iv should be different every time
414
415OH_Huks_Result HuksAgreeKey(const struct OH_Huks_ParamSet *paramSet, const struct OH_Huks_Blob *keyAlias,
416                            const struct OH_Huks_Blob *peerPublicKey, struct OH_Huks_Blob *agreedKey)
417{
418    uint8_t temp[10] = {0};
419    struct OH_Huks_Blob inData = {
420        sizeof(temp),
421        temp};
422
423    uint8_t handleU[sizeof(uint64_t)] = {0};
424    struct OH_Huks_Blob handle = {sizeof(uint64_t), handleU};
425    OH_Huks_Result ret = OH_Huks_InitSession(keyAlias, paramSet, &handle, nullptr);
426    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
427        return ret;
428    }
429
430    uint8_t outDataU[1024] = {0};
431    struct OH_Huks_Blob outDataUpdate = {1024, outDataU};
432    ret = OH_Huks_UpdateSession(&handle, paramSet, peerPublicKey, &outDataUpdate);
433    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
434        return ret;
435    }
436
437    ret = OH_Huks_FinishSession(&handle, paramSet, &inData, agreedKey);
438    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
439        return ret;
440    }
441    return ret;
442}
443
444static const uint32_t TIMES = 4;
445static const uint32_t MAX_UPDATE_SIZE = 64;
446static const uint32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES;
447
448#define HUKS_FREE_BLOB(blob) do { \
449    if ((blob).data != nullptr) { \
450        free((blob).data); \
451        (blob).data = nullptr; \
452    } \
453    (blob).size = 0; \
454} while (0)
455
456#define OH_HUKS_KEY_BYTES(keySize) (((keySize) + 7) / 8)
457
458static OH_Huks_Result HksEncryptLoopUpdate(const struct OH_Huks_Blob *handle, const struct OH_Huks_ParamSet *paramSet,
459                                           const struct OH_Huks_Blob *inData, struct OH_Huks_Blob *outData)
460{
461    struct OH_Huks_Result ret;
462    ret.errorCode = OH_HUKS_SUCCESS;
463
464    struct OH_Huks_Blob inDataSeg = *inData;
465    uint8_t *lastPtr = inData->data + inData->size - 1;
466    struct OH_Huks_Blob outDataSeg = {MAX_OUTDATA_SIZE, NULL};
467    uint8_t *cur = outData->data;
468    outData->size = 0;
469
470    inDataSeg.size = MAX_UPDATE_SIZE;
471    bool isFinished = false;
472
473    while (inDataSeg.data <= lastPtr) {
474        if (inDataSeg.data + MAX_UPDATE_SIZE <= lastPtr)
475        {
476            outDataSeg.size = MAX_OUTDATA_SIZE;
477        }
478        else
479        {
480            isFinished = true;
481            inDataSeg.size = lastPtr - inDataSeg.data + 1;
482            break;
483        }
484        if (MallocAndCheckBlobData(&outDataSeg, outDataSeg.size).errorCode != (int32_t)OH_HUKS_SUCCESS)
485        {
486            ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
487            return ret;
488        }
489        ret = OH_Huks_UpdateSession(handle, paramSet, &inDataSeg, &outDataSeg);
490        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
491            free(outDataSeg.data);
492            return ret;
493        }
494        std::copy(outDataSeg.data, outDataSeg.data + outDataSeg.size, cur);
495        cur += outDataSeg.size;
496        outData->size += outDataSeg.size;
497        free(outDataSeg.data);
498        if ((isFinished == false) && (inDataSeg.data + MAX_UPDATE_SIZE > lastPtr)) {
499            ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
500            return ret;
501        }
502        inDataSeg.data += MAX_UPDATE_SIZE;
503    }
504
505    struct OH_Huks_Blob outDataFinish = {inDataSeg.size * TIMES, NULL};
506    if (MallocAndCheckBlobData(&outDataFinish, outDataFinish.size).errorCode != (int32_t)OH_HUKS_SUCCESS) {
507        ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
508        return ret;
509    }
510
511    ret = OH_Huks_FinishSession(handle, paramSet, &inDataSeg, &outDataFinish);
512    if (ret.errorCode != OH_HUKS_SUCCESS) {
513        free(outDataFinish.data);
514        return ret;
515    }
516    std::copy(outDataFinish.data, outDataFinish.data + outDataFinish.size, cur);
517    outData->size += outDataFinish.size;
518    free(outDataFinish.data);
519
520    return ret;
521}
522
523OH_Huks_Result HuksEncrypt(const struct OH_Huks_Blob *key, const struct OH_Huks_ParamSet *paramSet,
524                           const struct OH_Huks_Blob *plainText, struct OH_Huks_Blob *cipherText)
525{
526    uint8_t handle[sizeof(uint64_t)] = {0};
527    struct OH_Huks_Blob handleBlob = {sizeof(uint64_t), handle};
528    OH_Huks_Result ret = OH_Huks_InitSession(key, paramSet, &handleBlob, nullptr);
529    if (ret.errorCode != OH_HUKS_SUCCESS) {
530        return ret;
531    }
532
533    ret = HksEncryptLoopUpdate(&handleBlob, paramSet, plainText, cipherText);
534    return ret;
535}
536
537static OH_Huks_Result BuildWrappedKeyData(struct OH_Huks_Blob **blobArray, uint32_t size, struct OH_Huks_Blob *outData)
538{
539    uint32_t totalLength = size * sizeof(uint32_t);
540    struct OH_Huks_Result ret;
541    ret.errorCode = OH_HUKS_SUCCESS;
542
543    /* counter size */
544    for (uint32_t i = 0; i < size; ++i) {
545        totalLength += blobArray[i]->size;
546    }
547
548    struct OH_Huks_Blob outBlob = {0, nullptr};
549    outBlob.size = totalLength;
550    ret = MallocAndCheckBlobData(&outBlob, outBlob.size);
551    if (ret.errorCode != OH_HUKS_SUCCESS) {
552        return ret;
553    }
554
555    uint32_t offset = 0;
556
557    /* copy data */
558    for (uint32_t i = 0; i < size; ++i) {
559        if (totalLength - offset >= sizeof(blobArray[i]->size)) {
560            std::copy(reinterpret_cast<uint8_t *>(&blobArray[i]->size), reinterpret_cast<uint8_t *>(&blobArray[i]->size) + sizeof(blobArray[i]->size), outBlob.data + offset);
561        } else {
562            ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
563            return ret;
564        }
565
566        offset += sizeof(blobArray[i]->size);
567
568        if (totalLength - offset >= blobArray[i]->size) {
569            std::copy(blobArray[i]->data, blobArray[i]->data + blobArray[i]->size, outBlob.data + offset);
570        } else {
571            ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
572            return ret;
573        }
574
575        offset += blobArray[i]->size;
576    }
577
578    outData->size = outBlob.size;
579    outData->data = outBlob.data;
580    return ret;
581}
582
583static OH_Huks_Result CheckParamsValid(const struct HksImportWrappedKeyTestParams *params)
584{
585    struct OH_Huks_Result ret;
586    ret.errorCode = OH_HUKS_SUCCESS;
587    if (params == nullptr) {
588        ret.errorCode = OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT;
589        return ret;
590    }
591
592    if (params->wrappingKeyAlias == nullptr || params->genWrappingKeyParamSet == nullptr ||
593        params->callerKeyAlias == nullptr ||
594        params->genCallerKeyParamSet == nullptr || params->callerKekAlias == nullptr ||
595        params->callerKek == nullptr || params->importCallerKekParamSet == nullptr ||
596        params->callerAgreeKeyAlias == nullptr || params->agreeParamSet == nullptr ||
597        params->importWrappedKeyParamSet == nullptr || params->importedKeyAlias == nullptr ||
598        params->importedPlainKey == nullptr) {
599        ret.errorCode = OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT;
600        return ret;
601    }
602    return ret;
603}
604
605static OH_Huks_Result GenerateAndExportHuksPublicKey(const struct HksImportWrappedKeyTestParams *params,
606                                           struct OH_Huks_Blob *huksPublicKey)
607{
608    OH_Huks_Result ret = OH_Huks_GenerateKeyItem(params->wrappingKeyAlias, params->genWrappingKeyParamSet, nullptr);
609    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
610        return ret;
611    }
612    huksPublicKey->size = params->publicKeySize;
613    ret = MallocAndCheckBlobData(huksPublicKey, huksPublicKey->size);
614    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
615        return ret;
616    }
617    ret = OH_Huks_ExportPublicKeyItem(params->wrappingKeyAlias, nullptr, huksPublicKey);
618    return ret;
619}
620
621static OH_Huks_Result GenerateAndExportCallerPublicKey(const struct HksImportWrappedKeyTestParams *params,
622                                             struct OH_Huks_Blob *callerSelfPublicKey)
623{
624    OH_Huks_Result ret = OH_Huks_GenerateKeyItem(params->callerKeyAlias, params->genCallerKeyParamSet, nullptr);
625    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
626        return ret;
627    }
628
629    callerSelfPublicKey->size = params->publicKeySize;
630    ret = MallocAndCheckBlobData(callerSelfPublicKey, callerSelfPublicKey->size);
631    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
632        return ret;
633    }
634    ret = OH_Huks_ExportPublicKeyItem(params->callerKeyAlias, params->genWrappingKeyParamSet, callerSelfPublicKey);
635    return ret;
636}
637
638static OH_Huks_Result ImportKekAndAgreeSharedSecret(const struct HksImportWrappedKeyTestParams *params,
639                                          const struct OH_Huks_Blob *huksPublicKey, struct OH_Huks_Blob *outSharedKey)
640{
641    OH_Huks_Result ret = OH_Huks_ImportKeyItem(params->callerKekAlias,
642                                               params->importCallerKekParamSet, params->callerKek);
643    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
644        return ret;
645    }
646
647    ret = MallocAndCheckBlobData(outSharedKey, outSharedKey->size);
648    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
649        return ret;
650    }
651
652    ret = HuksAgreeKey(params->agreeParamSet, params->callerKeyAlias, huksPublicKey, outSharedKey);
653    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
654        return ret;
655    }
656    struct OH_Huks_ParamSet *importAgreeKeyParams = nullptr;
657    ret = InitParamSet(&importAgreeKeyParams, g_importAgreeKeyParams,
658                       sizeof(g_importAgreeKeyParams) / sizeof(OH_Huks_Param));
659    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
660        return ret;
661    }
662    ret = OH_Huks_ImportKeyItem(params->callerAgreeKeyAlias, importAgreeKeyParams, outSharedKey);
663
664    OH_Huks_FreeParamSet(&importAgreeKeyParams);
665    return ret;
666}
667
668static OH_Huks_Result EncryptImportedPlainKeyAndKek(const struct HksImportWrappedKeyTestParams *params,
669                                          struct OH_Huks_Blob *plainCipherText, struct OH_Huks_Blob *kekCipherText)
670{
671    struct OH_Huks_ParamSet *encryptParamSet = nullptr;
672    OH_Huks_Result ret = InitParamSet(&encryptParamSet, g_aesKekEncryptParams,
673                               sizeof(g_aesKekEncryptParams) / sizeof(OH_Huks_Param));
674    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
675        return ret;
676    }
677    ret = HuksEncrypt(params->callerKekAlias, encryptParamSet, params->importedPlainKey, plainCipherText);
678    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
679        return ret;
680    }
681
682    ret = HuksEncrypt(params->callerAgreeKeyAlias, encryptParamSet, params->callerKek, kekCipherText);
683    OH_Huks_FreeParamSet(&encryptParamSet);
684    return ret;
685}
686
687static OH_Huks_Result ImportWrappedKey(const struct HksImportWrappedKeyTestParams *params, struct OH_Huks_Blob *plainCipher,
688                             struct OH_Huks_Blob *kekCipherText, struct OH_Huks_Blob *peerPublicKey, struct OH_Huks_Blob *wrappedKeyData)
689{
690    struct OH_Huks_Blob commonAad = {.size = AAD_SIZE,
691                                     .data = reinterpret_cast<uint8_t *>(AAD)};
692    struct OH_Huks_Blob commonNonce = {.size = NONCE_SIZE,
693                                       .data = reinterpret_cast<uint8_t *>(NONCE)};
694    struct OH_Huks_Blob keyMaterialLen = {.size = sizeof(uint32_t), .data = (uint8_t *)&params->keyMaterialLen};
695
696    /* copy AEAD tag from cipher text and decrease its size */
697    const uint32_t tagSize = AEAD_TAG_SIZE;
698    uint8_t kekTagBuf[tagSize] = {0};
699    struct OH_Huks_Blob kekTag = {.size = tagSize, .data = kekTagBuf};
700
701    std::copy(plainCipher->data + (plainCipher->size - tagSize), plainCipher->data + (plainCipher->size - tagSize) + tagSize, kekTag.data);
702
703    plainCipher->size -= tagSize;
704
705    /* copy AEAD tag from kek cipher text and decrease its size */
706    uint8_t agreeKeyTagBuf[tagSize] = {0};
707    struct OH_Huks_Blob agreeKeyTag = {.size = tagSize, .data = agreeKeyTagBuf};
708    std::copy(kekCipherText->data + (kekCipherText->size - tagSize), kekCipherText->data + (kekCipherText->size - tagSize) + tagSize, agreeKeyTagBuf);
709
710    kekCipherText->size -= tagSize;
711
712    struct OH_Huks_Blob *blobArray[] = {peerPublicKey, &commonAad, &commonNonce, &agreeKeyTag, kekCipherText,
713                                        &commonAad, &commonNonce, &kekTag, &keyMaterialLen, plainCipher};
714    OH_Huks_Result ret = BuildWrappedKeyData(blobArray, OH_HUKS_IMPORT_WRAPPED_KEY_TOTAL_BLOBS, wrappedKeyData);
715    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
716        return ret;
717    }
718    struct OH_Huks_Param *purpose = nullptr;
719    ret = OH_Huks_GetParam(params->importWrappedKeyParamSet, OH_HUKS_TAG_PURPOSE, &purpose);
720    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
721        return ret;
722    }
723    ret = OH_Huks_ImportWrappedKeyItem(params->importedKeyAlias, params->wrappingKeyAlias,
724                              params->importWrappedKeyParamSet, wrappedKeyData);
725
726    return ret;
727}
728
729OH_Huks_Result HksImportWrappedKeyTestCommonCase(const struct HksImportWrappedKeyTestParams *params)
730{
731    OH_Huks_Result ret = CheckParamsValid(params);
732    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
733        return ret;
734    }
735
736    struct OH_Huks_Blob huksPublicKey = {0, nullptr};
737    struct OH_Huks_Blob callerSelfPublicKey = {0, nullptr};
738    struct OH_Huks_Blob outSharedKey = {.size = OH_HUKS_KEY_BYTES(OH_HUKS_AES_KEY_SIZE_256), .data = nullptr};
739    struct OH_Huks_Blob wrappedKeyData = {0, nullptr};
740    uint8_t plainKeyCipherBuffer[OH_HUKS_MAX_KEY_SIZE] = {0};
741    struct OH_Huks_Blob plainCipherText = {OH_HUKS_MAX_KEY_SIZE, plainKeyCipherBuffer};
742    uint8_t kekCipherTextBuffer[OH_HUKS_MAX_KEY_SIZE] = {0};
743    struct OH_Huks_Blob kekCipherText = {OH_HUKS_MAX_KEY_SIZE, kekCipherTextBuffer};
744    do {
745        /**
746         * Securely import a key from remote device A to local device B.
747         *
748         * 1. Prepare the key material to be imported on device A. In this example, g_importedAes256PlainKey is used as an example.
749         */
750
751         /**
752         * 2. Generate an asymmetric key pair Caller_Key for device A.
753         */
754        ret = GenerateAndExportCallerPublicKey(params, &callerSelfPublicKey);
755        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
756            break;
757        }
758
759         /**
760          * 3. Generate an asymmetric key pair Wrapping_Key with the key purpose of unwrap for device B.
761          */
762        ret = GenerateAndExportHuksPublicKey(params, &huksPublicKey);
763        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
764            break;
765        }
766
767         /**
768         * 4. Generate a symmetric key Caller_Kek for device A.
769         * 5. Export the public key material from the asymmetric key pairs of devices A and B. In this example, the public key is stored in callerSelfPublicKey and huksPublicKey as variables.
770         * 6. Devices A and B perform key agreement and obtain an Agree_Key based on the private key of the Caller_Key (device A) and the public key of Wrapping_Key (device B).
771         */
772        ret = ImportKekAndAgreeSharedSecret(params, &huksPublicKey, &outSharedKey);
773        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
774            break;
775        }
776
777        /**
778         * 7. Use Caller_Kek to encrypt To_Import_Key of device A and generate the To_Import_Key_Enc.
779         * 8. Use Agree_Key to encrypt Caller_Kek of device A and generate the Caller_Kek_Enc.
780         */
781        ret = EncryptImportedPlainKeyAndKek(params, &plainCipherText, &kekCipherText);
782        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
783            break;
784        }
785
786        /**
787         * 9. Send the public key of Caller_Key, Caller_Kek_Enc, and To_Import_Key_Enc from device A to device B. In this example, keys are stored in callerSelfPublicKey, plainCipherText, and kekCipherText as variables.
788         */
789
790        /**
791         * 10. Encapsulate and encrypt the key materials to be imported to device B.
792         * 11. Import the encrypted key material to device B.
793         * 12. Delete the keys, used for encrypting the key to import, from devices A and B.
794         */
795        ret = ImportWrappedKey(params, &plainCipherText, &kekCipherText, &callerSelfPublicKey, &wrappedKeyData);
796    } while (0);
797
798    HUKS_FREE_BLOB(huksPublicKey);
799    HUKS_FREE_BLOB(callerSelfPublicKey);
800    HUKS_FREE_BLOB(outSharedKey);
801    HUKS_FREE_BLOB(wrappedKeyData);
802    return ret;
803}
804
805void HksClearKeysForWrappedKeyTest(const struct HksImportWrappedKeyTestParams *params)
806{
807    OH_Huks_Result ret = CheckParamsValid(params);
808    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
809        return;
810    }
811    (void)OH_Huks_DeleteKeyItem(params->wrappingKeyAlias, nullptr);
812    (void)OH_Huks_DeleteKeyItem(params->callerKeyAlias, nullptr);
813    (void)OH_Huks_DeleteKeyItem(params->callerKekAlias, nullptr);
814    (void)OH_Huks_DeleteKeyItem(params->callerAgreeKeyAlias, nullptr);
815    (void)OH_Huks_DeleteKeyItem(params->importedKeyAlias, nullptr);
816}
817
818static OH_Huks_Result InitCommonTestParamsAndDoImport(
819    struct HksImportWrappedKeyTestParams *importWrappedKeyTestParams,
820    const struct OH_Huks_Param *importedKeyParamSetArray,
821    uint32_t arraySize)
822{
823    struct OH_Huks_ParamSet *genX25519KeyParamSet = nullptr;
824    struct OH_Huks_ParamSet *genCallerKeyParamSet = nullptr;
825    struct OH_Huks_ParamSet *callerImportParamsKek = nullptr;
826    struct OH_Huks_ParamSet *agreeParamSet = nullptr;
827    struct OH_Huks_ParamSet *importPlainKeyParams = nullptr;
828
829    OH_Huks_Result ret;
830    do {
831        ret = InitParamSet(&genX25519KeyParamSet, g_genWrappingKeyParams,
832                               sizeof(g_genWrappingKeyParams) / sizeof(OH_Huks_Param));
833        if (ret.errorCode != OH_HUKS_SUCCESS) {
834            break;
835        }
836        importWrappedKeyTestParams->genWrappingKeyParamSet = genX25519KeyParamSet;
837        importWrappedKeyTestParams->publicKeySize = g_x25519PubKeySize;
838
839        ret = InitParamSet(&genCallerKeyParamSet, g_genCallerX25519Params,
840                           sizeof(g_genCallerX25519Params) / sizeof(OH_Huks_Param));
841        if (ret.errorCode != OH_HUKS_SUCCESS) {
842            break;
843        }
844        importWrappedKeyTestParams->genCallerKeyParamSet = genCallerKeyParamSet;
845
846        ret = InitParamSet(&callerImportParamsKek, g_importParamsCallerKek,
847                           sizeof(g_importParamsCallerKek) / sizeof(OH_Huks_Param));
848        if (ret.errorCode != OH_HUKS_SUCCESS) {
849            break;
850        }
851        importWrappedKeyTestParams->importCallerKekParamSet = callerImportParamsKek;
852
853        ret = InitParamSet(&agreeParamSet, g_callerAgreeParams,
854                           sizeof(g_callerAgreeParams) / sizeof(OH_Huks_Param));
855        if (ret.errorCode != OH_HUKS_SUCCESS) {
856            break;
857        }
858        importWrappedKeyTestParams->agreeParamSet = agreeParamSet;
859
860        ret = InitParamSet(&importPlainKeyParams, importedKeyParamSetArray, arraySize);
861        if (ret.errorCode != OH_HUKS_SUCCESS) {
862            break;
863        }
864        importWrappedKeyTestParams->importWrappedKeyParamSet = importPlainKeyParams;
865
866        ret = HksImportWrappedKeyTestCommonCase(importWrappedKeyTestParams);
867    } while (0);
868
869    OH_Huks_FreeParamSet(&genX25519KeyParamSet);
870    OH_Huks_FreeParamSet(&genCallerKeyParamSet);
871    OH_Huks_FreeParamSet(&callerImportParamsKek);
872    OH_Huks_FreeParamSet(&agreeParamSet);
873    OH_Huks_FreeParamSet(&importPlainKeyParams);
874    return ret;
875}
876
877static napi_value ImportWrappedKey(napi_env env, napi_callback_info info)
878{
879    struct HksImportWrappedKeyTestParams importWrappedKeyTestParams001 = {0};
880
881    importWrappedKeyTestParams001.wrappingKeyAlias = &g_wrappingKeyAliasAes256;
882    importWrappedKeyTestParams001.keyMaterialLen = g_importedAes256PlainKey.size;
883    importWrappedKeyTestParams001.callerKeyAlias = &g_callerKeyAliasAes256;
884    importWrappedKeyTestParams001.callerKekAlias = &g_callerKekAliasAes256;
885    importWrappedKeyTestParams001.callerKek = &g_callerAes256Kek;
886    importWrappedKeyTestParams001.callerAgreeKeyAlias = &g_callerAgreeKeyAliasAes256;
887    importWrappedKeyTestParams001.importedKeyAlias = &g_importedKeyAliasAes256;
888    importWrappedKeyTestParams001.importedPlainKey = &g_importedAes256PlainKey;
889    OH_Huks_Result ohResult = InitCommonTestParamsAndDoImport(&importWrappedKeyTestParams001, g_importWrappedAes256Params,
890                                   sizeof(g_importWrappedAes256Params) / sizeof(struct OH_Huks_Param));
891    HksClearKeysForWrappedKeyTest(&importWrappedKeyTestParams001);
892
893    napi_value ret;
894    napi_create_int32(env, ohResult.errorCode, &ret);
895    return ret;
896}
897```
898
899### Common Key Operations
900
901**Scenarios**
902
903To ensure data confidentiality and integrity, you may need to encrypt or decrypt data, generate or verify a signature, perform key agreement, and derive a key. The following describes common key operations.
904
905**General Development Process**
906
907The HUKS operates data based on key sessions. The general process is as follows:
908
9091. Initialize a key session using [OH_Huks_InitSession](../reference/native-apis/_huks_key_api.md#oh_huks_initsession).<br>You need to pass in the key alias and key operation parameters. After the initialization, a session handle is returned. The key operation parameters must contain the parameters required by the cipher algorithm, including the cipher algorithm, key size, key purpose, working mode, padding mode, hash mode, IV, nonce, and AAD.
9102. Update data by segment using [OH_Huks_UpdateSession](../reference/native-apis/_huks_key_api.md#oh_huks_updatesession) to pass in data by segment.<br>In key agreement, key derivation, and signature verification, you need to use this API to perform algorithm operations. In other cases, for example, the data exceeds 100 KB or the cryptographic algorithm requires data operations by segment, you can use this API to pass in data by segment.
9113. Finish the key session using [OH_Huks_FinishSession](../reference/native-apis/_huks_key_api.md#oh_huks_finishsession).<br>Operate the last segment of data and end the key session. If an error occurs during this process or the key operation data is not required, use [OH_Huks_AbortSession](../reference/native-apis/_huks_key_api.md#oh_huks_abortsession) to abort the session. This step is mandatory.
912
913#### Encryption and Decryption
914
915**C++ Code Example**
916
917```C++
918#include "huks/native_huks_api.h"
919#include "huks/native_huks_param.h"
920#include <string.h>
921OH_Huks_Result InitParamSet(
922    struct OH_Huks_ParamSet **paramSet,
923    const struct OH_Huks_Param *params,
924    uint32_t paramCount)
925{
926    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
927    if (ret.errorCode != OH_HUKS_SUCCESS) {
928        return ret;
929    }
930
931    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
932    if (ret.errorCode != OH_HUKS_SUCCESS) {
933        OH_Huks_FreeParamSet(paramSet);
934        return ret;
935    }
936
937    ret = OH_Huks_BuildParamSet(paramSet);
938    if (ret.errorCode != OH_HUKS_SUCCESS) {
939        OH_Huks_FreeParamSet(paramSet);
940        return ret;
941    }
942
943    return ret;
944}
945
946static const uint32_t IV_SIZE = 16;
947static uint8_t IV[IV_SIZE] = { 0 }; // this is a test value, for real use the iv should be different every time
948
949static struct OH_Huks_Param g_genEncDecParams[] = {
950    {
951        .tag = OH_HUKS_TAG_ALGORITHM,
952        .uint32Param = OH_HUKS_ALG_AES
953    }, {
954        .tag = OH_HUKS_TAG_PURPOSE,
955        .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT | OH_HUKS_KEY_PURPOSE_DECRYPT
956    }, {
957        .tag = OH_HUKS_TAG_KEY_SIZE,
958        .uint32Param = OH_HUKS_AES_KEY_SIZE_256
959    }, {
960        .tag = OH_HUKS_TAG_PADDING,
961        .uint32Param = OH_HUKS_PADDING_NONE
962    }, {
963        .tag = OH_HUKS_TAG_BLOCK_MODE,
964        .uint32Param = OH_HUKS_MODE_CBC
965    }
966};
967
968static struct OH_Huks_Param g_encryptParams[] = {
969    {
970        .tag = OH_HUKS_TAG_ALGORITHM,
971        .uint32Param = OH_HUKS_ALG_AES
972    }, {
973        .tag = OH_HUKS_TAG_PURPOSE,
974        .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT
975    }, {
976        .tag = OH_HUKS_TAG_KEY_SIZE,
977        .uint32Param = OH_HUKS_AES_KEY_SIZE_256
978    }, {
979        .tag = OH_HUKS_TAG_PADDING,
980        .uint32Param = OH_HUKS_PADDING_NONE
981    }, {
982        .tag = OH_HUKS_TAG_BLOCK_MODE,
983        .uint32Param = OH_HUKS_MODE_CBC
984    }, {
985        .tag = OH_HUKS_TAG_IV,
986        .blob = {
987            .size = IV_SIZE,
988            .data = (uint8_t *)IV // this is a test value, for real use the iv should be different every time
989        }
990    }
991};
992
993static struct OH_Huks_Param g_decryptParams[] = {
994    {
995        .tag = OH_HUKS_TAG_ALGORITHM,
996        .uint32Param = OH_HUKS_ALG_AES
997    }, {
998        .tag = OH_HUKS_TAG_PURPOSE,
999        .uint32Param = OH_HUKS_KEY_PURPOSE_DECRYPT
1000    }, {
1001        .tag = OH_HUKS_TAG_KEY_SIZE,
1002        .uint32Param = OH_HUKS_AES_KEY_SIZE_256
1003    }, {
1004        .tag = OH_HUKS_TAG_PADDING,
1005        .uint32Param = OH_HUKS_PADDING_NONE
1006    }, {
1007        .tag = OH_HUKS_TAG_BLOCK_MODE,
1008        .uint32Param = OH_HUKS_MODE_CBC
1009    }, {
1010        .tag = OH_HUKS_TAG_IV,
1011        .blob = {
1012            .size = IV_SIZE,
1013            .data = (uint8_t *)IV // this is a test value, for real use the iv should be different every time
1014        }
1015    }
1016};
1017
1018static const uint32_t AES_COMMON_SIZE = 1024;
1019
1020OH_Huks_Result HksAesCipherTestEncrypt(
1021        const struct OH_Huks_Blob *keyAlias,
1022        const struct OH_Huks_ParamSet *encryptParamSet, const struct OH_Huks_Blob *inData, struct OH_Huks_Blob *cipherText)
1023{
1024    uint8_t handleE[sizeof(uint64_t)] = {0};
1025    struct OH_Huks_Blob handleEncrypt = {sizeof(uint64_t), handleE};
1026    OH_Huks_Result ret = OH_Huks_InitSession(keyAlias, encryptParamSet, &handleEncrypt, nullptr);
1027    if (ret.errorCode != OH_HUKS_SUCCESS) {
1028        return ret;
1029    }
1030
1031    ret = OH_Huks_FinishSession(&handleEncrypt, encryptParamSet, inData, cipherText);
1032
1033    return ret;
1034}
1035
1036OH_Huks_Result HksAesCipherTestDecrypt(
1037    const struct OH_Huks_Blob *keyAlias,
1038    const struct OH_Huks_ParamSet *decryptParamSet, const struct OH_Huks_Blob *cipherText, struct OH_Huks_Blob *plainText,
1039    const struct OH_Huks_Blob *inData)
1040{
1041    uint8_t handleD[sizeof(uint64_t)] = {0};
1042    struct OH_Huks_Blob handleDecrypt = {sizeof(uint64_t), handleD};
1043    OH_Huks_Result ret = OH_Huks_InitSession(keyAlias, decryptParamSet, &handleDecrypt, nullptr);
1044    if (ret.errorCode != OH_HUKS_SUCCESS) {
1045        return ret;
1046    }
1047
1048    ret = OH_Huks_FinishSession(&handleDecrypt, decryptParamSet, cipherText, plainText);
1049
1050    return ret;
1051}
1052
1053static napi_value EncDecKey(napi_env env, napi_callback_info info)
1054{
1055    char tmpKeyAlias[] = "test_enc_dec";
1056    struct OH_Huks_Blob keyAlias = { (uint32_t)strlen(tmpKeyAlias), (uint8_t *)tmpKeyAlias };
1057    struct OH_Huks_ParamSet *genParamSet = nullptr;
1058    struct OH_Huks_ParamSet *encryptParamSet = nullptr;
1059    struct OH_Huks_ParamSet *decryptParamSet = nullptr;
1060    OH_Huks_Result ohResult;
1061    do {
1062        ohResult = InitParamSet(&genParamSet, g_genEncDecParams, sizeof(g_genEncDecParams) / sizeof(OH_Huks_Param));
1063        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1064            break;
1065        }
1066        ohResult = InitParamSet(&encryptParamSet, g_encryptParams, sizeof(g_encryptParams) / sizeof(OH_Huks_Param));
1067        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1068            break;
1069        }
1070        ohResult = InitParamSet(&decryptParamSet, g_decryptParams, sizeof(g_decryptParams) / sizeof(OH_Huks_Param));
1071        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1072            break;
1073        }
1074        char tmpInData[] = "AES_ECB_INDATA_1";
1075        struct OH_Huks_Blob inData = { (uint32_t)strlen(tmpInData), (uint8_t *)tmpInData };
1076        /* 1. Generate a key. */
1077        ohResult = OH_Huks_GenerateKeyItem(&keyAlias, genParamSet, nullptr);
1078        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1079            break;
1080        }
1081        /* 2. Encrypt data using a key. */
1082        uint8_t cipher[AES_COMMON_SIZE] = {0};
1083        struct OH_Huks_Blob cipherText = {AES_COMMON_SIZE, cipher};
1084        ohResult = HksAesCipherTestEncrypt(&keyAlias, encryptParamSet, &inData, &cipherText);
1085        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1086            break;
1087        }
1088
1089        /* 3. Decrypt data using a key. */
1090        uint8_t plain[AES_COMMON_SIZE] = {0};
1091        struct OH_Huks_Blob plainText = {AES_COMMON_SIZE, plain};
1092        ohResult = HksAesCipherTestDecrypt(&keyAlias, decryptParamSet, &cipherText, &plainText, &inData);
1093    } while (0);
1094    /* 4. Delete a key. */
1095    (void)OH_Huks_DeleteKeyItem(&keyAlias, genParamSet);
1096
1097    OH_Huks_FreeParamSet(&genParamSet);
1098    OH_Huks_FreeParamSet(&encryptParamSet);
1099    OH_Huks_FreeParamSet(&decryptParamSet);
1100
1101    napi_value ret;
1102    napi_create_int32(env, ohResult.errorCode, &ret);
1103    return ret;
1104}
1105```
1106
1107#### Signing and Signature Verification
1108
1109**C++ Code Example**
1110
1111```C++
1112#include "huks/native_huks_api.h"
1113#include "huks/native_huks_param.h"
1114#include <string.h>
1115OH_Huks_Result InitParamSet(
1116    struct OH_Huks_ParamSet **paramSet,
1117    const struct OH_Huks_Param *params,
1118    uint32_t paramCount)
1119{
1120    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
1121    if (ret.errorCode != OH_HUKS_SUCCESS) {
1122        return ret;
1123    }
1124
1125    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
1126    if (ret.errorCode != OH_HUKS_SUCCESS) {
1127        OH_Huks_FreeParamSet(paramSet);
1128        return ret;
1129    }
1130
1131    ret = OH_Huks_BuildParamSet(paramSet);
1132    if (ret.errorCode != OH_HUKS_SUCCESS) {
1133        OH_Huks_FreeParamSet(paramSet);
1134        return ret;
1135    }
1136
1137    return ret;
1138}
1139
1140static struct OH_Huks_Param g_genSignVerifyParamsTest[] = {
1141    {
1142        .tag = OH_HUKS_TAG_ALGORITHM,
1143        .uint32Param = OH_HUKS_ALG_RSA
1144    }, {
1145        .tag = OH_HUKS_TAG_PURPOSE,
1146        .uint32Param = OH_HUKS_KEY_PURPOSE_SIGN | OH_HUKS_KEY_PURPOSE_VERIFY
1147    }, {
1148        .tag = OH_HUKS_TAG_KEY_SIZE,
1149        .uint32Param = OH_HUKS_RSA_KEY_SIZE_2048
1150    }, {
1151        .tag = OH_HUKS_TAG_PADDING,
1152        .uint32Param = OH_HUKS_PADDING_PSS
1153    }, {
1154        .tag = OH_HUKS_TAG_DIGEST,
1155        .uint32Param = OH_HUKS_DIGEST_SHA384
1156    },
1157};
1158
1159static struct OH_Huks_Param g_signParamsTest[] = {
1160    {
1161        .tag = OH_HUKS_TAG_ALGORITHM,
1162        .uint32Param = OH_HUKS_ALG_RSA
1163    }, {
1164        .tag = OH_HUKS_TAG_PURPOSE,
1165        .uint32Param = OH_HUKS_KEY_PURPOSE_SIGN
1166    }, {
1167        .tag = OH_HUKS_TAG_KEY_SIZE,
1168        .uint32Param = OH_HUKS_RSA_KEY_SIZE_2048
1169    }, {
1170        .tag = OH_HUKS_TAG_PADDING,
1171        .uint32Param = OH_HUKS_PADDING_PSS
1172    }, {
1173        .tag = OH_HUKS_TAG_DIGEST,
1174        .uint32Param = OH_HUKS_DIGEST_SHA384
1175    }
1176};
1177
1178static struct OH_Huks_Param g_verifyParamsTest[] = {
1179    {
1180        .tag = OH_HUKS_TAG_ALGORITHM,
1181        .uint32Param = OH_HUKS_ALG_RSA
1182    }, {
1183        .tag = OH_HUKS_TAG_PURPOSE,
1184        .uint32Param = OH_HUKS_KEY_PURPOSE_VERIFY
1185    }, {
1186        .tag = OH_HUKS_TAG_KEY_SIZE,
1187        .uint32Param = OH_HUKS_RSA_KEY_SIZE_2048
1188    }, {
1189        .tag = OH_HUKS_TAG_PADDING,
1190        .uint32Param = OH_HUKS_PADDING_PSS
1191    }, {
1192        .tag = OH_HUKS_TAG_DIGEST,
1193        .uint32Param = OH_HUKS_DIGEST_SHA384
1194    }
1195};
1196
1197static const uint32_t RSA_COMMON_SIZE = 1024;
1198static const char *g_dataToSign = "Hks_RSA_Sign_Verify_Test_0000000000000000000000000000000000000000000000000000000"
1199                                    "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
1200                                    "0000000000000000000000000000000000000000000000000000000000000000000000000_string";
1201
1202static napi_value SignVerifyKey(napi_env env, napi_callback_info info)
1203{
1204    struct OH_Huks_Blob g_keyAlias = {
1205        (uint32_t)strlen("test_signVerify"),
1206        (uint8_t *)"test_signVerify"
1207    };
1208    struct OH_Huks_Blob inData = {
1209        (uint32_t)strlen(g_dataToSign),
1210        (uint8_t *)g_dataToSign
1211    };
1212    struct OH_Huks_ParamSet *genParamSet = nullptr;
1213    struct OH_Huks_ParamSet *signParamSet = nullptr;
1214    struct OH_Huks_ParamSet *verifyParamSet = nullptr;
1215    OH_Huks_Result ohResult;
1216    do {
1217        ohResult = InitParamSet(&genParamSet, g_genSignVerifyParamsTest, sizeof(g_genSignVerifyParamsTest) / sizeof(OH_Huks_Param));
1218        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1219            break;
1220        }
1221        ohResult = InitParamSet(&signParamSet, g_signParamsTest, sizeof(g_signParamsTest) / sizeof(OH_Huks_Param));
1222        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1223            break;
1224        }
1225        ohResult = InitParamSet(&verifyParamSet, g_verifyParamsTest, sizeof(g_verifyParamsTest) / sizeof(OH_Huks_Param));
1226        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1227            break;
1228        }
1229        /* 1. Generate a key. */
1230        ohResult = OH_Huks_GenerateKeyItem(&g_keyAlias, genParamSet, nullptr);
1231        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1232            break;
1233        }
1234        /* 2. Generate a signature. */
1235        // Init
1236        uint8_t handleS[sizeof(uint64_t)] = {0};
1237        struct OH_Huks_Blob handleSign = { (uint32_t)sizeof(uint64_t), handleS };
1238        ohResult = OH_Huks_InitSession(&g_keyAlias, signParamSet, &handleSign, nullptr);
1239
1240        // Update
1241        uint8_t outDataS[RSA_COMMON_SIZE] = {0};
1242        struct OH_Huks_Blob outDataSign = { RSA_COMMON_SIZE, outDataS };
1243
1244        ohResult = OH_Huks_UpdateSession(&handleSign, signParamSet,  &inData, &outDataSign);
1245        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1246            break;
1247        }
1248
1249        // Finish
1250        struct OH_Huks_Blob finishInData = { 0, NULL };
1251        ohResult = OH_Huks_FinishSession(&handleSign, signParamSet, &finishInData, &outDataSign);
1252
1253        /* 3. Verify a signature. */
1254        // Init
1255        uint8_t handleV[sizeof(uint64_t)] = {0};
1256        struct OH_Huks_Blob handleVerify = { (uint32_t)sizeof(uint64_t), handleV };
1257        ohResult = OH_Huks_InitSession(&g_keyAlias, verifyParamSet, &handleVerify, nullptr);
1258        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1259            break;
1260        }
1261        // Update loop
1262        uint8_t temp[] = "out";
1263        struct OH_Huks_Blob verifyOut = { (uint32_t)sizeof(temp), temp };
1264        ohResult = OH_Huks_UpdateSession(&handleVerify, verifyParamSet, &inData, &verifyOut);
1265        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1266            break;
1267        }
1268        // Finish
1269        ohResult = OH_Huks_FinishSession(&handleVerify, verifyParamSet, &outDataSign, &verifyOut);
1270        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1271            break;
1272        }
1273    } while (0);
1274    (void)OH_Huks_DeleteKeyItem(&g_keyAlias, genParamSet);
1275    OH_Huks_FreeParamSet(&genParamSet);
1276    OH_Huks_FreeParamSet(&signParamSet);
1277    OH_Huks_FreeParamSet(&verifyParamSet);
1278
1279    napi_value ret;
1280    napi_create_int32(env, ohResult.errorCode, &ret);
1281    return ret;
1282}
1283```
1284
1285#### Key Agreement
1286
1287You are advised to pass in [HuksKeyStorageType](../reference/apis/js-apis-huks.md#hukskeystoragetype) to specify the storage type in key agreement. From API version 10, only **HUKS_STORAGE_ONLY_USED_IN_HUKS** or **HUKS_STORAGE_KEY_EXPORT_ALLOWED** can be used. If **HuksKeyStorageType** is not passed in, the key can be stored or exported by default, which poses security risks.
1288
1289**C++ Code Example**
1290
1291```C++
1292#include "huks/native_huks_api.h"
1293#include "huks/native_huks_param.h"
1294#include <string.h>
1295OH_Huks_Result InitParamSet(
1296    struct OH_Huks_ParamSet **paramSet,
1297    const struct OH_Huks_Param *params,
1298    uint32_t paramCount)
1299{
1300    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
1301    if (ret.errorCode != OH_HUKS_SUCCESS) {
1302        return ret;
1303    }
1304
1305    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
1306    if (ret.errorCode != OH_HUKS_SUCCESS) {
1307        OH_Huks_FreeParamSet(paramSet);
1308        return ret;
1309    }
1310
1311    ret = OH_Huks_BuildParamSet(paramSet);
1312    if (ret.errorCode != OH_HUKS_SUCCESS) {
1313        OH_Huks_FreeParamSet(paramSet);
1314        return ret;
1315    }
1316
1317    return ret;
1318}
1319
1320static const uint32_t IV_SIZE = 16;
1321static uint8_t IV[IV_SIZE] = { 0 }; // this is a test value, for real use the iv should be different every time
1322
1323static struct OH_Huks_Blob g_keyAliasFinal1001 = {
1324    (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_1_final"),
1325    (uint8_t *)"HksECDHAgreeKeyAliasTest001_1_final"
1326};
1327
1328static struct OH_Huks_Param g_genAgreeParams[] = {
1329    {
1330        .tag = OH_HUKS_TAG_ALGORITHM,
1331        .uint32Param = OH_HUKS_ALG_ECC
1332    }, {
1333        .tag = OH_HUKS_TAG_PURPOSE,
1334        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
1335    }, {
1336        .tag = OH_HUKS_TAG_KEY_SIZE,
1337        .uint32Param = OH_HUKS_ECC_KEY_SIZE_256
1338    }, {
1339        .tag = OH_HUKS_TAG_DIGEST,
1340        .uint32Param = OH_HUKS_DIGEST_NONE
1341    }
1342};
1343
1344static struct OH_Huks_Param g_agreeParamsInit01[] = {
1345    {
1346        .tag = OH_HUKS_TAG_ALGORITHM,
1347        .uint32Param = OH_HUKS_ALG_ECDH
1348    }, {
1349        .tag = OH_HUKS_TAG_PURPOSE,
1350        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
1351    }, {
1352        .tag = OH_HUKS_TAG_KEY_SIZE,
1353        .uint32Param = OH_HUKS_ECC_KEY_SIZE_256
1354    }
1355};
1356
1357static struct OH_Huks_Param g_agreeParamsFinish01[] = {
1358    {
1359        .tag = OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
1360        .uint32Param = OH_HUKS_STORAGE_ONLY_USED_IN_HUKS
1361    }, {
1362        .tag = OH_HUKS_TAG_ALGORITHM,
1363        .uint32Param = OH_HUKS_ALG_AES
1364    }, {
1365        .tag = OH_HUKS_TAG_KEY_SIZE,
1366        .uint32Param = OH_HUKS_AES_KEY_SIZE_256
1367    }, {
1368        .tag = OH_HUKS_TAG_PURPOSE,
1369        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
1370    }, {
1371        .tag = OH_HUKS_TAG_KEY_ALIAS,
1372        .blob = g_keyAliasFinal1001
1373    }, {
1374        .tag = OH_HUKS_TAG_PADDING,
1375        .uint32Param = OH_HUKS_PADDING_NONE
1376    }, {
1377        .tag = OH_HUKS_TAG_BLOCK_MODE,
1378        .uint32Param = OH_HUKS_MODE_CBC
1379    }
1380};
1381
1382static struct OH_Huks_Blob g_keyAliasFinal2001 = {
1383    (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_2_final"),
1384    (uint8_t *)"HksECDHAgreeKeyAliasTest001_2_final"
1385};
1386
1387static struct OH_Huks_Param g_agreeParamsInit02[] = {
1388    {
1389        .tag = OH_HUKS_TAG_ALGORITHM,
1390        .uint32Param = OH_HUKS_ALG_ECDH
1391    }, {
1392        .tag = OH_HUKS_TAG_PURPOSE,
1393        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
1394    }, {
1395        .tag = OH_HUKS_TAG_KEY_SIZE,
1396        .uint32Param = OH_HUKS_ECC_KEY_SIZE_256
1397    }
1398};
1399
1400static struct OH_Huks_Param g_agreeParamsFinish02[] = {
1401    {
1402        .tag = OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
1403        .uint32Param = OH_HUKS_STORAGE_ONLY_USED_IN_HUKS
1404    }, {
1405        .tag = OH_HUKS_TAG_ALGORITHM,
1406        .uint32Param = OH_HUKS_ALG_AES
1407    }, {
1408        .tag = OH_HUKS_TAG_KEY_SIZE,
1409        .uint32Param = OH_HUKS_AES_KEY_SIZE_256
1410    }, {
1411        .tag = OH_HUKS_TAG_PURPOSE,
1412        .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE
1413    }, {
1414        .tag = OH_HUKS_TAG_KEY_ALIAS,
1415        .blob = g_keyAliasFinal2001
1416    }, {
1417        .tag = OH_HUKS_TAG_PADDING,
1418        .uint32Param = OH_HUKS_PADDING_NONE
1419    }, {
1420        .tag = OH_HUKS_TAG_BLOCK_MODE,
1421        .uint32Param = OH_HUKS_MODE_CBC
1422    }
1423};
1424
1425static const uint32_t ECDH_COMMON_SIZE = 1024;
1426
1427static struct OH_Huks_Blob g_keyAlias01001 = {
1428    (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_1"),
1429    (uint8_t *)"HksECDHAgreeKeyAliasTest001_1"
1430};
1431
1432static struct OH_Huks_Blob g_keyAlias02001 = {
1433    (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_2"),
1434    (uint8_t *)"HksECDHAgreeKeyAliasTest001_2"
1435};
1436
1437OH_Huks_Result MallocAndCheckBlobData(
1438    struct OH_Huks_Blob *blob,
1439    const uint32_t blobSize)
1440{
1441    struct OH_Huks_Result ret;
1442    ret.errorCode = OH_HUKS_SUCCESS;
1443
1444    blob->data = (uint8_t *)malloc(blobSize);
1445    if (blob->data == NULL) {
1446        ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
1447    }
1448
1449    return ret;
1450}
1451
1452OH_Huks_Result HksEcdhAgreeExport(const struct OH_Huks_Blob *keyAlias1, const struct OH_Huks_Blob *keyAlias2,
1453    struct OH_Huks_Blob *publicKey1, struct OH_Huks_Blob *publicKey2, const struct OH_Huks_ParamSet *genParamSet)
1454{
1455    OH_Huks_Result ret = OH_Huks_ExportPublicKeyItem(keyAlias1, genParamSet, publicKey1);
1456    if (ret.errorCode != OH_HUKS_SUCCESS) {
1457        return ret;
1458    }
1459    ret = OH_Huks_ExportPublicKeyItem(keyAlias2, genParamSet, publicKey2);
1460    if (ret.errorCode != OH_HUKS_SUCCESS) {
1461        return ret;
1462    }
1463    return ret;
1464}
1465
1466static const char *g_inData = "Hks_ECDH_Agree_Test_000000000000000000000000000000000000000000000000000000000000"
1467                                    "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
1468                                    "0000000000000000000000000000000000000000000000000000000000000000000000000_string";
1469
1470OH_Huks_Result HksEcdhAgreeFinish(const struct OH_Huks_Blob *keyAlias, const struct OH_Huks_Blob *publicKey,
1471    const struct OH_Huks_ParamSet *initParamSet, const struct OH_Huks_ParamSet *finishParamSet, struct OH_Huks_Blob *outData)
1472{
1473    struct OH_Huks_Blob inData = {
1474        (uint32_t)strlen(g_inData),
1475        (uint8_t *)g_inData
1476    };
1477
1478    uint8_t handleU[sizeof(uint64_t)] = {0};
1479    struct OH_Huks_Blob handle = { sizeof(uint64_t), handleU };
1480    OH_Huks_Result ret = OH_Huks_InitSession(keyAlias, initParamSet, &handle, nullptr);
1481    if (ret.errorCode != OH_HUKS_SUCCESS) {
1482        return ret;
1483    }
1484
1485    uint8_t outDataU[ECDH_COMMON_SIZE] = {0};
1486    struct OH_Huks_Blob outDataUpdate = { ECDH_COMMON_SIZE, outDataU };
1487    ret = OH_Huks_UpdateSession(&handle, initParamSet, publicKey, &outDataUpdate);
1488    if (ret.errorCode != OH_HUKS_SUCCESS) {
1489        return ret;
1490    }
1491
1492    ret = OH_Huks_FinishSession(&handle, finishParamSet, &inData, outData);
1493    if (ret.errorCode != OH_HUKS_SUCCESS) {
1494        return ret;
1495    }
1496    return ret;
1497}
1498
1499static napi_value AgreeKey(napi_env env, napi_callback_info info)
1500{
1501    struct OH_Huks_ParamSet *genParamSet = nullptr;
1502    struct OH_Huks_ParamSet *initParamSet01 = nullptr;
1503    struct OH_Huks_ParamSet *finishParamSet01 = nullptr;
1504    struct OH_Huks_ParamSet *initParamSet02 = nullptr;
1505    struct OH_Huks_ParamSet *finishParamSet02 = nullptr;
1506    struct OH_Huks_Blob publicKey01 = { .size = OH_HUKS_ECC_KEY_SIZE_256, .data = nullptr };
1507    struct OH_Huks_Blob publicKey02 = { .size = OH_HUKS_ECC_KEY_SIZE_256, .data = nullptr };
1508    struct OH_Huks_Blob outData01 = { .size = ECDH_COMMON_SIZE, .data = nullptr };
1509    struct OH_Huks_Blob outData02 = { .size = ECDH_COMMON_SIZE, .data = nullptr };
1510    OH_Huks_Result ohResult;
1511    do {
1512        ohResult = InitParamSet(&genParamSet, g_genAgreeParams, sizeof(g_genAgreeParams) / sizeof(OH_Huks_Param));
1513        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1514            break;
1515        }
1516        ohResult = InitParamSet(&initParamSet01, g_agreeParamsInit01, sizeof(g_agreeParamsInit01) / sizeof(OH_Huks_Param));
1517        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1518            break;
1519        }
1520        ohResult = InitParamSet(&finishParamSet01, g_agreeParamsFinish01,
1521            sizeof(g_agreeParamsFinish01) / sizeof(OH_Huks_Param));
1522        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1523            break;
1524        }
1525        ohResult = InitParamSet(&initParamSet02, g_agreeParamsInit02, sizeof(g_agreeParamsInit02) / sizeof(OH_Huks_Param));
1526        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1527            break;
1528        }
1529        ohResult = InitParamSet(&finishParamSet02, g_agreeParamsFinish02,
1530            sizeof(g_agreeParamsFinish02) / sizeof(OH_Huks_Param));
1531        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1532            break;
1533        }
1534        /* 1. Get Key One */
1535        ohResult = OH_Huks_GenerateKeyItem(&g_keyAlias01001, genParamSet, nullptr);
1536        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1537            break;
1538        }
1539        /* 2. Get Key Two */
1540        ohResult = OH_Huks_GenerateKeyItem(&g_keyAlias02001, genParamSet, nullptr);
1541        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1542            break;
1543        }
1544        ohResult = MallocAndCheckBlobData(&publicKey01, publicKey01.size);
1545        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1546            break;
1547        }
1548        ohResult = MallocAndCheckBlobData(&publicKey02, publicKey02.size);
1549        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1550            break;
1551        }
1552        /* 3. Get public keys of key one and key two */
1553        ohResult = HksEcdhAgreeExport(&g_keyAlias01001, &g_keyAlias02001, &publicKey01, &publicKey02, genParamSet);
1554        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1555            break;
1556        }
1557        ohResult = MallocAndCheckBlobData(&outData01, outData01.size);
1558        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1559            break;
1560        }
1561        ohResult = MallocAndCheckBlobData(&outData02, outData02.size);
1562        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1563            break;
1564        }
1565        /* 4. Agree with key one and public key of key two */
1566        ohResult = HksEcdhAgreeFinish(&g_keyAlias01001, &publicKey02, initParamSet01, finishParamSet01, &outData01);
1567        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1568            break;
1569        }
1570        /* 5. Agree with key two and public key of key one */
1571        ohResult = HksEcdhAgreeFinish(&g_keyAlias02001, &publicKey01, initParamSet02, finishParamSet02, &outData02);
1572    } while (0);
1573    free(publicKey01.data);
1574    free(publicKey02.data);
1575    free(outData01.data);
1576    free(outData02.data);
1577    OH_Huks_DeleteKeyItem(&g_keyAlias01001, genParamSet);
1578    OH_Huks_DeleteKeyItem(&g_keyAlias02001, genParamSet);
1579    OH_Huks_DeleteKeyItem(&g_keyAliasFinal1001, NULL);
1580    OH_Huks_DeleteKeyItem(&g_keyAliasFinal2001, NULL);
1581    OH_Huks_FreeParamSet(&genParamSet);
1582    OH_Huks_FreeParamSet(&initParamSet01);
1583    OH_Huks_FreeParamSet(&finishParamSet01);
1584    OH_Huks_FreeParamSet(&initParamSet02);
1585    OH_Huks_FreeParamSet(&finishParamSet02);
1586
1587    napi_value ret;
1588    napi_create_int32(env, ohResult.errorCode, &ret);
1589    return ret;
1590}
1591```
1592
1593
1594### Key Derivation
1595
1596You are advised to pass in [HuksKeyStorageType](../reference/apis/js-apis-huks.md#hukskeystoragetype) to specify the storage type in key derivation. From API version 10, only **HUKS_STORAGE_ONLY_USED_IN_HUKS** or **HUKS_STORAGE_KEY_EXPORT_ALLOWED** can be used. If **HuksKeyStorageType** is not passed in, the key can be stored or exported by default, which poses security risks.
1597
1598**C++ Code Example**
1599
1600```C++
1601#include "huks/native_huks_api.h"
1602#include "huks/native_huks_param.h"
1603#include <string.h>
1604OH_Huks_Result InitParamSet(
1605    struct OH_Huks_ParamSet **paramSet,
1606    const struct OH_Huks_Param *params,
1607    uint32_t paramCount)
1608{
1609    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
1610    if (ret.errorCode != OH_HUKS_SUCCESS) {
1611        return ret;
1612    }
1613
1614    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
1615    if (ret.errorCode != OH_HUKS_SUCCESS) {
1616        OH_Huks_FreeParamSet(paramSet);
1617        return ret;
1618    }
1619
1620    ret = OH_Huks_BuildParamSet(paramSet);
1621    if (ret.errorCode != OH_HUKS_SUCCESS) {
1622        OH_Huks_FreeParamSet(paramSet);
1623        return ret;
1624    }
1625
1626    return ret;
1627}
1628
1629static const uint32_t DERIVE_KEY_SIZE_32 = 32;
1630static struct OH_Huks_Blob g_deriveKeyAlias = {
1631    (uint32_t)strlen("test_derive"),
1632    (uint8_t *)"test_derive"
1633};
1634
1635static struct OH_Huks_Param g_genDeriveParams[] = {
1636    {
1637        .tag =  OH_HUKS_TAG_ALGORITHM,
1638        .uint32Param = OH_HUKS_ALG_AES
1639    }, {
1640        .tag =  OH_HUKS_TAG_PURPOSE,
1641        .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE
1642    }, {
1643        .tag =  OH_HUKS_TAG_DIGEST,
1644        .uint32Param = OH_HUKS_DIGEST_SHA256
1645    }, {
1646        .tag =  OH_HUKS_TAG_KEY_SIZE,
1647        .uint32Param = OH_HUKS_AES_KEY_SIZE_256
1648    }
1649};
1650
1651static struct OH_Huks_Param g_hkdfParams[] = {
1652    {
1653        .tag =  OH_HUKS_TAG_ALGORITHM,
1654        .uint32Param = OH_HUKS_ALG_HKDF
1655    }, {
1656        .tag =  OH_HUKS_TAG_PURPOSE,
1657        .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE
1658    }, {
1659        .tag =  OH_HUKS_TAG_DIGEST,
1660        .uint32Param = OH_HUKS_DIGEST_SHA256
1661    }, {
1662        .tag =  OH_HUKS_TAG_DERIVE_KEY_SIZE,
1663        .uint32Param = DERIVE_KEY_SIZE_32
1664    }
1665};
1666
1667static struct OH_Huks_Param g_hkdfFinishParams[] = {
1668    {
1669        .tag =  OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
1670        .uint32Param = OH_HUKS_STORAGE_ONLY_USED_IN_HUKS
1671    }, {
1672        .tag =  OH_HUKS_TAG_KEY_ALIAS,
1673        .blob = g_deriveKeyAlias
1674    }, {
1675        .tag =  OH_HUKS_TAG_ALGORITHM,
1676        .uint32Param = OH_HUKS_ALG_HKDF
1677    }, {
1678        .tag =  OH_HUKS_TAG_KEY_SIZE,
1679        .uint32Param = DERIVE_KEY_SIZE_32
1680    }, {
1681        .tag =  OH_HUKS_TAG_PURPOSE,
1682        .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE
1683    }, {
1684        .tag =  OH_HUKS_TAG_DIGEST,
1685        .uint32Param = OH_HUKS_DIGEST_SHA256
1686    }
1687};
1688
1689static const uint32_t COMMON_SIZE = 2048;
1690static const char *g_deriveInData = "Hks_HKDF_Derive_Test_00000000000000000000000000000000000000000000000000000000000"
1691                                    "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
1692                                    "0000000000000000000000000000000000000000000000000000000000000000000000000_string";
1693
1694static napi_value DeriveKey(napi_env env, napi_callback_info info)
1695{
1696    struct OH_Huks_Blob genAlias = {
1697        (uint32_t)strlen("test_signVerify"),
1698        (uint8_t *)"test_signVerify"
1699    };
1700    struct OH_Huks_Blob inData = {
1701        (uint32_t)strlen(g_deriveInData),
1702        (uint8_t *)g_deriveInData
1703    };
1704    struct OH_Huks_ParamSet *genParamSet = nullptr;
1705    struct OH_Huks_ParamSet *hkdfParamSet = nullptr;
1706    struct OH_Huks_ParamSet *hkdfFinishParamSet = nullptr;
1707    OH_Huks_Result ohResult;
1708    do {
1709        ohResult = InitParamSet(&genParamSet, g_genDeriveParams, sizeof(g_genDeriveParams) / sizeof(OH_Huks_Param));
1710        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1711            break;
1712        }
1713
1714        ohResult = InitParamSet(&hkdfParamSet, g_hkdfParams, sizeof(g_hkdfParams) / sizeof(OH_Huks_Param));
1715        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1716           break;
1717        }
1718
1719        // finish paramset
1720        ohResult = InitParamSet(&hkdfFinishParamSet, g_hkdfFinishParams, sizeof(g_hkdfFinishParams) / sizeof(OH_Huks_Param));
1721        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1722            break;
1723        }
1724
1725        /* 1. Generate Key */
1726        ohResult = OH_Huks_GenerateKeyItem(&genAlias, genParamSet, nullptr);
1727        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1728            break;
1729        }
1730        /* 2. Derive */
1731        // Init
1732        uint8_t handleD[sizeof(uint64_t)] = {0};
1733        struct OH_Huks_Blob handleDerive = { sizeof(uint64_t), handleD };
1734        ohResult = OH_Huks_InitSession(&genAlias, hkdfParamSet, &handleDerive, nullptr);
1735        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1736            break;
1737        }
1738        // Update
1739        uint8_t tmpOut[COMMON_SIZE] = {0};
1740        struct OH_Huks_Blob outData = { COMMON_SIZE, tmpOut };
1741        ohResult = OH_Huks_UpdateSession(&handleDerive, hkdfParamSet, &inData, &outData);
1742        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1743            break;
1744        }
1745        // Finish
1746        uint8_t outDataD[COMMON_SIZE] = {0};
1747        struct OH_Huks_Blob outDataDerive = { COMMON_SIZE, outDataD };
1748        ohResult = OH_Huks_FinishSession(&handleDerive, hkdfFinishParamSet, &inData, &outDataDerive);
1749    } while (0);
1750    (void)OH_Huks_DeleteKeyItem(&genAlias, nullptr);
1751    (void)OH_Huks_DeleteKeyItem(&g_deriveKeyAlias, nullptr);
1752    OH_Huks_FreeParamSet(&genParamSet);
1753    OH_Huks_FreeParamSet(&hkdfParamSet);
1754    OH_Huks_FreeParamSet(&hkdfFinishParamSet);
1755
1756    napi_value ret;
1757    napi_create_int32(env, ohResult.errorCode, &ret);
1758    return ret;
1759}
1760```
1761
1762### Key Attestation
1763
1764The HUKS provides attestation for the public keys of asymmetric key pairs. The HUKS can issue a certificate for the public key of an asymmetric key pair stored in the HUKS using the public key infrastructure (PKI) certificate chain technology. The certificate can prove the validity of the public key. The service can use the root CA certificate provided by the OpenHarmony to verify the key certificate issued by the HUKS level by level to ensure that the public key and private key in the certificate are from a trusted hardware device and stored in the HUKS.
1765
1766**How to Develop**
1767
17681. Pass in the key alias and the attribute tag of the key to be attested.
17692. Generate an X.509 certificate chain, which consists of the root CA certificate, device CA certificate, device certificate, and key certificate in sequence, for the application.
17703. Send the certificate chain to a trusted server. The server parses and verifies the validity of the certificate chain and whether a single certificate is revoked.
1771
1772**C++ Code Example**
1773
1774```C++
1775#include "huks/native_huks_api.h"
1776#include "huks/native_huks_param.h"
1777#include <string.h>
1778
1779OH_Huks_Result InitParamSet(
1780    struct OH_Huks_ParamSet **paramSet,
1781    const struct OH_Huks_Param *params,
1782    uint32_t paramCount)
1783{
1784    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
1785    if (ret.errorCode != OH_HUKS_SUCCESS) {
1786        return ret;
1787    }
1788
1789    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
1790    if (ret.errorCode != OH_HUKS_SUCCESS) {
1791        OH_Huks_FreeParamSet(paramSet);
1792        return ret;
1793    }
1794
1795    ret = OH_Huks_BuildParamSet(paramSet);
1796    if (ret.errorCode != OH_HUKS_SUCCESS) {
1797        OH_Huks_FreeParamSet(paramSet);
1798        return ret;
1799    }
1800
1801    return ret;
1802}
1803
1804static uint32_t g_size = 4096;
1805static uint32_t CERT_COUNT = 4;
1806
1807void FreeCertChain(struct OH_Huks_CertChain **certChain, const uint32_t pos)
1808{
1809    if (certChain == nullptr || *certChain == nullptr) {
1810        return;
1811    }
1812
1813    if ((*certChain)->certs == nullptr) {
1814        free(*certChain);
1815        *certChain = nullptr;
1816        return;
1817    }
1818    for (uint32_t j = 0; j < pos; j++) {
1819        if ((*certChain)->certs[j].data != nullptr) {
1820            free((*certChain)->certs[j].data);
1821            (*certChain)->certs[j].data = nullptr;
1822        }
1823    }
1824
1825    if ((*certChain)->certs != nullptr) {
1826        free((*certChain)->certs);
1827        (*certChain)->certs = nullptr;
1828    }
1829
1830    if (*certChain != nullptr) {
1831        free(*certChain);
1832        *certChain = nullptr;
1833    }
1834}
1835
1836int32_t ConstructDataToCertChain(struct OH_Huks_CertChain **certChain)
1837{
1838    *certChain = (struct OH_Huks_CertChain *)malloc(sizeof(struct OH_Huks_CertChain));
1839    if (*certChain == nullptr) {
1840        return OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT;
1841    }
1842    (*certChain)->certsCount = CERT_COUNT;
1843
1844    (*certChain)->certs = (struct OH_Huks_Blob *)malloc(sizeof(struct OH_Huks_Blob) * ((*certChain)->certsCount));
1845    if ((*certChain)->certs == nullptr) {
1846        free(*certChain);
1847        *certChain = nullptr;
1848    }
1849    for (uint32_t i = 0; i < (*certChain)->certsCount; i++) {
1850        (*certChain)->certs[i].size = g_size;
1851        (*certChain)->certs[i].data = (uint8_t *)malloc((*certChain)->certs[i].size);
1852        if ((*certChain)->certs[i].data == nullptr) {
1853            FreeCertChain(certChain, i);
1854            return OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT;
1855        }
1856    }
1857    return 0;
1858}
1859
1860static struct OH_Huks_Param g_genAttestParams[] = {
1861    { .tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_RSA },
1862    { .tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_RSA_KEY_SIZE_2048 },
1863    { .tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_VERIFY },
1864    { .tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_SHA256 },
1865    { .tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_PSS },
1866    { .tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_ECB },
1867};
1868
1869#define CHALLENGE_DATA "hi_challenge_data"
1870static struct OH_Huks_Blob g_challenge = { sizeof(CHALLENGE_DATA), (uint8_t *)CHALLENGE_DATA };
1871
1872static napi_value AttestKey(napi_env env, napi_callback_info info)
1873{
1874    struct OH_Huks_Blob genAlias = {
1875        (uint32_t)strlen("test_attest"),
1876        (uint8_t *)"test_attest"
1877    };
1878    static struct OH_Huks_Param g_attestParams[] = {
1879        { .tag = OH_HUKS_TAG_ATTESTATION_CHALLENGE, .blob = g_challenge },
1880        { .tag = OH_HUKS_TAG_ATTESTATION_ID_ALIAS, .blob = genAlias },
1881    };
1882    struct OH_Huks_ParamSet *genParamSet = nullptr;
1883    struct OH_Huks_ParamSet *attestParamSet = nullptr;
1884    OH_Huks_Result ohResult;
1885    OH_Huks_CertChain *certChain = NULL;
1886    do {
1887        ohResult = InitParamSet(&genParamSet, g_genAttestParams, sizeof(g_genAttestParams) / sizeof(OH_Huks_Param));
1888        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1889            break;
1890        }
1891        ohResult = InitParamSet(&attestParamSet, g_attestParams, sizeof(g_attestParams) / sizeof(OH_Huks_Param));
1892        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1893            break;
1894        }
1895        ohResult = OH_Huks_GenerateKeyItem(&genAlias, genParamSet, nullptr);
1896        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
1897            break;
1898        }
1899
1900        (void)ConstructDataToCertChain(&certChain);
1901        ohResult = OH_Huks_AttestKeyItem(&genAlias, attestParamSet, certChain);
1902    } while (0);
1903    if (certChain != nullptr) {
1904        FreeCertChain(&certChain, certChain->certsCount);
1905    }
1906    OH_Huks_FreeParamSet(&genParamSet);
1907    OH_Huks_FreeParamSet(&attestParamSet);
1908    (void)OH_Huks_DeleteKeyItem(&genAlias, NULL);
1909
1910    napi_value ret;
1911    napi_create_int32(env, ohResult.errorCode, &ret);
1912    return ret;
1913}
1914```
1915