944 lines
33 KiB
C
944 lines
33 KiB
C
/******************************************************************************
|
|
* Filename: crypto.c
|
|
* Revised: 2020-01-07 14:06:28 +0100 (Tue, 07 Jan 2020)
|
|
* Revision: 56632
|
|
*
|
|
* Description: Driver for the Crypto module
|
|
*
|
|
* Copyright (c) 2015 - 2017, 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 "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
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Write the key into the Key Ram.
|
|
//
|
|
//*****************************************************************************
|
|
uint32_t
|
|
CRYPTOAesLoadKey(uint32_t *pui32AesKey,
|
|
uint32_t ui32KeyLocation)
|
|
{
|
|
uint32_t returnStatus = AES_KEYSTORE_READ_ERROR;
|
|
|
|
// 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));
|
|
|
|
// Disable the external interrupt to stop the interrupt form propagating
|
|
// from the module to the System CPU.
|
|
IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ);
|
|
|
|
// Clear any previously written key at the keyLocation
|
|
HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITTENAREA) = (0x00000001 << ui32KeyLocation);
|
|
|
|
// 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.
|
|
// Do not write to the register if the correct key size is already set.
|
|
// Writing to this register causes all current keys to be invalidated.
|
|
if (HWREG(CRYPTO_BASE + CRYPTO_O_KEYSIZE) != KEY_STORE_SIZE_128) {
|
|
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) &
|
|
(CRYPTO_IRQSTAT_DMA_BUS_ERR_M |
|
|
CRYPTO_IRQSTAT_KEY_ST_WR_ERR_M |
|
|
CRYPTO_IRQSTAT_DMA_IN_DONE |
|
|
CRYPTO_IRQSTAT_RESULT_AVAIL_M)));
|
|
|
|
// 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 key status, return success if key valid.
|
|
if(HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITTENAREA) & (0x00000001 << ui32KeyLocation))
|
|
{
|
|
returnStatus = AES_SUCCESS;
|
|
}
|
|
}
|
|
|
|
// Return status.
|
|
return returnStatus;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// 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;
|
|
|
|
// 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;
|
|
|
|
// 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);
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
// 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;
|
|
|
|
// 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);
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
return (AES_DMA_BUS_ERROR);
|
|
}
|
|
|
|
// Operation successful - disable interrupt and return success.
|
|
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;
|
|
|
|
// 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)
|
|
{
|
|
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);
|
|
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;
|
|
|
|
// 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)
|
|
{
|
|
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;
|
|
uint8_t tempResult = 0;
|
|
|
|
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);
|
|
|
|
/* XOR each byte of the computed tag with the provided tag and OR the results.
|
|
* If the OR'd result is non-zero, the tags do not match.
|
|
* There is no branch based on the content of the buffers here to avoid
|
|
* timing attacks.
|
|
*/
|
|
for (i = 0; i < ui32AuthLength; i++) {
|
|
tempResult |= ((uint8_t *) (pui32CipherText))[ui32TagIndex + i] ^ ((uint8_t *)ui32Tag)[i];
|
|
}
|
|
|
|
return tempResult == 0 ? AES_SUCCESS : CCM_AUTHENTICATION_FAILED;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// 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;
|
|
}
|
|
}
|