fix(mbedtls): validate cert header extent before reading it in bundle check

esp_crt_check_bundle() read the 4-byte certificate header (name_len,
key_len) via esp_crt_get_len() after only checking that the cert's
start offset lies inside the bundle, so a crafted bundle whose first
or last certificate starts within the final 3 bytes caused a transient
out-of-bounds read of up to 3 bytes before the extent check rejected
it. Require the whole header to lie inside the bundle before reading
it.
This commit is contained in:
harshal.patil
2026-08-24 20:56:43 +05:30
parent 5e8921d589
commit 710ce291ac
@@ -438,6 +438,9 @@ static bool esp_crt_check_bundle(const uint8_t* const x509_bundle, const size_t
// Check all offsets for consistency with certificate data
for (uint32_t i = 0; i < num_certs - 1; ++i) {
const uint32_t off = offsets[i];
if (unlikely((uint64_t)off + CRT_HEADER_SIZE > bundle_size)) {
return false;
}
cert_t cert = x509_bundle + off;
// The next offset in the list must point to right after the current cert
const uint32_t expected_next_offset = off + esp_crt_get_len(cert);
@@ -450,7 +453,7 @@ static bool esp_crt_check_bundle(const uint8_t* const x509_bundle, const size_t
// The loop above stops at num_certs - 1, so the final certificate's extent is never
// validated; check it explicitly so its key data cannot run past the bundle (CWE-125).
const uint32_t last_off = offsets[num_certs - 1];
if (unlikely(last_off >= bundle_size)) {
if (unlikely((uint64_t)last_off + CRT_HEADER_SIZE > bundle_size)) {
return false;
}
const uint32_t last_len = esp_crt_get_len(x509_bundle + last_off);