49 "GcmWork outgrew PC_WORK_AESGCM - raise it in protocore_config.h, which derives PC_SECURE_ARENA_SIZE from it");
56inline void aes256_ecb(
GcmWork *w,
const uint8_t in[16], uint8_t out[16])
60inline void aes256_load_key(
GcmWork *w,
const uint8_t key[32])
64inline void aes256_free_key(
GcmWork *w)
69inline void xor16(uint8_t *dst,
const uint8_t *src)
74 if (((((uintptr_t)dst) | ((uintptr_t)src)) & 3u) == 0u)
76 uint32_t *d = (uint32_t *)dst;
77 const uint32_t *s = (
const uint32_t *)src;
84 for (
int i = 0; i < 16; i++)
90inline void put_be64(uint8_t *p, uint64_t v)
92 for (
int i = 7; i >= 0; i--)
94 p[i] = (uint8_t)(v & 0xff);
100inline void inc32(uint8_t ctr[16])
105 for (
int i = 15; i >= 12;
118 memset(w->
ks, 0, 16);
119 aes256_ecb(w, w->
ks, w->
h);
124void gcm_set_nonce(
GcmWork *w,
const uint8_t nonce[12])
126 memcpy(w->
j0, nonce, 12);
134void gctr(
GcmWork *w,
const uint8_t *in,
size_t len, uint8_t *out)
139 aes256_ecb(w, w->
ctr, w->
ks);
141 size_t take = len - off;
146 for (
size_t i = 0; i < take; i++)
148 out[off + i] = in[off + i] ^ w->
ks[i];
155void gcm_tag(
GcmWork *w,
const uint8_t *aad,
size_t aad_len,
const uint8_t *cipher,
size_t cipher_len,
158 memset(w->
acc, 0, 16);
161 put_be64(w->
lb, (uint64_t)aad_len * 8);
162 put_be64(w->
lb + 8, (uint64_t)cipher_len * 8);
163 xor16(w->
acc, w->
lb);
165 aes256_ecb(w, w->
j0, w->
ej0);
166 for (
int i = 0; i < 16; i++)
168 tag_out[i] = w->
acc[i] ^ w->
ej0[i];
180 aes256_load_key(w, key);
182 return reinterpret_cast<pc_aesgcm_key *
>(w);
189 pc_secure_wipe(
reinterpret_cast<uint8_t *
>(w),
sizeof(
GcmWork));
193 const uint8_t *pt,
size_t pt_len, uint8_t *ct_out, uint8_t tag_out[
PC_AESGCM_TAG_LEN])
196 gcm_set_nonce(w, nonce);
198 memcpy(w->
ctr, w->
j0, 16);
200 gctr(w, pt, pt_len, ct_out);
201 gcm_tag(w, aad, aad_len, ct_out, pt_len, tag_out);
206 const uint8_t *ct,
size_t ct_len,
const uint8_t tag[
PC_AESGCM_TAG_LEN], uint8_t *out)
209 gcm_set_nonce(w, nonce);
211 gcm_tag(w, aad, aad_len, ct, ct_len, w->
ej0);
216 memcpy(w->
ctr, w->
j0, 16);
218 gctr(w, ct, ct_len, out);
Compact table-free software AES key schedule + single-block encrypt (FIPS 197) - one source of truth.
void pc_aes_key_expand(const uint8_t *key, int nk, uint32_t *rk)
AES key expansion (FIPS 197 sec 5.2). nk key words (4=AES-128, 8=AES-256); rk receives 4*(nk + 7) rou...
void pc_aes_encrypt_block(const uint32_t *rk, int nr, const uint8_t in[16], uint8_t out[16])
AES single-block encrypt (FIPS 197 sec 5.1), nr rounds (10=AES-128, 14=AES-256). State is column-majo...
AES-256-GCM AEAD (RFC 5116) - stateless, detached-tag API.
#define PC_AESGCM_TAG_LEN
GCM authentication tag length (bytes).
#define PC_AESGCM_IV_LEN
GCM nonce length (bytes) = fixed_field(4) || invocation_counter(8).
#define PC_AESGCM_KEY_LEN
AES-256-GCM key length (bytes).
Per-translation-unit optimization override for hot, pure-integer crypto.
Constant-time comparison for secret-dependent checks.
GHASH (the GF(2^128) universal hash under AES-GCM, NIST SP 800-38D sec 6.3), 4-bit table.
void ghash_key_init(GhashKey *t, const uint8_t h[16])
Build the 4-bit multiplication table from the 16-byte subkey h. Call once per key.
void ghash_update(const GhashKey *t, uint8_t acc[16], const uint8_t *data, size_t len)
Fold len bytes of data into acc: acc = (acc XOR block) * H per 16 bytes, a final short block MSB-zero...
void ghash_mul(const GhashKey *t, uint8_t acc[16])
acc = acc * H in GF(2^128) with the GCM reduction, using the precomputed table t.
bool pc_aesgcm_open(pc_aesgcm_key *k, const uint8_t nonce[PC_AESGCM_IV_LEN], const uint8_t *aad, size_t aad_len, const uint8_t *ct, size_t ct_len, const uint8_t tag[PC_AESGCM_TAG_LEN], uint8_t *out)
Open one record: verify tag over aad || ct in constant time, then (only on success) decrypt ct into o...
pc_aesgcm_key * pc_aesgcm_key_init(void *storage, const uint8_t key[PC_AESGCM_KEY_LEN])
Bind storage as a context keyed with key.
pc_cspan pc_aesgcm_seal(pc_aesgcm_key *k, const uint8_t nonce[PC_AESGCM_IV_LEN], const uint8_t *aad, size_t aad_len, const uint8_t *pt, size_t pt_len, uint8_t *ct_out, uint8_t tag_out[PC_AESGCM_TAG_LEN])
Seal one record under k and nonce.
void pc_aesgcm_key_wipe(pc_aesgcm_key *k)
Wipe the expanded schedule. Call on rekey and on close; the storage stays the caller's.
Secure pool accessor - borrows that hold key material.
pc_cspan pc_cspan_from(const uint8_t *p, size_t len)
Bind a read-only span to memory whose extent is only known at run time.
uint8_t ctr[16]
running GCTR counter.
uint8_t ks[16]
GCTR keystream block (also the zero input used to derive H).
uint8_t lb[16]
length block (aad_len || cipher_len, in bits).
uint8_t j0[16]
pre-counter block J0 = nonce || 0^31 || 1.
uint8_t h[16]
GHASH subkey H = E(K, 0^128).
uint32_t rk[60]
AES-256 expanded round-key schedule (software).
uint8_t ej0[16]
E(K, J0), the tag mask.
uint8_t acc[16]
GHASH accumulator.
GhashKey ghk
4-bit GHASH table built from H.
4-bit GHASH table for a fixed subkey H = E(K, 0^128): M[i] = i*H as four big-endian uint32 words (M[i...