1 /**
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
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 * Description: hash kernel API function implementation.
15 *
16 * Create: 2023-05-26
17 */
18
19 #include "kapi_hash.h"
20 #include <securec.h>
21 #include "kapi_inner.h"
22 #include "kapi_km.h"
23
24 #include "drv_hash.h"
25 #include "crypto_common_macro.h"
26 #include "crypto_common_def.h"
27 #include "crypto_errno.h"
28 #include "crypto_drv_common.h"
29
30 typedef struct {
31 crypto_hash_type hmac_type;
32 td_u8 *key;
33 td_u32 key_length;
34 td_u8 *msg;
35 td_u32 msg_length;
36 } crypto_hkdf_hmac_param_t;
37
38 typedef struct {
39 crypto_hash_type hmac_type;
40 crypto_klad_hmac_type klad_hmac_type;
41 crypto_hash_type hash_type;
42 td_u32 block_size;
43 td_u32 result_size;
44 } crypto_hkdf_table_item_t;
45
46 #define CRYPTO_HASH_INIT_MAX_NUM 256
47
48 static const crypto_hkdf_table_item_t g_hkdf_hmac_table[] = {
49 {
50 .hmac_type = CRYPTO_HASH_TYPE_HMAC_SHA1, .klad_hmac_type = CRYPTO_KLAD_HMAC_TYPE_SHA1,
51 .hash_type = CRYPTO_HASH_TYPE_SHA1, .block_size = HASH_SHA1_BLOCK_SIZE,
52 .result_size = HASH_SHA1_RESULT_SIZE
53 },
54 {
55 .hmac_type = CRYPTO_HASH_TYPE_HMAC_SHA224, .klad_hmac_type = CRYPTO_KLAD_HMAC_TYPE_SHA224,
56 .hash_type = CRYPTO_HASH_TYPE_SHA224, .block_size = HASH_SHA224_BLOCK_SIZE,
57 .result_size = HASH_SHA224_RESULT_SIZE
58 },
59 {
60 .hmac_type = CRYPTO_HASH_TYPE_HMAC_SHA256, .klad_hmac_type = CRYPTO_KLAD_HMAC_TYPE_SHA256,
61 .hash_type = CRYPTO_HASH_TYPE_SHA256, .block_size = HASH_SHA256_BLOCK_SIZE,
62 .result_size = HASH_SHA256_RESULT_SIZE
63 },
64 {
65 .hmac_type = CRYPTO_HASH_TYPE_HMAC_SHA384, .klad_hmac_type = CRYPTO_KLAD_HMAC_TYPE_SHA384,
66 .hash_type = CRYPTO_HASH_TYPE_SHA384, .block_size = HASH_SHA384_BLOCK_SIZE,
67 .result_size = HASH_SHA384_RESULT_SIZE
68 },
69 {
70 .hmac_type = CRYPTO_HASH_TYPE_HMAC_SHA512, .klad_hmac_type = CRYPTO_KLAD_HMAC_TYPE_SHA512,
71 .hash_type = CRYPTO_HASH_TYPE_SHA512, .block_size = HASH_SHA512_BLOCK_SIZE,
72 .result_size = HASH_SHA512_RESULT_SIZE
73 },
74 {
75 .hmac_type = CRYPTO_HASH_TYPE_HMAC_SM3, .klad_hmac_type = CRYPTO_KLAD_HMAC_TYPE_SM3,
76 .hash_type = CRYPTO_HASH_TYPE_SM3, .block_size = HASH_SM3_BLOCK_SIZE,
77 .result_size = HASH_SM3_RESULT_SIZE
78 }
79 };
80
81 #define HASH_COMPAT_ERRNO(err_code) KAPI_COMPAT_ERRNO(ERROR_MODULE_HASH, err_code)
82
priv_get_hkdf_table_item(crypto_hash_type hmac_type)83 static const crypto_hkdf_table_item_t *priv_get_hkdf_table_item(crypto_hash_type hmac_type)
84 {
85 td_u32 i;
86
87 for (i = 0; i < crypto_array_size(g_hkdf_hmac_table); i++) {
88 if (hmac_type == g_hkdf_hmac_table[i].hmac_type) {
89 return &g_hkdf_hmac_table[i];
90 }
91 }
92 return TD_NULL;
93 }
94
inner_hkdf_hash(const crypto_hash_type hash_type,td_u8 * data,td_u32 data_length,td_u8 * out,td_u32 * out_length)95 static td_s32 inner_hkdf_hash(const crypto_hash_type hash_type, td_u8 *data, td_u32 data_length,
96 td_u8 *out, td_u32 *out_length)
97 {
98 td_s32 ret = 0;
99 td_handle hash_handle = 0;
100 crypto_hash_attr hash_attr = { 0 };
101 crypto_buf_attr src_buf = { 0 };
102
103 hash_attr.hash_type = hash_type;
104 hash_attr.is_long_term = TD_TRUE;
105 ret = kapi_cipher_hash_start(&hash_handle, &hash_attr);
106 crypto_chk_return((ret != TD_SUCCESS), TD_FAILURE, "kapi_cipher_hash_start failed!\n");
107
108 src_buf.virt_addr = data;
109 ret = kapi_cipher_hash_update(hash_handle, &src_buf, data_length);
110 crypto_chk_goto((ret != TD_SUCCESS), exit_hash_destroy, "kapi_cipher_hash_update failed!\n");
111
112 ret = kapi_cipher_hash_finish(hash_handle, out, out_length);
113 crypto_chk_goto((ret != TD_SUCCESS), exit_hash_destroy, "kapi_cipher_hash_finish failed!\n");
114 return ret;
115
116 exit_hash_destroy:
117 (void)kapi_cipher_hash_destroy(hash_handle);
118 return ret;
119 }
120
inner_hkdf_key_config(const crypto_hkdf_hmac_param_t * hmac_param,td_handle * ks_handle)121 static td_s32 inner_hkdf_key_config(const crypto_hkdf_hmac_param_t *hmac_param, td_handle *ks_handle)
122 {
123 td_s32 ret = 0;
124 td_handle klad_handle = 0;
125 crypto_klad_clear_key clear_key = {0};
126 crypto_klad_hmac_type klad_hmac_type = { 0 };
127 const crypto_hkdf_table_item_t *hkdf_item = TD_NULL;
128 crypto_klad_attr klad_attr = {
129 .key_cfg = {
130 .engine = CRYPTO_KLAD_ENGINE_SHA2_HMAC,
131 .decrypt_support = TD_TRUE,
132 .encrypt_support = TD_TRUE
133 },
134 .key_sec_cfg = {
135 .key_sec = TD_FALSE,
136 .master_only_enable = TD_FALSE,
137 .dest_buf_sec_support = TD_FALSE,
138 .dest_buf_non_sec_support = TD_TRUE,
139 .src_buf_sec_support = TD_FALSE,
140 .src_buf_non_sec_support = TD_TRUE,
141 }
142 };
143
144 hkdf_item = priv_get_hkdf_table_item(hmac_param->hmac_type);
145 crypto_chk_return(hkdf_item == TD_NULL, TD_FAILURE, "get hkdf hmac type failed!\n");
146 klad_hmac_type = hkdf_item->klad_hmac_type;
147
148 ret = kapi_keyslot_create(ks_handle, CRYPTO_KEYSLOT_TYPE_HMAC);
149 crypto_chk_return(ret != TD_SUCCESS, ret, "kapi_keyslot_create failed\n");
150
151 ret = kapi_klad_create(&klad_handle);
152 crypto_chk_goto((ret != TD_SUCCESS), exit_ks_destroy, "kapi_klad_create failed!\n");
153
154 ret = kapi_klad_attach(klad_handle, CRYPTO_KLAD_DEST_HMAC, *ks_handle);
155 crypto_chk_goto((ret != TD_SUCCESS), exit_klad_destroy, "kapi_klad_attach failed!\n");
156
157 ret = kapi_klad_set_attr(klad_handle, &klad_attr);
158 crypto_chk_goto((ret != TD_SUCCESS), exit_klad_detach, "kapi_klad_set_attr failed!\n");
159
160 clear_key.key = hmac_param->key;
161 clear_key.key_length = hmac_param->key_length;
162 clear_key.hmac_type = klad_hmac_type;
163 ret = kapi_klad_set_clear_key(klad_handle, &clear_key);
164 crypto_chk_goto((ret != TD_SUCCESS), exit_klad_detach, "kapi_klad_set_clear_key failed!\n");
165
166 kapi_klad_detach(klad_handle, CRYPTO_KLAD_DEST_HMAC, *ks_handle);
167 kapi_klad_destroy(klad_handle);
168 return ret;
169
170 exit_klad_detach:
171 kapi_klad_detach(klad_handle, CRYPTO_KLAD_DEST_HMAC, *ks_handle);
172 exit_klad_destroy:
173 kapi_klad_destroy(klad_handle);
174 exit_ks_destroy:
175 kapi_keyslot_destroy(*ks_handle);
176 return ret;
177 }
178
inner_hkdf_hmac(const crypto_hkdf_hmac_param_t * hmac_param,td_handle ks_handle,td_u8 * out,td_u32 * out_length)179 static td_s32 inner_hkdf_hmac(const crypto_hkdf_hmac_param_t *hmac_param, td_handle ks_handle,
180 td_u8 *out, td_u32 *out_length)
181 {
182 td_s32 ret = 0;
183 td_handle hash_handle = 0;
184 crypto_hash_attr hash_attr = { 0 };
185 crypto_buf_attr src_buf = { 0 };
186
187 hash_attr.hash_type = hmac_param->hmac_type;
188 hash_attr.drv_keyslot_handle = ks_handle;
189 hash_attr.is_keyslot = TD_TRUE;
190 hash_attr.is_long_term = TD_TRUE;
191 ret = kapi_cipher_hash_start(&hash_handle, &hash_attr);
192 crypto_chk_return((ret != TD_SUCCESS), TD_FAILURE, "kapi_cipher_hash_start failed!\n");
193
194 src_buf.virt_addr = hmac_param->msg;
195 ret = kapi_cipher_hash_update(hash_handle, &src_buf, hmac_param->msg_length);
196 crypto_chk_goto((ret != TD_SUCCESS), exit_hash_destroy, "kapi_cipher_hash_update failed!\n");
197
198 ret = kapi_cipher_hash_finish(hash_handle, out, out_length);
199 crypto_chk_goto((ret != TD_SUCCESS), exit_hash_destroy, "kapi_cipher_hash_finish failed!\n");
200 return ret;
201
202 exit_hash_destroy:
203 (void)kapi_cipher_hash_destroy(hash_handle);
204 return ret;
205 }
206
kapi_cipher_hkdf_extract(crypto_hkdf_extract_t * extract_param,td_u8 * prk,td_u32 * prk_length)207 td_s32 kapi_cipher_hkdf_extract(crypto_hkdf_extract_t *extract_param, td_u8 *prk, td_u32 *prk_length)
208 {
209 td_u32 input_block_length = 0;
210 td_handle ks_handle = 0;
211 crypto_hash_type hash_type = 0;
212 crypto_hkdf_hmac_param_t hmac_param = { 0 };
213 const crypto_hkdf_table_item_t *hkdf_item = TD_NULL;
214 td_s32 ret = 0;
215
216 crypto_chk_return(extract_param == TD_NULL || extract_param->ikm == TD_NULL, TD_FAILURE, "Param is NULL!\n");
217 crypto_chk_return(extract_param->salt_length != 0 && extract_param->salt == TD_NULL,
218 TD_FAILURE, "Param is NULL!\n");
219 crypto_chk_return(prk == TD_NULL || prk_length == TD_NULL, TD_FAILURE, "Param is NULL!\n");
220
221 hkdf_item = priv_get_hkdf_table_item(extract_param->hmac_type);
222 crypto_chk_return(hkdf_item == TD_NULL, TD_FAILURE, "get hkdf hmac type failed!\n");
223 input_block_length = hkdf_item->block_size;
224 hash_type = hkdf_item->hash_type;
225
226 if (extract_param->salt_length > input_block_length) {
227 ret = inner_hkdf_hash(hash_type, extract_param->salt, extract_param->salt_length,
228 extract_param->salt, &extract_param->salt_length);
229 crypto_chk_return(ret != TD_SUCCESS, ret, "inner_hkdf_hash failed\n");
230 }
231
232 hmac_param.hmac_type = extract_param->hmac_type;
233 hmac_param.key = extract_param->salt;
234 hmac_param.key_length = extract_param->salt_length;
235 ret = inner_hkdf_key_config(&hmac_param, &ks_handle);
236 crypto_chk_return(ret != TD_SUCCESS, ret, "inner_hkdf_key_config failed\n");
237
238 hmac_param.msg = extract_param->ikm;
239 hmac_param.msg_length = extract_param->ikm_length;
240 ret = inner_hkdf_hmac(&hmac_param, ks_handle, prk, prk_length);
241
242 kapi_keyslot_destroy(ks_handle);
243 return ret;
244 }
245 CRYPTO_EXPORT_SYMBOL(kapi_cipher_hkdf_extract);
246
kapi_cipher_hkdf_expand(const crypto_hkdf_expand_t * expand_param,td_u8 * okm,td_u32 okm_length)247 td_s32 kapi_cipher_hkdf_expand(const crypto_hkdf_expand_t *expand_param, td_u8 *okm, td_u32 okm_length)
248 {
249 td_u32 block_num = 0;
250 td_handle ks_handle = 0;
251 td_u8 output_block[64] = { 0 }; /* 64 is the max hash output length */
252 td_u32 output_block_length = 0;
253 td_u8 *buffer = TD_NULL;
254 td_u32 buffer_length = 0;
255 td_u32 processing_len = 0;
256 td_u32 last_len = 0;
257 crypto_hkdf_hmac_param_t hmac_param = { 0 };
258 const crypto_hkdf_table_item_t *hkdf_item = TD_NULL;
259 td_u32 i;
260 td_s32 ret = 0;
261
262 crypto_chk_return(expand_param == TD_NULL || expand_param->prk == TD_NULL, TD_FAILURE, "Param is NULL!\n");
263 crypto_chk_return(expand_param->info_length != 0 && expand_param->info == TD_NULL, TD_FAILURE, "Param is NULL!\n");
264 crypto_chk_return(okm == TD_NULL, TD_FAILURE, "Param is NULL!\n");
265 crypto_chk_return(expand_param->info_length > HKDF_EXPAND_INFO_MAX_LENGTH, TD_FAILURE, "Param is NULL!\n");
266
267 hkdf_item = priv_get_hkdf_table_item(expand_param->hmac_type);
268 crypto_chk_return(hkdf_item == TD_NULL, TD_FAILURE, "get hkdf hmac type failed!\n");
269 output_block_length = hkdf_item->result_size;
270 /* According to RFC 5869 Section2.3, the length must <= 255 * hash_length. */
271 if (okm_length > 255 * output_block_length) { // 255: refer to comment above
272 crypto_log_err("okm_length is too long\n");
273 return HASH_COMPAT_ERRNO(ERROR_INVALID_PARAM);
274 }
275
276 buffer_length = output_block_length + expand_param->info_length + 1;
277 buffer = crypto_malloc(buffer_length);
278 if (buffer == TD_NULL) {
279 crypto_log_err("crypto_malloc failed\n");
280 return TD_FAILURE;
281 }
282
283 hmac_param.hmac_type = expand_param->hmac_type;
284 hmac_param.key = expand_param->prk;
285 hmac_param.key_length = expand_param->prk_length;
286 ret = inner_hkdf_key_config(&hmac_param, &ks_handle);
287 crypto_chk_goto(ret != TD_SUCCESS, free_exit, "inner_hkdf_key_config failed\n");
288
289 block_num = okm_length / output_block_length + ((okm_length % output_block_length) == 0 ? 0 : 1);
290 for (i = 0; i < block_num; i++) {
291 if (i == 0) {
292 output_block_length = 0;
293 } else {
294 ret = memcpy_s(buffer, buffer_length, output_block, output_block_length);
295 crypto_chk_goto(ret != TD_SUCCESS, okm_exit, "memcpy_s failed\n");
296 }
297
298 if (expand_param->info != TD_NULL) {
299 ret = memcpy_s(buffer + output_block_length, buffer_length - output_block_length,
300 expand_param->info, expand_param->info_length);
301 crypto_chk_goto(ret != TD_SUCCESS, okm_exit, "memcpy_s failed\n");
302 }
303 buffer[output_block_length + expand_param->info_length] = i + 1;
304
305 processing_len = output_block_length + expand_param->info_length + 1;
306 output_block_length = hkdf_item->result_size;
307 hmac_param.hmac_type = expand_param->hmac_type;
308 hmac_param.msg = buffer;
309 hmac_param.msg_length = processing_len;
310 ret = inner_hkdf_hmac(&hmac_param, ks_handle, output_block, &output_block_length);
311 crypto_chk_goto(ret != TD_SUCCESS, okm_exit, "inner_hkdf_hmac failed\n");
312
313 if (i != block_num - 1) {
314 ret = memcpy_s(okm + i * output_block_length, okm_length - i * output_block_length,
315 output_block, output_block_length);
316 crypto_chk_goto(ret != TD_SUCCESS, okm_exit, "memcpy_s failed\n");
317 }
318 }
319
320 last_len = (okm_length % output_block_length) == 0 ? output_block_length : (okm_length % output_block_length);
321 ret = memcpy_s(okm + (i - 1) * output_block_length, okm_length - (i - 1) * output_block_length,
322 output_block, last_len);
323 crypto_chk_goto(ret != TD_SUCCESS, okm_exit, "memcpy_s failed\n");
324
325 goto expand_exit;
326
327 okm_exit:
328 memset_s(okm, okm_length, 0x00, okm_length);
329 expand_exit:
330 memset_s(output_block, sizeof(output_block), 0x00, sizeof(output_block));
331 memset_s(buffer, buffer_length, 0x00, buffer_length);
332 kapi_keyslot_destroy(ks_handle);
333 free_exit:
334 crypto_free(buffer);
335 return ret;
336 }
337 CRYPTO_EXPORT_SYMBOL(kapi_cipher_hkdf_expand);
338
kapi_cipher_hkdf(crypto_hkdf_t * hkdf_param,td_u8 * okm,td_u32 okm_length)339 td_s32 kapi_cipher_hkdf(crypto_hkdf_t *hkdf_param, td_u8 *okm, td_u32 okm_length)
340 {
341 td_u8 prk[64] = { 0 }; /* 64 is the max hash result length */
342 td_u32 prk_length = 0;
343 crypto_hkdf_extract_t hkdf_extract = { 0 };
344 crypto_hkdf_expand_t hkdf_expand = { 0 };
345 const crypto_hkdf_table_item_t *hkdf_item = TD_NULL;
346 td_s32 ret = 0;
347
348 crypto_chk_return(hkdf_param == TD_NULL || hkdf_param->ikm == TD_NULL, TD_FAILURE, "Param is NULL!\n");
349 crypto_chk_return(hkdf_param->salt_length != 0 && hkdf_param->salt == TD_NULL,
350 TD_FAILURE, "Param is NULL!\n");
351 crypto_chk_return(hkdf_param->info_length != 0 && hkdf_param->info == TD_NULL,
352 TD_FAILURE, "Param is NULL!\n");
353 crypto_chk_return(okm == TD_NULL, TD_FAILURE, "Param is NULL!\n");
354
355 hkdf_item = priv_get_hkdf_table_item(hkdf_param->hmac_type);
356 crypto_chk_return(hkdf_item == TD_NULL, TD_FAILURE, "get hkdf hmac type failed!\n");
357 prk_length = hkdf_item->result_size;
358
359 hkdf_extract.hmac_type = hkdf_param->hmac_type;
360 hkdf_extract.ikm = hkdf_param->ikm;
361 hkdf_extract.ikm_length = hkdf_param->ikm_length;
362 hkdf_extract.salt = hkdf_param->salt;
363 hkdf_extract.salt_length = hkdf_param->salt_length;
364 ret = kapi_cipher_hkdf_extract(&hkdf_extract, prk, &prk_length);
365 crypto_chk_return(ret != TD_SUCCESS, ret, "kapi_cipher_hkdf_extract failed\n");
366
367 hkdf_expand.hmac_type = hkdf_param->hmac_type;
368 hkdf_expand.info = hkdf_param->info;
369 hkdf_expand.info_length = hkdf_param->info_length;
370 hkdf_expand.prk = prk;
371 hkdf_expand.prk_length = prk_length;
372 ret = kapi_cipher_hkdf_expand(&hkdf_expand, okm, okm_length);
373
374 memset_s(prk, sizeof(prk), 0x00, sizeof(prk));
375 return ret;
376 }
377 CRYPTO_EXPORT_SYMBOL(kapi_cipher_hkdf);