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-12-23
17 */
18
19 #include <securec.h>
20 #include "kapi_hash.h"
21 #include "kapi_inner.h"
22
23 #include "drv_hash.h"
24 #include "crypto_common_macro.h"
25 #include "crypto_common_def.h"
26 #include "crypto_errno.h"
27 #include "crypto_drv_common.h"
28
29 #define INVALID_HANDLE 0xFFFFFFFF
30
31 #define HASH_COMPAT_ERRNO(err_code) KAPI_COMPAT_ERRNO(ERROR_MODULE_HASH, err_code)
32 #define hash_null_ptr_chk(ptr) \
33 crypto_chk_return((ptr) == TD_NULL, HASH_COMPAT_ERRNO(ERROR_PARAM_IS_NULL), #ptr" is NULL\n")
34
35 typedef struct {
36 crypto_hash_clone_ctx clone_ctx;
37 crypto_owner owner;
38 td_bool is_keyslot;
39 td_handle drv_hash_handle;
40 } kapi_hash_context;
41
42 static crypto_mutex g_hash_mutex;
43 static kapi_hash_context *g_hash_ctx[CRYPTO_HASH_VIRT_CHN_NUM];
44 static td_bool g_hash_ctx_used[CRYPTO_HASH_VIRT_CHN_NUM];
45
46 #define kapi_hash_lock() do { \
47 crypto_mutex_lock(&g_hash_mutex); \
48 } while (0)
49 #define kapi_hash_unlock() do { \
50 crypto_mutex_unlock(&g_hash_mutex); \
51 } while (0)
52
inner_kapi_hash_handle_check(td_handle kapi_hash_handle)53 static td_s32 inner_kapi_hash_handle_check(td_handle kapi_hash_handle)
54 {
55 crypto_chk_return(kapi_get_module_id(kapi_hash_handle) != KAPI_HASH_MODULE_ID,
56 HASH_COMPAT_ERRNO(ERROR_INVALID_HANDLE), "Invalid Hash Handle! 0x%x\n", kapi_hash_handle);
57 crypto_chk_return(kapi_get_ctx_idx(kapi_hash_handle) >= CRYPTO_HASH_VIRT_CHN_NUM,
58 HASH_COMPAT_ERRNO(ERROR_INVALID_HANDLE), "Invalid Hash Handle! 0x%x\n", kapi_hash_handle);
59 return TD_SUCCESS;
60 }
61
inner_kapi_alloc_hash_ctx(td_handle * hash_handle,kapi_hash_context ** hash_ctx)62 static int inner_kapi_alloc_hash_ctx(td_handle *hash_handle, kapi_hash_context **hash_ctx)
63 {
64 int ret = TD_FAILURE;
65 unsigned int i;
66 kapi_hash_lock();
67 for (i = 0; i < CRYPTO_HASH_VIRT_CHN_NUM; i++) {
68 if (g_hash_ctx_used[i] == TD_FALSE) {
69 break;
70 }
71 }
72 if (i >= CRYPTO_HASH_VIRT_CHN_NUM) {
73 crypto_log_err("All hash contexts are busy!\n");
74 ret = HASH_COMPAT_ERRNO(ERROR_CHN_BUSY);
75 goto exit_unlock;
76 }
77
78 *hash_ctx = crypto_malloc(sizeof(kapi_hash_context));
79 crypto_chk_goto_with_ret(ret, *hash_ctx == NULL, exit_unlock,
80 HASH_COMPAT_ERRNO(ERROR_MALLOC), "crypto_malloc failed\n");
81 (void)memset_s(*hash_ctx, sizeof(kapi_hash_context), 0, sizeof(kapi_hash_context));
82
83 g_hash_ctx_used[i] = TD_TRUE;
84 g_hash_ctx[i] = *hash_ctx;
85 crypto_get_owner(&(g_hash_ctx[i]->owner));
86 *hash_handle = synthesize_kapi_handle(KAPI_HASH_MODULE_ID, i);
87 ret = CRYPTO_SUCCESS;
88 exit_unlock:
89 kapi_hash_unlock();
90 return ret;
91 }
92
inner_kapi_free_hash_ctx(td_handle hash_handle)93 static int inner_kapi_free_hash_ctx(td_handle hash_handle)
94 {
95 unsigned int idx = kapi_get_ctx_idx(hash_handle);
96 if (inner_kapi_hash_handle_check(hash_handle) != TD_SUCCESS) {
97 return HASH_COMPAT_ERRNO(ERROR_INVALID_HANDLE);
98 }
99 kapi_hash_lock();
100 g_hash_ctx_used[idx] = TD_FALSE;
101 if (g_hash_ctx[idx] != NULL) {
102 crypto_free(g_hash_ctx[idx]);
103 g_hash_ctx[idx] = NULL;
104 }
105 kapi_hash_unlock();
106 return CRYPTO_SUCCESS;
107 }
108
inner_kapi_get_hash_ctx(td_handle hash_handle)109 static kapi_hash_context *inner_kapi_get_hash_ctx(td_handle hash_handle)
110 {
111 unsigned int idx = kapi_get_ctx_idx(hash_handle);
112 if (inner_kapi_hash_handle_check(hash_handle) != TD_SUCCESS) {
113 return NULL;
114 }
115 return g_hash_ctx[idx];
116 }
117
inner_drv_lock_start(kapi_hash_context * hash_ctx,const crypto_hash_attr * hash_attr)118 static td_s32 inner_drv_lock_start(kapi_hash_context *hash_ctx, const crypto_hash_attr *hash_attr)
119 {
120 td_s32 ret = TD_SUCCESS;
121 kapi_hash_lock();
122 ret = drv_cipher_hash_start(&hash_ctx->drv_hash_handle, hash_attr);
123 kapi_hash_unlock();
124 return ret;
125 }
126
kapi_cipher_hash_env_init(td_void)127 td_s32 kapi_cipher_hash_env_init(td_void)
128 {
129 td_s32 ret = TD_SUCCESS;
130 crypto_kapi_func_enter();
131
132 ret = drv_cipher_hash_init();
133 if (ret != TD_SUCCESS) {
134 crypto_log_err("drv_cipher_hash_init failed\n");
135 return ret;
136 }
137
138 ret = crypto_mutex_init(&g_hash_mutex);
139 if (ret != TD_SUCCESS) {
140 crypto_log_err("crypto_mutex_init failed\n");
141 ret = HASH_COMPAT_ERRNO(ERROR_MUTEX_INIT);
142 goto error_hash_deinit;
143 }
144
145 crypto_kapi_func_exit();
146 return ret;
147
148 error_hash_deinit:
149 drv_cipher_hash_deinit();
150 return ret;
151 }
152
kapi_cipher_hash_env_deinit(td_void)153 td_s32 kapi_cipher_hash_env_deinit(td_void)
154 {
155 unsigned int i;
156 td_s32 ret = TD_SUCCESS;
157 crypto_kapi_func_enter();
158 for (i = 0; i < CRYPTO_HASH_VIRT_CHN_NUM; i++) {
159 if (g_hash_ctx_used[i] == TD_FALSE) {
160 continue;
161 }
162 g_hash_ctx_used[i] = TD_FALSE;
163 if (g_hash_ctx[i] != NULL) {
164 crypto_free(g_hash_ctx[i]);
165 g_hash_ctx[i] = NULL;
166 }
167 }
168 crypto_mutex_destroy(&g_hash_mutex);
169 drv_cipher_hash_deinit();
170 crypto_kapi_func_exit();
171 return ret;
172 }
173
kapi_cipher_hash_init(td_void)174 td_s32 kapi_cipher_hash_init(td_void)
175 {
176 td_s32 ret = TD_SUCCESS;
177 crypto_kapi_func_enter();
178
179 crypto_kapi_func_exit();
180 return ret;
181 }
182 CRYPTO_EXPORT_SYMBOL(kapi_cipher_hash_init);
183
kapi_cipher_hash_deinit(td_void)184 td_s32 kapi_cipher_hash_deinit(td_void)
185 {
186 crypto_kapi_func_enter();
187 crypto_kapi_func_exit();
188 return TD_SUCCESS;
189 }
190 CRYPTO_EXPORT_SYMBOL(kapi_cipher_hash_deinit);
191
kapi_cipher_hash_start(td_handle * kapi_hash_handle,const crypto_hash_attr * hash_attr)192 td_s32 kapi_cipher_hash_start(td_handle *kapi_hash_handle, const crypto_hash_attr *hash_attr)
193 {
194 int ret = TD_FAILURE;
195 const unsigned int *sha_val = NULL;
196 unsigned int sha_val_len = 0;
197 kapi_hash_context *hash_ctx = NULL;
198 crypto_kapi_func_enter();
199
200 hash_null_ptr_chk(kapi_hash_handle);
201 hash_null_ptr_chk(hash_attr);
202
203 ret = inner_kapi_alloc_hash_ctx(kapi_hash_handle, &hash_ctx);
204 crypto_chk_return(ret != CRYPTO_SUCCESS, ret, "inner_kapi_alloc_hash_ctx failed\n");
205
206 if (crypto_hash_is_hmac(hash_attr->hash_type) == TD_TRUE) {
207 if (hash_attr->is_keyslot == TD_FALSE) {
208 crypto_log_err("hmac only support keyslot\n");
209 ret = HASH_COMPAT_ERRNO(ERROR_UNSUPPORT);
210 goto error_free_ctx;
211 }
212 ret = inner_drv_lock_start(hash_ctx, hash_attr);
213 crypto_chk_goto(ret != TD_SUCCESS, error_free_ctx, "inner_drv_lock_start failed\n");
214 hash_ctx->is_keyslot = hash_attr->is_keyslot;
215 return CRYPTO_SUCCESS;
216 }
217
218 (void)memset_s(&hash_ctx->clone_ctx, sizeof(hash_ctx->clone_ctx), 0, sizeof(hash_ctx->clone_ctx));
219
220 sha_val = drv_hash_get_state_iv(hash_attr->hash_type, &sha_val_len);
221 crypto_chk_goto_with_ret(ret, sha_val == TD_NULL, error_free_ctx, TD_FAILURE, "drv_hash_get_state_iv failed\n");
222
223 ret = memcpy_s(hash_ctx->clone_ctx.state, sizeof(hash_ctx->clone_ctx.state), sha_val, sha_val_len);
224 crypto_chk_goto_with_ret(ret, ret != EOK, error_free_ctx, HASH_COMPAT_ERRNO(ERROR_MEMCPY_S), "memcpy_s failed\n");
225
226 hash_ctx->clone_ctx.hash_type = hash_attr->hash_type;
227 crypto_kapi_func_exit();
228
229 return 0;
230 error_free_ctx:
231 inner_kapi_free_hash_ctx(*kapi_hash_handle);
232 return ret;
233 }
234 CRYPTO_EXPORT_SYMBOL(kapi_cipher_hash_start);
235
kapi_cipher_hash_update(td_handle kapi_hash_handle,const crypto_buf_attr * src_buf,const td_u32 len)236 td_s32 kapi_cipher_hash_update(td_handle kapi_hash_handle, const crypto_buf_attr *src_buf, const td_u32 len)
237 {
238 int ret;
239 td_handle hash_handle = INVALID_HANDLE;
240 crypto_hash_attr hash_attr;
241 kapi_hash_context *hash_ctx = NULL;
242 crypto_kapi_func_enter();
243
244 kapi_hash_lock();
245 hash_ctx = inner_kapi_get_hash_ctx(kapi_hash_handle);
246 crypto_chk_goto_with_ret(ret, hash_ctx == NULL, exit_mutex_unlock, HASH_COMPAT_ERRNO(ERROR_INVALID_HANDLE),
247 "inner_kapi_get_hash_ctx failed\n");
248
249 if (hash_ctx->is_keyslot == TD_TRUE) {
250 ret = drv_cipher_hash_update(hash_ctx->drv_hash_handle, src_buf, len);
251 crypto_chk_goto(ret != TD_SUCCESS, exit_mutex_unlock, "drv_cipher_hash_update failed\n");
252 kapi_hash_unlock();
253 return CRYPTO_SUCCESS;
254 }
255
256 hash_attr.hash_type = hash_ctx->clone_ctx.hash_type;
257 hash_attr.is_keyslot = hash_ctx->is_keyslot;
258 ret = drv_cipher_hash_start(&hash_handle, &hash_attr);
259 crypto_chk_goto(ret != 0, exit_mutex_unlock, "drv_cipher_hash_set failed\n");
260
261 ret = drv_cipher_hash_set(hash_handle, &hash_ctx->clone_ctx);
262 crypto_chk_goto(ret != 0, exit_hash_destroy, "drv_cipher_hash_set failed\n");
263
264 ret = drv_cipher_hash_update(hash_handle, src_buf, len);
265 crypto_chk_goto(ret != 0, exit_hash_destroy, "drv_cipher_hash_update failed\n");
266
267 ret = drv_cipher_hash_get(hash_handle, &hash_ctx->clone_ctx);
268 crypto_chk_goto(ret != 0, exit_hash_destroy, "drv_cipher_hash_get failed\n");
269
270 exit_hash_destroy:
271 (void)drv_cipher_hash_destroy(hash_handle);
272 exit_mutex_unlock:
273 kapi_hash_unlock();
274 crypto_kapi_func_exit();
275 return ret;
276 }
277 CRYPTO_EXPORT_SYMBOL(kapi_cipher_hash_update);
278
kapi_cipher_hash_finish(td_handle kapi_hash_handle,td_u8 * out,td_u32 * out_len)279 td_s32 kapi_cipher_hash_finish(td_handle kapi_hash_handle, td_u8 *out, td_u32 *out_len)
280 {
281 int ret;
282 td_handle hash_handle = INVALID_HANDLE;
283 crypto_hash_attr hash_attr;
284 kapi_hash_context *hash_ctx = NULL;
285 crypto_kapi_func_enter();
286
287 hash_ctx = inner_kapi_get_hash_ctx(kapi_hash_handle);
288 crypto_chk_return(hash_ctx == NULL, HASH_COMPAT_ERRNO(ERROR_INVALID_HANDLE), "inner_kapi_get_hash_ctx failed\n");
289
290 kapi_hash_lock();
291
292 if (hash_ctx->is_keyslot == TD_TRUE) {
293 ret = drv_cipher_hash_finish(hash_ctx->drv_hash_handle, out, out_len);
294 if (ret != TD_SUCCESS) {
295 crypto_log_err("drv_cipher_hash_finish failed\n");
296 goto exit_hash_destroy;
297 }
298 ret = CRYPTO_SUCCESS;
299 goto exit_mutex_unlock;
300 }
301
302 hash_attr.hash_type = hash_ctx->clone_ctx.hash_type;
303 hash_attr.is_keyslot = hash_ctx->is_keyslot;
304 ret = drv_cipher_hash_start(&hash_handle, &hash_attr);
305 crypto_chk_goto(ret != 0, exit_mutex_unlock, "drv_cipher_hash_start failed\n");
306
307 ret = drv_cipher_hash_set(hash_handle, &hash_ctx->clone_ctx);
308 crypto_chk_goto(ret != 0, exit_hash_destroy, "drv_cipher_hash_set failed\n");
309
310 ret = drv_cipher_hash_finish(hash_handle, out, out_len);
311 crypto_chk_goto(ret != 0, exit_hash_destroy, "drv_cipher_hash_finish failed\n");
312 hash_handle = INVALID_HANDLE;
313
314 exit_hash_destroy:
315 if (hash_handle != INVALID_HANDLE) {
316 (void)drv_cipher_hash_destroy(hash_handle);
317 }
318 exit_mutex_unlock:
319 kapi_hash_unlock();
320 inner_kapi_free_hash_ctx(kapi_hash_handle);
321 crypto_kapi_func_exit();
322 return ret;
323 }
324 CRYPTO_EXPORT_SYMBOL(kapi_cipher_hash_finish);
325
kapi_cipher_hash_get(td_handle kapi_hash_handle,crypto_hash_clone_ctx * hash_clone_ctx)326 td_s32 kapi_cipher_hash_get(td_handle kapi_hash_handle, crypto_hash_clone_ctx *hash_clone_ctx)
327 {
328 int ret;
329 kapi_hash_context *hash_ctx = NULL;
330 crypto_kapi_func_enter();
331
332 hash_ctx = inner_kapi_get_hash_ctx(kapi_hash_handle);
333 crypto_chk_return(hash_ctx == NULL, HASH_COMPAT_ERRNO(ERROR_INVALID_HANDLE), "inner_kapi_get_hash_ctx failed\n");
334
335 if (hash_ctx->is_keyslot == TD_TRUE) {
336 crypto_log_err("hmac unsupport hash get\n");
337 return HASH_COMPAT_ERRNO(ERROR_UNSUPPORT);
338 }
339
340 ret = memcpy_s(hash_clone_ctx, sizeof(crypto_hash_clone_ctx), &hash_ctx->clone_ctx, sizeof(crypto_hash_clone_ctx));
341 crypto_chk_return(ret != EOK, HASH_COMPAT_ERRNO(ERROR_MEMCPY_S), "memcpy_s failed\n");
342
343 crypto_kapi_func_exit();
344 return 0;
345 }
346 CRYPTO_EXPORT_SYMBOL(kapi_cipher_hash_get);
347
kapi_cipher_hash_set(td_handle kapi_hash_handle,const crypto_hash_clone_ctx * hash_clone_ctx)348 td_s32 kapi_cipher_hash_set(td_handle kapi_hash_handle, const crypto_hash_clone_ctx *hash_clone_ctx)
349 {
350 int ret;
351 kapi_hash_context *hash_ctx = NULL;
352 crypto_kapi_func_enter();
353
354 hash_ctx = inner_kapi_get_hash_ctx(kapi_hash_handle);
355 crypto_chk_return(hash_ctx == NULL, HASH_COMPAT_ERRNO(ERROR_INVALID_HANDLE), "inner_kapi_get_hash_ctx failed\n");
356
357 if (hash_ctx->is_keyslot == TD_TRUE) {
358 crypto_log_err("hmac unsupport hash set\n");
359 return HASH_COMPAT_ERRNO(ERROR_UNSUPPORT);
360 }
361
362 ret = memcpy_s(&hash_ctx->clone_ctx, sizeof(crypto_hash_clone_ctx), hash_clone_ctx, sizeof(crypto_hash_clone_ctx));
363 crypto_chk_return(ret != EOK, HASH_COMPAT_ERRNO(ERROR_MEMCPY_S), "memcpy_s failed\n");
364
365 crypto_kapi_func_exit();
366 return 0;
367 }
368 CRYPTO_EXPORT_SYMBOL(kapi_cipher_hash_set);
369
kapi_cipher_hash_destroy(td_handle kapi_hash_handle)370 td_s32 kapi_cipher_hash_destroy(td_handle kapi_hash_handle)
371 {
372 int ret;
373 crypto_kapi_func_enter();
374 ret = inner_kapi_free_hash_ctx(kapi_hash_handle);
375 crypto_kapi_func_exit();
376 return ret;
377 }
378 CRYPTO_EXPORT_SYMBOL(kapi_cipher_hash_destroy);
379
kapi_cipher_pbkdf2(const crypto_kdf_pbkdf2_param * param,td_u8 * out,const td_u32 out_len)380 td_s32 kapi_cipher_pbkdf2(const crypto_kdf_pbkdf2_param *param, td_u8 *out, const td_u32 out_len)
381 {
382 td_s32 ret = TD_SUCCESS;
383 crypto_kapi_func_enter();
384
385 kapi_hash_lock();
386 ret = drv_cipher_pbkdf2(param, out, out_len);
387 kapi_hash_unlock();
388 crypto_kapi_func_exit();
389 return ret;
390 }
391 CRYPTO_EXPORT_SYMBOL(kapi_cipher_pbkdf2);