/* * Copyright (c) 2019-2023 Beijing Hanwei Innovation Technology Ltd. Co. and * its subsidiaries and affiliates (collectly called MKSEMI). * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form, except as embedded into an MKSEMI * integrated circuit in a product or a software update for such product, * must reproduce the above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or other materials * provided with the distribution. * * 3. Neither the name of MKSEMI nor the names of its contributors may be used * to endorse or promote products derived from this software without * specific prior written permission. * * 4. This software, with or without modification, must only be used with a * MKSEMI integrated circuit. * * 5. Any software provided in binary form under this license must not be * reverse engineered, decompiled, modified and/or disassembled. * * THIS SOFTWARE IS PROVIDED BY MKSEMI "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL MKSEMI OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mk_aes.h" #include "mk_clock.h" #include "mk_reset.h" #include "mk_trace.h" #include "string.h" #if defined(__ICCARM__) && defined(XIP_EN) #pragma default_function_attributes = __ramfunc #endif #if AES_DMA_MODE_EN static void aes_dma_callback(void *ch, uint32_t err_code); #endif static struct AES_HANDLE_T aes_handle[AES_MAX_NUM] = { { .base = AES, .irq = AES_IRQn, .dma_in_ch = DMA_CH2, .dma_out_ch = DMA_CH3, .config = { .key = {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf}, .int_en = false, .dma_en = true, .din_burst_size = 1, .dout_burst_size = 1, }, }, }; #define MACTAG_IS_VALID(x) \ ((((aes_handle[x].base->CTRL1) & (AES_CTRL1_MODE(AES_MODE_CCM) | AES_CTRL1_DIR(AES_DIR_DECRYPT))) == \ (AES_CTRL1_MODE(AES_MODE_CCM) | AES_CTRL1_DIR(AES_DIR_DECRYPT))) \ ? (((aes_handle[x].base->STATUS) & AES_STATUS_MIC_VALID_MSK) ? (AES_MIN_VALID) : (AES_MIN_INVALID)) \ : (AES_MIN_INVALID)) int aes_open(enum AES_DEV_T id, struct AES_CFG_T *config) { if (id >= AES_MAX_NUM) { return DRV_ERROR; } else { // check if the AES is using by HW or not // enable AES clock clock_enable(CLOCK_AES); reset_module(RESET_MODULE_AES); } if (config) { memcpy(&aes_handle[id].config, config, sizeof(struct AES_CFG_T)); } #if AES_INT_MODE_EN if (aes_handle[id].config.int_en) { NVIC_SetPriority(aes_handle[id].irq, IRQ_PRIORITY_REALTIME); NVIC_ClearPendingIRQ(aes_handle[id].irq); NVIC_EnableIRQ(aes_handle[id].irq); } #endif aes_handle[id].state = AES_STATE_READY; return DRV_OK; } int aes_close(enum AES_DEV_T id) { if (id >= AES_MAX_NUM) { return DRV_ERROR; } // check if the AES is using by HW or not #if AES_INT_MODE_EN if (aes_handle[id].config.int_en) { NVIC_DisableIRQ(aes_handle[id].irq); NVIC_ClearPendingIRQ(aes_handle[id].irq); } #endif // disable AES clock clock_disable(CLOCK_AES); aes_handle[id].state = AES_STATE_RESET; return DRV_OK; } int aes_clear(enum AES_DEV_T id) { // clear AES aes_handle[id].base->CTRL0 = AES_CTRL0_CLEAR_MSK; if (aes_handle[id].state == AES_STATE_BUSY) { aes_handle[id].state = AES_STATE_READY; } return DRV_OK; } int aes_update_key(enum AES_DEV_T id, uint8_t key[16]) { memcpy(&aes_handle[id].config.key[0], key, 16); return DRV_OK; } void aes_set_state(enum AES_DEV_T id, enum AES_STATE_T state) { aes_handle[id].state |= state; } void aes_clr_state(enum AES_DEV_T id, enum AES_STATE_T state) { aes_handle[id].state &= ~state; } uint8_t aes_get_state(enum AES_DEV_T id) { return (uint8_t)aes_handle[id].state; } #if defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" #endif static int aes_engin_run(enum AES_DEV_T id, uint8_t *input, uint8_t *output, uint16_t input_len, uint16_t output_len) { uint32_t lock = int_lock(); // update state switch (aes_handle[id].state) { case AES_STATE_READY: aes_handle[id].state = AES_STATE_BUSY; break; case AES_STATE_BUSY: int_unlock(lock); return DRV_BUSY; case AES_STATE_BREAK: case AES_STATE_CONFLICT: case AES_STATE_RESET: case AES_STATE_TIMEOUT: case AES_STATE_ERROR: int_unlock(lock); return DRV_ERROR; } aes_handle[id].input = input; aes_handle[id].output = output; aes_handle[id].input_len = input_len; aes_handle[id].input_count = 0; aes_handle[id].output_len = output_len; aes_handle[id].output_count = 0; int_unlock(lock); // start AES engin aes_handle[id].base->CTRL0 = AES_CTRL0_START_MSK; if (aes_handle[id].config.dma_en) { #if AES_DMA_MODE_EN // enable DMA aes_handle[id].base->DMA_EN = AES_DMA_EN_DIN_DMA_EN_MSK | AES_DMA_EN_DOUT_DMA_EN_MSK | AES_DMA_EN_DIN_DMA_BURST_SIZE(aes_handle[id].config.din_burst_size) | AES_DMA_EN_DIUT_DMA_BURST_SIZE(aes_handle[id].config.dout_burst_size); struct DMA_CH_CFG_T aes_out_dma_cfg = { .fifo_th = DMA_FIFO_TH_1, .src_burst_size = DMA_SRC_BURST_SIZE_1, .src_width = DMA_WIDTH_1B, .dst_width = DMA_WIDTH_1B, .src_addr_ctrl = DMA_ADDR_FIXED, .dst_addr_ctrl = DMA_ADDR_INC, .src_req_sel = DMA_REQ_AES_TX, .dst_req_sel = DMA_REQ_MEM, }; dma_open(aes_handle[id].dma_out_ch, &aes_out_dma_cfg); dma_transfer(aes_handle[id].dma_out_ch, (uint8_t *)&aes_handle[id].base->DOUT, output, output_len, aes_dma_callback); struct DMA_CH_CFG_T aes_in_dma_cfg = { .fifo_th = DMA_FIFO_TH_1, .src_burst_size = DMA_SRC_BURST_SIZE_1, .src_width = DMA_WIDTH_1B, .dst_width = DMA_WIDTH_1B, .src_addr_ctrl = DMA_ADDR_INC, .dst_addr_ctrl = DMA_ADDR_FIXED, .src_req_sel = DMA_REQ_MEM, .dst_req_sel = DMA_REQ_AES_RX, }; dma_open(aes_handle[id].dma_in_ch, &aes_in_dma_cfg); // bump up DMA IRQ priority for calling AES from interrupt handler NVIC_SetPriority(DMA_IRQn, IRQ_PRIORITY_REALTIME); dma_transfer(aes_handle[id].dma_in_ch, input, (uint8_t *)&aes_handle[id].base->DIN, input_len, NULL); #endif } else if (aes_handle[id].config.int_en) { #if AES_INT_MODE_EN // write the first block data in uint32_t tx_free = GET_BIT_FIELD(aes_handle[id].base->STATUS, AES_STATUS_DIN_BUF_SPACE_MSK, AES_STATUS_DIN_BUF_SPACE_POS); uint8_t len = (uint8_t)MIN(tx_free, aes_handle[id].input_len - aes_handle[id].input_count); for (uint8_t i = 0; i < len; i++) { REG_WRITE_BYTE(&aes_handle[id].base->DIN, aes_handle[id].input[aes_handle[id].input_count + i]); } aes_handle[id].input_count += len; // enable interrupt aes_handle[id].base->INTR_EN = AES_INTR_EN_DONE_EN_MSK | AES_INTR_EN_DIN_OVERFLOW_EN_MSK | AES_INTR_EN_DIN_EMPTY_EN_MSK | AES_INTR_EN_DOUT_NOT_EMPTY_EN_MSK; #endif } else { #if AES_POLL_MODE_EN // polling while ((aes_handle[id].input_count < aes_handle[id].input_len) || (aes_handle[id].output_count < aes_handle[id].output_len)) { // write a block data in uint32_t tx_free = GET_BIT_FIELD(aes_handle[id].base->STATUS, AES_STATUS_DIN_BUF_SPACE_MSK, AES_STATUS_DIN_BUF_SPACE_POS); uint8_t len = (uint8_t)MIN(tx_free, aes_handle[id].input_len - aes_handle[id].input_count); for (uint8_t i = 0; i < len; i++) { REG_WRITE_BYTE(&aes_handle[id].base->DIN, aes_handle[id].input[aes_handle[id].input_count + i]); } aes_handle[id].input_count += len; // read a block result out uint32_t rx_cnt = GET_BIT_FIELD(aes_handle[id].base->STATUS, AES_STATUS_DOUT_BUF_CNT_MSK, AES_STATUS_DOUT_BUF_CNT_POS); len = (uint8_t)MIN(rx_cnt, aes_handle[id].output_len - aes_handle[id].output_count); for (uint8_t i = 0; i < len; i++) { aes_handle[id].output[aes_handle[id].output_count + i] = REG_READ_BYTE(&aes_handle[id].base->DOUT); } aes_handle[id].output_count += len; } uint8_t aes_state = aes_get_state(id); if (aes_state & AES_STATE_BREAK) { return DRV_ERROR; } else if (aes_state & AES_STATE_CONFLICT) { return DRV_ERROR; } aes_handle[id].is_valid = MACTAG_IS_VALID(id); // update state aes_handle[id].state = AES_STATE_READY; if (aes_handle[id].callback) { aes_handle[id].callback(&id, aes_handle[id].output_count); } #endif } return DRV_OK; } static int aes_encrypt(enum AES_DEV_T id, uint8_t *input, uint8_t *output, uint16_t input_len, uint16_t output_len) { aes_handle[id].base->CTRL1 &= ~AES_CTRL1_DIR_MSK; return aes_engin_run(id, input, output, input_len, output_len); } static int aes_decrypt(enum AES_DEV_T id, uint8_t *input, uint8_t *output, uint16_t input_len, uint16_t output_len) { aes_handle[id].base->CTRL1 |= AES_CTRL1_DIR_MSK; // derive decipher key aes_handle[id].base->CTRL0 = AES_CTRL0_CLEAR_MSK; // save CTRL1 register uint32_t ctrl1 = aes_handle[id].base->CTRL1; aes_handle[id].base->CTRL1 = AES_CTRL1_MODE(AES_MODE_DKEY); aes_handle[id].base->CTRL0 = AES_CTRL0_START_MSK; // wait decipher key ready, this is pretty fast. while ((aes_handle[id].base->STATUS & AES_STATUS_DONE_MSK) == 0) { } // restore CTRL1 aes_handle[id].base->CTRL0 = AES_CTRL0_CLEAR_MSK; aes_handle[id].base->CTRL1 = ctrl1; return aes_engin_run(id, input, output, input_len, output_len); } int aes_crypt_ecb(enum AES_DEV_T id, enum AES_DIR_T mode, uint8_t *input, uint8_t *output, uint16_t len, drv_callback_t callback) { ASSERT(output != NULL, "output address is NULL"); ASSERT(((len % 16) == 0) && (len >= 16), "len invalid"); aes_handle[id].callback = callback; // 1. clear AES aes_handle[id].base->CTRL0 = AES_CTRL0_CLEAR_MSK; // 2. configure mode and direction (encryption or decryption) aes_handle[id].base->CTRL1 = AES_CTRL1_MODE(AES_MODE_ECB) | AES_CTRL1_DIR(mode); // 3. configure payload length aes_handle[id].base->CTRL2 = AES_CTRL2_PLEN(len); // 4. configure key memcpy((uint8_t *)&aes_handle[id].base->KEY[0], &aes_handle[id].config.key[0], 16); if (mode == AES_DIR_ENCRYPT) { return aes_encrypt(id, input, output, len, len); } else if (mode == AES_DIR_DECRYPT) { return aes_decrypt(id, input, output, len, len); } return DRV_ERROR; } int aes_crypt_cbc(enum AES_DEV_T id, enum AES_DIR_T mode, uint8_t iv[16], uint8_t *input, uint8_t *output, uint16_t len, drv_callback_t callback) { ASSERT(output != NULL, "output address is NULL"); ASSERT(((len % 16) == 0) && (len >= 16), "len invalid"); aes_handle[id].callback = callback; // 1. clear AES aes_handle[id].base->CTRL0 = AES_CTRL0_CLEAR_MSK; // 2. configure mode and direction (encryption or decryption) aes_handle[id].base->CTRL1 = AES_CTRL1_MODE(AES_MODE_CBC) | AES_CTRL1_DIR(mode); // 3. configure payload length aes_handle[id].base->CTRL2 = AES_CTRL2_PLEN(len); // 4. configure key memcpy((uint8_t *)&aes_handle[id].base->KEY[0], &aes_handle[id].config.key[0], 16); // 5. configure iv memcpy((uint8_t *)&aes_handle[id].base->IV[0], iv, 16); if (mode == AES_DIR_ENCRYPT) { return aes_encrypt(id, input, output, len, len); } else if (mode == AES_DIR_DECRYPT) { return aes_decrypt(id, input, output, len, len); } return DRV_ERROR; } int aes_crypt_ctr(enum AES_DEV_T id, uint8_t initial_counter[16], uint8_t *input, uint8_t *output, uint16_t len, drv_callback_t callback) { ASSERT(output != NULL, "output address is NULL"); ASSERT(((len % 16) == 0) && (len >= 16), "len invalid"); aes_handle[id].callback = callback; // 1. clear AES aes_handle[id].base->CTRL0 = AES_CTRL0_CLEAR_MSK; // 2. configure mode aes_handle[id].base->CTRL1 = AES_CTRL1_MODE(AES_MODE_CTR) | AES_CTRL1_DIR(AES_DIR_ENCRYPT); // 3. configure payload length aes_handle[id].base->CTRL2 = AES_CTRL2_PLEN(len); // 4. configure key memcpy((uint8_t *)&aes_handle[id].base->KEY[0], &aes_handle[id].config.key[0], 16); // 5. configure initial counter memcpy((uint8_t *)&aes_handle[id].base->IV[0], initial_counter, 16); return aes_encrypt(id, input, output, len, len); } int aes_crypt_ccm(enum AES_DEV_T id, enum AES_CCM_MODE opt, struct AES_CCM_CONTEXT_T *cxt, drv_callback_t callback) { ASSERT(cxt != NULL, "cxt is NULL"); uint8_t q; uint8_t i; uint8_t CTR_ZERO[16]; uint16_t data_len; int ret = 0; enum AES_DIR_T mode; if ((AES_CCM_ENCRYPT_AND_AUTH == opt) || (AES_CCM_DECRYPT_AND_AUTH == opt)) { // CCM mac size [4, 6, 8, 10, 12, 14, 16] if ((cxt->mac_size < 4) || (cxt->mac_size > 16) || ((cxt->mac_size & 0x01) != 0)) { ret = MK_AES_CCM_ERROR_MAC_SIZE; goto err; } // CCM nonce size [7 ... 13] if ((cxt->nonce_size < 7) || (cxt->nonce_size > 16)) { ret = MK_AES_CCM_ERROR_NONCE_SIZE; goto err; } } else { // CCM* mac size [0, 4, 8, 16] if ((cxt->mac_size | 0x1C) != 0x1C) { ret = MK_AES_CCM_ERROR_MAC_SIZE; goto err; } // CCM* nonce size [13] */ if (cxt->nonce_size != 13) { ret = MK_AES_CCM_ERROR_NONCE_SIZE; goto err; } } if ((AES_CCM_ENCRYPT_AND_AUTH == opt) || (AES_CCM_STAR_ENCRYPT_AND_AUTH == opt)) { mode = AES_DIR_ENCRYPT; if (cxt->output_buf_size < (cxt->data_in_len + cxt->mac_size)) { ret = MK_AES_CCM_ERROR_OUTPUT_BUF_NOT_ENOUGH; goto err; } } else { mode = AES_DIR_DECRYPT; if (cxt->output_buf_size < (cxt->data_in_len - cxt->mac_size)) { ret = MK_AES_CCM_ERROR_OUTPUT_BUF_NOT_ENOUGH; goto err; } } // The maximum length of authentication data supported by the MK8000 is 65517 bytes if (cxt->adata_len > 0xFFED) { ret = MK_AES_CCM_ERROR_ADATA_LEN_NOT_SUPPORT; goto err; } if (cxt->input_buf_size < (cxt->adata_len + cxt->data_in_len + 18)) { ret = MK_AES_CCM_ERROR_INPUT_BUF_NOT_ENOUGH; goto err; } // Formatting of B0 /* |----------------------------------------------| * |Octet number | 0 | 1....15-q | 16-q...15 | * |----------------------------------------------| * |Contents | Flags | Nonce | q | * |----------------------------------------------| */ // Formatting of the Flags Octet in B0 // tag_size - The octet length of the MAC /* |----------------------------------------------------------------------------------| * |Bit number | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | * |----------------------------------------------------------------------------------| * |Contents | Reserved | Adata | (tag_size-2)/2 | q-1 | * |----------------------------------------------------------------------------------| */ // q = Block Size - 1 byte(flags) - Nonce size q = 16 - 1 - cxt->nonce_size; // B0 Initialize cxt->input_buf[0] = (cxt->adata_len > 0) ? 0x40 : 0x00; cxt->input_buf[0] |= ((cxt->mac_size - 2) / 2) << 3; cxt->input_buf[0] |= q - 1; memcpy(cxt->input_buf + 1, cxt->nonce, cxt->nonce_size); if (AES_DIR_ENCRYPT == mode) { for (i = 0, data_len = cxt->data_in_len; i < q; i++, data_len >>= 8) { cxt->input_buf[15 - i] = (uint8_t)(data_len & 0xFF); } } else { for (i = 0, data_len = (cxt->data_in_len - cxt->mac_size); i < q; i++, data_len >>= 8) { cxt->input_buf[15 - i] = (uint8_t)(data_len & 0xFF); } } // Formatting of B1 // If 0 < auth_data_len < 2^16-2^8, then auth_data_len is encoded as [a]16, two octets. // If 2^16-2^8 <= auth_data_len <= 2^32, then auth_data_len is encoded as 0xff || 0xfe || [a]32, six octets. // If 2^32 <= auth_data_len <= 2^64, then auth_data_len is encoded as 0xff || 0xff || [a]64, ten octets. // note - padding to a block boundary /* |-------------------------------------------------------| * |Octet number | 0-1 | 2-16 | * |-------------------------------------------------------| * | 0 < a < 2^16-2^8 | 2 bytes | 14 bytes auth_data | * |-------------------------------------------------------| * |-------------------------------------------------------| * | 2^16-2^8 <= a <= 2^32 | 6 bytes | 10 bytes auth_data | * |-------------------------------------------------------| * |-------------------------------------------------------| * | 2^16-2^8 <= a <= 2^32 | 10 bytes | 6 bytes auth_data | * |-------------------------------------------------------| * * auth_data_len = 65536, auth_data[10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}; * eg. encoded 0xFF || 0xFE || [len]32 auth_data[10] * 0xFF 0xFE 0x00 0x01 0x00 0x00 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 */ // B1 Initialize if (cxt->adata_len > 0) { cxt->input_buf[16] = (uint8_t)((cxt->adata_len >> 8) & 0xFF); cxt->input_buf[17] = (uint8_t)(cxt->adata_len & 0xFF); memcpy(cxt->input_buf + 18, cxt->adata, cxt->adata_len); data_len = 18 + cxt->adata_len; } else { data_len = 16; } if ((uint32_t)cxt->data_in != (uint32_t)cxt->input_buf + data_len) { memcpy(cxt->input_buf + data_len, cxt->data_in, cxt->data_in_len); } // Formatting of CTRi /* |----------------------------------------------| * |Octet number | 0 | 1....15-q | 16-q...15 | * |----------------------------------------------| * |Contents | Flags | Nonce | q(Counter) | * |----------------------------------------------| */ // Formatting of the Flags Field in CTRi /* |--------------------------------------------------------------------------| * |Bit number | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | * |--------------------------------------------------------------------------| * |Contents | Reserved | Reserved | 0 | 0 | 0 | q-1 | * |--------------------------------------------------------------------------| */ // Initialize CTR0 // The counter starts counting from 0 memset(CTR_ZERO, 0, 16); // Flags = q - 1 CTR_ZERO[0] = q - 1; // copy nonce memcpy(CTR_ZERO + 1, cxt->nonce, cxt->nonce_size); aes_handle[id].callback = callback; // 1. clear AES aes_handle[id].base->CTRL0 = AES_CTRL0_CLEAR_MSK; if (AES_DIR_ENCRYPT == mode) { // 2. configure mode aes_handle[id].base->CTRL1 = AES_CTRL1_MODE(AES_MODE_CCM) | AES_CTRL1_MIC_LEN(cxt->mac_size); // 3. configure payload length, and associate length (include 16 bytes nonce) aes_handle[id].base->CTRL2 = AES_CTRL2_PLEN(cxt->data_in_len) | AES_CTRL2_ALEN(data_len); } else { // 2. configure mode aes_handle[id].base->CTRL1 = AES_CTRL1_MODE(AES_MODE_CCM) | AES_CTRL1_MIC_LEN(cxt->mac_size); // 3. configure payload length, and associate length (include 16 bytes nonce) aes_handle[id].base->CTRL2 = AES_CTRL2_PLEN(cxt->data_in_len - cxt->mac_size) | AES_CTRL2_ALEN(data_len); } // 4. configure key memcpy((uint8_t *)&aes_handle[id].base->KEY[0], &aes_handle[id].config.key[0], 16); // 5. configure initial counter memcpy((uint8_t *)&aes_handle[id].base->IV[0], CTR_ZERO, 16); if (AES_DIR_ENCRYPT == mode) { ret = aes_encrypt(id, cxt->input_buf, cxt->output_buf, data_len + cxt->data_in_len, cxt->data_in_len + cxt->mac_size); } else { ret = aes_decrypt(id, cxt->input_buf, cxt->output_buf, data_len + cxt->data_in_len, cxt->data_in_len - cxt->mac_size); } err: #if 0 switch (ret) { case MK_AES_CCM_ERROR_MAC_SIZE: LOG_INFO(TRACE_MODULE_DRIVER, "MAC size ERR\r\n"); break; case MK_AES_CCM_ERROR_NONCE_SIZE: LOG_INFO(TRACE_MODULE_DRIVER, "Nonce size ERR\r\n"); break; case MK_AES_CCM_ERROR_INPUT_BUF_NOT_ENOUGH: LOG_INFO(TRACE_MODULE_DRIVER, "Insufficient input buffer space ERR\r\n"); break; case MK_AES_CCM_ERROR_OUTPUT_BUF_NOT_ENOUGH: LOG_INFO(TRACE_MODULE_DRIVER, "Insufficient output buffer space ERR\r\n"); break; case MK_AES_CCM_ERROR_ADATA_LEN_NOT_SUPPORT: LOG_INFO(TRACE_MODULE_DRIVER, "Length of authentication data shall be limited to 65517 bytes\r\n"); break; } #else if (ret) { LOG_ERROR(TRACE_MODULE_DRIVER, "AES ERR code %d\r\n", ret); } #endif return ret; } enum AES_MIN_CHE_T aes_ccm_dec_mic_isvalid(enum AES_DEV_T id) { return aes_handle[id].is_valid; } #if AES_DMA_MODE_EN static void aes_dma_callback(void *ch, uint32_t err_code) { enum AES_DEV_T id = AES_ID0; uint8_t ch_num = *(uint8_t *)ch; if (ch_num == aes_handle[id].dma_out_ch) { if (err_code == DMA_INT_TYPE_DONE) { // finished - update statue aes_handle[id].state = AES_STATE_READY; } else { aes_handle[id].state |= AES_STATE_ERROR; } aes_handle[id].is_valid = MACTAG_IS_VALID(id); if (aes_handle[id].callback) { aes_handle[id].callback(&id, aes_handle[id].output_len); } // restore DMA IRQ priority NVIC_SetPriority(DMA_IRQn, IRQ_PRIORITY_HIGH); } else { ASSERT(0, "Unexpected dma channel\r\n"); } } #endif void AES_IRQHandler(void) { #if AES_INT_MODE_EN enum AES_DEV_T id = AES_ID0; uint8_t len = 0; uint32_t int_stat = aes_handle[id].base->INTR_STATUS; aes_handle[id].is_valid = MACTAG_IS_VALID(id); if (int_stat & AES_INTR_STATUS_DIN_OVERFLOW_MSK) { // clear interrupt status aes_handle[id].base->INTR_STATUS = AES_INTR_STATUS_DIN_OVERFLOW_MSK; ASSERT(0, "AES input overflow\r\n"); } else if (int_stat & AES_INTR_STATUS_DOUT_UNDERFLOW_MSK) { // clear interrupt status aes_handle[id].base->INTR_STATUS = AES_INTR_STATUS_DOUT_UNDERFLOW_MSK; LOG_INFO(TRACE_MODULE_DRIVER, "AES output underflow\r\n"); } else if (int_stat & AES_INTR_STATUS_DONE_MSK) { // clear interrupt status aes_handle[id].base->INTR_STATUS = AES_INTR_STATUS_DONE_MSK; // LOG_INFO(TRACE_MODULE_DRIVER, "AES done\r\n"); } else { if (int_stat & AES_INTR_STATUS_DIN_EMPTY_MSK) { len = (uint8_t)MIN(16, aes_handle[id].input_len - aes_handle[id].input_count); if (len) { for (uint8_t i = 0; i < len; i++) { REG_WRITE_BYTE(&aes_handle[id].base->DIN, aes_handle[id].input[aes_handle[id].input_count + i]); } aes_handle[id].input_count += len; } else { // disable tx empty interrupt aes_handle[id].base->INTR_EN &= ~AES_INTR_EN_DIN_EMPTY_EN_MSK; } } if (int_stat & AES_INTR_STATUS_DOUT_NOT_EMPTY_MSK) { uint32_t rx_cnt = GET_BIT_FIELD(aes_handle[id].base->STATUS, AES_STATUS_DOUT_BUF_CNT_MSK, AES_STATUS_DOUT_BUF_CNT_POS); len = (uint8_t)MIN(rx_cnt, aes_handle[id].output_len - aes_handle[id].output_count); for (uint8_t i = 0; i < len; i++) { uint8_t byte = REG_READ_BYTE(&aes_handle[id].base->DOUT); aes_handle[id].output[aes_handle[id].output_count + i] = byte; } aes_handle[id].output_count += len; } if (aes_handle[id].output_count >= aes_handle[id].output_len) { // done - update state aes_handle[id].state = AES_STATE_READY; // disable all interrupt aes_handle[id].base->INTR_EN = 0; if (aes_handle[id].callback) { aes_handle[id].callback(&id, aes_handle[id].output_count); } } } #endif } #if defined(__GNUC__) #pragma GCC diagnostic pop #endif #if defined(__ICCARM__) && defined(XIP_EN) #pragma default_function_attributes = #endif