# AES-GCM

```c
#define FIO_AES
#include "fio-stl.h"
```

Authenticated encryption with associated data (AEAD) using AES-128-GCM and AES-256-GCM. The API is in-place and matches [`fio_chacha20_poly1305`](https://facil.io/0.8.x/chacha20-poly1305/), so the two cipher suites can be swapped with the same call shape.

Hardware acceleration is used when available (x86 AES-NI + PCLMULQDQ, ARM crypto extensions), with a portable fallback otherwise.

**Security note:** GCM nonces must never be reused with the same key. A 96-bit nonce runs out of uniqueness long before the key does; generate a fresh nonce for every message.

### API Functions

#### `fio_aes128_gcm_enc`

```c
SFUNC void fio_aes128_gcm_enc(void *restrict mac,
                              void *restrict data,
                              size_t len,
                              const void *ad,
                              size_t adlen,
                              const void *key,
                              const void *nonce);
```

Encrypts `data` in place with AES-128-GCM and writes a 16-byte authentication tag to `mac`.

**Parameters:**
- `mac` — output buffer; must have at least 16 writable bytes.
- `data` — plaintext buffer; encrypted in place. May be `NULL` if `len` is 0.
- `len` — plaintext length in bytes.
- `ad` — additional authenticated data; not encrypted but covered by the tag. May be `NULL`.
- `adlen` — length of `ad`.
- `key` — 16-byte AES-128 key.
- `nonce` — 12-byte nonce.

#### `fio_aes128_gcm_dec`

```c
SFUNC int fio_aes128_gcm_dec(void *restrict mac,
                             void *restrict data,
                             size_t len,
                             const void *ad,
                             size_t adlen,
                             const void *key,
                             const void *nonce);
```

Decrypts `data` in place and verifies the 16-byte tag in `mac`.

**Parameters:** same as `fio_aes128_gcm_enc`.

**Returns:** `0` on success, `-1` if authentication fails. On failure `data` is left unchanged.

#### `fio_aes256_gcm_enc`

```c
SFUNC void fio_aes256_gcm_enc(void *restrict mac,
                              void *restrict data,
                              size_t len,
                              const void *ad,
                              size_t adlen,
                              const void *key,
                              const void *nonce);
```

Same as `fio_aes128_gcm_enc` but uses a 32-byte AES-256 key.

#### `fio_aes256_gcm_dec`

```c
SFUNC int fio_aes256_gcm_dec(void *restrict mac,
                             void *restrict data,
                             size_t len,
                             const void *ad,
                             size_t adlen,
                             const void *key,
                             const void *nonce);
```

Same as `fio_aes128_gcm_dec` but uses a 32-byte AES-256 key.

### Example

```c
#define FIO_AES
#include "fio-stl.h"

int main(void) {
  uint8_t key[32] = {0};
  uint8_t nonce[12] = {0};
  uint8_t msg[32] = "hello, gcm world!";
  uint8_t tag[16];

  fio_rand_bytes_secure(key, sizeof(key));
  fio_rand_bytes_secure(nonce, sizeof(nonce));

  fio_aes256_gcm_enc(tag, msg, sizeof(msg), NULL, 0, key, nonce);
  /* msg is now ciphertext; tag authenticates it. */

  if (fio_aes256_gcm_dec(tag, msg, sizeof(msg), NULL, 0, key, nonce)) {
    printf("authentication failed\n");
    return 1;
  }
  /* msg is restored plaintext. */
  return 0;
}
```

------------------------------------------------------------
