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 *)¶ms->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