Commit Graph
3 Commits
Author SHA1 Message Date
zeekay 5b400e656a nras: delete SkipSignature kill-switch (Red audit F4)
VerifyOptions.SkipSignature was a test-only boolean that bypassed
JWS verification entirely. Removed unconditionally. Production has
always required verification; the only caller was a test that
exercised the skip path. JWS verification is now non-optional.
2025-12-28 17:46:45 -08:00
zeekay 4d1c8f6d3d nras/jws: enforce alg ↔ key-type binding (Red audit F3)
verifyJWS dispatched on the JWS header alg, then handed off to the
shared verifySignature helper which dispatched on the public-key type.
A token forged with header alg=EdDSA against a trust root that holds
an *rsa.PublicKey for the same kid would: (1) take the EdDSA branch
in verifyJWS, (2) call verifySignature(rsaPub, signedInput, sig),
(3) hit the *rsa.PublicKey case and run RSA-PSS over attacker-chosen
signedInput, (4) accept whatever sig forged. Classic CVE-2015-9235
algorithm-substitution shape.

Fix: the JWS path no longer routes through verifySignature. Each alg
arm in verifyJWS asserts the trust-root key type before any
verification primitive runs; for ECDSA the curve is also bound to
the alg (ES256→P-256, ES384→P-384). alg=none (any case) and unknown
algs are refused with explicit sentinels.

The companion verifySignature in rim.go is intentionally retained
for the RIM detached-signature path: RIM has no alg envelope, so
key-type dispatch is the only correct choice there. Splitting the
two paths is the only correct factoring; merging them re-introduces
this attack.

Sentinels:
  ErrAlgKeyTypeMismatch — alg announced does not match key type
  ErrAlgNoneRefused     — alg=none rejected unconditionally
  ErrUnknownAlg         — alg not recognized

Algs supported: EdDSA, ES256, ES384, PS256, PS384.

Tests (8/8 PASS, -race clean):
  TestVerifyJWS_EdDSA_Valid
  TestVerifyJWS_ES256_Valid
  TestVerifyJWS_PS256_Valid
  TestVerifyJWS_EdDSA_AgainstRSAPub_Rejected   (the substitution attack)
  TestVerifyJWS_ES256_AgainstEd25519Pub_Rejected
  TestVerifyJWS_ES256_AgainstP384Pub_Rejected  (curve mismatch)
  TestVerifyJWS_AlgNone_Refused
  TestVerifyJWS_UnknownAlg_Refused

Pre-existing nvidia package tests (RIM ed25519/ECDSA/RSA-PSS, NRAS
ES256 happy path, etc.) continue to pass.

LOC delta: nras_client.go +107/-65, nras_jws_test.go +178/-0.
2025-12-28 17:40:08 -08:00
zeekay 1996f1adc4 v0.61+v0.62: scheduler trust gate + NVIDIA attestation primitives
v0.61 — wire the scheduler workload-policy gate into the MPC SignGate.
SignGate gains optional Scheduler + Worker fields; AuthorizeSign now
runs scheduler.Eligible(worker, ci.PolicyID) BEFORE the policy
verifier and short-circuits on insufficient trust posture. Existing
callers that pass nil Scheduler are unaffected.

  pkg/scheduler/policy_gate.go     — TrustMode/IOLevel enums,
                                     WorkloadPolicy.Eligible(Worker)
  pkg/scheduler/service_drain.go   — AuthorizeDrain + AuthorizeSession
  pkg/mpc/sign_orchestrator.go     — Scheduler/Worker fields,
                                     WithScheduler(...), two-stage gate

v0.62 — NVIDIA Confidential-Compute attestation primitives. Clean-room
parsers + verifiers against the publicly documented nvTrust schema
(Apache-2 derived); no NVIDIA proprietary code vendored.

  pkg/attestation/nvidia/gpu_report.go   — GPU evidence-report parser
  pkg/attestation/nvidia/nras_client.go  — NRAS HTTP client + JWS verify
  pkg/attestation/nvidia/rim.go          — RIM signature + value match
  pkg/attestation/nvidia/composite.go    — VerifiedBundle (CPU+GPU bind)

Tests (57 passing, -race clean):
  pkg/scheduler                        — 11 (truth-table, drain,
                                          session, orchestrator
                                          integration)
  pkg/attestation/nvidia               — 46 (parser, RIM Ed25519/ECDSA/
                                          RSA-PSS, NRAS happy/error/
                                          signature paths, ECDSA JOSE)
  pkg/attestation/nvidia (hwattest)    — 3, env-skipped without real GPU

Sibling v0.60 reconciliation: pkg/registry + pkg/attestation already
land WorkerCapability + CompositeAttestation envelope using lattice
trust types. nvidia.VerifiedBundle is renamed (was Composite-) to
avoid collision with pkg/attestation.CompositeAttestation; the
canonical envelope wraps the verified blobs this package emits.

Residual: lattice/v7/types is not yet published, so pkg/registry +
pkg/attestation cannot compile against luxfi/[email protected]; the
sibling v0.60 work tracks that. pkg/policy still has a pre-existing
unresolved import of luxfi/fhe/threshold (should be /pkg/threshold);
sign_orchestrator_scheduler_test.go is ready to run as soon as that
upstream issue is fixed by its owner.
2025-12-28 16:53:46 -08:00