1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "crypto_kdf.h"
17 #include <stdlib.h>
18 #include <string.h>
19 #include <securec.h>
20 #include "crypto_common.h"
21 #include "native_common.h"
22 #include "memory.h"
23 #include "kdf.h"
24 #include "kdf_params.h"
25 #include "detailed_hkdf_params.h"
26 #include "detailed_pbkdf2_params.h"
27 #include "detailed_scrypt_params.h"
28
29 typedef struct OH_CryptoKdf {
30 HcfObjectBase base;
31
32 const char *(*getAlgorithm)(HcfKdf *self);
33
34 HcfResult (*generateSecret)(HcfKdf *self, HcfKdfParamsSpec* paramsSpec);
35 } OH_CryptoKdf;
36
37
38 typedef struct OH_CryptoKdfParams {
39 const char *algName;
40 } OH_CryptoKdfParams;
41
42 static const char *g_hkdfName = "HKDF";
43 static const char *g_pbkdf2Name = "PBKDF2";
44 static const char *g_scryptName = "SCRYPT";
45
OH_CryptoKdfParams_Create(const char * algoName,OH_CryptoKdfParams ** params)46 OH_Crypto_ErrCode OH_CryptoKdfParams_Create(const char *algoName, OH_CryptoKdfParams **params)
47 {
48 if ((algoName == NULL) || (params == NULL)) {
49 return CRYPTO_PARAMETER_CHECK_FAILED;
50 }
51
52 OH_CryptoKdfParams *tmParams = NULL;
53 const char *algName = NULL;
54 if (strcmp(algoName, g_hkdfName) == 0) {
55 tmParams = (OH_CryptoKdfParams *)HcfMalloc(sizeof(HcfHkdfParamsSpec), 0);
56 algName = g_hkdfName;
57 } else if (strcmp(algoName, g_pbkdf2Name) == 0) {
58 tmParams = (OH_CryptoKdfParams *)HcfMalloc(sizeof(HcfPBKDF2ParamsSpec), 0);
59 algName = g_pbkdf2Name;
60 } else if (strcmp(algoName, g_scryptName) == 0) {
61 tmParams = (OH_CryptoKdfParams *)HcfMalloc(sizeof(HcfScryptParamsSpec), 0);
62 algName = g_scryptName;
63 } else {
64 return CRYPTO_PARAMETER_CHECK_FAILED;
65 }
66 if (tmParams == NULL) {
67 return CRYPTO_MEMORY_ERROR;
68 }
69 tmParams->algName = algName;
70 *params = tmParams;
71 return CRYPTO_SUCCESS;
72 }
73
SetHkdfParam(HcfHkdfParamsSpec * params,CryptoKdf_ParamType type,Crypto_DataBlob * value)74 static OH_Crypto_ErrCode SetHkdfParam(HcfHkdfParamsSpec *params, CryptoKdf_ParamType type, Crypto_DataBlob *value)
75 {
76 uint8_t *data = (uint8_t *)HcfMalloc(value->len, 0);
77 if (data == NULL) {
78 return CRYPTO_MEMORY_ERROR;
79 }
80 (void)memcpy_s(data, value->len, value->data, value->len);
81 switch (type) {
82 case CRYPTO_KDF_KEY_DATABLOB:
83 HcfBlobDataClearAndFree(&(params->key));
84 params->key.data = data;
85 params->key.len = value->len;
86 break;
87 case CRYPTO_KDF_SALT_DATABLOB:
88 HcfBlobDataClearAndFree(&(params->salt));
89 params->salt.data = data;
90 params->salt.len = value->len;
91 break;
92 case CRYPTO_KDF_INFO_DATABLOB:
93 HcfBlobDataClearAndFree(&(params->info));
94 params->info.data = data;
95 params->info.len = value->len;
96 break;
97 default:
98 HcfFree(data);
99 data = NULL;
100 return CRYPTO_PARAMETER_CHECK_FAILED;
101 }
102 return CRYPTO_SUCCESS;
103 }
104
SetPbkdf2Param(HcfPBKDF2ParamsSpec * params,CryptoKdf_ParamType type,Crypto_DataBlob * value)105 static OH_Crypto_ErrCode SetPbkdf2Param(HcfPBKDF2ParamsSpec *params, CryptoKdf_ParamType type, Crypto_DataBlob *value)
106 {
107 switch (type) {
108 case CRYPTO_KDF_KEY_DATABLOB: {
109 uint8_t *data = (uint8_t *)HcfMalloc(value->len, 0);
110 if (data == NULL) {
111 return CRYPTO_MEMORY_ERROR;
112 }
113 (void)memcpy_s(data, value->len, value->data, value->len);
114 HcfBlobDataClearAndFree(&(params->password));
115 params->password.data = data;
116 params->password.len = value->len;
117 break;
118 }
119 case CRYPTO_KDF_SALT_DATABLOB: {
120 uint8_t *data = (uint8_t *)HcfMalloc(value->len, 0);
121 if (data == NULL) {
122 return CRYPTO_MEMORY_ERROR;
123 }
124 (void)memcpy_s(data, value->len, value->data, value->len);
125 HcfBlobDataClearAndFree(&(params->salt));
126 params->salt.data = data;
127 params->salt.len = value->len;
128 break;
129 }
130 case CRYPTO_KDF_ITER_COUNT_INT: {
131 if (value->len != sizeof(int)) {
132 return CRYPTO_PARAMETER_CHECK_FAILED;
133 }
134 params->iterations = *(int *)(value->data);
135 break;
136 }
137 default:
138 return CRYPTO_PARAMETER_CHECK_FAILED;
139 }
140 return CRYPTO_SUCCESS;
141 }
142
SetScryptKeyParam(HcfScryptParamsSpec * params,Crypto_DataBlob * value)143 static OH_Crypto_ErrCode SetScryptKeyParam(HcfScryptParamsSpec *params, Crypto_DataBlob *value)
144 {
145 uint8_t *data = (uint8_t *)HcfMalloc(value->len, 0);
146 if (data == NULL) {
147 return CRYPTO_MEMORY_ERROR;
148 }
149 (void)memcpy_s(data, value->len, value->data, value->len);
150 HcfBlobDataClearAndFree(&(params->passPhrase));
151 params->passPhrase.data = data;
152 params->passPhrase.len = value->len;
153 return CRYPTO_SUCCESS;
154 }
155
SetScryptSaltParam(HcfScryptParamsSpec * params,Crypto_DataBlob * value)156 static OH_Crypto_ErrCode SetScryptSaltParam(HcfScryptParamsSpec *params, Crypto_DataBlob *value)
157 {
158 uint8_t *data = (uint8_t *)HcfMalloc(value->len, 0);
159 if (data == NULL) {
160 return CRYPTO_MEMORY_ERROR;
161 }
162 (void)memcpy_s(data, value->len, value->data, value->len);
163 HcfBlobDataClearAndFree(&(params->salt));
164 params->salt.data = data;
165 params->salt.len = value->len;
166 return CRYPTO_SUCCESS;
167 }
168
SetScryptUint64Param(HcfScryptParamsSpec * params,Crypto_DataBlob * value,uint64_t * target)169 static OH_Crypto_ErrCode SetScryptUint64Param(HcfScryptParamsSpec *params, Crypto_DataBlob *value, uint64_t *target)
170 {
171 if (value->len != sizeof(uint64_t)) {
172 return CRYPTO_PARAMETER_CHECK_FAILED;
173 }
174 *target = *(uint64_t *)(value->data);
175 return CRYPTO_SUCCESS;
176 }
177
SetScryptParam(HcfScryptParamsSpec * params,CryptoKdf_ParamType type,Crypto_DataBlob * value)178 static OH_Crypto_ErrCode SetScryptParam(HcfScryptParamsSpec *params, CryptoKdf_ParamType type, Crypto_DataBlob *value)
179 {
180 switch (type) {
181 case CRYPTO_KDF_KEY_DATABLOB:
182 return SetScryptKeyParam(params, value);
183 case CRYPTO_KDF_SALT_DATABLOB:
184 return SetScryptSaltParam(params, value);
185 case CRYPTO_KDF_SCRYPT_N_UINT64:
186 return SetScryptUint64Param(params, value, ¶ms->n);
187 case CRYPTO_KDF_SCRYPT_R_UINT64:
188 return SetScryptUint64Param(params, value, ¶ms->r);
189 case CRYPTO_KDF_SCRYPT_P_UINT64:
190 return SetScryptUint64Param(params, value, ¶ms->p);
191 case CRYPTO_KDF_SCRYPT_MAX_MEM_UINT64:
192 return SetScryptUint64Param(params, value, ¶ms->maxMem);
193 default:
194 return CRYPTO_PARAMETER_CHECK_FAILED;
195 }
196 }
197
OH_CryptoKdfParams_SetParam(OH_CryptoKdfParams * params,CryptoKdf_ParamType type,Crypto_DataBlob * value)198 OH_Crypto_ErrCode OH_CryptoKdfParams_SetParam(OH_CryptoKdfParams *params, CryptoKdf_ParamType type,
199 Crypto_DataBlob *value)
200 {
201 if ((params == NULL) || (params->algName == NULL) || (value == NULL) || (value->data == NULL)) {
202 return CRYPTO_PARAMETER_CHECK_FAILED;
203 }
204 if (strcmp(params->algName, g_hkdfName) == 0) {
205 return SetHkdfParam((HcfHkdfParamsSpec*)params, type, value);
206 } else if (strcmp(params->algName, g_pbkdf2Name) == 0) {
207 return SetPbkdf2Param((HcfPBKDF2ParamsSpec*)params, type, value);
208 } else if (strcmp(params->algName, g_scryptName) == 0) {
209 return SetScryptParam((HcfScryptParamsSpec*)params, type, value);
210 } else {
211 return CRYPTO_PARAMETER_CHECK_FAILED;
212 }
213 }
214
FreeHkdfParamSpec(HcfHkdfParamsSpec * params)215 static void FreeHkdfParamSpec(HcfHkdfParamsSpec *params)
216 {
217 HcfBlobDataClearAndFree(&(params->key));
218 HcfBlobDataClearAndFree(&(params->salt));
219 HcfBlobDataClearAndFree(&(params->info));
220 HcfBlobDataClearAndFree(&(params->output));
221 }
222
FreePbkdf2ParamSpec(HcfPBKDF2ParamsSpec * params)223 static void FreePbkdf2ParamSpec(HcfPBKDF2ParamsSpec *params)
224 {
225 HcfBlobDataClearAndFree(&(params->password));
226 HcfBlobDataClearAndFree(&(params->salt));
227 HcfBlobDataClearAndFree(&(params->output));
228 }
229
FreeScryptParamSpec(HcfScryptParamsSpec * params)230 static void FreeScryptParamSpec(HcfScryptParamsSpec *params)
231 {
232 HcfBlobDataClearAndFree(&(params->passPhrase));
233 HcfBlobDataClearAndFree(&(params->salt));
234 HcfBlobDataClearAndFree(&(params->output));
235 }
236
FreeParamSpec(OH_CryptoKdfParams * params)237 static void FreeParamSpec(OH_CryptoKdfParams *params)
238 {
239 if (params->algName == NULL) {
240 return;
241 }
242 if (strcmp(params->algName, g_hkdfName) == 0) {
243 FreeHkdfParamSpec((HcfHkdfParamsSpec*)params);
244 } else if (strcmp(params->algName, g_pbkdf2Name) == 0) {
245 FreePbkdf2ParamSpec((HcfPBKDF2ParamsSpec*)params);
246 } else if (strcmp(params->algName, g_scryptName) == 0) {
247 FreeScryptParamSpec((HcfScryptParamsSpec*)params);
248 }
249 }
250
OH_CryptoKdfParams_Destroy(OH_CryptoKdfParams * params)251 void OH_CryptoKdfParams_Destroy(OH_CryptoKdfParams *params)
252 {
253 if (params == NULL) {
254 return;
255 }
256 FreeParamSpec(params);
257 params->algName = NULL;
258 HcfFree(params);
259 }
260
OH_CryptoKdf_Create(const char * algoName,OH_CryptoKdf ** ctx)261 OH_Crypto_ErrCode OH_CryptoKdf_Create(const char *algoName, OH_CryptoKdf **ctx)
262 {
263 if ((algoName == NULL) || (ctx == NULL)) {
264 return CRYPTO_PARAMETER_CHECK_FAILED;
265 }
266 HcfResult ret = HcfKdfCreate(algoName, (HcfKdf **)ctx);
267 return GetOhCryptoErrCodeNew(ret);
268 }
269
HkdfDerive(HcfKdf * ctx,const HcfHkdfParamsSpec * params,uint32_t keyLen,HcfBlob * key)270 static OH_Crypto_ErrCode HkdfDerive(HcfKdf *ctx, const HcfHkdfParamsSpec *params, uint32_t keyLen, HcfBlob *key)
271 {
272 uint8_t *out = (uint8_t *)HcfMalloc(keyLen, 0);
273 if (out == NULL) {
274 return CRYPTO_MEMORY_ERROR;
275 }
276 HcfBlob output = {.data = out, .len = keyLen};
277 HcfHkdfParamsSpec hkdfParams = {
278 .base = { .algName = g_hkdfName, },
279 .key = params->key,
280 .salt = params->salt,
281 .info = params->info,
282 .output = output,
283 };
284 HcfResult ret = ctx->generateSecret(ctx, &(hkdfParams.base));
285 if (ret != HCF_SUCCESS) {
286 HcfBlobDataClearAndFree(&output);
287 return GetOhCryptoErrCodeNew(ret);
288 }
289 key->data = hkdfParams.output.data;
290 key->len = hkdfParams.output.len;
291 return CRYPTO_SUCCESS;
292 }
293
Pbkdf2Derive(HcfKdf * ctx,const HcfPBKDF2ParamsSpec * params,uint32_t keyLen,HcfBlob * key)294 static OH_Crypto_ErrCode Pbkdf2Derive(HcfKdf *ctx, const HcfPBKDF2ParamsSpec *params, uint32_t keyLen, HcfBlob *key)
295 {
296 uint8_t *out = (uint8_t *)HcfMalloc(keyLen, 0);
297 if (out == NULL) {
298 return CRYPTO_MEMORY_ERROR;
299 }
300 HcfBlob output = {.data = out, .len = keyLen};
301 HcfPBKDF2ParamsSpec pbkdf2Params = {
302 .base = { .algName = g_pbkdf2Name, },
303 .password = params->password,
304 .salt = params->salt,
305 .iterations = params->iterations,
306 .output = output,
307 };
308 HcfResult ret = ctx->generateSecret(ctx, &(pbkdf2Params.base));
309 if (ret != HCF_SUCCESS) {
310 HcfBlobDataClearAndFree(&output);
311 return GetOhCryptoErrCodeNew(ret);
312 }
313 key->data = pbkdf2Params.output.data;
314 key->len = pbkdf2Params.output.len;
315 return CRYPTO_SUCCESS;
316 }
317
ScryptDerive(HcfKdf * ctx,const HcfScryptParamsSpec * params,uint32_t keyLen,HcfBlob * key)318 static OH_Crypto_ErrCode ScryptDerive(HcfKdf *ctx, const HcfScryptParamsSpec *params, uint32_t keyLen, HcfBlob *key)
319 {
320 uint8_t *out = (uint8_t *)HcfMalloc(keyLen, 0);
321 if (out == NULL) {
322 return CRYPTO_MEMORY_ERROR;
323 }
324 HcfBlob output = {.data = out, .len = keyLen};
325 HcfScryptParamsSpec scryptParams = {
326 .base = { .algName = g_scryptName, },
327 .passPhrase = params->passPhrase,
328 .salt = params->salt,
329 .n = params->n,
330 .p = params->p,
331 .r = params->r,
332 .maxMem = params->maxMem,
333 .output = output,
334 };
335 HcfResult ret = ctx->generateSecret(ctx, &(scryptParams.base));
336 if (ret != HCF_SUCCESS) {
337 HcfBlobDataClearAndFree(&output);
338 return GetOhCryptoErrCodeNew(ret);
339 }
340 key->data = scryptParams.output.data;
341 key->len = scryptParams.output.len;
342 return CRYPTO_SUCCESS;
343 }
344
OH_CryptoKdf_Derive(OH_CryptoKdf * ctx,const OH_CryptoKdfParams * params,int keyLen,Crypto_DataBlob * key)345 OH_Crypto_ErrCode OH_CryptoKdf_Derive(OH_CryptoKdf *ctx, const OH_CryptoKdfParams *params, int keyLen,
346 Crypto_DataBlob *key)
347 {
348 if ((ctx == NULL) || (params == NULL) || (params->algName == NULL) || (key == NULL) || (keyLen <= 0)) {
349 return CRYPTO_PARAMETER_CHECK_FAILED;
350 }
351
352 if (strcmp(params->algName, g_hkdfName) == 0) {
353 return HkdfDerive((HcfKdf *)ctx, (HcfHkdfParamsSpec *)params, (uint32_t)keyLen, (HcfBlob *)key);
354 } else if (strcmp(params->algName, g_pbkdf2Name) == 0) {
355 return Pbkdf2Derive((HcfKdf *)ctx, (HcfPBKDF2ParamsSpec*)params, (uint32_t)keyLen, (HcfBlob *)key);
356 } else if (strcmp(params->algName, g_scryptName) == 0) {
357 return ScryptDerive((HcfKdf *)ctx, (HcfScryptParamsSpec*)params, (uint32_t)keyLen, (HcfBlob *)key);
358 } else {
359 return CRYPTO_PARAMETER_CHECK_FAILED;
360 }
361 }
362
OH_CryptoKdf_Destroy(OH_CryptoKdf * ctx)363 void OH_CryptoKdf_Destroy(OH_CryptoKdf *ctx)
364 {
365 HcfObjDestroy((HcfKdf *)ctx);
366 }