1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include "drv_osal_lib.h"
20 #include "cryp_hash.h"
21 #include "mbedtls/md.h"
22 #include "securec.h"
23
24 #define HASH_MAX_BUFFER_SIZE 0x100000 /* 1M */
25
26 #if defined(SOFT_SHA1_SUPPORT) || defined(SOFT_SHA256_SUPPORT) || defined(SOFT_SHA512_SUPPORT)
27
mbedtls_hash_create(hash_mode mode)28 hi_void *mbedtls_hash_create(hash_mode mode)
29 {
30 mbedtls_md_type_t md_type;
31 const mbedtls_md_info_t *info;
32 mbedtls_md_context_t *ctx = HI_NULL;
33
34 hi_log_func_enter();
35
36 /* convert to mbedtls type */
37 md_type = MBEDTLS_MD_SHA1 + (mode - HASH_MODE_SHA1);
38
39 info = mbedtls_md_info_from_type(md_type);
40 if (info == HI_NULL) {
41 hi_log_error("error, invalid hash mode %d\n", mode);
42 hi_log_print_err_code(HI_ERR_CIPHER_INVALID_PARAM);
43 return HI_NULL;
44 }
45
46 ctx = crypto_malloc(sizeof(*ctx));
47 if (ctx == HI_NULL) {
48 hi_log_error("malloc hash context buffer failed!");
49 hi_log_print_err_code(HI_ERR_CIPHER_FAILED_MEM);
50 return HI_NULL;
51 }
52 (hi_void)memset_s(ctx, sizeof(mbedtls_md_context_t), 0, sizeof(mbedtls_md_context_t));
53
54 mbedtls_md_init(ctx);
55 mbedtls_md_setup(ctx, info, HI_FALSE);
56 mbedtls_md_starts(ctx);
57
58 hi_log_func_exit();
59
60 return ctx;
61 }
62
ext_hash_update_from_user(mbedtls_md_context_t * md,hi_u8 * chunk,hi_u32 chunk_len)63 static hi_s32 ext_hash_update_from_user(mbedtls_md_context_t *md, hi_u8 *chunk, hi_u32 chunk_len)
64 {
65 hi_s32 ret;
66 hi_u8 *ptr = HI_NULL;
67 hi_u32 len;
68 hi_u32 offset = 0;
69
70 ptr = crypto_calloc(HASH_MAX_BUFFER_SIZE);
71 if (ptr == HI_NULL) {
72 hi_log_print_func_err(crypto_malloc, HI_ERR_CIPHER_FAILED_MEM);
73 return HI_ERR_CIPHER_FAILED_MEM;
74 }
75
76 while (offset < chunk_len) {
77 len = chunk_len - offset;
78 if (len > HASH_MAX_BUFFER_SIZE) {
79 len = HASH_MAX_BUFFER_SIZE;
80 }
81 ret = crypto_copy_from_user(ptr, HASH_MAX_BUFFER_SIZE, chunk + offset, len);
82 if (ret != HI_SUCCESS) {
83 hi_log_print_func_err(crypto_copy_from_user, ret);
84 crypto_free(ptr);
85 ptr = HI_NULL;
86 return HI_ERR_CIPHER_FAILED_MEM;
87 }
88 ret = mbedtls_md_update(md, ptr, len);
89 if (ret != HI_SUCCESS) {
90 hi_log_print_func_err(mbedtls_md_update, ret);
91 crypto_free(ptr);
92 ptr = HI_NULL;
93 return ret;
94 }
95 crypto_msleep(1);
96 offset += len;
97 }
98
99 if (ptr != HI_NULL) {
100 crypto_free(ptr);
101 ptr = HI_NULL;
102 }
103
104 return HI_SUCCESS;
105 }
106
mbedtls_hash_update(hi_void * ctx,const hi_u8 * chunk,hi_u32 chunk_len,hash_chunk_src src)107 hi_s32 mbedtls_hash_update(hi_void *ctx, const hi_u8 *chunk, hi_u32 chunk_len, hash_chunk_src src)
108 {
109 hi_u8 *ptr = HI_NULL;
110 hi_s32 ret;
111 mbedtls_md_context_t *md = ctx;
112
113 hi_log_func_enter();
114
115 hi_log_chk_param_return(ctx == HI_NULL);
116
117 if (chunk_len == 0x00) {
118 return HI_SUCCESS;
119 }
120
121 if (src == HASH_CHUNCK_SRC_USER) {
122 ret = ext_hash_update_from_user(md, chunk, chunk_len);
123 if (ret != HI_SUCCESS) {
124 hi_log_print_func_err(mbedtls_md_update, ret);
125 return ret;
126 }
127 } else {
128 ret = mbedtls_md_update(md, chunk, chunk_len);
129 if (ret != HI_SUCCESS) {
130 hi_log_print_func_err(mbedtls_md_update, ret);
131 return ret;
132 }
133 }
134
135 hi_log_func_exit();
136 return HI_SUCCESS;
137 }
138
mbedtls_hash_finish(hi_void * ctx,hi_void * hash,hi_u32 hash_buf_len,hi_u32 * hashlen)139 hi_s32 mbedtls_hash_finish(hi_void *ctx, hi_void *hash, hi_u32 hash_buf_len, hi_u32 *hashlen)
140 {
141 mbedtls_md_context_t *md = ctx;
142
143 hi_log_func_enter();
144
145 hi_log_chk_param_return(ctx == HI_NULL);
146 hi_log_chk_param_return(hash_buf_len == 0);
147
148 mbedtls_md_finish(md, hash);
149
150 *hashlen = mbedtls_md_get_size(md->md_info);
151
152 hi_log_func_exit();
153 return HI_SUCCESS;
154 }
155
mbedtls_hash_destory(hi_void * ctx)156 hi_s32 mbedtls_hash_destory(hi_void *ctx)
157 {
158 mbedtls_md_context_t *md = ctx;
159
160 hi_log_func_enter();
161
162 hi_log_chk_param_return(ctx == HI_NULL);
163
164 mbedtls_md_free(md);
165 crypto_free(ctx);
166 ctx = HI_NULL;
167
168 hi_log_func_exit();
169 return HI_SUCCESS;
170 }
171
172 #endif /* End of SOFT_AES_CCM_GCM_SUPPORT */
173