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