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