element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      • Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Personal Blogs
  • Community Hub
  • More
Personal Blogs
Legacy Personal Blogs EFM32™︎ Zero Gecko: Encryption with AES
  • Blog
  • Documents
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 8 Dec 2014 8:04 PM Date Created
  • Views 621 views
  • Likes 4 likes
  • Comments 0 comments
  • 128_bit_aes_data_encryption
  • arm_cortex
  • aes
  • efm32
  • encryption
  • feature_tutorial
  • zero_gecko
Related
Recommended

EFM32™︎ Zero Gecko: Encryption with AES

Jan Cumps
Jan Cumps
8 Dec 2014

I hadn't reviewed the encryption module of the Zero Gecko microcontroller yet.

 

The Zero Gecko processor family supports an accelerator for encryption and decryption. Simplicity Studio comes with application note AN0033 and example projects.

The examples don't target the Zero Gecko. But they have enough info to get you started.

I loaded the example 'EFM32G_aes_cbc_128', a 128 bit CBC (Cipher Block Chaining) example.

 

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

My first step was to understand what the example is doing.

 

Overview of the AN0033 example

 

There are two arrays with example data. One structure has the unencryped data (exampledata[]), the other has the same data encrypted by a known key and seed (expectedEncryptedData[]).

const uint8_t exampleData[] = { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
                                0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
                                0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
                                0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
                                0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
                                0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
                                0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
                                0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10};

const uint8_t expectedEncryptedData[] = { 0x76, 0x49, 0xAB, 0xAC, 0x81, 0x19, 0xB2, 0x46,
                                          0xCE, 0xE9, 0x8E, 0x9B, 0x12, 0xE9, 0x19, 0x7D,
                                          0x50, 0x86, 0xCB, 0x9B, 0x50, 0x72, 0x19, 0xEE,
                                          0x95, 0xDB, 0x11, 0x3A, 0x91, 0x76, 0x78, 0xB2,
                                          0x73, 0xBE, 0xD6, 0xB8, 0xE3, 0xC1, 0x74, 0x3B,
                                          0x71, 0x16, 0xE6, 0x9E, 0x22, 0x22, 0x95, 0x16,
                                          0x3F, 0xF1, 0xCA, 0xA1, 0x68, 0x1F, 0xAC, 0x09,
                                          0x12, 0x0E, 0xCA, 0x30, 0x75, 0x86, 0xE1, 0xA7};

 

The example first prepares the encryption and decryption keys.

const uint8_t exampleKey[] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
                               0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C};
// ...


const uint8_t initVector[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
                               0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};


// ...

  /* Enable AES clock */
  CMU_ClockEnable(cmuClock_AES, true);


  /* Calculate decryption key from the original key, needs to be done once for each key */
  AES_DecryptKey128(decryptionKey, exampleKey);

 

Then it encrypts the plain data. And as a validation, it compares the result with what is expected (the predefined array of encrypted data expectedEncryptedData[]).

  /* Encrypt data in AES_128 CBC */
  AesCBC128(exampleKey,
            dataBuffer,
            dataBuffer,
            false,
            sizeof(dataBuffer) / (sizeof(dataBuffer[0]) * 16),
            initVector);


  /* Wait for AES to finish */
  while(!AesFinished());

  /* Check whether encrypted results are correct */
  for (i = 0; i < (sizeof(dataBuffer) / sizeof(dataBuffer[0])); i++)
  {
    if (dataBuffer[i] != expectedEncryptedData[i])
    {
      error = true;
    }
  }

 

The next step is to do the reverse. Encrypted data gets decrypted (this time using the decryption key generated at the start of the program in the AES_DecryptKey128() call).

That decrypted result is compared with the original plain data.

 

The example's implementation of AES128 CDC

 

The example talks directly to the AES registers. It also uses the AES interrupt to perform part of the encrypt/decrypt actions.

