golang/go · critical · CertificateVerificationError

server's certificate is not allowed in FIPS 140-3 mode

Error message

server's certificate is not allowed in FIPS 140-3 mode

What it means

Thrown when FIPS 140-3 mode is active (fips140tls.Required() returns true) and the server's leaf certificate uses algorithms or key types not on the FIPS 140-3 approved list. The error is wrapped in a CertificateVerificationError with UnverifiedCertificates set.

Source

Thrown at src/crypto/tls/handshake_client.go:1179

		for _, cert := range certs[1:] {
			opts.Intermediates.AddCert(cert)
		}
		chains, err := certs[0].Verify(opts)
		if err != nil {
			c.sendAlert(alertBadCertificate)
			return &CertificateVerificationError{UnverifiedCertificates: certs, Err: err}
		}

		c.verifiedChains, err = fipsAllowedChains(chains)
		if err != nil {
			c.sendAlert(alertBadCertificate)
			return &CertificateVerificationError{UnverifiedCertificates: certs, Err: err}
		}
	}

	if fips140tls.Required() && !isCertificateAllowedFIPS(certs[0]) {
		c.sendAlert(alertBadCertificate)
		err := errors.New("server's certificate is not allowed in FIPS 140-3 mode")
		return &CertificateVerificationError{UnverifiedCertificates: certs, Err: err}
	}

	switch certs[0].PublicKey.(type) {
	case *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey:
	case *mldsa.PublicKey:
		if c.vers < VersionTLS13 {
			c.sendAlert(alertIllegalParameter)
			return errors.New("tls: server's certificate uses ML-DSA, which requires TLS 1.3")
		}
	default:
		c.sendAlert(alertUnsupportedCertificate)
		return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey)
	}

	c.peerCertificates = certs

	if c.config.VerifyPeerCertificate != nil && !echRejected {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Identify which certificate property violates FIPS — check the leaf cert's key type, curve, signature hash algorithm, and key size.
  2. Replace the server certificate with one using FIPS-approved algorithms: RSA (2048+ bits), ECDSA P-256/P-384, SHA-256 or stronger.
  3. If FIPS compliance is not actually required for this connection, disable FIPS-only mode in the build or runtime configuration.
  4. Verify with: openssl x509 -in cert.pem -text to inspect the certificate's algorithm details.
Defensive patterns

Strategy: try-catch

Validate before calling

// Before connecting, verify FIPS mode requirement and server cert algorithm
if fips140tls.Required() {
    // Pre-fetch and inspect the server certificate
    conn, err := net.DialTimeout("tcp", addr, 5*time.Second)
    if err == nil {
        tlsConn := tls.Client(conn, &tls.Config{InsecureSkipVerify: true})
        if err := tlsConn.Handshake(); err == nil {
            certs := tlsConn.ConnectionState().PeerCertificates
            if len(certs) > 0 && !isCertificateAllowedFIPS(certs[0]) {
                log.Printf("server cert uses non-FIPS algorithm: %s", certs[0].PublicKeyAlgorithm)
            }
        }
        tlsConn.Close()
    }
}

Try / catch

// FIPS cert errors are wrapped in CertificateVerificationError
conn, err := tls.Dial("tcp", addr, config)
if err != nil {
    var certErr *tls.CertificateVerificationError
    if errors.As(err, &certErr) {
        if strings.Contains(certErr.Err.Error(), "FIPS 140-3") {
            log.Printf("server cert not FIPS-compliant: %v", certErr.Err)
            // Replace server cert or disable FIPS mode
        }
    }
}

Prevention

When it happens

Trigger: Triggered after successful chain verification when fips140tls.Required() is true and isCertificateAllowedFIPS(certs[0]) returns false. The check applies to the leaf certificate's public key type and signature algorithm.

Common situations: Running a Go binary built with GOEXPERIMENT=fips140tls or in a FIPS-enabled environment. Server certificate uses algorithms not approved under FIPS 140-3 (e.g. Ed25519, certain curves, or disallowed hash functions). Mixing a FIPS-compliant Go client with a non-FIPS-compliant server infrastructure.

Understand the failure class

Related errors


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