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