| /****************************************************************************** |
| * Filename: crypto.c |
| * Revised: 2016-05-27 09:37:54 +0200 (Fri, 27 May 2016) |
| * Revision: 46519 |
| * |
| * Description: Driver for the Crypto module |
| * |
| * Copyright (c) 2015 - 2016, Texas Instruments Incorporated |
| * 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 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 the ORGANIZATION nor the names of its contributors may |
| * be used to endorse or promote products derived from this software without |
| * specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 <driverlib/crypto.h> |
| |
| //***************************************************************************** |
| // |
| // Handle support for DriverLib in ROM: |
| // This section will undo prototype renaming made in the header file |
| // |
| //***************************************************************************** |
| #if !defined(DOXYGEN) |
| #undef CRYPTOAesLoadKey |
| #define CRYPTOAesLoadKey NOROM_CRYPTOAesLoadKey |
| #undef CRYPTOAesCbc |
| #define CRYPTOAesCbc NOROM_CRYPTOAesCbc |
| #undef CRYPTOAesCbcStatus |
| #define CRYPTOAesCbcStatus NOROM_CRYPTOAesCbcStatus |
| #undef CRYPTOAesEcb |
| #define CRYPTOAesEcb NOROM_CRYPTOAesEcb |
| #undef CRYPTOAesEcbStatus |
| #define CRYPTOAesEcbStatus NOROM_CRYPTOAesEcbStatus |
| #undef CRYPTOCcmAuthEncrypt |
| #define CRYPTOCcmAuthEncrypt NOROM_CRYPTOCcmAuthEncrypt |
| #undef CRYPTOCcmAuthEncryptStatus |
| #define CRYPTOCcmAuthEncryptStatus NOROM_CRYPTOCcmAuthEncryptStatus |
| #undef CRYPTOCcmAuthEncryptResultGet |
| #define CRYPTOCcmAuthEncryptResultGet NOROM_CRYPTOCcmAuthEncryptResultGet |
| #undef CRYPTOCcmInvAuthDecrypt |
| #define CRYPTOCcmInvAuthDecrypt NOROM_CRYPTOCcmInvAuthDecrypt |
| #undef CRYPTOCcmInvAuthDecryptStatus |
| #define CRYPTOCcmInvAuthDecryptStatus NOROM_CRYPTOCcmInvAuthDecryptStatus |
| #undef CRYPTOCcmInvAuthDecryptResultGet |
| #define CRYPTOCcmInvAuthDecryptResultGet NOROM_CRYPTOCcmInvAuthDecryptResultGet |
| #undef CRYPTODmaEnable |
| #define CRYPTODmaEnable NOROM_CRYPTODmaEnable |
| #undef CRYPTODmaDisable |
| #define CRYPTODmaDisable NOROM_CRYPTODmaDisable |
| #endif |
| |
| //***************************************************************************** |
| // |
| // Current AES operation initialized to None |
| // |
| //***************************************************************************** |
| volatile uint32_t g_ui32CurrentAesOp = CRYPTO_AES_NONE; |
| |
| |
| //***************************************************************************** |
| // |
| //! Write the key into the Key Ram. |
| // |
| //***************************************************************************** |
| uint32_t |
| CRYPTOAesLoadKey(uint32_t *pui32AesKey, |
| uint32_t ui32KeyLocation) |
| { |
| // |
| // Check the arguments. |
| // |
| ASSERT((ui32KeyLocation == CRYPTO_KEY_AREA_0) | |
| (ui32KeyLocation == CRYPTO_KEY_AREA_1) | |
| (ui32KeyLocation == CRYPTO_KEY_AREA_2) | |
| (ui32KeyLocation == CRYPTO_KEY_AREA_3) | |
| (ui32KeyLocation == CRYPTO_KEY_AREA_4) | |
| (ui32KeyLocation == CRYPTO_KEY_AREA_5) | |
| (ui32KeyLocation == CRYPTO_KEY_AREA_6) | |
| (ui32KeyLocation == CRYPTO_KEY_AREA_7)); |
| |
| // |
| // Set current operating state of the Crypto module. |
| // |
| g_ui32CurrentAesOp = CRYPTO_AES_KEYL0AD; |
| |
| // |
| // Disable the external interrupt to stop the interrupt form propagating |
| // from the module to the System CPU. |
| // |
| IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ); |
| |
| // |
| // Enable internal interrupts. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_IRQTYPE_LEVEL; |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_DMA_IN_DONE | |
| CRYPTO_IRQEN_RESULT_AVAIL; |
| |
| // |
| // Configure master control module. |
| // |
| HWREGBITW(CRYPTO_BASE + CRYPTO_O_ALGSEL, CRYPTO_ALGSEL_KEY_STORE_BITN) = 1; |
| |
| // |
| // Clear any outstanding events. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE | |
| CRYPTO_IRQCLR_RESULT_AVAIL); |
| |
| // |
| // Configure key store module for 128 bit operation. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_KEYSIZE) &= ~CRYPTO_KEYSIZE_SIZE_M; |
| HWREG(CRYPTO_BASE + CRYPTO_O_KEYSIZE) |= KEY_STORE_SIZE_128; |
| |
| // |
| // Enable keys to write (e.g. Key 0). |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITEAREA) = (0x00000001 << ui32KeyLocation); |
| |
| // |
| // Enable Crypto DMA channel 0. |
| // |
| HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1; |
| |
| // |
| // Base address of the key in ext. memory. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = (uint32_t)pui32AesKey; |
| |
| // |
| // Total key length in bytes (e.g. 16 for 1 x 128-bit key). |
| // Writing the length of the key enables the DMA operation. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = KEY_BLENGTH; |
| |
| // |
| // Wait for the DMA operation to complete. |
| // |
| do |
| { |
| CPUdelay(1); |
| } |
| while(!(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & 0x00000001)); |
| |
| // |
| // Check for errors in DMA and key store. |
| // |
| if((HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & |
| (CRYPTO_IRQSTAT_DMA_BUS_ERR | |
| CRYPTO_IRQSTAT_KEY_ST_WR_ERR)) == 0) |
| { |
| // |
| // Acknowledge/clear the interrupt and disable the master control. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE | |
| CRYPTO_IRQCLR_RESULT_AVAIL); |
| HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = 0x00000000; |
| |
| // |
| // Check status, if error return error code. |
| // |
| if(HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITTENAREA) != (1u << ui32KeyLocation)) |
| { |
| g_ui32CurrentAesOp = CRYPTO_AES_NONE; |
| return (AES_KEYSTORE_READ_ERROR); |
| } |
| } |
| |
| // |
| // Return success. |
| // |
| g_ui32CurrentAesOp = CRYPTO_AES_NONE; |
| return (AES_SUCCESS); |
| } |
| |
| //***************************************************************************** |
| // |
| //! Start an AES-CBC operation (encryption or decryption). |
| // |
| //***************************************************************************** |
| uint32_t |
| CRYPTOAesCbc(uint32_t *pui32MsgIn, uint32_t *pui32MsgOut, uint32_t ui32MsgLength, |
| uint32_t *pui32Nonce, uint32_t ui32KeyLocation, |
| bool bEncrypt, bool bIntEnable) |
| { |
| uint32_t ui32CtrlVal; |
| |
| // |
| // Set current operating state of the Crypto module. |
| // |
| g_ui32CurrentAesOp = CRYPTO_AES_CBC; |
| |
| // |
| // Enable internal interrupts. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_IRQTYPE_LEVEL; |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_RESULT_AVAIL; |
| |
| // |
| // Clear any outstanding interrupts. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE | |
| CRYPTO_IRQCLR_RESULT_AVAIL); |
| |
| // |
| // Wait for interrupt lines from module to be cleared |
| // |
| while(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & (CRYPTO_IRQSTAT_DMA_IN_DONE | CRYPTO_IRQSTAT_RESULT_AVAIL)); |
| |
| // |
| // If using interrupts clear any pending interrupts and enable interrupts |
| // for the Crypto module. |
| // |
| if(bIntEnable) |
| { |
| IntPendClear(INT_CRYPTO_RESULT_AVAIL_IRQ); |
| IntEnable(INT_CRYPTO_RESULT_AVAIL_IRQ); |
| } |
| |
| // |
| // Configure Master Control module. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = CRYPTO_ALGSEL_AES; |
| |
| // |
| // |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) = ui32KeyLocation; |
| |
| // |
| //Wait until key is loaded to the AES module. |
| // |
| do |
| { |
| CPUdelay(1); |
| } |
| while((HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) & CRYPTO_KEYREADAREA_BUSY)); |
| |
| // |
| // Check for Key store Read error. |
| // |
| if((HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT)& CRYPTO_KEY_ST_RD_ERR)) |
| { |
| return (AES_KEYSTORE_READ_ERROR); |
| } |
| |
| // |
| // Write initialization vector. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESIV0) = pui32Nonce[0]; |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESIV1) = pui32Nonce[1]; |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESIV2) = pui32Nonce[2]; |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESIV3) = pui32Nonce[3]; |
| |
| // |
| // Configure AES engine for AES-CBC with 128-bit key size. |
| // |
| ui32CtrlVal = (CRYPTO_AESCTL_SAVE_CONTEXT | CRYPTO_AESCTL_CBC); |
| if(bEncrypt) |
| { |
| ui32CtrlVal |= CRYPTO_AES128_ENCRYPT; |
| } |
| else |
| { |
| ui32CtrlVal |= CRYPTO_AES128_DECRYPT; |
| } |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) = ui32CtrlVal; |
| |
| // |
| // Write the length of the crypto block (plain text). |
| // Low and high part (high part is assumed to be always 0). |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN0) = ui32MsgLength; |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN1) = 0; |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESAUTHLEN) = 0; |
| |
| // |
| // Enable Crypto DMA channel 0. |
| // |
| HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1; |
| |
| // |
| // Base address of the input data in ext. memory. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = (uint32_t)pui32MsgIn; |
| |
| // |
| // Input data length in bytes, equal to the message. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = ui32MsgLength; |
| |
| // |
| // Enable Crypto DMA channel 1. |
| // |
| HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 1; |
| |
| // |
| // Set up the address and length of the output data. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1EXTADDR) = (uint32_t)pui32MsgOut; |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1LEN) = ui32MsgLength; |
| |
| // |
| // Return success |
| // |
| return AES_SUCCESS; |
| } |
| |
| //***************************************************************************** |
| // |
| //! Check the result of an AES CBC operation |
| // |
| //***************************************************************************** |
| uint32_t |
| CRYPTOAesCbcStatus(void) |
| { |
| return(CRYPTOAesEcbStatus()); |
| } |
| |
| //***************************************************************************** |
| // |
| //! Start an AES-ECB operation (encryption or decryption). |
| // |
| //***************************************************************************** |
| uint32_t |
| CRYPTOAesEcb(uint32_t *pui32MsgIn, uint32_t *pui32MsgOut, |
| uint32_t ui32KeyLocation, bool bEncrypt, |
| bool bIntEnable) |
| { |
| // |
| // Set current operating state of the Crypto module. |
| // |
| g_ui32CurrentAesOp = CRYPTO_AES_ECB; |
| |
| // |
| // Enable internal interrupts. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_IRQTYPE_LEVEL; |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_RESULT_AVAIL; |
| |
| // |
| // Clear any outstanding interrupts. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE | |
| CRYPTO_IRQCLR_RESULT_AVAIL); |
| |
| // |
| // Wait for interrupt lines from module to be cleared |
| // |
| while(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & (CRYPTO_IRQSTAT_DMA_IN_DONE | CRYPTO_IRQSTAT_RESULT_AVAIL)); |
| |
| // |
| // If using interrupts clear any pending interrupts and enable interrupts |
| // for the Crypto module. |
| // |
| if(bIntEnable) |
| { |
| IntPendClear(INT_CRYPTO_RESULT_AVAIL_IRQ); |
| IntEnable(INT_CRYPTO_RESULT_AVAIL_IRQ); |
| } |
| |
| // |
| // Configure Master Control module. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = CRYPTO_ALGSEL_AES; |
| |
| // |
| // |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) = ui32KeyLocation; |
| |
| // |
| //Wait until key is loaded to the AES module. |
| // |
| do |
| { |
| CPUdelay(1); |
| } |
| while((HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) & CRYPTO_KEYREADAREA_BUSY)); |
| |
| // |
| // Check for Key store Read error. |
| // |
| if((HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT)& CRYPTO_KEY_ST_RD_ERR)) |
| { |
| return (AES_KEYSTORE_READ_ERROR); |
| } |
| |
| // |
| // Configure AES engine (program AES-ECB-128 encryption and no |
| // initialization vector - IV). |
| // |
| if(bEncrypt) |
| { |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) = CRYPTO_AES128_ENCRYPT; |
| } |
| else |
| { |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) = CRYPTO_AES128_DECRYPT; |
| } |
| |
| // |
| // Write the length of the data. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN0) = AES_ECB_LENGTH; |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN1) = 0; |
| |
| // |
| // Enable Crypto DMA channel 0. |
| // |
| HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1; |
| |
| // |
| // Base address of the input data in ext. memory. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = (uint32_t)pui32MsgIn; |
| |
| // |
| // Input data length in bytes, equal to the message. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = AES_ECB_LENGTH; |
| |
| // |
| // Enable Crypto DMA channel 1. |
| // |
| HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 1; |
| |
| // |
| // Set up the address and length of the output data. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1EXTADDR) = (uint32_t)pui32MsgOut; |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1LEN) = AES_ECB_LENGTH; |
| |
| // |
| // Return success |
| // |
| return AES_SUCCESS; |
| } |
| |
| //***************************************************************************** |
| // |
| //! Check the result of an AES ECB operation |
| // |
| //***************************************************************************** |
| uint32_t |
| CRYPTOAesEcbStatus(void) |
| { |
| uint32_t ui32Status; |
| |
| // |
| // Get the current DMA status. |
| // |
| ui32Status = HWREG(CRYPTO_BASE + CRYPTO_O_DMASTAT); |
| |
| // |
| // Check if DMA is still busy. |
| // |
| if(ui32Status & CRYPTO_DMA_BSY) |
| { |
| return (AES_DMA_BSY); |
| } |
| |
| // |
| // Check the status of the DMA operation - return error if not success. |
| // |
| if(ui32Status & CRYPTO_DMA_BUS_ERROR) |
| { |
| g_ui32CurrentAesOp = CRYPTO_AES_NONE; |
| return (AES_DMA_BUS_ERROR); |
| } |
| |
| // |
| // Operation successful - disable interrupt and return success. |
| // |
| g_ui32CurrentAesOp = CRYPTO_AES_NONE; |
| IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ); |
| return (AES_SUCCESS); |
| } |
| |
| //***************************************************************************** |
| // |
| //! Start CCM operation |
| // |
| //***************************************************************************** |
| uint32_t |
| CRYPTOCcmAuthEncrypt(bool bEncrypt, uint32_t ui32AuthLength , |
| uint32_t *pui32Nonce, uint32_t *pui32PlainText, |
| uint32_t ui32PlainTextLength, uint32_t *pui32Header, |
| uint32_t ui32HeaderLength, uint32_t ui32KeyLocation, |
| uint32_t ui32FieldLength, bool bIntEnable) |
| { |
| uint32_t ui32CtrlVal; |
| uint32_t i; |
| uint32_t *pui32CipherText; |
| union { |
| uint32_t w[4]; |
| uint8_t b[16]; |
| } ui8InitVec; |
| |
| // |
| // Input address for the encryption engine is the same as the output. |
| // |
| pui32CipherText = pui32PlainText; |
| |
| // |
| // Set current operating state of the Crypto module. |
| // |
| g_ui32CurrentAesOp = CRYPTO_AES_CCM; |
| |
| // |
| // Disable global interrupt, enable local interrupt and clear any pending |
| // interrupts. |
| // |
| IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ); |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE | |
| CRYPTO_IRQCLR_RESULT_AVAIL); |
| |
| // |
| // Enable internal interrupts. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_IRQTYPE_LEVEL; |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_DMA_IN_DONE | |
| CRYPTO_IRQEN_RESULT_AVAIL; |
| |
| // |
| // Configure master control module for AES operation. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = CRYPTO_ALGSEL_AES; |
| |
| // |
| // Enable keys to read (e.g. Key 0). |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) = ui32KeyLocation; |
| |
| // |
| // Wait until key is loaded to the AES module. |
| // |
| do |
| { |
| CPUdelay(1); |
| } |
| while((HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) & CRYPTO_KEYREADAREA_BUSY)); |
| |
| // |
| // Check for Key store Read error. |
| // |
| if((HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT)& CRYPTO_KEY_ST_RD_ERR)) |
| { |
| return (AES_KEYSTORE_READ_ERROR); |
| } |
| |
| // |
| // Prepare the initialization vector (IV), |
| // Length of Nonce l(n) = 15 - ui32FieldLength. |
| // |
| ui8InitVec.b[0] = ui32FieldLength - 1; |
| for(i = 0; i < 12; i++) |
| { |
| ui8InitVec.b[i + 1] = ((uint8_t*)pui32Nonce)[i]; |
| } |
| if(ui32FieldLength == 2) |
| { |
| ui8InitVec.b[13] = ((uint8_t*)pui32Nonce)[12]; |
| } |
| else |
| { |
| ui8InitVec.b[13] = 0; |
| } |
| ui8InitVec.b[14] = 0; |
| ui8InitVec.b[15] = 0; |
| |
| // |
| // Write initialization vector. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESIV0) = ui8InitVec.w[0]; |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESIV1) = ui8InitVec.w[1]; |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESIV2) = ui8InitVec.w[2]; |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESIV3) = ui8InitVec.w[3]; |
| |
| // |
| // Configure AES engine. |
| // |
| ui32CtrlVal = ((ui32FieldLength - 1) << CRYPTO_AESCTL_CCM_L_S); |
| if ( ui32AuthLength >= 2 ) { |
| ui32CtrlVal |= ((( ui32AuthLength - 2 ) >> 1 ) << CRYPTO_AESCTL_CCM_M_S ); |
| } |
| ui32CtrlVal |= CRYPTO_AESCTL_CCM; |
| ui32CtrlVal |= CRYPTO_AESCTL_CTR; |
| ui32CtrlVal |= CRYPTO_AESCTL_SAVE_CONTEXT; |
| ui32CtrlVal |= (KEY_STORE_SIZE_128 << CRYPTO_AESCTL_KEY_SIZE_S); |
| ui32CtrlVal |= (1 << CRYPTO_AESCTL_DIR_S); |
| ui32CtrlVal |= (CRYPTO_AES_CTR_128 << CRYPTO_AESCTL_CTR_WIDTH_S); |
| |
| // |
| // Write the configuration for 128 bit AES-CCM. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) = ui32CtrlVal; |
| |
| // |
| // Write the length of the crypto block (plain text). |
| // Low and high part (high part is assumed to be always 0). |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN0) = ui32PlainTextLength; |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN1) = 0; |
| |
| // |
| // Write the length of the header field. |
| // Also called AAD - Additional Authentication Data. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESAUTHLEN) = ui32HeaderLength; |
| |
| // |
| // Check if any header information (AAD). |
| // If so configure the DMA controller to fetch the header. |
| // |
| if(ui32HeaderLength != 0) |
| { |
| // |
| // Enable DMA channel 0. |
| // |
| HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1; |
| |
| // |
| // Register the base address of the header (AAD). |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = (uint32_t)pui32Header; |
| |
| // |
| // Header length in bytes (may be non-block size aligned). |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = ui32HeaderLength; |
| |
| // |
| // Wait for completion of the header data transfer, DMA_IN_DONE. |
| // |
| do |
| { |
| CPUdelay(1); |
| } |
| while(!(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & CRYPTO_IRQSTAT_DMA_IN_DONE)); |
| |
| // |
| // Check for DMA errors. |
| // |
| if(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & CRYPTO_DMA_BUS_ERR) |
| { |
| return AES_DMA_BUS_ERROR; |
| } |
| } |
| |
| // |
| // Clear interrupt status. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE | |
| CRYPTO_IRQCLR_RESULT_AVAIL); |
| |
| // |
| // Wait for interrupt lines from module to be cleared |
| // |
| while(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & (CRYPTO_IRQSTAT_DMA_IN_DONE | CRYPTO_IRQSTAT_RESULT_AVAIL)); |
| |
| // |
| // Disable CRYPTO_IRQEN_DMA_IN_DONE interrupt as we only |
| // want interrupt to trigger once RESULT_AVAIL occurs. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) &= ~CRYPTO_IRQEN_DMA_IN_DONE; |
| |
| |
| // |
| // Is using interrupts enable globally. |
| // |
| if(bIntEnable) |
| { |
| IntPendClear(INT_CRYPTO_RESULT_AVAIL_IRQ); |
| IntEnable(INT_CRYPTO_RESULT_AVAIL_IRQ); |
| } |
| |
| // |
| // Enable interrupts locally. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_RESULT_AVAIL; |
| |
| // |
| // Perform encryption if requested. |
| // |
| if(bEncrypt) |
| { |
| // |
| // Enable DMA channel 0 |
| // |
| HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1; |
| |
| // |
| // base address of the payload data in ext. memory. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = |
| (uint32_t)pui32PlainText; |
| |
| // |
| // Enable DMA channel 1 |
| // |
| HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 1; |
| |
| // |
| // Base address of the output data buffer. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1EXTADDR) = |
| (uint32_t)pui32CipherText; |
| |
| // |
| // Payload data length in bytes, equal to the plaintext length. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = ui32PlainTextLength; |
| // |
| // Output data length in bytes, equal to the plaintext length. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1LEN) = ui32PlainTextLength; |
| } |
| |
| return AES_SUCCESS; |
| } |
| |
| //***************************************************************************** |
| // |
| //! Check the result of an AES CCM operation. |
| // |
| //***************************************************************************** |
| uint32_t |
| CRYPTOCcmAuthEncryptStatus(void) |
| { |
| uint32_t ui32Status; |
| |
| // |
| // Get the current DMA status. |
| // |
| ui32Status = HWREG(CRYPTO_BASE + CRYPTO_O_DMASTAT); |
| |
| // |
| // Check if DMA is still busy. |
| // |
| if(ui32Status & CRYPTO_DMA_BSY) |
| { |
| return (AES_DMA_BSY); |
| } |
| |
| // |
| // Check the status of the DMA operation - return error if not success. |
| // |
| if(ui32Status & CRYPTO_DMA_BUS_ERROR) |
| { |
| g_ui32CurrentAesOp = CRYPTO_AES_NONE; |
| return (AES_DMA_BUS_ERROR); |
| } |
| |
| // |
| // Operation successful - disable interrupt and return success. |
| // |
| IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ); |
| return (AES_SUCCESS); |
| } |
| |
| //***************************************************************************** |
| // |
| //! Get the result of an AES-CCM operation |
| // |
| //***************************************************************************** |
| uint32_t |
| CRYPTOCcmAuthEncryptResultGet(uint32_t ui32TagLength, uint32_t *pui32CcmTag) |
| { |
| uint32_t volatile ui32Tag[4]; |
| uint32_t ui32Idx; |
| |
| // |
| // Result has already been copied to the output buffer by DMA |
| // Disable master control. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = 0x00000000; |
| |
| // |
| // Read tag - wait for the context ready bit. |
| // |
| do |
| { |
| CPUdelay(1); |
| } |
| while(!(HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) & |
| CRYPTO_AESCTL_SAVED_CONTEXT_RDY)); |
| |
| // |
| // Read the Tag registers. |
| // |
| ui32Tag[0] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT0); |
| ui32Tag[1] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT1); |
| ui32Tag[2] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT2); |
| ui32Tag[3] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT3); |
| |
| for(ui32Idx = 0; ui32Idx < ui32TagLength ; ui32Idx++) |
| { |
| *((uint8_t*)pui32CcmTag + ui32Idx) = *((uint8_t*)ui32Tag + ui32Idx); |
| } |
| |
| // |
| // Operation successful - clear interrupt status. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE | |
| CRYPTO_IRQCLR_RESULT_AVAIL); |
| g_ui32CurrentAesOp = CRYPTO_AES_NONE; |
| return AES_SUCCESS; |
| } |
| |
| //***************************************************************************** |
| // |
| //! Start a CCM Decryption and Inverse Authentication operation. |
| // |
| //***************************************************************************** |
| uint32_t |
| CRYPTOCcmInvAuthDecrypt(bool bDecrypt, uint32_t ui32AuthLength, |
| uint32_t *pui32Nonce, uint32_t *pui32CipherText, |
| uint32_t ui32CipherTextLength, |
| uint32_t *pui32Header, uint32_t ui32HeaderLength, |
| uint32_t ui32KeyLocation, |
| uint32_t ui32FieldLength, bool bIntEnable) |
| { |
| uint32_t ui32CtrlVal; |
| uint32_t i; |
| uint32_t *pui32PlainText; |
| uint32_t ui32CryptoBlockLength; |
| union { |
| uint32_t w[4]; |
| uint8_t b[16]; |
| } ui8InitVec; |
| |
| // |
| // Input address for the encryption engine is the same as the output. |
| // |
| pui32PlainText = pui32CipherText; |
| |
| // |
| // Set current operating state of the Crypto module. |
| // |
| g_ui32CurrentAesOp = CRYPTO_AES_CCM; |
| |
| // |
| // Disable global interrupt, enable local interrupt and clear any pending. |
| // interrupts. |
| // |
| IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ); |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE | |
| CRYPTO_IRQCLR_RESULT_AVAIL); |
| // |
| // Enable internal interrupts. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_IRQTYPE_LEVEL; |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_DMA_IN_DONE | |
| CRYPTO_IRQEN_RESULT_AVAIL; |
| |
| // |
| // Configure master control module for AES operation. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = CRYPTO_ALGSEL_AES; |
| |
| // |
| // Enable keys to read (e.g. Key 0). |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) = ui32KeyLocation; |
| |
| // |
| // Wait until key is loaded to the AES module. |
| // |
| do |
| { |
| CPUdelay(1); |
| } |
| while((HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) & CRYPTO_KEYREADAREA_BUSY)); |
| |
| // |
| // Check for Key store Read error. |
| // |
| if((HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT)& CRYPTO_KEY_ST_RD_ERR)) |
| { |
| return (AES_KEYSTORE_READ_ERROR); |
| } |
| |
| // |
| // Prepare the initialization vector (IV), |
| // Length of Nonce l(n) = 15 - ui32FieldLength. |
| // |
| ui8InitVec.b[0] = ui32FieldLength - 1; |
| for(i = 0; i < 12; i++) |
| { |
| ui8InitVec.b[i + 1] = ((uint8_t*)pui32Nonce)[i]; |
| } |
| if(ui32FieldLength == 2) |
| { |
| ui8InitVec.b[13] = ((uint8_t*)pui32Nonce)[12]; |
| } |
| else |
| { |
| ui8InitVec.b[13] = 0; |
| } |
| ui8InitVec.b[14] = 0; |
| ui8InitVec.b[15] = 0; |
| |
| // |
| // Write initialization vector. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESIV0) = ui8InitVec.w[0]; |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESIV1) = ui8InitVec.w[1]; |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESIV2) = ui8InitVec.w[2]; |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESIV3) = ui8InitVec.w[3]; |
| |
| // |
| // Configure AES engine |
| // |
| ui32CryptoBlockLength = ui32CipherTextLength - ui32AuthLength; |
| ui32CtrlVal = ((ui32FieldLength - 1) << CRYPTO_AESCTL_CCM_L_S); |
| if ( ui32AuthLength >= 2 ) { |
| ui32CtrlVal |= ((( ui32AuthLength - 2 ) >> 1 ) << CRYPTO_AESCTL_CCM_M_S ); |
| } |
| ui32CtrlVal |= CRYPTO_AESCTL_CCM; |
| ui32CtrlVal |= CRYPTO_AESCTL_CTR; |
| ui32CtrlVal |= CRYPTO_AESCTL_SAVE_CONTEXT; |
| ui32CtrlVal |= (KEY_STORE_SIZE_128 << CRYPTO_AESCTL_KEY_SIZE_S); |
| ui32CtrlVal |= (0 << CRYPTO_AESCTL_DIR_S); |
| ui32CtrlVal |= (CRYPTO_AES_CTR_128 << CRYPTO_AESCTL_CTR_WIDTH_S); |
| |
| // |
| // Write the configuration for 128 bit AES-CCM. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) = ui32CtrlVal; |
| |
| // |
| // Write the length of the crypto block (plain text). |
| // Low and high part (high part is assumed to be always 0). |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN0) = ui32CryptoBlockLength; |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN1) = 0; |
| |
| // |
| // Write the length of the header field. |
| // Also called AAD - Additional Authentication Data. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_AESAUTHLEN) = ui32HeaderLength; |
| |
| // |
| // Check if any header information (AAD). |
| // If so configure the DMA controller to fetch the header. |
| // |
| if(ui32HeaderLength != 0) |
| { |
| // |
| // Enable DMA channel 0. |
| // |
| HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1; |
| |
| // |
| // Register the base address of the header (AAD). |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = (uint32_t)pui32Header; |
| |
| // |
| // Header length in bytes (may be non-block size aligned). |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = ui32HeaderLength; |
| |
| // |
| // Wait for completion of the header data transfer, DMA_IN_DONE. |
| // |
| do |
| { |
| CPUdelay(1); |
| } |
| while(!(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & CRYPTO_IRQSTAT_DMA_IN_DONE)); |
| |
| // |
| // Check for DMA errors. |
| // |
| if(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & CRYPTO_DMA_BUS_ERR) |
| { |
| return AES_DMA_BUS_ERROR; |
| } |
| } |
| |
| // |
| // Clear interrupt status. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE | |
| CRYPTO_IRQCLR_RESULT_AVAIL); |
| |
| // |
| // Wait for interrupt lines from module to be cleared |
| // |
| while(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & (CRYPTO_IRQSTAT_DMA_IN_DONE | CRYPTO_IRQSTAT_RESULT_AVAIL)); |
| |
| // |
| // Disable CRYPTO_IRQEN_DMA_IN_DONE interrupt as we only |
| // want interrupt to trigger once RESULT_AVAIL occurs. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) &= ~CRYPTO_IRQEN_DMA_IN_DONE; |
| |
| // |
| // Is using interrupts - clear and enable globally. |
| // |
| if(bIntEnable) |
| { |
| IntPendClear(INT_CRYPTO_RESULT_AVAIL_IRQ); |
| IntEnable(INT_CRYPTO_RESULT_AVAIL_IRQ); |
| } |
| |
| // |
| // Enable internal interrupts. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_IRQTYPE_LEVEL; |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_RESULT_AVAIL; |
| |
| // |
| // Perform decryption if requested. |
| // |
| if(bDecrypt) |
| { |
| // |
| // Configure the DMA controller - enable both DMA channels. |
| // |
| HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1; |
| |
| // |
| // Base address of the payload data in ext. memory. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = |
| (uint32_t)pui32CipherText; |
| |
| // |
| // Payload data length in bytes, equal to the cipher text length. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = ui32CryptoBlockLength; |
| |
| // |
| // Enable DMA channel 1. |
| // |
| HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 1; |
| |
| // |
| // Base address of the output data buffer. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1EXTADDR) = |
| (uint32_t)pui32PlainText; |
| |
| // |
| // Output data length in bytes, equal to the cipher text length. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1LEN) = ui32CryptoBlockLength; |
| } |
| |
| return AES_SUCCESS; |
| } |
| |
| //***************************************************************************** |
| // |
| //! Checks CCM decrypt and Inverse Authentication result. |
| // |
| //***************************************************************************** |
| uint32_t |
| CRYPTOCcmInvAuthDecryptStatus(void) |
| { |
| uint32_t ui32Status; |
| |
| // |
| // Get the current DMA status. |
| // |
| ui32Status = HWREG(CRYPTO_BASE + CRYPTO_O_DMASTAT); |
| |
| // |
| // Check if DMA is still busy. |
| // |
| if(ui32Status & CRYPTO_DMA_BSY) |
| { |
| return (AES_DMA_BSY); |
| } |
| |
| // |
| // Check the status of the DMA operation - return error if not success. |
| // |
| if(ui32Status & CRYPTO_DMA_BUS_ERROR) |
| { |
| g_ui32CurrentAesOp = CRYPTO_AES_NONE; |
| return (AES_DMA_BUS_ERROR); |
| } |
| |
| // |
| // Operation successful - disable interrupt and return success |
| // |
| IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ); |
| return (AES_SUCCESS); |
| } |
| |
| //***************************************************************************** |
| // |
| //! Get the result of the CCM operation. |
| // |
| //***************************************************************************** |
| uint32_t |
| CRYPTOCcmInvAuthDecryptResultGet(uint32_t ui32AuthLength, |
| uint32_t *pui32CipherText, |
| uint32_t ui32CipherTextLength, |
| uint32_t *pui32CcmTag) |
| { |
| uint32_t volatile ui32Tag[4]; |
| uint32_t ui32TagIndex; |
| uint32_t i; |
| uint32_t ui32Idx; |
| |
| ui32TagIndex = ui32CipherTextLength - ui32AuthLength; |
| |
| // |
| // Result has already been copied to the output buffer by DMA |
| // Disable master control. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = 0x00000000; |
| |
| // |
| // Read tag - wait for the context ready bit. |
| // |
| do |
| { |
| CPUdelay(1); |
| } |
| while(!(HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) & |
| CRYPTO_AESCTL_SAVED_CONTEXT_RDY)); |
| |
| // |
| // Read the Tag registers. |
| // |
| ui32Tag[0] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT0); |
| ui32Tag[1] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT1); |
| ui32Tag[2] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT2); |
| ui32Tag[3] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT3); |
| |
| for(ui32Idx = 0; ui32Idx < ui32AuthLength ; ui32Idx++) |
| { |
| *((uint8_t*)pui32CcmTag + ui32Idx) = *((uint8_t*)ui32Tag + ui32Idx); |
| } |
| |
| // |
| // Operation successful - clear interrupt status. |
| // |
| HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE | |
| CRYPTO_IRQCLR_RESULT_AVAIL); |
| |
| // |
| // Verify the Tag. |
| // |
| for(i = 0; i < ui32AuthLength; i++) |
| { |
| if(*((uint8_t *)pui32CcmTag + i) != |
| (*((uint8_t *)pui32CipherText + ui32TagIndex + i))) |
| { |
| return CCM_AUTHENTICATION_FAILED; |
| } |
| } |
| |
| g_ui32CurrentAesOp = CRYPTO_AES_NONE; |
| return AES_SUCCESS; |
| } |
| |
| //***************************************************************************** |
| // |
| //! Enable Crypto DMA operation |
| // |
| //***************************************************************************** |
| void |
| CRYPTODmaEnable(uint32_t ui32Channels) |
| { |
| // |
| // Check the arguments. |
| // |
| ASSERT((ui32Channels & CRYPTO_DMA_CHAN0) | |
| (ui32Channels & CRYPTO_DMA_CHAN1)); |
| |
| // |
| // Enable the selected channels, |
| // |
| if(ui32Channels & CRYPTO_DMA_CHAN0) |
| { |
| HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1; |
| } |
| if(ui32Channels & CRYPTO_DMA_CHAN1) |
| { |
| HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 1; |
| } |
| } |
| |
| //***************************************************************************** |
| // |
| //! Disable Crypto DMA operation |
| // |
| //***************************************************************************** |
| void |
| CRYPTODmaDisable(uint32_t ui32Channels) |
| { |
| // |
| // Check the arguments. |
| // |
| ASSERT((ui32Channels & CRYPTO_DMA_CHAN0) | |
| (ui32Channels & CRYPTO_DMA_CHAN1)); |
| |
| // |
| // Enable the selected channels. |
| // |
| if(ui32Channels & CRYPTO_DMA_CHAN0) |
| { |
| HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 0; |
| } |
| if(ui32Channels & CRYPTO_DMA_CHAN1) |
| { |
| HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 0; |
| } |
| } |