Inline AES 256 / CBC Implementation

Today I like to share some encryption code, which can be used in various situations – and is also useful for embedded systems.

It is a unique implementation of the AES 256 / CBC crypto algorithm. The goal of this implementation was neither speed nor size. It was written to inline it into existing code.

The compiler will create a new instance of the algorithm on the fly, at the place where you insert it into the code. Depending of used optimization flags, this inlined code can get very compact.


I had numerous goals and constraints while I created this implementation:

  • Completely inline.
  • Generated by the compiler on the fly.
  • Easy to read and understand.
  • Suitable for embedded processors.
  • No static tables (S-Box) in memory or the binary.
  • Minimal dependencies (just stdint and cstddef headers).
  • Compatible with other AES 256 / CBC implementation.

The following things were not relevant to me:

  • Speed
  • Size
  • Multiple algorithms
  • Error checking of inputs

Requirements and Usage

The requirements are very minimal, all what you need is a C++17 compatible compiler which provides the stdint and cstddef headers for the uint32_t types and the size_t type.

Using the code is very simple because you just add an include to it:

#include "../InlineAES256/CBC.hpp"

#include <iostream>
#include <iomanip>
#include <string>

using namespace lrcrypto;

void hexBlock(const uint8_t *data, size_t size) {
    for (size_t i = 0; i < size; ++i) {
        std::cout << std::internal << std::setw(2) << std::setfill('0')
            << std::hex << static_cast<int>(data[i]);
        std::cout << " ";
    std::cout << std::endl;

int main(int argc, const char * argv[]) {
	// Do _not_ store your key in a real application!
    const uint8_t key[aes256::cKeySizeBytes] = {
        0x4e, 0x89, 0x5a, 0xb7, 0xaf, 0x3d, 0xf6, 0xcf,
        0x6d, 0x22, 0x86, 0x01, 0x32, 0x0a, 0x8a, 0xa7,
        0x7b, 0x61, 0x2d, 0xdc, 0x92, 0xe0, 0xc9, 0x8a,
        0xd2, 0x43, 0x43, 0xb9, 0x35, 0x57, 0xad, 0x80
    // Do _not_ use a static IV in a real application!
    const uint8_t iv[aes256::cBlockSizeBytes] = {
        0x44, 0xa9, 0x48, 0x66, 0x3d, 0xb9, 0x92, 0xb8,
        0x2b, 0xe7, 0xd5, 0xed, 0xf0, 0x6d, 0x71, 0x4d
    // The buffer size has to be a multiple of the block size
    // which is 16 bytes.
    const int bufferSize = (aes256::cBlockSizeBytes * 4);
    uint8_t buffer[bufferSize];
    std::memset(buffer, 0, bufferSize);
    std::strcpy(reinterpret_cast<char*>(buffer), "Hello World!");
    std::cout << "Original: " << buffer << std::endl;
    hexBlock(buffer, bufferSize);
    aes256::SubstitutionBox box;
    aes256::encryptDataCBC(box, buffer, bufferSize, key, iv);
    std::cout << "Encrypted..." << std::endl;
    hexBlock(buffer, bufferSize);
    aes256::decryptDataCBC(box, buffer, bufferSize, key, iv);
    std::cout << "Decrypted: " << buffer << std::endl;
    hexBlock(buffer, bufferSize);
    return 0;

Source and License

I license the source using a very permissive MIT license. You can find it on GitHub:

If you have questions, miss some information or just have any feedback, feel free to add a comment below.

Have fun!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.