A small AES library in C for learning and experimentation.
Current design is a single-file library style:
- Public API:
aes.h - Implementation:
aes.c
Supports:
- AES-128 / AES-192 / AES-256
- Two backends:
AES_BACKEND_SBOXandAES_BACKEND_LUT - Operation modes (buffer API):
ECB,CBC,CFB
This project is for educational use. It is functionally tested, but not hardened for production security (no side-channel resistance, no secure memory wipe policy, etc.). Do not use directly in sensitive production systems.
Copy aes.h and aes.c into your project, then compile/link aes.c.
Example:
cc -std=c11 -O2 -I. your_app.c aes.c -o your_appint CoreInit(aes_core_context *ctx);
int CoreSetBackend(aes_core_context *ctx, aes_backend_t backend);
int CoreSetKey(aes_core_context *ctx, const uint8_t *key, aes_variation variant);
int CoreEncrypt(const aes_core_context *ctx, const uint8_t in[16], uint8_t out[16]);
int CoreDecrypt(const aes_core_context *ctx, const uint8_t in[16], uint8_t out[16]);Recommended call order:
CoreInitCoreSetBackendCoreSetKeyCoreEncrypt/CoreDecrypt
int OpInit(aes_op_context *opctx);
int OpSetMode(aes_op_context *opctx, aes_opmode_t mode);
int OpSetIV(aes_op_context *opctx, const uint8_t iv[16]);
int OpEncryptBuffer(const aes_core_context *corectx, const aes_op_context *opctx,
const uint8_t *in, size_t in_len,
uint8_t *out, size_t *out_len);
int OpDecryptBuffer(const aes_core_context *corectx, const aes_op_context *opctx,
const uint8_t *in, size_t in_len,
uint8_t *out, size_t *out_len);Mode behavior:
MODE_ECB: PKCS#7 padding on encrypt, PKCS#7 unpadding on decrypt.MODE_CBC: PKCS#7 padding on encrypt, PKCS#7 unpadding on decrypt, requires IV.MODE_CFB: stream-style, no PKCS#7 padding, output length equals input length, requires IV.
out_len contract:
- Input: capacity of output buffer.
- Output: actual bytes written.
- If capacity is insufficient, function returns error and writes required length to
*out_len.
Use this path when you only need AES block encryption/decryption and will manage mode/padding yourself.
- Declare a context:
aes_core_context core;
- Initialize:
CoreInit(&core);
- Select backend:
CoreSetBackend(&core, AES_BACKEND_SBOX)orAES_BACKEND_LUT
- Set key and variant:
CoreSetKey(&core, key, AES_128 / AES_192 / AES_256);
- Encrypt/decrypt one 16-byte block:
CoreEncrypt(&core, in16, out16);CoreDecrypt(&core, in16, out16);
Notes:
CoreEncrypt/CoreDecryptprocess exactly 16 bytes each call.- Call
CoreSetKeyagain if key or key size changes.
Use this path when you want mode handling (ECB/CBC/CFB) and padding behavior handled by the library.
- Prepare core:
CoreInit(&core);CoreSetBackend(&core, ...);CoreSetKey(&core, key, variant);
- Prepare op context:
OpInit(&op);OpSetMode(&op, MODE_ECB / MODE_CBC / MODE_CFB);- If mode needs IV (
CBC/CFB):OpSetIV(&op, iv16);
- Encrypt buffer:
- Set
out_len = output_buffer_capacity - Call
OpEncryptBuffer(&core, &op, in, in_len, out, &out_len);
- Set
- Decrypt buffer:
- Set
plain_len = output_buffer_capacity - Call
OpDecryptBuffer(&core, &op, in, in_len, out, &plain_len);
- Set
Mode-specific behavior:
MODE_ECB: PKCS#7 pad/unpad.MODE_CBC: PKCS#7 pad/unpad, requires IV.MODE_CFB: no PKCS#7, output length equals input length, requires IV.
The minimal runnable example is in examples/basic_demo.c.
Typical usage flow:
CoreInitCoreSetBackendCoreSetKeyOpInitOpSetMode(andOpSetIVif mode needs IV)OpEncryptBufferOpDecryptBuffer
For complete compilable code, see examples/basic_demo.c.
Core vectors (AES-128/192/256, SBOX/LUT):
cc -std=c11 -Wall -Wextra -Wpedantic -I. tests/core_vectors_test.c aes.c -o /tmp/core_vectors_test
/tmp/core_vectors_testOp-mode roundtrip tests (ECB/CBC/CFB, SBOX/LUT):
cc -std=c11 -Wall -Wextra -Wpedantic -I. tests/opmode_buffer_test.c aes.c -o /tmp/opmode_buffer_test
/tmp/opmode_buffer_testOp-mode KAT tests (NIST SP 800-38A ECB/CBC/CFB128 vectors, AES-128, SBOX/LUT):
cc -std=c11 -Wall -Wextra -Wpedantic -I. tests/opmode_kat_test.c aes.c -o /tmp/opmode_kat_test
/tmp/opmode_kat_testWith CMake/CTest:
cmake -S . -B build
cmake --build build -j
ctest --test-dir build --output-on-failure