|
ProtoCore v0.0.1
Deterministic, zero-heap network stack for embedded targets
|
AES-256-GCM AEAD (RFC 5116) - stateless, detached-tag API. More...
#include "protocore_config.h"#include "shared_primitives/span.h"#include <stddef.h>#include <stdint.h>Go to the source code of this file.
Macros | |
| #define | PC_AESGCM_KEY_LEN 32 |
| AES-256-GCM key length (bytes). | |
| #define | PC_AESGCM_IV_LEN 12 |
| GCM nonce length (bytes) = fixed_field(4) || invocation_counter(8). | |
| #define | PC_AESGCM_TAG_LEN 16 |
| GCM authentication tag length (bytes). | |
Functions | |
| 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. | |
| 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. | |
| 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. | |
| 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 out (may alias ct). | |
| void | pc_aesgcm_iv_increment (uint8_t iv[PC_AESGCM_IV_LEN]) |
| Advance the RFC 5647 invocation counter: the low 8 bytes of the 12-byte nonce as a big-endian integer; the 4-byte fixed field never changes. SSH calls this after each sealed/opened packet. | |
AES-256-GCM AEAD (RFC 5116) - stateless, detached-tag API.
A key is a per-connection object, so this is a KEYED api: build a context once from the 32-byte key with pc_aesgcm_key_init(), then seal or open each record against it. There is deliberately no raw-key one-shot. Standing a cipher context up and tearing it down costs ~9,200 cycles on an ESP32-S3 once the AES peripheral has actually been used - a FIXED cost per call, so roughly 10%% of a 1 KiB record, 30%% of a 256 B TLS record, and most of a small interactive SSH packet. A one-shot entry point would have let every caller pay that without seeing it.
The context holds an expanded key schedule for as long as the caller holds it, so it belongs in the caller's secure storage and must be wiped on rekey and on close. This is not a new exposure: the raw key is already resident for exactly that long, and the schedule is derivable from it.
Used by SSH aes25.nosp@m.6-gc.nosp@m.m@ope.nosp@m.nssh.nosp@m..com (RFC 5647: advance the invocation counter with pc_aesgcm_iv_increment after every packet) and SMB 3.x transport encryption.
The implementation is a backend under board_drivers/ selected by the vendor's PC_HAS_HW_AESGCM. Host-tested byte-exact against the NIST/McGrew AES-256-GCM vectors.
Definition in file aesgcm.h.
| #define PC_AESGCM_KEY_LEN 32 |
| #define PC_AESGCM_IV_LEN 12 |
| #define PC_AESGCM_TAG_LEN 16 |
| 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.
| storage | exactly PC_WORK_AESGCM bytes of the caller's secure storage, 8-aligned. Declare it as that macro and it cannot be wrong - the backend static_asserts its context fits, so the size is settled at compile time and there is nothing to check here. Must outlive every seal/open against it, and must be wiped on rekey and on close. |
Definition at line 177 of file portable_aesgcm.cpp.
Referenced by ssh_dh_derive_keys_sid().
| 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.
Definition at line 185 of file portable_aesgcm.cpp.
Referenced by ssh_dh_derive_keys_sid().
| 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.
ct_out receives pt_len ciphertext bytes (may alias pt) and tag_out the 16-byte tag. No state is kept or advanced - the caller owns the nonce.
Definition at line 192 of file portable_aesgcm.cpp.
References GcmWork::ctr, GcmWork::j0, and pc_cspan_from().
Referenced by ssh_pkt_send().
| 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 out (may alias ct).
Definition at line 205 of file portable_aesgcm.cpp.
References GcmWork::ctr, GcmWork::ej0, GcmWork::j0, and PC_AESGCM_TAG_LEN.
| void pc_aesgcm_iv_increment | ( | uint8_t | iv[PC_AESGCM_IV_LEN] | ) |
Advance the RFC 5647 invocation counter: the low 8 bytes of the 12-byte nonce as a big-endian integer; the 4-byte fixed field never changes. SSH calls this after each sealed/opened packet.
Definition at line 30 of file aesgcm.cpp.
References PC_AESGCM_IV_LEN.
Referenced by ssh_pkt_send().