golang/go · error

crypto/aes: GCM tag and nonce sizes can't be non-standard at

Error message

crypto/aes: GCM tag and nonce sizes can't be non-standard at the same time

What it means

Raised by the BoringCrypto AES backend's NewGCM when BOTH nonceSize and tagSize are non-standard simultaneously. BoringCrypto's EVP AEAD path can fall back to the standard library for a non-standard nonce OR a non-standard tag, but not both at once, so the combination is rejected up front.

Source

Thrown at src/crypto/internal/boring/aes.go:223

const (
	gcmBlockSize         = 16
	gcmTagSize           = 16
	gcmStandardNonceSize = 12
)

type aesNonceSizeError int

func (n aesNonceSizeError) Error() string {
	return "crypto/aes: invalid GCM nonce size " + strconv.Itoa(int(n))
}

type noGCM struct {
	cipher.Block
}

func (c *aesCipher) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) {
	if nonceSize != gcmStandardNonceSize && tagSize != gcmTagSize {
		return nil, errors.New("crypto/aes: GCM tag and nonce sizes can't be non-standard at the same time")
	}
	// Fall back to standard library for GCM with non-standard nonce or tag size.
	if nonceSize != gcmStandardNonceSize {
		return cipher.NewGCMWithNonceSize(&noGCM{c}, nonceSize)
	}
	if tagSize != gcmTagSize {
		return cipher.NewGCMWithTagSize(&noGCM{c}, tagSize)
	}
	return c.newGCM(0)
}

const (
	VersionTLS12 = 0x0303
	VersionTLS13 = 0x0304
)

func NewGCMTLS(c cipher.Block) (cipher.AEAD, error) {
	return c.(*aesCipher).newGCM(VersionTLS12)

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Keep at least one of nonceSize/tagSize at its standard value (12-byte nonce or 16-byte tag).
  2. If both must be non-standard, use the standard library crypto/aes GCM (non-boring build) or a pure-Go GCM implementation.
  3. Re-evaluate whether both deviations are truly required by the protocol; one of the two is usually fixed.
  4. On a boringcrypto build, fall back is automatic for a single deviation — request only one.

Example fix

// before (boringcrypto build)
aead, err := cipher.NewGCMWithNonceSize(block, 13) // non-standard nonce
tagAead, _ := cipher.NewGCMWithTagSize(block, 12)   // then non-standard tag elsewhere
// combining both on one AEAD is rejected

// after
aead, err := cipher.NewGCM(block) // standard 12-byte nonce, 16-byte tag
Defensive patterns

Strategy: validation

Validate before calling

func checkGCMParams(nonceSize, tagSize int) error {
    const stdNonce, stdTag = 12, 16
    if nonceSize != stdNonce && tagSize != stdTag {
        return errors.New("boringcrypto GCM cannot vary nonce and tag size together")
    }
    return nil
}

Prevention

When it happens

Trigger: Calling the internal boring aesCipher.NewGCM(nonceSize, tagSize) with nonceSize != 12 (gcmStandardNonceSize) AND tagSize != 16 (gcmTagSize). User-facing: cipher.NewGCMWithNonceSize combined with a non-standard tag on a boringcrypto build of Go.

Common situations: Applications that need SIV/non-12-byte nonces AND truncated/extended GCM tags; misconfigured AEAD wrappers that override both defaults; protocol implementations requiring bespoke GCM parameters under a FIPS/boringcrypto Go toolchain.

Related errors


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