{"record":{"id":"dc28e3601771f22d","repo":"golang/go","slug":"mldsa-unavailable-in-fips-140-3-go-cryptographic","errorCode":null,"errorMessage":"mldsa: unavailable in FIPS 140-3 Go Cryptographic Module v1.0.0","messagePattern":"mldsa: unavailable in FIPS 140-3 Go Cryptographic Module v1\\.0\\.0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/mldsa/mldsa_fips140v1.0.go","lineNumber":20,"sourceCode":"// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n//go:build fips140v1.0\n\npackage mldsa\n\nimport (\n\t\"crypto\"\n\t\"errors\"\n\t\"io\"\n)\n\n// This file provides stub implementations of the ML-DSA API for building\n// against the FIPS 140-3 Go Cryptographic Module v1.0.0, which does not include\n// ML-DSA. Top-level functions return an error, and methods are unreachable\n// since there is no way to construct a valid PublicKey or PrivateKey.\n\nvar errUnavailable = errors.New(\"mldsa: unavailable in FIPS 140-3 Go Cryptographic Module v1.0.0\")\n\n// PrivateKey is an in-memory ML-DSA private key. It implements [crypto.Signer]\n// and the informal extended [crypto.PrivateKey] interface.\n//\n// A PrivateKey is safe for concurrent use.\ntype PrivateKey struct{}\n\n// GenerateKey generates a new random ML-DSA private key.\nfunc GenerateKey(params Parameters) (*PrivateKey, error) {\n\treturn nil, errUnavailable\n}\n\n// NewPrivateKey decodes an ML-DSA private key from the given seed.\n//\n// The seed must be exactly [PrivateKeySize] bytes long.\nfunc NewPrivateKey(params Parameters, seed []byte) (*PrivateKey, error) {\n\treturn nil, errUnavailable\n}","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/mldsa/mldsa_fips140v1.0.go#L2-L38","documentation":"Returned by every top-level ML-DSA function in the stub file mldsa_fips140v1.0.go, which is compiled when building against the FIPS 140-3 Go Cryptographic Module v1.0.0. ML-DSA (NIST FIPS 204 post-quantum lattice signature) was not included in FIPS module v1.0, so the entire API is stubbed to return errUnavailable and methods are unreachable because PrivateKey/PublicKey are empty structs that cannot be constructed.","triggerScenarios":"Calling mldsa.GenerateKey (or any other top-level ML-DSA function: Sign, Verify, etc.) in a binary built against FIPS module v1.0 — i.e. the GOFIPS env var points at the v1.0 module, or the gofips build tag selects v1.0. There is no code path that returns a valid key, so all callers fail.","commonSituations":"Post-quantum pilot code deployed into a FIPS-only environment pinned to module v1.0; CI builds with the v1.0 module tag while developers expected the v1.26 API; library code that conditionally uses ML-DSA but the build resolved to the v1.0 stub file.","solutions":["Build/run against FIPS 140-3 Go Cryptographic Module v1.26.0 or later, which includes ML-DSA (the mldsa_fips140v1.26.go file with real GenerateKey44/65/87 is selected).","If you cannot upgrade the module, remove or feature-gate the ML-DSA code path so it is not called in v1.0 builds.","Detect errUnavailable at startup and fall back to a classical signature (Ed25519/ECDSA) when ML-DSA is unavailable, if your protocol allows it.","Pin the FIPS module version explicitly via GOFIPS / build tags and document the dependency in release notes."],"exampleFix":"// before\npriv, err := mldsa.GenerateKey(mldsa.MLDSA65()) // -> errUnavailable under v1.0\n// after\npriv, err := mldsa.GenerateKey(mldsa.MLDSA65())\nif errors.Is(err, errUnavailable) { priv, err = ed25519.GenerateKey(rand.Reader) }","handlingStrategy":"try-catch","validationCode":"// Detect at startup whether ML-DSA is available in this build:\nif _, err := mldsa.GenerateKey(mldsa.MLDSA44()); errors.Is(err, errUnavailable) {\n    log.Println(\"ML-DSA unavailable; falling back to classical signatures\")\n}","typeGuard":null,"tryCatchPattern":"priv, err := mldsa.GenerateKey(mldsa.MLDSA65())\nif errors.Is(err, errUnavailable) {\n    // FIPS module v1.0 in use; fall back to a classical signature\n    priv, err = ed25519.GenerateKey(rand.Reader)\n}\nif err != nil {\n    return err\n}","preventionTips":["Pin the FIPS module version explicitly (>= v1.26 for ML-DSA) and document it in release notes.","Detect errUnavailable at startup and switch to a classical signature if the protocol allows.","Feature-gate ML-DSA code paths so they are not compiled into v1.0 builds."],"tags":["crypto","mldsa","post-quantum","fips","versioning","go-stdlib"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}