Repository navigation
feat(s137): the toolchain floor refused at boot, and ML-DSA-87 known-answer tests through :crypto - #132
Merged
Conversation
…ated ML-DSA-87 refusal does not name its step, a bare private key crashes the signer Signed-off-by: Ayla Croft <aylacroft@proton.me>
…and ML-DSA-87 known-answer tests through :crypto) Signed-off-by: Ayla Croft <aylacroft@proton.me>
…state, so the gate in FIPS mode inherits no keys or rows Signed-off-by: Ayla Croft <aylacroft@proton.me>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Slice 137. A node refuses to boot on an Erlang runtime below the release that fixed CVE-2026-55737 for its line, or on Elixir outside 1.20.x. Whether ML-DSA-87 is usable is answered by known-answer tests through
:crypto, not by a listing that is always empty in FIPS mode.What it does
Trinity.Toolchainreads the three rows of erlang/otp'sotp_versions.tablefor the fixing releases (OTP-27.3.4.15, OTP-28.5.0.4, OTP-29.0.4), checked in verbatim atpriv/otp_floor.tablewith their source commit and SHA-256. It compares erts and every loaded application the row names, because the same releases fix CVEs in ssl, public_key, crypto, ssh and stdlib. Majors above 29 pass, below 27 refuse. Elixir must match~> 1.20.0. The comparison uses erts and the loaded applications, notOTP_VERSION, because an assembled release carries noOTP_VERSIONfile.Trinity.Crypto.Preflight.mldsa87/1runs six named steps: NIST ACVP's keyGen case (the published secret key regenerates the published public key), Wycheproof's valid, bit-flipped and malformed-hints signatures, then a fresh key's generate, sign, verify and one-bit refusal. Vectors are atpriv/kat/, each with its source commit and file SHA-256. OTP'sbuild_pkey_type_list/3(lib/crypto/c_src/pkey.c) lists no ML-DSA or SLH-DSA type whenever FIPS mode is on, atOTP-28.5.0.7,OTP-29.0.6andmaster, whatever the provider can do.Signer.MLDSA87.available?/0was that listing, so on a FIPS node whose provider signs ML-DSA-87 a regulated boot would have refused a node that can sign. It now answers from the preflight, andKeyCustody.select/0returns the preflight's reason, so a refused regulated boot names the step.:defaultstays fail-open over the signer, held by a node test.encode_private/1matched only the tagged form, so the receipts supervisor crashed at boot. A bare key is now stored tagged by its size; ML-DSA-87 has exactly two private-key sizes, so this is unambiguous.erts,elixirandmldsa87_preflightin the signed subject, and the receipts page shows them.Trinity.Toolchain's checks and the preflight, so a check no row cites fails.Evidence
lib/: a boot below the floor printedBOOT_OK, a regulated ML-DSA-87 refusal namedno_approved_signerinstead of the step, and a bare private key raisedFunctionClauseError. All green with the change.otp_below_floornaming16.4.0.3and16.4.0.4. CI repeats it in a newgatestep.receipt_v3_mldsa87and verifies offline. A planted garbage signature turns that case red with{:signature_invalid, 1}.gaterunners link OpenSSL 3.0. Thefipsjob runs the three ML-DSA-87 test files whole with the mode off, andTRINITY_REQUIRE_MLDSA87_RUNTIME=1fails that step if the runtime cannot sign, rather than excluding the tests.Declared gap
In FIPS mode, on the image's Red Hat provider, ML-DSA-87 does not sign, so a regulated FIPS node cannot use ML-DSA-87 receipts yet. A provider validated with ML-DSA-87 (CMVP #5523) would change that. Getting one is a procurement item, outside this change.