• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Key Derivation (C/C++)
2
3<!--Kit: Universal Keystore Kit-->
4<!--Subsystem: Security-->
5<!--Owner: @wutiantian-gitee-->
6<!--Designer: @HighLowWorld-->
7<!--Tester: @wxy1234564846-->
8<!--Adviser: @zengyawen-->
9
10This topic walks you through on how to derive a 256-bit key using HKDF. For details about the scenarios and supported algorithms, see [Supported Algorithms](huks-key-generation-overview.md#supported-algorithms).
11
12## Add the dynamic library in the CMake script.
13```txt
14target_link_libraries(entry PUBLIC libhuks_ndk.z.so)
15```
16
17## How to Develop
18
19**Key Generation**
20
211. Specify the key alias. For details about the naming rules, see [Key Generation Overview and Algorithm Specifications](huks-key-generation-overview.md).
22
232. Initialize the key property set. You can set **OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG** (optional) to specify how the key derived from this key is managed.
24
25    - If this tag is set to **OH_HUKS_STORAGE_ONLY_USED_IN_HUKS**, the derived key is managed by HUKS. That is, the derived key is always in a secure environment throughout its lifecycle.
26
27    - If this tag is set to **OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED**, the derived key will be returned to the caller for management. That is, the service side ensures the key security.
28
29    - If this tag is not set, the derived key can be either managed by HUKS or returned to the caller for management. The key protection mode can be set in the subsequent key derivation on the service side.
30
313. Use [OH_Huks_GenerateKeyItem](../../reference/apis-universal-keystore-kit/capi-native-huks-api-h.md#oh_huks_generatekeyitem) to generate a key. For details, see [Key Generation Overview and Algorithm Specifications](huks-key-generation-overview.md).
32
33Alternatively, you can [import a key](huks-key-import-overview.md).
34
35**Key Derivation**
36
371. Obtain the key alias and set the **HuksOptions** parameter.
38
39   You can set **OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG** to specify how the derived key is managed.
40
41    | Key Generation| Key Derivation| Specifications|
42    | -------- | -------- | -------- |
43    | OH_HUKS_STORAGE_ONLY_USED_IN_HUKS | OH_HUKS_STORAGE_ONLY_USED_IN_HUKS | The key is managed by HUKS.|
44    | OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED | OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED | The key is returned to the caller for management.|
45    | The tag is not set.| OH_HUKS_STORAGE_ONLY_USED_IN_HUKS | The key is managed by HUKS.|
46    | The tag is not set.| OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED | The key is returned to the caller for management.|
47    | The tag is not set.| The tag is not set.| The key is returned to the caller for management.|
48
49    Note: The tag value set in key derivation should not conflict with the tag value set in key generation. The above table lists only valid settings.
50
512. Use [OH_Huks_InitSession](../../reference/apis-universal-keystore-kit/capi-native-huks-api-h.md#oh_huks_initsession) to initialize a key session and obtain the session handle.
52
533. Use [OH_Huks_UpdateSession](../../reference/apis-universal-keystore-kit/capi-native-huks-api-h.md#oh_huks_updatesession) to update the key session.
54
554. Use [OH_Huks_FinishSession](../../reference/apis-universal-keystore-kit/capi-native-huks-api-h.md#oh_huks_finishsession) to end the key session and finish derivation.
56
57**Key Deletion**
58
59Use **OH_Huks_DeleteKeyItem** to delete the key that is not required. For details, see [Deleting a Key](huks-delete-key-ndk.md).
60
61```c++
62#include "huks/native_huks_api.h"
63#include "huks/native_huks_param.h"
64#include "napi/native_api.h"
65#include <string.h>
66OH_Huks_Result InitParamSet(
67    struct OH_Huks_ParamSet **paramSet,
68    const struct OH_Huks_Param *params,
69    uint32_t paramCount)
70{
71    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
72    if (ret.errorCode != OH_HUKS_SUCCESS) {
73        return ret;
74    }
75    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
76    if (ret.errorCode != OH_HUKS_SUCCESS) {
77        OH_Huks_FreeParamSet(paramSet);
78        return ret;
79    }
80    ret = OH_Huks_BuildParamSet(paramSet);
81    if (ret.errorCode != OH_HUKS_SUCCESS) {
82        OH_Huks_FreeParamSet(paramSet);
83        return ret;
84    }
85    return ret;
86}
87static const uint32_t DERIVE_KEY_SIZE_32 = 32;
88static const uint32_t DERIVE_KEY_SIZE_256 = 256;
89static struct OH_Huks_Blob g_deriveKeyAlias = {
90    (uint32_t)strlen("test_derive"),
91    (uint8_t *)"test_derive"
92};
93static struct OH_Huks_Param g_genDeriveParams[] = {
94    {
95        .tag =  OH_HUKS_TAG_ALGORITHM,
96        .uint32Param = OH_HUKS_ALG_AES
97    }, {
98        .tag =  OH_HUKS_TAG_PURPOSE,
99        .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE
100    }, {
101        .tag =  OH_HUKS_TAG_DIGEST,
102        .uint32Param = OH_HUKS_DIGEST_SHA256
103    }, {
104        .tag =  OH_HUKS_TAG_KEY_SIZE,
105        .uint32Param = OH_HUKS_AES_KEY_SIZE_256
106    }
107};
108static struct OH_Huks_Param g_hkdfParams[] = {
109    {
110        .tag =  OH_HUKS_TAG_ALGORITHM,
111        .uint32Param = OH_HUKS_ALG_HKDF
112    }, {
113        .tag =  OH_HUKS_TAG_PURPOSE,
114        .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE
115    }, {
116        .tag =  OH_HUKS_TAG_DIGEST,
117        .uint32Param = OH_HUKS_DIGEST_SHA256
118    }, {
119        .tag =  OH_HUKS_TAG_DERIVE_KEY_SIZE,
120        .uint32Param = DERIVE_KEY_SIZE_32
121    }
122};
123static struct OH_Huks_Param g_hkdfFinishParams[] = {
124    {
125        .tag =  OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
126        .uint32Param = OH_HUKS_STORAGE_ONLY_USED_IN_HUKS
127    }, {
128        .tag =  OH_HUKS_TAG_KEY_ALIAS,
129        .blob = g_deriveKeyAlias
130    }, {
131        .tag =  OH_HUKS_TAG_ALGORITHM,
132        .uint32Param = OH_HUKS_ALG_AES
133    }, {
134        .tag =  OH_HUKS_TAG_KEY_SIZE,
135        .uint32Param = DERIVE_KEY_SIZE_256
136    }, {
137        .tag =  OH_HUKS_TAG_PURPOSE,
138        .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE
139    }, {
140        .tag =  OH_HUKS_TAG_DIGEST,
141        .uint32Param = OH_HUKS_DIGEST_SHA256
142    }
143};
144static const uint32_t COMMON_SIZE = 2048;
145static const char *g_deriveInData = "Hks_HKDF_Derive_Test_00000000000000000000000000000000000000000000000000000000000"
146                                    "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
147                                    "0000000000000000000000000000000000000000000000000000000000000000000000000_string";
148static napi_value DeriveKey(napi_env env, napi_callback_info info)
149{
150    struct OH_Huks_Blob genAlias = {
151        (uint32_t)strlen("test_signVerify"),
152        (uint8_t *)"test_signVerify"
153    };
154    struct OH_Huks_Blob inData = {
155        (uint32_t)strlen(g_deriveInData),
156        (uint8_t *)g_deriveInData
157    };
158    struct OH_Huks_ParamSet *genParamSet = nullptr;
159    struct OH_Huks_ParamSet *hkdfParamSet = nullptr;
160    struct OH_Huks_ParamSet *hkdfFinishParamSet = nullptr;
161    OH_Huks_Result ohResult;
162    do {
163        ohResult = InitParamSet(&genParamSet, g_genDeriveParams, sizeof(g_genDeriveParams) / sizeof(OH_Huks_Param));
164        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
165            break;
166        }
167
168        ohResult = InitParamSet(&hkdfParamSet, g_hkdfParams, sizeof(g_hkdfParams) / sizeof(OH_Huks_Param));
169        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
170           break;
171        }
172
173        // finish paramset
174        ohResult = InitParamSet(&hkdfFinishParamSet, g_hkdfFinishParams, sizeof(g_hkdfFinishParams) / sizeof(OH_Huks_Param));
175        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
176            break;
177        }
178
179        /* 1. Generate Key */
180        ohResult = OH_Huks_GenerateKeyItem(&genAlias, genParamSet, nullptr);
181        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
182            break;
183        }
184        /* 2. Derive */
185        // Init
186        uint8_t handleD[sizeof(uint64_t)] = {0};
187        struct OH_Huks_Blob handleDerive = { sizeof(uint64_t), handleD };
188        ohResult = OH_Huks_InitSession(&genAlias, hkdfParamSet, &handleDerive, nullptr);
189        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
190            break;
191        }
192        // Update
193        uint8_t tmpOut[COMMON_SIZE] = {0};
194        struct OH_Huks_Blob outData = { COMMON_SIZE, tmpOut };
195        ohResult = OH_Huks_UpdateSession(&handleDerive, hkdfParamSet, &inData, &outData);
196        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
197            break;
198        }
199        // Finish
200        uint8_t outDataD[COMMON_SIZE] = {0};
201        struct OH_Huks_Blob outDataDerive = { COMMON_SIZE, outDataD };
202        ohResult = OH_Huks_FinishSession(&handleDerive, hkdfFinishParamSet, &inData, &outDataDerive);
203    } while (0);
204    (void)OH_Huks_DeleteKeyItem(&genAlias, nullptr);
205    (void)OH_Huks_DeleteKeyItem(&g_deriveKeyAlias, nullptr);
206    OH_Huks_FreeParamSet(&genParamSet);
207    OH_Huks_FreeParamSet(&hkdfParamSet);
208    OH_Huks_FreeParamSet(&hkdfFinishParamSet);
209
210    napi_value ret;
211    napi_create_int32(env, ohResult.errorCode, &ret);
212    return ret;
213}
214```
215