chacha20poly1305: error out in fips140=only mode

We don't guarantee fips140=only support in x/crypto, but
chacha20poly1305 is special in that it's vendored into the standard
library. We could wrap all the callsites, but it's more robust to
just error out at construction time.

Change-Id: I4b1e451bd250429c4c5c5b61c8b2141c6a6a6964
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/728480
Reviewed-by: Roland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
diff --git a/chacha20poly1305/chacha20poly1305.go b/chacha20poly1305/chacha20poly1305.go
index 8cf5d81..9567955 100644
--- a/chacha20poly1305/chacha20poly1305.go
+++ b/chacha20poly1305/chacha20poly1305.go
@@ -38,6 +38,9 @@
 
 // New returns a ChaCha20-Poly1305 AEAD that uses the given 256-bit key.
 func New(key []byte) (cipher.AEAD, error) {
+	if fips140Enforced() {
+		return nil, errors.New("chacha20poly1305: use of ChaCha20Poly1305 is not allowed in FIPS 140-only mode")
+	}
 	if len(key) != KeySize {
 		return nil, errors.New("chacha20poly1305: bad key length")
 	}
diff --git a/chacha20poly1305/fips140only_compat.go b/chacha20poly1305/fips140only_compat.go
new file mode 100644
index 0000000..9b9d564
--- /dev/null
+++ b/chacha20poly1305/fips140only_compat.go
@@ -0,0 +1,9 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !go1.26
+
+package chacha20poly1305
+
+func fips140Enforced() bool { return false }
diff --git a/chacha20poly1305/fips140only_go1.26.go b/chacha20poly1305/fips140only_go1.26.go
new file mode 100644
index 0000000..f71089c
--- /dev/null
+++ b/chacha20poly1305/fips140only_go1.26.go
@@ -0,0 +1,11 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.26
+
+package chacha20poly1305
+
+import "crypto/fips140"
+
+func fips140Enforced() bool { return fips140.Enforced() }
diff --git a/chacha20poly1305/xchacha20poly1305.go b/chacha20poly1305/xchacha20poly1305.go
index 1cebfe9..b4299b7 100644
--- a/chacha20poly1305/xchacha20poly1305.go
+++ b/chacha20poly1305/xchacha20poly1305.go
@@ -22,6 +22,9 @@
 // preferred when nonce uniqueness cannot be trivially ensured, or whenever
 // nonces are randomly generated.
 func NewX(key []byte) (cipher.AEAD, error) {
+	if fips140Enforced() {
+		return nil, errors.New("chacha20poly1305: use of ChaCha20Poly1305 is not allowed in FIPS 140-only mode")
+	}
 	if len(key) != KeySize {
 		return nil, errors.New("chacha20poly1305: bad key length")
 	}