golang/go · error

mldsa: invalid input length for bitUnpackSlow

Error message

mldsa: invalid input length for bitUnpackSlow

What it means

bitUnpackSlow decodes a single ring element from a tightly packed byte slice where each coefficient occupies bitlen bits. The decoder requires the input length to be exactly n*bitlen/8 (n=256 coefficients); anything else means the slice does not align to the element boundary and 'invalid input length for bitUnpackSlow' is returned. It is used by the semi-expanded key decoder to read s1/s2/t0 regions.

Source

Thrown at src/crypto/internal/fips140/mldsa/semiexpanded.go:215

			v[0] = byte(acc)
			v = v[1:]
			acc >>= 8
			accBits -= 8
		}
	}
	if accBits > 0 {
		v[0] = byte(acc)
	}
	return out
}

func bitUnpackSlow(v []byte, a, b int) (ringElement, error) {
	bitlen := bits.Len(uint(a + b))
	if bitlen <= 0 || bitlen > 16 {
		panic("mldsa: internal error: invalid bitlen")
	}
	if len(v) != n*bitlen/8 {
		return ringElement{}, errors.New("mldsa: invalid input length for bitUnpackSlow")
	}

	mask := uint32((1 << bitlen) - 1)
	maxValue := uint32(a + b)

	var r ringElement
	var acc uint32
	var accBits uint
	vIdx := 0

	for i := range r {
		for accBits < uint(bitlen) {
			if vIdx < len(v) {
				acc |= uint32(v[vIdx]) << accBits
				vIdx++
				accBits += 8
			}
		}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Validate the total semi-expanded length up front (see error 369) so region offsets are always in-bounds.
  2. Regenerate the blob from a known-good key via TestingOnlyPrivateKeySemiExpandedBytes.
  3. Use complete, untouched NIST/ACVP vectors.

Example fix

// before
priv, err := mldsa.TestingOnlyNewPrivateKeyFromSemiExpanded(truncated)

// after
want := semiExpandedPrivKeySize(params44)
if len(sk) != want { return fmt.Errorf("need %d bytes", want) }
priv, err := mldsa.TestingOnlyNewPrivateKeyFromSemiExpanded(sk)
Defensive patterns

Strategy: validation

Validate before calling

if len(sk) != semiExpandedSizeForVariant(v) {
    return ErrBadSemiExpandedSize
}

Prevention

When it happens

Trigger: bitUnpackSlow is handed a slice whose length is not 256*bitlen/8 bytes (e.g. 33 bytes for an η=2 element that expects 32), typically because the surrounding semi-expanded blob is truncated or its regions were sliced at the wrong offsets.

Common situations: Truncating the semi-expanded key partway through a region; slicing regions with the wrong η/bitlen assumption; corrupt ACVP vector.

Related errors


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