Microchip® Advanced Software Framework

Quick Start Guide for AES - Callback

The supported board list:

  • SAM L21 Xplained Pro
  • SAM L22 Xplained Pro

This example demonstrates how to use the AES driver to perform:

  • ECB encryption and decryption
  • CBC encryption and decryption
  • CFB128 encryption and decryption
  • OFB encryption and decryption
  • CTR encryption and decryption

Upon startup, the program uses the USART driver to display application output message from which several encryption/decryption modes can be tested.

Quick Start Callback

Prerequisites

There are no prerequisites for this use case.

Code

Add to the main application source file, outside of any functions:

#define AES_EXAMPLE_REFBUF_SIZE 4
/* @{ */
uint32_t ref_plain_text[AES_EXAMPLE_REFBUF_SIZE] = {
0xe2bec16b,
0x969f402e,
0x117e3de9,
0x2a179373
};
uint32_t ref_cipher_text_ecb[AES_EXAMPLE_REFBUF_SIZE] = {
0xb47bd73a,
0x60367a0d,
0xf3ca9ea8,
0x97ef6624
};
0xacab4976,
0x46b21981,
0x9b8ee9ce,
0x7d19e912
};
0x2ed93f3b,
0x20ad2db7,
0xf8493433,
0x4afb3ce8
};
0x2ed93f3b,
0x20ad2db7,
0xf8493433,
0x4afb3ce8
};
0x91614d87,
0x26e320b6,
0x6468ef1b,
0xceb60d99
};
const uint32_t key128[4] = {
0x16157e2b,
0xa6d2ae28,
0x8815f7ab,
0x3c4fcf09
};
const uint32_t init_vector[4] = {
0x03020100,
0x07060504,
0x0b0a0908,
0x0f0e0d0c
};
const uint32_t init_vector_ctr[4] = {
0xf3f2f1f0,
0xf7f6f5f4,
0xfbfaf9f8,
0xfffefdfc
};
/* @} */

Add to the main application source file, outside of any functions:

/* Output data array */
static uint32_t output_data[AES_EXAMPLE_REFBUF_SIZE];
/* State indicate */
volatile bool state = false;
struct aes_module aes_instance;

Copy-paste the following setup code to your user application:

