ProtoCore v0.0.1
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
aes256ctr.h File Reference

AES-256-CTR stream cipher (aes256-ctr, RFC 4344 §4) - stateless one-shot API. More...

#include <stddef.h>
#include <stdint.h>

Go to the source code of this file.

Macros

#define PC_AES256CTR_KEY_LEN   32
 AES-256-CTR key length (bytes).
 
#define PC_AES256CTR_CTR_LEN   16
 AES-256-CTR counter/IV block length (bytes).
 

Functions

void pc_aes256ctr_crypt (const uint8_t key[PC_AES256CTR_KEY_LEN], uint8_t counter[PC_AES256CTR_CTR_LEN], const uint8_t *in, uint8_t *out, size_t len)
 Encrypt or decrypt len bytes with AES-256-CTR (the two are identical).
 
uint32_t pc_aes256ctr_get_length (const uint8_t key[PC_AES256CTR_KEY_LEN], const uint8_t counter[PC_AES256CTR_CTR_LEN], const uint8_t enc4[4])
 Decrypt only the 4-byte SSH packet_length prefix WITHOUT advancing counter.
 

Detailed Description

AES-256-CTR stream cipher (aes256-ctr, RFC 4344 §4) - stateless one-shot API.

AES-256-CTR is the mandatory cipher for this SSH implementation. CTR mode turns AES into a stream cipher: each 16-byte counter block is AES-ECB encrypted to produce a keystream block, and data is XOR'd with the keystream. Encrypt and decrypt are the identical operation.

STATELESS API (mirrors chachapoly.h) ──────────────────────────────────── There is no context object. The caller keeps the two things that must persist across packets - the 32-byte key and the 16-byte counter - as plain bytes (SshKeyMat holds them, exactly as it holds the raw chacha20-poly1305 key), and passes both in on every call. The AES key schedule is rebuilt per call in the secure pool and wiped when released, so expanded key material never lives in BSS or on the stack - every crypto secret is funneled through the one hardened, wiped scratch region (crypto_scratch.h). counter is advanced in place by ceil(len / 16) blocks so successive calls continue the stream.

COUNTER FORMAT (RFC 4344 §4) The 16-byte counter increments as a big-endian 128-bit integer after each 16-byte keystream block. The initial counter is the IV from the key exchange (RFC 4253 §7.2, labels 'A'/'B').

Note
The SSH binary packet is always a whole number of cipher blocks, so every call is block-aligned and the counter alone is sufficient state. A non-block-aligned len is permitted only as the final call of a stream (any leftover keystream in the last block is discarded, not carried).

On Arduino (ESP32) the AES block is mbedtls, routed to the hardware AES accelerator; on native host builds a compact software AES-256 is used so the cipher is unit-testable off-target.

Author
Douglas Quigg (dstroy0)
Date
2026

Definition in file aes256ctr.h.

Macro Definition Documentation

◆ PC_AES256CTR_KEY_LEN

#define PC_AES256CTR_KEY_LEN   32

AES-256-CTR key length (bytes).

Definition at line 44 of file aes256ctr.h.

◆ PC_AES256CTR_CTR_LEN

#define PC_AES256CTR_CTR_LEN   16

AES-256-CTR counter/IV block length (bytes).

Definition at line 46 of file aes256ctr.h.

Function Documentation

◆ pc_aes256ctr_crypt()

void pc_aes256ctr_crypt ( const uint8_t  key[PC_AES256CTR_KEY_LEN],
uint8_t  counter[PC_AES256CTR_CTR_LEN],
const uint8_t *  in,
uint8_t *  out,
size_t  len 
)

Encrypt or decrypt len bytes with AES-256-CTR (the two are identical).

Rebuilds the key schedule from key on the stack, produces the CTR keystream starting at counter, and XORs it into out. counter is advanced in place by ceil(len / 16) blocks so the next call continues the same stream. in and out may alias (in-place is the mode ssh_packet.cpp uses).

Parameters
key32-byte AES-256 key.
counter16-byte counter block (big-endian); updated in place to the next unused block.
inInput bytes.
outOutput bytes (may equal in).
lenNumber of bytes to process.

Definition at line 45 of file aes256ctr.cpp.

References Aes256CtrWork::aes, pc_span::buf, Aes256CtrWork::ks, pc_span_ok(), and SecureBorrow::span().

Referenced by ssh_pkt_send().

◆ pc_aes256ctr_get_length()

uint32_t pc_aes256ctr_get_length ( const uint8_t  key[PC_AES256CTR_KEY_LEN],
const uint8_t  counter[PC_AES256CTR_CTR_LEN],
const uint8_t  enc4[4] 
)

Decrypt only the 4-byte SSH packet_length prefix WITHOUT advancing counter.

Mirrors pc_chachapoly_get_length: lets the receiver learn a packet's length (and thus how many bytes to wait for) before the whole packet has arrived, without consuming counter state. The key schedule and keystream block live in the shared crypto scratch; no cipher state touches the stack.

Parameters
key32-byte AES-256 key.
countercurrent 16-byte counter block (read only; not advanced).
enc4the 4 encrypted length bytes (start of the packet).
Returns
the decrypted big-endian SSH packet_length.

Definition at line 117 of file aes256ctr.cpp.

References Aes256CtrWork::aes, pc_span::buf, Aes256CtrWork::ks, pc_aes_encrypt_block(), pc_aes_key_expand(), pc_span_ok(), and SecureBorrow::span().