• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 加密导入密钥(C/C++)
2
3以加密导入ECDH密钥对为例,涉及业务侧加密密钥的[密钥生成](huks-key-generation-overview.md)、[协商](huks-key-agreement-overview.md)等操作不在本示例中体现。
4
5具体的场景介绍及支持的算法规格,请参考[密钥导入的支持的算法](huks-key-import-overview.md#支持的算法)。
6
7## 在CMake脚本中链接相关动态库
8```txt
9target_link_libraries(entry PUBLIC libhuks_ndk.z.so)
10```
11
12## 开发步骤
13> **说明:**
14> 下文中wrap指加密,unwrap指解密。
151. 设备A(导入设备)将待导入密钥转换成[HUKS密钥材料格式](huks-concepts.md#密钥材料格式)To_Import_Key(仅针对非对称密钥,若待导入密钥是对称密钥则可省略此步骤)。
16
172. 设备B(被导入设备)生成一个加密导入用途的、用于协商的非对称密钥对Wrapping_Key(公钥Wrapping_Pk,私钥Wrapping_Sk),其密钥用途设置为unwrap,导出Wrapping_Key的公钥材料Wrapping_Pk并保存。
18
193. 设备A使用和设备B同样的算法,生成一个加密导入用途的、用于协商的非对称密钥对Caller_Key(公钥Caller_Pk,私钥Caller_Sk),导出Caller_Key的公钥材料Caller_Pk并保存。
20
214. 设备A生成一个对称密钥Caller_Kek,该密钥后续将用于加密To_Import_Key。
22
235. 设备A基于Caller_Key的私钥Caller_Sk和设备B Wrapping_Key的公钥Wrapping_Pk,协商出Shared_Key。
24
256. 设备A使用Caller_Kek加密To_Import_Key,生成To_Import_Key_Enc。
26
277. 设备A使用Shared_Key加密Caller_Kek,生成Caller_Kek_Enc。
28
298. 设备A封装Caller_Pk、Caller_Kek_Enc、To_Import_Key_Enc等加密导入的密钥材料并发送给设备B,加密导入密钥材料格式见[加密导入密钥材料格式](huks-key-import-overview.md#加密导入密钥材料格式)。
30
319. 设备B导入封装的加密密钥材料。
32
3310. 设备A、B删除用于加密导入的密钥。
34
35```c++
36#include "huks/native_huks_api.h"
37#include "huks/native_huks_param.h"
38#include "napi/native_api.h"
39#include <algorithm>
40OH_Huks_Result InitParamSet(struct OH_Huks_ParamSet **paramSet, const struct OH_Huks_Param *params,
41                            uint32_t paramCount) {
42    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
43    if (ret.errorCode != OH_HUKS_SUCCESS) {
44        return ret;
45    }
46    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
47    if (ret.errorCode != OH_HUKS_SUCCESS) {
48        OH_Huks_FreeParamSet(paramSet);
49        return ret;
50    }
51    ret = OH_Huks_BuildParamSet(paramSet);
52    if (ret.errorCode != OH_HUKS_SUCCESS) {
53        OH_Huks_FreeParamSet(paramSet);
54        return ret;
55    }
56    return ret;
57}
58struct HksImportWrappedKeyTestParams {
59    // server key, for real.
60    struct OH_Huks_Blob *wrappingKeyAlias;
61    struct OH_Huks_ParamSet *genWrappingKeyParamSet;
62    uint32_t publicKeySize;
63    struct OH_Huks_Blob *callerKeyAlias;
64    struct OH_Huks_ParamSet *genCallerKeyParamSet;
65    struct OH_Huks_Blob *callerKekAlias;
66    struct OH_Huks_Blob *callerKek;
67    struct OH_Huks_ParamSet *importCallerKekParamSet;
68    struct OH_Huks_Blob *callerAgreeKeyAlias;
69    struct OH_Huks_ParamSet *agreeParamSet;
70    struct OH_Huks_ParamSet *importWrappedKeyParamSet;
71    struct OH_Huks_Blob *importedKeyAlias;
72    struct OH_Huks_Blob *importedPlainKey;
73    uint32_t keyMaterialLen;
74};
75static const uint32_t IV_SIZE = 16;
76static uint8_t IV[IV_SIZE] = "bababababababab"; // 此处仅为测试数据,实际使用时该值每次应该不同。
77static const uint32_t WRAPPED_KEY_IV_SIZE = 16;
78static uint8_t WRAPPED_KEY_IV[IV_SIZE] = "bababababababab"; // 此处仅为测试数据,实际使用时该值每次应该不同。
79static const uint32_t AAD_SIZE = 16;
80static uint8_t AAD[AAD_SIZE] = "abababababababa"; // 此处仅为测试数据,实际使用时该值每次应该不同。
81static const uint32_t NONCE_SIZE = 12;
82static uint8_t NONCE[NONCE_SIZE] = "hahahahahah"; // 此处仅为测试数据,实际使用时该值每次应该不同。
83static const uint32_t AEAD_TAG_SIZE = 16;
84static const uint32_t X25519_256_SIZE = 256;
85static struct OH_Huks_Blob g_wrappingKeyAliasAes256 = {.size = (uint32_t)strlen("test_wrappingKey_x25519_aes256"),
86                                                       .data = (uint8_t *)"test_wrappingKey_x25519_aes256"};
87static struct OH_Huks_Blob g_callerKeyAliasAes256 = {.size = (uint32_t)strlen("test_caller_key_x25519_aes256"),
88                                                     .data = (uint8_t *)"test_caller_key_x25519_aes256"};
89static struct OH_Huks_Blob g_callerKekAliasAes256 = {.size = (uint32_t)strlen("test_caller_kek_x25519_aes256"),
90                                                     .data = (uint8_t *)"test_caller_kek_x25519_aes256"};
91static struct OH_Huks_Blob g_callerAes256Kek = {.size = (uint32_t)strlen("This is kek to encrypt plain key"),
92                                                .data = (uint8_t *)"This is kek to encrypt plain key"};
93static struct OH_Huks_Blob g_callerAgreeKeyAliasAes256 = {.size =
94                                                              (uint32_t)strlen("test_caller_agree_key_x25519_aes256"),
95                                                          .data = (uint8_t *)"test_caller_agree_key_x25519_aes256"};
96static struct OH_Huks_Blob g_importedKeyAliasAes256 = {.size = (uint32_t)strlen("test_import_key_x25519_aes256"),
97                                                       .data = (uint8_t *)"test_import_key_x25519_aes256"};
98static struct OH_Huks_Blob g_importedAes256PlainKey = {.size = (uint32_t)strlen("This is plain key to be imported"),
99                                                       .data = (uint8_t *)"This is plain key to be imported"};
100static struct OH_Huks_Param g_importWrappedAes256Params[] = {
101    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
102    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT | OH_HUKS_KEY_PURPOSE_DECRYPT},
103    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
104    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE},
105    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM},
106    {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE},
107    {.tag = OH_HUKS_TAG_UNWRAP_ALGORITHM_SUITE, .uint32Param = OH_HUKS_UNWRAP_SUITE_X25519_AES_256_GCM_NOPADDING},
108    {.tag = OH_HUKS_TAG_ASSOCIATED_DATA,
109     .blob = {.size = AAD_SIZE, .data = (uint8_t *)AAD}}, // 此处仅为测试数据,实际使用时该值应与调用者信息相关。
110    {.tag = OH_HUKS_TAG_NONCE,
111     .blob = {.size = NONCE_SIZE, .data = (uint8_t *)NONCE}}}; // 此处仅为测试数据,实际使用时该值每次应该不同。
112static const uint32_t g_x25519PubKeySize = 32;
113static struct OH_Huks_Param g_genWrappingKeyParams[] = {
114    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519},
115    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_UNWRAP},
116    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}};
117static struct OH_Huks_Param g_genCallerX25519Params[] = {
118    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519},
119    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE},
120    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}};
121static struct OH_Huks_Param g_importParamsCallerKek[] = {
122    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
123    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT},
124    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
125    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE},
126    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM},
127    {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE},
128    {.tag = OH_HUKS_TAG_IV,
129     .blob = {.size = WRAPPED_KEY_IV_SIZE,
130              .data = (uint8_t *)WRAPPED_KEY_IV}}}; // 此处仅为测试数据,实际使用时该值每次应该不同。
131static struct OH_Huks_Param g_callerAgreeParams[] = {
132    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519},
133    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE},
134    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}};
135static struct OH_Huks_Param g_aesKekEncryptParams[] = {
136    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
137    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT},
138    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
139    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE},
140    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM},
141    {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE},
142    {.tag = OH_HUKS_TAG_ASSOCIATED_DATA,
143     .blob = {.size = AAD_SIZE, .data = (uint8_t *)AAD}}, // 此处仅为测试数据,实际使用时该值应与调用者信息相关。
144    {.tag = OH_HUKS_TAG_NONCE,
145     .blob = {.size = NONCE_SIZE, .data = (uint8_t *)NONCE}}}; // 此处仅为测试数据,实际使用时该值每次应该不同。
146static struct OH_Huks_Param g_importAgreeKeyParams[] = {
147    {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES},
148    {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT},
149    {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256},
150    {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE},
151    {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM},
152    {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE},
153    {.tag = OH_HUKS_TAG_IV,
154     .blob = {.size = IV_SIZE, .data = (uint8_t *)IV}}}; // 此处仅为测试数据,实际使用时该值每次应该不同。
155OH_Huks_Result HuksAgreeKey(const struct OH_Huks_ParamSet *paramSet, const struct OH_Huks_Blob *keyAlias,
156                            const struct OH_Huks_Blob *peerPublicKey, struct OH_Huks_Blob *agreedKey) {
157    uint8_t temp[10] = {0};
158    struct OH_Huks_Blob inData = {sizeof(temp), temp};
159    uint8_t handleU[sizeof(uint64_t)] = {0};
160    struct OH_Huks_Blob handle = {sizeof(uint64_t), handleU};
161    OH_Huks_Result ret = OH_Huks_InitSession(keyAlias, paramSet, &handle, nullptr);
162    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
163        return ret;
164    }
165    uint8_t outDataU[1024] = {0};
166    struct OH_Huks_Blob outDataUpdate = {1024, outDataU};
167    ret = OH_Huks_UpdateSession(&handle, paramSet, peerPublicKey, &outDataUpdate);
168    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
169        return ret;
170    }
171    ret = OH_Huks_FinishSession(&handle, paramSet, &inData, agreedKey);
172    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
173        return ret;
174    }
175    return ret;
176}
177OH_Huks_Result MallocAndCheckBlobData(struct OH_Huks_Blob *blob, const uint32_t blobSize) {
178    struct OH_Huks_Result ret;
179    ret.errorCode = OH_HUKS_SUCCESS;
180    blob->data = (uint8_t *)malloc(blobSize);
181    if (blob->data == NULL) {
182        ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
183    }
184    return ret;
185}
186static const uint32_t TIMES = 4;
187static const uint32_t MAX_UPDATE_SIZE = 64;
188static const uint32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES;
189#define HUKS_FREE_BLOB(blob)                                                                                           \
190    do {                                                                                                               \
191        if ((blob).data != nullptr) {                                                                                  \
192            free((blob).data);                                                                                         \
193            (blob).data = nullptr;                                                                                     \
194        }                                                                                                              \
195        (blob).size = 0;                                                                                               \
196    } while (0)
197#define OH_HUKS_KEY_BYTES(keySize) (((keySize) + 7) / 8)
198static OH_Huks_Result HksEncryptLoopUpdate(const struct OH_Huks_Blob *handle, const struct OH_Huks_ParamSet *paramSet,
199                                           const struct OH_Huks_Blob *inData, struct OH_Huks_Blob *outData) {
200    struct OH_Huks_Result ret;
201    ret.errorCode = OH_HUKS_SUCCESS;
202    struct OH_Huks_Blob inDataSeg = *inData;
203    uint8_t *lastPtr = inData->data + inData->size - 1;
204    struct OH_Huks_Blob outDataSeg = {MAX_OUTDATA_SIZE, NULL};
205    uint8_t *cur = outData->data;
206    outData->size = 0;
207    inDataSeg.size = MAX_UPDATE_SIZE;
208    bool isFinished = false;
209    while (inDataSeg.data <= lastPtr) {
210        if (inDataSeg.data + MAX_UPDATE_SIZE <= lastPtr) {
211            outDataSeg.size = MAX_OUTDATA_SIZE;
212        } else {
213            isFinished = true;
214            inDataSeg.size = lastPtr - inDataSeg.data + 1;
215            break;
216        }
217        if (MallocAndCheckBlobData(&outDataSeg, outDataSeg.size).errorCode != (int32_t)OH_HUKS_SUCCESS) {
218            ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
219            return ret;
220        }
221        ret = OH_Huks_UpdateSession(handle, paramSet, &inDataSeg, &outDataSeg);
222        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
223            free(outDataSeg.data);
224            return ret;
225        }
226        std::copy(outDataSeg.data, outDataSeg.data + outDataSeg.size, cur);
227        cur += outDataSeg.size;
228        outData->size += outDataSeg.size;
229        free(outDataSeg.data);
230        if ((isFinished == false) && (inDataSeg.data + MAX_UPDATE_SIZE > lastPtr)) {
231            ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
232            return ret;
233        }
234        inDataSeg.data += MAX_UPDATE_SIZE;
235    }
236    struct OH_Huks_Blob outDataFinish = {inDataSeg.size * TIMES, NULL};
237    if (MallocAndCheckBlobData(&outDataFinish, outDataFinish.size).errorCode != (int32_t)OH_HUKS_SUCCESS) {
238        ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
239        return ret;
240    }
241    ret = OH_Huks_FinishSession(handle, paramSet, &inDataSeg, &outDataFinish);
242    if (ret.errorCode != OH_HUKS_SUCCESS) {
243        free(outDataFinish.data);
244        return ret;
245    }
246    std::copy(outDataFinish.data, outDataFinish.data + outDataFinish.size, cur);
247    outData->size += outDataFinish.size;
248    free(outDataFinish.data);
249    return ret;
250}
251OH_Huks_Result HuksEncrypt(const struct OH_Huks_Blob *key, const struct OH_Huks_ParamSet *paramSet,
252                           const struct OH_Huks_Blob *plainText, struct OH_Huks_Blob *cipherText) {
253    uint8_t handle[sizeof(uint64_t)] = {0};
254    struct OH_Huks_Blob handleBlob = {sizeof(uint64_t), handle};
255    OH_Huks_Result ret = OH_Huks_InitSession(key, paramSet, &handleBlob, nullptr);
256    if (ret.errorCode != OH_HUKS_SUCCESS) {
257        return ret;
258    }
259    ret = HksEncryptLoopUpdate(&handleBlob, paramSet, plainText, cipherText);
260    return ret;
261}
262static OH_Huks_Result BuildWrappedKeyData(struct OH_Huks_Blob **blobArray, uint32_t size,
263                                          struct OH_Huks_Blob *outData) {
264    uint32_t totalLength = size * sizeof(uint32_t);
265    struct OH_Huks_Result ret;
266    ret.errorCode = OH_HUKS_SUCCESS;
267    /* 计算大小 */
268    for (uint32_t i = 0; i < size; ++i) {
269        totalLength += blobArray[i]->size;
270    }
271    struct OH_Huks_Blob outBlob = {0, nullptr};
272    outBlob.size = totalLength;
273    ret = MallocAndCheckBlobData(&outBlob, outBlob.size);
274    if (ret.errorCode != OH_HUKS_SUCCESS) {
275        return ret;
276    }
277    uint32_t offset = 0;
278    /* 拷贝数据 */
279    for (uint32_t i = 0; i < size; ++i) {
280        if (totalLength - offset >= sizeof(blobArray[i]->size)) {
281            std::copy(reinterpret_cast<uint8_t *>(&blobArray[i]->size),
282                      reinterpret_cast<uint8_t *>(&blobArray[i]->size) + sizeof(blobArray[i]->size),
283                      outBlob.data + offset);
284        } else {
285            ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
286            return ret;
287        }
288        offset += sizeof(blobArray[i]->size);
289        if (totalLength - offset >= blobArray[i]->size) {
290            std::copy(blobArray[i]->data, blobArray[i]->data + blobArray[i]->size, outBlob.data + offset);
291        } else {
292            ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
293            return ret;
294        }
295        offset += blobArray[i]->size;
296    }
297    outData->size = outBlob.size;
298    outData->data = outBlob.data;
299    return ret;
300}
301static OH_Huks_Result CheckParamsValid(const struct HksImportWrappedKeyTestParams *params) {
302    struct OH_Huks_Result ret;
303    ret.errorCode = OH_HUKS_SUCCESS;
304    if (params == nullptr) {
305        ret.errorCode = OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT;
306        return ret;
307    }
308    if (params->wrappingKeyAlias == nullptr || params->genWrappingKeyParamSet == nullptr ||
309        params->callerKeyAlias == nullptr || params->genCallerKeyParamSet == nullptr ||
310        params->callerKekAlias == nullptr || params->callerKek == nullptr ||
311        params->importCallerKekParamSet == nullptr || params->callerAgreeKeyAlias == nullptr ||
312        params->agreeParamSet == nullptr || params->importWrappedKeyParamSet == nullptr ||
313        params->importedKeyAlias == nullptr || params->importedPlainKey == nullptr) {
314        ret.errorCode = OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT;
315        return ret;
316    }
317    return ret;
318}
319static OH_Huks_Result GenerateAndExportHuksPublicKey(const struct HksImportWrappedKeyTestParams *params,
320                                                     struct OH_Huks_Blob *huksPublicKey) {
321    OH_Huks_Result ret = OH_Huks_GenerateKeyItem(params->wrappingKeyAlias, params->genWrappingKeyParamSet, nullptr);
322    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
323        return ret;
324    }
325    huksPublicKey->size = params->publicKeySize;
326    ret = MallocAndCheckBlobData(huksPublicKey, huksPublicKey->size);
327    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
328        return ret;
329    }
330    ret = OH_Huks_ExportPublicKeyItem(params->wrappingKeyAlias, nullptr, huksPublicKey);
331    return ret;
332}
333static OH_Huks_Result GenerateAndExportCallerPublicKey(const struct HksImportWrappedKeyTestParams *params,
334                                                       struct OH_Huks_Blob *callerSelfPublicKey) {
335    OH_Huks_Result ret = OH_Huks_GenerateKeyItem(params->callerKeyAlias, params->genCallerKeyParamSet, nullptr);
336    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
337        return ret;
338    }
339    callerSelfPublicKey->size = params->publicKeySize;
340    ret = MallocAndCheckBlobData(callerSelfPublicKey, callerSelfPublicKey->size);
341    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
342        return ret;
343    }
344    ret = OH_Huks_ExportPublicKeyItem(params->callerKeyAlias, params->genWrappingKeyParamSet, callerSelfPublicKey);
345    return ret;
346}
347static OH_Huks_Result ImportKekAndAgreeSharedSecret(const struct HksImportWrappedKeyTestParams *params,
348                                                    const struct OH_Huks_Blob *huksPublicKey,
349                                                    struct OH_Huks_Blob *outSharedKey) {
350    OH_Huks_Result ret =
351        OH_Huks_ImportKeyItem(params->callerKekAlias, params->importCallerKekParamSet, params->callerKek);
352    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
353        return ret;
354    }
355    ret = MallocAndCheckBlobData(outSharedKey, outSharedKey->size);
356    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
357        return ret;
358    }
359    ret = HuksAgreeKey(params->agreeParamSet, params->callerKeyAlias, huksPublicKey, outSharedKey);
360    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
361        return ret;
362    }
363    struct OH_Huks_ParamSet *importAgreeKeyParams = nullptr;
364    ret = InitParamSet(&importAgreeKeyParams, g_importAgreeKeyParams,
365                       sizeof(g_importAgreeKeyParams) / sizeof(OH_Huks_Param));
366    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
367        return ret;
368    }
369    ret = OH_Huks_ImportKeyItem(params->callerAgreeKeyAlias, importAgreeKeyParams, outSharedKey);
370    OH_Huks_FreeParamSet(&importAgreeKeyParams);
371    return ret;
372}
373static OH_Huks_Result EncryptImportedPlainKeyAndKek(const struct HksImportWrappedKeyTestParams *params,
374                                                    struct OH_Huks_Blob *plainCipherText,
375                                                    struct OH_Huks_Blob *kekCipherText) {
376    struct OH_Huks_ParamSet *encryptParamSet = nullptr;
377    OH_Huks_Result ret =
378        InitParamSet(&encryptParamSet, g_aesKekEncryptParams, sizeof(g_aesKekEncryptParams) / sizeof(OH_Huks_Param));
379    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
380        return ret;
381    }
382    ret = HuksEncrypt(params->callerKekAlias, encryptParamSet, params->importedPlainKey, plainCipherText);
383    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
384        return ret;
385    }
386    ret = HuksEncrypt(params->callerAgreeKeyAlias, encryptParamSet, params->callerKek, kekCipherText);
387    OH_Huks_FreeParamSet(&encryptParamSet);
388    return ret;
389}
390static OH_Huks_Result ImportWrappedKey(const struct HksImportWrappedKeyTestParams *params,
391                                       struct OH_Huks_Blob *plainCipher, struct OH_Huks_Blob *kekCipherText,
392                                       struct OH_Huks_Blob *peerPublicKey, struct OH_Huks_Blob *wrappedKeyData) {
393    struct OH_Huks_Blob commonAad = {.size = AAD_SIZE, .data = reinterpret_cast<uint8_t *>(AAD)};
394    struct OH_Huks_Blob commonNonce = {.size = NONCE_SIZE, .data = reinterpret_cast<uint8_t *>(NONCE)};
395    struct OH_Huks_Blob keyMaterialLen = {.size = sizeof(uint32_t), .data = (uint8_t *)&params->keyMaterialLen};
396    /* 从密文中拷贝AEAD的tag并缩小其大小 */
397    const uint32_t tagSize = AEAD_TAG_SIZE;
398    uint8_t kekTagBuf[tagSize] = {0};
399    struct OH_Huks_Blob kekTag = {.size = tagSize, .data = kekTagBuf};
400    std::copy(plainCipher->data + (plainCipher->size - tagSize),
401              plainCipher->data + (plainCipher->size - tagSize) + tagSize, kekTag.data);
402    plainCipher->size -= tagSize;
403    /* 从密钥加密密钥的密文中拷贝AEAD的tag并缩小其大小 */
404    uint8_t agreeKeyTagBuf[tagSize] = {0};
405    struct OH_Huks_Blob agreeKeyTag = {.size = tagSize, .data = agreeKeyTagBuf};
406    std::copy(kekCipherText->data + (kekCipherText->size - tagSize),
407              kekCipherText->data + (kekCipherText->size - tagSize) + tagSize, agreeKeyTagBuf);
408    kekCipherText->size -= tagSize;
409    struct OH_Huks_Blob *blobArray[] = {peerPublicKey, &commonAad,   &commonNonce, &agreeKeyTag,    kekCipherText,
410                                        &commonAad,    &commonNonce, &kekTag,      &keyMaterialLen, plainCipher};
411    OH_Huks_Result ret = BuildWrappedKeyData(blobArray, OH_HUKS_IMPORT_WRAPPED_KEY_TOTAL_BLOBS, wrappedKeyData);
412    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
413        return ret;
414    }
415    struct OH_Huks_Param *purpose = nullptr;
416    ret = OH_Huks_GetParam(params->importWrappedKeyParamSet, OH_HUKS_TAG_PURPOSE, &purpose);
417    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
418        return ret;
419    }
420    ret = OH_Huks_ImportWrappedKeyItem(params->importedKeyAlias, params->wrappingKeyAlias,
421                                       params->importWrappedKeyParamSet, wrappedKeyData);
422    return ret;
423}
424OH_Huks_Result HksImportWrappedKeyTestCommonCase(const struct HksImportWrappedKeyTestParams *params) {
425    OH_Huks_Result ret = CheckParamsValid(params);
426    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
427        return ret;
428    }
429    struct OH_Huks_Blob huksPublicKey = {0, nullptr};
430    struct OH_Huks_Blob callerSelfPublicKey = {0, nullptr};
431    struct OH_Huks_Blob outSharedKey = {.size = OH_HUKS_KEY_BYTES(OH_HUKS_AES_KEY_SIZE_256), .data = nullptr};
432    struct OH_Huks_Blob wrappedKeyData = {0, nullptr};
433    uint8_t plainKeyCipherBuffer[OH_HUKS_MAX_KEY_SIZE] = {0};
434    struct OH_Huks_Blob plainCipherText = {OH_HUKS_MAX_KEY_SIZE, plainKeyCipherBuffer};
435    uint8_t kekCipherTextBuffer[OH_HUKS_MAX_KEY_SIZE] = {0};
436    struct OH_Huks_Blob kekCipherText = {OH_HUKS_MAX_KEY_SIZE, kekCipherTextBuffer};
437    /* 模拟加密导入密钥场景,设备A为远端设备(导入设备),设备B为本端设备(被导入设备) */
438    do {
439        /**
440         * 1.设备A将待导入密钥转换成HUKS密钥材料格式To_Import_Key(仅针对非对称密钥,若待导入密钥是对称密钥则可省略此步骤),
441         *   本示例使用g_importedAes256PlainKey(对称密钥)作为模拟
442         */
443        /* 2.设备B生成一个加密导入用途的、用于协商的非对称密钥对Wrapping_Key(公钥Wrapping_Pk,私钥Wrapping_Sk),其密钥用途设置为unwrap,导出Wrapping_Key公钥Wrapping_Pk存放在变量huksPublicKey中
444         */
445        ret = GenerateAndExportHuksPublicKey(params, &huksPublicKey);
446        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
447            break;
448        }
449        /* 3.设备A使用和设备B同样的算法,生成一个加密导入用途的、用于协商的非对称密钥对Caller_Key(公钥Caller_Pk,私钥Caller_Sk),导出Caller_Key公钥Caller_Pk存放在变量callerSelfPublicKey中
450         */
451        ret = GenerateAndExportCallerPublicKey(params, &callerSelfPublicKey);
452        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
453            break;
454        }
455        /**
456         * 4. 设备A生成一个对称密钥Caller_Kek,该密钥后续将用于加密To_Import_Key
457         * 5. 设备A基于Caller_Key的私钥Caller_Sk和设备B Wrapping_Key的公钥Wrapping_Pk,协商出Shared_Key
458         */
459        ret = ImportKekAndAgreeSharedSecret(params, &huksPublicKey, &outSharedKey);
460        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
461            break;
462        }
463        /**
464         * 6. 设备A使用Caller_Kek加密To_Import_Key,生成To_Import_Key_Enc
465         * 7. 设备A使用Shared_Key加密Caller_Kek,生成Caller_Kek_Enc
466         */
467        ret = EncryptImportedPlainKeyAndKek(params, &plainCipherText, &kekCipherText);
468        if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
469            break;
470        }
471        /* 8. 设备A封装Caller_Pk、To_Import_Key_Enc、Caller_Kek_Enc等加密导入的材料并发送给设备B。
472         * 本示例作为变量存放在callerSelfPublicKey,plainCipherText,kekCipherText
473         * 9. 设备B导入封装的加密密钥材料
474         */
475        ret = ImportWrappedKey(params, &plainCipherText, &kekCipherText, &callerSelfPublicKey, &wrappedKeyData);
476    } while (0);
477    /* 10. 设备A、B删除用于加密导入的密钥 */
478    HUKS_FREE_BLOB(huksPublicKey);
479    HUKS_FREE_BLOB(callerSelfPublicKey);
480    HUKS_FREE_BLOB(outSharedKey);
481    HUKS_FREE_BLOB(wrappedKeyData);
482    return ret;
483}
484void HksClearKeysForWrappedKeyTest(const struct HksImportWrappedKeyTestParams *params) {
485    OH_Huks_Result ret = CheckParamsValid(params);
486    if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
487        return;
488    }
489    (void)OH_Huks_DeleteKeyItem(params->wrappingKeyAlias, nullptr);
490    (void)OH_Huks_DeleteKeyItem(params->callerKeyAlias, nullptr);
491    (void)OH_Huks_DeleteKeyItem(params->callerKekAlias, nullptr);
492    (void)OH_Huks_DeleteKeyItem(params->callerAgreeKeyAlias, nullptr);
493    (void)OH_Huks_DeleteKeyItem(params->importedKeyAlias, nullptr);
494}
495static OH_Huks_Result InitCommonTestParamsAndDoImport(struct HksImportWrappedKeyTestParams *importWrappedKeyTestParams,
496                                                      const struct OH_Huks_Param *importedKeyParamSetArray,
497                                                      uint32_t arraySize) {
498    struct OH_Huks_ParamSet *genX25519KeyParamSet = nullptr;
499    struct OH_Huks_ParamSet *genCallerKeyParamSet = nullptr;
500    struct OH_Huks_ParamSet *callerImportParamsKek = nullptr;
501    struct OH_Huks_ParamSet *agreeParamSet = nullptr;
502    struct OH_Huks_ParamSet *importPlainKeyParams = nullptr;
503    OH_Huks_Result ret;
504    do {
505        ret = InitParamSet(&genX25519KeyParamSet, g_genWrappingKeyParams,
506                           sizeof(g_genWrappingKeyParams) / sizeof(OH_Huks_Param));
507        if (ret.errorCode != OH_HUKS_SUCCESS) {
508            break;
509        }
510        importWrappedKeyTestParams->genWrappingKeyParamSet = genX25519KeyParamSet;
511        importWrappedKeyTestParams->publicKeySize = g_x25519PubKeySize;
512        ret = InitParamSet(&genCallerKeyParamSet, g_genCallerX25519Params,
513                           sizeof(g_genCallerX25519Params) / sizeof(OH_Huks_Param));
514        if (ret.errorCode != OH_HUKS_SUCCESS) {
515            break;
516        }
517        importWrappedKeyTestParams->genCallerKeyParamSet = genCallerKeyParamSet;
518        ret = InitParamSet(&callerImportParamsKek, g_importParamsCallerKek,
519                           sizeof(g_importParamsCallerKek) / sizeof(OH_Huks_Param));
520        if (ret.errorCode != OH_HUKS_SUCCESS) {
521            break;
522        }
523        importWrappedKeyTestParams->importCallerKekParamSet = callerImportParamsKek;
524        ret = InitParamSet(&agreeParamSet, g_callerAgreeParams, sizeof(g_callerAgreeParams) / sizeof(OH_Huks_Param));
525        if (ret.errorCode != OH_HUKS_SUCCESS) {
526            break;
527        }
528        importWrappedKeyTestParams->agreeParamSet = agreeParamSet;
529        ret = InitParamSet(&importPlainKeyParams, importedKeyParamSetArray, arraySize);
530        if (ret.errorCode != OH_HUKS_SUCCESS) {
531            break;
532        }
533        importWrappedKeyTestParams->importWrappedKeyParamSet = importPlainKeyParams;
534        ret = HksImportWrappedKeyTestCommonCase(importWrappedKeyTestParams);
535    } while (0);
536    OH_Huks_FreeParamSet(&genX25519KeyParamSet);
537    OH_Huks_FreeParamSet(&genCallerKeyParamSet);
538    OH_Huks_FreeParamSet(&callerImportParamsKek);
539    OH_Huks_FreeParamSet(&agreeParamSet);
540    OH_Huks_FreeParamSet(&importPlainKeyParams);
541    return ret;
542}
543static napi_value ImportWrappedKey(napi_env env, napi_callback_info info) {
544    struct HksImportWrappedKeyTestParams importWrappedKeyTestParams001 = {0};
545    importWrappedKeyTestParams001.wrappingKeyAlias = &g_wrappingKeyAliasAes256;
546    importWrappedKeyTestParams001.keyMaterialLen = g_importedAes256PlainKey.size;
547    importWrappedKeyTestParams001.callerKeyAlias = &g_callerKeyAliasAes256;
548    importWrappedKeyTestParams001.callerKekAlias = &g_callerKekAliasAes256;
549    importWrappedKeyTestParams001.callerKek = &g_callerAes256Kek;
550    importWrappedKeyTestParams001.callerAgreeKeyAlias = &g_callerAgreeKeyAliasAes256;
551    importWrappedKeyTestParams001.importedKeyAlias = &g_importedKeyAliasAes256;
552    importWrappedKeyTestParams001.importedPlainKey = &g_importedAes256PlainKey;
553    OH_Huks_Result ohResult =
554        InitCommonTestParamsAndDoImport(&importWrappedKeyTestParams001, g_importWrappedAes256Params,
555                                        sizeof(g_importWrappedAes256Params) / sizeof(struct OH_Huks_Param));
556    HksClearKeysForWrappedKeyTest(&importWrappedKeyTestParams001);
557    napi_value ret;
558    napi_create_int32(env, ohResult.errorCode, &ret);
559    return ret;
560}
561```
562
563
564## 调测验证
565
566调用[OH_Huks_IsKeyItemExist](../../reference/apis-universal-keystore-kit/_huks_key_api.md#oh_huks_iskeyitemexist)验证密钥是否存在,如密钥存在即表示密钥导入成功。
567
568```c++
569#include "huks/native_huks_api.h"
570#include "huks/native_huks_param.h"
571#include "napi/native_api.h"
572#include <string.h>
573static napi_value IsKeyExist(napi_env env, napi_callback_info info)
574{
575    /* 1.指定密钥别名 */
576    struct OH_Huks_Blob keyAlias = {
577        (uint32_t)strlen("test_key"),
578        (uint8_t *)"test_key"
579    };
580
581    /* 2.调用OH_Huks_IsKeyItemExist判断密钥是否存在  */
582    struct OH_Huks_Result ohResult = OH_Huks_IsKeyItemExist(&keyAlias, NULL);
583    if (ohResult.errorCode != OH_HUKS_SUCCESS) {
584        // 失败。
585    } else {
586        // 成功。
587    }
588}
589```
590