{"record":{"id":"ccf6aa689bef1ffb","repo":"slackhq/nebula","slug":"use-of-curve25519-is-not-allowed-in-fips-140-only-ccf6aa","errorCode":null,"errorMessage":"use of Curve25519 is not allowed in FIPS 140-only mode","messagePattern":"use of Curve25519 is not allowed in FIPS 140-only mode","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/nebula-cert/keygen.go","lineNumber":67,"sourceCode":"\t}\n\tif err = mustFlagString(\"out-pub\", cf.outPubPath); err != nil {\n\t\treturn err\n\t}\n\n\tvar pub, rawPriv []byte\n\tvar curve cert.Curve\n\tif isP11 {\n\t\tswitch *cf.curve {\n\t\tcase \"P256\":\n\t\t\tcurve = cert.Curve_P256\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"invalid curve for PKCS#11: %s\", *cf.curve)\n\t\t}\n\t} else {\n\t\tswitch *cf.curve {\n\t\tcase \"25519\", \"X25519\", \"Curve25519\", \"CURVE25519\":\n\t\t\tif fips140.Enforced() {\n\t\t\t\treturn errors.New(\"use of Curve25519 is not allowed in FIPS 140-only mode\")\n\t\t\t}\n\t\t\tpub, rawPriv = x25519Keypair()\n\t\t\tcurve = cert.Curve_CURVE25519\n\t\tcase \"P256\":\n\t\t\tpub, rawPriv = p256Keypair()\n\t\t\tcurve = cert.Curve_P256\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"invalid curve: %s\", *cf.curve)\n\t\t}\n\t}\n\n\tvar claims ioClaims\n\tif err := reserveOutputs(&claims,\n\t\t\"out-key\", *cf.outKeyPath,\n\t\t\"out-pub\", *cf.outPubPath,\n\t); err != nil {\n\t\treturn err\n\t}","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cmd/nebula-cert/keygen.go#L49-L85","documentation":"In cmd/nebula-cert/keygen.go (keygen), selecting any Curve25519 alias while fips140.Enforced() is true makes the command fail immediately instead of calling x25519Keypair(). FIPS 140-only mode forbids non-validated primitives, so X25519 keypair generation is rejected.","triggerScenarios":"Running 'nebula-cert keygen -curve 25519/X25519/Curve25519/CURVE25519' on a FIPS 140-enforced build/environment (keygen.go:67 check).","commonSituations":"Automation scripts generating node keys on FIPS-hardened hosts; teams standardizing on 25519 hitting FIPS policy on new infrastructure.","solutions":["Regenerate keys with an approved curve: nebula-cert keygen -curve P256.","Disable FIPS 140-only mode if policy allows (unset fips140=only GODEBUG / non-FIPS binary).","Use PKCS#11 hardware tokens that provide a FIPS-validated key generation path.","Align deployment configs so the declared curve matches FIPS requirements."],"exampleFix":"// before\n$ nebula-cert keygen -curve 25519 -out-key node.key -out-pub node.pub\n\n// after\n$ nebula-cert keygen -curve P256 -out-key node.key -out-pub node.pub","handlingStrategy":"validation","validationCode":"if fips140.Enforced() && strings.EqualFold(strings.TrimPrefix(strings.ToLower(cf.curve), \"curve\"), \"25519\") {\n    return errors.New(\"keygen: select -curve P256 under FIPS 140-only mode\")\n}","typeGuard":"func isCurve25519Alias(c string) bool {\n    switch c {\n    case \"25519\", \"X25519\", \"Curve25519\", \"CURVE25519\":\n        return true\n    }\n    return false\n}","tryCatchPattern":"out, err := exec.Command(\"nebula-cert\", \"keygen\", \"-curve\", curve).CombinedOutput()\nif err != nil && strings.Contains(string(out), \"FIPS 140-only\") {\n    out, err = exec.Command(\"nebula-cert\", \"keygen\", \"-curve\", \"P256\").CombinedOutput()\n}","preventionTips":["Choose the curve from environment policy, not hardcoded defaults.","Test keygen scripts on a FIPS-enforced image before rollout.","Prefer PKCS#11 FIPS-validated modules for key material in regulated environments.","Reject 25519 aliases early in automation scripts when fips140=only is set."],"tags":["fips","crypto","curve25519","keygen"],"backgroundTag":"fips-only-algorithm-rejected","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}