About Me
Policy Analysis

Implementations of AES (Rijndael) in C/C++ and Assembler

  1. 6th December - improved the Visual Basic for Applications (VBA) example of how the AES DLL
    is used from VBA and added a Microsoft Word document that contains this VBA source code.
  2. 16th January 2002 - Significant simplification and restructuring of the code to make it easier to use.
    BUT NOTE that there are changes to the cipher interface.  My thanks to David Hopwood for finding
    an error in the interface code and to Nigel Metheringham for some restructuring suggestions.
  3. 21st January - update to make code integration easier (suggested by Peter Gutmann).
  4. 28th January - update to correct an error in endian detection (my thanks to Gary Gorbet for testing
    this release on a wide range of big and little endian systems).
  5. 8th February - update to overcome macro expansion limits in some compilers when compiling aestab.c
    (reported by Peter Gutmann).
  6. 5th April 2002 - minor release to remove a few TAB characters that confused some compilers and to add
    project files for Visual Studio .Net development.
  7. 8th June 2002 - a small update to remove a compilation failure that occurred on a rare combination of options
    (reported by Atasu Kubilay).
  8. 27 September 2002 - this release does not involve any bug fixes.  It removes the use of the 'standard' fixed
    width integer types (more trouble than they are worth at the moment).  It also changes the AES example
    code to use ciphertext stealing.
  9. 6th June 2003 - added revised code for AES with support for royalty free combined encryption/authentication modes

New Code

I have recently updated my AES code and the new version is available here.  Since the interface has changed, the previous version remains available here but it won't now be updated.  The main aim of the new code is to concentrate on AES only and to offer a simpler interface with more compile time parameter checking.   The new code also supports x86 assembler versions for both integer and MMX operations and can achieve about 17 cycles per byte on a P4 processor (the best code achieves about 14 cycles per byte but is not free).

Algorithm Specification

I have taken an interest in helping to ensure that the Rijndael and AES specifications are effective from an implementation perspective and I wrote an early input paper to the US NIST AES FIPS development with this in mind. I have since further developed this original input document into a full description of Rijndael which I make available here as a Adobe Acrobat PDF file.

Algorithm Code in C/C++

This code implements both AES and Rijndael. The standard code implements block sizes of 16, 24 and 32 bytes, fixed during compilation, and a variable block size option covering these block sizes chosen at time of use. Each of these options operates with key sizes of 16, 24 and 32 bytes chosen at time of use.  An alternative implementation offers block and key sizes of 16, 20, 24, 28 and 32 bytes.

The standard implementation provides AES when implemented with a block size of 16 bytes.  This is heavily optimised, especially for the 16 byte key size.  The variable block size option is much slower and is not recommended unless this is really needed. The alternative implementation is also less optimised.

The code is arranged so that encryption and decryption operations are entirely separate so that encryption only and decryption only applications can be produced without the overhead of the other mode.  This has been possible because speed optimisations have allowed the decryption schedule to be compiled directly without relying on the encryption key schedule without compromising speed. 

The C interface is:

aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]); /* set the block length (if it is variable) */

aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]);    /* set the encryption key */
aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]); /* encrypt block */

aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]);   /* set the decryption key */
aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]);/* decrypt block */

The code has also been optimised so that only the tables required are compiled into the code. It has also been divided into components so that the compilation options can be more easily set (these are also more fully explained).   Lastly there is fully integrated x86 assembler code for the standard AES encryption and decryption operations.

This code supports all Rijndael block sizes. It can be compiled with a fixed or a variable block size (although the latter involves a very significant performance penalty). The block and key sizes are specified in units of bytes to match the associated input arrays (legal values 16, 24 and 32) . The input parameters are checked for correctness and the encrypt and decrypt routines check that an appropriate key has been set up. The functions hence return a success or failure value.  For the variable block size version there is a call to set the block size, a value of 16 being assumed if this is not set (i.e. the AES standard block size).

The source code for the algorithm is in C but there is a C++ interface as well.  The main files are:

aes.h The main C header file for the cipher
aescpp.h A C++ header file that provides a class interface for the cipher
aesopt.h The header file for setting compilation options (also contains shared code)
uitypes.h A header file for defining unsigned integer types of specified length
aescrypt.c encryption and decryption for block and key sizes of 16, 24 and 32 bytes
aescrypt.asm x86 assembler code for AES encryption and decryption (16 byte blocks)
aeskey.c key schedule generation for  block and key sizes of 16, 24 and 32 bytes
aestab.c The file that implements the tables needed by the cipher
aescrypp.c encryption and decryption for block and key sizes of 16, 20, 24, 28 and 32 bytes
aeskeypp.c key schedule generation for  block and key sizes of 16, 20 24, 28 and 32 bytes

