2 * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 /******************************************************************************
19 * @brief CSI Source File for aes driver
22 ******************************************************************************/
28 #define ERR_AES(errno) (CSI_DRV_ERRNO_AES_BASE | errno)
29 #define AES_NULL_PARA_CHK(para) \
32 return ERR_AES(EDRV_PARAMETER); \
35 static ck_aes_reg_t *aes_reg = NULL;
36 volatile static uint8_t block_cal_done = 0;
46 aes_key_len_bits_e keylen;
47 aes_endian_mode_e endian;
48 aes_crypto_mode_e enc;
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);
55 static ck_aes_priv_t aes_handle[CONFIG_AES_NUM];
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 */
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);
75 static inline void aes_set_opcode(aes_crypto_mode_e opcode)
77 aes_reg->ctrl &= ~(3 << AES_OPCODE_OFFSET); //clear bit[7:6]
78 aes_reg->ctrl |= (opcode << AES_OPCODE_OFFSET); //set opcode
81 static inline void aes_set_endian(aes_endian_mode_e endian)
83 if (endian == AES_ENDIAN_LITTLE) {
84 aes_reg->ctrl &= ~AES_LITTLE_ENDIAN;
86 aes_reg->ctrl |= AES_LITTLE_ENDIAN;
90 static inline uint32_t aes_set_keylen(aes_key_len_bits_e keylength)
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
98 static inline void aes_set_mode(aes_mode_e mode)
100 aes_reg->ctrl &= ~(1 << AES_MODE_OFFSET); //clear bit 3
101 aes_reg->ctrl |= (mode << AES_MODE_OFFSET); //set mode
104 static inline void aes_enable(void)
106 aes_reg->ctrl |= (1 << AES_WORK_ENABLE_OFFSET);
109 static inline void aes_disable(void)
111 aes_reg->ctrl &= ~(1 << AES_WORK_ENABLE_OFFSET);
114 static inline void aes_enable_interrupt(void)
116 aes_reg->ctrl |= (1 << AES_INT_ENABLE_OFFSET);
119 static inline void aes_disable_interrupt(void)
121 aes_reg->ctrl &= ~(1 << AES_INT_ENABLE_OFFSET);
124 static inline void aes_clear_interrupt(void)
126 aes_reg->state = 0x0;
129 static inline uint32_t aes_get_intstatus(uint32_t AES_IT)
131 return (aes_reg->state & AES_IT) ? 1 : 0;
134 static void aes_set_key(void *context, uint8_t *key, aes_key_len_bits_e keylen, uint32_t enc, uint32_t endian)
138 if (keylen == AES_KEY_LEN_BITS_128) {
140 } else if (keylen == AES_KEY_LEN_BITS_192) {
142 } else if (keylen == AES_KEY_LEN_BITS_256) {
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;
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;
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 */
166 // while(block_cal_done == 0);
167 // block_cal_done = 0;
169 while (aes_get_intstatus(AES_IT_KEYINT));
171 aes_set_opcode(AES_CRYPTO_MODE_DECRYPT);
172 } else if (enc == AES_CRYPTO_MODE_ENCRYPT) {
173 aes_set_opcode(AES_CRYPTO_MODE_ENCRYPT);
179 static void aes_set_iv(uint32_t mode, uint32_t endian, uint8_t *iv)
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;
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;
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)
206 aes_set_iv(mode, endian, iv);
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];
224 while(block_cal_done == 0);
227 if (enc == AES_CRYPTO_MODE_ENCRYPT && mode == AES_MODE_CBC) {
228 aes_set_iv(mode, endian, out);
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);
240 void ck_aes_irqhandler(int32_t idx)
242 ck_aes_priv_t *aes_priv = &aes_handle[idx];
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];
255 memcpy(aes_priv->result_out, &tmp, 4);
256 aes_priv->result_out += 4;
262 /* disable aes and clear the aes interrupt */
264 aes_clear_interrupt();
266 /* execute the callback function */
267 if (aes_priv->len == 0) {
269 aes_priv->cb(AES_EVENT_CRYPTO_COMPLETE);
275 \brief get aes instance count.
276 \return aes handle count
278 int32_t csi_aes_get_instance_count(void)
280 return target_get_aes_count();
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
289 aes_handle_t csi_aes_initialize(int32_t idx, aes_event_cb_t cb_event)
292 if (idx < 0 || idx >= CONFIG_AES_NUM) {
298 /* obtain the aes information */
299 int32_t real_idx = target_get_aes(idx, &base, &irq);
301 if (real_idx != idx) {
305 ck_aes_priv_t *aes_priv = &aes_handle[idx];
307 aes_priv->base = base;
310 /* initialize the aes context */
311 aes_reg = (ck_aes_reg_t *)(aes_priv->base);
312 aes_priv->cb = cb_event;
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;
321 aes_enable_interrupt(); /* enable the aes interrupt */
323 drv_nvic_enable_irq(aes_priv->irq); /* enable the aes bit in nvic */
325 return (aes_handle_t)aes_priv;
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.
333 int32_t csi_aes_uninitialize(aes_handle_t handle)
335 AES_NULL_PARA_CHK(handle);
337 ck_aes_priv_t *aes_priv = handle;
340 aes_disable_interrupt(); /* disable the aes interrupt */
342 drv_nvic_disable_irq(aes_priv->irq);
348 \brief Get driver capabilities.
349 \param[in] handle aes handle to operate.
350 \return \ref aes_capabilities_t
352 aes_capabilities_t csi_aes_get_capabilities(aes_handle_t handle)
354 return driver_capabilities;
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
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)
368 AES_NULL_PARA_CHK(handle);
370 ck_aes_priv_t *aes_priv = handle;
371 aes_reg = (ck_aes_reg_t *)(aes_priv->base);
373 /* config the aes mode */
376 aes_priv->iv = (void *)arg;
377 aes_priv->mode = mode;
382 aes_priv->mode = mode;
389 return ERR_AES(EDRV_UNSUPPORTED);
392 return ERR_AES(EDRV_PARAMETER);
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);
405 return ERR_AES(EDRV_PARAMETER);
408 /* config the endian mode */
410 case AES_ENDIAN_LITTLE:
411 aes_priv->endian = endian;
412 aes_set_endian(endian);
416 aes_priv->endian = endian;
417 aes_set_endian(endian);
421 return ERR_AES(EDRV_PARAMETER);
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
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)
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);
448 ck_aes_priv_t *aes_priv = handle;
450 aes_set_key(context, key, key_len, enc, aes_priv->endian);
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.
465 int32_t csi_aes_crypto(aes_handle_t handle, void *context, void *in, void *out, uint32_t len, aes_padding_mode_e padding)
467 AES_NULL_PARA_CHK(handle);
468 AES_NULL_PARA_CHK(in);
469 AES_NULL_PARA_CHK(out);
470 AES_NULL_PARA_CHK(len);
472 ck_aes_priv_t *aes_priv = handle;
474 aes_priv->status.busy = 1;
476 uint8_t left_len = len & 0xf;
478 case AES_PADDING_MODE_NO:
480 return ERR_AES(EDRV_PARAMETER);
483 /* crypto in padding no mode */
484 aes_priv->result_out = out;
486 aes_crypto(context, in, out, len, aes_priv->iv, aes_priv->mode, aes_priv->endian, aes_priv->enc);
489 case AES_PADDING_MODE_ZERO:
491 return ERR_AES(EDRV_PARAMETER);
495 for (i = 0; i < (16 - left_len); i++) {
496 *((uint8_t *)in + len + i) = 0x0;
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);
505 case AES_PADDING_MODE_PKCS5:
506 return ERR_AES(EDRV_UNSUPPORTED);
509 return ERR_AES(EDRV_PARAMETER);
512 aes_priv->status.busy = 0;
517 \brief Get AES status.
518 \param[in] handle aes handle to operate.
519 \return AES status \ref aes_status_t
521 aes_status_t csi_aes_get_status(aes_handle_t handle)
523 ck_aes_priv_t *aes_priv = handle;
524 return aes_priv->status;