15#if (DETWS_ENABLE_HTTP3 || DETWS_ENABLE_DTLS)
26void quic_aes128_init(QuicAes128 *ctx,
const uint8_t key[16])
28 mbedtls_aes_init(&ctx->mbed);
29 mbedtls_aes_setkey_enc(&ctx->mbed, key, 128);
32void quic_aes128_encrypt_block(QuicAes128 *ctx,
const uint8_t in[16], uint8_t out[16])
34 mbedtls_aes_crypt_ecb(&ctx->mbed, MBEDTLS_AES_ENCRYPT, in, out);
37void quic_aes128_wipe(QuicAes128 *ctx)
39 mbedtls_aes_free(&ctx->mbed);
50const uint8_t RCON[11] = {0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
52inline uint8_t xtime(uint8_t a)
54 return (uint8_t)((a << 1) ^ ((a >> 7) ? 0x1bu : 0x00u));
58uint32_t aes_sub_word(uint32_t w)
60 return ((uint32_t)DET_AES_SBOX[w >> 24] << 24) | ((uint32_t)DET_AES_SBOX[(w >> 16) & 0xff] << 16) |
61 ((uint32_t)DET_AES_SBOX[(w >> 8) & 0xff] << 8) | (uint32_t)DET_AES_SBOX[w & 0xff];
64uint32_t aes_rot_word(uint32_t w)
66 return (w << 8) | (w >> 24);
70void aes128_key_expand(
const uint8_t key[16], uint32_t rk[44])
72 for (
int i = 0; i < 4; i++)
73 rk[i] = ((uint32_t)key[4 * i] << 24) | ((uint32_t)key[4 * i + 1] << 16) | ((uint32_t)key[4 * i + 2] << 8) |
74 (uint32_t)key[4 * i + 3];
76 for (
int i = 4; i < 44; i++)
78 uint32_t t = rk[i - 1];
80 t = aes_sub_word(aes_rot_word(t)) ^ ((uint32_t)RCON[i / 4] << 24);
81 rk[i] = rk[i - 4] ^ t;
86void aes128_encrypt_block(
const uint32_t rk[44],
const uint8_t in[16], uint8_t out[16])
89 for (
int i = 0; i < 16; i++)
90 s[i] = in[i] ^ (uint8_t)(rk[i / 4] >> (24 - (i % 4) * 8));
92 for (
int r = 1; r <= 9; r++)
94 for (
int i = 0; i < 16; i++)
95 s[i] = DET_AES_SBOX[s[i]];
115 for (
int c = 0; c < 4; c++)
117 uint8_t a = s[c * 4];
118 uint8_t b = s[c * 4 + 1];
119 uint8_t cc = s[c * 4 + 2];
120 uint8_t d = s[c * 4 + 3];
121 uint8_t e = a ^ b ^ cc ^ d;
122 s[c * 4] = a ^ e ^ xtime(a ^ b);
123 s[c * 4 + 1] = b ^ e ^ xtime(b ^ cc);
124 s[c * 4 + 2] = cc ^ e ^ xtime(cc ^ d);
125 s[c * 4 + 3] = d ^ e ^ xtime(d ^ a);
128 for (
int i = 0; i < 16; i++)
129 s[i] ^= (uint8_t)(rk[r * 4 + i / 4] >> (24 - (i % 4) * 8));
132 for (
int i = 0; i < 16; i++)
133 s[i] = DET_AES_SBOX[s[i]];
153 for (
int i = 0; i < 16; i++)
154 s[i] ^= (uint8_t)(rk[40 + i / 4] >> (24 - (i % 4) * 8));
160void quic_aes128_init(QuicAes128 *ctx,
const uint8_t key[16])
162 aes128_key_expand(key, ctx->rk);
165void quic_aes128_encrypt_block(QuicAes128 *ctx,
const uint8_t in[16], uint8_t out[16])
167 aes128_encrypt_block(ctx->rk, in, out);
170void quic_aes128_wipe(QuicAes128 *ctx)
172 volatile uint8_t *p = (
volatile uint8_t *)ctx;
173 for (
size_t i = 0; i <
sizeof(QuicAes128); i++)
185inline void xor16(uint8_t *dst,
const uint8_t *src)
187 for (
int i = 0; i < 16; i++)
195inline void put_be64(uint8_t *p, uint64_t v)
197 for (
int i = 7; i >= 0; i--)
199 p[i] = (uint8_t)(v & 0xff);
205inline void inc32(uint8_t ctr[16])
207 for (
int i = 15; i >= 12; i--)
214void gctr(QuicAes128 *aes, uint8_t ctr[16],
const uint8_t *in,
size_t len, uint8_t *out)
220 quic_aes128_encrypt_block(aes, ctr, ks);
222 size_t take = len - off;
225 for (
size_t i = 0; i < take; i++)
226 out[off + i] = in[off + i] ^ ks[i];
233void gcm_core(QuicAes128 *aes,
const uint8_t nonce[12],
const uint8_t *aad,
size_t aad_len,
const uint8_t *cipher,
234 size_t cipher_len, uint8_t j0[16], uint8_t tag[16])
237 quic_aes128_encrypt_block(aes, h, h);
242 memcpy(j0, nonce, 12);
252 put_be64(lb, (uint64_t)aad_len * 8);
253 put_be64(lb + 8, (uint64_t)cipher_len * 8);
258 quic_aes128_encrypt_block(aes, j0, ej0);
259 for (
int i = 0; i < 16; i++)
260 tag[i] = s[i] ^ ej0[i];
264void quic_aes128_gcm_seal(
const uint8_t key[16],
const uint8_t nonce[12],
const uint8_t *aad,
size_t aad_len,
265 const uint8_t *pt,
size_t pt_len, uint8_t *out)
268 quic_aes128_init(&aes, key);
272 memcpy(j0, nonce, 12);
280 gctr(&aes, ctr, pt, pt_len, out);
284 gcm_core(&aes, nonce, aad, aad_len, out, pt_len, j0b, tag);
285 memcpy(out + pt_len, tag, QUIC_AEAD_TAG_LEN);
287 quic_aes128_wipe(&aes);
290bool quic_aes128_gcm_open(
const uint8_t key[16],
const uint8_t nonce[12],
const uint8_t *aad,
size_t aad_len,
291 const uint8_t *ct,
size_t ct_len, uint8_t *out)
293 if (ct_len < QUIC_AEAD_TAG_LEN)
295 size_t pt_len = ct_len - QUIC_AEAD_TAG_LEN;
298 quic_aes128_init(&aes, key);
303 gcm_core(&aes, nonce, aad, aad_len, ct, pt_len, j0, tag);
306 for (
int i = 0; i < QUIC_AEAD_TAG_LEN; i++)
307 diff |= (uint8_t)(tag[i] ^ ct[pt_len + i]);
310 quic_aes128_wipe(&aes);
317 gctr(&aes, ctr, ct, pt_len, out);
319 quic_aes128_wipe(&aes);
The AES forward S-box (FIPS 197 Figure 7) - one shared copy.
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.
AES-128 block cipher and AEAD_AES_128_GCM (RFC 5116 / NIST SP 800-38D).
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...