1e41f4b71Sopenharmony_ci# Importing a Key in Ciphertext (C/C++)
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci
4e41f4b71Sopenharmony_ciThis topic walks you through on how to import an ECDH key pair. However, the example does not cover the operations such as [key generation](huks-key-generation-overview.md) and [key agreement](huks-key-agreement-overview.md) of the service side.
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ciFor details about the scenarios and supported algorithm specifications, see [Supported Algorithms](huks-key-import-overview.md#supported-algorithms).
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ci## Add the dynamic library in the CMake script.
10e41f4b71Sopenharmony_ci```txt
11e41f4b71Sopenharmony_ci   target_link_libraries(entry PUBLIC libhuks_ndk.z.so)
12e41f4b71Sopenharmony_ci```
13e41f4b71Sopenharmony_ci
14e41f4b71Sopenharmony_ci## How to Develop
15e41f4b71Sopenharmony_ci
16e41f4b71Sopenharmony_ci1. Convert the key to be imported from device A (device from which the key is imported) to [HUKS key material format](huks-concepts.md#key material format) **To_Import_Key**. (This step applies only to asymmetric key pairs. If the key to be imported is a symmetric key, skip over this step.)
17e41f4b71Sopenharmony_ci
18e41f4b71Sopenharmony_ci2. Generate an asymmetric key pair **Wrapping_Key** (public key **Wrapping_Pk** and private key **Wrapping_Sk**) with the purpose of **HUKS_KEY_PURPOSE_UNWRAP** for device B (device to which the key is imported), and export the public key **Wrapping_Pk** of **Wrapping_Key** and save it. The asymmetric key pair **Wrapping_Key** is used for key agreement in the encrypted import process.
19e41f4b71Sopenharmony_ci
20e41f4b71Sopenharmony_ci3. Use the same algorithm to generate an asymmetric key pair **Caller_Key** (public key **Caller_Pk** and private key **Caller_Sk**) with the purpose of **HUKS_KEY_PURPOSE_UNWRAP** for device A, and export the public key **Caller_Pk** of **Caller_Key** and save it. The asymmetric key pair **Caller_Key** is used for key agreement in the encrypted import process.
21e41f4b71Sopenharmony_ci
22e41f4b71Sopenharmony_ci4. Generate a symmetric key **Caller_Kek** for device A. This key is used to encrypt **To_Import_Key**.
23e41f4b71Sopenharmony_ci
24e41f4b71Sopenharmony_ci5. Perform key agreement with the private key **Caller_Sk** in **Caller_Key** of device A and the public key **Wrapping_Pk** in **Wrapping_Key** of device B to yield a **Shared_Key**.
25e41f4b71Sopenharmony_ci
26e41f4b71Sopenharmony_ci6. Use **Caller_Kek** to encrypt **To_Import_Key** of device A and generate **To_Import_Key_Enc**.
27e41f4b71Sopenharmony_ci
28e41f4b71Sopenharmony_ci7. Use **Shared_Key** to encrypt **Caller_Kek** of device A and generate **Caller_Kek_Enc**.
29e41f4b71Sopenharmony_ci
30e41f4b71Sopenharmony_ci8. Encapsulate the key material **Caller_Pk**, **Caller_Kek_Enc**, and **To_Import_Key_Enc** of device A, and sends it to device B. For details about the format of the key material to be imported, see [Key Material Format for Encrypted Import](huks-key-import-overview.md#key-material-format-for-encrypted-import).
31e41f4b71Sopenharmony_ci
32e41f4b71Sopenharmony_ci9. Import the encrypted key material to device B.
33e41f4b71Sopenharmony_ci
34e41f4b71Sopenharmony_ci10. Delete the intermediate keys (keys used for encrypting the key to import) from devices A and B.
35e41f4b71Sopenharmony_ci
36e41f4b71Sopenharmony_ci```c++
37e41f4b71Sopenharmony_ci#include "napi/native_api.h"
38e41f4b71Sopenharmony_ci#include "huks/native_huks_api.h"
39e41f4b71Sopenharmony_ci#include "huks/native_huks_param.h"
40e41f4b71Sopenharmony_ci#include <algorithm>
41e41f4b71Sopenharmony_ciOH_Huks_Result InitParamSet(struct OH_Huks_ParamSet **paramSet, const struct OH_Huks_Param *params,
42e41f4b71Sopenharmony_ci                            uint32_t paramCount) {
43e41f4b71Sopenharmony_ci    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
44e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
45e41f4b71Sopenharmony_ci        return ret;
46e41f4b71Sopenharmony_ci    }
47e41f4b71Sopenharmony_ci    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
48e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
49e41f4b71Sopenharmony_ci        OH_Huks_FreeParamSet(paramSet);
50e41f4b71Sopenharmony_ci        return ret;
51e41f4b71Sopenharmony_ci    }
52e41f4b71Sopenharmony_ci    ret = OH_Huks_BuildParamSet(paramSet);
53e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
54e41f4b71Sopenharmony_ci        OH_Huks_FreeParamSet(paramSet);
55e41f4b71Sopenharmony_ci        return ret;
56e41f4b71Sopenharmony_ci    }
57e41f4b71Sopenharmony_ci    return ret;
58e41f4b71Sopenharmony_ci}
59e41f4b71Sopenharmony_cistruct HksImportWrappedKeyTestParams {
60e41f4b71Sopenharmony_ci    // server key, for real
61e41f4b71Sopenharmony_ci    struct OH_Huks_Blob *wrappingKeyAlias;
62e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *genWrappingKeyParamSet;
63e41f4b71Sopenharmony_ci    uint32_t publicKeySize;
64e41f4b71Sopenharmony_ci    struct OH_Huks_Blob *callerKeyAlias;
65e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *genCallerKeyParamSet;
66e41f4b71Sopenharmony_ci    struct OH_Huks_Blob *callerKekAlias;
67e41f4b71Sopenharmony_ci    struct OH_Huks_Blob *callerKek;
68e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *importCallerKekParamSet;
69e41f4b71Sopenharmony_ci    struct OH_Huks_Blob *callerAgreeKeyAlias;
70e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *agreeParamSet;
71e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *importWrappedKeyParamSet;
72e41f4b71Sopenharmony_ci    struct OH_Huks_Blob *importedKeyAlias;
73e41f4b71Sopenharmony_ci    struct OH_Huks_Blob *importedPlainKey;
74e41f4b71Sopenharmony_ci    uint32_t keyMaterialLen;
75e41f4b71Sopenharmony_ci};
76e41f4b71Sopenharmony_cistatic const uint32_t IV_SIZE = 16;
77e41f4b71Sopenharmony_cistatic uint8_t IV[IV_SIZE] = "babababababab"; // Test data only. The value must be different each time.
78e41f4b71Sopenharmony_cistatic const uint32_t WRAPPED_KEY_IV_SIZE = 16;
79e41f4b71Sopenharmony_cistatic uint8_t WRAPPED_KEY_IV[IV_SIZE] = "bababababababab"; // Test data only. The value must be different each time.
80e41f4b71Sopenharmony_cistatic const uint32_t AAD_SIZE = 16;
81e41f4b71Sopenharmony_cistatic uint8_t AAD[AAD_SIZE] = "abababababababa"; // Test data only. The value must be different each time.
82e41f4b71Sopenharmony_cistatic const uint32_t NONCE_SIZE = 12;
83e41f4b71Sopenharmony_cistatic uint8_t NONCE[NONCE_SIZE] = "hahahahahah"; // Test data only. The value must be different each time.
84e41f4b71Sopenharmony_cistatic const uint32_t AEAD_TAG_SIZE = 16;
85e41f4b71Sopenharmony_cistatic const uint32_t X25519_256_SIZE = 256;
86e41f4b71Sopenharmony_cistatic struct OH_Huks_Blob g_wrappingKeyAliasAes256 = {.size = (uint32_t)strlen("test_wrappingKey_x25519_aes256"),
87e41f4b71Sopenharmony_ci                                                       .data = (uint8_t *)"test_wrappingKey_x25519_aes256"};
88e41f4b71Sopenharmony_cistatic struct OH_Huks_Blob g_callerKeyAliasAes256 = {.size = (uint32_t)strlen("test_caller_key_x25519_aes256"),
89e41f4b71Sopenharmony_ci                                                     .data = (uint8_t *)"test_caller_key_x25519_aes256"};
90e41f4b71Sopenharmony_cistatic struct OH_Huks_Blob g_callerKekAliasAes256 = {.size = (uint32_t)strlen("test_caller_kek_x25519_aes256"),
91e41f4b71Sopenharmony_ci                                                     .data = (uint8_t *)"test_caller_kek_x25519_aes256"};
92e41f4b71Sopenharmony_cistatic struct OH_Huks_Blob g_callerAes256Kek = {.size = (uint32_t)strlen("This is kek to encrypt plain key"),
93e41f4b71Sopenharmony_ci                                                .data = (uint8_t *)"This is kek to encrypt plain key"};
94e41f4b71Sopenharmony_cistatic struct OH_Huks_Blob g_callerAgreeKeyAliasAes256 = {.size =
95e41f4b71Sopenharmony_ci                                                              (uint32_t)strlen("test_caller_agree_key_x25519_aes256"),
96e41f4b71Sopenharmony_ci                                                          .data = (uint8_t *)"test_caller_agree_key_x25519_aes256"};
97e41f4b71Sopenharmony_cistatic struct OH_Huks_Blob g_importedKeyAliasAes256 = {.size = (uint32_t)strlen("test_import_key_x25519_aes256"),
98e41f4b71Sopenharmony_ci                                                       .data = (uint8_t *)"test_import_key_x25519_aes256"};
99e41f4b71Sopenharmony_cistatic struct OH_Huks_Blob g_importedAes256PlainKey = {.size = (uint32_t)strlen("This is plain key to be imported"),
100e41f4b71Sopenharmony_ci                                                       .data = (uint8_t *)"This is plain key to be imported"};
101e41f4b71Sopenharmony_cistatic struct OH_Huks_Param g_importWrappedAes256Params[] = {
102e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
103e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT | OH_HUKS_KEY_PURPOSE_DECRYPT},
104e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
105e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE},
106e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM},
107e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE},
108e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_UNWRAP_ALGORITHM_SUITE, .uint32Param = OH_HUKS_UNWRAP_SUITE_X25519_AES_256_GCM_NOPADDING},
109e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_ASSOCIATED_DATA,
110e41f4b71Sopenharmony_ci     .blob = {.size = AAD_SIZE, .data = (uint8_t *)AAD}}, // Test data only. The value varies with the caller information.
111e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_NONCE,
112e41f4b71Sopenharmony_ci     .blob = {.size = NONCE_SIZE, .data = (uint8_t *)NONCE}}}; // Test data only. The value must be different each time.
113e41f4b71Sopenharmony_cistatic const uint32_t g_x25519PubKeySize = 32;
114e41f4b71Sopenharmony_cistatic struct OH_Huks_Param g_genWrappingKeyParams[] = {
115e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519},
116e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_UNWRAP},
117e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}};
118e41f4b71Sopenharmony_cistatic struct OH_Huks_Param g_genCallerX25519Params[] = {
119e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519},
120e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE},
121e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}};
122e41f4b71Sopenharmony_cistatic struct OH_Huks_Param g_importParamsCallerKek[] = {
123e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
124e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT},
125e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
126e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE},
127e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM},
128e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE},
129e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_IV,
130e41f4b71Sopenharmony_ci     .blob = {.size = WRAPPED_KEY_IV_SIZE,
131e41f4b71Sopenharmony_ci              .data = (uint8_t *)WRAPPED_KEY_IV}}}; // Test data only. The value must be different each time.
132e41f4b71Sopenharmony_cistatic struct OH_Huks_Param g_callerAgreeParams[] = {
133e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519},
134e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE},
135e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}};
136e41f4b71Sopenharmony_cistatic struct OH_Huks_Param g_aesKekEncryptParams[] = {
137e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
138e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT},
139e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
140e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE},
141e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM},
142e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE},
143e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_ASSOCIATED_DATA,
144e41f4b71Sopenharmony_ci     .blob = {.size = AAD_SIZE, .data = (uint8_t *)AAD}}, // Test data only. The value varies with the caller information.
145e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_NONCE,
146e41f4b71Sopenharmony_ci     .blob = {.size = NONCE_SIZE, .data = (uint8_t *)NONCE}}}; // Test data only. The value must be different each time.
147e41f4b71Sopenharmony_cistatic struct OH_Huks_Param g_importAgreeKeyParams[] = {
148e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
149e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT},
150e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
151e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE},
152e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM},
153e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE},
154e41f4b71Sopenharmony_ci    {.tag = OH_HUKS_TAG_IV,
155e41f4b71Sopenharmony_ci     .blob = {.size = IV_SIZE, .data = (uint8_t *)IV}}}; // Test data only. The value must be different each time.
156e41f4b71Sopenharmony_ciOH_Huks_Result HuksAgreeKey(const struct OH_Huks_ParamSet *paramSet, const struct OH_Huks_Blob *keyAlias,
157e41f4b71Sopenharmony_ci                            const struct OH_Huks_Blob *peerPublicKey, struct OH_Huks_Blob *agreedKey) {
158e41f4b71Sopenharmony_ci    uint8_t temp[10] = {0};
159e41f4b71Sopenharmony_ci    struct OH_Huks_Blob inData = {sizeof(temp), temp};
160e41f4b71Sopenharmony_ci    uint8_t handleU[sizeof(uint64_t)] = {0};
161e41f4b71Sopenharmony_ci    struct OH_Huks_Blob handle = {sizeof(uint64_t), handleU};
162e41f4b71Sopenharmony_ci    OH_Huks_Result ret = OH_Huks_InitSession(keyAlias, paramSet, &handle, nullptr);
163e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
164e41f4b71Sopenharmony_ci        return ret;
165e41f4b71Sopenharmony_ci    }
166e41f4b71Sopenharmony_ci    uint8_t outDataU[1024] = {0};
167e41f4b71Sopenharmony_ci    struct OH_Huks_Blob outDataUpdate = {1024, outDataU};
168e41f4b71Sopenharmony_ci    ret = OH_Huks_UpdateSession(&handle, paramSet, peerPublicKey, &outDataUpdate);
169e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
170e41f4b71Sopenharmony_ci        return ret;
171e41f4b71Sopenharmony_ci    }
172e41f4b71Sopenharmony_ci    ret = OH_Huks_FinishSession(&handle, paramSet, &inData, agreedKey);
173e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
174e41f4b71Sopenharmony_ci        return ret;
175e41f4b71Sopenharmony_ci    }
176e41f4b71Sopenharmony_ci    return ret;
177e41f4b71Sopenharmony_ci}
178e41f4b71Sopenharmony_ciOH_Huks_Result MallocAndCheckBlobData(struct OH_Huks_Blob *blob, const uint32_t blobSize) {
179e41f4b71Sopenharmony_ci    struct OH_Huks_Result ret;
180e41f4b71Sopenharmony_ci    ret.errorCode = OH_HUKS_SUCCESS;
181e41f4b71Sopenharmony_ci    blob->data = (uint8_t *)malloc(blobSize);
182e41f4b71Sopenharmony_ci    if (blob->data == NULL) {
183e41f4b71Sopenharmony_ci        ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
184e41f4b71Sopenharmony_ci    }
185e41f4b71Sopenharmony_ci    return ret;
186e41f4b71Sopenharmony_ci}
187e41f4b71Sopenharmony_cistatic const uint32_t TIMES = 4;
188e41f4b71Sopenharmony_cistatic const uint32_t MAX_UPDATE_SIZE = 64;
189e41f4b71Sopenharmony_cistatic const uint32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES;
190e41f4b71Sopenharmony_ci#define HUKS_FREE_BLOB(blob)                                                                                           \
191e41f4b71Sopenharmony_ci    do {                                                                                                               \
192e41f4b71Sopenharmony_ci        if ((blob).data != nullptr) {                                                                                  \
193e41f4b71Sopenharmony_ci            free((blob).data);                                                                                         \
194e41f4b71Sopenharmony_ci            (blob).data = nullptr;                                                                                     \
195e41f4b71Sopenharmony_ci        }                                                                                                              \
196e41f4b71Sopenharmony_ci        (blob).size = 0;                                                                                               \
197e41f4b71Sopenharmony_ci    } while (0)
198e41f4b71Sopenharmony_ci#define OH_HUKS_KEY_BYTES(keySize) (((keySize) + 7) / 8)
199e41f4b71Sopenharmony_cistatic OH_Huks_Result HksEncryptLoopUpdate(const struct OH_Huks_Blob *handle, const struct OH_Huks_ParamSet *paramSet,
200e41f4b71Sopenharmony_ci                                           const struct OH_Huks_Blob *inData, struct OH_Huks_Blob *outData) {
201e41f4b71Sopenharmony_ci    struct OH_Huks_Result ret;
202e41f4b71Sopenharmony_ci    ret.errorCode = OH_HUKS_SUCCESS;
203e41f4b71Sopenharmony_ci    struct OH_Huks_Blob inDataSeg = *inData;
204e41f4b71Sopenharmony_ci    uint8_t *lastPtr = inData->data + inData->size - 1;
205e41f4b71Sopenharmony_ci    struct OH_Huks_Blob outDataSeg = {MAX_OUTDATA_SIZE, NULL};
206e41f4b71Sopenharmony_ci    uint8_t *cur = outData->data;
207e41f4b71Sopenharmony_ci    outData->size = 0;
208e41f4b71Sopenharmony_ci    inDataSeg.size = MAX_UPDATE_SIZE;
209e41f4b71Sopenharmony_ci    bool isFinished = false;
210e41f4b71Sopenharmony_ci    while (inDataSeg.data <= lastPtr) {
211e41f4b71Sopenharmony_ci        if (inDataSeg.data + MAX_UPDATE_SIZE <= lastPtr) {
212e41f4b71Sopenharmony_ci            outDataSeg.size = MAX_OUTDATA_SIZE;
213e41f4b71Sopenharmony_ci        } else {
214e41f4b71Sopenharmony_ci            isFinished = true;
215e41f4b71Sopenharmony_ci            inDataSeg.size = lastPtr - inDataSeg.data + 1;
216e41f4b71Sopenharmony_ci            break;
217e41f4b71Sopenharmony_ci        }
218e41f4b71Sopenharmony_ci        if (MallocAndCheckBlobData(&outDataSeg, outDataSeg.size).errorCode != (int32_t)OH_HUKS_SUCCESS) {
219e41f4b71Sopenharmony_ci            ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
220e41f4b71Sopenharmony_ci            return ret;
221e41f4b71Sopenharmony_ci        }
222e41f4b71Sopenharmony_ci        ret = OH_Huks_UpdateSession(handle, paramSet, &inDataSeg, &outDataSeg);
223e41f4b71Sopenharmony_ci        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
224e41f4b71Sopenharmony_ci            free(outDataSeg.data);
225e41f4b71Sopenharmony_ci            return ret;
226e41f4b71Sopenharmony_ci        }
227e41f4b71Sopenharmony_ci        std::copy(outDataSeg.data, outDataSeg.data + outDataSeg.size, cur);
228e41f4b71Sopenharmony_ci        cur += outDataSeg.size;
229e41f4b71Sopenharmony_ci        outData->size += outDataSeg.size;
230e41f4b71Sopenharmony_ci        free(outDataSeg.data);
231e41f4b71Sopenharmony_ci        if ((isFinished == false) && (inDataSeg.data + MAX_UPDATE_SIZE > lastPtr)) {
232e41f4b71Sopenharmony_ci            ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
233e41f4b71Sopenharmony_ci            return ret;
234e41f4b71Sopenharmony_ci        }
235e41f4b71Sopenharmony_ci        inDataSeg.data += MAX_UPDATE_SIZE;
236e41f4b71Sopenharmony_ci    }
237e41f4b71Sopenharmony_ci    struct OH_Huks_Blob outDataFinish = {inDataSeg.size * TIMES, NULL};
238e41f4b71Sopenharmony_ci    if (MallocAndCheckBlobData(&outDataFinish, outDataFinish.size).errorCode != (int32_t)OH_HUKS_SUCCESS) {
239e41f4b71Sopenharmony_ci        ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
240e41f4b71Sopenharmony_ci        return ret;
241e41f4b71Sopenharmony_ci    }
242e41f4b71Sopenharmony_ci    ret = OH_Huks_FinishSession(handle, paramSet, &inDataSeg, &outDataFinish);
243e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
244e41f4b71Sopenharmony_ci        free(outDataFinish.data);
245e41f4b71Sopenharmony_ci        return ret;
246e41f4b71Sopenharmony_ci    }
247e41f4b71Sopenharmony_ci    std::copy(outDataFinish.data, outDataFinish.data + outDataFinish.size, cur);
248e41f4b71Sopenharmony_ci    outData->size += outDataFinish.size;
249e41f4b71Sopenharmony_ci    free(outDataFinish.data);
250e41f4b71Sopenharmony_ci    return ret;
251e41f4b71Sopenharmony_ci}
252e41f4b71Sopenharmony_ciOH_Huks_Result HuksEncrypt(const struct OH_Huks_Blob *key, const struct OH_Huks_ParamSet *paramSet,
253e41f4b71Sopenharmony_ci                           const struct OH_Huks_Blob *plainText, struct OH_Huks_Blob *cipherText) {
254e41f4b71Sopenharmony_ci    uint8_t handle[sizeof(uint64_t)] = {0};
255e41f4b71Sopenharmony_ci    struct OH_Huks_Blob handleBlob = {sizeof(uint64_t), handle};
256e41f4b71Sopenharmony_ci    OH_Huks_Result ret = OH_Huks_InitSession(key, paramSet, &handleBlob, nullptr);
257e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
258e41f4b71Sopenharmony_ci        return ret;
259e41f4b71Sopenharmony_ci    }
260e41f4b71Sopenharmony_ci    ret = HksEncryptLoopUpdate(&handleBlob, paramSet, plainText, cipherText);
261e41f4b71Sopenharmony_ci    return ret;
262e41f4b71Sopenharmony_ci}
263e41f4b71Sopenharmony_cistatic OH_Huks_Result BuildWrappedKeyData(struct OH_Huks_Blob **blobArray, uint32_t size,
264e41f4b71Sopenharmony_ci                                          struct OH_Huks_Blob *outData) {
265e41f4b71Sopenharmony_ci    uint32_t totalLength = size * sizeof(uint32_t);
266e41f4b71Sopenharmony_ci    struct OH_Huks_Result ret;
267e41f4b71Sopenharmony_ci    ret.errorCode = OH_HUKS_SUCCESS;
268e41f4b71Sopenharmony_ci    /* Data size. */
269e41f4b71Sopenharmony_ci    for (uint32_t i = 0; i < size; ++i) {
270e41f4b71Sopenharmony_ci        totalLength += blobArray[i]->size;
271e41f4b71Sopenharmony_ci    }
272e41f4b71Sopenharmony_ci    struct OH_Huks_Blob outBlob = {0, nullptr};
273e41f4b71Sopenharmony_ci    outBlob.size = totalLength;
274e41f4b71Sopenharmony_ci    ret = MallocAndCheckBlobData(&outBlob, outBlob.size);
275e41f4b71Sopenharmony_ci    if (ret.errorCode != OH_HUKS_SUCCESS) {
276e41f4b71Sopenharmony_ci        return ret;
277e41f4b71Sopenharmony_ci    }
278e41f4b71Sopenharmony_ci    uint32_t offset = 0;
279e41f4b71Sopenharmony_ci    /* Copy data. */
280e41f4b71Sopenharmony_ci    for (uint32_t i = 0; i < size; ++i) {
281e41f4b71Sopenharmony_ci        if (totalLength - offset >= sizeof(blobArray[i]->size)) {
282e41f4b71Sopenharmony_ci            std::copy(reinterpret_cast<uint8_t *>(&blobArray[i]->size),
283e41f4b71Sopenharmony_ci                      reinterpret_cast<uint8_t *>(&blobArray[i]->size) + sizeof(blobArray[i]->size),
284e41f4b71Sopenharmony_ci                      outBlob.data + offset);
285e41f4b71Sopenharmony_ci        } else {
286e41f4b71Sopenharmony_ci            ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
287e41f4b71Sopenharmony_ci            return ret;
288e41f4b71Sopenharmony_ci        }
289e41f4b71Sopenharmony_ci        offset += sizeof(blobArray[i]->size);
290e41f4b71Sopenharmony_ci        if (totalLength - offset >= blobArray[i]->size) {
291e41f4b71Sopenharmony_ci            std::copy(blobArray[i]->data, blobArray[i]->data + blobArray[i]->size, outBlob.data + offset);
292e41f4b71Sopenharmony_ci        } else {
293e41f4b71Sopenharmony_ci            ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
294e41f4b71Sopenharmony_ci            return ret;
295e41f4b71Sopenharmony_ci        }
296e41f4b71Sopenharmony_ci        offset += blobArray[i]->size;
297e41f4b71Sopenharmony_ci    }
298e41f4b71Sopenharmony_ci    outData->size = outBlob.size;
299e41f4b71Sopenharmony_ci    outData->data = outBlob.data;
300e41f4b71Sopenharmony_ci    return ret;
301e41f4b71Sopenharmony_ci}
302e41f4b71Sopenharmony_cistatic OH_Huks_Result CheckParamsValid(const struct HksImportWrappedKeyTestParams *params) {
303e41f4b71Sopenharmony_ci    struct OH_Huks_Result ret;
304e41f4b71Sopenharmony_ci    ret.errorCode = OH_HUKS_SUCCESS;
305e41f4b71Sopenharmony_ci    if (params == nullptr) {
306e41f4b71Sopenharmony_ci        ret.errorCode = OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT;
307e41f4b71Sopenharmony_ci        return ret;
308e41f4b71Sopenharmony_ci    }
309e41f4b71Sopenharmony_ci    if (params->wrappingKeyAlias == nullptr || params->genWrappingKeyParamSet == nullptr ||
310e41f4b71Sopenharmony_ci        params->callerKeyAlias == nullptr || params->genCallerKeyParamSet == nullptr ||
311e41f4b71Sopenharmony_ci        params->callerKekAlias == nullptr || params->callerKek == nullptr ||
312e41f4b71Sopenharmony_ci        params->importCallerKekParamSet == nullptr || params->callerAgreeKeyAlias == nullptr ||
313e41f4b71Sopenharmony_ci        params->agreeParamSet == nullptr || params->importWrappedKeyParamSet == nullptr ||
314e41f4b71Sopenharmony_ci        params->importedKeyAlias == nullptr || params->importedPlainKey == nullptr) {
315e41f4b71Sopenharmony_ci        ret.errorCode = OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT;
316e41f4b71Sopenharmony_ci        return ret;
317e41f4b71Sopenharmony_ci    }
318e41f4b71Sopenharmony_ci    return ret;
319e41f4b71Sopenharmony_ci}
320e41f4b71Sopenharmony_cistatic OH_Huks_Result GenerateAndExportHuksPublicKey(const struct HksImportWrappedKeyTestParams *params,
321e41f4b71Sopenharmony_ci                                                     struct OH_Huks_Blob *huksPublicKey) {
322e41f4b71Sopenharmony_ci    OH_Huks_Result ret = OH_Huks_GenerateKeyItem(params->wrappingKeyAlias, params->genWrappingKeyParamSet, nullptr);
323e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
324e41f4b71Sopenharmony_ci        return ret;
325e41f4b71Sopenharmony_ci    }
326e41f4b71Sopenharmony_ci    huksPublicKey->size = params->publicKeySize;
327e41f4b71Sopenharmony_ci    ret = MallocAndCheckBlobData(huksPublicKey, huksPublicKey->size);
328e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
329e41f4b71Sopenharmony_ci        return ret;
330e41f4b71Sopenharmony_ci    }
331e41f4b71Sopenharmony_ci    ret = OH_Huks_ExportPublicKeyItem(params->wrappingKeyAlias, nullptr, huksPublicKey);
332e41f4b71Sopenharmony_ci    return ret;
333e41f4b71Sopenharmony_ci}
334e41f4b71Sopenharmony_cistatic OH_Huks_Result GenerateAndExportCallerPublicKey(const struct HksImportWrappedKeyTestParams *params,
335e41f4b71Sopenharmony_ci                                                       struct OH_Huks_Blob *callerSelfPublicKey) {
336e41f4b71Sopenharmony_ci    OH_Huks_Result ret = OH_Huks_GenerateKeyItem(params->callerKeyAlias, params->genCallerKeyParamSet, nullptr);
337e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
338e41f4b71Sopenharmony_ci        return ret;
339e41f4b71Sopenharmony_ci    }
340e41f4b71Sopenharmony_ci    callerSelfPublicKey->size = params->publicKeySize;
341e41f4b71Sopenharmony_ci    ret = MallocAndCheckBlobData(callerSelfPublicKey, callerSelfPublicKey->size);
342e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
343e41f4b71Sopenharmony_ci        return ret;
344e41f4b71Sopenharmony_ci    }
345e41f4b71Sopenharmony_ci    ret = OH_Huks_ExportPublicKeyItem(params->callerKeyAlias, params->genWrappingKeyParamSet, callerSelfPublicKey);
346e41f4b71Sopenharmony_ci    return ret;
347e41f4b71Sopenharmony_ci}
348e41f4b71Sopenharmony_cistatic OH_Huks_Result ImportKekAndAgreeSharedSecret(const struct HksImportWrappedKeyTestParams *params,
349e41f4b71Sopenharmony_ci                                                    const struct OH_Huks_Blob *huksPublicKey,
350e41f4b71Sopenharmony_ci                                                    struct OH_Huks_Blob *outSharedKey) {
351e41f4b71Sopenharmony_ci    OH_Huks_Result ret =
352e41f4b71Sopenharmony_ci        OH_Huks_ImportKeyItem(params->callerKekAlias, params->importCallerKekParamSet, params->callerKek);
353e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
354e41f4b71Sopenharmony_ci        return ret;
355e41f4b71Sopenharmony_ci    }
356e41f4b71Sopenharmony_ci    ret = MallocAndCheckBlobData(outSharedKey, outSharedKey->size);
357e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
358e41f4b71Sopenharmony_ci        return ret;
359e41f4b71Sopenharmony_ci    }
360e41f4b71Sopenharmony_ci    ret = HuksAgreeKey(params->agreeParamSet, params->callerKeyAlias, huksPublicKey, outSharedKey);
361e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
362e41f4b71Sopenharmony_ci        return ret;
363e41f4b71Sopenharmony_ci    }
364e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *importAgreeKeyParams = nullptr;
365e41f4b71Sopenharmony_ci    ret = InitParamSet(&importAgreeKeyParams, g_importAgreeKeyParams,
366e41f4b71Sopenharmony_ci                       sizeof(g_importAgreeKeyParams) / sizeof(OH_Huks_Param));
367e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
368e41f4b71Sopenharmony_ci        return ret;
369e41f4b71Sopenharmony_ci    }
370e41f4b71Sopenharmony_ci    ret = OH_Huks_ImportKeyItem(params->callerAgreeKeyAlias, importAgreeKeyParams, outSharedKey);
371e41f4b71Sopenharmony_ci    OH_Huks_FreeParamSet(&importAgreeKeyParams);
372e41f4b71Sopenharmony_ci    return ret;
373e41f4b71Sopenharmony_ci}
374e41f4b71Sopenharmony_cistatic OH_Huks_Result EncryptImportedPlainKeyAndKek(const struct HksImportWrappedKeyTestParams *params,
375e41f4b71Sopenharmony_ci                                                    struct OH_Huks_Blob *plainCipherText,
376e41f4b71Sopenharmony_ci                                                    struct OH_Huks_Blob *kekCipherText) {
377e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *encryptParamSet = nullptr;
378e41f4b71Sopenharmony_ci    OH_Huks_Result ret =
379e41f4b71Sopenharmony_ci        InitParamSet(&encryptParamSet, g_aesKekEncryptParams, sizeof(g_aesKekEncryptParams) / sizeof(OH_Huks_Param));
380e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
381e41f4b71Sopenharmony_ci        return ret;
382e41f4b71Sopenharmony_ci    }
383e41f4b71Sopenharmony_ci    ret = HuksEncrypt(params->callerKekAlias, encryptParamSet, params->importedPlainKey, plainCipherText);
384e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
385e41f4b71Sopenharmony_ci        return ret;
386e41f4b71Sopenharmony_ci    }
387e41f4b71Sopenharmony_ci    ret = HuksEncrypt(params->callerAgreeKeyAlias, encryptParamSet, params->callerKek, kekCipherText);
388e41f4b71Sopenharmony_ci    OH_Huks_FreeParamSet(&encryptParamSet);
389e41f4b71Sopenharmony_ci    return ret;
390e41f4b71Sopenharmony_ci}
391e41f4b71Sopenharmony_cistatic OH_Huks_Result ImportWrappedKey(const struct HksImportWrappedKeyTestParams *params,
392e41f4b71Sopenharmony_ci                                       struct OH_Huks_Blob *plainCipher, struct OH_Huks_Blob *kekCipherText,
393e41f4b71Sopenharmony_ci                                       struct OH_Huks_Blob *peerPublicKey, struct OH_Huks_Blob *wrappedKeyData) {
394e41f4b71Sopenharmony_ci    struct OH_Huks_Blob commonAad = {.size = AAD_SIZE, .data = reinterpret_cast<uint8_t *>(AAD)};
395e41f4b71Sopenharmony_ci    struct OH_Huks_Blob commonNonce = {.size = NONCE_SIZE, .data = reinterpret_cast<uint8_t *>(NONCE)};
396e41f4b71Sopenharmony_ci    struct OH_Huks_Blob keyMaterialLen = {.size = sizeof(uint32_t), .data = (uint8_t *)&params->keyMaterialLen};
397e41f4b71Sopenharmony_ci    /* Copy the AEAD tag from the ciphertext and reduce its size. */
398e41f4b71Sopenharmony_ci    const uint32_t tagSize = AEAD_TAG_SIZE;
399e41f4b71Sopenharmony_ci    uint8_t kekTagBuf[tagSize] = {0};
400e41f4b71Sopenharmony_ci    struct OH_Huks_Blob kekTag = {.size = tagSize, .data = kekTagBuf};
401e41f4b71Sopenharmony_ci    std::copy(plainCipher->data + (plainCipher->size - tagSize),
402e41f4b71Sopenharmony_ci              plainCipher->data + (plainCipher->size - tagSize) + tagSize, kekTag.data);
403e41f4b71Sopenharmony_ci    plainCipher->size -= tagSize;
404e41f4b71Sopenharmony_ci    /* Copy the AEAD tag from kekCipherText and reduce the tag size. */
405e41f4b71Sopenharmony_ci    uint8_t agreeKeyTagBuf[tagSize] = {0};
406e41f4b71Sopenharmony_ci    struct OH_Huks_Blob agreeKeyTag = {.size = tagSize, .data = agreeKeyTagBuf};
407e41f4b71Sopenharmony_ci    std::copy(kekCipherText->data + (kekCipherText->size - tagSize),
408e41f4b71Sopenharmony_ci              kekCipherText->data + (kekCipherText->size - tagSize) + tagSize, agreeKeyTagBuf);
409e41f4b71Sopenharmony_ci    kekCipherText->size -= tagSize;
410e41f4b71Sopenharmony_ci    struct OH_Huks_Blob *blobArray[] = {peerPublicKey, &commonAad,   &commonNonce, &agreeKeyTag,    kekCipherText,
411e41f4b71Sopenharmony_ci                                        &commonAad,    &commonNonce, &kekTag,      &keyMaterialLen, plainCipher};
412e41f4b71Sopenharmony_ci    OH_Huks_Result ret = BuildWrappedKeyData(blobArray, OH_HUKS_IMPORT_WRAPPED_KEY_TOTAL_BLOBS, wrappedKeyData);
413e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
414e41f4b71Sopenharmony_ci        return ret;
415e41f4b71Sopenharmony_ci    }
416e41f4b71Sopenharmony_ci    struct OH_Huks_Param *purpose = nullptr;
417e41f4b71Sopenharmony_ci    ret = OH_Huks_GetParam(params->importWrappedKeyParamSet, OH_HUKS_TAG_PURPOSE, &purpose);
418e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
419e41f4b71Sopenharmony_ci        return ret;
420e41f4b71Sopenharmony_ci    }
421e41f4b71Sopenharmony_ci    ret = OH_Huks_ImportWrappedKeyItem(params->importedKeyAlias, params->wrappingKeyAlias,
422e41f4b71Sopenharmony_ci                                       params->importWrappedKeyParamSet, wrappedKeyData);
423e41f4b71Sopenharmony_ci    return ret;
424e41f4b71Sopenharmony_ci}
425e41f4b71Sopenharmony_ciOH_Huks_Result HksImportWrappedKeyTestCommonCase(const struct HksImportWrappedKeyTestParams *params) {
426e41f4b71Sopenharmony_ci    OH_Huks_Result ret = CheckParamsValid(params);
427e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
428e41f4b71Sopenharmony_ci        return ret;
429e41f4b71Sopenharmony_ci    }
430e41f4b71Sopenharmony_ci    struct OH_Huks_Blob huksPublicKey = {0, nullptr};
431e41f4b71Sopenharmony_ci    struct OH_Huks_Blob callerSelfPublicKey = {0, nullptr};
432e41f4b71Sopenharmony_ci    struct OH_Huks_Blob outSharedKey = {.size = OH_HUKS_KEY_BYTES(OH_HUKS_AES_KEY_SIZE_256), .data = nullptr};
433e41f4b71Sopenharmony_ci    struct OH_Huks_Blob wrappedKeyData = {0, nullptr};
434e41f4b71Sopenharmony_ci    uint8_t plainKeyCipherBuffer[OH_HUKS_MAX_KEY_SIZE] = {0};
435e41f4b71Sopenharmony_ci    struct OH_Huks_Blob plainCipherText = {OH_HUKS_MAX_KEY_SIZE, plainKeyCipherBuffer};
436e41f4b71Sopenharmony_ci    uint8_t kekCipherTextBuffer[OH_HUKS_MAX_KEY_SIZE] = {0};
437e41f4b71Sopenharmony_ci    struct OH_Huks_Blob kekCipherText = {OH_HUKS_MAX_KEY_SIZE, kekCipherTextBuffer};
438e41f4b71Sopenharmony_ci    /* Simulate the encrypted key import scenario. Import a key from device A (remote device) to device B (local device). */
439e41f4b71Sopenharmony_ci    do {
440e41f4b71Sopenharmony_ci        /**
441e41f4b71Sopenharmony_ci         * 1. If the key to be imported from device A is an asymmetric key pair, convert it into the HUKS key material format **To_Import_Key**. Skip over this step if the key is a symmetric key.
442e41f4b71Sopenharmony_ci         * This example uses a 256-bit AES key (symmetric key) as an example.
443e41f4b71Sopenharmony_ci         */
444e41f4b71Sopenharmony_ci        /* 2. Generate an asymmetric key pair Wrapping_Key (public key Wrapping_Pk and private key Wrapping_Sk) with the purpose of HUKS_KEY_PURPOSE_UNWRAP for device B, export the public key Wrapping_Pk of Wrapping_Key, and save it to huksPubKey.
445e41f4b71Sopenharmony_ci         */
446e41f4b71Sopenharmony_ci        ret = GenerateAndExportHuksPublicKey(params, &huksPublicKey);
447e41f4b71Sopenharmony_ci        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
448e41f4b71Sopenharmony_ci            break;
449e41f4b71Sopenharmony_ci        }
450e41f4b71Sopenharmony_ci        /* 3. Use the same algorithm to generate an asymmetric key pair Caller_Key (public key Caller_Pk and private key Caller_Sk) with the purpose of HUKS_KEY_PURPOSE_UNWRAP for device A, export the public key Caller_Pk of Caller_Key, save it to callerSelfPublicKey.
451e41f4b71Sopenharmony_ci         */
452e41f4b71Sopenharmony_ci        ret = GenerateAndExportCallerPublicKey(params, &callerSelfPublicKey);
453e41f4b71Sopenharmony_ci        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
454e41f4b71Sopenharmony_ci            break;
455e41f4b71Sopenharmony_ci        }
456e41f4b71Sopenharmony_ci        /**
457e41f4b71Sopenharmony_ci         4. Generate a symmetric key Caller_Kek for device A. This key is used to encrypt To_Import_Key.
458e41f4b71Sopenharmony_ci         * 5. Perform key agreement with the private key **Caller_Sk** in **Caller_Key** of device A and the public key **Wrapping_Pk** in **Wrapping_Key** of device B to yield a **Shared_Key**.
459e41f4b71Sopenharmony_ci         */
460e41f4b71Sopenharmony_ci        ret = ImportKekAndAgreeSharedSecret(params, &huksPublicKey, &outSharedKey);
461e41f4b71Sopenharmony_ci        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
462e41f4b71Sopenharmony_ci            break;
463e41f4b71Sopenharmony_ci        }
464e41f4b71Sopenharmony_ci        /**
465e41f4b71Sopenharmony_ci         * 6. Use Caller_Kek to encrypt To_Import_Key of device A and generate To_Import_Key_Enc.
466e41f4b71Sopenharmony_ci         * 7. Use Shared_Key to encrypt Caller_Kek of device A and generate Caller_Kek_Enc.
467e41f4b71Sopenharmony_ci         */
468e41f4b71Sopenharmony_ci        ret = EncryptImportedPlainKeyAndKek(params, &plainCipherText, &kekCipherText);
469e41f4b71Sopenharmony_ci        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
470e41f4b71Sopenharmony_ci            break;
471e41f4b71Sopenharmony_ci        }
472e41f4b71Sopenharmony_ci        /* 8. Encapsulate the key material Caller_Pk, To_Import_Key_Enc, and Caller_Kek_Enc of device A, and sends it to device B.
473e41f4b71Sopenharmony_ci         * In this example, Caller_Pk is placed in callerSelfPublicKey, To_Import_Key_Enc in PlainKeyEncData, and Caller_Kek_Enc in KekEncData.
474e41f4b71Sopenharmony_ci         * 9. Import the encapsulated key material to device B.
475e41f4b71Sopenharmony_ci         */
476e41f4b71Sopenharmony_ci        ret = ImportWrappedKey(params, &plainCipherText, &kekCipherText, &callerSelfPublicKey, &wrappedKeyData);
477e41f4b71Sopenharmony_ci    } while (0);
478e41f4b71Sopenharmony_ci    /* 10. Delete the intermediate keys (keys used for encrypting the key to import) from devices A and B. */
479e41f4b71Sopenharmony_ci    HUKS_FREE_BLOB(huksPublicKey);
480e41f4b71Sopenharmony_ci    HUKS_FREE_BLOB(callerSelfPublicKey);
481e41f4b71Sopenharmony_ci    HUKS_FREE_BLOB(outSharedKey);
482e41f4b71Sopenharmony_ci    HUKS_FREE_BLOB(wrappedKeyData);
483e41f4b71Sopenharmony_ci    return ret;
484e41f4b71Sopenharmony_ci}
485e41f4b71Sopenharmony_civoid HksClearKeysForWrappedKeyTest(const struct HksImportWrappedKeyTestParams *params) {
486e41f4b71Sopenharmony_ci    OH_Huks_Result ret = CheckParamsValid(params);
487e41f4b71Sopenharmony_ci    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
488e41f4b71Sopenharmony_ci        return;
489e41f4b71Sopenharmony_ci    }
490e41f4b71Sopenharmony_ci    (void)OH_Huks_DeleteKeyItem(params->wrappingKeyAlias, nullptr);
491e41f4b71Sopenharmony_ci    (void)OH_Huks_DeleteKeyItem(params->callerKeyAlias, nullptr);
492e41f4b71Sopenharmony_ci    (void)OH_Huks_DeleteKeyItem(params->callerKekAlias, nullptr);
493e41f4b71Sopenharmony_ci    (void)OH_Huks_DeleteKeyItem(params->callerAgreeKeyAlias, nullptr);
494e41f4b71Sopenharmony_ci    (void)OH_Huks_DeleteKeyItem(params->importedKeyAlias, nullptr);
495e41f4b71Sopenharmony_ci}
496e41f4b71Sopenharmony_cistatic OH_Huks_Result InitCommonTestParamsAndDoImport(struct HksImportWrappedKeyTestParams *importWrappedKeyTestParams,
497e41f4b71Sopenharmony_ci                                                      const struct OH_Huks_Param *importedKeyParamSetArray,
498e41f4b71Sopenharmony_ci                                                      uint32_t arraySize) {
499e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *genX25519KeyParamSet = nullptr;
500e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *genCallerKeyParamSet = nullptr;
501e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *callerImportParamsKek = nullptr;
502e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *agreeParamSet = nullptr;
503e41f4b71Sopenharmony_ci    struct OH_Huks_ParamSet *importPlainKeyParams = nullptr;
504e41f4b71Sopenharmony_ci    OH_Huks_Result ret;
505e41f4b71Sopenharmony_ci    do {
506e41f4b71Sopenharmony_ci        ret = InitParamSet(&genX25519KeyParamSet, g_genWrappingKeyParams,
507e41f4b71Sopenharmony_ci                           sizeof(g_genWrappingKeyParams) / sizeof(OH_Huks_Param));
508e41f4b71Sopenharmony_ci        if (ret.errorCode != OH_HUKS_SUCCESS) {
509e41f4b71Sopenharmony_ci            break;
510e41f4b71Sopenharmony_ci        }
511e41f4b71Sopenharmony_ci        importWrappedKeyTestParams->genWrappingKeyParamSet = genX25519KeyParamSet;
512e41f4b71Sopenharmony_ci        importWrappedKeyTestParams->publicKeySize = g_x25519PubKeySize;
513e41f4b71Sopenharmony_ci        ret = InitParamSet(&genCallerKeyParamSet, g_genCallerX25519Params,
514e41f4b71Sopenharmony_ci                           sizeof(g_genCallerX25519Params) / sizeof(OH_Huks_Param));
515e41f4b71Sopenharmony_ci        if (ret.errorCode != OH_HUKS_SUCCESS) {
516e41f4b71Sopenharmony_ci            break;
517e41f4b71Sopenharmony_ci        }
518e41f4b71Sopenharmony_ci        importWrappedKeyTestParams->genCallerKeyParamSet = genCallerKeyParamSet;
519e41f4b71Sopenharmony_ci        ret = InitParamSet(&callerImportParamsKek, g_importParamsCallerKek,
520e41f4b71Sopenharmony_ci                           sizeof(g_importParamsCallerKek) / sizeof(OH_Huks_Param));
521e41f4b71Sopenharmony_ci        if (ret.errorCode != OH_HUKS_SUCCESS) {
522e41f4b71Sopenharmony_ci            break;
523e41f4b71Sopenharmony_ci        }
524e41f4b71Sopenharmony_ci        importWrappedKeyTestParams->importCallerKekParamSet = callerImportParamsKek;
525e41f4b71Sopenharmony_ci        ret = InitParamSet(&agreeParamSet, g_callerAgreeParams, sizeof(g_callerAgreeParams) / sizeof(OH_Huks_Param));
526e41f4b71Sopenharmony_ci        if (ret.errorCode != OH_HUKS_SUCCESS) {
527e41f4b71Sopenharmony_ci            break;
528e41f4b71Sopenharmony_ci        }
529e41f4b71Sopenharmony_ci        importWrappedKeyTestParams->agreeParamSet = agreeParamSet;
530e41f4b71Sopenharmony_ci        ret = InitParamSet(&importPlainKeyParams, importedKeyParamSetArray, arraySize);
531e41f4b71Sopenharmony_ci        if (ret.errorCode != OH_HUKS_SUCCESS) {
532e41f4b71Sopenharmony_ci            break;
533e41f4b71Sopenharmony_ci        }
534e41f4b71Sopenharmony_ci        importWrappedKeyTestParams->importWrappedKeyParamSet = importPlainKeyParams;
535e41f4b71Sopenharmony_ci        ret = HksImportWrappedKeyTestCommonCase(importWrappedKeyTestParams);
536e41f4b71Sopenharmony_ci    } while (0);
537e41f4b71Sopenharmony_ci    OH_Huks_FreeParamSet(&genX25519KeyParamSet);
538e41f4b71Sopenharmony_ci    OH_Huks_FreeParamSet(&genCallerKeyParamSet);
539e41f4b71Sopenharmony_ci    OH_Huks_FreeParamSet(&callerImportParamsKek);
540e41f4b71Sopenharmony_ci    OH_Huks_FreeParamSet(&agreeParamSet);
541e41f4b71Sopenharmony_ci    OH_Huks_FreeParamSet(&importPlainKeyParams);
542e41f4b71Sopenharmony_ci    return ret;
543e41f4b71Sopenharmony_ci}
544e41f4b71Sopenharmony_cistatic napi_value ImportWrappedKey(napi_env env, napi_callback_info info) {
545e41f4b71Sopenharmony_ci    struct HksImportWrappedKeyTestParams importWrappedKeyTestParams001 = {0};
546e41f4b71Sopenharmony_ci    importWrappedKeyTestParams001.wrappingKeyAlias = &g_wrappingKeyAliasAes256;
547e41f4b71Sopenharmony_ci    importWrappedKeyTestParams001.keyMaterialLen = g_importedAes256PlainKey.size;
548e41f4b71Sopenharmony_ci    importWrappedKeyTestParams001.callerKeyAlias = &g_callerKeyAliasAes256;
549e41f4b71Sopenharmony_ci    importWrappedKeyTestParams001.callerKekAlias = &g_callerKekAliasAes256;
550e41f4b71Sopenharmony_ci    importWrappedKeyTestParams001.callerKek = &g_callerAes256Kek;
551e41f4b71Sopenharmony_ci    importWrappedKeyTestParams001.callerAgreeKeyAlias = &g_callerAgreeKeyAliasAes256;
552e41f4b71Sopenharmony_ci    importWrappedKeyTestParams001.importedKeyAlias = &g_importedKeyAliasAes256;
553e41f4b71Sopenharmony_ci    importWrappedKeyTestParams001.importedPlainKey = &g_importedAes256PlainKey;
554e41f4b71Sopenharmony_ci    OH_Huks_Result ohResult =
555e41f4b71Sopenharmony_ci        InitCommonTestParamsAndDoImport(&importWrappedKeyTestParams001, g_importWrappedAes256Params,
556e41f4b71Sopenharmony_ci                                        sizeof(g_importWrappedAes256Params) / sizeof(struct OH_Huks_Param));
557e41f4b71Sopenharmony_ci    HksClearKeysForWrappedKeyTest(&importWrappedKeyTestParams001);
558e41f4b71Sopenharmony_ci    napi_value ret;
559e41f4b71Sopenharmony_ci    napi_create_int32(env, ohResult.errorCode, &ret);
560e41f4b71Sopenharmony_ci    return ret;
561e41f4b71Sopenharmony_ci}
562e41f4b71Sopenharmony_ci```
563e41f4b71Sopenharmony_ci
564e41f4b71Sopenharmony_ci
565e41f4b71Sopenharmony_ci## Verification
566e41f4b71Sopenharmony_ci
567e41f4b71Sopenharmony_ciUse [OH_Huks_IsKeyItemExist](../../reference/apis-universal-keystore-kit/_huks_key_api.md#oh_huks_iskeyitemexist) to check whether the key exists. If the key exists, the key is successfully imported.
568e41f4b71Sopenharmony_ci
569e41f4b71Sopenharmony_ci```c++
570e41f4b71Sopenharmony_ci#include "huks/native_huks_api.h"
571e41f4b71Sopenharmony_ci#include "huks/native_huks_param.h"
572e41f4b71Sopenharmony_ci#include <string.h>
573e41f4b71Sopenharmony_cistatic napi_value IsKeyExist(napi_env env, napi_callback_info info)
574e41f4b71Sopenharmony_ci{
575e41f4b71Sopenharmony_ci    /* 1. Set the key alias. */
576e41f4b71Sopenharmony_ci    struct OH_Huks_Blob keyAlias = {
577e41f4b71Sopenharmony_ci        (uint32_t)strlen("test_key"),
578e41f4b71Sopenharmony_ci        (uint8_t *)"test_key"
579e41f4b71Sopenharmony_ci    };
580e41f4b71Sopenharmony_ci    
581e41f4b71Sopenharmony_ci    /* 2. Call OH_Huks_IsKeyItemExist to check whether the key exists. */
582e41f4b71Sopenharmony_ci    struct OH_Huks_Result ohResult = OH_Huks_IsKeyItemExist(&keyAlias, NULL);
583e41f4b71Sopenharmony_ci    if (ohResult.errorCode != OH_HUKS_SUCCESS) {
584e41f4b71Sopenharmony_ci        // Operation failed.
585e41f4b71Sopenharmony_ci    } else {
586e41f4b71Sopenharmony_ci        // Operation successful.
587e41f4b71Sopenharmony_ci    }
588e41f4b71Sopenharmony_ci}
589e41f4b71Sopenharmony_ci```
590