static void configure_usart(void)
{
struct usart_config config_usart;
usart_get_config_defaults(&config_usart);
config_usart.baudrate = 38400;
config_usart.mux_setting = EDBG_CDC_SERCOM_MUX_SETTING;
config_usart.pinmux_pad0 = EDBG_CDC_SERCOM_PINMUX_PAD0;
config_usart.pinmux_pad1 = EDBG_CDC_SERCOM_PINMUX_PAD1;
config_usart.pinmux_pad2 = EDBG_CDC_SERCOM_PINMUX_PAD2;
config_usart.pinmux_pad3 = EDBG_CDC_SERCOM_PINMUX_PAD3;
stdio_serial_init(&usart_instance, EDBG_CDC_MODULE, &config_usart);
}
static void aes_callback(void)
{
/* Read the output. */
state = true;
}
static void ecb_mode_test(void)
{
printf("\r\n-----------------------------------\r\n");
printf("- 128bit cryptographic key\r\n");
printf("- ECB cipher mode\r\n");
printf("- Auto start mode\r\n");
printf("- 4 32bit words\r\n");
printf("-----------------------------------\r\n");
state = false;
/* Configure the AES. */
g_aes_cfg.lod = false;
/* Set the cryptographic key. */
/* The initialization vector is not used by the ECB cipher mode. */
/* Write the data to be ciphered to the input data registers. */
/* Wait for the end of the encryption process. */
while (false == state) {
}
if ((ref_cipher_text_ecb[0] != output_data[0]) ||
(ref_cipher_text_ecb[1] != output_data[1]) ||
(ref_cipher_text_ecb[2] != output_data[2]) ||
(ref_cipher_text_ecb[3] != output_data[3])) {
printf("\r\nKO!!!\r\n");
} else {
printf("\r\nOK!!!\r\n");
}
printf("\r\n-----------------------------------\r\n");
printf("- 128bit cryptographic key\r\n");
printf("- ECB decipher mode\r\n");
printf("- Auto start mode\r\n");
printf("- 4 32bit words\r\n");
printf("-----------------------------------\r\n");
state = false;
/* Configure the AES. */
g_aes_cfg.lod = false;
/* Set the cryptographic key. */
/* The initialization vector is not used by the ECB cipher mode. */
/* Write the data to be deciphered to the input data registers. */
aes_write_input_data(&aes_instance, ref_cipher_text_ecb);
/* Wait for the end of the decryption process. */
while (false == state) {
}
/* check the result. */
if ((ref_plain_text[0] != output_data[0]) ||
(ref_plain_text[1] != output_data[1]) ||
(ref_plain_text[2] != output_data[2]) ||
(ref_plain_text[3] != output_data[3])) {
printf("\r\nKO!!!\r\n");
} else {
printf("\r\nOK!!!\r\n");
}
}
static void cbc_mode_test(void)
{
printf("\r\n-----------------------------------\r\n");
printf("- 128bit cryptographic key\r\n");
printf("- CBC cipher mode\r\n");
printf("- Auto start mode\r\n");
printf("- 4 32bit words\r\n");
printf("-----------------------------------\r\n");
state = false;
/* Configure the AES. */
g_aes_cfg.lod = false;
/* Set the cryptographic key. */
/* Set the initialization vector. */
/* Write the data to be ciphered to the input data registers. */
/* Wait for the end of the encryption process. */
while (false == state) {
}
if ((ref_cipher_text_cbc[0] != output_data[0]) ||
(ref_cipher_text_cbc[1] != output_data[1]) ||
(ref_cipher_text_cbc[2] != output_data[2]) ||
(ref_cipher_text_cbc[3] != output_data[3])) {
printf("\r\nKO!!!\r\n");
} else {
printf("\r\nOK!!!\r\n");
}
printf("\r\n-----------------------------------\r\n");
printf("- 128bit cryptographic key\r\n");
printf("- CBC decipher mode\r\n");
printf("- Auto start mode\r\n");
printf("- 4 32bit words\r\n");
printf("-----------------------------------\r\n");
state = false;
/* Configure the AES. */
g_aes_cfg.lod = false;
/* Set the cryptographic key. */
/* Set the initialization vector. */
/* Write the data to be deciphered to the input data registers. */
aes_write_input_data(&aes_instance, ref_cipher_text_cbc);
/* Wait for the end of the decryption process. */
while (false == state) {
}
if ((ref_plain_text[0] != output_data[0]) ||
(ref_plain_text[1] != output_data[1]) ||
(ref_plain_text[2] != output_data[2]) ||
(ref_plain_text[3] != output_data[3])) {
printf("\r\nKO!!!\r\n");
} else {
printf("\r\nOK!!!\r\n");
}
}
static void cfb128_mode_test(void)
{
printf("\r\n-----------------------------------\r\n");
printf("- 128bit cryptographic key\r\n");
printf("- CFB128 cipher mode\r\n");
printf("- Auto start mode\r\n");
printf("- 4 32bit words\r\n");
printf("-----------------------------------\r\n");
state = false;
/* Configure the AES. */
g_aes_cfg.lod = false;
/* Set the cryptographic key. */
/* Set the initialization vector. */
/* Write the data to be ciphered to the input data registers. */
/* Wait for the end of the encryption process. */
while (false == state) {
}
/* check the result. */
if ((ref_cipher_text_cfb128[0] != output_data[0]) ||
(ref_cipher_text_cfb128[1] != output_data[1]) ||
(ref_cipher_text_cfb128[2] != output_data[2]) ||
(ref_cipher_text_cfb128[3] != output_data[3])) {
printf("\r\nKO!!!\r\n");
} else {
printf("\r\nOK!!!\r\n");
}
printf("\r\n-----------------------------------\r\n");
printf("- 128bit cryptographic key\r\n");
printf("- CFB128 decipher mode\r\n");
printf("- Auto start mode\r\n");
printf("- 4 32bit words\r\n");
printf("-----------------------------------\r\n");
state = false;
/* Configure the AES. */
g_aes_cfg.lod = false;
/* Set the cryptographic key. */
/* Set the initialization vector. */
/* Write the data to be deciphered to the input data registers. */
aes_write_input_data(&aes_instance, ref_cipher_text_cfb128);
/* Wait for the end of the decryption process. */
while (false == state) {
}
/* check the result. */
if ((ref_plain_text[0] != output_data[0]) ||
(ref_plain_text[1] != output_data[1]) ||
(ref_plain_text[2] != output_data[2]) ||
(ref_plain_text[3] != output_data[3])) {
printf("\r\nKO!!!\r\n");
} else {
printf("\r\nOK!!!\r\n");
}
}
static void ofb_mode_test(void)
{
printf("\r\n-----------------------------------\r\n");
printf("- 128bit cryptographic key\r\n");
printf("- OFB cipher mode\r\n");
printf("- Auto start mode\r\n");
printf("- 4 32bit words\r\n");
printf("-----------------------------------\r\n");
state = false;
/* Configure the AES. */
g_aes_cfg.lod = false;
/* Set the cryptographic key. */
/* Set the initialization vector. */
/* Write the data to be ciphered to the input data registers. */
/* Wait for the end of the encryption process. */
while (false == state) {
}
/* check the result. */
if ((ref_cipher_text_ofb[0] != output_data[0]) ||
(ref_cipher_text_ofb[1] != output_data[1]) ||
(ref_cipher_text_ofb[2] != output_data[2]) ||
(ref_cipher_text_ofb[3] != output_data[3])) {
printf("\r\nKO!!!\r\n");
} else {
printf("\r\nOK!!!\r\n");
}
printf("\r\n-----------------------------------\r\n");
printf("- 128bit cryptographic key\r\n");
printf("- OFB decipher mode\r\n");
printf("- Auto start mode\r\n");
printf("- 4 32bit words\r\n");
printf("-----------------------------------\r\n");
state = false;
/* Configure the AES. */
g_aes_cfg.lod = false;
/* Set the cryptographic key. */
/* Set the initialization vector. */
/* Write the data to be deciphered to the input data registers. */
aes_write_input_data(&aes_instance, ref_cipher_text_ofb);
/* Wait for the end of the decryption process. */
while (false == state) {
}
/* check the result. */
if ((ref_plain_text[0] != output_data[0]) ||
(ref_plain_text[1] != output_data[1]) ||
(ref_plain_text[2] != output_data[2]) ||
(ref_plain_text[3] != output_data[3])) {
printf("\r\nKO!!!\r\n");
} else {
printf("\r\nOK!!!\r\n");
}
}
static void ctr_mode_test(void)
{
printf("\r\n-----------------------------------\r\n");
printf("- 128bit cryptographic key\r\n");
printf("- CTR cipher mode\r\n");
printf("- Auto start mode\r\n");
printf("- 4 32bit words\r\n");
printf("-----------------------------------\r\n");
state = false;
/* Configure the AES. */
g_aes_cfg.lod = false;
/* Set the cryptographic key. */
/* Set the initialization vector. */
aes_write_init_vector(&aes_instance, init_vector_ctr);
/* Write the data to be ciphered to the input data registers. */
/* Wait for the end of the encryption process. */
while (false == state) {
}
/* check the result. */
if ((ref_cipher_text_ctr[0] != output_data[0]) ||
(ref_cipher_text_ctr[1] != output_data[1]) ||
(ref_cipher_text_ctr[2] != output_data[2]) ||
(ref_cipher_text_ctr[3] != output_data[3])) {
printf("\r\nKO!!!\r\n");
} else {
printf("\r\nOK!!!\r\n");
}
printf("\r\n-----------------------------------\r\n");
printf("- 128bit cryptographic key\r\n");
printf("- CTR decipher mode\r\n");
printf("- Auto start mode\r\n");
printf("- 4 32bit words\r\n");
printf("-----------------------------------\r\n");
state = false;
/* Configure the AES. */
g_aes_cfg.lod = false;
/* Set the cryptographic key. */
/* Set the initialization vector. */
aes_write_init_vector(&aes_instance, init_vector_ctr);
/* Write the data to be deciphered to the input data registers. */
aes_write_input_data(&aes_instance, ref_cipher_text_ctr);
/* Wait for the end of the decryption process. */
while (false == state) {
}
/* check the result. */
if ((ref_plain_text[0] != output_data[0]) ||
(ref_plain_text[1] != output_data[1]) ||
(ref_plain_text[2] != output_data[2]) ||
(ref_plain_text[3] != output_data[3])) {
printf("\r\nKO!!!\r\n");
} else {
printf("\r\nOK!!!\r\n");
}
}

