SH2SC-EDT
Self-Healing Hardware and Software Complex for Encrypted Data Transmission
Loading...
Searching...
No Matches
csprng.h File Reference

ChaCha20-based CSPRNG for SH2SC-EDT — Receiver Node B (ATmega328P). More...

#include <Arduino.h>
#include <ChaCha.h>
+ Include dependency graph for csprng.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

static void s_fillKeystreamBlock ()
 Produce the next 64-byte ChaCha20 keystream block into s_keystreamBuf.
 
void initCSPRNG (const uint8_t *hardwareSeed)
 Seed the ChaCha20 CSPRNG with 256 bits of hardware entropy.
 
uint32_t getSecureRandom32 ()
 Return 32 bits of CSPRNG output (non-blocking).
 

Variables

static const uint8_t CSPRNG_BLOCK_BYTES = 64u
 Size of one ChaCha20 keystream output block in bytes.
 
static ChaCha s_chacha
 ChaCha20 cipher object (20-round configuration by default constructor).
 
static uint8_t s_keystreamBuf [CSPRNG_BLOCK_BYTES]
 One-block keystream cache. Refilled automatically when s_keystreamUsed >= CSPRNG_BLOCK_BYTES.
 
static uint8_t s_keystreamUsed = CSPRNG_BLOCK_BYTES
 Number of bytes consumed from s_keystreamBuf so far.
 

Detailed Description

ChaCha20-based CSPRNG for SH2SC-EDT — Receiver Node B (ATmega328P).

Part of the SH2SC-EDT project. Implements the C2P-ARQ protocol.

     This module wraps the ChaCha20 stream cipher as a Cryptographically
     Secure Pseudo-Random Number Generator (CSPRNG) for the ATmega328P.
     The cipher is seeded once with 256 bits of hardware entropy collected
     by generateEntropyPool(), then used as an unlimited deterministic
     keystream to produce session nonces.

     Mathematical basis:
     @code
     C = P XOR KS  ->  C = 0x00..0 XOR KS = KS
     @endcode
     Encrypting an all-zeros plaintext yields the raw ChaCha20 keystream.

     **Buffer design (AVR memory optimisation):**
     ChaCha20 generates output in 64-byte blocks. Invoking the cipher for
     every byte would be prohibitively expensive on an 8-bit MCU, so this
     module maintains a 64-byte keystream cache. getSecureRandom32() draws
     4 bytes per call; the block is refilled every 16 calls (~100 us at
     16 MHz).

     **Static SRAM budget (approximate):**
     - s_chacha object: ~140 bytes (ChaCha20 key schedule + state)
     - s_keystreamBuf:    64 bytes
     - s_keystreamUsed:    1 byte
     - Total:           ~205 bytes of 2048 bytes available

     **Requires:** Arduino Crypto library by Rhys Weatherley.
     Library Manager: "Crypto" by Rhys Weatherley.

     **Usage:**
     1. Call initCSPRNG(seed) ONCE in setup() after generateEntropyPool().
     2. Call getSecureRandom32() anywhere in the main loop for 32-bit random output.

Definition in file csprng.h.

Function Documentation

◆ getSecureRandom32()

uint32_t getSecureRandom32 ( )

Return 32 bits of CSPRNG output (non-blocking).

Normal cost: O(1) — four byte reads and one counter increment. Amortised refill cost: ~100 us every 16 calls (once per 64-byte block).

Byte assembly uses explicit shifts to avoid type-punning undefined behaviour; casting uint8_t* to uint32_t* is UB under the AVR strict-aliasing ABI.

Returns
A 32-bit pseudo-random value drawn from the ChaCha20 keystream.

Definition at line 126 of file csprng.h.

References CSPRNG_BLOCK_BYTES, s_fillKeystreamBlock(), s_keystreamBuf, and s_keystreamUsed.

+ Here is the call graph for this function:

◆ initCSPRNG()

void initCSPRNG ( const uint8_t *  hardwareSeed)

Seed the ChaCha20 CSPRNG with 256 bits of hardware entropy.

Key and nonce policy:

  • Key = hardwareSeed (256 bits, unique per power-on cycle).
  • IV = 0x00..0 (8 bytes, zeroed deliberately). A zero nonce is safe because the key itself is non-repeating; the (key, nonce) pair is globally unique across all sessions.

Pre-fills s_keystreamBuf so the very first getSecureRandom32() call returns immediately without an additional cipher invocation.

Parameters
hardwareSeedPointer to exactly 32 bytes produced by generateEntropyPool(). The pointer is read once; the caller is responsible for scrubbing the seed buffer after this call if desired.
Note
Must be called ONCE in setup() after generateEntropyPool() completes.

Definition at line 102 of file csprng.h.

References s_chacha, and s_fillKeystreamBlock().

+ Here is the call graph for this function:

◆ s_fillKeystreamBlock()

static void s_fillKeystreamBlock ( )
static

Produce the next 64-byte ChaCha20 keystream block into s_keystreamBuf.

Memory-efficient technique — zero the buffer in-place, then encrypt over it:

output[i] = input[i] XOR keystream[i] = 0x00 XOR keystream[i] = keystream[i]

This avoids allocating a second 64-byte "zeros input" buffer in SRAM. ChaCha20's internal 64-bit block counter is advanced automatically by encrypt(), so successive calls produce entirely distinct blocks; the keystream never repeats within 2^64 blocks.

Definition at line 75 of file csprng.h.

References CSPRNG_BLOCK_BYTES, s_chacha, s_keystreamBuf, and s_keystreamUsed.

Referenced by getSecureRandom32(), and initCSPRNG().

+ Here is the caller graph for this function:

Variable Documentation

◆ CSPRNG_BLOCK_BYTES

const uint8_t CSPRNG_BLOCK_BYTES = 64u
static

Size of one ChaCha20 keystream output block in bytes.

Must be a multiple of 4 so that getSecureRandom32() never straddles a block boundary. One block = 64 bytes = 512 bits.

Definition at line 49 of file csprng.h.

Referenced by getSecureRandom32(), and s_fillKeystreamBlock().

◆ s_chacha

ChaCha s_chacha
static

ChaCha20 cipher object (20-round configuration by default constructor).

Definition at line 52 of file csprng.h.

Referenced by initCSPRNG(), and s_fillKeystreamBlock().

◆ s_keystreamBuf

uint8_t s_keystreamBuf[CSPRNG_BLOCK_BYTES]
static

One-block keystream cache. Refilled automatically when s_keystreamUsed >= CSPRNG_BLOCK_BYTES.

Definition at line 55 of file csprng.h.

Referenced by getSecureRandom32(), and s_fillKeystreamBlock().

◆ s_keystreamUsed

uint8_t s_keystreamUsed = CSPRNG_BLOCK_BYTES
static

Number of bytes consumed from s_keystreamBuf so far.

Initialised to CSPRNG_BLOCK_BYTES to trigger an immediate refill on the very first call to getSecureRandom32().

Definition at line 62 of file csprng.h.

Referenced by getSecureRandom32(), and s_fillKeystreamBlock().