From 94c8b51b44cdce6003a3e0c490601fde4ada527e Mon Sep 17 00:00:00 2001 From: vasilito Date: Mon, 27 Jul 2026 16:24:01 +0900 Subject: [PATCH] btintel: fix F22 ECDSA firmware blob out-of-bounds slice panic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CRITICAL F22 from NETWORKING-AND-DRIVERS-CODE-ASSESSMENT-2026-07-27.md ยง3.5: redbear-btusb/src/btintel.rs:178-187 sliced fw_data[644+128..644+224] and [644+224..644+320] on the ECDSA branch with only 'if fw_data.len() < 644' bounds-check. A 645..963 byte ECDSA firmware blob would panic with 'range start index 772 out of range for slice of length N'. Fix: introduce ECDSA_FULL_LEN = ECDSA_HEADER_LEN + 128 + 96 + 96 (= 964) covering the full ECDSA header (CSS + PKEY + SIG). Update the bounds check to require fw_data.len() >= ECDSA_FULL_LEN. The payload slice now starts at ECDSA_FULL_LEN, making the slice operations guaranteed in-bounds. The error message is updated to print the actual minimum length (964) instead of the misleading 644. Also updates the existing ECDSA_HEADER_LEN = 644 constant reference: the constant is correctly used; the bug was that the check itself was under-specifying the requirement (only the header start, not the header end). --- .../drivers/redbear-btusb/source/src/btintel.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/local/recipes/drivers/redbear-btusb/source/src/btintel.rs b/local/recipes/drivers/redbear-btusb/source/src/btintel.rs index e11cbfbe92..bd6502d700 100644 --- a/local/recipes/drivers/redbear-btusb/source/src/btintel.rs +++ b/local/recipes/drivers/redbear-btusb/source/src/btintel.rs @@ -176,14 +176,23 @@ pub fn firmware_download_commands(fw_data: &[u8]) -> Vec { commands.extend(secure_send_commands(FRAGMENT_TYPE_PAYLOAD, payload)); } CssKeyType::Ecdsa => { - if fw_data.len() < 644 { - warn!("btintel: ECDSA firmware too short ({} bytes)", fw_data.len()); + // ECDSA firmware layout: CSS @ 644..772, PKEY @ 772..868, + // SIG @ 868..964. Payload starts at 964. Without the full + // bounds check, a 645..963 byte blob would panic on the + // PKEY/SIG slices. + const ECDSA_FULL_LEN: usize = ECDSA_HEADER_LEN + 128 + 96 + 96; + if fw_data.len() < ECDSA_FULL_LEN { + warn!( + "btintel: ECDSA firmware too short ({} bytes, need {})", + fw_data.len(), + ECDSA_FULL_LEN + ); return commands; } commands.extend(secure_send_commands(FRAGMENT_TYPE_CSS, &fw_data[644..644 + 128])); commands.extend(secure_send_commands(FRAGMENT_TYPE_PKEY, &fw_data[644 + 128..644 + 224])); commands.extend(secure_send_commands(FRAGMENT_TYPE_SIGNATURE, &fw_data[644 + 224..644 + 320])); - let payload = &fw_data[644 + 320..]; + let payload = &fw_data[ECDSA_FULL_LEN..]; commands.extend(secure_send_commands(FRAGMENT_TYPE_PAYLOAD, payload)); } CssKeyType::Hybrid => {