AES-128 Encryption (aes128)
AES-128 symmetric encryption/decryption supporting ECB, CBC, and CTR block cipher modes.
- Key size: 16 bytes
- Block size: 16 bytes
- Rounds: 10
Constants
#define AES128_KEY_SIZE (16)
#define AES128_BLOCK_SIZE (16)
Data Structure
struct aes128_ctx_t {
uint8_t xkey[4 * 4 * (10 + 1)];
};
xkey stores the AES-128 expanded key (10 rounds + initial round key, 11 groups of 4 × 32-bit words, totaling 176 bytes).
API
void aes128_set_key(struct aes128_ctx_t * ctx, uint8_t * key);
Set the 16-byte key, initialize the encryption context, and perform key expansion.
void aes128_ecb_encrypt(struct aes128_ctx_t * ctx, uint8_t * in, uint8_t * out, int blks);
void aes128_ecb_decrypt(struct aes128_ctx_t * ctx, uint8_t * in, uint8_t * out, int blks);
ECB mode encrypt/decrypt. in and out must be blks * 16 bytes, i.e., the input must be a multiple of 16 bytes.
void aes128_cbc_encrypt(struct aes128_ctx_t * ctx, uint8_t * iv, uint8_t * in, uint8_t * out, int blks);
void aes128_cbc_decrypt(struct aes128_ctx_t * ctx, uint8_t * iv, uint8_t * in, uint8_t * out, int blks);
CBC mode encrypt/decrypt. iv is the 16-byte initialization vector, in and out must be blks * 16 bytes. Note that iv is modified during encryption; make a copy beforehand if the original iv needs to be preserved.
void aes128_ctr_encrypt(struct aes128_ctx_t * ctx, uint64_t offset, uint8_t * in, uint8_t * out, int bytes);
void aes128_ctr_decrypt(struct aes128_ctx_t * ctx, uint64_t offset, uint8_t * in, uint8_t * out, int bytes);
CTR mode encrypt/decrypt. offset is the counter offset (in blocks), bytes is the number of bytes to process. CTR mode does not require the input to be a multiple of 16 bytes, and encryption and decryption use the same operation.
Examples
ECB Mode (NIST Test Vector)
struct aes128_ctx_t ctx;
uint8_t key[16] = {
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
};
uint8_t in[16] = {
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
};
uint8_t out[16];
aes128_set_key(&ctx, key);
aes128_ecb_encrypt(&ctx, in, out, 1);
/* out = 0x3a,0xd7,0x7b,0xb4,0x0d,0x7a,0x36,0x60,
0xa8,0x9e,0xca,0xf3,0x24,0x66,0xef,0x97 */
CBC Mode (NIST Test Vector)
struct aes128_ctx_t ctx;
uint8_t key[16] = {
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
};
uint8_t iv[16] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
};
uint8_t in[16] = {
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
};
uint8_t out[16];
aes128_set_key(&ctx, key);
aes128_cbc_encrypt(&ctx, iv, in, out, 1);
/* out = 0x76,0x49,0xab,0xac,0x81,0x19,0xb2,0x46,
0xce,0xe9,0x8e,0x9b,0x12,0xe9,0x19,0x7d */
CTR Mode
struct aes128_ctx_t ctx;
uint8_t key[16] = { ... };
uint8_t in[100] = { ... };
uint8_t enc[100];
uint8_t dec[100];
aes128_set_key(&ctx, key);
aes128_ctr_encrypt(&ctx, 0, in, enc, 100);
aes128_ctr_decrypt(&ctx, 0, enc, dec, 100);
/* dec equals in */
Encrypt→Decrypt Round-Trip Verification
struct aes128_ctx_t ctx;
uint8_t key[AES128_KEY_SIZE] = { ... };
uint8_t iv[AES128_BLOCK_SIZE] = { ... };
uint8_t in[AES128_BLOCK_SIZE * 10];
uint8_t enc[AES128_BLOCK_SIZE * 10];
uint8_t dec[AES128_BLOCK_SIZE * 10];
aes128_set_key(&ctx, key);
/* ECB round-trip */
aes128_ecb_encrypt(&ctx, in, enc, 10);
aes128_ecb_decrypt(&ctx, enc, dec, 10);
/* memcmp(in, dec, sizeof(in)) == 0 */
/* CBC round-trip (note: iv is modified during encryption, reset before decrypt) */
aes128_cbc_encrypt(&ctx, iv, in, enc, 10);
aes128_cbc_decrypt(&ctx, iv, enc, dec, 10);
/* memcmp(in, dec, sizeof(in)) == 0 */