{"record":{"id":"d51cb2e1eec702f5","repo":"golang/go","slug":"crypto-rsa-use-of-pss-salt-longer-than-the-hash-i","errorCode":null,"errorMessage":"crypto/rsa: use of PSS salt longer than the hash is not allowed in FIPS 140-only mode","messagePattern":"crypto/rsa: use of PSS salt longer than the hash is not allowed in FIPS 140-only mode","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/rsa/fips.go","lineNumber":107,"sourceCode":"\n\tif err := checkFIPS140OnlyPrivateKey(priv); err != nil {\n\t\treturn nil, err\n\t}\n\tif fips140only.Enforced() && !fips140only.ApprovedHash(h) {\n\t\treturn nil, errors.New(\"crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode\")\n\t}\n\tif fips140only.Enforced() && !fips140only.ApprovedRandomReader(random) {\n\t\treturn nil, errors.New(\"crypto/rsa: only crypto/rand.Reader is allowed in FIPS 140-only mode\")\n\t}\n\n\tk, err := fipsPrivateKey(priv)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tsaltLength := opts.saltLength()\n\tif fips140only.Enforced() && saltLength > h.Size() {\n\t\treturn nil, errors.New(\"crypto/rsa: use of PSS salt longer than the hash is not allowed in FIPS 140-only mode\")\n\t}\n\tswitch saltLength {\n\tcase PSSSaltLengthAuto:\n\t\tsaltLength, err = rsa.PSSMaxSaltLength(k.PublicKey(), h)\n\t\tif err != nil {\n\t\t\treturn nil, fipsError(err)\n\t\t}\n\tcase PSSSaltLengthEqualsHash:\n\t\tsaltLength = h.Size()\n\tdefault:\n\t\t// If we get here saltLength is either > 0 or < -1, in the\n\t\t// latter case we fail out.\n\t\tif saltLength <= 0 {\n\t\t\treturn nil, errors.New(\"crypto/rsa: invalid PSS salt length\")\n\t\t}\n\t}\n\n\treturn fipsError2(rsa.SignPSS(random, k, h, digest, saltLength))","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/rsa/fips.go#L89-L125","documentation":"Thrown by SignPSS in FIPS 140-only mode when opts.SaltLength (after resolving sentinels) is strictly greater than the hash function's output size (h.Size()). FIPS 186-5 caps the PSS salt at the hash output length, so an explicit saltLength larger than h.Size() is rejected before signing proceeds. This guard only fires when fips140only.Enforced() returns true (the binary was built/run in FIPS-only mode).","triggerScenarios":"Calling rsa.SignPSS (or PrivateKey.Sign with *PSSOptions) where opts.SaltLength is a positive int larger than hash.Size() — e.g. SaltLength: 64 with crypto.SHA256 (Size()==32) — while GOFIPS-only enforcement is active. The sentinel PSSSaltLengthEqualsHash and PSSSaltLengthAuto do NOT trip this (they are resolved before the comparison).","commonSituations":"Migrating an app from a non-FIPS Go build to a FIPS-only toolchain where the original code set an oversized explicit salt. Porting PSS parameters from another library (OpenSSL default salt = key size, often > hash size). Hardcoding a salt length chosen for maximum entropy without considering the hash.","solutions":["Set PSSOptions.SaltLength to rsa.PSSSaltLengthEqualsHash (-1) so the salt always equals h.Size(), which is always FIPS-legal.","Set PSSOptions.SaltLength to rsa.PSSSaltLengthAuto (0); in FIPS mode this is capped at the hash size automatically.","If you must set an explicit byte count, clamp it: saltLength = min(saltLength, hash.Size()).","If the oversized salt is an unavoidable protocol requirement, you cannot use FIPS-only mode — remove the enforcement setting for this operation."],"exampleFix":"// before\nopts := &rsa.PSSOptions{SaltLength: 64, Hash: crypto.SHA256}\nsig, err := rsa.SignPSS(rand.Reader, priv, crypto.SHA256, digest, opts)\n\n// after\nopts := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: crypto.SHA256}\nsig, err := rsa.SignPSS(rand.Reader, priv, crypto.SHA256, digest, opts)","handlingStrategy":"validation","validationCode":"// Before calling SignPSS, ensure the salt length is FIPS-legal.\nfunc safeSaltLength(hash crypto.Hash, opts *rsa.PSSOptions) int {\n    sl := rsa.PSSSaltLengthAuto\n    if opts != nil {\n        sl = opts.SaltLength\n    }\n    switch sl {\n    case rsa.PSSSaltLengthAuto, rsa.PSSSaltLengthEqualsHash:\n        return sl\n    default:\n        if sl > hash.Size() {\n            return rsa.PSSSaltLengthEqualsHash // clamp to hash size\n        }\n        return sl\n    }\n}\nopts.SaltLength = safeSaltLength(crypto.SHA256, opts)","typeGuard":"func isFIPSCompliantSaltLength(hash crypto.Hash, sl int) bool {\n    return sl == rsa.PSSSaltLengthAuto ||\n        sl == rsa.PSSSaltLengthEqualsHash ||\n        (sl > 0 && sl <= hash.Size())\n}","tryCatchPattern":null,"preventionTips":["Default PSSOptions.SaltLength to rsa.PSSSaltLengthEqualsHash in all signing code.","If FIPS-only mode is a deployment target, run the crypto/rsa test suite under GOFIPS-only to catch salt-length issues early.","Document the hash:salt relationship in the signing config so operators understand the cap."],"tags":["crypto","rsa","fips","pss","signing"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}