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