{"record":{"id":"e03469cfb1e6b451","repo":"golang/go","slug":"crypto-rsa-invalid-pss-salt-length","errorCode":null,"errorMessage":"crypto/rsa: invalid PSS salt length","messagePattern":"crypto/rsa: invalid PSS salt length","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/internal/boring/rsa.go","lineNumber":255,"sourceCode":"// These dumb wrappers work around the fact that cgo functions cannot be used as values directly.\n\nfunc decryptInit(ctx *C.GO_EVP_PKEY_CTX) C.int {\n\treturn C._goboringcrypto_EVP_PKEY_decrypt_init(ctx)\n}\n\nfunc decrypt(ctx *C.GO_EVP_PKEY_CTX, out *C.uint8_t, outLen *C.size_t, in *C.uint8_t, inLen C.size_t) C.int {\n\treturn C._goboringcrypto_EVP_PKEY_decrypt(ctx, out, outLen, in, inLen)\n}\n\nfunc encryptInit(ctx *C.GO_EVP_PKEY_CTX) C.int {\n\treturn C._goboringcrypto_EVP_PKEY_encrypt_init(ctx)\n}\n\nfunc encrypt(ctx *C.GO_EVP_PKEY_CTX, out *C.uint8_t, outLen *C.size_t, in *C.uint8_t, inLen C.size_t) C.int {\n\treturn C._goboringcrypto_EVP_PKEY_encrypt(ctx, out, outLen, in, inLen)\n}\n\nvar invalidSaltLenErr = errors.New(\"crypto/rsa: invalid PSS salt length\")\n\nfunc SignRSAPSS(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte, saltLen int) ([]byte, error) {\n\tmd := cryptoHashToMD(h)\n\tif md == nil {\n\t\treturn nil, errors.New(\"crypto/rsa: unsupported hash function\")\n\t}\n\n\t// A salt length of -2 is valid in BoringSSL, but not in crypto/rsa, so reject\n\t// it, and lengths < -2, before we convert to the BoringSSL sentinel values.\n\tif saltLen <= -2 {\n\t\treturn nil, invalidSaltLenErr\n\t}\n\n\t// BoringSSL uses sentinel salt length values like we do, but the values don't\n\t// fully match what we use. We both use -1 for salt length equal to hash length,\n\t// but BoringSSL uses -2 to mean maximal size where we use 0. In the latter\n\t// case convert to the BoringSSL version.\n\tif saltLen == 0 {","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/internal/boring/rsa.go#L237-L273","documentation":"invalidSaltLenErr is returned by SignRSAPSS (and VerifyRSAPSS) when saltLen <= -2. BoringSSL treats -2 as 'maximal salt length', but Go's crypto/rsa uses 0 for that and reserves -1 for hash-length; values <= -2 are not part of crypto/rsa's contract, so they are rejected before conversion to BoringSSL sentinels.","triggerScenarios":"Calling SignRSAPSS/VerifyRSAPSS with saltLen of -2 or lower. This typically arises when callers pass BoringSSL-style sentinels into the Go API, or compute saltLen incorrectly (e.g. negative overflow).","commonSituations":"Porting code that uses BoringSSL/OpenSSL sentinel salt lengths directly; arithmetic that produces unexpectedly negative saltLen; interop with libraries that emit -2 for maximal salt.","solutions":["Use crypto/rsa sentinels: rsa.PSSSaltLengthAuto (-1-ish semantics) or rsa.PSSSaltLengthEqualsHash, or a non-negative explicit salt length.","For maximal salt length pass 0 (Go's sentinel), not -2.","Validate saltLen is >= -1 before calling Sign/Verify PSS."],"exampleFix":"// before\nsig, err := boring.SignRSAPSS(priv, crypto.SHA256, digest, -2) // invalid\n\n// after\nsig, err := boring.SignRSAPSS(priv, crypto.SHA256, digest, rsa.PSSSaltLengthEqualsHash)","handlingStrategy":"validation","validationCode":"func validatePSSSaltLen(saltLen int) error {\n    if saltLen <= -2 {\n        return errors.New(\"crypto/rsa: invalid PSS salt length\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use crypto/rsa sentinels: PSSSaltLengthAuto, PSSSaltLengthEqualsHash, or a non-negative length.","Pass 0 for maximal salt (Go's sentinel), never -2.","Validate saltLen >= -1 before sign/verify."],"tags":["crypto","rsa","pss","boringcrypto","fips","validation"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}