slackhq/nebula · error

no cipher state available to encrypt

Error message

no cipher state available to encrypt

What it means

The FIPS-140 GCM implementation's EncryptDanger has the same nil-receiver guard: a nil *aeadGCMFIPS140Cipher has no AEAD to seal with, so it returns this error instead of panicking, and also enforces the same RejectAfterMessages nonce ceiling.

Source

Thrown at noiseutil/fips140.go:118

func (c *aeadGCMFIPS140Cipher) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
	if !c.ready {
		c.init(nonce)
	}
	return c.AEAD.Seal(dst, nonce, plaintext, additionalData)
}

func (c *aeadGCMFIPS140Cipher) Encrypt(out []byte, n uint64, ad, plaintext []byte) []byte {
	return c.Seal(out, aeadGCMFIPS140CipherNonce(n), plaintext, ad)
}

func (c *aeadGCMFIPS140Cipher) Decrypt(out []byte, n uint64, ad, ciphertext []byte) ([]byte, error) {
	return c.Open(out, aeadGCMFIPS140CipherNonce(n), ciphertext, ad)
}

func (c *aeadGCMFIPS140Cipher) EncryptDanger(out, ad, plaintext []byte, n uint64, nb []byte) ([]byte, error) {
	if c == nil {
		return nil, errors.New("no cipher state available to encrypt")
	}
	if n >= RejectAfterMessages {
		return nil, ErrMessageCounterExhausted
	}
	binary.BigEndian.PutUint64(nb[4:], n)
	out = c.Seal(out, nb, plaintext, ad)
	return out, nil
}

func (c *aeadGCMFIPS140Cipher) DecryptDanger(out, ad, ciphertext []byte, n uint64, nb []byte) ([]byte, error) {
	if c == nil {
		return []byte{}, nil
	}
	binary.BigEndian.PutUint64(nb[4:], n)
	return c.Open(out, nb, ciphertext, ad)
}

func (c *aeadGCMFIPS140Cipher) Overhead() int {

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Ensure the handshake completes and the FIPS GCM cipher is constructed before any EncryptDanger call.
  2. Add a nil check on the cipher before sending in FIPS mode.
  3. Rekey if the nonce has reached RejectAfterMessages.

Example fix

// before
out, err := c.EncryptDanger(out, ad, plaintext, n, nb) // c may be nil
// after
if c == nil { return nil, errors.New("FIPS GCM cipher not initialized") }
Defensive patterns

Strategy: type-guard

Validate before calling

if c == nil {
    return errors.New("FIPS GCM cipher not initialized")
}

Type guard

func fipsCipherReady(c *aeadGCMFIPS140Cipher) bool { return c != nil }

Try / catch

out, err := c.EncryptDanger(out, ad, plaintext, n, nb)
if err != nil {
    // nil state: re-run handshake; exhausted: rekey
}

Prevention

When it happens

Trigger: EncryptDanger called on a nil aeadGCMFIPS140Cipher (FIPS mode cipher never initialized because handshake failed or FIPS mode setup was skipped), or the nonce n reaching RejectAfterMessages.

Common situations: FIPS-140 mode enabled but cipher construction failed upstream, handshake not completed before sending data traffic in a FIPS-restricted deployment.

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/209fc07104963749. Report an issue: GitHub.