# SHA-3

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

The SHA-3 family (SHA3-224/256/384/512) and the SHAKE128/SHAKE256 extendable-output functions, built on Keccak-f[1600]. All variants share one streaming context type.

### Types

#### `fio_sha3_s`

```c
typedef struct {
  uint64_t state[25];
  uint8_t buf[200];
  size_t buflen;
  size_t rate;
  size_t outlen;
  uint8_t delim;
} fio_sha3_s;
```

Streaming context for every SHA-3 and SHAKE variant.

**Members:**
- `state` - the 25-word Keccak-f[1600] state.
- `buf` - partial-block input buffer.
- `buflen` - bytes currently buffered.
- `rate` - absorption/squeezing rate in bytes, set by the init function.
- `outlen` - fixed output length in bytes for SHA-3; 0 for SHAKE.
- `delim` - domain separator (`0x06` for SHA-3, `0x1F` for SHAKE).

**Note:** treat this as opaque. Always initialize it with one of the `fio_sha3_*_init` or `fio_shake*_init` functions.

### SHA-3 Fixed-Output Functions

#### `fio_sha3_224_init`

```c
fio_sha3_s fio_sha3_224_init(void);
```

**Returns:** a SHA3-224 context (28-byte output, rate 144).

#### `fio_sha3_256_init`

```c
fio_sha3_s fio_sha3_256_init(void);
```

**Returns:** a SHA3-256 context (32-byte output, rate 136).

#### `fio_sha3_384_init`

```c
fio_sha3_s fio_sha3_384_init(void);
```

**Returns:** a SHA3-384 context (48-byte output, rate 104).

#### `fio_sha3_512_init`

```c
fio_sha3_s fio_sha3_512_init(void);
```

**Returns:** a SHA3-512 context (64-byte output, rate 72).

#### `fio_sha3_consume`

```c
void fio_sha3_consume(fio_sha3_s *restrict h,
                      const void *restrict data,
                      size_t len);
```

Feeds `len` bytes into a SHA-3 context. May be called repeatedly.

**Parameters:**
- `h` - pointer to the streaming context.
- `data` - pointer to the data to absorb.
- `len` - length of the data in bytes.

#### `fio_sha3_finalize`

```c
void fio_sha3_finalize(fio_sha3_s *restrict h, void *restrict out);
```

Pads, permutes, and writes `h->outlen` digest bytes to `out`.

**Parameters:**
- `h` - pointer to the streaming context.
- `out` - output buffer, must hold at least `h->outlen` bytes.

**Note:** do not call this on a SHAKE context. Use `fio_shake_squeeze` instead.

#### `fio_sha3_224`

```c
void fio_sha3_224(void *restrict out,
                  const void *restrict data,
                  size_t len);
```

One-shot SHA3-224.

**Parameters:**
- `out` - output buffer (28 bytes).
- `data` - pointer to the data to hash.
- `len` - length of the data in bytes.

#### `fio_sha3_256`

```c
void fio_sha3_256(void *restrict out,
                  const void *restrict data,
                  size_t len);
```

One-shot SHA3-256.

**Parameters:**
- `out` - output buffer (32 bytes).
- `data` - pointer to the data to hash.
- `len` - length of the data in bytes.

#### `fio_sha3_384`

```c
void fio_sha3_384(void *restrict out,
                  const void *restrict data,
                  size_t len);
```

One-shot SHA3-384.

**Parameters:**
- `out` - output buffer (48 bytes).
- `data` - pointer to the data to hash.
- `len` - length of the data in bytes.

#### `fio_sha3_512`

```c
void fio_sha3_512(void *restrict out,
                  const void *restrict data,
                  size_t len);
```

One-shot SHA3-512.

**Parameters:**
- `out` - output buffer (64 bytes).
- `data` - pointer to the data to hash.
- `len` - length of the data in bytes.

### SHAKE Extendable-Output Functions

#### `fio_shake128_init`

```c
fio_sha3_s fio_shake128_init(void);
```

**Returns:** a SHAKE128 context (variable output, rate 168).

#### `fio_shake256_init`

```c
fio_sha3_s fio_shake256_init(void);
```

**Returns:** a SHAKE256 context (variable output, rate 136).

#### `fio_shake_consume`

```c
#define fio_shake_consume fio_sha3_consume
```

Alias for `fio_sha3_consume`. Feeds data into a SHAKE context.

#### `fio_shake_squeeze`

```c
void fio_shake_squeeze(fio_sha3_s *restrict h,
                       void *restrict out,
                       size_t outlen);
```

Squeezes `outlen` bytes from a SHAKE context. On the first call it applies padding and runs the first permutation; later calls continue squeezing and re-permute as needed.

**Parameters:**
- `h` - pointer to the SHAKE context.
- `out` - output buffer, must hold at least `outlen` bytes.
- `outlen` - number of bytes to squeeze.

#### `fio_shake128`

```c
void fio_shake128(void *restrict out,
                  size_t outlen,
                  const void *restrict data,
                  size_t len);
```

One-shot SHAKE128.

**Parameters:**
- `out` - output buffer.
- `outlen` - number of bytes to produce.
- `data` - pointer to the data to hash.
- `len` - length of the data in bytes.

#### `fio_shake256`

```c
void fio_shake256(void *restrict out,
                  size_t outlen,
                  const void *restrict data,
                  size_t len);
```

One-shot SHAKE256.

**Parameters:**
- `out` - output buffer.
- `outlen` - number of bytes to produce.
- `data` - pointer to the data to hash.
- `len` - length of the data in bytes.

### Examples

#### One-shot SHA3-256

```c
#define FIO_SHA3
#include "fio-stl.h"
#include <stdio.h>
#include <string.h>

int main(void) {
  const char *msg = "hello";
  uint8_t digest[32];
  fio_sha3_256(digest, msg, strlen(msg));
  for (size_t i = 0; i < sizeof(digest); ++i)
    printf("%02x", digest[i]);
  printf("\n");
  return 0;
}
```

#### Streaming SHA3-512

```c
fio_sha3_s h = fio_sha3_512_init();
fio_sha3_consume(&h, "hello, ", 7);
fio_sha3_consume(&h, "world", 5);
uint8_t digest[64];
fio_sha3_finalize(&h, digest);
```

#### SHAKE256 extendable output

```c
const char *seed = "hello";
uint8_t out[128];
fio_sha3_s h = fio_shake256_init();
fio_shake_consume(&h, seed, strlen(seed));
fio_shake_squeeze(&h, out, sizeof(out));
```

**Note:** state is caller-owned; no heap allocation occurs. Keep SHA-3 and SHAKE contexts separate at finalization time (`fio_sha3_finalize` vs. `fio_shake_squeeze`).

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