1e41f4b71Sopenharmony_ci# Key Agreement (C/C++)
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci
4e41f4b71Sopenharmony_ciThis topic walks you through on how to agree on an ECDH key that is used only in HUKS. For details about the scenarios and supported algorithms, see [Supported Algorithms](huks-key-generation-overview.md#supported-algorithms).
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ci## Add the dynamic library in the CMake script.
7e41f4b71Sopenharmony_ci```txt
8e41f4b71Sopenharmony_ci   target_link_libraries(entry PUBLIC libhuks_ndk.z.so)
9e41f4b71Sopenharmony_ci```
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ci## How to Develop
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ci**Key Generation**
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ciGenerate an asymmetric key for device A and device B each. For details, see [Key Generation](huks-key-generation-overview.md) or [Key Import](huks-key-import-overview.md).
16e41f4b71Sopenharmony_ci
17e41f4b71Sopenharmony_ciWhen generating a key, you can set **OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG** (optional) to specify how the shared secret generated from this key through key agreement is managed.
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ci- If this tag is set to **OH_HUKS_STORAGE_ONLY_USED_IN_HUKS**, the shared secret is managed by HUKS. That is, the shared secret is always in a secure environment throughout its lifecycle.
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci- If this tag is set to **OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED**, the shared secret generated will be returned to the caller for management. That is, the service side ensures the key security.
22e41f4b71Sopenharmony_ci
23e41f4b71Sopenharmony_ci- If this tag is not set, the shared secret generated can be either managed by HUKS or returned to the caller for management. The key protection mode can be set in the subsequent key agreement on the service side.
24e41f4b71Sopenharmony_ci
25e41f4b71Sopenharmony_ci**Key Export**
26e41f4b71Sopenharmony_ci
27e41f4b71Sopenharmony_ciExport the public key of the asymmetric key pair of device A and device B. For details, see [Key Export](huks-export-key-arkts.md).
28e41f4b71Sopenharmony_ci
29e41f4b71Sopenharmony_ci**Key Agreement**
30e41f4b71Sopenharmony_ci
31e41f4b71Sopenharmony_ciPerform key agreement using the public key of the peer device and private key of the local device (that is, public key of device B and private key of device A for device A, and public key of device A and private key of device B for device B) to produce a shared secret.
32e41f4b71Sopenharmony_ci
33e41f4b71Sopenharmony_ciDuring key agreement, you can set **OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG** (optional) to specify how the shared secret generated is managed.
34e41f4b71Sopenharmony_ci
35e41f4b71Sopenharmony_ci| Key Generation| Key Agreement| Specifications|
36e41f4b71Sopenharmony_ci| -------- | -------- | -------- |
37e41f4b71Sopenharmony_ci| OH_HUKS_STORAGE_ONLY_USED_IN_HUKS | OH_HUKS_STORAGE_ONLY_USED_IN_HUKS | The key is managed by HUKS.|
38e41f4b71Sopenharmony_ci| OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED | OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED | The key is returned to the caller for management.|
39e41f4b71Sopenharmony_ci| The tag is not set.| OH_HUKS_STORAGE_ONLY_USED_IN_HUKS | The key is managed by HUKS.|
40e41f4b71Sopenharmony_ci| The tag is not set.| OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED | The key is returned to the caller for management.|
41e41f4b71Sopenharmony_ci| The tag is not set.| The tag is not set.| The key is returned to the caller for management.|
42e41f4b71Sopenharmony_ci
43e41f4b71Sopenharmony_ci>**NOTE**<br>The tag value set in key agreement should not conflict with the tag value set in key generation. The above table lists only valid settings.
44e41f4b71Sopenharmony_ci
45e41f4b71Sopenharmony_ci**Key Deletion**
46e41f4b71Sopenharmony_ci
47e41f4b71Sopenharmony_ciDelete the keys from device A and device B when the keys are not required. For details, see [Deleting a Key](huks-delete-key-ndk.md).
48e41f4b71Sopenharmony_ci
49e41f4b71Sopenharmony_ci```c++
50e41f4b71Sopenharmony_ci#include "huks/native_huks_api.h"
51e41f4b71Sopenharmony_ci#include "huks/native_huks_param.h"
52e41f4b71Sopenharmony_ci#include <string.h>
53e41f4b71Sopenharmony_ci/* Initialize parameters. */
54e41f4b71Sopenharmony_ciOH_Huks_Result InitParamSet(
55e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet **paramSet,
56e41f4b71Sopenharmony_ci    const struct OH_Huks_Param *params,
57e41f4b71Sopenharmony_ci    uint32_t paramCount)
58e41f4b71Sopenharmony_ci{
59e41f4b71Sopenharmony_ci    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
60e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
61e41f4b71Sopenharmony_ci        return ret;
62e41f4b71Sopenharmony_ci    }
63e41f4b71Sopenharmony_ci    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
64e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
65e41f4b71Sopenharmony_ci        OH_Huks_FreeParamSet(paramSet);
66e41f4b71Sopenharmony_ci        return ret;
67e41f4b71Sopenharmony_ci    }
68e41f4b71Sopenharmony_ci    ret = OH_Huks_BuildParamSet(paramSet);
69e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
70e41f4b71Sopenharmony_ci        OH_Huks_FreeParamSet(paramSet);
71e41f4b71Sopenharmony_ci        return ret;
72e41f4b71Sopenharmony_ci    }
73e41f4b71Sopenharmony_ci    return ret;
74e41f4b71Sopenharmony_ci}
75e41f4b71Sopenharmony_cistatic const uint32_t IV_SIZE = 16;
76e41f4b71Sopenharmony_cistatic uint8_t IV[IV_SIZE] = { 0 }; // this is a test value, for real use the iv should be different every time
77e41f4b71Sopenharmony_cistatic struct OH_Huks_Blob g_keyAliasFinal1001 = {
78e41f4b71Sopenharmony_ci    (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_1_final"),
79e41f4b71Sopenharmony_ci    (uint8_t *)"HksECDHAgreeKeyAliasTest001_1_final"
80e41f4b71Sopenharmony_ci};
81e41f4b71Sopenharmony_ci/* Set the key parameter set. */
82e41f4b71Sopenharmony_cistatic struct OH_Huks_Param g_genAgreeParams[] = {
83e41f4b71Sopenharmony_ci    {
84e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_ALGORITHM,
85e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_ALG_ECC
86e41f4b71Sopenharmony_ci    }, {
87e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_PURPOSE,
88e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
89e41f4b71Sopenharmony_ci    }, {
90e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_KEY_SIZE,
91e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_ECC_KEY_SIZE_256
92e41f4b71Sopenharmony_ci    }, {
93e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_DIGEST,
94e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_DIGEST_NONE
95e41f4b71Sopenharmony_ci    }
96e41f4b71Sopenharmony_ci};
97e41f4b71Sopenharmony_cistatic struct OH_Huks_Param g_agreeParamsInit01[] = {
98e41f4b71Sopenharmony_ci    {
99e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_ALGORITHM,
100e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_ALG_ECDH
101e41f4b71Sopenharmony_ci    }, {
102e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_PURPOSE,
103e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
104e41f4b71Sopenharmony_ci    }, {
105e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_KEY_SIZE,
106e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_ECC_KEY_SIZE_256
107e41f4b71Sopenharmony_ci    }
108e41f4b71Sopenharmony_ci};
109e41f4b71Sopenharmony_cistatic struct OH_Huks_Param g_agreeParamsFinish01[] = {
110e41f4b71Sopenharmony_ci    {
111e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
112e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_STORAGE_ONLY_USED_IN_HUKS
113e41f4b71Sopenharmony_ci    }, {
114e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_ALGORITHM,
115e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_ALG_AES
116e41f4b71Sopenharmony_ci    }, {
117e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_KEY_SIZE,
118e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_AES_KEY_SIZE_256
119e41f4b71Sopenharmony_ci    }, {
120e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_PURPOSE,
121e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
122e41f4b71Sopenharmony_ci    }, {
123e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_KEY_ALIAS,
124e41f4b71Sopenharmony_ci        .blob = g_keyAliasFinal1001
125e41f4b71Sopenharmony_ci    }, {
126e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_PADDING,
127e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_PADDING_NONE
128e41f4b71Sopenharmony_ci    }, {
129e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_BLOCK_MODE,
130e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_MODE_CBC
131e41f4b71Sopenharmony_ci    }
132e41f4b71Sopenharmony_ci};
133e41f4b71Sopenharmony_cistatic struct OH_Huks_Blob g_keyAliasFinal2001 = {
134e41f4b71Sopenharmony_ci    (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_2_final"),
135e41f4b71Sopenharmony_ci    (uint8_t *)"HksECDHAgreeKeyAliasTest001_2_final"
136e41f4b71Sopenharmony_ci};
137e41f4b71Sopenharmony_cistatic struct OH_Huks_Param g_agreeParamsInit02[] = {
138e41f4b71Sopenharmony_ci    {
139e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_ALGORITHM,
140e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_ALG_ECDH
141e41f4b71Sopenharmony_ci    }, {
142e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_PURPOSE,
143e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
144e41f4b71Sopenharmony_ci    }, {
145e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_KEY_SIZE,
146e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_ECC_KEY_SIZE_256
147e41f4b71Sopenharmony_ci    }
148e41f4b71Sopenharmony_ci};
149e41f4b71Sopenharmony_cistatic struct OH_Huks_Param g_agreeParamsFinish02[] = {
150e41f4b71Sopenharmony_ci    {
151e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
152e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_STORAGE_ONLY_USED_IN_HUKS
153e41f4b71Sopenharmony_ci    }, {
154e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_ALGORITHM,
155e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_ALG_AES
156e41f4b71Sopenharmony_ci    }, {
157e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_KEY_SIZE,
158e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_AES_KEY_SIZE_256
159e41f4b71Sopenharmony_ci    }, {
160e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_PURPOSE,
161e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE
162e41f4b71Sopenharmony_ci    }, {
163e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_KEY_ALIAS,
164e41f4b71Sopenharmony_ci        .blob = g_keyAliasFinal2001
165e41f4b71Sopenharmony_ci    }, {
166e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_PADDING,
167e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_PADDING_NONE
168e41f4b71Sopenharmony_ci    }, {
169e41f4b71Sopenharmony_ci        .tag = OH_HUKS_TAG_BLOCK_MODE,
170e41f4b71Sopenharmony_ci        .uint32Param = OH_HUKS_MODE_CBC
171e41f4b71Sopenharmony_ci    }
172e41f4b71Sopenharmony_ci};
173e41f4b71Sopenharmony_cistatic const uint32_t ECDH_COMMON_SIZE = 1024;
174e41f4b71Sopenharmony_cistatic struct OH_Huks_Blob g_keyAlias01001 = {
175e41f4b71Sopenharmony_ci    (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_1"),
176e41f4b71Sopenharmony_ci    (uint8_t *)"HksECDHAgreeKeyAliasTest001_1"
177e41f4b71Sopenharmony_ci};
178e41f4b71Sopenharmony_cistatic struct OH_Huks_Blob g_keyAlias02001 = {
179e41f4b71Sopenharmony_ci    (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_2"),
180e41f4b71Sopenharmony_ci    (uint8_t *)"HksECDHAgreeKeyAliasTest001_2"
181e41f4b71Sopenharmony_ci};
182e41f4b71Sopenharmony_ciOH_Huks_Result MallocAndCheckBlobData(
183e41f4b71Sopenharmony_ci    struct OH_Huks_Blob *blob,
184e41f4b71Sopenharmony_ci    const uint32_t blobSize)
185e41f4b71Sopenharmony_ci{
186e41f4b71Sopenharmony_ci    struct OH_Huks_Result ret;
187e41f4b71Sopenharmony_ci    ret.errorCode = OH_HUKS_SUCCESS;
188e41f4b71Sopenharmony_ci    blob->data = (uint8_t *)malloc(blobSize);
189e41f4b71Sopenharmony_ci    if (blob->data == NULL) {
190e41f4b71Sopenharmony_ci        ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
191e41f4b71Sopenharmony_ci    }
192e41f4b71Sopenharmony_ci    return ret;
193e41f4b71Sopenharmony_ci}
194e41f4b71Sopenharmony_ci/* Export a key. */
195e41f4b71Sopenharmony_ciOH_Huks_Result HksEcdhAgreeExport(const struct OH_Huks_Blob *keyAlias1, const struct OH_Huks_Blob *keyAlias2,
196e41f4b71Sopenharmony_ci    struct OH_Huks_Blob *publicKey1, struct OH_Huks_Blob *publicKey2, const struct OH_Huks_ParamSet *genParamSet)
197e41f4b71Sopenharmony_ci{
198e41f4b71Sopenharmony_ci    OH_Huks_Result ret = OH_Huks_ExportPublicKeyItem(keyAlias1, genParamSet, publicKey1);
199e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
200e41f4b71Sopenharmony_ci        return ret;
201e41f4b71Sopenharmony_ci    }
202e41f4b71Sopenharmony_ci    ret = OH_Huks_ExportPublicKeyItem(keyAlias2, genParamSet, publicKey2);
203e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
204e41f4b71Sopenharmony_ci        return ret;
205e41f4b71Sopenharmony_ci    }
206e41f4b71Sopenharmony_ci    return ret;
207e41f4b71Sopenharmony_ci}
208e41f4b71Sopenharmony_cistatic const char *g_inData = "Hks_ECDH_Agree_Test_000000000000000000000000000000000000000000000000000000000000"
209e41f4b71Sopenharmony_ci                                    "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
210e41f4b71Sopenharmony_ci                                    "0000000000000000000000000000000000000000000000000000000000000000000000000_string";
211e41f4b71Sopenharmony_ci/* Perform key agreement. */
212e41f4b71Sopenharmony_ciOH_Huks_Result HksEcdhAgreeFinish(const struct OH_Huks_Blob *keyAlias, const struct OH_Huks_Blob *publicKey,
213e41f4b71Sopenharmony_ci    const struct OH_Huks_ParamSet *initParamSet, const struct OH_Huks_ParamSet *finishParamSet, struct OH_Huks_Blob *outData)
214e41f4b71Sopenharmony_ci{
215e41f4b71Sopenharmony_ci    struct OH_Huks_Blob inData = {
216e41f4b71Sopenharmony_ci        (uint32_t)strlen(g_inData),
217e41f4b71Sopenharmony_ci        (uint8_t *)g_inData
218e41f4b71Sopenharmony_ci    };
219e41f4b71Sopenharmony_ci    uint8_t handleU[sizeof(uint64_t)] = {0};
220e41f4b71Sopenharmony_ci    struct OH_Huks_Blob handle = { sizeof(uint64_t), handleU };
221e41f4b71Sopenharmony_ci    OH_Huks_Result ret = OH_Huks_InitSession(keyAlias, initParamSet, &handle, nullptr);
222e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
223e41f4b71Sopenharmony_ci        return ret;
224e41f4b71Sopenharmony_ci    }
225e41f4b71Sopenharmony_ci    uint8_t outDataU[ECDH_COMMON_SIZE] = {0};
226e41f4b71Sopenharmony_ci    struct OH_Huks_Blob outDataUpdate = { ECDH_COMMON_SIZE, outDataU };
227e41f4b71Sopenharmony_ci    ret = OH_Huks_UpdateSession(&handle, initParamSet, publicKey, &outDataUpdate);
228e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
229e41f4b71Sopenharmony_ci        return ret;
230e41f4b71Sopenharmony_ci    }
231e41f4b71Sopenharmony_ci    ret = OH_Huks_FinishSession(&handle, finishParamSet, &inData, outData);
232e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
233e41f4b71Sopenharmony_ci        return ret;
234e41f4b71Sopenharmony_ci    }
235e41f4b71Sopenharmony_ci    return ret;
236e41f4b71Sopenharmony_ci}
237e41f4b71Sopenharmony_ci/* Key agreement process. */
238e41f4b71Sopenharmony_cistatic napi_value AgreeKey(napi_env env, napi_callback_info info)
239e41f4b71Sopenharmony_ci{
240e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *genParamSet = nullptr;
241e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *initParamSet01 = nullptr;
242e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *finishParamSet01 = nullptr;
243e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *initParamSet02 = nullptr;
244e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *finishParamSet02 = nullptr;
245e41f4b71Sopenharmony_ci    struct OH_Huks_Blob publicKey01 = { .size = OH_HUKS_ECC_KEY_SIZE_256, .data = nullptr };
246e41f4b71Sopenharmony_ci    struct OH_Huks_Blob publicKey02 = { .size = OH_HUKS_ECC_KEY_SIZE_256, .data = nullptr };
247e41f4b71Sopenharmony_ci    struct OH_Huks_Blob outData01 = { .size = ECDH_COMMON_SIZE, .data = nullptr };
248e41f4b71Sopenharmony_ci    struct OH_Huks_Blob outData02 = { .size = ECDH_COMMON_SIZE, .data = nullptr };
249e41f4b71Sopenharmony_ci    OH_Huks_Result ohResult;
250e41f4b71Sopenharmony_ci    do {
251e41f4b71Sopenharmony_ci        /* 1. Set the key alias and key parameter set. */
252e41f4b71Sopenharmony_ci        ohResult = InitParamSet(&genParamSet, g_genAgreeParams, sizeof(g_genAgreeParams) / sizeof(OH_Huks_Param));
253e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
254e41f4b71Sopenharmony_ci            break;
255e41f4b71Sopenharmony_ci        }
256e41f4b71Sopenharmony_ci        ohResult = InitParamSet(&initParamSet01, g_agreeParamsInit01, sizeof(g_agreeParamsInit01) / sizeof(OH_Huks_Param));
257e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
258e41f4b71Sopenharmony_ci            break;
259e41f4b71Sopenharmony_ci        }
260e41f4b71Sopenharmony_ci        ohResult = InitParamSet(&finishParamSet01, g_agreeParamsFinish01,
261e41f4b71Sopenharmony_ci            sizeof(g_agreeParamsFinish01) / sizeof(OH_Huks_Param));
262e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
263e41f4b71Sopenharmony_ci            break;
264e41f4b71Sopenharmony_ci        }
265e41f4b71Sopenharmony_ci        ohResult = InitParamSet(&initParamSet02, g_agreeParamsInit02, sizeof(g_agreeParamsInit02) / sizeof(OH_Huks_Param));
266e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
267e41f4b71Sopenharmony_ci            break;
268e41f4b71Sopenharmony_ci        }
269e41f4b71Sopenharmony_ci        ohResult = InitParamSet(&finishParamSet02, g_agreeParamsFinish02,
270e41f4b71Sopenharmony_ci            sizeof(g_agreeParamsFinish02) / sizeof(OH_Huks_Param));
271e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
272e41f4b71Sopenharmony_ci            break;
273e41f4b71Sopenharmony_ci        }
274e41f4b71Sopenharmony_ci        /* 2. Generate an asymmetric key pair for device A. */
275e41f4b71Sopenharmony_ci        ohResult = OH_Huks_GenerateKeyItem(&g_keyAlias01001, genParamSet, nullptr);
276e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
277e41f4b71Sopenharmony_ci            break;
278e41f4b71Sopenharmony_ci        }
279e41f4b71Sopenharmony_ci        /* 3. Generate an asymmetric key pair for device B. */
280e41f4b71Sopenharmony_ci        ohResult = OH_Huks_GenerateKeyItem(&g_keyAlias02001, genParamSet, nullptr);
281e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
282e41f4b71Sopenharmony_ci            break;
283e41f4b71Sopenharmony_ci        }
284e41f4b71Sopenharmony_ci        ohResult = MallocAndCheckBlobData(&publicKey01, publicKey01.size);
285e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
286e41f4b71Sopenharmony_ci            break;
287e41f4b71Sopenharmony_ci        }
288e41f4b71Sopenharmony_ci        ohResult = MallocAndCheckBlobData(&publicKey02, publicKey02.size);
289e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
290e41f4b71Sopenharmony_ci            break;
291e41f4b71Sopenharmony_ci        }
292e41f4b71Sopenharmony_ci        /* 4. Export the public key from device A and device B separately. */
293e41f4b71Sopenharmony_ci        ohResult = HksEcdhAgreeExport(&g_keyAlias01001, &g_keyAlias02001, &publicKey01, &publicKey02, genParamSet);
294e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
295e41f4b71Sopenharmony_ci            break;
296e41f4b71Sopenharmony_ci        }
297e41f4b71Sopenharmony_ci        ohResult = MallocAndCheckBlobData(&outData01, outData01.size);
298e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
299e41f4b71Sopenharmony_ci            break;
300e41f4b71Sopenharmony_ci        }
301e41f4b71Sopenharmony_ci        ohResult = MallocAndCheckBlobData(&outData02, outData02.size);
302e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
303e41f4b71Sopenharmony_ci            break;
304e41f4b71Sopenharmony_ci        }
305e41f4b71Sopenharmony_ci        /* 5. Perform key agreement for device A. */
306e41f4b71Sopenharmony_ci        ohResult = HksEcdhAgreeFinish(&g_keyAlias01001, &publicKey02, initParamSet01, finishParamSet01, &outData01);
307e41f4b71Sopenharmony_ci        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
308e41f4b71Sopenharmony_ci            break;
309e41f4b71Sopenharmony_ci        }
310e41f4b71Sopenharmony_ci        /* 5. Perform key agreement for device B. */
311e41f4b71Sopenharmony_ci        ohResult = HksEcdhAgreeFinish(&g_keyAlias02001, &publicKey01, initParamSet02, finishParamSet02, &outData02);
312e41f4b71Sopenharmony_ci    } while (0);
313e41f4b71Sopenharmony_ci    free(publicKey01.data);
314e41f4b71Sopenharmony_ci    free(publicKey02.data);
315e41f4b71Sopenharmony_ci    free(outData01.data);
316e41f4b71Sopenharmony_ci    free(outData02.data);
317e41f4b71Sopenharmony_ci    /* 6. Delete keys from device A and device B. */
318e41f4b71Sopenharmony_ci    OH_Huks_DeleteKeyItem(&g_keyAlias01001, genParamSet);
319e41f4b71Sopenharmony_ci    OH_Huks_DeleteKeyItem(&g_keyAlias02001, genParamSet);
320e41f4b71Sopenharmony_ci    OH_Huks_DeleteKeyItem(&g_keyAliasFinal1001, NULL);
321e41f4b71Sopenharmony_ci    OH_Huks_DeleteKeyItem(&g_keyAliasFinal2001, NULL);
322e41f4b71Sopenharmony_ci    OH_Huks_FreeParamSet(&genParamSet);
323e41f4b71Sopenharmony_ci    OH_Huks_FreeParamSet(&initParamSet01);
324e41f4b71Sopenharmony_ci    OH_Huks_FreeParamSet(&finishParamSet01);
325e41f4b71Sopenharmony_ci    OH_Huks_FreeParamSet(&initParamSet02);
326e41f4b71Sopenharmony_ci    OH_Huks_FreeParamSet(&finishParamSet02);
327e41f4b71Sopenharmony_ci    
328e41f4b71Sopenharmony_ci    napi_value ret;
329e41f4b71Sopenharmony_ci    napi_create_int32(env, ohResult.errorCode, &ret);
330e41f4b71Sopenharmony_ci    return ret;
331e41f4b71Sopenharmony_ci}
332e41f4b71Sopenharmony_ci```
333