golang/go · error
crypto/cipher: use of GCM with arbitrary IVs is not allowed
Error message
crypto/cipher: use of GCM with arbitrary IVs is not allowed in FIPS 140-only mode, use NewGCMWithRandomNonce
What it means
When FIPS 140-only mode is enforced (the toolchain was built with GOEXPERIMENT=fips140 and the process opted in via GOFIPS=1, or the fips140-only toggle is otherwise active), cipher.NewGCM refuses to construct a GCM AEAD with caller-controlled nonces. FIPS 140-3 guidance requires either random nonces or a counter-based construction, supplied by NewGCMWithRandomNonce.
Source
Thrown at src/crypto/cipher/gcm.go:28
"crypto/internal/fips140/alias"
"crypto/internal/fips140only"
"crypto/subtle"
"errors"
"internal/byteorder"
)
const (
gcmBlockSize = 16
gcmStandardNonceSize = 12
gcmTagSize = 16
gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes.
)
// NewGCM returns the given 128-bit, block cipher wrapped in Galois Counter Mode
// with the standard nonce length.
func NewGCM(cipher Block) (AEAD, error) {
if fips140only.Enforced() {
return nil, errors.New("crypto/cipher: use of GCM with arbitrary IVs is not allowed in FIPS 140-only mode, use NewGCMWithRandomNonce")
}
return newGCM(cipher, gcmStandardNonceSize, gcmTagSize)
}
// NewGCMWithNonceSize returns the given 128-bit, block cipher wrapped in Galois
// Counter Mode, which accepts nonces of the given length. The length must not
// be zero.
//
// Only use this function if you require compatibility with an existing
// cryptosystem that uses non-standard nonce lengths. All other users should use
// [NewGCM], which is faster and more resistant to misuse.
func NewGCMWithNonceSize(cipher Block, size int) (AEAD, error) {
if fips140only.Enforced() {
return nil, errors.New("crypto/cipher: use of GCM with arbitrary IVs is not allowed in FIPS 140-only mode, use NewGCMWithRandomNonce")
}
return newGCM(cipher, size, gcmTagSize)
}
View on GitHub (pinned to b6b368adc5)
Solutions
- Switch to cipher.NewGCMWithRandomNonce(block), which generates a random 96-bit nonce per Seal call.
- If you need deterministic encryption for compatibility, run the binary with FIPS-only mode disabled (GOFIPS=0 or do not opt in) — but verify this is acceptable to your compliance posture.
- Refactor wire formats that previously transmitted nonce separately so they accept the prepended-random-nonce layout produced by NewGCMWithRandomNonce.
- If you must keep arbitrary IVs for protocol compatibility, document a compensating control (e.g., a separate audit log) per your FIPS security policy.
Example fix
// before
a, err := cipher.NewGCM(block) // fails in FIPS-only mode
// after
a, err := cipher.NewGCMWithRandomNonce(block)
if err != nil { return err }
ct := a.Seal(nil, nil, plaintext, nil) // nonce generated + prepended Defensive patterns
Strategy: type-guard
Validate before calling
// Decide at construction time based on whether FIPS-only mode is on.
// (You usually know this from build/deploy flags.)
func newAEAD(block cipher.Block) (cipher.AEAD, error) {
if fipsEnabled() {
return cipher.NewGCMWithRandomNonce(block)
}
return cipher.NewGCM(block)
} Type guard
func isAESBlock(b cipher.Block) bool {
_, ok := b.(*aes.Block)
return ok
} Try / catch
a, err := cipher.NewGCM(block)
if err != nil {
if strings.Contains(err.Error(), "FIPS 140-only mode") {
a, err = cipher.NewGCMWithRandomNonce(block)
if err != nil { return err }
} else {
return err
}
} Prevention
- Standardize on NewGCMWithRandomNonce for FIPS-targeted builds.
- Document the deployment's FIPS posture in CI configuration.
- Refactor wire formats to accept the prepended-random-nonce layout.
When it happens
Trigger: Calling cipher.NewGCM(block) while fips140only.Enforced() returns true. The check fires before any AEAD is allocated, so the error is returned directly from the constructor.
Common situations: Running a Go FIPS build in a regulated environment (US federal, healthcare, finance), upgrading a service that previously used arbitrary-IV GCM to a FIPS-only toolchain, or shipping a binary in a container whose base image set GOFIPS=1.
Related errors
- crypto/cipher: use of GCM with non-AES ciphers is not allowe
- crypto/aes: GCM tag and nonce sizes can't be non-standard at
- cipher: incorrect tag size given to GCM
- cipher: the nonce can't have zero length
- cipher: NewGCM requires 128-bit block cipher
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/ce7c2f2ef45cb539.
Report an issue: GitHub.