void AesCBC128(const uint8_t* key,
               const uint8_t* inputData,
               uint8_t*       outputData,
               bool           decrypt,
               const uint32_t blockNumber,
               const uint8_t* iv)
{
// ...
  AES->IEN = AES_IEN_DONE;
  NVIC_EnableIRQ(AES_IRQn);



  /* Write the KEY to AES module */
  /* Writing only the KEYHA 4 times will transfer the key to all 4
   * high key registers, used here, in 128 bit key mode, as buffers */ 
  for (i = 3; i >= 0; i--)
  {
    AES->KEYLA = __REV(key32[i]);
  }


  /* Decryption */
  if (decryptG)
  {
    /* Configure AES module */
    AES->CTRL = AES_CTRL_DECRYPT |     /* Set decryption */
//                AES_CTRL_KEYBUFEN |    /* Use key buffering */
                AES_CTRL_DATASTART;    /* Start decryption on data write */


    /* Make a copy of the initial vector */
    for (i = 0; i < 4; i++)
    {
      prev[i] = iv32[i];
    }


    /* Load data and trigger a decryption */ 
    for (i = 3; i >= 0; i--)
    {
      AES->DATA = __REV(inputDataG[i]);
    }
  }


  /* Encryption */
  else
  {
    AES->CTRL = /*AES_CTRL_KEYBUFEN |   */  /* Use key buffering */
                AES_CTRL_XORSTART;      /* Start encryption on data write */


    /* Writing to the DATA register here does NOT trigger encryption */   
    for (i = 3; i >= 0; i--)
    {
      AES->DATA = __REV(iv32[i]);
    } 


    /* Load data and trigger encryption using XORDATA*/  
    for (i = 3; i >= 0; i--)
    {
      AES->XORDATA = __REV(inputDataG[i]);
    } 
  }
}

 

 

and the supporting interrupt handler:

void AES_IRQHandler(void)
{
  // ...

  /* Clear interrupt flag */
  AES->IFC = AES_IFC_DONE;


  /* Decryption */
  if (decryptG)
  {
    if (blockIndex < numberOfBlocks)
    {
      /* Writing to the XOR register here does NOT trigger decryption*/  
      for (i = 3; i >= 0; i--)
      {
        AES->XORDATA = __REV(prev[i]);
        prev[i]      = inputDataG[i];
      }
      inputDataG += 4;


      /* Store decrypted data */     
      for (i = 3; i >= 0; i--)
      {
        outputDataG[i] = __REV(AES->DATA);
      }
      outputDataG += 4;


      /* Load data and trigger a decryption */ 
      for (i = 3; i >= 0; i--)
      {
        AES->DATA = __REV(inputDataG[i]);
      }
    }


    /* Indicate last block */
    else
    {
      aesFinished = true;
    }


    /* Increase block index */
    blockIndex++;
  }


  /* Encryption */
  else
  {
    /* Store encrypted data */
    for (i = 3; i >= 0; i--)
    {
      outputDataG[i] = __REV(AES->DATA);
    }


    outputDataG += 4;


    if (blockIndex < numberOfBlocks)
    {
      /* If not last block, write new data to be decrypted. */
      /* AES is started automatically by the last write */
      inputDataG += 4;    
      for (i = 3; i >= 0; i--)
      {
        AES->XORDATA = __REV(inputDataG[i]);
      } 
    }


    /* Indicate last block */
    else
    {
      aesFinished = true;
    }


    /* Increase block index */
    blockIndex++;
  }
}

 

The validation of the work is fully completed:

bool AesFinished(void)
{
  return aesFinished;
}

 

I wanted to check the functionality of the AES Peripheral API in stead.

 

 

My simplified example

 

The only changes I had to make to the whole project are all in the source file aes_cbc_128.c :

 

I removed the interrupt handler AES_IRQHandler() completely.

 

The function AesCBC128() (with the low level implementation using the registers and interrupt) was replaced by a single function call to the AES API:

void AesCBC128(const uint8_t* key,
               const uint8_t* inputData,
               uint8_t*       outputData,
               bool           decrypt,
               const uint32_t blockNumber,
               const uint8_t* iv)
{


  AES_CBC128(outputData,
  inputData,
  blockNumber * 16 , // AES_BLOCKSIZE
                 key,
                 iv,
                 ! decrypt);
}

 

And to avoid that I had to change the main example code, I changed the AesFinished() function to just return true. The main code uses this function to check that the work is finished.

The API implementation only returns when the encryption or decryption is complete, so we are ok to always return true.

bool AesFinished(void)
{
  return true;
}

 

The result is a less advanced implementation. On the other hand it's also simpler and easier to understand as first step into the AES module.

 

I've attached the zero gecko project for Simplicity Studio.

Attachments:
STK3200_aes_cbc_128.zip
  • Sign in to reply
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube