You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 2ad4ed8
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: docs/regulated/control-mapping.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -117,7 +117,7 @@ register does not claim is never Trinity's.
117
117
|`SC-12`| Keys pass through one behaviour, so a KMS or HSM adapter is a module and a configuration line; none ships in this tree |`lib/trinity/keys.ex`|`test/trinity/keys/signer_seam_test.exs` "a sealed key still signs, which is the point of sealing it" | shared | A KMS or HSM adapter, where one is required | CRM "A KMS or HSM adapter" |
118
118
|`SC-12`| Custody of the signing key is not addressed: a key in a file shows the records were not altered by anything without read access to it, and nothing about who held it |`docs/10-assurance-case.md`| none | the deployment's | Custody of the signing key | CRM "Custody of the signing key" |
119
119
|`SC-13`| Signing picks its algorithm by the runtime's mode: Ed25519 by default, ECDSA P-384 with SHA-384 in FIPS mode, where Ed25519 reports itself unavailable. The gate and the suite run in FIPS mode on every push |`lib/trinity/receipts/signer.ex`, `docs/fips-leg.md`, `docs/regulated/crypto-inventory.md`|`test/trinity/receipts/signer_test.exs` "outside FIPS mode the default is Ed25519; in FIPS mode (the fips leg) it is P-384"; `test/fips/receipts_test.exs` "the mode is on, Ed25519 reports unavailable, P-384 is selected and the boot receipt names it" | shared | A validated cryptographic module on the host, established from its certificate and the running binary | Register "FIPS 140-3 validated cryptography in FIPS mode": :unknown; Register "FIPS 140-2 certificates on the Historical list from 2026-09-22": real-world dependency |
120
-
| `SC-13` | ML-DSA-87 is offered for receipts only where a known-answer check passes through `:crypto` in the mode the node is in: NIST's ACVP keyGen case (the published secret key yields the published public key), Wycheproof's verify cases (a valid signature, a bit-flipped one and one with malformed hints), then a fresh key. Not where the algorithm is merely listed: OTP lists no ML-DSA type in FIPS mode whatever the provider can do. A regulated node configured for ML-DSA-87 that fails the check refuses to boot naming the step; the boot receipt records the check's answer | `lib/trinity/crypto/preflight.ex`, `priv/kat/`, `lib/trinity/receipts/signer/mldsa87.ex`, `lib/trinity/receipts/key_custody.ex` | `Trinity.Crypto.Preflight.mldsa87/1`; `test/trinity/crypto/preflight_test.exs` "a provider that derives the wrong public key fails at :keygen_kat"; `test/trinity/crypto/preflight_test.exs` "a verifier that accepts Wycheproof's bit-flipped signature fails at :sigver_kat, naming the case"; `test/trinity/crypto/preflight_test.exs` "the ML-DSA-87 signer is available exactly when the preflight passes (F-137-1)"; `test/trinity/toolchain_node_test.exs` "a failing preflight refuses the boot, naming the step" | Trinity's | none | none |
120
+
| `SC-13` | Every node checks at boot that `:crypto` verifies ML-DSA-87 rightly, by doing it: nine published cases (NIST ACVP sigGen and sigVer, five Wycheproof cases, and flips of a valid signature), each of which must give exactly its expected answer, so a verifier that says yes to everything is refused. A case answered wrongly refuses the boot in every profile; on the `nss` profile a runtime that cannot run the check refuses too, and so does FIPS mode off, no FIPS provider, or a provider whose build string is not the one CMVP #5523's security policy names. Where receipts sign with ML-DSA-87 the signer check adds ACVP's keyGen case and a signature made with a published test key, and generates no key at boot. Not where the algorithm is merely listed: OTP lists no ML-DSA type in FIPS mode whatever the provider can do. The check is defence in depth, never FIPS evidence; the boot receipt records its answer | `lib/trinity/crypto/preflight.ex`, `lib/trinity/crypto/boot_check.ex`, `priv/kat/`, `lib/trinity/receipts/signer/mldsa87.ex`, `lib/trinity/receipts/key_custody.ex` | `Trinity.Crypto.Preflight.verifier/1`; `Trinity.Crypto.Preflight.signer/1`; `Trinity.Crypto.BootCheck.decide/3`; `test/trinity/crypto/preflight_test.exs` "a verifier that says true to everything fails at the first negative"; `test/trinity/crypto/preflight_test.exs` "a provider that derives the wrong public key fails at :keygen_kat"; `test/trinity/crypto/preflight_test.exs` "the ML-DSA-87 signer is available exactly when the signer check passes (F-137-1)"; `test/trinity/crypto/boot_check_test.exs` "another provider's build string refuses, naming both"; `test/trinity/crypto/boot_check_node_test.exs` "a node whose verifier answers a case wrongly refuses, naming the case, in every profile"; `test/trinity/crypto/boot_check_node_test.exs` "an nss node refuses, naming the mode or the provider's build string"; `test/trinity/toolchain_node_test.exs` "a failing preflight refuses the boot, naming the step" | Trinity's | none | none |
121
121
| `SC-13` | Signed statements have one byte form: deterministic CBOR inside COSE_Sign1 with ML-DSA-87, or on the `commercial` profile only Ed25519 (slice 139) or, for a node in FIPS mode, ECDSA P-384 as ESP384 with its 96-byte signature (slice 140). Receipts and checkpoints are written in it since slice 140. The decoder refuses any input that is not exactly the deterministic encoding of an allowed value, naming the first defect; the header admits only `alg` -50 (and -19 or -51 at `commercial`), the key's RFC 9679 thumbprint as `kid`, and `typ`; the key's registration names its algorithm and a header naming another is refused; one `typ` per kind, and a body under another kind's is refused; a single-signer carrier refuses a `typ` that needs two signers and a body without an issuer; a verifier that cannot run the header's algorithm answers no trust, never a pass, and so does the receipt verifier for a row whose algorithm the runtime refuses. A census classifies every hashing and signing call in the tree and names the sites that still re-encode data from elsewhere before hashing it | `lib/trinity/n6/`, `lib/trinity/receipts/v4.ex`, `test/fixtures/n6/`, `scripts/n6_vectors.exs` | `test/trinity/n6/cbor_test.exs` "every negative vector is refused with its code"; `test/trinity/n6/cose_test.exs` "every negative header is refused with its code, at either entry point"; `test/trinity/n6/carrier_test.exs` "AC5: every sample gives its expected outcome under its context"; `test/trinity/n6/cose_test.exs` "kid for ACVP's published key is SHA-384 over exactly the RFC 9679 input"; `test/trinity/n6/cose_signing_test.exs` "one flipped byte in the protected header, the payload or the signature is invalid"; `test/trinity/n6/esp384_test.exs` "DER, or 95 or 97 bytes, is signature_encoding"; `test/trinity/n6/esp384_test.exs` "a compressed point, a P-256 key and a point off the curve are key_invalid"; `test/fips/receipts_test.exs` "no effect is denied for want of a signer: an effect runs, its receipts are P-384 and verify"; `test/trinity/n6/census_test.exs` "every hashing and signing call in lib/ is in the census, with its count and a class" | Trinity's | none | none |
122
122
|`SC-23`| A request whose `Host` is not the loopback or the configured host is refused before routing, and the websocket origin check is an explicit list in every environment; under `TRINITY_PROFILE=regulated` an origin check of `false` or `:conn` refuses to boot, because a DNS rebinding page controls both |`lib/trinity_web/plugs/host_allow_list.ex`, `lib/trinity/profile.ex`|`Trinity.Profile.check_origin/2`; `test/trinity_web/auth/host_and_origin_test.exs` "a foreign Host is 403 before routing, wherever it points"; `test/trinity_web/auth/host_and_origin_test.exs` "check_origin is an explicit list in dev, test and prod" | shared | Setting `PHX_HOST` to the host users reach | CRM "Refusing a request whose Host is not this deployment's" |
123
123
|`SC-23`| The state an MCP client carries between rounds is sealed with AES-256-GCM: a replay, one tampered byte, an expired envelope and a state bound to other arguments are refused |`lib/trinity/mcp/server/envelope.ex`|`test/trinity/mcp/server_mrtr_test.exs` "a replay inside the partition, one tampered byte, an expired envelope and a state bound to other arguments are refused; a missing state is a first call" | Trinity's | none | Register "Envelope MAC in FIPS mode is an approved algorithm": :unknown|
Copy file name to clipboardExpand all lines: docs/regulated/crypto-inventory.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,7 +15,8 @@ to that provider, on that host, not to this software. **Anything not established
15
15
|---|---|---|---|---|
16
16
| Receipt signing, default |`lib/trinity/receipts/signer/ed25519.ex`|`:crypto.sign(:eddsa, :none, …, :ed25519)`, line 21 |**UNKNOWN**| Ed25519, RFC 8032. `available?/0` line 14 returns false when `:crypto.info_fips() == :enabled`, so it is not selected in FIPS mode |
17
17
| Receipt signing, FIPS mode |`lib/trinity/receipts/signer/p384.ex`|`:crypto.sign(:ecdsa, :sha384, …, :secp384r1)`, line 25 |**UNKNOWN**| ECDSA P-384 with SHA-384. Selected when the mode is enabled. Since slice 140 its DER signature is carried as ESP384's 96-byte `r \|\| s` (`lib/trinity/n6/ec2.ex`) |
18
-
| Receipt signing, opt-in |`lib/trinity/receipts/signer/mldsa87.ex`|`:crypto` ML-DSA-87, FIPS 204 |**UNKNOWN**| Never the default. `available?/0` asks the runtime by generating, signing and verifying a known answer (`Trinity.Crypto.Preflight`, slice 137); it was a `:crypto.supports/1` lookup before, which never holds in FIPS mode |
18
+
| Receipt signing, opt-in |`lib/trinity/receipts/signer/mldsa87.ex`|`:crypto` ML-DSA-87, FIPS 204 |**UNKNOWN**| Never the default. `available?/0` asks the runtime by its signer check (`Trinity.Crypto.Preflight.signer/1`, slice 143): published verify cases, ACVP's keyGen case and a signature made with a published test key, with no key generated; it was slice 137's six steps before, and a `:crypto.supports/1` lookup before those, which never holds in FIPS mode |
19
+
| ML-DSA-87 verifier check at boot (slice 143) |`lib/trinity/crypto/preflight.ex`, `lib/trinity/crypto/boot_check.ex`|`:crypto.verify(:mldsa87, :none, …)` over nine published cases | Not applicable | Defence in depth, never FIPS evidence. On `nss` the boot also asserts the FIPS provider's build string (`fips_provider_buildinfo`) against CMVP #5523's security policy |
19
20
| Receipt hashing, v2 and v3 rows |`lib/trinity/receipts/envelope.ex:36`|`:crypto.hash(:sha256, …)`|**UNKNOWN**| Over the DSSE pre-authentication encoding, not the bare payload. Rows written before slice 140; still verified |
20
21
| Receipt identity and link, v4 rows (slice 140) |`lib/trinity/receipts/v4.ex`|`:crypto.hash(:sha384, …)`|**UNKNOWN**|`statement_id` over the kind's `typ` and the N6 body; the link to a v3 predecessor over its PAE bytes |
21
22
| Merkle tree over a chain |`lib/trinity/receipts/merkle.ex`|`:crypto.hash(:sha256, …)`|**UNKNOWN**| RFC 6962 hashing: distinct leaf and node prefixes, odd nodes promoted not duplicated |
0 commit comments