Skip to content

Finding 8: multi-source entropy with ChaCha20 KDF conditioning#20

Open
sensei-hacker wants to merge 4 commits intosecure_01from
security/add-encryption-test-suite
Open

Finding 8: multi-source entropy with ChaCha20 KDF conditioning#20
sensei-hacker wants to merge 4 commits intosecure_01from
security/add-encryption-test-suite

Conversation

@sensei-hacker
Copy link
Copy Markdown
Owner

@sensei-hacker sensei-hacker commented Dec 2, 2025

Summary

  • Replaces single-source `RandRSSI()` with `CollectEntropy()` for session key and nonce generation
  • XOR-mixes RSSI analog noise and ESP32 hardware TRNG into a 32-byte accumulator
  • Conditions output via ChaCha20 used as a PRF — same construction as Linux kernel CRNG (v5.17+)
  • Replaces the incomplete `GetRandomBytes()` stub left in the codebase
  • Fixes hardcoded `24` at call site → `sizeof(nonce_key)` to guard against future struct changes
  • Adds compile-time `#warning` when no radio is defined and RSSI source is unavailable

Security

Finding 8 (MEDIUM): RNG quality — RSSI sampling alone is insufficient for cryptographic key material.

Raw XOR of entropy sources is not safe as direct key material; a conditioning step is required. ChaCha20 with entropy as the key encrypting zeros yields a keystream that is computationally indistinguishable from uniform random under PRF security — no separate SHA-256 dependency needed.

Testing

Native unit tests: `pio test -e native` with `-DUSE_ENCRYPTION` — 21/21 previously-passing tests still pass, 2 pre-existing failures (Finding #1, unrelated).

Hardware validation on ESP32-D0WDQ6 @ 240 MHz via `test_esp32_standalone/`:

Test Result
`esp_random()` non-zero PASS (0x43C6BC54)
`esp_random()` varies across 10 calls PASS
`CollectEntropy()` output non-zero PASS
Two successive calls produce different output PASS
ChaCha20 KDF deterministic (same key → same output) PASS
Different keys → different output PASS
Bit distribution over 1008 bytes PASS (50.8% ones)

ChaCha20 adds 3.52 µs per packet (0.09% CPU at 250 Hz) — negligible overhead.

Code Review

Reviewed with inav-code-review agent and security analyst. Critical findings addressed: KDF conditioning added, flawed timer jitter source removed, sizeof used at call site.

This commit adds a comprehensive test suite for PrivacyLRS encryption,
demonstrating security findings from cryptographic analysis and providing
regression testing for security fixes.

Test Coverage (24 tests total):
- Stream cipher counter synchronization (Finding #1 - CRITICAL)
  * 2 tests demonstrate desynchronization vulnerabilities
  * Tests fail as expected, validating the security finding
- Key logging documentation (Finding #4 - HIGH)
- Forward secrecy validation (Finding #7 - MEDIUM)
- RNG quality checks (Finding #8 - MEDIUM)
- ChaCha20 functionality verification (10 tests)
- Integration tests with timer simulation (6 tests)

Expected Test Results:
- WITHOUT fixes: 2 tests FAIL (Finding #1), 22 tests PASS
- AFTER Finding #1 fix: All 24 tests PASS

Test Execution:
  cd src
  PLATFORMIO_BUILD_FLAGS="-DRegulatory_Domain_ISM_2400 -DUSE_ENCRYPTION" \
    pio test -e native --filter test_encryption

Files Added:
- test/test_encryption/test_encryption.cpp (1540 lines)
- test/test_encryption/README.md (comprehensive documentation)

This is Phase 1 of the security improvement project. Phase 2 will
implement fixes for the critical synchronization vulnerability.
Resolves build failures in native test environment that were blocking
PR #18 validation.

**Issue #1: Missing stdio.h header**
- Added #include <cstdio> to test_encryption.cpp
- Fixes printf() undeclared errors on line 1535-1536

**Issue #2: Undefined ICACHE_RAM_ATTR for native builds**
- Added #include "targets.h" to encryption.h
- Added TARGET_NATIVE case in targets.h to define ICACHE_RAM_ATTR as empty
- Fixes "expected initializer before 'DecryptMsg'" errors

**Test Results:**
- Native build now succeeds (24 tests: 21 pass, 2 intentionally fail)
- 2 failing tests demonstrate Finding #1 vulnerability (as expected)
- All compilation errors resolved

**Files Changed:**
- src/test/test_encryption/test_encryption.cpp (+1 line)
- src/include/encryption.h (+2 lines)
- src/include/targets.h (+5 lines)
@sensei-hacker sensei-hacker changed the base branch from master to secure_01 December 2, 2025 04:56
Resolved merge conflict in test_encryption.cpp (whitespace differences only).
The files were functionally identical, used secure_01 version for consistency.
Single RSSI source is insufficient for session key/nonce generation.
CollectEntropy XOR-mixes RSSI noise and ESP32 hardware TRNG into a
32-byte accumulator, then conditions output via ChaCha20 as a PRF
(same construction as Linux kernel CRNG v5.17+). Replaces the
incomplete GetRandomBytes stub.

Also adds test_esp32_standalone with hardware validation tests covering
esp_random() liveness, KDF determinism, output uniqueness, and bit
distribution (50.8% ones measured on ESP32-D0WDQ6 @ 240 MHz).
@sensei-hacker sensei-hacker changed the title Fix native build infrastructure for encryption tests Finding 8: multi-source entropy with ChaCha20 KDF conditioning Mar 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant