• 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-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);