• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Key Agreement (C/C++)
2
3
4This topic walks you through on how to agree on an ECDH key that is used only in HUKS. For details about the scenarios and supported algorithms, see [Supported Algorithms](huks-key-generation-overview.md#supported-algorithms).
5
6
7## How to Develop
8
9**Key Generation**
10
11Generate an asymmetric key for device A and device B each. For details, see [Key Generation](huks-key-generation-overview.md) or [Key Import](huks-key-import-overview.md).
12
13The optional parameter **OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG** specifies how a derived key or a key generated after key agreement is stored.
14
15- **OH_HUKS_STORAGE_ONLY_USED_IN_HUKS**: The key is stored and managed by HUKS.
16
17- **OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED** (default): The key is directly exported to the service and not managed by HUKS.
18
19**Key Export**
20
21Export the public key of the asymmetric key pair of device A and device B. For details, see [Key Export](huks-export-key-arkts.md).
22
23**Key Agreement**
24
25Perform key agreement using the public key of the peer device and private key of the local device (that is, public key of device B and private key of device A for device A, and public key of device A and private key of device B for device B) to produce a shared secrete key.
26
27**Key Deletion**
28
29Delete the keys from device A and device B when the keys are not required. For details, see [Deleting a Key](huks-delete-key-ndk.md).
30
31```c++
32#include "huks/native_huks_api.h"
33#include "huks/native_huks_param.h"
34#include <string.h>
35/* Initialize parameters. */
36OH_Huks_Result InitParamSet(
37    struct OH_Huks_ParamSet **paramSet,
38    const struct OH_Huks_Param *params,
39    uint32_t paramCount)
40{
41    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
42    if (ret.errorCode != OH_HUKS_SUCCESS) {
43        return ret;
44    }
45    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
46    if (ret.errorCode != OH_HUKS_SUCCESS) {
47        OH_Huks_FreeParamSet(paramSet);
48        return ret;
49    }
50    ret = OH_Huks_BuildParamSet(paramSet);
51    if (ret.errorCode != OH_HUKS_SUCCESS) {
52        OH_Huks_FreeParamSet(paramSet);
53        return ret;
54    }
55    return ret;
56}
57static const uint32_t IV_SIZE = 16;
58static uint8_t IV[IV_SIZE] = { 0 }; // this is a test value, for real use the iv should be different every time
59static struct OH_Huks_Blob g_keyAliasFinal1001 = {
60    (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_1_final"),
61    (uint8_t *)"HksECDHAgreeKeyAliasTest001_1_final"
62};
63/* Set the key parameter set. */
64static struct OH_Huks_Param g_genAgreeParams[] = {
65    {
66        .tag = OH_HUKS_TAG_ALGORITHM,
67        .uint32Param = OH_HUKS_ALG_ECC
68    }, {
69        .tag = OH_HUKS_TAG_PURPOSE,
70        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
71    }, {
72        .tag = OH_HUKS_TAG_KEY_SIZE,
73        .uint32Param = OH_HUKS_ECC_KEY_SIZE_256
74    }, {
75        .tag = OH_HUKS_TAG_DIGEST,
76        .uint32Param = OH_HUKS_DIGEST_NONE
77    }
78};
79static struct OH_Huks_Param g_agreeParamsInit01[] = {
80    {
81        .tag = OH_HUKS_TAG_ALGORITHM,
82        .uint32Param = OH_HUKS_ALG_ECDH
83    }, {
84        .tag = OH_HUKS_TAG_PURPOSE,
85        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
86    }, {
87        .tag = OH_HUKS_TAG_KEY_SIZE,
88        .uint32Param = OH_HUKS_ECC_KEY_SIZE_256
89    }
90};
91static struct OH_Huks_Param g_agreeParamsFinish01[] = {
92    {
93        .tag = OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
94        .uint32Param = OH_HUKS_STORAGE_ONLY_USED_IN_HUKS
95    }, {
96        .tag = OH_HUKS_TAG_ALGORITHM,
97        .uint32Param = OH_HUKS_ALG_AES
98    }, {
99        .tag = OH_HUKS_TAG_KEY_SIZE,
100        .uint32Param = OH_HUKS_AES_KEY_SIZE_256
101    }, {
102        .tag = OH_HUKS_TAG_PURPOSE,
103        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
104    }, {
105        .tag = OH_HUKS_TAG_KEY_ALIAS,
106        .blob = g_keyAliasFinal1001
107    }, {
108        .tag = OH_HUKS_TAG_PADDING,
109        .uint32Param = OH_HUKS_PADDING_NONE
110    }, {
111        .tag = OH_HUKS_TAG_BLOCK_MODE,
112        .uint32Param = OH_HUKS_MODE_CBC
113    }
114};
115static struct OH_Huks_Blob g_keyAliasFinal2001 = {
116    (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_2_final"),
117    (uint8_t *)"HksECDHAgreeKeyAliasTest001_2_final"
118};
119static struct OH_Huks_Param g_agreeParamsInit02[] = {
120    {
121        .tag = OH_HUKS_TAG_ALGORITHM,
122        .uint32Param = OH_HUKS_ALG_ECDH
123    }, {
124        .tag = OH_HUKS_TAG_PURPOSE,
125        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
126    }, {
127        .tag = OH_HUKS_TAG_KEY_SIZE,
128        .uint32Param = OH_HUKS_ECC_KEY_SIZE_256
129    }
130};
131static struct OH_Huks_Param g_agreeParamsFinish02[] = {
132    {
133        .tag = OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
134        .uint32Param = OH_HUKS_STORAGE_ONLY_USED_IN_HUKS
135    }, {
136        .tag = OH_HUKS_TAG_ALGORITHM,
137        .uint32Param = OH_HUKS_ALG_AES
138    }, {
139        .tag = OH_HUKS_TAG_KEY_SIZE,
140        .uint32Param = OH_HUKS_AES_KEY_SIZE_256
141    }, {
142        .tag = OH_HUKS_TAG_PURPOSE,
143        .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE
144    }, {
145        .tag = OH_HUKS_TAG_KEY_ALIAS,
146        .blob = g_keyAliasFinal2001
147    }, {
148        .tag = OH_HUKS_TAG_PADDING,
149        .uint32Param = OH_HUKS_PADDING_NONE
150    }, {
151        .tag = OH_HUKS_TAG_BLOCK_MODE,
152        .uint32Param = OH_HUKS_MODE_CBC
153    }
154};
155static const uint32_t ECDH_COMMON_SIZE = 1024;
156static struct OH_Huks_Blob g_keyAlias01001 = {
157    (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_1"),
158    (uint8_t *)"HksECDHAgreeKeyAliasTest001_1"
159};
160static struct OH_Huks_Blob g_keyAlias02001 = {
161    (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_2"),
162    (uint8_t *)"HksECDHAgreeKeyAliasTest001_2"
163};
164OH_Huks_Result MallocAndCheckBlobData(
165    struct OH_Huks_Blob *blob,
166    const uint32_t blobSize)
167{
168    struct OH_Huks_Result ret;
169    ret.errorCode = OH_HUKS_SUCCESS;
170    blob->data = (uint8_t *)malloc(blobSize);
171    if (blob->data == NULL) {
172        ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
173    }
174    return ret;
175}
176/* Export a key. */
177OH_Huks_Result HksEcdhAgreeExport(const struct OH_Huks_Blob *keyAlias1, const struct OH_Huks_Blob *keyAlias2,
178    struct OH_Huks_Blob *publicKey1, struct OH_Huks_Blob *publicKey2, const struct OH_Huks_ParamSet *genParamSet)
179{
180    OH_Huks_Result ret = OH_Huks_ExportPublicKeyItem(keyAlias1, genParamSet, publicKey1);
181    if (ret.errorCode != OH_HUKS_SUCCESS) {
182        return ret;
183    }
184    ret = OH_Huks_ExportPublicKeyItem(keyAlias2, genParamSet, publicKey2);
185    if (ret.errorCode != OH_HUKS_SUCCESS) {
186        return ret;
187    }
188    return ret;
189}
190static const char *g_inData = "Hks_ECDH_Agree_Test_000000000000000000000000000000000000000000000000000000000000"
191                                    "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
192                                    "0000000000000000000000000000000000000000000000000000000000000000000000000_string";
193/* Perform key agreement. */
194OH_Huks_Result HksEcdhAgreeFinish(const struct OH_Huks_Blob *keyAlias, const struct OH_Huks_Blob *publicKey,
195    const struct OH_Huks_ParamSet *initParamSet, const struct OH_Huks_ParamSet *finishParamSet, struct OH_Huks_Blob *outData)
196{
197    struct OH_Huks_Blob inData = {
198        (uint32_t)strlen(g_inData),
199        (uint8_t *)g_inData
200    };
201    uint8_t handleU[sizeof(uint64_t)] = {0};
202    struct OH_Huks_Blob handle = { sizeof(uint64_t), handleU };
203    OH_Huks_Result ret = OH_Huks_InitSession(keyAlias, initParamSet, &handle, nullptr);
204    if (ret.errorCode != OH_HUKS_SUCCESS) {
205        return ret;
206    }
207    uint8_t outDataU[ECDH_COMMON_SIZE] = {0};
208    struct OH_Huks_Blob outDataUpdate = { ECDH_COMMON_SIZE, outDataU };
209    ret = OH_Huks_UpdateSession(&handle, initParamSet, publicKey, &outDataUpdate);
210    if (ret.errorCode != OH_HUKS_SUCCESS) {
211        return ret;
212    }
213    ret = OH_Huks_FinishSession(&handle, finishParamSet, &inData, outData);
214    if (ret.errorCode != OH_HUKS_SUCCESS) {
215        return ret;
216    }
217    return ret;
218}
219/* Key agreement process. */
220static napi_value AgreeKey(napi_env env, napi_callback_info info)
221{
222    struct OH_Huks_ParamSet *genParamSet = nullptr;
223    struct OH_Huks_ParamSet *initParamSet01 = nullptr;
224    struct OH_Huks_ParamSet *finishParamSet01 = nullptr;
225    struct OH_Huks_ParamSet *initParamSet02 = nullptr;
226    struct OH_Huks_ParamSet *finishParamSet02 = nullptr;
227    struct OH_Huks_Blob publicKey01 = { .size = OH_HUKS_ECC_KEY_SIZE_256, .data = nullptr };
228    struct OH_Huks_Blob publicKey02 = { .size = OH_HUKS_ECC_KEY_SIZE_256, .data = nullptr };
229    struct OH_Huks_Blob outData01 = { .size = ECDH_COMMON_SIZE, .data = nullptr };
230    struct OH_Huks_Blob outData02 = { .size = ECDH_COMMON_SIZE, .data = nullptr };
231    OH_Huks_Result ohResult;
232    do {
233        /* 1. Set the key alias and key parameter set. */
234        ohResult = InitParamSet(&genParamSet, g_genAgreeParams, sizeof(g_genAgreeParams) / sizeof(OH_Huks_Param));
235        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
236            break;
237        }
238        ohResult = InitParamSet(&initParamSet01, g_agreeParamsInit01, sizeof(g_agreeParamsInit01) / sizeof(OH_Huks_Param));
239        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
240            break;
241        }
242        ohResult = InitParamSet(&finishParamSet01, g_agreeParamsFinish01,
243            sizeof(g_agreeParamsFinish01) / sizeof(OH_Huks_Param));
244        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
245            break;
246        }
247        ohResult = InitParamSet(&initParamSet02, g_agreeParamsInit02, sizeof(g_agreeParamsInit02) / sizeof(OH_Huks_Param));
248        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
249            break;
250        }
251        ohResult = InitParamSet(&finishParamSet02, g_agreeParamsFinish02,
252            sizeof(g_agreeParamsFinish02) / sizeof(OH_Huks_Param));
253        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
254            break;
255        }
256        /* 2. Generate an asymmetric key pair for device A. */
257        ohResult = OH_Huks_GenerateKeyItem(&g_keyAlias01001, genParamSet, nullptr);
258        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
259            break;
260        }
261        /* 3. Generate an asymmetric key pair for device B. */
262        ohResult = OH_Huks_GenerateKeyItem(&g_keyAlias02001, genParamSet, nullptr);
263        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
264            break;
265        }
266        ohResult = MallocAndCheckBlobData(&publicKey01, publicKey01.size);
267        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
268            break;
269        }
270        ohResult = MallocAndCheckBlobData(&publicKey02, publicKey02.size);
271        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
272            break;
273        }
274        /* 4. Export the public key from device A and device B separately. */
275        ohResult = HksEcdhAgreeExport(&g_keyAlias01001, &g_keyAlias02001, &publicKey01, &publicKey02, genParamSet);
276        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
277            break;
278        }
279        ohResult = MallocAndCheckBlobData(&outData01, outData01.size);
280        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
281            break;
282        }
283        ohResult = MallocAndCheckBlobData(&outData02, outData02.size);
284        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
285            break;
286        }
287        /* 5. Perform key agreement for device A. */
288        ohResult = HksEcdhAgreeFinish(&g_keyAlias01001, &publicKey02, initParamSet01, finishParamSet01, &outData01);
289        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
290            break;
291        }
292        /* 5. Perform key agreement for device B. */
293        ohResult = HksEcdhAgreeFinish(&g_keyAlias02001, &publicKey01, initParamSet02, finishParamSet02, &outData02);
294    } while (0);
295    free(publicKey01.data);
296    free(publicKey02.data);
297    free(outData01.data);
298    free(outData02.data);
299    /* 6. Delete keys from device A and device B. */
300    OH_Huks_DeleteKeyItem(&g_keyAlias01001, genParamSet);
301    OH_Huks_DeleteKeyItem(&g_keyAlias02001, genParamSet);
302    OH_Huks_DeleteKeyItem(&g_keyAliasFinal1001, NULL);
303    OH_Huks_DeleteKeyItem(&g_keyAliasFinal2001, NULL);
304    OH_Huks_FreeParamSet(&genParamSet);
305    OH_Huks_FreeParamSet(&initParamSet01);
306    OH_Huks_FreeParamSet(&finishParamSet01);
307    OH_Huks_FreeParamSet(&initParamSet02);
308    OH_Huks_FreeParamSet(&finishParamSet02);
309
310    napi_value ret;
311    napi_create_int32(env, ohResult.errorCode, &ret);
312    return ret;
313}
314```
315