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
};
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
};
/* @} */

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_config g_aes_cfg;
struct aes_module aes_instance;
struct usart_module usart_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);
usart_enable(&usart_instance);
}
static void aes_callback(void)
{
/* Read the output. */
aes_read_output_data(&aes_instance, output_data);
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.encrypt_mode = AES_ENCRYPTION;
g_aes_cfg.key_size = AES_KEY_SIZE_128;
g_aes_cfg.start_mode = AES_AUTO_START;
g_aes_cfg.opmode = AES_ECB_MODE;
g_aes_cfg.cfb_size = AES_CFB_SIZE_128;
g_aes_cfg.lod = false;
aes_set_config(&aes_instance,AES, &g_aes_cfg);
/* Set the cryptographic key. */
aes_write_key(&aes_instance, key128);
/* The initialization vector is not used by the ECB cipher mode. */
aes_set_new_message(&aes_instance);
/* Write the data to be ciphered to the input data registers. */
aes_write_input_data(&aes_instance, ref_plain_text);
aes_clear_new_message(&aes_instance);
/* 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.encrypt_mode = AES_DECRYPTION;
g_aes_cfg.key_size = AES_KEY_SIZE_128;
g_aes_cfg.start_mode = AES_AUTO_START;
g_aes_cfg.opmode = AES_ECB_MODE;
g_aes_cfg.cfb_size = AES_CFB_SIZE_128;
g_aes_cfg.lod = false;
aes_set_config(&aes_instance,AES, &g_aes_cfg);
/* Set the cryptographic key. */
aes_write_key(&aes_instance, key128);
/* The initialization vector is not used by the ECB cipher mode. */
aes_set_new_message(&aes_instance);
/* Write the data to be deciphered to the input data registers. */
aes_write_input_data(&aes_instance, ref_cipher_text_ecb);
aes_clear_new_message(&aes_instance);
/* 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.encrypt_mode = AES_ENCRYPTION;
g_aes_cfg.key_size = AES_KEY_SIZE_128;
g_aes_cfg.start_mode = AES_MANUAL_START;
g_aes_cfg.opmode = AES_CBC_MODE;
g_aes_cfg.cfb_size = AES_CFB_SIZE_128;
g_aes_cfg.lod = false;
aes_set_config(&aes_instance,AES, &g_aes_cfg);
/* Set the cryptographic key. */
aes_write_key(&aes_instance, key128);
/* Set the initialization vector. */
aes_write_init_vector(&aes_instance, init_vector);
/* Write the data to be ciphered to the input data registers. */
aes_write_input_data(&aes_instance, ref_plain_text);
aes_set_new_message(&aes_instance);
aes_start(&aes_instance);
aes_clear_new_message(&aes_instance);
/* 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.encrypt_mode = AES_DECRYPTION;
g_aes_cfg.key_size = AES_KEY_SIZE_128;
g_aes_cfg.start_mode = AES_AUTO_START;
g_aes_cfg.opmode = AES_CBC_MODE;
g_aes_cfg.cfb_size = AES_CFB_SIZE_128;
g_aes_cfg.lod = false;
aes_set_config(&aes_instance,AES, &g_aes_cfg);
/* Set the cryptographic key. */
aes_write_key(&aes_instance, key128);
/* Set the initialization vector. */
aes_write_init_vector(&aes_instance, init_vector);
aes_set_new_message(&aes_instance);
/* Write the data to be deciphered to the input data registers. */
aes_write_input_data(&aes_instance, ref_cipher_text_cbc);
aes_clear_new_message(&aes_instance);
/* 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.encrypt_mode = AES_ENCRYPTION;
g_aes_cfg.key_size = AES_KEY_SIZE_128;
g_aes_cfg.start_mode = AES_MANUAL_START;
g_aes_cfg.opmode = AES_CFB_MODE;
g_aes_cfg.cfb_size = AES_CFB_SIZE_128;
g_aes_cfg.lod = false;
aes_set_config(&aes_instance,AES, &g_aes_cfg);
/* Set the cryptographic key. */
aes_write_key(&aes_instance, key128);
/* Set the initialization vector. */
aes_write_init_vector(&aes_instance, init_vector);
/* Write the data to be ciphered to the input data registers. */
aes_write_input_data(&aes_instance, ref_plain_text);
aes_set_new_message(&aes_instance);
aes_start(&aes_instance);
aes_clear_new_message(&aes_instance);
/* 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.encrypt_mode = AES_DECRYPTION;
g_aes_cfg.key_size = AES_KEY_SIZE_128;
g_aes_cfg.start_mode = AES_MANUAL_START;
g_aes_cfg.opmode = AES_CFB_MODE;
g_aes_cfg.cfb_size = AES_CFB_SIZE_128;
g_aes_cfg.lod = false;
aes_set_config(&aes_instance,AES, &g_aes_cfg);
/* Set the cryptographic key. */
aes_write_key(&aes_instance, key128);
/* Set the initialization vector. */
aes_write_init_vector(&aes_instance, init_vector);
/* Write the data to be deciphered to the input data registers. */
aes_write_input_data(&aes_instance, ref_cipher_text_cfb128);
aes_set_new_message(&aes_instance);
aes_start(&aes_instance);
aes_clear_new_message(&aes_instance);
/* 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.encrypt_mode = AES_ENCRYPTION;
g_aes_cfg.key_size = AES_KEY_SIZE_128;
g_aes_cfg.start_mode = AES_AUTO_START;
g_aes_cfg.opmode = AES_OFB_MODE;
g_aes_cfg.cfb_size = AES_CFB_SIZE_128;
g_aes_cfg.lod = false;
aes_set_config(&aes_instance,AES, &g_aes_cfg);
/* Set the cryptographic key. */
aes_write_key(&aes_instance, key128);
/* Set the initialization vector. */
aes_write_init_vector(&aes_instance, init_vector);
aes_set_new_message(&aes_instance);
/* Write the data to be ciphered to the input data registers. */
aes_write_input_data(&aes_instance, ref_plain_text);
aes_clear_new_message(&aes_instance);
/* 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.encrypt_mode = AES_DECRYPTION;
g_aes_cfg.key_size = AES_KEY_SIZE_128;
g_aes_cfg.start_mode = AES_MANUAL_START;
g_aes_cfg.opmode = AES_OFB_MODE;
g_aes_cfg.cfb_size = AES_CFB_SIZE_128;
g_aes_cfg.lod = false;
aes_set_config(&aes_instance,AES, &g_aes_cfg);
/* Set the cryptographic key. */
aes_write_key(&aes_instance, key128);
/* Set the initialization vector. */
aes_write_init_vector(&aes_instance, init_vector);
/* Write the data to be deciphered to the input data registers. */
aes_write_input_data(&aes_instance, ref_cipher_text_ofb);
aes_set_new_message(&aes_instance);
aes_start(&aes_instance);
aes_clear_new_message(&aes_instance);
/* 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.encrypt_mode = AES_ENCRYPTION;
g_aes_cfg.key_size = AES_KEY_SIZE_128;
g_aes_cfg.start_mode = AES_AUTO_START;
g_aes_cfg.opmode = AES_CTR_MODE;
g_aes_cfg.cfb_size = AES_CFB_SIZE_128;
g_aes_cfg.lod = false;
aes_set_config(&aes_instance,AES, &g_aes_cfg);
/* Set the cryptographic key. */
aes_write_key(&aes_instance, key128);
/* Set the initialization vector. */
aes_write_init_vector(&aes_instance, init_vector_ctr);
aes_set_new_message(&aes_instance);
/* Write the data to be ciphered to the input data registers. */
aes_write_input_data(&aes_instance, ref_plain_text);
aes_clear_new_message(&aes_instance);
/* 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.encrypt_mode = AES_DECRYPTION;
g_aes_cfg.key_size = AES_KEY_SIZE_128;
g_aes_cfg.start_mode = AES_MANUAL_START;
g_aes_cfg.opmode = AES_CTR_MODE;
g_aes_cfg.cfb_size = AES_CFB_SIZE_128;
g_aes_cfg.lod = false;
aes_set_config(&aes_instance,AES, &g_aes_cfg);
/* Set the cryptographic key. */
aes_write_key(&aes_instance, key128);
/* 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);
aes_set_new_message(&aes_instance);
aes_start(&aes_instance);
aes_clear_new_message(&aes_instance);
/* 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()):

/* Initialize the system and console*/
configure_usart();
aes_init(&aes_instance,AES, &g_aes_cfg);
aes_enable(&aes_instance);
/* Enable AES interrupt. */

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_config g_aes_cfg;
    struct aes_module aes_instance;
    struct usart_module usart_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.
      aes_init(&aes_instance,AES, &g_aes_cfg);
    3. Enable the AES module.
      aes_enable(&aes_instance);
    4. Register and enable the AES module callback.

Use Case

Code

Copy-paste the following code to your user application:

ecb_mode_test();
cbc_mode_test();
cfb128_mode_test();
ofb_mode_test();
ctr_mode_test();

Workflow

  1. Configure ECB mode encryption and decryption and run test.
    ecb_mode_test();
  2. Configure CBC mode encryption and decryption and run test.
    cbc_mode_test();
  3. Configure CFB mode encryption and decryption and run test.
    cfb128_mode_test();
  4. Configure OFB mode encryption and decryption and run test.
    ofb_mode_test();
  5. Configure CTR mode encryption and decryption and run test.
    ctr_mode_test();