From a6a9a25149f1d973bd7b9ef48d213eb12c20f392 Mon Sep 17 00:00:00 2001 From: David Zimmermann Date: Wed, 26 Aug 2026 17:19:32 -0700 Subject: [PATCH 1/7] add fuzz_tbor_part_info --- fuzz/Cargo.toml | 7 +++++++ .../fuzz_targets/ddi/tbor/fuzz_tbor_part_info.rs | 16 ++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_info.rs diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 7cf7ae55f..296a9b7cf 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -112,3 +112,10 @@ doc = false name = "fuzz_tbor_part_final" path = "fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs" test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_part_info" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_part_info.rs" +test = false diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_info.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_info.rs new file mode 100644 index 000000000..60ee9bf93 --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_info.rs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +#[path = "../../common.rs"] +mod common; + +use azihsm_ddi_tbor_types::TborPartInfoReq; +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|_input: &[u8]| { + let dev = common::open_emu_dev(); + let req = TborPartInfoReq; + common::fuzz_exec_op_tbor(&dev, &req); +}); From 6d7ef9780339ec6c9c83a380712afe5f27760ed1 Mon Sep 17 00:00:00 2001 From: David Zimmermann Date: Wed, 19 Aug 2026 18:15:57 -0700 Subject: [PATCH 2/7] add fuzz targets for TBOR_OP_PART_INIT & TBOR_OP_PART_FINAL opcodes --- fuzz/Cargo.toml | 15 ++++++ .../ddi/tbor/fuzz_tbor_part_final.rs | 54 +++++++++++++++++++ .../ddi/tbor/fuzz_tbor_part_init.rs | 52 ++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs create mode 100644 fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 501806bbf..bd17109ea 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -17,6 +17,7 @@ azihsm_ddi_tbor_test_harness = { features = [ "emu", ], path = "../crates/tbor_test_harness" } azihsm_ddi_tbor_types = { path = "../ddi/tbor/types" } +zerocopy = { features = ["derive"], version = "0.8.17" } # dependencies for fuzzing libfuzzer-sys = { features = ["arbitrary-derive"], version = "0.4" } @@ -97,3 +98,17 @@ doc = false name = "fuzz_tbor_psk_change" path = "fuzz_targets/ddi/tbor/fuzz_tbor_psk_change.rs" test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_part_init" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs" +test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_part_final" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs" +test = false diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs new file mode 100644 index 000000000..aa70ef7ad --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +use azihsm_ddi_tbor_test_harness::TestCtx; +use azihsm_ddi_tbor_types::CERT_DESCRIPTOR_LEN; +use azihsm_ddi_tbor_types::CertDescriptor; +use azihsm_ddi_tbor_types::LOCAL_MK_BACKUP_LEN; +use azihsm_ddi_tbor_types::MAX_CERTS; +use azihsm_ddi_tbor_types::PartPolicy; +use azihsm_ddi_tbor_types::SessionType; +use azihsm_ddi_tbor_types::TborPartFinalReq; +use libfuzzer_sys::arbitrary; +use libfuzzer_sys::arbitrary::Arbitrary; +use libfuzzer_sys::fuzz_target; +use zerocopy::FromBytes; + +const CU: u8 = 1; +static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); + +#[derive(Arbitrary, Debug)] +struct FuzzInput { + /// Fixed-length fuzzed cert_descriptors buffer. + cert_descriptors: [u8; MAX_CERTS * CERT_DESCRIPTOR_LEN], + /// Fixed-length fuzzed prev_local_mk_backup buffer. + prev_local_mk_backup: [u8; LOCAL_MK_BACKUP_LEN], +} + +fuzz_target!(|input: FuzzInput| { + let ctx = CTX.get_or_init(TestCtx::new); + ctx.erase().expect("erase should succeed"); + + let session = ctx + .open_session(CU, SessionType::PlainText) + .expect("session open should succeed"); + + // Reinterpret the fuzzed byte array as CertDescriptor slice. + let cert_descriptors: Vec = input + .cert_descriptors + .chunks_exact(CERT_DESCRIPTOR_LEN) + .map(|chunk| CertDescriptor::read_from_bytes(chunk).unwrap()) + .collect(); + + let part_final_req = TborPartFinalReq { + session_id: session.session_id(), + part_policy: PartPolicy::zeroed(), + cert_descriptors, + prev_local_mk_backup: input.prev_local_mk_backup.to_vec(), + }; + let _ = ctx.tbor(&part_final_req); + + session.close().expect("session close should succeed"); +}); diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs new file mode 100644 index 000000000..74501636a --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +use azihsm_ddi_tbor_test_harness::TestCtx; +use azihsm_ddi_tbor_types::MACH_SEED_ENVELOPE_MAX_LEN; +use azihsm_ddi_tbor_types::POTA_THUMBPRINT_LEN; +use azihsm_ddi_tbor_types::SAPOTA_THUMBPRINT_LEN; +use azihsm_ddi_tbor_types::SATA_THUMBPRINT_LEN; +use azihsm_ddi_tbor_types::PartPolicy; +use azihsm_ddi_tbor_types::SessionType; +use azihsm_ddi_tbor_types::TborPartInitReq; +use libfuzzer_sys::arbitrary; +use libfuzzer_sys::arbitrary::Arbitrary; +use libfuzzer_sys::fuzz_target; + +const CU: u8 = 1; +static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); + +#[derive(Arbitrary, Debug)] +struct FuzzInput { + /// Fixed-length fuzzed mach_seed_envelope buffer. + mach_seed_envelope: [u8; MACH_SEED_ENVELOPE_MAX_LEN], + /// Fixed-length fuzzed POTA thumbprint. + pota_thumbprint: [u8; POTA_THUMBPRINT_LEN], + /// Fixed-length fuzzed SATA thumbprint. + sata_thumbprint: [u8; SATA_THUMBPRINT_LEN], + /// Fixed-length fuzzed optional SAPOTA thumbprint. + sapota_thumbprint: [u8; SAPOTA_THUMBPRINT_LEN], +} + +fuzz_target!(|input: FuzzInput| { + let ctx = CTX.get_or_init(TestCtx::new); + ctx.erase().expect("erase should succeed"); + + let session = ctx + .open_session(CU, SessionType::PlainText) + .expect("session open should succeed"); + + let part_init_req = TborPartInitReq { + session_id: session.session_id(), + mach_seed_envelope: input.mach_seed_envelope.to_vec(), + part_policy: PartPolicy::zeroed(), + pota_thumbprint: input.pota_thumbprint, + sata_thumbprint: input.sata_thumbprint, + sapota_thumbprint: input.sapota_thumbprint.to_vec(), + }; + let _ = ctx.tbor(&part_init_req); + + session.close().expect("session close should succeed"); +}); From 65014a8b036b53fdb20b082c87be11b270885552 Mon Sep 17 00:00:00 2001 From: David Zimmermann Date: Thu, 20 Aug 2026 10:44:03 -0700 Subject: [PATCH 3/7] Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- fuzz/Cargo.toml | 2 +- fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index bd17109ea..7cf7ae55f 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -17,7 +17,7 @@ azihsm_ddi_tbor_test_harness = { features = [ "emu", ], path = "../crates/tbor_test_harness" } azihsm_ddi_tbor_types = { path = "../ddi/tbor/types" } -zerocopy = { features = ["derive"], version = "0.8.17" } +zerocopy = { version = "0.8.17" } # dependencies for fuzzing libfuzzer-sys = { features = ["arbitrary-derive"], version = "0.4" } diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs index 74501636a..c17a9aefa 100644 --- a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs @@ -26,7 +26,9 @@ struct FuzzInput { pota_thumbprint: [u8; POTA_THUMBPRINT_LEN], /// Fixed-length fuzzed SATA thumbprint. sata_thumbprint: [u8; SATA_THUMBPRINT_LEN], - /// Fixed-length fuzzed optional SAPOTA thumbprint. + /// Whether to include a SAPOTA thumbprint (empty = absent). + sapota_present: bool, + /// Fixed-length fuzzed SAPOTA thumbprint (used when `sapota_present`). sapota_thumbprint: [u8; SAPOTA_THUMBPRINT_LEN], } From 7d9fa07e638241d99c6b23198dccdfc76ff90317 Mon Sep 17 00:00:00 2001 From: David Zimmermann Date: Thu, 20 Aug 2026 17:03:02 -0700 Subject: [PATCH 4/7] in part init/final targets, open session w/ CO instead of CU --- fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs | 4 ++-- fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs index aa70ef7ad..68c91cdbd 100644 --- a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs @@ -16,7 +16,7 @@ use libfuzzer_sys::arbitrary::Arbitrary; use libfuzzer_sys::fuzz_target; use zerocopy::FromBytes; -const CU: u8 = 1; +const CO: u8 = 0; static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); #[derive(Arbitrary, Debug)] @@ -32,7 +32,7 @@ fuzz_target!(|input: FuzzInput| { ctx.erase().expect("erase should succeed"); let session = ctx - .open_session(CU, SessionType::PlainText) + .open_session(CO, SessionType::PlainText) .expect("session open should succeed"); // Reinterpret the fuzzed byte array as CertDescriptor slice. diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs index c17a9aefa..76ebb2a04 100644 --- a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs @@ -15,7 +15,7 @@ use libfuzzer_sys::arbitrary; use libfuzzer_sys::arbitrary::Arbitrary; use libfuzzer_sys::fuzz_target; -const CU: u8 = 1; +const CO: u8 = 0; static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); #[derive(Arbitrary, Debug)] @@ -37,7 +37,7 @@ fuzz_target!(|input: FuzzInput| { ctx.erase().expect("erase should succeed"); let session = ctx - .open_session(CU, SessionType::PlainText) + .open_session(CO, SessionType::PlainText) .expect("session open should succeed"); let part_init_req = TborPartInitReq { From 787af599628c1a7ae314e107d0f6a9aa941f262a Mon Sep 17 00:00:00 2001 From: David Zimmermann Date: Sun, 23 Aug 2026 19:31:51 -0700 Subject: [PATCH 5/7] copilot feedback --- .../ddi/tbor/fuzz_tbor_part_final.rs | 132 ++++++++++++++---- .../ddi/tbor/fuzz_tbor_part_init.rs | 10 +- 2 files changed, 110 insertions(+), 32 deletions(-) diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs index 68c91cdbd..66946f5d0 100644 --- a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs @@ -3,52 +3,124 @@ #![no_main] +use azihsm_ddi_tbor_test_harness::SessionOpenInitOptions; use azihsm_ddi_tbor_test_harness::TestCtx; -use azihsm_ddi_tbor_types::CERT_DESCRIPTOR_LEN; -use azihsm_ddi_tbor_types::CertDescriptor; -use azihsm_ddi_tbor_types::LOCAL_MK_BACKUP_LEN; -use azihsm_ddi_tbor_types::MAX_CERTS; -use azihsm_ddi_tbor_types::PartPolicy; +use azihsm_ddi_tbor_test_harness::x509_fixture::CaKey; +use azihsm_ddi_tbor_test_harness::x509_fixture::make_pta_chain; +use azihsm_ddi_tbor_test_harness::x509_fixture::pta_pub_from_csr; +use azihsm_ddi_tbor_types::MACH_SEED_LEN; +use azihsm_ddi_tbor_types::PART_POLICY_LEN; +use azihsm_ddi_tbor_types::POTA_THUMBPRINT_LEN; +use azihsm_ddi_tbor_types::PSK_LEN; +use azihsm_ddi_tbor_types::PolicyKeyKind; use azihsm_ddi_tbor_types::SessionType; -use azihsm_ddi_tbor_types::TborPartFinalReq; use libfuzzer_sys::arbitrary; use libfuzzer_sys::arbitrary::Arbitrary; use libfuzzer_sys::fuzz_target; -use zerocopy::FromBytes; const CO: u8 = 0; + +/// Non-default CO PSK used to clear the default-PSK gate before `PartInit`. +const ROTATED_CO_PSK: [u8; PSK_LEN] = [ + 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, + 0xBF, 0xC0, +]; + static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); #[derive(Arbitrary, Debug)] struct FuzzInput { - /// Fixed-length fuzzed cert_descriptors buffer. - cert_descriptors: [u8; MAX_CERTS * CERT_DESCRIPTOR_LEN], - /// Fixed-length fuzzed prev_local_mk_backup buffer. - prev_local_mk_backup: [u8; LOCAL_MK_BACKUP_LEN], + /// Fuzzed prior local_mk backup (empty = first-instantiation path). + prev_local_mk_backup: Vec, +} + +/// Build a `PartPolicy` with `pota_raw` (raw P-384 `X ‖ Y`) as the POTA +/// trust anchor so `PartFinal` can validate the cert chain against it. +fn part_policy_with_pota(pota_raw: &[u8; 96]) -> [u8; PART_POLICY_LEN] { + const OFF_POTA: usize = 2; + const OFF_SATA: usize = 102; + const OFF_FLAGS: usize = 418; + const OFF_INFO: usize = 419; + + fn write_pubkey(bytes: &mut [u8], off: usize, fill: u8) { + bytes[off..off + 2].copy_from_slice(&PolicyKeyKind::Ecc384.0.to_le_bytes()); + bytes[off + 2..off + 4].copy_from_slice(&96u16.to_le_bytes()); + for (i, b) in bytes[off + 4..off + 4 + 96].iter_mut().enumerate() { + *b = (fill.wrapping_add(i as u8)) | 0x80; + } + } + + let mut bytes = [0u8; PART_POLICY_LEN]; + bytes[0] = 1; // version major + bytes[1] = 0; // version minor + write_pubkey(&mut bytes, OFF_POTA, 0x10); + write_pubkey(&mut bytes, OFF_SATA, 0x20); + bytes[OFF_FLAGS] = 0; + for b in bytes[OFF_INFO..OFF_INFO + 64].iter_mut() { + *b = 0xAB; + } + // Overwrite the POTA key data with the real public key. + bytes[OFF_POTA + 4..OFF_POTA + 4 + 96].copy_from_slice(pota_raw); + bytes +} + +fn mach_seed() -> [u8; MACH_SEED_LEN] { + let mut v = [0u8; MACH_SEED_LEN]; + for (i, b) in v.iter_mut().enumerate() { + *b = 0x40 + i as u8; + } + v +} + +fn pota_thumbprint() -> [u8; POTA_THUMBPRINT_LEN] { + let mut v = [0u8; POTA_THUMBPRINT_LEN]; + for (i, b) in v.iter_mut().enumerate() { + *b = 0x80 ^ i as u8; + } + v } fuzz_target!(|input: FuzzInput| { let ctx = CTX.get_or_init(TestCtx::new); ctx.erase().expect("erase should succeed"); + // Rotate the CO PSK to clear the default-PSK gate before PartInit. + let bootstrap = ctx + .open_session(CO, SessionType::Authenticated) + .expect("bootstrap session open should succeed"); + ctx.psk_change(bootstrap.handshake(), &ROTATED_CO_PSK) + .expect("PSK rotation should succeed"); + bootstrap.close().expect("bootstrap session close should succeed"); + + // Open a CO session under the rotated PSK. + let opts = + SessionOpenInitOptions::new(CO, SessionType::Authenticated).with_psk(&ROTATED_CO_PSK); + let pending = ctx + .session_open_init_with_options(opts) + .expect("session_open_init should succeed"); let session = ctx - .open_session(CO, SessionType::PlainText) - .expect("session open should succeed"); - - // Reinterpret the fuzzed byte array as CertDescriptor slice. - let cert_descriptors: Vec = input - .cert_descriptors - .chunks_exact(CERT_DESCRIPTOR_LEN) - .map(|chunk| CertDescriptor::read_from_bytes(chunk).unwrap()) - .collect(); - - let part_final_req = TborPartFinalReq { - session_id: session.session_id(), - part_policy: PartPolicy::zeroed(), - cert_descriptors, - prev_local_mk_backup: input.prev_local_mk_backup.to_vec(), - }; - let _ = ctx.tbor(&part_final_req); - - session.close().expect("session close should succeed"); + .session_open_finish(pending) + .expect("session_open_finish should succeed"); + + // Generate a POTA trust anchor and embed its public key in the policy. + let pota = CaKey::generate(); + let policy = part_policy_with_pota(&pota.raw_pub()); + + // PartInit: transition the partition to PartState::Initializing. + let init = ctx + .part_init(&session, &mach_seed(), &policy, &pota_thumbprint()) + .expect("PartInit should succeed"); + + // Build a valid PTA cert chain anchored to the POTA key, using the CSR + // returned by PartInit to certify the correct partition PTA public key. + let pta_pub = pta_pub_from_csr(&init.pta_csr); + let chain = make_pta_chain(&pota, &pta_pub); + + // PartFinal: the valid chain clears both the lifecycle and OOB gates, + // so the fuzzed prev_local_mk_backup reaches the handler logic. + let _ = ctx.part_final(&session, &policy, &input.prev_local_mk_backup, &chain.der_items()); + + ctx.session_close(session.session_id) + .expect("session close should succeed"); }); diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs index 76ebb2a04..98b4f064b 100644 --- a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_init.rs @@ -37,16 +37,22 @@ fuzz_target!(|input: FuzzInput| { ctx.erase().expect("erase should succeed"); let session = ctx - .open_session(CO, SessionType::PlainText) + .open_session(CO, SessionType::Authenticated) .expect("session open should succeed"); + let sapota_thumbprint = if input.sapota_present { + input.sapota_thumbprint.to_vec() + } else { + Vec::new() + }; + let part_init_req = TborPartInitReq { session_id: session.session_id(), mach_seed_envelope: input.mach_seed_envelope.to_vec(), part_policy: PartPolicy::zeroed(), pota_thumbprint: input.pota_thumbprint, sata_thumbprint: input.sata_thumbprint, - sapota_thumbprint: input.sapota_thumbprint.to_vec(), + sapota_thumbprint, }; let _ = ctx.tbor(&part_init_req); From 4b0d1dacb347060e06de2cccd0f93215d8209899 Mon Sep 17 00:00:00 2001 From: David Zimmermann Date: Tue, 25 Aug 2026 14:26:15 -0700 Subject: [PATCH 6/7] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs index 66946f5d0..9bef96040 100644 --- a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs @@ -29,9 +29,17 @@ const ROTATED_CO_PSK: [u8; PSK_LEN] = [ static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); +fn bounded_prev_local_mk_backup(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result> { + // Keep allocations bounded to improve fuzz throughput while still exercising invalid lengths. + let max = azihsm_ddi_tbor_types::LOCAL_MK_BACKUP_LEN * 4; + let len = usize::arbitrary(u)? % (max + 1); + Ok(u.bytes(len)?.to_vec()) +} + #[derive(Arbitrary, Debug)] struct FuzzInput { /// Fuzzed prior local_mk backup (empty = first-instantiation path). + #[arbitrary(with = bounded_prev_local_mk_backup)] prev_local_mk_backup: Vec, } From 41a5973db4b88a60d75e339db00779625e5079c1 Mon Sep 17 00:00:00 2001 From: David Zimmermann Date: Wed, 26 Aug 2026 17:19:32 -0700 Subject: [PATCH 7/7] add fuzz_tbor_part_info --- fuzz/Cargo.toml | 7 +++++++ .../fuzz_targets/ddi/tbor/fuzz_tbor_part_info.rs | 16 ++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_info.rs diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 7cf7ae55f..296a9b7cf 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -112,3 +112,10 @@ doc = false name = "fuzz_tbor_part_final" path = "fuzz_targets/ddi/tbor/fuzz_tbor_part_final.rs" test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_part_info" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_part_info.rs" +test = false diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_info.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_info.rs new file mode 100644 index 000000000..60ee9bf93 --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_part_info.rs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +#[path = "../../common.rs"] +mod common; + +use azihsm_ddi_tbor_types::TborPartInfoReq; +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|_input: &[u8]| { + let dev = common::open_emu_dev(); + let req = TborPartInfoReq; + common::fuzz_exec_op_tbor(&dev, &req); +});