Apply Phase 9D security mitigations

- Add fail-closed wolfSSL small-math policy and vectors
- Backport DHCP, EMS, and X.509 allocation fixes
- Extend source override validation and operational documentation
This commit is contained in:
2026-09-15 23:06:23 +02:00
parent cdc9c7335a
commit c010e1a1d5
22 changed files with 1562 additions and 38 deletions
+31 -6
View File
@@ -1,6 +1,6 @@
# Security hardening — Phase 9
**Status: in progress.** Phase 8 is complete at the accepted 8D.22 scope. **9A crash/debug policy, 9B SSH admission/credential handling and 9C library cleanup/protocol policy** are implemented with host/build validation. At the user's request, hardware validation is deferred to **Phase 9 as a whole**, not an approval gate between implementation slices. This document records policy and procedures, not unrun passes or production certification.
**Status: in progress.** Phase 8 is complete at the accepted 8D.22 scope. **9A crash/debug policy, 9B SSH admission/credential handling and 9C library cleanup/protocol policy** are implemented with host/build validation. At the user's request, hardware validation is deferred to **Phase 9 as a whole**, not an approval gate between implementation slices. **9D maintenance/lifecycle is in progress, with unresolved advisory and distribution/source/notice questions. Phase 9 is not complete or production-ready.** This document records policy and procedures, not unrun passes or production certification.
## Scope and threat model
@@ -71,7 +71,7 @@ Hidden UART0 and shared remote-console prompts now reject overflow or unsupporte
### Reproducible source corrections
`tools/security_overrides.py` verifies full original-file SHA-256 values and ESP-IDF 5.5.0, applies exact-once edits, and generates four corrected sources under the build directory. `cmake/security_overrides.cmake`, included after `project()`, replaces exactly the corresponding sources in existing IDF/component targets, retaining compilation properties. Installed SDK/managed sources and their notices remain unchanged. Missing, changed or ambiguous sources fail configuration; there is no unpatched fallback. Do not edit derived files or repin a hash merely to make an upgrade build.
`tools/security_overrides.py` verifies full original-file SHA-256 values and ESP-IDF 5.5.0, applies exact-once edits, and generates seven corrected sources under the build directory (four from 9C plus three advisory backports in 9D). `cmake/security_overrides.cmake`, included after `project()`, replaces exactly the corresponding sources in existing IDF/component targets, retaining compilation properties. Installed SDK/managed sources and their notices remain unchanged. Missing, changed or ambiguous sources fail configuration; there is no unpatched fallback. Do not edit derived files or repin a hash merely to make an upgrade build.
- **HTTPS:** delete TLS on post-handshake transport-allocation failure; fully destroy retained TLS configuration on failed HTTPD start; wipe the copied raw private key before free. Failed stop still retains live ownership.
- **HTTPD parser:** allocate/copy/wipe/free scratch on resize, preserve the old pointer on allocation failure, wipe final scratch, and handle the null initial parser pointer without undefined subtraction. Pending/unread bytes retain their existing behavior.
@@ -102,6 +102,16 @@ A non-consuming quota/epoch check now runs after valid challenge consumption but
The existing global five-verifications/60-second fixed window is unchanged: malformed requests do not charge it, counter clear does not replenish it, and web service restart does. This differs deliberately from SSH's boot-lifetime buckets. The first boot-minute window remains anchored at uptime zero. Challenge monopolization, global-budget starvation and malformed-body work while budget is available are not solved by this early check.
## 9D maintenance and lifecycle — in progress
- [Security operations](security_operations.md) supplies source-checked provisioning, explicit-save, account/key/identity rotation, recovery, reconstruction and approved erase/decommissioning procedures. There is no implemented configuration backup/export or private-identity restore workflow. Commands and checklists are not device execution evidence; the user will validate Phase 9 as a whole.
- [wolfSSL/wolfSSH review and implementation addendum](wolf_security_review.md): the **CVE-2025-12888** Xtensa mitigation now selects `CURVE25519_SMALL` and `ED25519_SMALL` consistently for wolfSSL and consumers. The PUBLIC forced-include resolved-settings guard rejects missing small implementations, X25519 blinding (incompatible with small in this pinned version), and unreviewed Curve448/Ed448 enablement. **Still open:** server-recommended message-order correction for **CVE-2025-14942**, parser/ECC review and broader API/feature applicability. No server credential-leak or invalid-curve exploit is demonstrated; target timing/interoperability remains untested.
- [Focused IDF review and implementation addendum](idf_security_review.md): pinned backports now implement DHCP option bounds (**CVE-2026-45160**), TLS 1.2 EMS failure return (**CVE-2026-50581**) and X.509 OID allocation-failure handling (**CVE-2026-34874**). Explicit nested-target validation places the mbedTLS edits on `mbedtls`/`mbedx509`, retaining source properties and exactly-one-source checks. WS negotiation **CVE-2026-45541** and ASN.1 named-data **CVE-2025-48965** remain unpatched with the review's qualified applicability, not blanket closure.
- [Dependency license inventory](dependency_licenses.md) is a bounded engineering inventory, not legal or distribution clearance. All seven generated sources now carry prominent modification notices dated **2026-09-15**, with upstream notices retained, including both mbedTLS dual-license headers. That narrow finding is resolved. Radio-blob corresponding-source/exception questions, actual firmware/device/browser notice delivery, preferred-source packaging, wolfSSH package-license discrepancy and icon provenance/full-license work remain open. Existing repository notices alone are not a complete release bundle.
- No dependency versions were upgraded. Beyond the implemented backports above, proposed upgrades/backports remain candidates, not approved compatible versions. Re-audit coherent source/header changes, effective compile policy, exact-hash overrides and callback/parser contracts, then obtain host/build and whole-phase target evidence. 9A9C passes below are historical scoped evidence, not closure of these newly recorded findings.
Secure boot and encrypted NVS remain excluded. No runbook, advisory report or license inventory establishes production readiness or authorizes a destructive device operation.
## Operational profiles
These are handling and validation profiles of the **same supported build baseline**, not separate PlatformIO environments or selectable security overrides.
@@ -118,7 +128,22 @@ Raw flash, RAM and dumps can contain Wi-Fi passwords, private keys, password ver
## Validation gates
### Host and build — passed 2026-09-15 (9A9C)
### Mitigation host/build evidence — 2026-09-15
Supplied parent results (not rerun for this documentation update): `pio run` **PASS**, **94,340 B linked RAM / 1,767,217 B flash**. Against the historical 9C build below, RAM is unchanged and flash is **64,092 B smaller**. Linked size is not runtime headroom or timing evidence.
All four parent commands passed:
```sh
CCACHE_DISABLE=1 python3 tests/sdk_security_overrides/run.py --build-dir .pio/build/esp32-s3-devkitc-1-n16r8
CCACHE_DISABLE=1 python3 tests/wolf_crypto_policy/run.py
CCACHE_DISABLE=1 python3 tests/wolfssh_auth_contract/run.py
CCACHE_DISABLE=1 python3 tests/ssh_protocol_policy/run.py
```
The independent reviewer reports the first two suites passed with no blocking implementation defects. Documentation verification separately matched all seven existing generated files to pinned originals plus checked-in edits/notices and checked retained mbedTLS license headers. This is scoped implementation/host/build evidence, not completed wolfSSH ordering/parser/ECC review, license packaging clearance or whole-phase acceptance. No target evidence, upgrade, asset regeneration or device operation is claimed.
### Host and build — historical passes 2026-09-15 (9A9C)
From the repository root:
@@ -136,13 +161,13 @@ python3 tests/ssh_protocol_policy/run.py
python3 tests/web_cookie_auth/run.py --admission
```
Latest 9C `pio run` passed with **94,340 B linked RAM / 1,831,309 B flash**, unchanged linked RAM / +1,384 B flash against 9B. This is linked size, not measured runtime headroom. Five focused suites passed after final HTTPD first-read correction: pinned SDK cleanup/TLS/source registration, 135 generated wolfSSH parser/control-flow cases, secure allocator, SSH policy (including 15 actual context-integration cases), and web early admission/wiping. The allocator's optional installed-SDK extent contract was also run with the installed IDF path and passed; plain invocation reports that optional check skipped. Seventeen integrated regression commands passed before the final first-read addition, including SSH auth/management, HTTPD idle, HTTPS lifecycle, five cookie-auth modes and the 18-case crash-policy matrix. All ten existing cookie-auth domain modes also passed during implementation. Independent reviews found no blocking issues; the identified inherited first-read pointer issue was corrected and tested. Use `CCACHE_DISABLE=1` on host commands if the compiler wrapper's cache is read-only in a sandbox. No upload, erase, eFuse operation or target test was performed.
Historical final 9C `pio run` passed with **94,340 B linked RAM / 1,831,309 B flash**, unchanged linked RAM / +1,384 B flash against 9B. This is linked size, not measured runtime headroom. Five focused suites passed after final HTTPD first-read correction: pinned SDK cleanup/TLS/source registration, 135 generated wolfSSH parser/control-flow cases, secure allocator, SSH policy (including 15 actual context-integration cases), and web early admission/wiping. The allocator's optional installed-SDK extent contract was also run with the installed IDF path and passed; plain invocation reports that optional check skipped. Seventeen integrated regression commands passed before the final first-read addition, including SSH auth/management, HTTPD idle, HTTPS lifecycle, five cookie-auth modes and the 18-case crash-policy matrix. All ten existing cookie-auth domain modes also passed during implementation. Independent reviews found no blocking issues; the identified inherited first-read pointer issue was corrected and tested. Use `CCACHE_DISABLE=1` on host commands if the compiler wrapper's cache is read-only in a sandbox. No upload, erase, eFuse operation or target test was performed.
Record the revision, compiler/build outcome and effective configuration. Confirm that the matrix accepts the supported configuration, rejects each prohibited option independently, and rejects absent/disabled required settings. Confirm the normal firmware build compiles the guard. A rejected unsafe configuration is an expected negative-test result, not a firmware build pass. Neither these commands nor a successful build proves target panic behavior.
### Combined Phase 9 target validation — deferred, not run
Retain these checks for the final phase test session; do not stop implementation for a separate 9A/9B/9C sign-off.
Retain these checks for the user's final whole-phase test session; do not stop implementation for separate slice sign-off. Include the [9D operational rehearsal](security_operations.md#deferred-whole-phase-9-hardware-rehearsal) and targeted message-order/parser/key-validation/interoperability checks for the eventual reviewed advisory mitigations. None is recorded as passed here.
#### Crash and recovery
@@ -171,7 +196,7 @@ Retain these checks for the final phase test session; do not stop implementation
## Staged next work
- **Next — 9D maintenance and lifecycle.** Review current ESP-IDF/wolfSSL/wolfSSH advisories and third-party licenses, then plan any upgrades and source re-audits separately. Complete provisioning, key rotation, backup, factory reset, recovery and decommissioning runbooks without claiming physical-extraction resistance or secure erasure. No external advisory or complete license review has been performed by 9C.
- **Continue 9D maintenance and lifecycle.** Resolve the [open advisory priorities](wolf_security_review.md#release-decision--current-path-priorities), finish broader dependency coverage beyond the bounded IDF/mbedTLS review and three implemented backports, and address the [release source/notice work](dependency_licenses.md#actionable-release-work-not-performed). Runbooks are documented, not rehearsed; remaining mitigations/reviews, distribution clearance and whole-phase acceptance remain outstanding.
- **Retained evidence limits:** 9C completes a bounded cleanup/protocol review, not every-library-copy zeroization. Live inline residue, compaction tails, hardware/stack intermediates, global admission starvation and resource/interop measurements remain documented limitations or combined target gates. Any additional hardening must preserve owner lifetimes and bounded recovery.
- **Phase 10: OTA trust.** Define independent image-signature verification, trust-anchor provisioning, rotation/revocation, rollback/downgrade and recovery policy without secure boot. Authenticated transport alone is not image-signing policy, and OTA signature checks cannot prevent physical firmware replacement.