Advanced Encryption Standard (AES) on embedded system

by François Finfe | Project initiated on December 2008 | Last update: January 01 2009 23:59:16.

Introduction

The Advanced Encryption Standard (AES), also known as Rijndael, is a block cipher adopted as an encryption standard by the U.S. government. It has been analyzed extensively and is now used worldwide, as was the case with its predecessor, the Data Encryption Standard (DES). AES is one of the most popular algorithms used in symmetric key cryptography. It is available by choice in many different encryption packages. AES is the first publicly accessible and open cipher approved by the NSA for top secret information (see Security of AES, below).

The cipher was developed by two Belgian cryptographers, Joan Daemen and Vincent Rijmen.

Unlike DES (the predecessor of AES), AES is a substitution-permutation network. Compared to DES, AES is fast in both software and hardware, is relatively easy to implement, and requires little memory. As a new encryption standard, it is currently being deployed on a large scale. The AES algorithme run much faster than its predessor (Triple DES, also knowed as TDES or 3DES).

This article present to code implementation of the AES algorithme on a 8-bit environment (PIC18F) and a 32-bit environment (ARM Cortex M3).
The purpose is not to present the most efficient code. Commercial library had already been released, some are written in ASM for more efficiency on the target processor.

The aim is neither to explain how AES work. If you are looking for this information, just take a look on the wikipedia page and on the external link of it.

In most cases, programs are compromises between speed and code size. The first implementation, on a PICmicro is more optimised for space than for speed. The second (ARM) has been optimised for speed, because ARM are more endow of memory.

Reference source of a part of this paragraph is wikipedia.

Implementation on PIC18 microcontroller, using C18 compiler.

For this implementation, I've based on this C code from Niyaz PK.

As the author said, the main feature of this AES implementation is not efficiency. It is simplicity and readability. However, I have performe some modifications, mainly to perform time optimisations and code size.

You can select the key size (128, 192 or 256 bits) with a "#define key_size" in the AES header file.

This code has been written for C18 compiler from Microchip.

How to use this code ?

First of all, put your AES key in the unsigned char array Key. This variable is a global variable of aes.c. The size of the key is defined in the header with key_size (in bits). The size of the array is key_size/8 (16 bytes for 128 bits, 24 bytes for 192 and so on ...)

If you want, you can directly initiate the array in the aes.c file by:

unsigned char Key[key_size/8] = {0x00 ,0x01 ,0x02 ,0x03 ,0x04 ,0x05 ,0x06 ,0x07 ,0x08 ,0x09 ,0x0a ,0x0b ,0x0c ,0x0d ,0x0e ,0x0f};

Next, we need to expand the key. This is simply done by the function "void KeyExpansion()". The key expanded is store in the global variable char array "RoundKey".

If you always use the same key, an optimisation could be done by pre-computing (not with the uC) the roundKey and declare it as constant rom array in the program. You will spare program memory and ram memory.

KeyExpansion must be called one time: when the algo start or when you change the key. Ones done, you can call Cipher() and InvCipher() many times. It's unuseful to recall keyExpansion() before each Cipher or InvCipher() call.

To encrypt data (by packet of 16 bytes), put the plaintext data (data to be ciphered) in the global variable char array in (buffer). Than, call Cipher(). Crypted data are stored in the var out.

Decryption work in the same way. Put ciphered data in char array "out" and retrieve clear data in the "in" buffer.

Here is a small code example:
void main()
{
extern unsigned char in[16];
extern unsigned char out[16];

// Put "Hello World !!!\0" in the input buffer.
sprintf(in,"Hello World !!!");

// The KeyExpansion routine must be called before encryption.
KeyExpansion();

// The next function call encrypts the PlainText with the Key using AES algorithm.
Cipher();

// content of in buffer is: 48 6c 6c 6c 6f 20 57 6f 72 6c 64 20 21 21 21 00
// content of out buffer is: 0b c9 19 32 c6 be 88 bf 55 24 49 45 b3 1f 00 b9

// The next function call decrypts the crypted data with the Key using AES algorithm.
InvCipher();

Code size

This algorithme need about 2K2 word of ROM (program memory) and 240 bytes of RAM to perform 128 bit encryption.

Execution time

Simulations where made with the simulator of MPLAB IDE, using a PIC18F4620 and a 40 MHz clock (or a 10-MHz-crystal + PLL x 4).

Function Time
KeyExpansion() 28K cycles - 2.8 ms
Cipher() 40K cycles - 4 ms
InvCipher() 110K cycles - 11 ms

Source

AES.c

AES.h

Download

Description Lien/Fichier(s)

Implementation on ARM M3 cortex microcontroller, using RealView compiler.

C compiler for ARM is very much closer to ANSI-C than 8-bit C compiler.

A lot of implementations already exist on the web for 32-bit controller. I just extract and adapt the mains functions of this source.