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