{"record":{"id":"7e4755d5f7dc3202","repo":"golang/go","slug":"crypto-ecdsa-use-of-custom-curves-is-not-allowed","errorCode":null,"errorMessage":"crypto/ecdsa: use of custom curves is not allowed in FIPS 140-only mode","messagePattern":"crypto/ecdsa: use of custom curves is not allowed in FIPS 140-only mode","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/ecdsa/ecdsa_legacy.go","lineNumber":24,"sourceCode":"\nimport (\n\t\"crypto/elliptic\"\n\t\"crypto/internal/fips140only\"\n\t\"errors\"\n\t\"io\"\n\t\"math/big\"\n\t\"math/rand/v2\"\n\n\t\"golang.org/x/crypto/cryptobyte\"\n\t\"golang.org/x/crypto/cryptobyte/asn1\"\n)\n\n// This file contains a math/big implementation of ECDSA that is only used for\n// deprecated custom curves.\n\nfunc generateLegacy(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) {\n\tif fips140only.Enforced() {\n\t\treturn nil, errors.New(\"crypto/ecdsa: use of custom curves is not allowed in FIPS 140-only mode\")\n\t}\n\n\tk, err := randFieldElement(c, rand)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tpriv := new(PrivateKey)\n\tpriv.PublicKey.Curve = c\n\tpriv.D = k\n\tpriv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes())\n\treturn priv, nil\n}\n\n// hashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4,\n// we use the left-most bits of the hash to match the bit-length of the order of\n// the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3.\nfunc hashToInt(hash []byte, c elliptic.Curve) *big.Int {","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/ecdsa/ecdsa_legacy.go#L6-L42","documentation":"Thrown by generateLegacy (ecdsa_legacy.go:24) when fips140only.Enforced() is true and a non-NIST (custom/deprecated) elliptic curve is used to generate a key. In FIPS 140-only mode (GOEXPERIMENT=fips140 / GOFIPS=140 behavior), only approved NIST curves (P-224/256/384/521) are permitted; custom curves like secp256k1 or legacy P-521 handling are blocked.","triggerScenarios":"Calling ecdsa.GenerateKey with a custom curve (elliptic curve other than the NIST curves) while FIPS 140-only mode is active. Triggered via the legacy generation path used for non-FIPS curves.","commonSituations":"Building for a FIPS-validated deployment (GOEXPERIMENT=fips140) and using a non-NIST curve such as secp256k1 (blockchain), or pinning a curve via an old config. Environment: GOFIPS=1 or a fips140 build tag flips enforcement.","solutions":["Switch to a NIST curve: elliptic.P256(), P384(), or P521().","If a custom curve is mandatory, disable FIPS 140-only mode (remove GOEXPERIMENT=fips140 / the fips140 build tag) and accept the loss of FIPS compliance.","Audit config / key generation code to confirm the curve is NIST-standard under FIPS builds."],"exampleFix":"// before\npriv, err := ecdsa.GenerateKey(customCurve, rand.Reader) // FIPS-only -> error 244\n\n// after\npriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)","handlingStrategy":"validation","validationCode":"if fips140only.Enforced() && !isNISTCurve(curve) {\n    return errors.New(\"custom curves not allowed in FIPS 140-only mode\")\n}\nfunc isNISTCurve(c elliptic.Curve) bool {\n    switch c {\n    case elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521():\n        return true\n    }\n    return false\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use NIST curves (P-256/384/521) for FIPS-validated builds.","Gate custom-curve code behind a build tag that is disabled in FIPS mode.","Audit curve selection when enabling GOEXPERIMENT=fips140."],"tags":["go","crypto","ecdsa","fips","compliance"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}