embassy-rs/embassy · error

Message is too large for given IV size.

Error message

Message is too large for given IV size.

What it means

This panic fires during GCM/GMAC J0 (IV) block construction in the CRYP driver. When iv.len() > 11, byte 12 of the fixed block is occupied by the IV, so a payload length whose most significant byte (payload_len_bytes[0]) is nonzero cannot be encoded — i.e. payload length >= 16,777,216 bytes (~16 MiB) with a long IV.

Solutions

  1. Use the standard 12-byte GCM IV, which encodes the length field without this limitation.
  2. Chunk the message into pieces under 16 MiB, each with its own GCM context.
  3. Shorten the IV to <= 11 bytes if the monolithic payload must be kept.

Example fix

// before
cipher.encrypt(ctx, &long_iv, aad, &huge_plaintext, &mut out);
// after
for chunk in plaintext.chunks(16 * 1024 * 1024) {
    cipher.encrypt(ctx, iv, aad, chunk, &mut out_chunk);
}
Defensive patterns

Strategy: validation

Validate before calling

const MAX_PAYLOAD_WITH_LONG_IV: usize = (1 << 24) - 1;
if iv.len() > 11 && payload_len > MAX_PAYLOAD_WITH_LONG_IV {
    // chunk the message or use a 12-byte IV
}

Prevention

When it happens

Trigger: GCM encrypt/decrypt payload processing with an IV longer than 11 bytes AND payload_len >= 2^24 bytes.

Common situations: Streaming very large files (>16 MiB) through GCM with a non-standard long IV; encrypting an entire large buffer in one call instead of chunking.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10). Data as JSON: /api/errors/f5a9a181b1573de6. Report an issue: GitHub.

Appendix: source

Thrown at embassy-stm32/src/cryp/mod.rs:796

            aad_header[2] = aad_len_bytes[0];
            aad_header[3] = aad_len_bytes[1];
            aad_header[4] = aad_len_bytes[2];
            aad_header[5] = aad_len_bytes[3];
            aad_header_len = 6;
        }
    }
    let mut block0: Aligned<A4, [u8; 16]> = Aligned([0; 16]);
    if aad_len > 0 {
        block0[0] = 0x40;
    }
    block0[0] |= ((((tag_size as u8) - 2) >> 1) & 0x07) << 3;
    block0[0] |= ((15 - (iv.len() as u8)) - 1) & 0x07;
    block0[1..1 + iv.len()].copy_from_slice(iv);
    let payload_len_bytes: [u8; 4] = (payload_len as u32).to_be_bytes();
    if iv.len() <= 11 {
        block0[12] = payload_len_bytes[0];
    } else if payload_len_bytes[0] > 0 {
        panic!("Message is too large for given IV size.");
    }
    if iv.len() <= 12 {
        block0[13] = payload_len_bytes[1];
    } else if payload_len_bytes[1] > 0 {
        panic!("Message is too large for given IV size.");
    }
    block0[14] = payload_len_bytes[2];
    block0[15] = payload_len_bytes[3];
    let mut ctr: [u8; 16] = [0; 16];
    ctr[0] = block0[0] & 0x07;
    ctr[1..1 + iv.len()].copy_from_slice(&block0[1..1 + iv.len()]);
    ctr[15] = 0x01;

    (aad_header, aad_header_len, block0, ctr)
}

/// Type-erased AES-CCM operation.
#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]

View on GitHub (pinned to 463a07b963)