]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/aes/ck_aes.c
Introduce a port for T-HEAD CK802. A simple demo for T-HEAD CB2201 is also included.
[freertos] / FreeRTOS / Demo / T-HEAD_CB2201_CDK / csi / csi_driver / csky / common / aes / ck_aes.c
1 /*
2  * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /******************************************************************************
18  * @file     ck_aes.c
19  * @brief    CSI Source File for aes driver
20  * @version  V1.0
21  * @date     02. June 2017
22  ******************************************************************************/
23 #include <string.h>
24 #include "csi_core.h"
25 #include "drv_aes.h"
26 #include "ck_aes.h"
27
28 #define ERR_AES(errno) (CSI_DRV_ERRNO_AES_BASE | errno)
29 #define AES_NULL_PARA_CHK(para)                         \
30         do {                                        \
31             if (para == NULL) {                     \
32                 return ERR_AES(EDRV_PARAMETER);   \
33             }                                       \
34         } while (0)
35 static ck_aes_reg_t *aes_reg = NULL;
36 volatile static uint8_t block_cal_done = 0;
37
38 typedef struct {
39     uint32_t base;
40     uint32_t irq;
41     void *iv;
42     uint8_t *result_out;
43     uint32_t len;
44     aes_event_cb_t cb;
45     aes_mode_e mode;
46     aes_key_len_bits_e keylen;
47     aes_endian_mode_e endian;
48     aes_crypto_mode_e enc;
49     aes_status_t status;
50 } ck_aes_priv_t;
51
52 extern int32_t target_get_aes_count(void);
53 extern int32_t target_get_aes(int32_t idx, uint32_t *base, uint32_t *irq);
54
55 static ck_aes_priv_t aes_handle[CONFIG_AES_NUM];
56
57 /* Driver Capabilities */
58 static const aes_capabilities_t driver_capabilities = {
59     .ecb_mode = 1, /* ECB mode */
60     .cbc_mode = 1, /* CBC mode */
61     .cfb_mode = 0, /* CFB mode */
62     .ofb_mode = 0, /* OFB mode */
63     .ctr_mode = 0, /* CTR mode */
64     .bits_128 = 1, /* 128bits key length mode */
65     .bits_192 = 1, /* 192bits key lenght mode */
66     .bits_256 = 1  /* 256bits key length mode */
67 };
68
69 extern int32_t target_get_aes(int32_t idx, uint32_t *base, uint32_t *irq);
70 extern int32_t target_get_aes_count(void);
71 //
72 // Functions
73 //
74
75 static inline void aes_set_opcode(aes_crypto_mode_e opcode)
76 {
77     aes_reg->ctrl &= ~(3 << AES_OPCODE_OFFSET);          //clear bit[7:6]
78     aes_reg->ctrl |= (opcode << AES_OPCODE_OFFSET);    //set opcode
79 }
80
81 static inline void aes_set_endian(aes_endian_mode_e endian)
82 {
83     if (endian == AES_ENDIAN_LITTLE) {
84         aes_reg->ctrl &= ~AES_LITTLE_ENDIAN;
85     } else {
86         aes_reg->ctrl |= AES_LITTLE_ENDIAN;
87     }
88 }
89
90 static inline uint32_t aes_set_keylen(aes_key_len_bits_e keylength)
91 {
92     aes_reg->ctrl &= ~(3 << AES_KEY_LEN_OFFSET);        //clear bit[5:4]
93     aes_reg->ctrl |= (keylength << AES_KEY_LEN_OFFSET);// Set key length
94
95     return 0;
96 }
97
98 static inline void aes_set_mode(aes_mode_e mode)
99 {
100     aes_reg->ctrl &= ~(1 << AES_MODE_OFFSET);      //clear bit 3
101     aes_reg->ctrl |= (mode << AES_MODE_OFFSET);  //set mode
102 }
103
104 static inline void aes_enable(void)
105 {
106     aes_reg->ctrl |= (1 << AES_WORK_ENABLE_OFFSET);
107 }
108
109 static inline void aes_disable(void)
110 {
111     aes_reg->ctrl &= ~(1 << AES_WORK_ENABLE_OFFSET);
112 }
113
114 static inline void aes_enable_interrupt(void)
115 {
116     aes_reg->ctrl |= (1 << AES_INT_ENABLE_OFFSET);
117 }
118
119 static inline void aes_disable_interrupt(void)
120 {
121     aes_reg->ctrl &= ~(1 << AES_INT_ENABLE_OFFSET);
122 }
123
124 static inline void aes_clear_interrupt(void)
125 {
126     aes_reg->state = 0x0;
127 }
128
129 static inline uint32_t aes_get_intstatus(uint32_t AES_IT)
130 {
131     return (aes_reg->state & AES_IT) ? 1 : 0;
132 }
133
134 static void aes_set_key(void *context, uint8_t *key, aes_key_len_bits_e keylen, uint32_t enc, uint32_t endian)
135 {
136     uint8_t keynum = 0;
137
138     if (keylen == AES_KEY_LEN_BITS_128) {
139         keynum = 4;
140     } else if (keylen == AES_KEY_LEN_BITS_192) {
141         keynum = 6;
142     } else if (keylen == AES_KEY_LEN_BITS_256) {
143         keynum = 8;
144     }
145
146     uint32_t i;
147     uint32_t temp = 0;
148     /* set key according to the endian mode */
149     if (endian == AES_ENDIAN_LITTLE) {
150         for (i = 0; i < keynum; i++) {
151             temp = key[3] << 24 | key[2] << 16 | key[1] << 8 | key[0];
152             aes_reg->key[keynum - 1 - i] = temp;
153             key += 4;
154         }
155     } else if (endian == AES_ENDIAN_BIG) {
156         for (i = 0; i < keynum; i++) {
157             temp = key[3] << 24 | key[2] << 16 | key[1] << 8 | key[0];
158             aes_reg->key[i] = temp;
159             key += 4;
160         }
161     }
162
163     if (enc == AES_CRYPTO_MODE_DECRYPT) {
164         aes_set_opcode(AES_CRYPTO_KEYEXP);      /* if the mode is decrypt before decrypt you have to keyexpand */
165         aes_enable();
166 //        while(block_cal_done == 0);
167 //        block_cal_done = 0;
168
169         while (aes_get_intstatus(AES_IT_KEYINT));
170
171         aes_set_opcode(AES_CRYPTO_MODE_DECRYPT);
172     } else if (enc == AES_CRYPTO_MODE_ENCRYPT) {
173         aes_set_opcode(AES_CRYPTO_MODE_ENCRYPT);
174     }
175
176     aes_disable();
177 }
178
179 static void aes_set_iv(uint32_t mode, uint32_t endian, uint8_t *iv)
180 {
181     uint32_t temp;
182     uint32_t i;
183     /* set iv if the mode is CBC */
184     if (mode == AES_MODE_CBC) {
185         if (endian == AES_ENDIAN_BIG) {
186             for (i = 0; i < 4; i++) {
187                 temp = iv[3] << 24 | iv[2] << 16 | iv[1] << 8 | iv[0];
188                 aes_reg->iv[i] = temp;
189                 iv += 4;
190             }
191         } else if (endian == AES_ENDIAN_LITTLE) {
192             for (i = 0; i < 4; i++) {
193                 temp = iv[3] << 24 | iv[2] << 16 | iv[1] << 8 | iv[0];
194                 aes_reg->iv[3 - i] = temp;
195                 iv += 4;
196             }
197         }
198     }
199 }
200
201 static int aes_crypto(void *context, uint8_t *in, uint8_t *out,
202                uint32_t len, uint8_t *iv, uint32_t mode, uint32_t endian, uint32_t enc)
203 {
204
205     uint32_t temp[4];
206     aes_set_iv(mode, endian, iv);
207
208     uint32_t i = 0;
209     uint32_t j = 0;
210     /* set the text before aes calculating */
211     for (i = 0; i < len; i = i + 16) {
212         for (j = 0; j < 4; j++) {
213             temp[j] = in[3] << 24 | in[2] << 16 | in[1] << 8 | in[0];
214             if (endian == AES_ENDIAN_BIG) {
215                 aes_reg->datain[j] = temp[j];
216             } else if (endian == AES_ENDIAN_LITTLE) {
217                 aes_reg->datain[3 - j] = temp[j];
218             }
219
220             in += 4;
221         }
222         aes_enable();
223
224         while(block_cal_done == 0);
225         block_cal_done = 0;
226
227         if (enc == AES_CRYPTO_MODE_ENCRYPT && mode == AES_MODE_CBC) {
228             aes_set_iv(mode, endian, out);
229             memcpy(iv, out, 16);
230             out += 16;
231         } else if (enc == AES_CRYPTO_MODE_DECRYPT && mode == AES_MODE_CBC) {
232             aes_set_iv(mode, endian, (uint8_t *)&temp);
233             memcpy(iv, temp, 16);
234         }
235     }
236
237     return 0;
238 }
239
240 void ck_aes_irqhandler(int32_t idx)
241 {
242     ck_aes_priv_t *aes_priv = &aes_handle[idx];
243
244     volatile uint32_t j;
245     uint32_t tmp = 0;
246     /* get the result after aes calculating*/
247     if (aes_priv->result_out != NULL) {
248         for (j = 0; j < 4; j++) {
249             if (aes_priv->endian == AES_ENDIAN_BIG) {
250                 tmp = aes_reg->dataout[j];
251             } else if (aes_priv->endian == AES_ENDIAN_LITTLE) {
252                 tmp = aes_reg->dataout[3 - j];
253             }
254
255             memcpy(aes_priv->result_out, &tmp, 4);
256             aes_priv->result_out += 4;
257             aes_priv->len -= 4;
258         }
259     }
260
261     block_cal_done = 1;
262     /* disable aes and clear the aes interrupt */
263     aes_disable();
264     aes_clear_interrupt();
265
266     /* execute the callback function */
267     if (aes_priv->len == 0) {
268         if (aes_priv->cb) {
269             aes_priv->cb(AES_EVENT_CRYPTO_COMPLETE);
270         }
271     }
272 }
273
274 /**
275   \brief       get aes instance count.
276   \return      aes handle count
277 */
278 int32_t csi_aes_get_instance_count(void)
279 {
280     return target_get_aes_count();
281 }
282
283 /**
284   \brief       Initialize AES Interface. 1. Initializes the resources needed for the AES interface 2.registers event callback function
285   \param[in]   idx must not exceed return value of csi_aes_get_instance_count().
286   \param[in]   cb_event  Pointer to \ref aes_event_cb_t
287   \return      return aes handle if success
288 */
289 aes_handle_t csi_aes_initialize(int32_t idx, aes_event_cb_t cb_event)
290 {
291
292     if (idx < 0 || idx >= CONFIG_AES_NUM) {
293         return NULL;
294     }
295
296     uint32_t irq = 0u;
297     uint32_t base = 0u;
298     /* obtain the aes information */
299     int32_t real_idx = target_get_aes(idx, &base, &irq);
300
301     if (real_idx != idx) {
302         return NULL;
303     }
304
305     ck_aes_priv_t *aes_priv = &aes_handle[idx];
306
307     aes_priv->base = base;
308     aes_priv->irq  = irq;
309
310     /* initialize the aes context */
311     aes_reg = (ck_aes_reg_t *)(aes_priv->base);
312     aes_priv->cb = cb_event;
313     aes_priv->iv = NULL;
314     aes_priv->len = 16;
315     aes_priv->result_out = NULL;
316     aes_priv->mode = AES_MODE_CBC;
317     aes_priv->keylen = AES_KEY_LEN_BITS_128;
318     aes_priv->endian = AES_ENDIAN_LITTLE;
319     aes_priv->status.busy = 0;
320
321     aes_enable_interrupt();             /* enable the aes interrupt */
322
323     drv_nvic_enable_irq(aes_priv->irq); /* enable the aes bit in nvic */
324
325     return (aes_handle_t)aes_priv;
326 }
327
328 /**
329   \brief       De-initialize AES Interface. stops operation and releases the software resources used by the interface
330   \param[in]   handle  aes handle to operate.
331   \return      error code
332 */
333 int32_t csi_aes_uninitialize(aes_handle_t handle)
334 {
335     AES_NULL_PARA_CHK(handle);
336
337     ck_aes_priv_t *aes_priv = handle;
338     aes_priv->cb = NULL;
339
340     aes_disable_interrupt();            /* disable the aes interrupt */
341
342     drv_nvic_disable_irq(aes_priv->irq);
343
344     return 0;
345 }
346
347 /**
348   \brief       Get driver capabilities.
349   \param[in]   handle  aes handle to operate.
350   \return      \ref aes_capabilities_t
351 */
352 aes_capabilities_t csi_aes_get_capabilities(aes_handle_t handle)
353 {
354     return driver_capabilities;
355 }
356
357 /**
358   \brief       config aes mode.
359   \param[in]   handle  aes handle to operate.
360   \param[in]   mode      \ref aes_mode_e
361   \param[in]   keylen_bits \ref aes_key_len_bits_e
362   \param[in]   endian    \ref aes_endian_mode_e
363   \param[in]   arg       Pointer to the iv address when mode is cbc_mode
364   \return      error code
365 */
366 int32_t csi_aes_config(aes_handle_t handle, aes_mode_e mode, aes_key_len_bits_e keylen_bits, aes_endian_mode_e endian, uint32_t arg)
367 {
368     AES_NULL_PARA_CHK(handle);
369
370     ck_aes_priv_t *aes_priv = handle;
371     aes_reg = (ck_aes_reg_t *)(aes_priv->base);
372
373     /* config the aes mode */
374     switch (mode) {
375         case AES_MODE_CBC:
376             aes_priv->iv = (void *)arg;
377             aes_priv->mode = mode;
378             aes_set_mode(mode);
379             break;
380
381         case AES_MODE_ECB:
382             aes_priv->mode = mode;
383             aes_set_mode(mode);
384             break;
385
386         case AES_MODE_CFB:
387         case AES_MODE_OFB:
388         case AES_MODE_CTR:
389             return ERR_AES(EDRV_UNSUPPORTED);
390
391         default:
392             return ERR_AES(EDRV_PARAMETER);
393     }
394
395     /* config the key length */
396     switch (keylen_bits) {
397         case AES_KEY_LEN_BITS_128:
398         case AES_KEY_LEN_BITS_192:
399         case AES_KEY_LEN_BITS_256:
400             aes_priv->keylen = keylen_bits;
401             aes_set_keylen(keylen_bits);
402             break;
403
404         default:
405             return ERR_AES(EDRV_PARAMETER);
406     }
407
408     /* config the endian mode */
409     switch (endian) {
410         case AES_ENDIAN_LITTLE:
411             aes_priv->endian = endian;
412             aes_set_endian(endian);
413             break;
414
415         case AES_ENDIAN_BIG:
416             aes_priv->endian = endian;
417             aes_set_endian(endian);
418             break;
419
420         default:
421             return ERR_AES(EDRV_PARAMETER);
422     }
423
424     return 0;
425 }
426
427 /**
428   \brief       set crypto key.
429   \param[in]   handle    aes handle to operate.
430   \param[in]   context   aes information context(NULL when hardware implementation)
431   \param[in]   key       Pointer to the key buf
432   \param[in]   key_len   Pointer to the aes_key_len_bits_e
433   \param[in]   enc       \ref aes_crypto_mode_e
434   \return      error code
435 */
436 int32_t csi_aes_set_key(aes_handle_t handle, void *context, void *key, aes_key_len_bits_e key_len, aes_crypto_mode_e enc)
437 {
438     AES_NULL_PARA_CHK(handle);
439     AES_NULL_PARA_CHK(key);
440     if ((key_len != AES_KEY_LEN_BITS_128 &&
441         key_len != AES_KEY_LEN_BITS_192 &&
442         key_len != AES_KEY_LEN_BITS_256) ||
443         (enc != AES_CRYPTO_MODE_ENCRYPT &&
444         enc != AES_CRYPTO_MODE_DECRYPT)) {
445         return ERR_AES(EDRV_PARAMETER);
446     }
447
448     ck_aes_priv_t *aes_priv = handle;
449     aes_priv->enc = enc;
450     aes_set_key(context, key, key_len, enc, aes_priv->endian);
451
452     return 0;
453 }
454
455 /**
456   \brief       encrypt or decrypt
457   \param[in]   handle  aes handle to operate.
458   \param[in]   context aes information context(NULL when hardware implementation)
459   \param[in]   in   Pointer to the Source data
460   \param[out]  out  Pointer to the Result data.
461   \param[in]   len  the Source data len.
462   \param[in]   padding \ref aes_padding_mode_e.
463   \return      error code
464 */
465 int32_t csi_aes_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len, aes_padding_mode_e padding)
466 {
467     AES_NULL_PARA_CHK(handle);
468     AES_NULL_PARA_CHK(in);
469     AES_NULL_PARA_CHK(out);
470     AES_NULL_PARA_CHK(len);
471
472     ck_aes_priv_t *aes_priv = handle;
473
474     aes_priv->status.busy = 1;
475
476     uint8_t left_len = len & 0xf;
477     switch (padding) {
478         case AES_PADDING_MODE_NO:
479             if (left_len) {
480                 return ERR_AES(EDRV_PARAMETER);
481             }
482
483             /* crypto in padding no mode */
484             aes_priv->result_out = out;
485             aes_priv->len = len;
486             aes_crypto(context, in, out, len, aes_priv->iv, aes_priv->mode, aes_priv->endian, aes_priv->enc);
487             break;
488
489         case AES_PADDING_MODE_ZERO:
490             if (left_len == 0) {
491                 return ERR_AES(EDRV_PARAMETER);
492             }
493
494             uint8_t i = 0;
495             for (i = 0; i < (16 - left_len); i++) {
496                 *((uint8_t *)in + len + i) = 0x0;
497             }
498
499             /* crypto in padding zero mode */
500             aes_priv->result_out = out;
501             aes_priv->len = len + 16 -left_len;
502             aes_crypto(context, in, out, len + 16 - left_len, aes_priv->iv, aes_priv->mode, aes_priv->endian, aes_priv->enc);
503             break;
504
505         case AES_PADDING_MODE_PKCS5:
506             return ERR_AES(EDRV_UNSUPPORTED);
507
508         default:
509             return ERR_AES(EDRV_PARAMETER);
510     }
511
512     aes_priv->status.busy = 0;
513     return 0;
514 }
515
516 /**
517   \brief       Get AES status.
518   \param[in]   handle  aes handle to operate.
519   \return      AES status \ref aes_status_t
520 */
521 aes_status_t csi_aes_get_status(aes_handle_t handle)
522 {
523     ck_aes_priv_t *aes_priv = handle;
524     return aes_priv->status;
525 }