These files are in the zip archive aessrc.zip.  The full Microsoft project for the code development is in the archive aestest.zip (this file includes the source code files in aessrc.zip).

Algorithm Code in Pentium Family Assembler

There is an assembler code source file for the encryption and decryption subroutines for the Pentium family (Pentium II/III/IV). This version only implement the standard block size of 16 bytes (128 bits) but is 20% faster than the C/C++ code. It achieves a maximum speed with a fully primed processor cache of about 280 cycles/block, which is around 58 Mbytes/second on a 1GHz processor.  Note also that it uses the Microsoft VC++ register saving conventions and may need to be modified to work with other C/C++ compilers.  The code uses the NASM assembler available here and integrates with the C/C++ code for key scheduling and table generation.

If you need still more speed Helger Lipmaa has a commercial version here that achieves around 229 cycles/block.

Test Vectors

This zip file contains a full set of round values for each of the 25 block and key length combinations from 128, 160, 192, 224 and 256 bits for one input block and one key value.

These zip files contain the variable key and variable text test vectors for the same 25 combinations of block and key lengths

These zip files contain proposed new variable key and variable text test vectors proposed by Paulo Barreto and myself as replacements for the current versions.  These are designed to assist in finding errors in byte order within input, output and key blocks.

Dynamic Link Libraries

The code can be compiled into a Dynamic Link Library and the file aesdll.zip contains a DLL for the AES standard (fixed) block size of 16 bytes. Other versions of this DLL can be compiled from the source code if needed.

This DLL can be called from any language that supports DLL use, including both Microsoft Visual Basic and Visual Basic for Applications (VBA).  This zip file provides an example of use in VBA hosted in a Microsoft Word document that contains example VBA source code as text and as a macro that can be run to show its operation.

Example Application

I am often asked for an example of how to use the algorithm code on this page so I have now produced a simple file console mode encryption application. The file aesxam.c encrypts a file with a user provided key using a command line as follows:

    aesxam input_file_name output_file_name [d|e] hexadecimal_key_digits

For example:

    aesxam aes.c aes.enc e 0123456789abcdeffedcba9876543210

will encrypt aes.c to aes.enc with the key given. The file is then decrypted by using 'd' instead of 'e'.  Here is a zip file containing the example source code and a binary executable for Windows in console mode.  This is an example application that is not intended for real use, I believe it works correctly but I cannot guarantee this. Hence if you do use it, you do so at your own risk.

A Note on Algorithm Speed

The timing values quoted here are the best available (i.e. the fastest) from this code and are not representative of the sort of speed that will be achieved in practice, especially when small numbers of blocks are being processed.  This is because the way I do the timing is by running the code on a particular set of input values before I time it using the same values.  I am hence giving the speed achieved with the processor's data cache fully primed. 

In encryption (or decryption) operations involving a small number of blocks the processor cache will not necessarily be primed and this will mean that the performance will be severely degraded compared with the figures given here.  However as the number of blocks being encrypted increases, the processor cache progressively accumulates values from the tables and the performance for large numbers of blocks becomes close to the best figures given here.

For the highest speed, this code uses a maximum of 20 tables of 256 32-bit words, a total of 20Kbytes of data.

I don't offer the other test vectors because the files are too large.

All the source code used to create the application is available on this page so you can check it out yourself.  They are also quite simple since both the applications and the AES algorithm are not difficult to understand and this makes them useful for those who believe that security is best achieved by keeping things simple.

Code Use

I am happy for this code to be used without payment provided that I don't carry any risks as a result.  I would appreciate an appropriate acknowledgement of the source of the code if you do use it in a product or activity provided to third parties.   I would also be grateful for feedback on how the code is being used, any problems you encounter, any changes or additions that are desirable for particular processors and any more general improvements you would like to see (no promises mind!).


I would like to thank the following individuals who have made contributions in the development of this code:

Karl M. Syring.
Eugene Mayevski
Frank Yellin
Chris Heath
Peter Gutmann
Rainer Nausedat
Ganapathi Bhat
Kevin Steves
Theo de Raadt
David Wagner
Malcolm Smith
Helger Lipmaa
David Hopwood
Nigel Metheringham

Back to Brian Gladman's Home Page.