• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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);