{"record":{"id":"f1773c987a131155","repo":"slackhq/nebula","slug":"use-of-curve25519-is-not-allowed-in-fips-140-only","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/ca.go","lineNumber":272,"sourceCode":"\t\t\treturn fmt.Errorf(\"invalid curve for PKCS#11: %s\", *cf.curve)\n\t\t}\n\n\t\tp11Client, err = pkclient.FromUrl(*cf.p11url)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error while creating PKCS#11 client: %w\", err)\n\t\t}\n\t\tdefer func(client *pkclient.PKClient) {\n\t\t\t_ = client.Close()\n\t\t}(p11Client)\n\t\tpub, err = p11Client.GetPubKey()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error while getting public key with PKCS#11: %w\", err)\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\tcurve = cert.Curve_CURVE25519\n\t\t\tpub, rawPriv, err = ed25519.GenerateKey(rand.Reader)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error while generating ed25519 keys: %s\", err)\n\t\t\t}\n\t\tcase \"P256\":\n\t\t\tvar key *ecdsa.PrivateKey\n\t\t\tcurve = cert.Curve_P256\n\t\t\tkey, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error while generating ecdsa keys: %s\", err)\n\t\t\t}\n\n\t\t\t// ecdh.PrivateKey lets us get at the encoded bytes, even though\n\t\t\t// we aren't using ECDH here.\n\t\t\teKey, err := key.ECDH()\n\t\t\tif err != nil {","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cmd/nebula-cert/ca.go#L254-L290","documentation":"In cmd/nebula-cert/ca.go (ca), when generating a CA with a Curve25519 curve ('25519', 'X25519', 'Curve25519', 'CURVE25519') and FIPS 140-only mode is enforced (fips140.Enforced()), the tool refuses to proceed. FIPS-only mode disallows non-approved algorithms, and Curve25519/X25519 is not FIPS-approved, so CA key generation is blocked deliberately.","triggerScenarios":"Running 'nebula-cert ca -curve 25519' (or any alias) while the binary/environment has FIPS 140 enforcement enabled (GODEBUG fips140=only / fips140.Enforced() true).","commonSituations":"Deploying nebula-cert on FIPS-mandated hosts (government/regulated environments) while reusing an existing 25519-based config; CI containers built with FIPS-only Go toolchains.","solutions":["Generate the CA with a FIPS-approved curve instead: pass -curve P256.","If 25519 is required, run without FIPS 140-only enforcement (remove fips140=only GODEBUG / use a non-FIPS build).","Reuse an existing FIPS-compliant CA and only sign new certs with P256.","Update organizational policy/config to declare the approved curve explicitly."],"exampleFix":"// before\n$ nebula-cert ca -curve 25519\n\n// after\n$ nebula-cert ca -curve P256","handlingStrategy":"validation","validationCode":"if fips140.Enforced() {\n    if curve == \"25519\" || curve == \"X25519\" || curve == \"Curve25519\" || curve == \"CURVE25519\" {\n        return fmt.Errorf(\"curve %s unavailable under FIPS 140-only mode; use P256\", curve)\n    }\n}\nreturn nebulaCertCA(curve)","typeGuard":"func fipsAllowedCurve(c string) bool {\n    switch c {\n    case \"25519\", \"X25519\", \"Curve25519\", \"CURVE25519\":\n        return !fips140.Enforced()\n    case \"P256\":\n        return true\n    }\n    return false\n}","tryCatchPattern":"err := runCA(args)\nif errors.Is(err, errFipsCurve) /* or check message */ {\n    log.Println(\"FIPS mode: falling back to P256\")\n    err = runCA(replaceCurve(args, \"P256\"))\n}","preventionTips":["Detect FIPS enforcement at startup and fail fast with a clear curve policy.","Standardize on P256 for FIPS-regulated deployments.","Pin curve settings in config/templates per environment (FIPS vs non-FIPS).","Document that Go FIPS 140-only mode forbids Curve25519 family primitives."],"tags":["fips","crypto","curve25519","pki"],"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"}