golang/go · error

unsupported curve

Error message

unsupported curve

What it means

unsupportedCurveKEM is a sentinel returned by DHKEM() when the supplied ecdh.Curve is not P-256/P-384/P-521/X25519. Every method on this sentinel returns "unsupported curve". Because ecdh.Curve is a closed interface (unexported methods), this default branch is only reachable if a new curve type is added to the standard library or by an internal fork.

Source

Thrown at src/crypto/hpke/kem.go:171

	case ecdh.P521():
		return dhKEMP521
	case ecdh.X25519():
		return dhKEMX25519
	default:
		// The set of ecdh.Curve implementations is closed, because the
		// interface has unexported methods. Therefore, this default case is
		// only hit if a new curve is added that DHKEM doesn't support.
		return unsupportedCurveKEM{}
	}
}

type unsupportedCurveKEM struct{}

func (unsupportedCurveKEM) ID() uint16 {
	return 0
}
func (unsupportedCurveKEM) GenerateKey() (PrivateKey, error) {
	return nil, errors.New("unsupported curve")
}
func (unsupportedCurveKEM) NewPublicKey([]byte) (PublicKey, error) {
	return nil, errors.New("unsupported curve")
}
func (unsupportedCurveKEM) NewPrivateKey([]byte) (PrivateKey, error) {
	return nil, errors.New("unsupported curve")
}
func (unsupportedCurveKEM) DeriveKeyPair([]byte) (PrivateKey, error) {
	return nil, errors.New("unsupported curve")
}
func (unsupportedCurveKEM) encSize() int {
	return 0
}

type dhKEMPublicKey struct {
	kem *dhKEM
	pub *ecdh.PublicKey
}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Pass one of ecdh.P256(), ecdh.P384(), ecdh.P521(), or ecdh.X25519() to DHKEM.
  2. Upgrade the vendored crypto/hpke to match the toolchain's crypto/ecdh.
  3. Avoid constructing ecdh.Curve values from external input.

Example fix

// before
kem := hpke.DHKEM(someNewCurve)
k, err := kem.GenerateKey() // "unsupported curve"

// after
kem := hpke.DHKEM(ecdh.X25519())
k, err := kem.GenerateKey()
Defensive patterns

Strategy: validation

Validate before calling

func supportedDHCurve(c ecdh.Curve) bool {
    switch c {
    case ecdh.P256(), ecdh.P384(), ecdh.P521(), ecdh.X25519():
        return true
    }
    return false
}

func generateKey(c ecdh.Curve) (hpke.PrivateKey, error) {
    if !supportedDHCurve(c) {
        return nil, fmt.Errorf("curve %v not supported by DHKEM", c)
    }
    return hpke.DHKEM(c).GenerateKey()
}

Try / catch

k, err := kem.GenerateKey()
if err != nil && err.Error() == "unsupported curve" {
    return fmt.Errorf("DHKEM returned sentinel; pass a supported ecdh.Curve")
}

Prevention

When it happens

Trigger: DHKEM(unknownCurve).GenerateKey() where unknownCurve is any ecdh.Curve outside the four supported. In practice reachable only by a fork that introduces a new ecdh.Curve constant, or by a future stdlib addition this build predates.

Common situations: Vendoring an older copy of crypto/hpke into a toolchain whose crypto/ecdh gained a new curve; or a downstream fork adding experimental curves.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/c589b8ffe4c6f6dc. Report an issue: GitHub.