std1.0.0-beta-7 SafeC docs

Source crypto/aes.h

View in the repository

// SafeC Standard Library — AES Block Cipher
// AES-128 and AES-256 in ECB, CBC and GCM modes.  Pure software; no SIMD.
// Freestanding-safe.
#pragma once
#include <std/crypto/buf.h>

#define AES_BLOCK_SIZE  16   // bytes
#define AES128_KEY_SIZE 16   // bytes
#define AES256_KEY_SIZE 32   // bytes
#define AES128_ROUNDS   10
#define AES256_ROUNDS   14

// Expanded key schedule: max 15 round keys × 4 words × 4 bytes = 240 bytes.
#define AES_KS_WORDS   60

namespace std {

struct AesCtx {
    unsigned int  ks[AES_KS_WORDS]; // expanded key schedule
    int           rounds;            // 10 (AES-128) or 14 (AES-256)
    unsigned char iv[AES_BLOCK_SIZE]; // CBC initialisation vector

    // An AES-128 context from a 16-byte key (IV zeroed).
    static struct AesCtx new_128([]const unsigned char key);
    // internal: the (reference, length) core of new_128()
    static struct AesCtx new_128_n_(const &unsigned char key);

    // An AES-256 context from a 32-byte key (IV zeroed).
    static struct AesCtx new_256([]const unsigned char key);
    // internal: the (reference, length) core of new_256()
    static struct AesCtx new_256_n_(const &unsigned char key);

    // Encrypt one 16-byte block in-place (ECB).
    void encrypt_block([]unsigned char block);
    // internal: the (reference, length) core of encrypt_block()
    void encrypt_block_n_(&unsigned char block);

    // Decrypt one 16-byte block in-place (ECB).
    void decrypt_block([]unsigned char block);
    // internal: the (reference, length) core of decrypt_block()
    void decrypt_block_n_(&unsigned char block);

    // Encrypt `len` bytes (must be multiple of 16) in CBC mode.
    // Uses and updates self.iv.
    void cbc_encrypt([]unsigned char data);
    // internal: the (reference, length) core of cbc_encrypt()
    void cbc_encrypt_n_(&unsigned char data, unsigned long len);

    // Decrypt `len` bytes in CBC mode.  Uses and updates self.iv.
    void cbc_decrypt([]unsigned char data);
    // internal: the (reference, length) core of cbc_decrypt()
    void cbc_decrypt_n_(&unsigned char data, unsigned long len);

    // Set the CBC initialisation vector.
    void set_iv([]const unsigned char iv);
    // internal: the (reference, length) core of set_iv()
    void set_iv_n_(const &unsigned char iv);

    // AES-GCM (NIST SP 800-38D) with a 12-byte IV and a 16-byte tag:
    // encrypts data[0..len) in place and writes the tag over the
    // additional data aad[0..aad_len) (aad may be null when aad_len is 0)
    // and the ciphertext. Never reuse an IV with the same key.
    void gcm_encrypt([]const unsigned char iv, []const unsigned char aad, []unsigned char data, []unsigned char tag);
    // internal: the (reference, length) core of gcm_encrypt()
    void gcm_encrypt_n_(const &unsigned char iv, const ?&unsigned char aad, unsigned long aad_len,
                     &unsigned char data, unsigned long len, &unsigned char tag);

    // Checks the tag (in constant time) and, only if it matches, decrypts
    // data[0..len) in place. Returns 1 if authentic, 0 if not (data is then
    // left as the unauthenticated ciphertext).
    int  gcm_decrypt([]const unsigned char iv, []const unsigned char aad, []unsigned char data, []const unsigned char tag);
    // internal: the (reference, length) core of gcm_decrypt()
    int  gcm_decrypt_n_(const &unsigned char iv, const ?&unsigned char aad, unsigned long aad_len,
                     &unsigned char data, unsigned long len, const &unsigned char tag);

    // Securely wipe the expanded key schedule and IV (via
    // mem_zero_secure — a volatile write-through that survives
    // dead-store elimination, unlike a plain assignment the optimizer
    // could see is never read again and drop). Call this once a context
    // is done being used, before it goes out of scope, so the key
    // material doesn't linger readable in memory (e.g. in a stack frame
    // reused by a later, unrelated function, or in a crash dump).
    void drop();
    void destroy() consume;   // = drop()
};

} // namespace std