golang/go · error

crypto/mlkem/mlkemtest: use of derandomized encapsulation is

Error message

crypto/mlkem/mlkemtest: use of derandomized encapsulation is not allowed in FIPS 140-only mode

What it means

Returned by mlkemtest.Encapsulate768 when fips140only.Enforced() is true. Derandomized (fixed-randomness) encapsulation is a test-only operation that violates FIPS 140's approved-mode requirements because it bypasses the approved RNG; therefore the Go crypto module blocks it whenever the binary is built in FIPS 140-only mode. The same message appears in Encapsulate1024.

Source

Thrown at src/crypto/mlkem/mlkemtest/mlkemtest.go:25

import (
	fips140mlkem "crypto/internal/fips140/mlkem"
	"crypto/internal/fips140only"
	"crypto/mlkem"
	"errors"
)

// Encapsulate768 implements derandomized ML-KEM-768 encapsulation
// (ML-KEM.Encaps_internal from FIPS 203) using the provided encapsulation key
// ek and 32 bytes of randomness.
//
// It must only be used for known-answer tests.
func Encapsulate768(ek *mlkem.EncapsulationKey768, random []byte) (sharedKey, ciphertext []byte, err error) {
	if len(random) != 32 {
		return nil, nil, errors.New("mlkemtest: Encapsulate768: random must be 32 bytes")
	}
	if fips140only.Enforced() {
		return nil, nil, errors.New("crypto/mlkem/mlkemtest: use of derandomized encapsulation is not allowed in FIPS 140-only mode")
	}
	k, err := fips140mlkem.NewEncapsulationKey768(ek.Bytes())
	if err != nil {
		return nil, nil, errors.New("mlkemtest: Encapsulate768: failed to reconstruct key: " + err.Error())
	}
	sharedKey, ciphertext = k.EncapsulateInternal((*[32]byte)(random))
	return sharedKey, ciphertext, nil
}

// Encapsulate1024 implements derandomized ML-KEM-1024 encapsulation
// (ML-KEM.Encaps_internal from FIPS 203) using the provided encapsulation key
// ek and 32 bytes of randomness.
//
// It must only be used for known-answer tests.
func Encapsulate1024(ek *mlkem.EncapsulationKey1024, random []byte) (sharedKey, ciphertext []byte, err error) {
	if len(random) != 32 {
		return nil, nil, errors.New("mlkemtest: Encapsulate1024: random must be 32 bytes")
	}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Do not call mlkemtest functions in FIPS-only builds; gate them behind a non-FIPS build tag or test-only import.
  2. Use the standard mlkem.EncapsulationKey768.Encapsulate() which uses the approved RNG and is allowed in FIPS mode.
  3. If you need KATs, run them in a separate non-FIPS test binary.

Example fix

// before (in FIPS-only build)
shared, ct, err := mlkemtest.Encapsulate768(ek, z) // blocked

// after
shared, ct, err := ek.Encapsulate() // approved RNG path
Defensive patterns

Strategy: validation

Validate before calling

if fips140only.Enforced() {
    return ek.Encapsulate() // approved path
}
return mlkemtest.Encapsulate768(ek, random)

Type guard

func isFipsOnly() bool { return fips140only.Enforced() }

Try / catch

shared, ct, err := mlkemtest.Encapsulate768(ek, random)
if err != nil && strings.Contains(err.Error(), "FIPS 140-only mode") {
    shared, ct, err = ek.Encapsulate()
}
return shared, ct, err

Prevention

When it happens

Trigger: Building with GOEXPERIMENT=boringcrypto / FIPS-only settings (so fips140only.Enforced() returns true) and calling mlkemtest.Encapsulate768. Running KAT tests inside a FIPS-enforced binary.

Common situations: Shipping a FIPS-validated build and accidentally including KAT helper calls. CI that runs the full test matrix under FIPS mode. Importing mlkemtest in non-test code that must be FIPS-compliant.

Related errors


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