Harden SSH parsing and add notice tooling

- Enforce exact service and channel names with bounded failure parsing
- Add hash-pinned offline notice assembly and regression coverage
- Record advisory dispositions, provenance, integration evidence, and
  remaining gates
This commit is contained in:
2026-09-16 15:06:38 +02:00
parent bea33e1c95
commit 51f835c22f
29 changed files with 3332 additions and 46 deletions
+10 -4
View File
@@ -105,9 +105,9 @@ The existing global five-verifications/60-second fixed window is unchanged: malf
## 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. The existing generated wolfSSH override now bounds IGNORE/service strings, rejects zero-capacity string output and channel-window overflow, corrects ECC/Ed25519 key/signature labels, and enforces exact signature framing (ECC nested r/s bounds plus inner/outer consumption; Ed25519 outer consumption). These are PR892/881/880 subsets plus local framing corrections, not full backports; password wiping/async retention remain unchanged. PUBLIC `WOLFSSL_VALIDATE_ECC_IMPORT` and `WOLFSSL_ECDHX_SHARED_NOT_ZERO` now enable P-256 import validation and X25519 all-zero-result rejection, with effective production flags confirmed and fail-closed backend guards. See [key-validation evidence](ssh_key_validation_review.md) and [parser scope/limits](../tests/wolfssh_parser_contract/README.md). The restricted existing-profile correction for **CVE-2025-14942** is implemented as described below. **Still open:** PR899/deferred parsers, service/key-blob semantics and broader API applicability. Current raw SSH digest construction does not expose the reviewed short-digest/OID trigger; generic PR10131 API hardening is not backported. No exploit or whole-library clearance is demonstrated; added validation CPU/allocation cost and target interoperability remain unmeasured.
- [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 **eight generated C sources plus one header** carry prominent modification notices: the baseline **2026-09-15** notice plus **2026-09-16** ordering/provenance notices on wolfSSH outputs, 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.
- [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. The existing generated wolfSSH override now bounds IGNORE/service strings, rejects zero-capacity string output and channel-window overflow, corrects ECC/Ed25519 key/signature labels, and enforces exact signature framing (ECC nested r/s bounds plus inner/outer consumption; Ed25519 outer consumption). These are PR892/881/880 subsets plus local framing corrections, not full backports; password wiping/async retention remain unchanged. PUBLIC `WOLFSSL_VALIDATE_ECC_IMPORT` and `WOLFSSL_ECDHX_SHARED_NOT_ZERO` now enable P-256 import validation and X25519 all-zero-result rejection, with effective production flags confirmed and fail-closed backend guards. See [key-validation evidence](ssh_key_validation_review.md) and [parser scope/limits](../tests/wolfssh_parser_contract/README.md). The restricted existing-profile correction for **CVE-2025-14942** is implemented as described below. The [finite remaining SSH review](ssh_parser_remaining_review.md) is complete: bounded exact CHANNEL_FAILURE recipient parsing (fatal policy retained), exact `ssh-userauth` service validation, and exact length/byte dispatch for all nine channel-request names are implemented. Unknown-request/trailing-payload behavior is preserved. PR899 client key skips are unchanged and blocked by current server role/ordering; PR918/919 forwarding is disabled. The inspected generic signature caller trace found no attacker-selected short-digest/OID path; generic APIs remain unpatched. These are profile-specific dispositions, not exhaustive parser/library safety; revisit on caller, feature, KEX or source changes. No exploit or whole-library clearance is demonstrated; added validation CPU/allocation cost and target interoperability remain unmeasured.
- [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. The [finite IDF applicability completion](idf_security_review.md#finite-applicability-completion--2026-09-16) dispositions all six named findings: ECDH small-output, zero-length ECC PK parse, basicConstraints, server NewSessionTicket and stale ASN.1 length are not current paths/configurations for their documented reasons; optimized ECC reduction is active but its privileged-local/physical side-channel attacker model is excluded. No new current-path correction was established. Only the first advisory-index page was screened; unpatched primitives and broader coverage remain, not “all CVEs safe.”
- [Dependency license inventory](dependency_licenses.md) is a bounded engineering inventory, not legal or distribution clearance. All **eight generated C sources plus one header** carry prominent modification notices: the baseline **2026-09-15** notice plus **2026-09-16** ordering/provenance notices on wolfSSH outputs, 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 exact icon provenance and recipient license delivery remain open. Notice assembly does not prove recipient delivery. [Offline notice assembly](release_packaging.md) is implemented by [tools/release_notices.py](../tools/release_notices.py): 62 mandatory hash/size-pinned inputs, deterministic bounded outputs, fail-closed preflight and no overwrite/fetch/build/device access. Parent notices suite: 30 PASS. Supplied independent review found no actionable scoped parser/bundle defects and verified two actual 62-input bundles were deterministic. The previously measured actual bundle was 64 files / 541,147 bytes; that is snapshot evidence, not a newly measured bundle size or legal clearance.
- **Restricted ordering correction implemented, not a full upstream backport or sign-off.** The [ordering review](wolf_security_review.md#restricted-ordering-correction-and-remaining-gates) and [provenance/prerequisite disposition](../tools/wolfssh_order/README.md) document the audited PR793/819/840/855/921 subsets plus local gates. Existing X25519/P-256 KEX only; independent SELF/PEER state, exact expected replies and authentication-phase checks cover both roles. Queued NEWKEYS survives WANT_WRITE without duplication. **EXT_INFO is deliberately disabled; no `server-sig-algs` is sent**, and `extInfoSent` stays zero. CMake applies the generated ABI header BEFORE PUBLIC and via a PUBLIC forced include; joined `-include/path` flags fix PlatformIO sorting/deduplication for ordering and crypto guards. Review's misplaced EOF guard is corrected before channel mutation; verification found no scoped blocker. Target cleanup during rekey and no-EXT_INFO client compatibility remain pending.
- 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.
@@ -131,12 +131,14 @@ Raw flash, RAM and dumps can contain Wi-Fi passwords, private keys, password ver
### Ordering host/build evidence — 2026-09-16
Supplied parent `pio run` **PASS**: **94,340 B linked RAM / 1,768,701 B flash**, unchanged RAM / **248 B flash** versus 1,768,949 B. **Supplied final parent results: all six suites PASS** — ordering `--interop` (8,028 checks, seven rejected mutations, 12 sessions with exact 256 KiB echo each and clean channel close plus transport EOF), SDK overrides `--build-dir .pio/build/esp32-s3-devkitc-1-n16r8`, auth (135 cases), protocol, strict crypto, and parser (3,124 cases in each of two stack modes). Interop required unsandboxed approval solely for local AF_UNIX sockets; no remote network or device operation occurred. This documentation update did not rerun firmware or host suites.
Supplied parent `pio run` **PASS**: **94,340 B linked RAM / 1,768,901 B flash**, unchanged RAM / **+200 B flash** versus 1,768,701 B. **Supplied final parent results: all seven suites PASS** — ordering `--interop` (8,028 checks, seven rejected mutations, 12 sessions with exact 256 KiB echo each and clean channel close plus transport EOF), SDK overrides `--build-dir .pio/build/esp32-s3-devkitc-1-n16r8`, auth (135 cases), protocol, strict crypto, notices (30), and parser (3,258 cases in each of two stack modes plus channel profiles; 11 + 18 + 2 rejected mutations). Interop required unsandboxed approval solely for local AF_UNIX sockets; no remote network or device operation occurred. This documentation update did not rerun firmware or host suites.
Supplied agent ordering tests passed **8,028 checks and seven rejected mutations**, including the corrected EOF guard and real shutdown/exit-status rekey fences. The installed PlatformIO/SCons adapter regression validates joined forced-header flags with a real Xtensa consumer and rejects a split-option mutation. The [test README and code](../tests/wolfssh_order_contract/README.md) describe full generated translation units, real wolfCrypt, message-ID matrices, fragmented writes and both roles/rekey directions.
Initial host interoperability failed a harness close race: early `INTEROP PASS` preceded OpenSSH `Broken pipe` and was not a pass. The harness now waits for peer channel close and transport EOF, passes a local socket descriptor to OpenSSH, independently owns/reaps the server, and checks both process exits. Final agent `python3 tests/wolfssh_order_contract/run.py --interop --interop-repeat 3` evidence: **36/36 sessions**, each exact **256 KiB** binary echo, **ten** key exchanges in client-rekey cases or **two** in fragmented server-rekey cases, clean exits and no EXT_INFO. Coverage uses OpenSSH 10.2p1, both KEX algorithms, Ed25519/P-256/password authentication and AES128-GCM. It is not general library shutdown, arbitrary-client or target evidence. Whole-phase gates remain pending.
The [source-authoritative parser report](ssh_parser_remaining_review.md#validation-and-remaining-handoff) and [test contract](../tests/wolfssh_parser_contract/README.md) split the channel matrix from the 3,258 base cases: **2,737 per stack mode** for TERM-only, TERM+SHELL and TERM+SHELL+AGENT; **2,735 per stack mode** for no-terminal and SHELL-only. All five profiles run both modes; alternate features are host fixtures, not firmware enablement. Mutations are **11 base + 18 name/length + 2 real application admission gates**. Parent ordering adds **12 OpenSSH sessions**, each exact **256 KiB**, rekey and clean client/server exit; SDK tests checked actual build registration. These integrated parent results supersede the parser report's earlier stale-build handoff, without changing its historical execution record. Independent review reported no actionable defects within the scoped parser/bundle review, not a Phase 9 approval.
### 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,768,949 B flash**. RAM is unchanged and flash is **1,732 B larger** than the preceding 1,767,217 B mitigation build. Linked size is not runtime headroom or timing evidence.
@@ -206,6 +208,10 @@ Retain these checks for the user's final whole-phase test session; do not stop i
## Staged next work
- **Implementation/maintenance gate:** the finite SSH and six-finding IDF reviews are complete for their stated profiles; do not re-list them as unimplemented. Finish broader advisory coverage and resolve any newly established current-path findings with pinned changes and fresh production-source tests. Optional ASN.1/ECDH/basicConstraints defense-in-depth backports are not implemented or required by a demonstrated current-path finding.
- **Release gate:** notice assembly is implemented; validate actual firmware/device/browser delivery, corresponding source and preferred asset sources, radio-blob legal basis, wolfSSH packaging clarification, exact icon provenance, final runtime/bootloader attribution and any Installation Information. See [packaging gates](release_packaging.md#separate-work-before-distribution).
- **Target/acceptance gate:** rehearse operations and the combined target checklist above, including panic/recovery, abuse/isolation, cleanup during rekey, intended-client compatibility without EXT_INFO, loaded KEX/rekey and heap/stack/CPU timing. Obtain explicit whole-phase acceptance; no scoped reviewer or host PASS can substitute.
- **Continue 9D maintenance and lifecycle.** Execute the [remaining ordering gates and advisory work](wolf_security_review.md#restricted-ordering-correction-and-remaining-gates), 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.