Commit graph

3 commits

Author SHA1 Message Date
3a1ba15851 feat(tls): X.509 basicConstraints + EKU chain hardening (rv2 9 F3c-net decision 6)
- crypto.c: x509_find_ext (generic extension walker) + wo_x509_basic_constraints
  (cA / pathLenConstraint, absent => not a CA) + wo_x509_eku_serverauth_ok
  (EKU absent, serverAuth, or anyEKU => usable; else not)
- wo_tls_verify_chain enforces decision 6: the leaf must be server-usable
  (EKU), every server-sent issuer and the signing anchor must be a CA
  (basicConstraints CA:TRUE) with a pathLenConstraint covering the
  intermediates below it — stops a leaf masquerading as a CA
- gen_x509.py extended (folds in the wildcard leaf, adds EKU clientAuth-only,
  EKU serverAuth, a non-CA intermediate + a leaf issued under it); vectors
  regenerated
- KATs: extractors (test_crypto 104) + chain enforcement (test_tls 103) —
  EKU serverAuth accepted, clientAuth-only rejected, leaf-under-non-CA
  rejected though every signature verifies; existing chains still pass.
  ASan/UBSan clean

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 3811418014c2c8d9bc3a9464256f52104261b1b9)
2026-09-15 01:15:31 +02:00
d7a6888931 feat(tls): SAN/hostname verification + driver enforcement (rv2 9 phase E/F3c)
- wo_x509_check_host: match a hostname against the cert subjectAltName
  dNSNames (RFC 6125) — case-insensitive, single left-most wildcard that
  covers exactly one label; no SAN => refused; no legacy CN fallback.
  Completes the phase-E deferred hostname check (walks the [3] extensions)
- wo_tls_client_set_host + driver enforcement: with a host set, a leaf
  whose SAN does not match is refused at the Certificate step (MITM
  defense); unset skips the check (offline testing only, documented unsafe)
- KAT: exact/case-insensitive/mismatch, no-SAN refused, wildcard one-label
  (not zero, not sub-label) via a wildcard-SAN cert; driver refuses the
  RFC 8448 leaf (no SAN) once a host is set. test_crypto 95, test_tls 91,
  ASan/UBSan clean

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 319ce8bfcf608030f958b36ab2c8f62fd76e1740)
2026-09-15 01:15:31 +02:00
5f5d774d76 feat(crypto): X.509 chain-link verification (rv2 9 phase E core)
- defensive ASN.1/DER reader: every length/bound checked; malformation
  is rejection, never over-read (truncated input KAT-gated)
- x509_parse: tbsCertificate span, sig-alg OID, signature,
  SubjectPublicKeyInfo (RSA n/e or EC P-256 x/y), validity dates
- wo_x509_verify_one: one chain link's signature, dispatching to
  phase-D RSA-PKCS1/PSS + ECDSA-P256 by the issuer key type
- wo_x509_parse_spki + wo_x509_check_validity (caller supplies time)
- KAT against real python-generated chains (test/gen_x509.py):
  RSA CA+leaf (SHA256withRSA), EC P-256 CA+leaf (ecdsa-with-SHA256);
  leaf-vs-CA, self-signed CA, wrong-issuer/tampered/truncated reject,
  validity window, SPKI extraction. test_crypto 84 pass, ASan/UBSan clean
- deferred to phase F: SAN/hostname match + multi-cert chain walk to a
  system CA bundle (both need the target host / trust store, known at
  handshake time)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
(cherry picked from commit 4ec1c75f889df3612e31b9a1a77c4c927fb546c1)
2026-09-15 01:15:31 +02:00