I'm working on an AES implementation for the MSP432 that uses the AES256 accelerator and DMA. I'm using Code Composer Studio and an MSP-EXP432P401R development board. For starters, I'm just implementing ECB encryption to keep it simple while I'm still learning. I'm trying to follow the pseudocode in the Technical Reference Manual (SLAU356A p.543). After a lot of trial and error, I've managed to get it partially working. If I encrypt 1 AES block of data, it succeeds (i.e., encrypted data is written to the output buffer), but if I attempt to encrypt multiple blocks, it fails (i.e., no data is written to the output buffer). I've run out of things to try, so any suggestions would be appreciated. Thanks in advance.
// DriverLib Includes
#include "driverlib.h"
// Standard Includes
#include <stdint.h>
#include <stdbool.h>
// Statics
static uint8_t Data[48] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F
};
static uint8_t CipherKey[32] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
};
static uint8_t DataAESencrypted[48]; // Encrypted data
// DMA Control Table
#ifdef ewarm
#pragma data_alignment=1024
#else
#pragma DATA_ALIGN(controlTable, 1024)
#endif
uint8_t controlTable[256];
// AES ECB Encryption using DMA (SLAU356A p.543)
ECB_Encryption(uint8_t* key, uint8_t* plaintext, uint8_t* ciphertext, uint8_t num_blocks)
{
// Reset AES Controller
MAP_AES256_reset(AES256_BASE);
// Configure AES for block cipher. (AESACTL0 Register: SLAU356A p.553)
// AESCMEN = 1 (DMA)
AESACTL0 |= AESCMEN; // Enable DMA ciphermode support
// AESCMx = 00b (ECB)
AESACTL0 &= ~AESCM0; // Select AES cipher mode (00b = ECB)
AESACTL0 &= ~AESCM1; // Select AES cipher mode (00b = ECB)
// AESOPx = 00b (Encryption)
AESACTL0 &= ~AESOP0; // Select AES operation (00b = Encryption)
AESACTL0 &= ~AESOP1; // Select AES operation (00b = Encryption)
// AESKLx = 10b (AES256)
AESACTL0 |= AESKL1; // Set AES key length (10b = AES256)
AESACTL0 &= ~AESKL0; // Set AES key length (10b = AES256)
// Write key into AESAKEY.
MAP_AES256_setCipherKey(AES256_BASE, key, AES256_KEYLENGTH_256BIT);
// Assign DMA channels to AES triggers.
MAP_DMA_assignChannel(DMA_CH0_AESTRIGGER0);
MAP_DMA_assignChannel(DMA_CH1_AESTRIGGER1);
// Set DMA priorities.
MAP_DMA_enableChannelAttribute(DMA_CH0_AESTRIGGER0, UDMA_ATTR_HIGH_PRIORITY);
MAP_DMA_enableChannelAttribute(DMA_CH1_AESTRIGGER1, UDMA_ATTR_HIGH_PRIORITY);
// Setup DMA:
// DMA0: Triggered by AES trigger 0,
// Source: AESADOUT, Destination: ciphertext, Size: num_blocks*8 words
MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH0_AESTRIGGER0,
UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1024);
MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH0_AESTRIGGER0,
UDMA_MODE_AUTO,
(uint16_t*) &(AES256->DOUT),
ciphertext,
num_blocks * 8);
// Assign/Enable Interrupts.
MAP_DMA_assignInterrupt(DMA_INT1, 0);
MAP_Interrupt_enableInterrupt(INT_DMA_INT1);
MAP_Interrupt_enableMaster();
// Enable DMA Channel 0.
MAP_DMA_enableChannel(0);
// Setup DMA:
// DMA1: Triggered by AES trigger 1,
// Source: plaintext, Destination: AESADIN, Size: num_blocks*8 words
MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH1_AESTRIGGER1,
UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_1024);
MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH1_AESTRIGGER1,
UDMA_MODE_AUTO,
plaintext,
(uint16_t*) &(AES256->DIN),
num_blocks * 8);
// Assign/Enable Interrupts.
MAP_DMA_assignInterrupt(DMA_INT2, 1);
MAP_Interrupt_enableInterrupt(INT_DMA_INT2);
MAP_Interrupt_enableMaster();
// Enable DMA Channel 1.
MAP_DMA_enableChannel(1);
// Start encryption.
// AESBLKCNTx = Number of 16-byte blocks
AESACTL1 = (uint16_t) num_blocks; // Cipher Block Counter: Number of blocks to be encrypted or decrypted. (p.555)
// End of encryption: DMA0IFG = 1
// Wait for the AES accelerator to finish.
while(AESASTAT & AESBUSY)
{
}
}
// Completion interrupt for DMA
void DMA_INT1_IRQHandler(void)
{
MAP_DMA_disableChannel(0);
}
// Completion interrupt for DMA
void DMA_INT2_IRQHandler(void)
{
MAP_DMA_disableChannel(1);
}
int main(void)
{
// Stop Watchdog
MAP_WDT_A_holdTimer();
// Configuring DMA module
MAP_DMA_enableModule();
MAP_DMA_setControlBase(controlTable);
ECB_Encryption(CipherKey, Data, DataAESencrypted, 3);
return 0;
}