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_symc.h"
21 #include "mbedtls/ccm.h"
22 #include "mbedtls/gcm.h"
23 #include "securec.h"
24
25 #ifdef SOFT_AES_CCM_GCM_SUPPORT
26
27 /*
28 * aes ccm context structure
29 */
30 typedef struct {
31 hi_u32 key[SYMC_KEY_SIZE / WORD_WIDTH]; /* SYMC even round keys, default */
32 hi_u32 iv[AES_IV_SIZE / WORD_WIDTH]; /* symc IV */
33 hi_u32 tag[AEAD_TAG_SIZE / WORD_WIDTH]; /* aead tag */
34 hi_u32 ivlen; /* symc IV length */
35 hi_u32 klen; /* symc key length */
36 compat_addr aad; /* Associated Data */
37 hi_u32 alen; /* Associated Data length */
38 hi_u32 tlen; /* Tag length */
39 } ext_aead_context;
40
41 typedef struct {
42 crypto_mem in;
43 crypto_mem out;
44 crypto_mem aad;
45 } ext_ccm_gcm_mem;
46
ext_mbedtls_aead_create(hi_u32 hard_chn)47 hi_void *ext_mbedtls_aead_create(hi_u32 hard_chn)
48 {
49 ext_aead_context *ctx = HI_NULL;
50
51 hi_log_func_enter();
52
53 ctx = crypto_calloc(1, sizeof(ext_aead_context));
54 if (ctx == HI_NULL) {
55 hi_log_error("malloc failed \n");
56 hi_log_print_func_err(crypto_calloc, 0);
57 return HI_NULL;
58 }
59
60 hi_log_func_exit();
61
62 return ctx;
63 }
64
ext_mbedtls_aead_destory(hi_void * ctx)65 hi_s32 ext_mbedtls_aead_destory(hi_void *ctx)
66 {
67 hi_log_func_enter();
68
69 if (ctx != HI_NULL) {
70 crypto_free(ctx);
71 ctx = HI_NULL;
72 }
73
74 hi_log_func_exit();
75 return HI_SUCCESS;
76 }
77
ext_mbedtls_aead_setiv(hi_void * ctx,const hi_u8 * iv,hi_u32 ivlen,hi_u32 usage)78 hi_s32 ext_mbedtls_aead_setiv(hi_void *ctx, const hi_u8 *iv, hi_u32 ivlen, hi_u32 usage)
79 {
80 ext_aead_context *aead = ctx;
81
82 hi_log_func_enter();
83
84 hi_log_chk_param_return(aead == HI_NULL);
85 hi_log_chk_param_return(ivlen > AES_IV_SIZE);
86
87 if (iv != HI_NULL) {
88 if (memcpy_s(aead->iv, AES_IV_SIZE, iv, ivlen) != EOK) {
89 hi_log_print_func_err(memcpy_s, HI_ERR_CIPHER_MEMCPY_S_FAILED);
90 return HI_ERR_CIPHER_MEMCPY_S_FAILED;
91 }
92 aead->ivlen = ivlen;
93 hi_log_debug("ivlen %u\n", ivlen);
94 }
95
96 hi_log_func_exit();
97 return HI_SUCCESS;
98 }
99
ext_mbedtls_aead_setkey(hi_void * ctx,const hi_u8 * fkey,const hi_u8 * skey,hi_u32 * hisi_klen)100 hi_s32 ext_mbedtls_aead_setkey(hi_void *ctx, const hi_u8 *fkey, const hi_u8 *skey, hi_u32 *hisi_klen)
101 {
102 hi_u32 klen;
103 ext_aead_context *aead = ctx;
104
105 hi_log_func_enter();
106
107 hi_log_chk_param_return(aead == HI_NULL);
108 hi_log_chk_param_return(fkey == HI_NULL);
109 hi_log_chk_param_return(hisi_klen == HI_NULL);
110
111 switch (*hisi_klen) {
112 case HI_CIPHER_KEY_AES_128BIT:
113 klen = AES_KEY_128BIT;
114 break;
115 case HI_CIPHER_KEY_AES_192BIT:
116 klen = AES_KEY_192BIT;
117 break;
118 case HI_CIPHER_KEY_AES_256BIT:
119 klen = AES_KEY_256BIT;
120 break;
121 default:
122 hi_log_error("Invalid aes key len: %u\n", *hisi_klen);
123 hi_log_print_err_code(HI_ERR_CIPHER_INVALID_PARAM);
124 return HI_ERR_CIPHER_INVALID_PARAM;
125 }
126 hi_log_info("key len %u, type %u\n", klen, *hisi_klen);
127
128 if (memcpy_s(aead->key, SYMC_KEY_SIZE, fkey, klen) != EOK) {
129 hi_log_print_func_err(memcpy_s, HI_ERR_CIPHER_MEMCPY_S_FAILED);
130 return HI_ERR_CIPHER_MEMCPY_S_FAILED;
131 }
132 aead->klen = klen;
133 *hisi_klen = klen;
134
135 hi_log_func_exit();
136 return HI_SUCCESS;
137 }
138
ext_mbedtls_aead_set_aad(hi_void * ctx,compat_addr aad,hi_u32 alen,hi_u32 tlen)139 hi_s32 ext_mbedtls_aead_set_aad(hi_void *ctx, compat_addr aad, hi_u32 alen, hi_u32 tlen)
140 {
141 ext_aead_context *aead = ctx;
142
143 hi_log_func_enter();
144
145 hi_log_chk_param_return(aead == HI_NULL);
146
147 aead->aad = aad;
148 aead->alen = alen;
149 aead->tlen = tlen;
150
151 hi_log_func_exit();
152 return HI_SUCCESS;
153 }
154
ext_mbedtls_aead_get_tag(hi_void * ctx,hi_u32 tag[AEAD_TAG_SIZE_IN_WORD],hi_u32 * taglen)155 hi_s32 ext_mbedtls_aead_get_tag(hi_void *ctx, hi_u32 tag[AEAD_TAG_SIZE_IN_WORD], hi_u32 *taglen)
156 {
157 ext_aead_context *aead = ctx;
158
159 hi_log_func_enter();
160
161 hi_log_chk_param_return(aead == HI_NULL);
162 hi_log_chk_param_return(*taglen < aead->tlen);
163
164 hi_log_debug("tag buffer len %u, tag len %u\n", *taglen, aead->tlen);
165
166 *taglen = aead->tlen;
167
168 if (memcpy_s(tag, AEAD_TAG_SIZE, aead->tag, aead->tlen) != EOK) {
169 hi_log_print_func_err(memcpy_s, HI_ERR_CIPHER_MEMCPY_S_FAILED);
170 return HI_ERR_CIPHER_MEMCPY_S_FAILED;
171 }
172
173 hi_log_func_exit();
174 return HI_SUCCESS;
175 }
176
ext_ccm_gcm_mem_open(ext_ccm_gcm_mem * mem,symc_multi_pack * pack,compat_addr aad,hi_u32 aad_len)177 static hi_s32 ext_ccm_gcm_mem_open(ext_ccm_gcm_mem *mem, symc_multi_pack *pack, compat_addr aad, hi_u32 aad_len)
178 {
179 hi_s32 ret;
180
181 ret = crypto_mem_open(&mem->in, pack->in[0], pack->len[0]);
182 if (ret != HI_SUCCESS) {
183 hi_log_print_func_err(crypto_mem_open, ret);
184 return ret;
185 }
186
187 ret = crypto_mem_open(&mem->out, pack->out[0], pack->len[0]);
188 if (ret != HI_SUCCESS) {
189 hi_log_print_func_err(crypto_mem_open, ret);
190 (hi_void)crypto_mem_close(&mem->in);
191 return ret;
192 }
193
194 ret = crypto_mem_open(&mem->aad, aad, aad_len);
195 if (ret != HI_SUCCESS) {
196 hi_log_print_func_err(crypto_mem_open, ret);
197 (hi_void)crypto_mem_close(&mem->out);
198 (hi_void)crypto_mem_close(&mem->in);
199 return ret;
200 }
201
202 return HI_SUCCESS;
203 }
204
ext_ccm_gcm_mem_close(ext_ccm_gcm_mem * mem)205 static hi_s32 ext_ccm_gcm_mem_close(ext_ccm_gcm_mem *mem)
206 {
207 hi_s32 ret;
208
209 ret = crypto_mem_close(&mem->aad);
210 if (ret != HI_SUCCESS) {
211 hi_log_print_func_err(crypto_mem_close, ret);
212 (hi_void)crypto_mem_close(&mem->out);
213 (hi_void)crypto_mem_close(&mem->in);
214 return ret;
215 }
216
217 ret = crypto_mem_close(&mem->out);
218 if (ret != HI_SUCCESS) {
219 hi_log_print_func_err(crypto_mem_close, ret);
220 (hi_void)crypto_mem_close(&mem->in);
221 return ret;
222 }
223
224 ret = crypto_mem_close(&mem->in);
225 if (ret != HI_SUCCESS) {
226 hi_log_print_func_err(crypto_mem_close, ret);
227 return ret;
228 }
229
230 return HI_SUCCESS;
231 }
232
ext_mbedtls_aead_ccm_crypto(hi_void * ctx,hi_u32 operation,symc_multi_pack * pack,hi_u32 last)233 hi_s32 ext_mbedtls_aead_ccm_crypto(hi_void *ctx, hi_u32 operation, symc_multi_pack *pack, hi_u32 last)
234 {
235 hi_s32 ret, ret_err;
236 ext_aead_context *aead = ctx;
237 mbedtls_ccm_context ccm;
238 ext_ccm_gcm_mem mem;
239
240 hi_log_func_enter();
241
242 hi_log_chk_param_return((aead == HI_NULL) || (pack == HI_NULL));
243 hi_log_chk_param_return((pack->num != 1) || (pack->len == HI_NULL));
244
245 (hi_void)memset_s(&mem, sizeof(ext_ccm_gcm_mem), 0, sizeof(ext_ccm_gcm_mem));
246 (hi_void)memset_s(&ccm, sizeof(mbedtls_ccm_context), 0, sizeof(mbedtls_ccm_context));
247
248 ret = ext_ccm_gcm_mem_open(&mem, pack, aead->aad, aead->alen);
249 if (ret != HI_SUCCESS) {
250 hi_log_print_func_err(ext_ccm_gcm_mem_open, ret);
251 return ret;
252 }
253
254 mbedtls_ccm_init(&ccm);
255
256 hi_log_debug("aead 0x%pK, klen len: %u\n", aead, aead->klen);
257
258 ret = mbedtls_ccm_setkey(&ccm, MBEDTLS_CIPHER_ID_AES, (hi_u8 *)aead->key, aead->klen * BITS_IN_BYTE);
259 if (ret != HI_SUCCESS) {
260 hi_log_print_func_err(mbedtls_ccm_setkey, ret);
261 goto error0;
262 }
263
264 if (operation) {
265 ret = mbedtls_ccm_auth_decrypt(&ccm, pack->len[0], (hi_u8 *)aead->iv, aead->ivlen, crypto_mem_virt(&mem.aad),
266 aead->alen, crypto_mem_virt(&mem.in), crypto_mem_virt(&mem.out), (hi_u8 *)aead->tag, aead->tlen);
267 if (ret != HI_SUCCESS) {
268 hi_log_print_func_err(mbedtls_ccm_auth_decrypt, ret);
269 }
270 } else {
271 ret = mbedtls_ccm_encrypt_and_tag(&ccm, pack->len[0], (hi_u8 *)aead->iv, aead->ivlen, crypto_mem_virt(&mem.aad),
272 aead->alen, crypto_mem_virt(&mem.in), crypto_mem_virt(&mem.out), (hi_u8 *)aead->tag, aead->tlen);
273 if (ret != HI_SUCCESS) {
274 hi_log_print_func_err(mbedtls_ccm_encrypt_and_tag, ret);
275 }
276 }
277
278 hi_log_func_exit();
279
280 error0:
281 mbedtls_ccm_free(&ccm);
282 ret_err = ext_ccm_gcm_mem_close(&mem);
283 if (ret_err != HI_SUCCESS) {
284 hi_log_print_func_err(ext_ccm_gcm_mem_close, ret_err);
285 }
286 return ret;
287 }
288
ext_mbedtls_aead_gcm_crypto(hi_void * ctx,hi_u32 operation,symc_multi_pack * pack,hi_u32 last)289 hi_s32 ext_mbedtls_aead_gcm_crypto(hi_void *ctx, hi_u32 operation, symc_multi_pack *pack, hi_u32 last)
290 {
291 hi_s32 ret, ret_err;
292 ext_aead_context *aead = ctx;
293 mbedtls_gcm_context *gcm = HI_NULL;
294 ext_ccm_gcm_mem mem;
295
296 hi_log_func_enter();
297
298 hi_log_chk_param_return((aead == HI_NULL) || (pack == HI_NULL));
299 hi_log_chk_param_return((pack->num != 1) || (pack->len == HI_NULL));
300
301 (hi_void)memset_s(&mem, sizeof(mem), 0, sizeof(mem));
302
303 gcm = crypto_calloc(1, sizeof(mbedtls_gcm_context));
304 if (gcm == HI_NULL) {
305 hi_log_print_func_err(crypto_calloc, HI_ERR_CIPHER_FAILED_MEM);
306 return HI_ERR_CIPHER_FAILED_MEM;
307 }
308
309 ret = ext_ccm_gcm_mem_open(&mem, pack, aead->aad, aead->alen);
310 if (ret != HI_SUCCESS) {
311 hi_log_print_func_err(ext_ccm_gcm_mem_open, ret);
312 goto error0;
313 }
314
315 mbedtls_gcm_init(gcm);
316
317 ret = mbedtls_gcm_setkey(gcm, MBEDTLS_CIPHER_ID_AES, (hi_u8 *)aead->key, aead->klen * BITS_IN_BYTE);
318 if (ret != HI_SUCCESS) {
319 hi_log_print_func_err(mbedtls_gcm_setkey, ret);
320 goto error1;
321 }
322
323 ret = mbedtls_gcm_starts(gcm, operation ? MBEDTLS_DECRYPT : MBEDTLS_ENCRYPT, (hi_u8 *)aead->iv, aead->ivlen,
324 crypto_mem_virt(&mem.aad), aead->alen);
325 if (ret != HI_SUCCESS) {
326 hi_log_print_func_err(mbedtls_gcm_starts, ret);
327 goto error1;
328 }
329
330 ret = mbedtls_gcm_update(gcm, pack->len[0], crypto_mem_virt(&mem.in), crypto_mem_virt(&mem.out));
331 if (ret != HI_SUCCESS) {
332 hi_log_print_func_err(mbedtls_gcm_update, ret);
333 goto error1;
334 }
335
336 ret = mbedtls_gcm_finish(gcm, (hi_u8 *)aead->tag, aead->tlen);
337
338 error1:
339 mbedtls_gcm_free(gcm);
340 ret_err = ext_ccm_gcm_mem_close(&mem);
341 if (ret_err != HI_SUCCESS) {
342 hi_log_print_func_err(ext_ccm_gcm_mem_close, ret_err);
343 }
344
345 error0:
346 crypto_free(gcm);
347 gcm = HI_NULL;
348 return ret;
349 }
350
351 #endif /* End of SOFT_AES_CCM_GCM_SUPPORT */
352