1 /*
2  * Copyright (c) 2006-2022, Synwit Technology Co.,Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2021-07-01     lik          first version
9  */
10 
11 #include "drv_crypto.h"
12 #include <string.h>
13 
14 #ifdef RT_USING_HWCRYPTO
15 
16 //#define DRV_DEBUG
17 #define LOG_TAG "drv.crypto"
18 #include <drv_log.h>
19 
20 struct swm_hwcrypto_device
21 {
22     struct rt_hwcrypto_device dev;
23     struct rt_mutex mutex;
24 };
25 
26 static struct swm_hwcrypto_device hwcrypto_obj;
27 
28 #ifdef BSP_USING_CRC
29 
30 struct swm_crc_cfg
31 {
32     CRC_TypeDef *CRCx;
33     CRC_InitStructure CRC_initstruct;
34 };
35 
36 static struct hwcrypto_crc_cfg swm_crc_cfg;
37 
swm_crc_update(struct hwcrypto_crc * ctx,const rt_uint8_t * in,rt_size_t length)38 static rt_uint32_t swm_crc_update(struct hwcrypto_crc *ctx, const rt_uint8_t *in, rt_size_t length)
39 {
40     rt_uint32_t result = 0;
41     struct swm_hwcrypto_device *hwcrypto_dev = (struct swm_hwcrypto_device *)ctx->parent.device->user_data;
42 
43     struct swm_crc_cfg *crc_cfg = (struct swm_crc_cfg *)(ctx->parent.contex);
44 
45     rt_mutex_take(&hwcrypto_dev->mutex, RT_WAITING_FOREVER);
46 
47     if (memcmp(&swm_crc_cfg, &ctx->crc_cfg, sizeof(struct hwcrypto_crc_cfg)) != 0)
48     {
49         crc_cfg->CRCx = CRC;
50 
51         crc_cfg->CRC_initstruct.init_crc = ctx->crc_cfg.last_val;
52 
53         switch (ctx->crc_cfg.poly)
54         {
55         case 0x07:
56             crc_cfg->CRC_initstruct.Poly = CRC_POLY_107;
57             break;
58         case 0x1021:
59             crc_cfg->CRC_initstruct.Poly = CRC_POLY_11021;
60             break;
61         case 0x8005:
62             crc_cfg->CRC_initstruct.Poly = CRC_POLY_18005;
63             break;
64         case 0x04C11DB7:
65             crc_cfg->CRC_initstruct.Poly = CRC_POLY_104C11DB7;
66             break;
67         default:
68 
69             goto _exit;
70         }
71 
72         switch (ctx->crc_cfg.width)
73         {
74         case 8:
75             crc_cfg->CRC_initstruct.in_width = CRC_WIDTH_8;
76             break;
77         case 16:
78             crc_cfg->CRC_initstruct.in_width = CRC_WIDTH_16;
79             break;
80         case 32:
81             crc_cfg->CRC_initstruct.in_width = CRC_WIDTH_32;
82             break;
83         default:
84             goto _exit;
85         }
86 
87         switch (ctx->crc_cfg.flags)
88         {
89         case 0:
90             crc_cfg->CRC_initstruct.in_not = false;
91             crc_cfg->CRC_initstruct.out_not = false;
92             break;
93         case CRC_FLAG_REFIN:
94             crc_cfg->CRC_initstruct.in_not = true;
95             crc_cfg->CRC_initstruct.out_not = false;
96             break;
97         case CRC_FLAG_REFOUT:
98             crc_cfg->CRC_initstruct.in_not = false;
99             crc_cfg->CRC_initstruct.out_not = true;
100             break;
101         case CRC_FLAG_REFIN | CRC_FLAG_REFOUT:
102             crc_cfg->CRC_initstruct.in_not = true;
103             crc_cfg->CRC_initstruct.out_not = true;
104             break;
105         default:
106             goto _exit;
107         }
108 
109         crc_cfg->CRC_initstruct.in_rev = CRC_REV_NOT;
110         crc_cfg->CRC_initstruct.out_rev = CRC_REV_NOT;
111         CRC_Init(crc_cfg->CRCx, &(crc_cfg->CRC_initstruct));
112         memcpy(&swm_crc_cfg, &ctx->crc_cfg, sizeof(struct hwcrypto_crc_cfg));
113     }
114 
115     for (uint32_t i = 0; i < length; i++)
116         CRC_Write((uint32_t)in[i]);
117     result = CRC_Result();
118 
119     ctx->crc_cfg.last_val = result;
120 
121     swm_crc_cfg.last_val = ctx->crc_cfg.last_val;
122     result = (result ? result ^ (ctx->crc_cfg.xorout) : result);
123 
124 _exit:
125     rt_mutex_release(&hwcrypto_dev->mutex);
126 
127     return result;
128 }
129 
130 static const struct hwcrypto_crc_ops swm_crc_ops =
131     {
132         .update = swm_crc_update,
133 };
134 #endif /* BSP_USING_CRC */
135 
136 #if defined(BSP_USING_RNG)
137 
138 struct swm_rng_cfg
139 {
140     SYS_TypeDef *SYSx;
141 };
142 
swm_rng_update(struct hwcrypto_rng * ctx)143 static rt_uint32_t swm_rng_update(struct hwcrypto_rng *ctx)
144 {
145     rt_uint32_t gen_randoml = 0, gen_randomh = 0;
146 
147     struct swm_rng_cfg *rng_cfg = (struct swm_rng_cfg *)(ctx->parent.contex);
148 
149     while ((rng_cfg->SYSx->PRNGCR & SYS_PRNGCR_RDY_Msk) == 0)
150         __NOP();
151     gen_randoml = rng_cfg->SYSx->PRNGDL;
152     gen_randomh = rng_cfg->SYSx->PRNGDH;
153     return gen_randoml;
154 }
155 
156 static const struct hwcrypto_rng_ops swm_rng_ops =
157     {
158         .update = swm_rng_update,
159 };
160 #endif /* BSP_USING_RNG */
161 
swm_crypto_create(struct rt_hwcrypto_ctx * ctx)162 static rt_err_t swm_crypto_create(struct rt_hwcrypto_ctx *ctx)
163 {
164     rt_err_t res = RT_EOK;
165 
166     switch (ctx->type & HWCRYPTO_MAIN_TYPE_MASK)
167     {
168 #if defined(BSP_USING_CRC)
169     case HWCRYPTO_TYPE_CRC:
170     {
171         struct swm_crc_cfg *crc_cfg = rt_calloc(1, sizeof(struct swm_crc_cfg));
172         if (RT_NULL == crc_cfg)
173         {
174             res = -RT_ERROR;
175             break;
176         }
177 
178         ctx->contex = crc_cfg;
179         ((struct hwcrypto_crc *)ctx)->ops = &swm_crc_ops;
180         break;
181     }
182 #endif /* BSP_USING_CRC */
183 
184 #if defined(BSP_USING_RNG)
185     case HWCRYPTO_TYPE_RNG:
186     {
187         struct swm_rng_cfg *rng_cfg = rt_calloc(1, sizeof(struct swm_rng_cfg));
188         if (RT_NULL == rng_cfg)
189         {
190             res = -RT_ERROR;
191             break;
192         }
193         rng_cfg->SYSx = SYS;
194         rng_cfg->SYSx->HRCCR |= (1 << SYS_HRCCR_ON_Pos);
195         rng_cfg->SYSx->LRCCR |= (1 << SYS_LRCCR_ON_Pos);
196         rng_cfg->SYSx->PRNGCR = (0 << SYS_PRNGCR_CLR_Pos) |
197                              (3 << SYS_PRNGCR_MODE_Pos);
198         ctx->contex = rng_cfg;
199         ((struct hwcrypto_rng *)ctx)->ops = &swm_rng_ops;
200 
201         break;
202     }
203 #endif /* BSP_USING_RNG */
204 
205     default:
206         res = -RT_ERROR;
207         break;
208     }
209     return res;
210 }
211 
swm_crypto_destroy(struct rt_hwcrypto_ctx * ctx)212 static void swm_crypto_destroy(struct rt_hwcrypto_ctx *ctx)
213 {
214     struct swm_crc_cfg *crc_cfg = (struct swm_crc_cfg *)(ctx->contex);
215     switch (ctx->type & HWCRYPTO_MAIN_TYPE_MASK)
216     {
217 #if defined(BSP_USING_CRC)
218     case HWCRYPTO_TYPE_CRC:
219         crc_cfg->CRCx->CR &= ~CRC_CR_EN_Msk;
220         break;
221 #endif /* BSP_USING_CRC */
222 
223 #if defined(BSP_USING_RNG)
224     case HWCRYPTO_TYPE_RNG:
225         break;
226 #endif /* BSP_USING_RNG */
227 
228     default:
229         break;
230     }
231 
232     rt_free(ctx->contex);
233 }
234 
swm_crypto_clone(struct rt_hwcrypto_ctx * des,const struct rt_hwcrypto_ctx * src)235 static rt_err_t swm_crypto_clone(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src)
236 {
237     rt_err_t res = RT_EOK;
238 
239     switch (src->type & HWCRYPTO_MAIN_TYPE_MASK)
240     {
241 #if defined(BSP_USING_CRC)
242     case HWCRYPTO_TYPE_CRC:
243         if (des->contex && src->contex)
244         {
245             rt_memcpy(des->contex, src->contex, sizeof(struct swm_crc_cfg));
246         }
247         break;
248 #endif /* BSP_USING_CRC */
249 
250 #if defined(BSP_USING_RNG)
251     case HWCRYPTO_TYPE_RNG:
252         if (des->contex && src->contex)
253         {
254             rt_memcpy(des->contex, src->contex, sizeof(struct swm_rng_cfg));
255         }
256         break;
257 #endif /* BSP_USING_RNG */
258 
259     default:
260         res = -RT_ERROR;
261         break;
262     }
263     return res;
264 }
265 
swm_crypto_reset(struct rt_hwcrypto_ctx * ctx)266 static void swm_crypto_reset(struct rt_hwcrypto_ctx *ctx)
267 {
268     struct swm_crc_cfg *crc_cfg = (struct swm_crc_cfg *)(ctx->contex);
269     switch (ctx->type & HWCRYPTO_MAIN_TYPE_MASK)
270     {
271 #if defined(BSP_USING_CRC)
272     case HWCRYPTO_TYPE_CRC:
273         crc_cfg->CRCx->CR &= ~CRC_CR_EN_Msk;
274         break;
275 #endif /* BSP_USING_CRC */
276 
277 #if defined(BSP_USING_RNG)
278     case HWCRYPTO_TYPE_RNG:
279         break;
280 #endif /* BSP_USING_RNG */
281 
282     default:
283         break;
284     }
285 }
286 
287 static const struct rt_hwcrypto_ops swm_hwcrypto_ops =
288     {
289         .create = swm_crypto_create,
290         .destroy = swm_crypto_destroy,
291         .copy = swm_crypto_clone,
292         .reset = swm_crypto_reset,
293 };
294 
swm_crypto_init(void)295 int swm_crypto_init(void)
296 {
297     rt_uint32_t cpuid[2] = {0};
298 
299     hwcrypto_obj.dev.ops = &swm_hwcrypto_ops;
300 
301     cpuid[0] = SCB->CPUID;
302     hwcrypto_obj.dev.id = 0;
303     rt_memcpy(&hwcrypto_obj.dev.id, cpuid, 8);
304 
305     hwcrypto_obj.dev.user_data = &hwcrypto_obj;
306 
307     if (rt_hwcrypto_register(&hwcrypto_obj.dev, RT_HWCRYPTO_DEFAULT_NAME) != RT_EOK)
308     {
309         return -1;
310     }
311     rt_mutex_init(&hwcrypto_obj.mutex, RT_HWCRYPTO_DEFAULT_NAME, RT_IPC_FLAG_FIFO);
312     return 0;
313 }
314 INIT_BOARD_EXPORT(swm_crypto_init);
315 
316 #endif /* RT_USING_HWCRYPTO */
317