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