Add to user application initialization (typically the start of main()):

Workflow

  1. Define sample data from NIST-800-38A appendix F for ECB mode.
    #define AES_EXAMPLE_REFBUF_SIZE 4
    /* @{ */
    uint32_t ref_plain_text[AES_EXAMPLE_REFBUF_SIZE] = {
    0xe2bec16b,
    0x969f402e,
    0x117e3de9,
    0x2a179373
    };
    uint32_t ref_cipher_text_ecb[AES_EXAMPLE_REFBUF_SIZE] = {
    0xb47bd73a,
    0x60367a0d,
    0xf3ca9ea8,
    0x97ef6624
    };
    uint32_t ref_cipher_text_cbc[AES_EXAMPLE_REFBUF_SIZE] = {
    0xacab4976,
    0x46b21981,
    0x9b8ee9ce,
    0x7d19e912
    };
    uint32_t ref_cipher_text_cfb128[AES_EXAMPLE_REFBUF_SIZE] = {
    0x2ed93f3b,
    0x20ad2db7,
    0xf8493433,
    0x4afb3ce8
    };
    uint32_t ref_cipher_text_ofb[AES_EXAMPLE_REFBUF_SIZE] = {
    0x2ed93f3b,
    0x20ad2db7,
    0xf8493433,
    0x4afb3ce8
    };
    uint32_t ref_cipher_text_ctr[AES_EXAMPLE_REFBUF_SIZE] = {
    0x91614d87,
    0x26e320b6,
    0x6468ef1b,
    0xceb60d99
    };
    const uint32_t key128[4] = {
    0x16157e2b,
    0xa6d2ae28,
    0x8815f7ab,
    0x3c4fcf09
    };
    const uint32_t init_vector[4] = {
    0x03020100,
    0x07060504,
    0x0b0a0908,
    0x0f0e0d0c
    };
    const uint32_t init_vector_ctr[4] = {
    0xf3f2f1f0,
    0xf7f6f5f4,
    0xfbfaf9f8,
    0xfffefdfc
    };
    /* @} */
  2. Create related module variable and software instance structure.
    /* Output data array */
    static uint32_t output_data[AES_EXAMPLE_REFBUF_SIZE];
    /* State indicate */
    volatile bool state = false;
    struct aes_module aes_instance;
  3. Configure, initialize, and enable AES module.
    1. Configuration AES struct, which can be filled out to adjust the configuration of a physical AES peripheral.
    2. Initialize the AES configuration struct with the module's default values.
    3. Enable the AES module.
    4. Register and enable the AES module callback.

Use Case

Code

Copy-paste the following code to your user application:

Workflow

  1. Configure ECB mode encryption and decryption and run test.
  2. Configure CBC mode encryption and decryption and run test.
  3. Configure CFB mode encryption and decryption and run test.
  4. Configure OFB mode encryption and decryption and run test.
  5. Configure CTR mode encryption and decryption and run test.