Add restricted wolfSSH ordering fix
Apply hash-pinned generated edits for CVE-2025-14942 while keeping wolfSSH 1.4.20 managed sources unchanged. Add the ABI header overlay, provenance records, and real state-machine interoperability contracts.
This commit is contained in:
@@ -11,6 +11,7 @@ from __future__ import annotations
|
||||
import argparse
|
||||
from dataclasses import dataclass
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
@@ -37,6 +38,7 @@ class Entry:
|
||||
sha256: str
|
||||
edits: tuple[Edit, ...]
|
||||
target: str = "" # Explicit nested library; empty means IDF COMPONENT_LIB.
|
||||
header: bool = False # PUBLIC overlay, never a translation unit.
|
||||
|
||||
|
||||
MODIFICATION_NOTICE = """/* Modified by the ESP32_serial_swiss_army_knife project on 2026-09-15.
|
||||
@@ -47,6 +49,15 @@ MODIFICATION_NOTICE = """/* Modified by the ESP32_serial_swiss_army_knife projec
|
||||
"""
|
||||
|
||||
|
||||
# Exact, reviewed consolidated delta; upstream mail patches are provenance only.
|
||||
# No network, patch utility, fuzz, or managed-component mutation at configure time.
|
||||
WOLFSSH_ORDER_DIR = Path(__file__).resolve().parent / "wolfssh_order"
|
||||
WOLFSSH_ORDER_PLAN = json.loads((WOLFSSH_ORDER_DIR / "delta.json").read_text())
|
||||
WOLFSSH_ORDER_EDITS = {
|
||||
path: tuple(Edit(**edit) for edit in item["edits"])
|
||||
for path, item in WOLFSSH_ORDER_PLAN.items()
|
||||
}
|
||||
|
||||
WIPE = """/* Retired secret-bearing storage must not survive allocator reuse. */
|
||||
static void security_override_wipe(void *buffer, size_t length)
|
||||
{
|
||||
@@ -427,7 +438,7 @@ ENTRIES = (
|
||||
), target="mbedx509"),
|
||||
Entry("wolfssh_internal", "wolfssl__wolfssh", "project",
|
||||
"managed_components/wolfssl__wolfssh/src/internal.c",
|
||||
"81ff1f9166708abd5c2911e9fe57c0aee01c88b5d3f68c909ee8a856d37f36a9", WOLFSSH_PARSER_EDITS + (
|
||||
"81ff1f9166708abd5c2911e9fe57c0aee01c88b5d3f68c909ee8a856d37f36a9", WOLFSSH_ORDER_EDITS["src/internal.c"] + WOLFSSH_PARSER_EDITS + (
|
||||
Edit(""" WS_UserAuthData_Password* pw = NULL;
|
||||
int ret = WS_SUCCESS;
|
||||
""", """ WS_UserAuthData_Password* pw = NULL;
|
||||
@@ -582,6 +593,18 @@ ENTRIES = (
|
||||
)
|
||||
|
||||
|
||||
ENTRIES += (
|
||||
Entry("wolfssh_ssh", "wolfssl__wolfssh", "project",
|
||||
"managed_components/wolfssl__wolfssh/src/ssh.c",
|
||||
"a4f479ff87eea0980ec1ebdf2c7dd090da473780181b695a56799cb9611f4366",
|
||||
WOLFSSH_ORDER_EDITS["src/ssh.c"]),
|
||||
Entry("wolfssh_internal_header", "wolfssl__wolfssh", "project",
|
||||
"managed_components/wolfssl__wolfssh/wolfssh/internal.h",
|
||||
"8e417149a68f8a6c0506957adf014b3e6c1727a723536826ce5fb0c9e1f1aba3",
|
||||
WOLFSSH_ORDER_EDITS["wolfssh/internal.h"], header=True),
|
||||
)
|
||||
|
||||
|
||||
def apply_edits(text: str, edits: tuple[Edit, ...]) -> str:
|
||||
for index, edit in enumerate(edits, 1):
|
||||
count = text.count(edit.old) if edit.old else 0
|
||||
@@ -607,6 +630,11 @@ def render_entry(entry: Entry, roots: dict[str, Path]) -> tuple[Path, bytes]:
|
||||
if entry.target and (entry.component != "mbedtls" or entry.target not in
|
||||
{"mbedtls", "mbedx509", "mbedcrypto"}):
|
||||
raise OverrideError("invalid nested target selection")
|
||||
if entry.header and (entry.name != "wolfssh_internal_header" or
|
||||
entry.component != "wolfssl__wolfssh" or entry.target or
|
||||
entry.root != "project" or entry.source !=
|
||||
"managed_components/wolfssl__wolfssh/wolfssh/internal.h"):
|
||||
raise OverrideError("unaudited header overlay")
|
||||
root = roots[entry.root].resolve()
|
||||
source = (root / entry.source).resolve()
|
||||
if not source.is_relative_to(root):
|
||||
@@ -615,7 +643,18 @@ def render_entry(entry: Entry, roots: dict[str, Path]) -> tuple[Path, bytes]:
|
||||
actual = hashlib.sha256(raw).hexdigest()
|
||||
if actual != entry.sha256:
|
||||
raise OverrideError(f"{entry.name}: SHA256 mismatch for {source}: expected {entry.sha256}, got {actual}; reaudit, do not repin blindly")
|
||||
return source, (MODIFICATION_NOTICE + apply_edits(raw.decode("utf-8"), entry.edits)).encode("utf-8")
|
||||
notice = MODIFICATION_NOTICE
|
||||
if entry.component == "wolfssl__wolfssh":
|
||||
notice += ("/* Ordering profile modified 2026-09-16: PR793/819/840/855/921\n"
|
||||
" * plus project restricted no-EXT_INFO correction. Provenance and\n"
|
||||
" * limitations: tools/wolfssh_order/README.md and delta.json.\n"
|
||||
" */\n")
|
||||
if entry.header:
|
||||
notice += ("#if defined(_WOLFSSH_INTERNAL_H_) && \\\n"
|
||||
" (!defined(SAK_WOLFSSH_ORDER_ABI) || SAK_WOLFSSH_ORDER_ABI != 20260916)\n"
|
||||
'#error "Security override: stale wolfSSH internal.h included before overlay"\n'
|
||||
"#endif\n#define SAK_WOLFSSH_ORDER_ABI 20260916\n")
|
||||
return source, (notice + apply_edits(raw.decode("utf-8"), entry.edits)).encode("utf-8")
|
||||
|
||||
|
||||
def write_if_changed(path: Path, data: bytes) -> bool:
|
||||
@@ -659,10 +698,13 @@ def generate(idf: Path, project: Path, binary: Path, entries: tuple[Entry, ...]
|
||||
if source in seen:
|
||||
raise OverrideError(f"ambiguous duplicate source: {source}")
|
||||
seen.add(source)
|
||||
target = output / entry.name / source.name
|
||||
target = (output / "wolfssh_include" / "wolfssh" / source.name
|
||||
if entry.header else output / entry.name / source.name)
|
||||
rendered.append((entry, source, target, data))
|
||||
lines = ["# Generated by tools/security_overrides.py; do not edit.",
|
||||
"set(SAK_SECURITY_OVERRIDE_IDS " + " ".join(names) + ")",
|
||||
"set(SAK_SECURITY_OVERRIDE_IDS " + " ".join(e.name for e in entries if not e.header) + ")",
|
||||
"set(SAK_SECURITY_HEADER_IDS " + " ".join(e.name for e in entries if e.header) + ")",
|
||||
"set(SAK_SECURITY_WOLFSSH_INCLUDE " + cmake_quote(str(output / "wolfssh_include")) + ")",
|
||||
"set(SAK_SECURITY_VERSION_HEADER " + cmake_quote(str(version)) + ")"]
|
||||
for entry, source, target, _ in rendered:
|
||||
for key, value in (("COMPONENT", entry.component), ("TARGET", entry.target), ("ORIGINAL", str(source)),
|
||||
|
||||
Reference in New Issue
Block a user