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:
+105
-2
@@ -36,6 +36,15 @@ class Entry:
|
||||
source: str
|
||||
sha256: str
|
||||
edits: tuple[Edit, ...]
|
||||
target: str = "" # Explicit nested library; empty means IDF COMPONENT_LIB.
|
||||
|
||||
|
||||
MODIFICATION_NOTICE = """/* Modified by the ESP32_serial_swiss_army_knife project on 2026-09-15.
|
||||
* Generated security-corrected source; edits are maintained in
|
||||
* tools/security_overrides.py. Do not edit this generated copy.
|
||||
* Upstream copyright and license notices are retained below.
|
||||
*/
|
||||
"""
|
||||
|
||||
|
||||
WIPE = """/* Retired secret-bearing storage must not survive allocator reuse. */
|
||||
@@ -103,7 +112,98 @@ TLS_POLICY = """ /* mbedTLS retains this pointer: it must outlive every serve
|
||||
|
||||
"""
|
||||
|
||||
# Official patches (TLS 1.2 hunk only for EMS):
|
||||
# https://github.com/espressif/esp-idf/commit/d51b1076092487e533eadf8b48c9c8579d3a6712.patch
|
||||
# https://github.com/Mbed-TLS/mbedtls/commit/f595df4569c1a1650ad9d077e2f2e819e9f1dddb.patch
|
||||
# https://github.com/Mbed-TLS/mbedtls/commit/bfaf4a47fd33da860796feaba6235847acb71127.patch
|
||||
# DHCP uses equivalent remaining-length checks to avoid forming pointers beyond
|
||||
# the input object. Keep original upstream notices verbatim, rather than changing
|
||||
# their copyright year; the central project modification notice is separate.
|
||||
ENTRIES = (
|
||||
Entry("dhcpserver", "lwip", "idf",
|
||||
"components/lwip/apps/dhcpserver/dhcpserver.c",
|
||||
"953f46189bc64680ea5fa761e75511fadb3aebf698a0d9dff251d77166d78b80", (
|
||||
Edit("#define DHCP_OPTION_SUBNET_MASK 1",
|
||||
"#define DHCP_OPTION_PAD 0\n#define DHCP_OPTION_SUBNET_MASK 1"),
|
||||
Edit(" bool is_dhcp_parse_end = false;\n", ""),
|
||||
Edit(" switch ((s16_t) *optptr) {", """ if (*optptr == DHCP_OPTION_PAD) {
|
||||
optptr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*optptr == DHCP_OPTION_END) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (end - optptr < 2) {
|
||||
break;
|
||||
}
|
||||
|
||||
u8_t opt_len = optptr[1];
|
||||
|
||||
if (opt_len > end - optptr - 2) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((s16_t) *optptr) {"""),
|
||||
Edit(" type = *(optptr + 2);", """ if (opt_len >= 1) {
|
||||
type = optptr[2];
|
||||
}"""),
|
||||
Edit(""" if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
|
||||
#if DHCPS_DEBUG
|
||||
DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\\n");
|
||||
#endif
|
||||
s.state = DHCPS_STATE_ACK;
|
||||
} else {
|
||||
#if DHCPS_DEBUG
|
||||
DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\\n");
|
||||
#endif
|
||||
s.state = DHCPS_STATE_NAK;
|
||||
}""", """ if (opt_len >= 4) {
|
||||
if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
|
||||
#if DHCPS_DEBUG
|
||||
DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\\n");
|
||||
#endif
|
||||
s.state = DHCPS_STATE_ACK;
|
||||
} else {
|
||||
#if DHCPS_DEBUG
|
||||
DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\\n");
|
||||
#endif
|
||||
s.state = DHCPS_STATE_NAK;
|
||||
}
|
||||
}"""),
|
||||
Edit("""
|
||||
case DHCP_OPTION_END: {
|
||||
is_dhcp_parse_end = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_dhcp_parse_end) {
|
||||
break;
|
||||
}
|
||||
|
||||
optptr += optptr[1] + 2;""", """
|
||||
}
|
||||
|
||||
optptr += opt_len + 2;"""),
|
||||
)),
|
||||
Entry("mbedtls_ssl_tls", "mbedtls", "idf",
|
||||
"components/mbedtls/mbedtls/library/ssl_tls.c",
|
||||
"b726c0c55bc5f32255f129d55f9f2fface85ce83de90a2d16c9017b93b738bff", (
|
||||
Edit(' MBEDTLS_SSL_DEBUG_RET(1, "calc_verify", ret);\n',
|
||||
' MBEDTLS_SSL_DEBUG_RET(1, "calc_verify", ret);\n return ret;\n'),
|
||||
), target="mbedtls"),
|
||||
Entry("mbedtls_x509_create", "mbedtls", "idf",
|
||||
"components/mbedtls/mbedtls/library/x509_create.c",
|
||||
"fd399239aee30384786a19b47bfe5dd22b979d5d89bb38f29f0c82a3d81daaf7", (
|
||||
Edit(" oid.p = mbedtls_calloc(1, oid.len);\n",
|
||||
""" oid.p = mbedtls_calloc(1, oid.len);
|
||||
if (oid.p == NULL) {
|
||||
return MBEDTLS_ERR_X509_ALLOC_FAILED;
|
||||
}
|
||||
"""),
|
||||
), target="mbedx509"),
|
||||
Entry("wolfssh_internal", "wolfssl__wolfssh", "project",
|
||||
"managed_components/wolfssl__wolfssh/src/internal.c",
|
||||
"81ff1f9166708abd5c2911e9fe57c0aee01c88b5d3f68c909ee8a856d37f36a9", (
|
||||
@@ -283,6 +383,9 @@ def verify_version(idf: Path) -> Path:
|
||||
def render_entry(entry: Entry, roots: dict[str, Path]) -> tuple[Path, bytes]:
|
||||
if not all(re.fullmatch(r"[a-zA-Z0-9_-]+", value) for value in (entry.name, entry.component)):
|
||||
raise OverrideError("invalid entry name/component")
|
||||
if entry.target and (entry.component != "mbedtls" or entry.target not in
|
||||
{"mbedtls", "mbedx509", "mbedcrypto"}):
|
||||
raise OverrideError("invalid nested target selection")
|
||||
root = roots[entry.root].resolve()
|
||||
source = (root / entry.source).resolve()
|
||||
if not source.is_relative_to(root):
|
||||
@@ -291,7 +394,7 @@ 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, apply_edits(raw.decode("utf-8"), entry.edits).encode("utf-8")
|
||||
return source, (MODIFICATION_NOTICE + apply_edits(raw.decode("utf-8"), entry.edits)).encode("utf-8")
|
||||
|
||||
|
||||
def write_if_changed(path: Path, data: bytes) -> bool:
|
||||
@@ -341,7 +444,7 @@ def generate(idf: Path, project: Path, binary: Path, entries: tuple[Entry, ...]
|
||||
"set(SAK_SECURITY_OVERRIDE_IDS " + " ".join(names) + ")",
|
||||
"set(SAK_SECURITY_VERSION_HEADER " + cmake_quote(str(version)) + ")"]
|
||||
for entry, source, target, _ in rendered:
|
||||
for key, value in (("COMPONENT", entry.component), ("ORIGINAL", str(source)),
|
||||
for key, value in (("COMPONENT", entry.component), ("TARGET", entry.target), ("ORIGINAL", str(source)),
|
||||
("GENERATED", str(target)), ("SHA256", entry.sha256)):
|
||||
lines.append(f"set(SAK_SECURITY_{entry.name}_{key} {cmake_quote(value)})")
|
||||
manifest = output / "manifest.cmake"
|
||||
|
||||
Reference in New Issue
Block a user