1# HUKS Development (Native) 2 3## When to Use 4 5The OpenHarmony Universal KeyStore (HUKS) provides full lifecycle management capability for keys. The keys managed by the HUKS can be imported by an application or generated by calling the HUKS APIs. For a key generated by the HUKS, the plaintext will never be exposed outside throughout the lifecycle. No one can obtain the key in plaintext. Even the service itself can call APIs provided by the HUKS to perform operations on the key and obtain the operation result, but cannot access the key. 6 7With the Native APIs provided by the HUKS, you can: 8 9* Generate a key. 10* Import an external key to the HUKS. 11* Encrypt and decrypt data by using a key. 12* Generate a digital signature and verify a signature. 13* Generate a shared secrete through key agreement. 14* Derive a key. 15* Provide key attestation. 16 17## Available APIs 18 19### APIs for Key Use 20 21| API| Description| 22| -------- | -------- | 23| [OH_Huks_GetSdkVersion](../reference/native-apis/_huks_key_api.md#oh_huks_getsdkversion) (struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*sdkVersion) | Obtains the current HUKS SDK version. | 24| [OH_Huks_GenerateKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_generatekeyitem) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSetIn, struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSetOut) | Generates a key. | 25| [OH_Huks_ImportKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_importkeyitem) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*key) | Imports a key in plaintext. | 26| [OH_Huks_ImportWrappedKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_importwrappedkeyitem) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*wrappingKeyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*wrappedKeyData) | Imports a wrapped (encrypted) key. | 27| [OH_Huks_ExportPublicKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_exportpublickeyitem) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*key) | Exports a public key. | 28| [OH_Huks_DeleteKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_deletekeyitem) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet) | Deletes a key. | 29| [OH_Huks_GetKeyItemParamSet](../reference/native-apis/_huks_key_api.md#oh_huks_getkeyitemparamset) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSetIn, struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSetOut) | Obtains the parameter set of a key. | 30| [OH_Huks_IsKeyItemExist](../reference/native-apis/_huks_key_api.md#oh_huks_iskeyitemexist) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet) | Checks whether a key exists. | 31| [OH_Huks_AttestKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_attestkeyitem) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, struct [OH_Huks_CertChain](../reference/native-apis/_o_h___huks___cert_chain.md) \*certChain) | Obtains the key certificate chain. | 32| [OH_Huks_InitSession](../reference/native-apis/_huks_key_api.md#oh_huks_initsession) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*handle, struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*token) | Initializes the key session to obtain a handle (mandatory) and a challenge value (optional). | 33| [OH_Huks_UpdateSession](../reference/native-apis/_huks_key_api.md#oh_huks_updatesession) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*handle, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*inData, struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*outData) | Adds data by segment for the key operation, performs the related key operation, and outputs the processed data. | 34| [OH_Huks_FinishSession](../reference/native-apis/_huks_key_api.md#oh_huks_finishsession) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*handle, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*inData, struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*outData) | Finishes the key session. | 35| [OH_Huks_AbortSession](../reference/native-apis/_huks_key_api.md#oh_huks_abortsession) (const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*handle, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet) | Aborts a key session. | 36 37### APIs for Key Parameters 38 39| API| Description| 40| -------- | -------- | 41| [OH_Huks_InitParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_initparamset) (struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*\*paramSet) | Initializes a parameter set. | 42| [OH_Huks_AddParams](../reference/native-apis/_huks_param_set_api.md#oh_huks_addparams) (struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, const struct [OH_Huks_Param](../reference/native-apis/_o_h___huks___param.md) \*params, uint32_t paramCnt) | Adds parameters to a parameter set. | 43| [OH_Huks_BuildParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_buildparamset) (struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*\*paramSet) | Builds a formal parameter set. | 44| [OH_Huks_FreeParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_freeparamset) (struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*\*paramSet) | Destroys a parameter set. | 45| [OH_Huks_CopyParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_copyparamset) (const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*fromParamSet, uint32_t fromParamSetSize, struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*\*paramSet) | Copies a parameter set (deep copy). | 46| [OH_Huks_GetParam](../reference/native-apis/_huks_param_set_api.md#oh_huks_getparam) (const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, uint32_t tag, struct [OH_Huks_Param](../reference/native-apis/_o_h___huks___param.md) \*\*param) | Obtains parameters from a parameter set. | 47| [OH_Huks_FreshParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_freshparamset) (struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, bool isCopy) | Refreshes data of the **Blob** type in a parameter set. | 48| [OH_Huks_IsParamSetTagValid](../reference/native-apis/_huks_param_set_api.md#oh_huks_isparamsettagvalid) (const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet) | Checks whether the parameters in a parameter set are valid. | 49| [OH_Huks_IsParamSetValid](../reference/native-apis/_huks_param_set_api.md#oh_huks_isparamsetvalid) (const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, uint32_t size) | Checks whether a parameter set is of the valid size. | 50| [OH_Huks_CheckParamMatch](../reference/native-apis/_huks_param_set_api.md#oh_huks_checkparammatch) (const struct [OH_Huks_Param](../reference/native-apis/_o_h___huks___param.md) \*baseParam, const struct [OH_Huks_Param](../reference/native-apis/_o_h___huks___param.md) \*param) | Compares whether two parameters are the same. | 51 52## How to Develop 53 54### Key Generation 55The HUKS provides the capability of randomly generating keys for services. For a key generated by the HUKS, the plaintext will never be exposed outside throughout the lifecycle. No one can obtain the key in plaintext. Even the service itself can call APIs provided by the HUKS to perform operations on the key and obtain the operation result, but cannot access the key. 56 57**How to Develop** 58 59Use [OH_Huks_GenerateKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_generatekeyitem) to generate a key. You need to pass in **keyAlias** and **paramSetIn**. 60 611. Set the key alias. 622. Initialize the key parameter set. Use [OH_Huks_InitParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_initparamset), [OH_Huks_AddParams](../reference/native-apis/_huks_param_set_api.md#oh_huks_addparams), and [OH_Huks_BuildParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_buildparamset) to construct **paramSet**, which must contain the [OH_Huks_KeyAlg](../reference/native-apis/_huks_type_api.md#oh_huks_keyalg), [OH_Huks_KeySize](../reference/native-apis/_huks_type_api.md#oh_huks_keysize), and [OH_Huks_KeyPurpose](../reference/native-apis/_huks_type_api.md#oh_huks_keypurpose). 633. Pass in the key alias and key parameter set to generate a key. 64 65> **NOTE** 66> 67> The key alias cannot exceed 64 bytes. 68 69**C++ Code Example** 70 71```C++ 72#include "huks/native_huks_api.h" 73#include "huks/native_huks_param.h" 74#include <string.h> 75OH_Huks_Result InitParamSet( 76 struct OH_Huks_ParamSet **paramSet, 77 const struct OH_Huks_Param *params, 78 uint32_t paramCount) 79{ 80 OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet); 81 if (ret.errorCode != OH_HUKS_SUCCESS) { 82 return ret; 83 } 84 85 ret = OH_Huks_AddParams(*paramSet, params, paramCount); 86 if (ret.errorCode != OH_HUKS_SUCCESS) { 87 OH_Huks_FreeParamSet(paramSet); 88 return ret; 89 } 90 91 ret = OH_Huks_BuildParamSet(paramSet); 92 if (ret.errorCode != OH_HUKS_SUCCESS) { 93 OH_Huks_FreeParamSet(paramSet); 94 return ret; 95 } 96 97 return ret; 98} 99 100struct OH_Huks_Param g_testGenerateKeyParam[] = { 101 { 102 .tag = OH_HUKS_TAG_ALGORITHM, 103 .uint32Param = OH_HUKS_ALG_ECC 104 }, { 105 .tag = OH_HUKS_TAG_PURPOSE, 106 .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE 107 }, { 108 .tag = OH_HUKS_TAG_KEY_SIZE, 109 .uint32Param = OH_HUKS_ECC_KEY_SIZE_256 110 }, { 111 .tag = OH_HUKS_TAG_DIGEST, 112 .uint32Param = OH_HUKS_DIGEST_NONE 113 } 114}; 115 116static napi_value GenerateKey(napi_env env, napi_callback_info info) 117{ 118 const char *alias = "test_generate"; 119 struct OH_Huks_Blob aliasBlob = { .size = (uint32_t)strlen(alias), .data = (uint8_t *)alias }; 120 struct OH_Huks_ParamSet *testGenerateKeyParamSet = nullptr; 121 struct OH_Huks_Result ohResult; 122 do { 123 ohResult = InitParamSet(&testGenerateKeyParamSet, g_testGenerateKeyParam, 124 sizeof(g_testGenerateKeyParam) / sizeof(OH_Huks_Param)); 125 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 126 break; 127 } 128 ohResult = OH_Huks_GenerateKeyItem(&aliasBlob, testGenerateKeyParamSet, nullptr); 129 } while (0); 130 OH_Huks_FreeParamSet(&testGenerateKeyParamSet); 131 napi_value ret; 132 napi_create_int32(env, ohResult.errorCode, &ret); 133 return ret; 134} 135``` 136 137 138### Key Import 139 140A key generated outside the HUKS (for example, generated through key agreement or by a server) can be imported to the HUKS for management. The HUKS supports import of keys in plaintext. However, if a key is imported in plaintext, the key is exposed in the Rich Execution Environment (REE) memory. This type of import applies to lightweight devices or security-insensitive services. For security-sensitive services, use the secure import feature provided by the HUKS. Secure import allows the keys generated for services to be transferred to the HUKS through an end-to-end encrypted transmission channel. 141 142Once a key is imported to the HUKS, its plaintext will not be exposed outside the HUKS throughout the lifecycle of the key. 143 144#### Importing a Key in Plaintext 145 146Use [OH_Huks_ImportKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_importkeyitem) to import a key in plaintext. You need to pass in the key alias and **paramSetIn**, which must contain the key material and key property set. 147 1481. Set the key alias. 1492. Encapsulate the key material and key property set. The key material must comply with the HUKS key material formats (huks-appendix.md#key-material-formats) and assign a value to the key field. In addition, use [OH_Huks_InitParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_initparamset), [OH_Huks_AddParams](../reference/native-apis/_huks_param_set_api.md#oh_huks_addparams), and [OH_Huks_BuildParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_buildparamset) to construct **paramSet**, which must contain [OH_Huks_KeyAlg](../reference/native-apis/_huks_type_api.md#oh_huks_keyalg), [OH_Huks_KeySize](../reference/native-apis/_huks_type_api.md#oh_huks_keysize), and [OH_Huks_KeyPurpose](../reference/native-apis/_huks_type_api.md#oh_huks_keypurpose). 1503. Import the key. 151 152**C++ Code Example** 153 154```C++ 155#include "huks/native_huks_api.h" 156#include "huks/native_huks_param.h" 157#include <string.h> 158OH_Huks_Result InitParamSet( 159 struct OH_Huks_ParamSet **paramSet, 160 const struct OH_Huks_Param *params, 161 uint32_t paramCount) 162{ 163 OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet); 164 if (ret.errorCode != OH_HUKS_SUCCESS) { 165 return ret; 166 } 167 168 ret = OH_Huks_AddParams(*paramSet, params, paramCount); 169 if (ret.errorCode != OH_HUKS_SUCCESS) { 170 OH_Huks_FreeParamSet(paramSet); 171 return ret; 172 } 173 174 ret = OH_Huks_BuildParamSet(paramSet); 175 if (ret.errorCode != OH_HUKS_SUCCESS) { 176 OH_Huks_FreeParamSet(paramSet); 177 return ret; 178 } 179 180 return ret; 181} 182 183static napi_value ImportKey(napi_env env, napi_callback_info info) 184{ 185 (void)GenerateKey(env, info); 186 const char *alias = "test_generate"; 187 struct OH_Huks_Blob aliasBlob = { .size = (uint32_t)strlen(alias), .data = (uint8_t *)alias }; 188 uint8_t pubKey[OH_HUKS_ECC_KEY_SIZE_256] = {0}; 189 struct OH_Huks_Blob publicKey = { OH_HUKS_ECC_KEY_SIZE_256, pubKey }; 190 struct OH_Huks_ParamSet *testImportKeyParamSet = nullptr; 191 struct OH_Huks_Result ohResult; 192 do { 193 ohResult = InitParamSet(&testImportKeyParamSet, g_testGenerateKeyParam, 194 sizeof(g_testGenerateKeyParam) / sizeof(OH_Huks_Param)); 195 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 196 break; 197 } 198 ohResult = OH_Huks_ExportPublicKeyItem(&aliasBlob, testImportKeyParamSet, &publicKey); 199 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 200 break; 201 } 202 /* 4. Import Key */ 203 char newKey[] = "test_import"; 204 struct OH_Huks_Blob newKeyAlias = { .size = (uint32_t)strlen(newKey), .data = (uint8_t *)newKey }; 205 ohResult = OH_Huks_ImportKeyItem(&newKeyAlias, testImportKeyParamSet, &publicKey); 206 } while (0); 207 OH_Huks_FreeParamSet(&testImportKeyParamSet); 208 napi_value ret; 209 napi_create_int32(env, ohResult.errorCode, &ret); 210 return ret; 211} 212``` 213 214#### Importing a Wrapped Key 215 216Compared with import of a key in plaintext, the import of a wrapped key involves more complex key material and operations. The following figure illustrates the basic development process. 217 218**Figure 2** Development process for importing a wrapped key 219 220 221 222**Available APIs** 223 224During the development process, you need to use the APIs for key generation, export, import, and deletion in sequence. 225 226>**NOTE**<br>The public key plaintext material returned by **exportKeyItem()** is encapsulated in X.509 format, and the key material to be imported by **importWrappedKeyItem()** must be encapsulated in **Length<sub>Data</sub>-Data** format. Specifically, the application needs to encapsulate the wrapped key material in sequence according to the sequence in the following table. 227 228**Table 2** Format of the wrapped key material 229 230| **Content**| Public Key Length (L<sub>pk2</sub>)| Public Key (pk2)| k2 AAD Length (L<sub>AAD2</sub>)| k2 AAD (AAD2)| k2 Nonce Length (L<sub>Nonce2</sub>)| k2 Nonce (Nonce2)| 231| :--: |:----:|:----: |:----: | :----: | :----:|:----:| 232|Length| 4 bytes|L<sub>pk2</sub> bytes| 4 bytes| L<sub>AAD2</sub> bytes| 4 bytes| L<sub>Nonce2</sub> bytes| 233| **Content**| k2 AEAD Length (L<sub>AEAD2</sub>)| k2 AEAD (AEAD2)| k3 Ciphertext Length (L<sub>k3_enc</sub>)| k3 Ciphertext (k3_enc)| k3 AAD Length (L<sub>AAD3</sub>)| k3 AAD (AAD3)| 234|Length| 4 bytes|L<sub>AEAD2</sub> bytes| 4 bytes| L<sub>k3_enc</sub> bytes| 4 bytes| L<sub>AAD3</sub> bytes| 235| Content| k3 Nonce Length (L<sub>Nonce3</sub>)| k3 Nonce (Nonce3)| k3 AEAD Length (L<sub>AEAD3</sub>)| k3 AEAD (AEAD3)| Length of **k1'_size** (L<sub>k1'_size</sub>)| Key Plaintext Material Length (k1'_size)| 236|Length| 4 bytes|L<sub>Nonce3</sub> bytes| 4 bytes| L<sub>AEAD3</sub> bytes| 4 bytes| L<sub>k1'_size</sub> bytes| 237|Content|k1' Ciphertext Length L<sub>k1'_enc</sub>| k1' ciphertext k1'_enc| | | | | 238|Length| 4 bytes|L<sub>k1'_enc</sub> bytes| | | | | 239 240**How to Develop** 241 242The following example provides the development involving HUKS APIs (using the ECDH key agreement suite). The operations performed by the service are not included. In the following example, a key is imported from device A to device B. 243 2441. Convert the key to be imported from device A into the key material in HUKS format **To_Import_Key**. 2452. Generate an asymmetric key pair **Caller_Key** for device A. 2463. Generate an asymmetric key pair **Wrapping_Key**, with key purpose of **unwrap**, for device B. 2474. Generate a symmetric key **Caller_Kek** for device A. 2485. Export the public key material from the asymmetric key pairs of devices A and B. 2496. Use the private key of **Caller_Key** (device A) and the public key of **Wrapping_Key** (device B) to perform key agreement, and obtain an **Agree_Key**. 2507. Use the **Caller_Kek** to encrypt the **To_Import_Key** of device A and generate **To_Import_Key_Enc**. 2518. Use **Agree_Key** to encrypt the **Caller_Kek** of device A and generate **Caller_Kek_Enc**. 2529. Send the public key of **Caller_Key**, **Caller_Kek_Enc**, and **To_Import_Key_Enc** from device A to device B. 25310. Encapsulate and encrypt the key materials to be imported to device B. 25411. Import the encrypted key material to device B. 25512. Delete the keys, which are used for encrypting the key to import, from devices A and B. 256 257**C++ Code Example** 258 259```C++ 260#include "napi/native_api.h" 261#include "huks/native_huks_api.h" 262#include "huks/native_huks_param.h" 263#include <algorithm> 264 265OH_Huks_Result InitParamSet( 266 struct OH_Huks_ParamSet **paramSet, 267 const struct OH_Huks_Param *params, 268 uint32_t paramCount) 269{ 270 OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet); 271 if (ret.errorCode != OH_HUKS_SUCCESS) { 272 return ret; 273 } 274 275 ret = OH_Huks_AddParams(*paramSet, params, paramCount); 276 if (ret.errorCode != OH_HUKS_SUCCESS) { 277 OH_Huks_FreeParamSet(paramSet); 278 return ret; 279 } 280 281 ret = OH_Huks_BuildParamSet(paramSet); 282 if (ret.errorCode != OH_HUKS_SUCCESS) { 283 OH_Huks_FreeParamSet(paramSet); 284 return ret; 285 } 286 287 return ret; 288} 289 290/** 291 * Securely import a key from device A to the HUKS of device B. 292 * wrappingKey is a key pair of device B. 293 * callerKey is a key pair of device A. 294 * callerAgreeKey is generated through key agreement based on the private key of the key pair of device A and the public key of device B . 295 */ 296struct HksImportWrappedKeyTestParams { 297 // server key, for real 298 struct OH_Huks_Blob *wrappingKeyAlias; 299 struct OH_Huks_ParamSet *genWrappingKeyParamSet; 300 uint32_t publicKeySize; 301 302 struct OH_Huks_Blob *callerKeyAlias; 303 struct OH_Huks_ParamSet *genCallerKeyParamSet; 304 305 struct OH_Huks_Blob *callerKekAlias; 306 struct OH_Huks_Blob *callerKek; 307 struct OH_Huks_ParamSet *importCallerKekParamSet; 308 309 struct OH_Huks_Blob *callerAgreeKeyAlias; 310 struct OH_Huks_ParamSet *agreeParamSet; 311 312 struct OH_Huks_ParamSet *importWrappedKeyParamSet; 313 struct OH_Huks_Blob *importedKeyAlias; 314 struct OH_Huks_Blob *importedPlainKey; 315 uint32_t keyMaterialLen; 316}; 317 318static const uint32_t WRAPPED_KEY_IV_SIZE = 16; 319static uint8_t WRAPPED_KEY_IV[IV_SIZE] = "bababababababab"; // This is a test value. For real use, the IV should be different each time. 320 321static const uint32_t AAD_SIZE = 16; 322static uint8_t AAD[AAD_SIZE] = "abababababababa"; // This is a test value. For real use, the AAD should be different each time. 323 324static const uint32_t NONCE_SIZE = 12; 325static uint8_t NONCE[NONCE_SIZE] = "hahahahahah"; // This is a test value. For real use, the nonce should be different each time. 326 327static const uint32_t AEAD_TAG_SIZE = 16; 328 329static const uint32_t X25519_256_SIZE = 256; 330static struct OH_Huks_Blob g_wrappingKeyAliasAes256 = { 331 .size = (uint32_t)strlen("test_wrappingKey_x25519_aes256"), 332 .data = (uint8_t *)"test_wrappingKey_x25519_aes256"}; 333 334static struct OH_Huks_Blob g_callerKeyAliasAes256 = { 335 .size = (uint32_t)strlen("test_caller_key_x25519_aes256"), 336 .data = (uint8_t *)"test_caller_key_x25519_aes256"}; 337 338static struct OH_Huks_Blob g_callerKekAliasAes256 = { 339 .size = (uint32_t)strlen("test_caller_kek_x25519_aes256"), 340 .data = (uint8_t *)"test_caller_kek_x25519_aes256"}; 341 342static struct OH_Huks_Blob g_callerAes256Kek = { 343 .size = (uint32_t)strlen("This is kek to encrypt plain key"), 344 .data = (uint8_t *)"This is kek to encrypt plain key"}; 345 346static struct OH_Huks_Blob g_callerAgreeKeyAliasAes256 = { 347 .size = (uint32_t)strlen("test_caller_agree_key_x25519_aes256"), 348 .data = (uint8_t *)"test_caller_agree_key_x25519_aes256"}; 349 350static struct OH_Huks_Blob g_importedKeyAliasAes256 = { 351 .size = (uint32_t)strlen("test_import_key_x25519_aes256"), 352 .data = (uint8_t *)"test_import_key_x25519_aes256"}; 353 354static struct OH_Huks_Blob g_importedAes256PlainKey = { 355 .size = (uint32_t)strlen("This is plain key to be imported"), 356 .data = (uint8_t *)"This is plain key to be imported"}; 357 358static struct OH_Huks_Param g_importWrappedAes256Params[] = { 359 {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES}, 360 {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT | OH_HUKS_KEY_PURPOSE_DECRYPT}, 361 {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256}, 362 {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE}, 363 {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM}, 364 {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE}, 365 {.tag = OH_HUKS_TAG_UNWRAP_ALGORITHM_SUITE, .uint32Param = OH_HUKS_UNWRAP_SUITE_X25519_AES_256_GCM_NOPADDING}, 366 {.tag = OH_HUKS_TAG_ASSOCIATED_DATA, .blob = {.size = AAD_SIZE, .data = (uint8_t *)AAD}}, // this is a test value, for real use the aad should be info associated with caller 367 {.tag = OH_HUKS_TAG_NONCE, .blob = {.size = NONCE_SIZE, .data = (uint8_t *)NONCE}}}; // this is a test value, for real use the nonce should be different every time 368 369static const uint32_t g_x25519PubKeySize = 32; 370 371static struct OH_Huks_Param g_genWrappingKeyParams[] = { 372 {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519}, 373 {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_UNWRAP}, 374 {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}}; 375 376static struct OH_Huks_Param g_genCallerX25519Params[] = { 377 {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519}, 378 {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE}, 379 {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}}; 380 381static struct OH_Huks_Param g_importParamsCallerKek[] = { 382 {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES}, 383 {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT}, 384 {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256}, 385 {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE}, 386 {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM}, 387 {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE}, 388 {.tag = OH_HUKS_TAG_IV, .blob = {.size = WRAPPED_KEY_IV_SIZE, .data = (uint8_t *)WRAPPED_KEY_IV }}}; // this is a test value, for real use the iv should be different every time 389 390static struct OH_Huks_Param g_callerAgreeParams[] = { 391 {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519}, 392 {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE}, 393 {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256} 394}; 395 396static struct OH_Huks_Param g_aesKekEncryptParams[] = { 397 {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES}, 398 {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT}, 399 {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256}, 400 {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE}, 401 {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM}, 402 {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE}, 403 {.tag = OH_HUKS_TAG_ASSOCIATED_DATA, .blob = {.size = AAD_SIZE, .data = (uint8_t *)AAD}}, // this is a test value, for real use the aad should be info associated with caller 404 {.tag = OH_HUKS_TAG_NONCE, .blob = {.size = NONCE_SIZE, .data = (uint8_t *)NONCE}}}; // this is a test value, for real use the nonce should be different every time 405 406static struct OH_Huks_Param g_importAgreeKeyParams[] = { 407 {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES}, 408 {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT}, 409 {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256}, 410 {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE}, 411 {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM}, 412 {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE}, 413 {.tag = OH_HUKS_TAG_IV, .blob = {.size = IV_SIZE, .data = (uint8_t *)IV}}}; // this is a test value, for real use the iv should be different every time 414 415OH_Huks_Result HuksAgreeKey(const struct OH_Huks_ParamSet *paramSet, const struct OH_Huks_Blob *keyAlias, 416 const struct OH_Huks_Blob *peerPublicKey, struct OH_Huks_Blob *agreedKey) 417{ 418 uint8_t temp[10] = {0}; 419 struct OH_Huks_Blob inData = { 420 sizeof(temp), 421 temp}; 422 423 uint8_t handleU[sizeof(uint64_t)] = {0}; 424 struct OH_Huks_Blob handle = {sizeof(uint64_t), handleU}; 425 OH_Huks_Result ret = OH_Huks_InitSession(keyAlias, paramSet, &handle, nullptr); 426 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 427 return ret; 428 } 429 430 uint8_t outDataU[1024] = {0}; 431 struct OH_Huks_Blob outDataUpdate = {1024, outDataU}; 432 ret = OH_Huks_UpdateSession(&handle, paramSet, peerPublicKey, &outDataUpdate); 433 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 434 return ret; 435 } 436 437 ret = OH_Huks_FinishSession(&handle, paramSet, &inData, agreedKey); 438 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 439 return ret; 440 } 441 return ret; 442} 443 444static const uint32_t TIMES = 4; 445static const uint32_t MAX_UPDATE_SIZE = 64; 446static const uint32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES; 447 448#define HUKS_FREE_BLOB(blob) do { \ 449 if ((blob).data != nullptr) { \ 450 free((blob).data); \ 451 (blob).data = nullptr; \ 452 } \ 453 (blob).size = 0; \ 454} while (0) 455 456#define OH_HUKS_KEY_BYTES(keySize) (((keySize) + 7) / 8) 457 458static OH_Huks_Result HksEncryptLoopUpdate(const struct OH_Huks_Blob *handle, const struct OH_Huks_ParamSet *paramSet, 459 const struct OH_Huks_Blob *inData, struct OH_Huks_Blob *outData) 460{ 461 struct OH_Huks_Result ret; 462 ret.errorCode = OH_HUKS_SUCCESS; 463 464 struct OH_Huks_Blob inDataSeg = *inData; 465 uint8_t *lastPtr = inData->data + inData->size - 1; 466 struct OH_Huks_Blob outDataSeg = {MAX_OUTDATA_SIZE, NULL}; 467 uint8_t *cur = outData->data; 468 outData->size = 0; 469 470 inDataSeg.size = MAX_UPDATE_SIZE; 471 bool isFinished = false; 472 473 while (inDataSeg.data <= lastPtr) { 474 if (inDataSeg.data + MAX_UPDATE_SIZE <= lastPtr) 475 { 476 outDataSeg.size = MAX_OUTDATA_SIZE; 477 } 478 else 479 { 480 isFinished = true; 481 inDataSeg.size = lastPtr - inDataSeg.data + 1; 482 break; 483 } 484 if (MallocAndCheckBlobData(&outDataSeg, outDataSeg.size).errorCode != (int32_t)OH_HUKS_SUCCESS) 485 { 486 ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR; 487 return ret; 488 } 489 ret = OH_Huks_UpdateSession(handle, paramSet, &inDataSeg, &outDataSeg); 490 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 491 free(outDataSeg.data); 492 return ret; 493 } 494 std::copy(outDataSeg.data, outDataSeg.data + outDataSeg.size, cur); 495 cur += outDataSeg.size; 496 outData->size += outDataSeg.size; 497 free(outDataSeg.data); 498 if ((isFinished == false) && (inDataSeg.data + MAX_UPDATE_SIZE > lastPtr)) { 499 ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR; 500 return ret; 501 } 502 inDataSeg.data += MAX_UPDATE_SIZE; 503 } 504 505 struct OH_Huks_Blob outDataFinish = {inDataSeg.size * TIMES, NULL}; 506 if (MallocAndCheckBlobData(&outDataFinish, outDataFinish.size).errorCode != (int32_t)OH_HUKS_SUCCESS) { 507 ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR; 508 return ret; 509 } 510 511 ret = OH_Huks_FinishSession(handle, paramSet, &inDataSeg, &outDataFinish); 512 if (ret.errorCode != OH_HUKS_SUCCESS) { 513 free(outDataFinish.data); 514 return ret; 515 } 516 std::copy(outDataFinish.data, outDataFinish.data + outDataFinish.size, cur); 517 outData->size += outDataFinish.size; 518 free(outDataFinish.data); 519 520 return ret; 521} 522 523OH_Huks_Result HuksEncrypt(const struct OH_Huks_Blob *key, const struct OH_Huks_ParamSet *paramSet, 524 const struct OH_Huks_Blob *plainText, struct OH_Huks_Blob *cipherText) 525{ 526 uint8_t handle[sizeof(uint64_t)] = {0}; 527 struct OH_Huks_Blob handleBlob = {sizeof(uint64_t), handle}; 528 OH_Huks_Result ret = OH_Huks_InitSession(key, paramSet, &handleBlob, nullptr); 529 if (ret.errorCode != OH_HUKS_SUCCESS) { 530 return ret; 531 } 532 533 ret = HksEncryptLoopUpdate(&handleBlob, paramSet, plainText, cipherText); 534 return ret; 535} 536 537static OH_Huks_Result BuildWrappedKeyData(struct OH_Huks_Blob **blobArray, uint32_t size, struct OH_Huks_Blob *outData) 538{ 539 uint32_t totalLength = size * sizeof(uint32_t); 540 struct OH_Huks_Result ret; 541 ret.errorCode = OH_HUKS_SUCCESS; 542 543 /* counter size */ 544 for (uint32_t i = 0; i < size; ++i) { 545 totalLength += blobArray[i]->size; 546 } 547 548 struct OH_Huks_Blob outBlob = {0, nullptr}; 549 outBlob.size = totalLength; 550 ret = MallocAndCheckBlobData(&outBlob, outBlob.size); 551 if (ret.errorCode != OH_HUKS_SUCCESS) { 552 return ret; 553 } 554 555 uint32_t offset = 0; 556 557 /* copy data */ 558 for (uint32_t i = 0; i < size; ++i) { 559 if (totalLength - offset >= sizeof(blobArray[i]->size)) { 560 std::copy(reinterpret_cast<uint8_t *>(&blobArray[i]->size), reinterpret_cast<uint8_t *>(&blobArray[i]->size) + sizeof(blobArray[i]->size), outBlob.data + offset); 561 } else { 562 ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR; 563 return ret; 564 } 565 566 offset += sizeof(blobArray[i]->size); 567 568 if (totalLength - offset >= blobArray[i]->size) { 569 std::copy(blobArray[i]->data, blobArray[i]->data + blobArray[i]->size, outBlob.data + offset); 570 } else { 571 ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR; 572 return ret; 573 } 574 575 offset += blobArray[i]->size; 576 } 577 578 outData->size = outBlob.size; 579 outData->data = outBlob.data; 580 return ret; 581} 582 583static OH_Huks_Result CheckParamsValid(const struct HksImportWrappedKeyTestParams *params) 584{ 585 struct OH_Huks_Result ret; 586 ret.errorCode = OH_HUKS_SUCCESS; 587 if (params == nullptr) { 588 ret.errorCode = OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT; 589 return ret; 590 } 591 592 if (params->wrappingKeyAlias == nullptr || params->genWrappingKeyParamSet == nullptr || 593 params->callerKeyAlias == nullptr || 594 params->genCallerKeyParamSet == nullptr || params->callerKekAlias == nullptr || 595 params->callerKek == nullptr || params->importCallerKekParamSet == nullptr || 596 params->callerAgreeKeyAlias == nullptr || params->agreeParamSet == nullptr || 597 params->importWrappedKeyParamSet == nullptr || params->importedKeyAlias == nullptr || 598 params->importedPlainKey == nullptr) { 599 ret.errorCode = OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT; 600 return ret; 601 } 602 return ret; 603} 604 605static OH_Huks_Result GenerateAndExportHuksPublicKey(const struct HksImportWrappedKeyTestParams *params, 606 struct OH_Huks_Blob *huksPublicKey) 607{ 608 OH_Huks_Result ret = OH_Huks_GenerateKeyItem(params->wrappingKeyAlias, params->genWrappingKeyParamSet, nullptr); 609 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 610 return ret; 611 } 612 huksPublicKey->size = params->publicKeySize; 613 ret = MallocAndCheckBlobData(huksPublicKey, huksPublicKey->size); 614 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 615 return ret; 616 } 617 ret = OH_Huks_ExportPublicKeyItem(params->wrappingKeyAlias, nullptr, huksPublicKey); 618 return ret; 619} 620 621static OH_Huks_Result GenerateAndExportCallerPublicKey(const struct HksImportWrappedKeyTestParams *params, 622 struct OH_Huks_Blob *callerSelfPublicKey) 623{ 624 OH_Huks_Result ret = OH_Huks_GenerateKeyItem(params->callerKeyAlias, params->genCallerKeyParamSet, nullptr); 625 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 626 return ret; 627 } 628 629 callerSelfPublicKey->size = params->publicKeySize; 630 ret = MallocAndCheckBlobData(callerSelfPublicKey, callerSelfPublicKey->size); 631 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 632 return ret; 633 } 634 ret = OH_Huks_ExportPublicKeyItem(params->callerKeyAlias, params->genWrappingKeyParamSet, callerSelfPublicKey); 635 return ret; 636} 637 638static OH_Huks_Result ImportKekAndAgreeSharedSecret(const struct HksImportWrappedKeyTestParams *params, 639 const struct OH_Huks_Blob *huksPublicKey, struct OH_Huks_Blob *outSharedKey) 640{ 641 OH_Huks_Result ret = OH_Huks_ImportKeyItem(params->callerKekAlias, 642 params->importCallerKekParamSet, params->callerKek); 643 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 644 return ret; 645 } 646 647 ret = MallocAndCheckBlobData(outSharedKey, outSharedKey->size); 648 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 649 return ret; 650 } 651 652 ret = HuksAgreeKey(params->agreeParamSet, params->callerKeyAlias, huksPublicKey, outSharedKey); 653 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 654 return ret; 655 } 656 struct OH_Huks_ParamSet *importAgreeKeyParams = nullptr; 657 ret = InitParamSet(&importAgreeKeyParams, g_importAgreeKeyParams, 658 sizeof(g_importAgreeKeyParams) / sizeof(OH_Huks_Param)); 659 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 660 return ret; 661 } 662 ret = OH_Huks_ImportKeyItem(params->callerAgreeKeyAlias, importAgreeKeyParams, outSharedKey); 663 664 OH_Huks_FreeParamSet(&importAgreeKeyParams); 665 return ret; 666} 667 668static OH_Huks_Result EncryptImportedPlainKeyAndKek(const struct HksImportWrappedKeyTestParams *params, 669 struct OH_Huks_Blob *plainCipherText, struct OH_Huks_Blob *kekCipherText) 670{ 671 struct OH_Huks_ParamSet *encryptParamSet = nullptr; 672 OH_Huks_Result ret = InitParamSet(&encryptParamSet, g_aesKekEncryptParams, 673 sizeof(g_aesKekEncryptParams) / sizeof(OH_Huks_Param)); 674 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 675 return ret; 676 } 677 ret = HuksEncrypt(params->callerKekAlias, encryptParamSet, params->importedPlainKey, plainCipherText); 678 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 679 return ret; 680 } 681 682 ret = HuksEncrypt(params->callerAgreeKeyAlias, encryptParamSet, params->callerKek, kekCipherText); 683 OH_Huks_FreeParamSet(&encryptParamSet); 684 return ret; 685} 686 687static OH_Huks_Result ImportWrappedKey(const struct HksImportWrappedKeyTestParams *params, struct OH_Huks_Blob *plainCipher, 688 struct OH_Huks_Blob *kekCipherText, struct OH_Huks_Blob *peerPublicKey, struct OH_Huks_Blob *wrappedKeyData) 689{ 690 struct OH_Huks_Blob commonAad = {.size = AAD_SIZE, 691 .data = reinterpret_cast<uint8_t *>(AAD)}; 692 struct OH_Huks_Blob commonNonce = {.size = NONCE_SIZE, 693 .data = reinterpret_cast<uint8_t *>(NONCE)}; 694 struct OH_Huks_Blob keyMaterialLen = {.size = sizeof(uint32_t), .data = (uint8_t *)¶ms->keyMaterialLen}; 695 696 /* copy AEAD tag from cipher text and decrease its size */ 697 const uint32_t tagSize = AEAD_TAG_SIZE; 698 uint8_t kekTagBuf[tagSize] = {0}; 699 struct OH_Huks_Blob kekTag = {.size = tagSize, .data = kekTagBuf}; 700 701 std::copy(plainCipher->data + (plainCipher->size - tagSize), plainCipher->data + (plainCipher->size - tagSize) + tagSize, kekTag.data); 702 703 plainCipher->size -= tagSize; 704 705 /* copy AEAD tag from kek cipher text and decrease its size */ 706 uint8_t agreeKeyTagBuf[tagSize] = {0}; 707 struct OH_Huks_Blob agreeKeyTag = {.size = tagSize, .data = agreeKeyTagBuf}; 708 std::copy(kekCipherText->data + (kekCipherText->size - tagSize), kekCipherText->data + (kekCipherText->size - tagSize) + tagSize, agreeKeyTagBuf); 709 710 kekCipherText->size -= tagSize; 711 712 struct OH_Huks_Blob *blobArray[] = {peerPublicKey, &commonAad, &commonNonce, &agreeKeyTag, kekCipherText, 713 &commonAad, &commonNonce, &kekTag, &keyMaterialLen, plainCipher}; 714 OH_Huks_Result ret = BuildWrappedKeyData(blobArray, OH_HUKS_IMPORT_WRAPPED_KEY_TOTAL_BLOBS, wrappedKeyData); 715 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 716 return ret; 717 } 718 struct OH_Huks_Param *purpose = nullptr; 719 ret = OH_Huks_GetParam(params->importWrappedKeyParamSet, OH_HUKS_TAG_PURPOSE, &purpose); 720 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 721 return ret; 722 } 723 ret = OH_Huks_ImportWrappedKeyItem(params->importedKeyAlias, params->wrappingKeyAlias, 724 params->importWrappedKeyParamSet, wrappedKeyData); 725 726 return ret; 727} 728 729OH_Huks_Result HksImportWrappedKeyTestCommonCase(const struct HksImportWrappedKeyTestParams *params) 730{ 731 OH_Huks_Result ret = CheckParamsValid(params); 732 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 733 return ret; 734 } 735 736 struct OH_Huks_Blob huksPublicKey = {0, nullptr}; 737 struct OH_Huks_Blob callerSelfPublicKey = {0, nullptr}; 738 struct OH_Huks_Blob outSharedKey = {.size = OH_HUKS_KEY_BYTES(OH_HUKS_AES_KEY_SIZE_256), .data = nullptr}; 739 struct OH_Huks_Blob wrappedKeyData = {0, nullptr}; 740 uint8_t plainKeyCipherBuffer[OH_HUKS_MAX_KEY_SIZE] = {0}; 741 struct OH_Huks_Blob plainCipherText = {OH_HUKS_MAX_KEY_SIZE, plainKeyCipherBuffer}; 742 uint8_t kekCipherTextBuffer[OH_HUKS_MAX_KEY_SIZE] = {0}; 743 struct OH_Huks_Blob kekCipherText = {OH_HUKS_MAX_KEY_SIZE, kekCipherTextBuffer}; 744 do { 745 /** 746 * Securely import a key from remote device A to local device B. 747 * 748 * 1. Prepare the key material to be imported on device A. In this example, g_importedAes256PlainKey is used as an example. 749 */ 750 751 /** 752 * 2. Generate an asymmetric key pair Caller_Key for device A. 753 */ 754 ret = GenerateAndExportCallerPublicKey(params, &callerSelfPublicKey); 755 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 756 break; 757 } 758 759 /** 760 * 3. Generate an asymmetric key pair Wrapping_Key with the key purpose of unwrap for device B. 761 */ 762 ret = GenerateAndExportHuksPublicKey(params, &huksPublicKey); 763 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 764 break; 765 } 766 767 /** 768 * 4. Generate a symmetric key Caller_Kek for device A. 769 * 5. Export the public key material from the asymmetric key pairs of devices A and B. In this example, the public key is stored in callerSelfPublicKey and huksPublicKey as variables. 770 * 6. Devices A and B perform key agreement and obtain an Agree_Key based on the private key of the Caller_Key (device A) and the public key of Wrapping_Key (device B). 771 */ 772 ret = ImportKekAndAgreeSharedSecret(params, &huksPublicKey, &outSharedKey); 773 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 774 break; 775 } 776 777 /** 778 * 7. Use Caller_Kek to encrypt To_Import_Key of device A and generate the To_Import_Key_Enc. 779 * 8. Use Agree_Key to encrypt Caller_Kek of device A and generate the Caller_Kek_Enc. 780 */ 781 ret = EncryptImportedPlainKeyAndKek(params, &plainCipherText, &kekCipherText); 782 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 783 break; 784 } 785 786 /** 787 * 9. Send the public key of Caller_Key, Caller_Kek_Enc, and To_Import_Key_Enc from device A to device B. In this example, keys are stored in callerSelfPublicKey, plainCipherText, and kekCipherText as variables. 788 */ 789 790 /** 791 * 10. Encapsulate and encrypt the key materials to be imported to device B. 792 * 11. Import the encrypted key material to device B. 793 * 12. Delete the keys, used for encrypting the key to import, from devices A and B. 794 */ 795 ret = ImportWrappedKey(params, &plainCipherText, &kekCipherText, &callerSelfPublicKey, &wrappedKeyData); 796 } while (0); 797 798 HUKS_FREE_BLOB(huksPublicKey); 799 HUKS_FREE_BLOB(callerSelfPublicKey); 800 HUKS_FREE_BLOB(outSharedKey); 801 HUKS_FREE_BLOB(wrappedKeyData); 802 return ret; 803} 804 805void HksClearKeysForWrappedKeyTest(const struct HksImportWrappedKeyTestParams *params) 806{ 807 OH_Huks_Result ret = CheckParamsValid(params); 808 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 809 return; 810 } 811 (void)OH_Huks_DeleteKeyItem(params->wrappingKeyAlias, nullptr); 812 (void)OH_Huks_DeleteKeyItem(params->callerKeyAlias, nullptr); 813 (void)OH_Huks_DeleteKeyItem(params->callerKekAlias, nullptr); 814 (void)OH_Huks_DeleteKeyItem(params->callerAgreeKeyAlias, nullptr); 815 (void)OH_Huks_DeleteKeyItem(params->importedKeyAlias, nullptr); 816} 817 818static OH_Huks_Result InitCommonTestParamsAndDoImport( 819 struct HksImportWrappedKeyTestParams *importWrappedKeyTestParams, 820 const struct OH_Huks_Param *importedKeyParamSetArray, 821 uint32_t arraySize) 822{ 823 struct OH_Huks_ParamSet *genX25519KeyParamSet = nullptr; 824 struct OH_Huks_ParamSet *genCallerKeyParamSet = nullptr; 825 struct OH_Huks_ParamSet *callerImportParamsKek = nullptr; 826 struct OH_Huks_ParamSet *agreeParamSet = nullptr; 827 struct OH_Huks_ParamSet *importPlainKeyParams = nullptr; 828 829 OH_Huks_Result ret; 830 do { 831 ret = InitParamSet(&genX25519KeyParamSet, g_genWrappingKeyParams, 832 sizeof(g_genWrappingKeyParams) / sizeof(OH_Huks_Param)); 833 if (ret.errorCode != OH_HUKS_SUCCESS) { 834 break; 835 } 836 importWrappedKeyTestParams->genWrappingKeyParamSet = genX25519KeyParamSet; 837 importWrappedKeyTestParams->publicKeySize = g_x25519PubKeySize; 838 839 ret = InitParamSet(&genCallerKeyParamSet, g_genCallerX25519Params, 840 sizeof(g_genCallerX25519Params) / sizeof(OH_Huks_Param)); 841 if (ret.errorCode != OH_HUKS_SUCCESS) { 842 break; 843 } 844 importWrappedKeyTestParams->genCallerKeyParamSet = genCallerKeyParamSet; 845 846 ret = InitParamSet(&callerImportParamsKek, g_importParamsCallerKek, 847 sizeof(g_importParamsCallerKek) / sizeof(OH_Huks_Param)); 848 if (ret.errorCode != OH_HUKS_SUCCESS) { 849 break; 850 } 851 importWrappedKeyTestParams->importCallerKekParamSet = callerImportParamsKek; 852 853 ret = InitParamSet(&agreeParamSet, g_callerAgreeParams, 854 sizeof(g_callerAgreeParams) / sizeof(OH_Huks_Param)); 855 if (ret.errorCode != OH_HUKS_SUCCESS) { 856 break; 857 } 858 importWrappedKeyTestParams->agreeParamSet = agreeParamSet; 859 860 ret = InitParamSet(&importPlainKeyParams, importedKeyParamSetArray, arraySize); 861 if (ret.errorCode != OH_HUKS_SUCCESS) { 862 break; 863 } 864 importWrappedKeyTestParams->importWrappedKeyParamSet = importPlainKeyParams; 865 866 ret = HksImportWrappedKeyTestCommonCase(importWrappedKeyTestParams); 867 } while (0); 868 869 OH_Huks_FreeParamSet(&genX25519KeyParamSet); 870 OH_Huks_FreeParamSet(&genCallerKeyParamSet); 871 OH_Huks_FreeParamSet(&callerImportParamsKek); 872 OH_Huks_FreeParamSet(&agreeParamSet); 873 OH_Huks_FreeParamSet(&importPlainKeyParams); 874 return ret; 875} 876 877static napi_value ImportWrappedKey(napi_env env, napi_callback_info info) 878{ 879 struct HksImportWrappedKeyTestParams importWrappedKeyTestParams001 = {0}; 880 881 importWrappedKeyTestParams001.wrappingKeyAlias = &g_wrappingKeyAliasAes256; 882 importWrappedKeyTestParams001.keyMaterialLen = g_importedAes256PlainKey.size; 883 importWrappedKeyTestParams001.callerKeyAlias = &g_callerKeyAliasAes256; 884 importWrappedKeyTestParams001.callerKekAlias = &g_callerKekAliasAes256; 885 importWrappedKeyTestParams001.callerKek = &g_callerAes256Kek; 886 importWrappedKeyTestParams001.callerAgreeKeyAlias = &g_callerAgreeKeyAliasAes256; 887 importWrappedKeyTestParams001.importedKeyAlias = &g_importedKeyAliasAes256; 888 importWrappedKeyTestParams001.importedPlainKey = &g_importedAes256PlainKey; 889 OH_Huks_Result ohResult = InitCommonTestParamsAndDoImport(&importWrappedKeyTestParams001, g_importWrappedAes256Params, 890 sizeof(g_importWrappedAes256Params) / sizeof(struct OH_Huks_Param)); 891 HksClearKeysForWrappedKeyTest(&importWrappedKeyTestParams001); 892 893 napi_value ret; 894 napi_create_int32(env, ohResult.errorCode, &ret); 895 return ret; 896} 897``` 898 899### Common Key Operations 900 901**Scenarios** 902 903To ensure data confidentiality and integrity, you may need to encrypt or decrypt data, generate or verify a signature, perform key agreement, and derive a key. The following describes common key operations. 904 905**General Development Process** 906 907The HUKS operates data based on key sessions. The general process is as follows: 908 9091. Initialize a key session using [OH_Huks_InitSession](../reference/native-apis/_huks_key_api.md#oh_huks_initsession).<br>You need to pass in the key alias and key operation parameters. After the initialization, a session handle is returned. The key operation parameters must contain the parameters required by the cipher algorithm, including the cipher algorithm, key size, key purpose, working mode, padding mode, hash mode, IV, nonce, and AAD. 9102. Update data by segment using [OH_Huks_UpdateSession](../reference/native-apis/_huks_key_api.md#oh_huks_updatesession) to pass in data by segment.<br>In key agreement, key derivation, and signature verification, you need to use this API to perform algorithm operations. In other cases, for example, the data exceeds 100 KB or the cryptographic algorithm requires data operations by segment, you can use this API to pass in data by segment. 9113. Finish the key session using [OH_Huks_FinishSession](../reference/native-apis/_huks_key_api.md#oh_huks_finishsession).<br>Operate the last segment of data and end the key session. If an error occurs during this process or the key operation data is not required, use [OH_Huks_AbortSession](../reference/native-apis/_huks_key_api.md#oh_huks_abortsession) to abort the session. This step is mandatory. 912 913#### Encryption and Decryption 914 915**C++ Code Example** 916 917```C++ 918#include "huks/native_huks_api.h" 919#include "huks/native_huks_param.h" 920#include <string.h> 921OH_Huks_Result InitParamSet( 922 struct OH_Huks_ParamSet **paramSet, 923 const struct OH_Huks_Param *params, 924 uint32_t paramCount) 925{ 926 OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet); 927 if (ret.errorCode != OH_HUKS_SUCCESS) { 928 return ret; 929 } 930 931 ret = OH_Huks_AddParams(*paramSet, params, paramCount); 932 if (ret.errorCode != OH_HUKS_SUCCESS) { 933 OH_Huks_FreeParamSet(paramSet); 934 return ret; 935 } 936 937 ret = OH_Huks_BuildParamSet(paramSet); 938 if (ret.errorCode != OH_HUKS_SUCCESS) { 939 OH_Huks_FreeParamSet(paramSet); 940 return ret; 941 } 942 943 return ret; 944} 945 946static const uint32_t IV_SIZE = 16; 947static uint8_t IV[IV_SIZE] = { 0 }; // this is a test value, for real use the iv should be different every time 948 949static struct OH_Huks_Param g_genEncDecParams[] = { 950 { 951 .tag = OH_HUKS_TAG_ALGORITHM, 952 .uint32Param = OH_HUKS_ALG_AES 953 }, { 954 .tag = OH_HUKS_TAG_PURPOSE, 955 .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT | OH_HUKS_KEY_PURPOSE_DECRYPT 956 }, { 957 .tag = OH_HUKS_TAG_KEY_SIZE, 958 .uint32Param = OH_HUKS_AES_KEY_SIZE_256 959 }, { 960 .tag = OH_HUKS_TAG_PADDING, 961 .uint32Param = OH_HUKS_PADDING_NONE 962 }, { 963 .tag = OH_HUKS_TAG_BLOCK_MODE, 964 .uint32Param = OH_HUKS_MODE_CBC 965 } 966}; 967 968static struct OH_Huks_Param g_encryptParams[] = { 969 { 970 .tag = OH_HUKS_TAG_ALGORITHM, 971 .uint32Param = OH_HUKS_ALG_AES 972 }, { 973 .tag = OH_HUKS_TAG_PURPOSE, 974 .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT 975 }, { 976 .tag = OH_HUKS_TAG_KEY_SIZE, 977 .uint32Param = OH_HUKS_AES_KEY_SIZE_256 978 }, { 979 .tag = OH_HUKS_TAG_PADDING, 980 .uint32Param = OH_HUKS_PADDING_NONE 981 }, { 982 .tag = OH_HUKS_TAG_BLOCK_MODE, 983 .uint32Param = OH_HUKS_MODE_CBC 984 }, { 985 .tag = OH_HUKS_TAG_IV, 986 .blob = { 987 .size = IV_SIZE, 988 .data = (uint8_t *)IV // this is a test value, for real use the iv should be different every time 989 } 990 } 991}; 992 993static struct OH_Huks_Param g_decryptParams[] = { 994 { 995 .tag = OH_HUKS_TAG_ALGORITHM, 996 .uint32Param = OH_HUKS_ALG_AES 997 }, { 998 .tag = OH_HUKS_TAG_PURPOSE, 999 .uint32Param = OH_HUKS_KEY_PURPOSE_DECRYPT 1000 }, { 1001 .tag = OH_HUKS_TAG_KEY_SIZE, 1002 .uint32Param = OH_HUKS_AES_KEY_SIZE_256 1003 }, { 1004 .tag = OH_HUKS_TAG_PADDING, 1005 .uint32Param = OH_HUKS_PADDING_NONE 1006 }, { 1007 .tag = OH_HUKS_TAG_BLOCK_MODE, 1008 .uint32Param = OH_HUKS_MODE_CBC 1009 }, { 1010 .tag = OH_HUKS_TAG_IV, 1011 .blob = { 1012 .size = IV_SIZE, 1013 .data = (uint8_t *)IV // this is a test value, for real use the iv should be different every time 1014 } 1015 } 1016}; 1017 1018static const uint32_t AES_COMMON_SIZE = 1024; 1019 1020OH_Huks_Result HksAesCipherTestEncrypt( 1021 const struct OH_Huks_Blob *keyAlias, 1022 const struct OH_Huks_ParamSet *encryptParamSet, const struct OH_Huks_Blob *inData, struct OH_Huks_Blob *cipherText) 1023{ 1024 uint8_t handleE[sizeof(uint64_t)] = {0}; 1025 struct OH_Huks_Blob handleEncrypt = {sizeof(uint64_t), handleE}; 1026 OH_Huks_Result ret = OH_Huks_InitSession(keyAlias, encryptParamSet, &handleEncrypt, nullptr); 1027 if (ret.errorCode != OH_HUKS_SUCCESS) { 1028 return ret; 1029 } 1030 1031 ret = OH_Huks_FinishSession(&handleEncrypt, encryptParamSet, inData, cipherText); 1032 1033 return ret; 1034} 1035 1036OH_Huks_Result HksAesCipherTestDecrypt( 1037 const struct OH_Huks_Blob *keyAlias, 1038 const struct OH_Huks_ParamSet *decryptParamSet, const struct OH_Huks_Blob *cipherText, struct OH_Huks_Blob *plainText, 1039 const struct OH_Huks_Blob *inData) 1040{ 1041 uint8_t handleD[sizeof(uint64_t)] = {0}; 1042 struct OH_Huks_Blob handleDecrypt = {sizeof(uint64_t), handleD}; 1043 OH_Huks_Result ret = OH_Huks_InitSession(keyAlias, decryptParamSet, &handleDecrypt, nullptr); 1044 if (ret.errorCode != OH_HUKS_SUCCESS) { 1045 return ret; 1046 } 1047 1048 ret = OH_Huks_FinishSession(&handleDecrypt, decryptParamSet, cipherText, plainText); 1049 1050 return ret; 1051} 1052 1053static napi_value EncDecKey(napi_env env, napi_callback_info info) 1054{ 1055 char tmpKeyAlias[] = "test_enc_dec"; 1056 struct OH_Huks_Blob keyAlias = { (uint32_t)strlen(tmpKeyAlias), (uint8_t *)tmpKeyAlias }; 1057 struct OH_Huks_ParamSet *genParamSet = nullptr; 1058 struct OH_Huks_ParamSet *encryptParamSet = nullptr; 1059 struct OH_Huks_ParamSet *decryptParamSet = nullptr; 1060 OH_Huks_Result ohResult; 1061 do { 1062 ohResult = InitParamSet(&genParamSet, g_genEncDecParams, sizeof(g_genEncDecParams) / sizeof(OH_Huks_Param)); 1063 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1064 break; 1065 } 1066 ohResult = InitParamSet(&encryptParamSet, g_encryptParams, sizeof(g_encryptParams) / sizeof(OH_Huks_Param)); 1067 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1068 break; 1069 } 1070 ohResult = InitParamSet(&decryptParamSet, g_decryptParams, sizeof(g_decryptParams) / sizeof(OH_Huks_Param)); 1071 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1072 break; 1073 } 1074 char tmpInData[] = "AES_ECB_INDATA_1"; 1075 struct OH_Huks_Blob inData = { (uint32_t)strlen(tmpInData), (uint8_t *)tmpInData }; 1076 /* 1. Generate a key. */ 1077 ohResult = OH_Huks_GenerateKeyItem(&keyAlias, genParamSet, nullptr); 1078 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1079 break; 1080 } 1081 /* 2. Encrypt data using a key. */ 1082 uint8_t cipher[AES_COMMON_SIZE] = {0}; 1083 struct OH_Huks_Blob cipherText = {AES_COMMON_SIZE, cipher}; 1084 ohResult = HksAesCipherTestEncrypt(&keyAlias, encryptParamSet, &inData, &cipherText); 1085 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1086 break; 1087 } 1088 1089 /* 3. Decrypt data using a key. */ 1090 uint8_t plain[AES_COMMON_SIZE] = {0}; 1091 struct OH_Huks_Blob plainText = {AES_COMMON_SIZE, plain}; 1092 ohResult = HksAesCipherTestDecrypt(&keyAlias, decryptParamSet, &cipherText, &plainText, &inData); 1093 } while (0); 1094 /* 4. Delete a key. */ 1095 (void)OH_Huks_DeleteKeyItem(&keyAlias, genParamSet); 1096 1097 OH_Huks_FreeParamSet(&genParamSet); 1098 OH_Huks_FreeParamSet(&encryptParamSet); 1099 OH_Huks_FreeParamSet(&decryptParamSet); 1100 1101 napi_value ret; 1102 napi_create_int32(env, ohResult.errorCode, &ret); 1103 return ret; 1104} 1105``` 1106 1107#### Signing and Signature Verification 1108 1109**C++ Code Example** 1110 1111```C++ 1112#include "huks/native_huks_api.h" 1113#include "huks/native_huks_param.h" 1114#include <string.h> 1115OH_Huks_Result InitParamSet( 1116 struct OH_Huks_ParamSet **paramSet, 1117 const struct OH_Huks_Param *params, 1118 uint32_t paramCount) 1119{ 1120 OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet); 1121 if (ret.errorCode != OH_HUKS_SUCCESS) { 1122 return ret; 1123 } 1124 1125 ret = OH_Huks_AddParams(*paramSet, params, paramCount); 1126 if (ret.errorCode != OH_HUKS_SUCCESS) { 1127 OH_Huks_FreeParamSet(paramSet); 1128 return ret; 1129 } 1130 1131 ret = OH_Huks_BuildParamSet(paramSet); 1132 if (ret.errorCode != OH_HUKS_SUCCESS) { 1133 OH_Huks_FreeParamSet(paramSet); 1134 return ret; 1135 } 1136 1137 return ret; 1138} 1139 1140static struct OH_Huks_Param g_genSignVerifyParamsTest[] = { 1141 { 1142 .tag = OH_HUKS_TAG_ALGORITHM, 1143 .uint32Param = OH_HUKS_ALG_RSA 1144 }, { 1145 .tag = OH_HUKS_TAG_PURPOSE, 1146 .uint32Param = OH_HUKS_KEY_PURPOSE_SIGN | OH_HUKS_KEY_PURPOSE_VERIFY 1147 }, { 1148 .tag = OH_HUKS_TAG_KEY_SIZE, 1149 .uint32Param = OH_HUKS_RSA_KEY_SIZE_2048 1150 }, { 1151 .tag = OH_HUKS_TAG_PADDING, 1152 .uint32Param = OH_HUKS_PADDING_PSS 1153 }, { 1154 .tag = OH_HUKS_TAG_DIGEST, 1155 .uint32Param = OH_HUKS_DIGEST_SHA384 1156 }, 1157}; 1158 1159static struct OH_Huks_Param g_signParamsTest[] = { 1160 { 1161 .tag = OH_HUKS_TAG_ALGORITHM, 1162 .uint32Param = OH_HUKS_ALG_RSA 1163 }, { 1164 .tag = OH_HUKS_TAG_PURPOSE, 1165 .uint32Param = OH_HUKS_KEY_PURPOSE_SIGN 1166 }, { 1167 .tag = OH_HUKS_TAG_KEY_SIZE, 1168 .uint32Param = OH_HUKS_RSA_KEY_SIZE_2048 1169 }, { 1170 .tag = OH_HUKS_TAG_PADDING, 1171 .uint32Param = OH_HUKS_PADDING_PSS 1172 }, { 1173 .tag = OH_HUKS_TAG_DIGEST, 1174 .uint32Param = OH_HUKS_DIGEST_SHA384 1175 } 1176}; 1177 1178static struct OH_Huks_Param g_verifyParamsTest[] = { 1179 { 1180 .tag = OH_HUKS_TAG_ALGORITHM, 1181 .uint32Param = OH_HUKS_ALG_RSA 1182 }, { 1183 .tag = OH_HUKS_TAG_PURPOSE, 1184 .uint32Param = OH_HUKS_KEY_PURPOSE_VERIFY 1185 }, { 1186 .tag = OH_HUKS_TAG_KEY_SIZE, 1187 .uint32Param = OH_HUKS_RSA_KEY_SIZE_2048 1188 }, { 1189 .tag = OH_HUKS_TAG_PADDING, 1190 .uint32Param = OH_HUKS_PADDING_PSS 1191 }, { 1192 .tag = OH_HUKS_TAG_DIGEST, 1193 .uint32Param = OH_HUKS_DIGEST_SHA384 1194 } 1195}; 1196 1197static const uint32_t RSA_COMMON_SIZE = 1024; 1198static const char *g_dataToSign = "Hks_RSA_Sign_Verify_Test_0000000000000000000000000000000000000000000000000000000" 1199 "00000000000000000000000000000000000000000000000000000000000000000000000000000000" 1200 "0000000000000000000000000000000000000000000000000000000000000000000000000_string"; 1201 1202static napi_value SignVerifyKey(napi_env env, napi_callback_info info) 1203{ 1204 struct OH_Huks_Blob g_keyAlias = { 1205 (uint32_t)strlen("test_signVerify"), 1206 (uint8_t *)"test_signVerify" 1207 }; 1208 struct OH_Huks_Blob inData = { 1209 (uint32_t)strlen(g_dataToSign), 1210 (uint8_t *)g_dataToSign 1211 }; 1212 struct OH_Huks_ParamSet *genParamSet = nullptr; 1213 struct OH_Huks_ParamSet *signParamSet = nullptr; 1214 struct OH_Huks_ParamSet *verifyParamSet = nullptr; 1215 OH_Huks_Result ohResult; 1216 do { 1217 ohResult = InitParamSet(&genParamSet, g_genSignVerifyParamsTest, sizeof(g_genSignVerifyParamsTest) / sizeof(OH_Huks_Param)); 1218 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1219 break; 1220 } 1221 ohResult = InitParamSet(&signParamSet, g_signParamsTest, sizeof(g_signParamsTest) / sizeof(OH_Huks_Param)); 1222 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1223 break; 1224 } 1225 ohResult = InitParamSet(&verifyParamSet, g_verifyParamsTest, sizeof(g_verifyParamsTest) / sizeof(OH_Huks_Param)); 1226 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1227 break; 1228 } 1229 /* 1. Generate a key. */ 1230 ohResult = OH_Huks_GenerateKeyItem(&g_keyAlias, genParamSet, nullptr); 1231 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1232 break; 1233 } 1234 /* 2. Generate a signature. */ 1235 // Init 1236 uint8_t handleS[sizeof(uint64_t)] = {0}; 1237 struct OH_Huks_Blob handleSign = { (uint32_t)sizeof(uint64_t), handleS }; 1238 ohResult = OH_Huks_InitSession(&g_keyAlias, signParamSet, &handleSign, nullptr); 1239 1240 // Update 1241 uint8_t outDataS[RSA_COMMON_SIZE] = {0}; 1242 struct OH_Huks_Blob outDataSign = { RSA_COMMON_SIZE, outDataS }; 1243 1244 ohResult = OH_Huks_UpdateSession(&handleSign, signParamSet, &inData, &outDataSign); 1245 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1246 break; 1247 } 1248 1249 // Finish 1250 struct OH_Huks_Blob finishInData = { 0, NULL }; 1251 ohResult = OH_Huks_FinishSession(&handleSign, signParamSet, &finishInData, &outDataSign); 1252 1253 /* 3. Verify a signature. */ 1254 // Init 1255 uint8_t handleV[sizeof(uint64_t)] = {0}; 1256 struct OH_Huks_Blob handleVerify = { (uint32_t)sizeof(uint64_t), handleV }; 1257 ohResult = OH_Huks_InitSession(&g_keyAlias, verifyParamSet, &handleVerify, nullptr); 1258 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1259 break; 1260 } 1261 // Update loop 1262 uint8_t temp[] = "out"; 1263 struct OH_Huks_Blob verifyOut = { (uint32_t)sizeof(temp), temp }; 1264 ohResult = OH_Huks_UpdateSession(&handleVerify, verifyParamSet, &inData, &verifyOut); 1265 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1266 break; 1267 } 1268 // Finish 1269 ohResult = OH_Huks_FinishSession(&handleVerify, verifyParamSet, &outDataSign, &verifyOut); 1270 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1271 break; 1272 } 1273 } while (0); 1274 (void)OH_Huks_DeleteKeyItem(&g_keyAlias, genParamSet); 1275 OH_Huks_FreeParamSet(&genParamSet); 1276 OH_Huks_FreeParamSet(&signParamSet); 1277 OH_Huks_FreeParamSet(&verifyParamSet); 1278 1279 napi_value ret; 1280 napi_create_int32(env, ohResult.errorCode, &ret); 1281 return ret; 1282} 1283``` 1284 1285#### Key Agreement 1286 1287You are advised to pass in [HuksKeyStorageType](../reference/apis/js-apis-huks.md#hukskeystoragetype) to specify the storage type in key agreement. From API version 10, only **HUKS_STORAGE_ONLY_USED_IN_HUKS** or **HUKS_STORAGE_KEY_EXPORT_ALLOWED** can be used. If **HuksKeyStorageType** is not passed in, the key can be stored or exported by default, which poses security risks. 1288 1289**C++ Code Example** 1290 1291```C++ 1292#include "huks/native_huks_api.h" 1293#include "huks/native_huks_param.h" 1294#include <string.h> 1295OH_Huks_Result InitParamSet( 1296 struct OH_Huks_ParamSet **paramSet, 1297 const struct OH_Huks_Param *params, 1298 uint32_t paramCount) 1299{ 1300 OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet); 1301 if (ret.errorCode != OH_HUKS_SUCCESS) { 1302 return ret; 1303 } 1304 1305 ret = OH_Huks_AddParams(*paramSet, params, paramCount); 1306 if (ret.errorCode != OH_HUKS_SUCCESS) { 1307 OH_Huks_FreeParamSet(paramSet); 1308 return ret; 1309 } 1310 1311 ret = OH_Huks_BuildParamSet(paramSet); 1312 if (ret.errorCode != OH_HUKS_SUCCESS) { 1313 OH_Huks_FreeParamSet(paramSet); 1314 return ret; 1315 } 1316 1317 return ret; 1318} 1319 1320static const uint32_t IV_SIZE = 16; 1321static uint8_t IV[IV_SIZE] = { 0 }; // this is a test value, for real use the iv should be different every time 1322 1323static struct OH_Huks_Blob g_keyAliasFinal1001 = { 1324 (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_1_final"), 1325 (uint8_t *)"HksECDHAgreeKeyAliasTest001_1_final" 1326}; 1327 1328static struct OH_Huks_Param g_genAgreeParams[] = { 1329 { 1330 .tag = OH_HUKS_TAG_ALGORITHM, 1331 .uint32Param = OH_HUKS_ALG_ECC 1332 }, { 1333 .tag = OH_HUKS_TAG_PURPOSE, 1334 .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE 1335 }, { 1336 .tag = OH_HUKS_TAG_KEY_SIZE, 1337 .uint32Param = OH_HUKS_ECC_KEY_SIZE_256 1338 }, { 1339 .tag = OH_HUKS_TAG_DIGEST, 1340 .uint32Param = OH_HUKS_DIGEST_NONE 1341 } 1342}; 1343 1344static struct OH_Huks_Param g_agreeParamsInit01[] = { 1345 { 1346 .tag = OH_HUKS_TAG_ALGORITHM, 1347 .uint32Param = OH_HUKS_ALG_ECDH 1348 }, { 1349 .tag = OH_HUKS_TAG_PURPOSE, 1350 .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE 1351 }, { 1352 .tag = OH_HUKS_TAG_KEY_SIZE, 1353 .uint32Param = OH_HUKS_ECC_KEY_SIZE_256 1354 } 1355}; 1356 1357static struct OH_Huks_Param g_agreeParamsFinish01[] = { 1358 { 1359 .tag = OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 1360 .uint32Param = OH_HUKS_STORAGE_ONLY_USED_IN_HUKS 1361 }, { 1362 .tag = OH_HUKS_TAG_ALGORITHM, 1363 .uint32Param = OH_HUKS_ALG_AES 1364 }, { 1365 .tag = OH_HUKS_TAG_KEY_SIZE, 1366 .uint32Param = OH_HUKS_AES_KEY_SIZE_256 1367 }, { 1368 .tag = OH_HUKS_TAG_PURPOSE, 1369 .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE 1370 }, { 1371 .tag = OH_HUKS_TAG_KEY_ALIAS, 1372 .blob = g_keyAliasFinal1001 1373 }, { 1374 .tag = OH_HUKS_TAG_PADDING, 1375 .uint32Param = OH_HUKS_PADDING_NONE 1376 }, { 1377 .tag = OH_HUKS_TAG_BLOCK_MODE, 1378 .uint32Param = OH_HUKS_MODE_CBC 1379 } 1380}; 1381 1382static struct OH_Huks_Blob g_keyAliasFinal2001 = { 1383 (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_2_final"), 1384 (uint8_t *)"HksECDHAgreeKeyAliasTest001_2_final" 1385}; 1386 1387static struct OH_Huks_Param g_agreeParamsInit02[] = { 1388 { 1389 .tag = OH_HUKS_TAG_ALGORITHM, 1390 .uint32Param = OH_HUKS_ALG_ECDH 1391 }, { 1392 .tag = OH_HUKS_TAG_PURPOSE, 1393 .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE 1394 }, { 1395 .tag = OH_HUKS_TAG_KEY_SIZE, 1396 .uint32Param = OH_HUKS_ECC_KEY_SIZE_256 1397 } 1398}; 1399 1400static struct OH_Huks_Param g_agreeParamsFinish02[] = { 1401 { 1402 .tag = OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 1403 .uint32Param = OH_HUKS_STORAGE_ONLY_USED_IN_HUKS 1404 }, { 1405 .tag = OH_HUKS_TAG_ALGORITHM, 1406 .uint32Param = OH_HUKS_ALG_AES 1407 }, { 1408 .tag = OH_HUKS_TAG_KEY_SIZE, 1409 .uint32Param = OH_HUKS_AES_KEY_SIZE_256 1410 }, { 1411 .tag = OH_HUKS_TAG_PURPOSE, 1412 .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE 1413 }, { 1414 .tag = OH_HUKS_TAG_KEY_ALIAS, 1415 .blob = g_keyAliasFinal2001 1416 }, { 1417 .tag = OH_HUKS_TAG_PADDING, 1418 .uint32Param = OH_HUKS_PADDING_NONE 1419 }, { 1420 .tag = OH_HUKS_TAG_BLOCK_MODE, 1421 .uint32Param = OH_HUKS_MODE_CBC 1422 } 1423}; 1424 1425static const uint32_t ECDH_COMMON_SIZE = 1024; 1426 1427static struct OH_Huks_Blob g_keyAlias01001 = { 1428 (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_1"), 1429 (uint8_t *)"HksECDHAgreeKeyAliasTest001_1" 1430}; 1431 1432static struct OH_Huks_Blob g_keyAlias02001 = { 1433 (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_2"), 1434 (uint8_t *)"HksECDHAgreeKeyAliasTest001_2" 1435}; 1436 1437OH_Huks_Result MallocAndCheckBlobData( 1438 struct OH_Huks_Blob *blob, 1439 const uint32_t blobSize) 1440{ 1441 struct OH_Huks_Result ret; 1442 ret.errorCode = OH_HUKS_SUCCESS; 1443 1444 blob->data = (uint8_t *)malloc(blobSize); 1445 if (blob->data == NULL) { 1446 ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR; 1447 } 1448 1449 return ret; 1450} 1451 1452OH_Huks_Result HksEcdhAgreeExport(const struct OH_Huks_Blob *keyAlias1, const struct OH_Huks_Blob *keyAlias2, 1453 struct OH_Huks_Blob *publicKey1, struct OH_Huks_Blob *publicKey2, const struct OH_Huks_ParamSet *genParamSet) 1454{ 1455 OH_Huks_Result ret = OH_Huks_ExportPublicKeyItem(keyAlias1, genParamSet, publicKey1); 1456 if (ret.errorCode != OH_HUKS_SUCCESS) { 1457 return ret; 1458 } 1459 ret = OH_Huks_ExportPublicKeyItem(keyAlias2, genParamSet, publicKey2); 1460 if (ret.errorCode != OH_HUKS_SUCCESS) { 1461 return ret; 1462 } 1463 return ret; 1464} 1465 1466static const char *g_inData = "Hks_ECDH_Agree_Test_000000000000000000000000000000000000000000000000000000000000" 1467 "00000000000000000000000000000000000000000000000000000000000000000000000000000000" 1468 "0000000000000000000000000000000000000000000000000000000000000000000000000_string"; 1469 1470OH_Huks_Result HksEcdhAgreeFinish(const struct OH_Huks_Blob *keyAlias, const struct OH_Huks_Blob *publicKey, 1471 const struct OH_Huks_ParamSet *initParamSet, const struct OH_Huks_ParamSet *finishParamSet, struct OH_Huks_Blob *outData) 1472{ 1473 struct OH_Huks_Blob inData = { 1474 (uint32_t)strlen(g_inData), 1475 (uint8_t *)g_inData 1476 }; 1477 1478 uint8_t handleU[sizeof(uint64_t)] = {0}; 1479 struct OH_Huks_Blob handle = { sizeof(uint64_t), handleU }; 1480 OH_Huks_Result ret = OH_Huks_InitSession(keyAlias, initParamSet, &handle, nullptr); 1481 if (ret.errorCode != OH_HUKS_SUCCESS) { 1482 return ret; 1483 } 1484 1485 uint8_t outDataU[ECDH_COMMON_SIZE] = {0}; 1486 struct OH_Huks_Blob outDataUpdate = { ECDH_COMMON_SIZE, outDataU }; 1487 ret = OH_Huks_UpdateSession(&handle, initParamSet, publicKey, &outDataUpdate); 1488 if (ret.errorCode != OH_HUKS_SUCCESS) { 1489 return ret; 1490 } 1491 1492 ret = OH_Huks_FinishSession(&handle, finishParamSet, &inData, outData); 1493 if (ret.errorCode != OH_HUKS_SUCCESS) { 1494 return ret; 1495 } 1496 return ret; 1497} 1498 1499static napi_value AgreeKey(napi_env env, napi_callback_info info) 1500{ 1501 struct OH_Huks_ParamSet *genParamSet = nullptr; 1502 struct OH_Huks_ParamSet *initParamSet01 = nullptr; 1503 struct OH_Huks_ParamSet *finishParamSet01 = nullptr; 1504 struct OH_Huks_ParamSet *initParamSet02 = nullptr; 1505 struct OH_Huks_ParamSet *finishParamSet02 = nullptr; 1506 struct OH_Huks_Blob publicKey01 = { .size = OH_HUKS_ECC_KEY_SIZE_256, .data = nullptr }; 1507 struct OH_Huks_Blob publicKey02 = { .size = OH_HUKS_ECC_KEY_SIZE_256, .data = nullptr }; 1508 struct OH_Huks_Blob outData01 = { .size = ECDH_COMMON_SIZE, .data = nullptr }; 1509 struct OH_Huks_Blob outData02 = { .size = ECDH_COMMON_SIZE, .data = nullptr }; 1510 OH_Huks_Result ohResult; 1511 do { 1512 ohResult = InitParamSet(&genParamSet, g_genAgreeParams, sizeof(g_genAgreeParams) / sizeof(OH_Huks_Param)); 1513 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1514 break; 1515 } 1516 ohResult = InitParamSet(&initParamSet01, g_agreeParamsInit01, sizeof(g_agreeParamsInit01) / sizeof(OH_Huks_Param)); 1517 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1518 break; 1519 } 1520 ohResult = InitParamSet(&finishParamSet01, g_agreeParamsFinish01, 1521 sizeof(g_agreeParamsFinish01) / sizeof(OH_Huks_Param)); 1522 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1523 break; 1524 } 1525 ohResult = InitParamSet(&initParamSet02, g_agreeParamsInit02, sizeof(g_agreeParamsInit02) / sizeof(OH_Huks_Param)); 1526 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1527 break; 1528 } 1529 ohResult = InitParamSet(&finishParamSet02, g_agreeParamsFinish02, 1530 sizeof(g_agreeParamsFinish02) / sizeof(OH_Huks_Param)); 1531 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1532 break; 1533 } 1534 /* 1. Get Key One */ 1535 ohResult = OH_Huks_GenerateKeyItem(&g_keyAlias01001, genParamSet, nullptr); 1536 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1537 break; 1538 } 1539 /* 2. Get Key Two */ 1540 ohResult = OH_Huks_GenerateKeyItem(&g_keyAlias02001, genParamSet, nullptr); 1541 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1542 break; 1543 } 1544 ohResult = MallocAndCheckBlobData(&publicKey01, publicKey01.size); 1545 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1546 break; 1547 } 1548 ohResult = MallocAndCheckBlobData(&publicKey02, publicKey02.size); 1549 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1550 break; 1551 } 1552 /* 3. Get public keys of key one and key two */ 1553 ohResult = HksEcdhAgreeExport(&g_keyAlias01001, &g_keyAlias02001, &publicKey01, &publicKey02, genParamSet); 1554 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1555 break; 1556 } 1557 ohResult = MallocAndCheckBlobData(&outData01, outData01.size); 1558 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1559 break; 1560 } 1561 ohResult = MallocAndCheckBlobData(&outData02, outData02.size); 1562 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1563 break; 1564 } 1565 /* 4. Agree with key one and public key of key two */ 1566 ohResult = HksEcdhAgreeFinish(&g_keyAlias01001, &publicKey02, initParamSet01, finishParamSet01, &outData01); 1567 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1568 break; 1569 } 1570 /* 5. Agree with key two and public key of key one */ 1571 ohResult = HksEcdhAgreeFinish(&g_keyAlias02001, &publicKey01, initParamSet02, finishParamSet02, &outData02); 1572 } while (0); 1573 free(publicKey01.data); 1574 free(publicKey02.data); 1575 free(outData01.data); 1576 free(outData02.data); 1577 OH_Huks_DeleteKeyItem(&g_keyAlias01001, genParamSet); 1578 OH_Huks_DeleteKeyItem(&g_keyAlias02001, genParamSet); 1579 OH_Huks_DeleteKeyItem(&g_keyAliasFinal1001, NULL); 1580 OH_Huks_DeleteKeyItem(&g_keyAliasFinal2001, NULL); 1581 OH_Huks_FreeParamSet(&genParamSet); 1582 OH_Huks_FreeParamSet(&initParamSet01); 1583 OH_Huks_FreeParamSet(&finishParamSet01); 1584 OH_Huks_FreeParamSet(&initParamSet02); 1585 OH_Huks_FreeParamSet(&finishParamSet02); 1586 1587 napi_value ret; 1588 napi_create_int32(env, ohResult.errorCode, &ret); 1589 return ret; 1590} 1591``` 1592 1593 1594### Key Derivation 1595 1596You are advised to pass in [HuksKeyStorageType](../reference/apis/js-apis-huks.md#hukskeystoragetype) to specify the storage type in key derivation. From API version 10, only **HUKS_STORAGE_ONLY_USED_IN_HUKS** or **HUKS_STORAGE_KEY_EXPORT_ALLOWED** can be used. If **HuksKeyStorageType** is not passed in, the key can be stored or exported by default, which poses security risks. 1597 1598**C++ Code Example** 1599 1600```C++ 1601#include "huks/native_huks_api.h" 1602#include "huks/native_huks_param.h" 1603#include <string.h> 1604OH_Huks_Result InitParamSet( 1605 struct OH_Huks_ParamSet **paramSet, 1606 const struct OH_Huks_Param *params, 1607 uint32_t paramCount) 1608{ 1609 OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet); 1610 if (ret.errorCode != OH_HUKS_SUCCESS) { 1611 return ret; 1612 } 1613 1614 ret = OH_Huks_AddParams(*paramSet, params, paramCount); 1615 if (ret.errorCode != OH_HUKS_SUCCESS) { 1616 OH_Huks_FreeParamSet(paramSet); 1617 return ret; 1618 } 1619 1620 ret = OH_Huks_BuildParamSet(paramSet); 1621 if (ret.errorCode != OH_HUKS_SUCCESS) { 1622 OH_Huks_FreeParamSet(paramSet); 1623 return ret; 1624 } 1625 1626 return ret; 1627} 1628 1629static const uint32_t DERIVE_KEY_SIZE_32 = 32; 1630static struct OH_Huks_Blob g_deriveKeyAlias = { 1631 (uint32_t)strlen("test_derive"), 1632 (uint8_t *)"test_derive" 1633}; 1634 1635static struct OH_Huks_Param g_genDeriveParams[] = { 1636 { 1637 .tag = OH_HUKS_TAG_ALGORITHM, 1638 .uint32Param = OH_HUKS_ALG_AES 1639 }, { 1640 .tag = OH_HUKS_TAG_PURPOSE, 1641 .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE 1642 }, { 1643 .tag = OH_HUKS_TAG_DIGEST, 1644 .uint32Param = OH_HUKS_DIGEST_SHA256 1645 }, { 1646 .tag = OH_HUKS_TAG_KEY_SIZE, 1647 .uint32Param = OH_HUKS_AES_KEY_SIZE_256 1648 } 1649}; 1650 1651static struct OH_Huks_Param g_hkdfParams[] = { 1652 { 1653 .tag = OH_HUKS_TAG_ALGORITHM, 1654 .uint32Param = OH_HUKS_ALG_HKDF 1655 }, { 1656 .tag = OH_HUKS_TAG_PURPOSE, 1657 .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE 1658 }, { 1659 .tag = OH_HUKS_TAG_DIGEST, 1660 .uint32Param = OH_HUKS_DIGEST_SHA256 1661 }, { 1662 .tag = OH_HUKS_TAG_DERIVE_KEY_SIZE, 1663 .uint32Param = DERIVE_KEY_SIZE_32 1664 } 1665}; 1666 1667static struct OH_Huks_Param g_hkdfFinishParams[] = { 1668 { 1669 .tag = OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 1670 .uint32Param = OH_HUKS_STORAGE_ONLY_USED_IN_HUKS 1671 }, { 1672 .tag = OH_HUKS_TAG_KEY_ALIAS, 1673 .blob = g_deriveKeyAlias 1674 }, { 1675 .tag = OH_HUKS_TAG_ALGORITHM, 1676 .uint32Param = OH_HUKS_ALG_HKDF 1677 }, { 1678 .tag = OH_HUKS_TAG_KEY_SIZE, 1679 .uint32Param = DERIVE_KEY_SIZE_32 1680 }, { 1681 .tag = OH_HUKS_TAG_PURPOSE, 1682 .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE 1683 }, { 1684 .tag = OH_HUKS_TAG_DIGEST, 1685 .uint32Param = OH_HUKS_DIGEST_SHA256 1686 } 1687}; 1688 1689static const uint32_t COMMON_SIZE = 2048; 1690static const char *g_deriveInData = "Hks_HKDF_Derive_Test_00000000000000000000000000000000000000000000000000000000000" 1691 "00000000000000000000000000000000000000000000000000000000000000000000000000000000" 1692 "0000000000000000000000000000000000000000000000000000000000000000000000000_string"; 1693 1694static napi_value DeriveKey(napi_env env, napi_callback_info info) 1695{ 1696 struct OH_Huks_Blob genAlias = { 1697 (uint32_t)strlen("test_signVerify"), 1698 (uint8_t *)"test_signVerify" 1699 }; 1700 struct OH_Huks_Blob inData = { 1701 (uint32_t)strlen(g_deriveInData), 1702 (uint8_t *)g_deriveInData 1703 }; 1704 struct OH_Huks_ParamSet *genParamSet = nullptr; 1705 struct OH_Huks_ParamSet *hkdfParamSet = nullptr; 1706 struct OH_Huks_ParamSet *hkdfFinishParamSet = nullptr; 1707 OH_Huks_Result ohResult; 1708 do { 1709 ohResult = InitParamSet(&genParamSet, g_genDeriveParams, sizeof(g_genDeriveParams) / sizeof(OH_Huks_Param)); 1710 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1711 break; 1712 } 1713 1714 ohResult = InitParamSet(&hkdfParamSet, g_hkdfParams, sizeof(g_hkdfParams) / sizeof(OH_Huks_Param)); 1715 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1716 break; 1717 } 1718 1719 // finish paramset 1720 ohResult = InitParamSet(&hkdfFinishParamSet, g_hkdfFinishParams, sizeof(g_hkdfFinishParams) / sizeof(OH_Huks_Param)); 1721 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1722 break; 1723 } 1724 1725 /* 1. Generate Key */ 1726 ohResult = OH_Huks_GenerateKeyItem(&genAlias, genParamSet, nullptr); 1727 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1728 break; 1729 } 1730 /* 2. Derive */ 1731 // Init 1732 uint8_t handleD[sizeof(uint64_t)] = {0}; 1733 struct OH_Huks_Blob handleDerive = { sizeof(uint64_t), handleD }; 1734 ohResult = OH_Huks_InitSession(&genAlias, hkdfParamSet, &handleDerive, nullptr); 1735 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1736 break; 1737 } 1738 // Update 1739 uint8_t tmpOut[COMMON_SIZE] = {0}; 1740 struct OH_Huks_Blob outData = { COMMON_SIZE, tmpOut }; 1741 ohResult = OH_Huks_UpdateSession(&handleDerive, hkdfParamSet, &inData, &outData); 1742 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1743 break; 1744 } 1745 // Finish 1746 uint8_t outDataD[COMMON_SIZE] = {0}; 1747 struct OH_Huks_Blob outDataDerive = { COMMON_SIZE, outDataD }; 1748 ohResult = OH_Huks_FinishSession(&handleDerive, hkdfFinishParamSet, &inData, &outDataDerive); 1749 } while (0); 1750 (void)OH_Huks_DeleteKeyItem(&genAlias, nullptr); 1751 (void)OH_Huks_DeleteKeyItem(&g_deriveKeyAlias, nullptr); 1752 OH_Huks_FreeParamSet(&genParamSet); 1753 OH_Huks_FreeParamSet(&hkdfParamSet); 1754 OH_Huks_FreeParamSet(&hkdfFinishParamSet); 1755 1756 napi_value ret; 1757 napi_create_int32(env, ohResult.errorCode, &ret); 1758 return ret; 1759} 1760``` 1761 1762### Key Attestation 1763 1764The HUKS provides attestation for the public keys of asymmetric key pairs. The HUKS can issue a certificate for the public key of an asymmetric key pair stored in the HUKS using the public key infrastructure (PKI) certificate chain technology. The certificate can prove the validity of the public key. The service can use the root CA certificate provided by the OpenHarmony to verify the key certificate issued by the HUKS level by level to ensure that the public key and private key in the certificate are from a trusted hardware device and stored in the HUKS. 1765 1766**How to Develop** 1767 17681. Pass in the key alias and the attribute tag of the key to be attested. 17692. Generate an X.509 certificate chain, which consists of the root CA certificate, device CA certificate, device certificate, and key certificate in sequence, for the application. 17703. Send the certificate chain to a trusted server. The server parses and verifies the validity of the certificate chain and whether a single certificate is revoked. 1771 1772**C++ Code Example** 1773 1774```C++ 1775#include "huks/native_huks_api.h" 1776#include "huks/native_huks_param.h" 1777#include <string.h> 1778 1779OH_Huks_Result InitParamSet( 1780 struct OH_Huks_ParamSet **paramSet, 1781 const struct OH_Huks_Param *params, 1782 uint32_t paramCount) 1783{ 1784 OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet); 1785 if (ret.errorCode != OH_HUKS_SUCCESS) { 1786 return ret; 1787 } 1788 1789 ret = OH_Huks_AddParams(*paramSet, params, paramCount); 1790 if (ret.errorCode != OH_HUKS_SUCCESS) { 1791 OH_Huks_FreeParamSet(paramSet); 1792 return ret; 1793 } 1794 1795 ret = OH_Huks_BuildParamSet(paramSet); 1796 if (ret.errorCode != OH_HUKS_SUCCESS) { 1797 OH_Huks_FreeParamSet(paramSet); 1798 return ret; 1799 } 1800 1801 return ret; 1802} 1803 1804static uint32_t g_size = 4096; 1805static uint32_t CERT_COUNT = 4; 1806 1807void FreeCertChain(struct OH_Huks_CertChain **certChain, const uint32_t pos) 1808{ 1809 if (certChain == nullptr || *certChain == nullptr) { 1810 return; 1811 } 1812 1813 if ((*certChain)->certs == nullptr) { 1814 free(*certChain); 1815 *certChain = nullptr; 1816 return; 1817 } 1818 for (uint32_t j = 0; j < pos; j++) { 1819 if ((*certChain)->certs[j].data != nullptr) { 1820 free((*certChain)->certs[j].data); 1821 (*certChain)->certs[j].data = nullptr; 1822 } 1823 } 1824 1825 if ((*certChain)->certs != nullptr) { 1826 free((*certChain)->certs); 1827 (*certChain)->certs = nullptr; 1828 } 1829 1830 if (*certChain != nullptr) { 1831 free(*certChain); 1832 *certChain = nullptr; 1833 } 1834} 1835 1836int32_t ConstructDataToCertChain(struct OH_Huks_CertChain **certChain) 1837{ 1838 *certChain = (struct OH_Huks_CertChain *)malloc(sizeof(struct OH_Huks_CertChain)); 1839 if (*certChain == nullptr) { 1840 return OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT; 1841 } 1842 (*certChain)->certsCount = CERT_COUNT; 1843 1844 (*certChain)->certs = (struct OH_Huks_Blob *)malloc(sizeof(struct OH_Huks_Blob) * ((*certChain)->certsCount)); 1845 if ((*certChain)->certs == nullptr) { 1846 free(*certChain); 1847 *certChain = nullptr; 1848 } 1849 for (uint32_t i = 0; i < (*certChain)->certsCount; i++) { 1850 (*certChain)->certs[i].size = g_size; 1851 (*certChain)->certs[i].data = (uint8_t *)malloc((*certChain)->certs[i].size); 1852 if ((*certChain)->certs[i].data == nullptr) { 1853 FreeCertChain(certChain, i); 1854 return OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT; 1855 } 1856 } 1857 return 0; 1858} 1859 1860static struct OH_Huks_Param g_genAttestParams[] = { 1861 { .tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_RSA }, 1862 { .tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_RSA_KEY_SIZE_2048 }, 1863 { .tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_VERIFY }, 1864 { .tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_SHA256 }, 1865 { .tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_PSS }, 1866 { .tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_ECB }, 1867}; 1868 1869#define CHALLENGE_DATA "hi_challenge_data" 1870static struct OH_Huks_Blob g_challenge = { sizeof(CHALLENGE_DATA), (uint8_t *)CHALLENGE_DATA }; 1871 1872static napi_value AttestKey(napi_env env, napi_callback_info info) 1873{ 1874 struct OH_Huks_Blob genAlias = { 1875 (uint32_t)strlen("test_attest"), 1876 (uint8_t *)"test_attest" 1877 }; 1878 static struct OH_Huks_Param g_attestParams[] = { 1879 { .tag = OH_HUKS_TAG_ATTESTATION_CHALLENGE, .blob = g_challenge }, 1880 { .tag = OH_HUKS_TAG_ATTESTATION_ID_ALIAS, .blob = genAlias }, 1881 }; 1882 struct OH_Huks_ParamSet *genParamSet = nullptr; 1883 struct OH_Huks_ParamSet *attestParamSet = nullptr; 1884 OH_Huks_Result ohResult; 1885 OH_Huks_CertChain *certChain = NULL; 1886 do { 1887 ohResult = InitParamSet(&genParamSet, g_genAttestParams, sizeof(g_genAttestParams) / sizeof(OH_Huks_Param)); 1888 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1889 break; 1890 } 1891 ohResult = InitParamSet(&attestParamSet, g_attestParams, sizeof(g_attestParams) / sizeof(OH_Huks_Param)); 1892 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1893 break; 1894 } 1895 ohResult = OH_Huks_GenerateKeyItem(&genAlias, genParamSet, nullptr); 1896 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 1897 break; 1898 } 1899 1900 (void)ConstructDataToCertChain(&certChain); 1901 ohResult = OH_Huks_AttestKeyItem(&genAlias, attestParamSet, certChain); 1902 } while (0); 1903 if (certChain != nullptr) { 1904 FreeCertChain(&certChain, certChain->certsCount); 1905 } 1906 OH_Huks_FreeParamSet(&genParamSet); 1907 OH_Huks_FreeParamSet(&attestParamSet); 1908 (void)OH_Huks_DeleteKeyItem(&genAlias, NULL); 1909 1910 napi_value ret; 1911 napi_create_int32(env, ohResult.errorCode, &ret); 1912 return ret; 1913} 1914``` 1915