From 96ba3027a027fe3540b7251c5c4ba28d68716442 Mon Sep 17 00:00:00 2001 From: Siva Date: Thu, 30 Jul 2026 18:37:38 +0000 Subject: [PATCH 01/10] Enable the retry for cert during IDFU --- ddi/mbor/types/tests/integration/common.rs | 121 ++++++++++++++++++--- 1 file changed, 105 insertions(+), 16 deletions(-) diff --git a/ddi/mbor/types/tests/integration/common.rs b/ddi/mbor/types/tests/integration/common.rs index 1e502acac..5ced970a1 100644 --- a/ddi/mbor/types/tests/integration/common.rs +++ b/ddi/mbor/types/tests/integration/common.rs @@ -177,19 +177,91 @@ pub fn helper_verify_cert_chain(collaterals: &[Vec]) -> Result::Dev) -> Vec { - let result = helper_get_cert_chain_info(dev); - assert!(result.is_ok(), "result {:?}", result); - let resp = result.unwrap(); - let num_certs = resp.data.num_certs; +/// Retrieves the device's leaf certificate with retry logic to handle transient +/// `InvalidCertificate` errors that occur during concurrent iDFU (softreset) operations. +/// Retries the `get_cert` call every 50ms until it succeeds or the specified +/// `retry_secs` window elapses. Returns the last result (success or error). + fn helper_get_cert_with_retry( + dev: &::Dev, + retry_secs: u64, + ) -> Result { + let start = std::time::Instant::now(); + let retry_window = std::time::Duration::from_secs(retry_secs); + let mut result; - // The leaf certificate is the partition ID cert - let result = helper_get_certificate(dev, num_certs - 1); - assert!(result.is_ok(), "result {:?}", result); - let resp = result.unwrap(); + loop { + tracing::debug!("Get Certificate"); + + let cert_info = helper_get_cert_chain_info(dev); + assert!(cert_info.is_ok(), "cert_info {:?}", cert_info); + let resp = cert_info.unwrap(); + let num_certs = resp.data.num_certs; + + result = helper_get_certificate(dev, num_certs - 1); + + if let Err(DdiError::DdiStatus(DdiStatus::InvalidCertificate)) = &result { + if start.elapsed() > retry_window { + break; + } + println!("Retrying the get_cert operation"); + std::thread::sleep(std::time::Duration::from_millis(50)); + } else { + break; + } + } + result + +} + /// Retrieves a certificate by ID with retry logic to handle transient + /// `InvalidCertificate` errors during concurrent iDFU (softreset) operations. + /// Retries every 50ms until success or `retry_secs` elapses. + fn helper_get_cert_by_id_with_retry( + dev: &::Dev, + cert_id: u8, + retry_secs: u64, + ) -> Result { + let start = std::time::Instant::now(); + let retry_window = std::time::Duration::from_secs(retry_secs); + let mut result; + + loop { + tracing::debug!("Get Certificate id={}", cert_id); + + result = helper_get_certificate(dev, cert_id); + + if let Err(DdiError::DdiStatus(DdiStatus::InvalidCertificate)) = &result { + if start.elapsed() > retry_window { + break; + } + println!("Retrying the get_cert operation for cert_id {}", cert_id); + std::thread::sleep(std::time::Duration::from_millis(50)); + } else { + break; + } + } + result + } + +#[allow(dead_code)] +pub fn helper_get_partition_id_pub_key(dev: &mut ::Dev) -> Vec { + let idfu_enabled = std::env::var("IDFU").map(|v| v == "1").unwrap_or(false); + + let resp = if idfu_enabled { + tracing::debug!("Device is in IDfu mode"); + helper_get_cert_with_retry(dev, 5).unwrap() + } else { + tracing::debug!("Device is not in IDfu mode"); + let result = helper_get_cert_chain_info(dev); + assert!(result.is_ok(), "result {:?}", result); + let chain_resp = result.unwrap(); + let num_certs = chain_resp.data.num_certs; + let result = helper_get_certificate(dev, num_certs - 1); + assert!(result.is_ok(), "result {:?}", result); + result.unwrap() + }; + let cert_der = resp.data.certificate.as_slice(); // Verify the leaf cert with the cert chain to ensure it is valid @@ -272,6 +344,7 @@ pub fn helper_verify_leaf_cert( // cert id is 0 to num_certs - 1. // 3. Gets the partition id cert using DDI command GetCertificate which is the last cert in the chain + let idfu_enabled = std::env::var("IDFU").map(|v| v == "1").unwrap_or(false); let result = helper_get_cert_chain_info(dev); assert!(result.is_ok(), "result {:?}", result); @@ -280,10 +353,19 @@ pub fn helper_verify_leaf_cert( let mut cert_chain: Vec> = Vec::with_capacity(num_certs as usize); for i in 0..num_certs - 1 { - let result = helper_get_certificate(dev, i); - assert!(result.is_ok(), "result {:?}", result); - - let resp = result.unwrap(); + let resp = if idfu_enabled { + tracing::debug!("Device is in IDfu mode, retrying get_certificate for cert {}", i); + helper_get_cert_by_id_with_retry(dev, i, 5).unwrap() + } else { + let result = helper_get_certificate(dev, i); + assert!(result.is_ok(), "result {:?}", result); + result.unwrap() + }; + + // let result: Result = helper_get_certificate(dev, i); + // assert!(result.is_ok(), "result {:?}", result); + + // let resp = result.unwrap(); let der = &resp.data.certificate.as_slice(); print!("cert DER {:?}", der); @@ -298,9 +380,16 @@ pub fn helper_verify_leaf_cert( } pub fn helper_get_pota_endorsement(dev: &::Dev) -> (Vec, Vec) { + let idfu_enabled = std::env::var("IDFU").map(|v| v == "1").unwrap_or(false); let get_cert_chain_info = helper_get_cert_chain_info(dev).unwrap(); - // Get last cert - let cert_resp = helper_get_certificate(dev, get_cert_chain_info.data.num_certs - 1).unwrap(); + let leaf_cert_id = get_cert_chain_info.data.num_certs - 1; + let cert_resp = if idfu_enabled { + tracing::debug!("Device is in IDfu mode"); + helper_get_cert_by_id_with_retry(dev, leaf_cert_id, 5).unwrap() + } else { + tracing::debug!("Device is not in IDfu mode"); + helper_get_certificate(dev, get_cert_chain_info.data.num_certs - 1).unwrap() + }; let cert = cert_resp.data.certificate.as_slice(); let cert = X509Certificate::from_der(cert).unwrap(); let cert_pub_key_der = cert.get_public_key_der().unwrap(); From 072bb475cbcd08461cd6e498ea7dce7acef5464b Mon Sep 17 00:00:00 2001 From: Siva Date: Thu, 30 Jul 2026 22:45:38 +0000 Subject: [PATCH 02/10] increase the retry window --- ddi/mbor/types/tests/integration/common.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ddi/mbor/types/tests/integration/common.rs b/ddi/mbor/types/tests/integration/common.rs index 5ced970a1..db959ea22 100644 --- a/ddi/mbor/types/tests/integration/common.rs +++ b/ddi/mbor/types/tests/integration/common.rs @@ -250,7 +250,7 @@ pub fn helper_get_partition_id_pub_key(dev: &mut ::Dev) -> Vec::Dev) -> (Vec, Vec let leaf_cert_id = get_cert_chain_info.data.num_certs - 1; let cert_resp = if idfu_enabled { tracing::debug!("Device is in IDfu mode"); - helper_get_cert_by_id_with_retry(dev, leaf_cert_id, 5).unwrap() + helper_get_cert_by_id_with_retry(dev, leaf_cert_id, 9).unwrap() } else { tracing::debug!("Device is not in IDfu mode"); helper_get_certificate(dev, get_cert_chain_info.data.num_certs - 1).unwrap() From 1efd291ba658b2e924f2bdfe03a3d21b9767660c Mon Sep 17 00:00:00 2001 From: Siva Date: Fri, 31 Jul 2026 19:31:19 +0000 Subject: [PATCH 03/10] increase the retry window --- ddi/mbor/types/tests/integration/common.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ddi/mbor/types/tests/integration/common.rs b/ddi/mbor/types/tests/integration/common.rs index db959ea22..bb5ff36cc 100644 --- a/ddi/mbor/types/tests/integration/common.rs +++ b/ddi/mbor/types/tests/integration/common.rs @@ -250,7 +250,7 @@ pub fn helper_get_partition_id_pub_key(dev: &mut ::Dev) -> Vec::Dev) -> (Vec, Vec let leaf_cert_id = get_cert_chain_info.data.num_certs - 1; let cert_resp = if idfu_enabled { tracing::debug!("Device is in IDfu mode"); - helper_get_cert_by_id_with_retry(dev, leaf_cert_id, 9).unwrap() + helper_get_cert_by_id_with_retry(dev, leaf_cert_id, 15).unwrap() } else { tracing::debug!("Device is not in IDfu mode"); helper_get_certificate(dev, get_cert_chain_info.data.num_certs - 1).unwrap() From 49e4068faba2fa99a8e6ae7d0436ebbee9cf7980 Mon Sep 17 00:00:00 2001 From: Siva Parvathi Date: Mon, 3 Aug 2026 23:01:47 +0000 Subject: [PATCH 04/10] Modify the get cert retry method --- ddi/mbor/types/tests/integration/common.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ddi/mbor/types/tests/integration/common.rs b/ddi/mbor/types/tests/integration/common.rs index bb5ff36cc..ce00132db 100644 --- a/ddi/mbor/types/tests/integration/common.rs +++ b/ddi/mbor/types/tests/integration/common.rs @@ -355,7 +355,7 @@ pub fn helper_verify_leaf_cert( for i in 0..num_certs - 1 { let resp = if idfu_enabled { tracing::debug!("Device is in IDfu mode, retrying get_certificate for cert {}", i); - helper_get_cert_by_id_with_retry(dev, i, 15).unwrap() + helper_get_cert_with_retry(dev, 15).unwrap() } else { let result = helper_get_certificate(dev, i); assert!(result.is_ok(), "result {:?}", result); @@ -385,7 +385,7 @@ pub fn helper_get_pota_endorsement(dev: &::Dev) -> (Vec, Vec let leaf_cert_id = get_cert_chain_info.data.num_certs - 1; let cert_resp = if idfu_enabled { tracing::debug!("Device is in IDfu mode"); - helper_get_cert_by_id_with_retry(dev, leaf_cert_id, 15).unwrap() + helper_get_cert_with_retry(dev, 15).unwrap() } else { tracing::debug!("Device is not in IDfu mode"); helper_get_certificate(dev, get_cert_chain_info.data.num_certs - 1).unwrap() From 539f513d136b94ad62733e49417720b91e04869b Mon Sep 17 00:00:00 2001 From: Siva Parvathi Date: Mon, 3 Aug 2026 23:26:25 +0000 Subject: [PATCH 05/10] Cleanup --- ddi/mbor/types/tests/integration/common.rs | 48 +++++++++++----------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/ddi/mbor/types/tests/integration/common.rs b/ddi/mbor/types/tests/integration/common.rs index ce00132db..cc50c84be 100644 --- a/ddi/mbor/types/tests/integration/common.rs +++ b/ddi/mbor/types/tests/integration/common.rs @@ -217,32 +217,32 @@ pub fn helper_verify_cert_chain(collaterals: &[Vec]) -> Result::Dev, - cert_id: u8, - retry_secs: u64, - ) -> Result { - let start = std::time::Instant::now(); - let retry_window = std::time::Duration::from_secs(retry_secs); - let mut result; +// fn helper_get_cert_by_id_with_retry( +// dev: &::Dev, +// cert_id: u8, +// retry_secs: u64, +// ) -> Result { +// let start = std::time::Instant::now(); +// let retry_window = std::time::Duration::from_secs(retry_secs); +// let mut result; - loop { - tracing::debug!("Get Certificate id={}", cert_id); +// loop { +// tracing::debug!("Get Certificate id={}", cert_id); - result = helper_get_certificate(dev, cert_id); +// result = helper_get_certificate(dev, cert_id); - if let Err(DdiError::DdiStatus(DdiStatus::InvalidCertificate)) = &result { - if start.elapsed() > retry_window { - break; - } - println!("Retrying the get_cert operation for cert_id {}", cert_id); - std::thread::sleep(std::time::Duration::from_millis(50)); - } else { - break; - } - } - result - } +// if let Err(DdiError::DdiStatus(DdiStatus::InvalidCertificate)) = &result { +// if start.elapsed() > retry_window { +// break; +// } +// println!("Retrying the get_cert operation for cert_id {}", cert_id); +// std::thread::sleep(std::time::Duration::from_millis(50)); +// } else { +// break; +// } +// } +// result +// } #[allow(dead_code)] pub fn helper_get_partition_id_pub_key(dev: &mut ::Dev) -> Vec { @@ -382,7 +382,7 @@ pub fn helper_verify_leaf_cert( pub fn helper_get_pota_endorsement(dev: &::Dev) -> (Vec, Vec) { let idfu_enabled = std::env::var("IDFU").map(|v| v == "1").unwrap_or(false); let get_cert_chain_info = helper_get_cert_chain_info(dev).unwrap(); - let leaf_cert_id = get_cert_chain_info.data.num_certs - 1; + // let leaf_cert_id = get_cert_chain_info.data.num_certs - 1; let cert_resp = if idfu_enabled { tracing::debug!("Device is in IDfu mode"); helper_get_cert_with_retry(dev, 15).unwrap() From e9abff9f8d5cc2e5bc26cf193c57311a1e54545e Mon Sep 17 00:00:00 2001 From: Siva Parvathi Date: Tue, 4 Aug 2026 15:26:50 +0000 Subject: [PATCH 06/10] enable retry in get_cert_chain --- .../types/tests/integration/get_cert_chain.rs | 75 +++++++++++++++++-- 1 file changed, 70 insertions(+), 5 deletions(-) diff --git a/ddi/mbor/types/tests/integration/get_cert_chain.rs b/ddi/mbor/types/tests/integration/get_cert_chain.rs index 4a0e3609f..2a12b726e 100644 --- a/ddi/mbor/types/tests/integration/get_cert_chain.rs +++ b/ddi/mbor/types/tests/integration/get_cert_chain.rs @@ -11,6 +11,63 @@ use test_with_tracing::test; use super::common::*; + + + fn helper_get_certificate_chain_retry(dev: &mut ::Dev) -> (u8, [u8; 32]) { + let idfu_enabled = std::env::var("IDFU").map(|v| v == "1").unwrap_or(false); + let start = std::time::Instant::now(); + let retry_window = std::time::Duration::from_secs(15); + + loop { + let (num_certs, thumbprint) = helper_get_cert_chain_info_data(dev); + + assert!( + num_certs > 0, + "a provisioned partition must report at least one certificate" + ); + assert!( + thumbprint.iter().any(|&b| b != 0), + "thumbprint must not be all zeros" + ); + + let mut got_invalid_cert = false; + + for cert_id in 0..num_certs { + let result = helper_get_certificate(dev, cert_id); + + if idfu_enabled { + if let Err(DdiError::DdiStatus(DdiStatus::InvalidCertificate)) = &result { + got_invalid_cert = true; + break; + } + } + + assert!(result.is_ok(), "result {:?}", result); + + let resp = result.unwrap(); + assert!( + !resp.data.certificate.as_slice().is_empty(), + "certificate {} must not be empty", + cert_id + ); + } + + if got_invalid_cert { + if start.elapsed() > retry_window { + panic!("get_certificate still returning InvalidCertificate after {:?}", start.elapsed()); + } + println!("InvalidCertificate during cert fetch, retrying from chain info..."); + std::thread::sleep(std::time::Duration::from_millis(500)); + continue; + } + + let (num_certs_after, thumbprint_after) = helper_get_cert_chain_info_data(dev); + assert_eq!(num_certs, num_certs_after, "cert count must be stable across the fetch"); + assert_eq!(thumbprint, thumbprint_after, "thumbprint must be stable across the fetch"); + + return (num_certs, thumbprint); + } + } /// Fetch the full certificate chain and validate the properties the host /// SDK actually relies on. /// @@ -73,8 +130,12 @@ fn test_get_certificate_chain() { |dev, _ddi, _path, session_id| { close_app_session(dev, session_id); - helper_get_certificate_chain(dev); - }, + let idfu_enabled = std::env::var("IDFU").map(|v| v == "1").unwrap_or(false); + if idfu_enabled { + helper_get_certificate_chain_retry(dev); + } else { + helper_get_certificate_chain(dev); + } }, ); } @@ -128,21 +189,25 @@ fn test_get_cert_chain_multithread() { Some(DdiApiRev { major: 1, minor: 0 }), ); assert!(resp.is_ok(), "resp: {:?}", resp); - + let idfu_enabled = std::env::var("IDFU").map(|v| v == "1").unwrap_or(false); let mut threads = Vec::new(); let thread_count = MAX_SESSIONS - 1; println!("Thread count: {}", thread_count); for _ in 0..thread_count { let device_path = path.to_string(); - + let idfu = idfu_enabled; let thread = thread::spawn(move || { let ddi = DdiTest::default(); let mut dev = ddi.open_dev(device_path.as_str()).unwrap(); thread::sleep(std::time::Duration::from_secs(2)); - let (num_certs, thumbprint) = helper_get_certificate_chain(&mut dev); + let (num_certs, thumbprint) = if idfu { + helper_get_certificate_chain_retry(&mut dev) + } else { + helper_get_certificate_chain(&mut dev) + }; thread::sleep(std::time::Duration::from_secs(1)); From e56fb40fae25b480b7cafcc606da4be12b07f3a8 Mon Sep 17 00:00:00 2001 From: Siva Parvathi Date: Tue, 4 Aug 2026 19:06:47 +0000 Subject: [PATCH 07/10] Update the idfu enabled retry for get_certs_after_lm --- ddi/mbor/types/tests/integration/common.rs | 2 +- .../tests/integration/live_migration_expected_errors.rs | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ddi/mbor/types/tests/integration/common.rs b/ddi/mbor/types/tests/integration/common.rs index cc50c84be..17eab973c 100644 --- a/ddi/mbor/types/tests/integration/common.rs +++ b/ddi/mbor/types/tests/integration/common.rs @@ -182,7 +182,7 @@ pub fn helper_verify_cert_chain(collaterals: &[Vec]) -> Result::Dev, retry_secs: u64, ) -> Result { diff --git a/ddi/mbor/types/tests/integration/live_migration_expected_errors.rs b/ddi/mbor/types/tests/integration/live_migration_expected_errors.rs index 189012921..fc1a730a3 100644 --- a/ddi/mbor/types/tests/integration/live_migration_expected_errors.rs +++ b/ddi/mbor/types/tests/integration/live_migration_expected_errors.rs @@ -252,7 +252,12 @@ fn test_get_cert_after_lm() { result ); - let resp = helper_get_certificate(dev, cert_info.data.num_certs - 1); + let idfu_enabled = std::env::var("IDFU").map(|v| v == "1").unwrap_or(false); + let resp = if idfu_enabled { + helper_get_cert_with_retry(dev, 15) + } else { + helper_get_certificate(dev, cert_info.data.num_certs - 1) + }; assert!(resp.is_ok(), "resp {:?}", resp); }); From 498f1d45808e2863f9e51c88126abeae302d54f9 Mon Sep 17 00:00:00 2001 From: Siva Parvathi Date: Tue, 4 Aug 2026 19:38:57 +0000 Subject: [PATCH 08/10] Update the retry with id for leaf_cert --- ddi/mbor/types/tests/integration/common.rs | 48 +++++++++++----------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/ddi/mbor/types/tests/integration/common.rs b/ddi/mbor/types/tests/integration/common.rs index 17eab973c..779d62676 100644 --- a/ddi/mbor/types/tests/integration/common.rs +++ b/ddi/mbor/types/tests/integration/common.rs @@ -217,32 +217,32 @@ pub fn helper_get_cert_with_retry( /// Retrieves a certificate by ID with retry logic to handle transient /// `InvalidCertificate` errors during concurrent iDFU (softreset) operations. /// Retries every 50ms until success or `retry_secs` elapses. -// fn helper_get_cert_by_id_with_retry( -// dev: &::Dev, -// cert_id: u8, -// retry_secs: u64, -// ) -> Result { -// let start = std::time::Instant::now(); -// let retry_window = std::time::Duration::from_secs(retry_secs); -// let mut result; + fn helper_get_cert_by_id_with_retry( + dev: &::Dev, + cert_id: u8, + retry_secs: u64, + ) -> Result { + let start = std::time::Instant::now(); + let retry_window = std::time::Duration::from_secs(retry_secs); + let mut result; -// loop { -// tracing::debug!("Get Certificate id={}", cert_id); + loop { + tracing::debug!("Get Certificate id={}", cert_id); -// result = helper_get_certificate(dev, cert_id); + result = helper_get_certificate(dev, cert_id); -// if let Err(DdiError::DdiStatus(DdiStatus::InvalidCertificate)) = &result { -// if start.elapsed() > retry_window { -// break; -// } -// println!("Retrying the get_cert operation for cert_id {}", cert_id); -// std::thread::sleep(std::time::Duration::from_millis(50)); -// } else { -// break; -// } -// } -// result -// } + if let Err(DdiError::DdiStatus(DdiStatus::InvalidCertificate)) = &result { + if start.elapsed() > retry_window { + break; + } + println!("Retrying the get_cert operation for cert_id {}", cert_id); + std::thread::sleep(std::time::Duration::from_millis(50)); + } else { + break; + } + } + result + } #[allow(dead_code)] pub fn helper_get_partition_id_pub_key(dev: &mut ::Dev) -> Vec { @@ -355,7 +355,7 @@ pub fn helper_verify_leaf_cert( for i in 0..num_certs - 1 { let resp = if idfu_enabled { tracing::debug!("Device is in IDfu mode, retrying get_certificate for cert {}", i); - helper_get_cert_with_retry(dev, 15).unwrap() + helper_get_cert_by_id_with_retry(dev,i, 15).unwrap() } else { let result = helper_get_certificate(dev, i); assert!(result.is_ok(), "result {:?}", result); From 31f6f97ad9c17e06f337b31f756d798ec1e2de9e Mon Sep 17 00:00:00 2001 From: Siva Parvathi Date: Tue, 4 Aug 2026 19:54:49 +0000 Subject: [PATCH 09/10] Enable the refetch of thumbprint as part of get_cert_chain_info to handle the thumbprint mismatch as part of idfu --- .../types/tests/integration/get_cert_chain.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/ddi/mbor/types/tests/integration/get_cert_chain.rs b/ddi/mbor/types/tests/integration/get_cert_chain.rs index 2a12b726e..234718260 100644 --- a/ddi/mbor/types/tests/integration/get_cert_chain.rs +++ b/ddi/mbor/types/tests/integration/get_cert_chain.rs @@ -281,6 +281,7 @@ fn test_get_cert_chain_info_multithread() { // Collect and compare the results let mut prev_num_cert = None; let mut prev_thumbprint = [0u8; 32]; + let idfu_enabled = std::env::var("IDFU").map(|v| v == "1").unwrap_or(false); for thread in threads { let result = thread.join(); assert!(result.is_ok(), "result {:?}", result); @@ -289,8 +290,19 @@ fn test_get_cert_chain_info_multithread() { match prev_num_cert { Some(prev) => { assert_eq!(prev, num_cert); - assert_eq!(prev_thumbprint, thumbprint); - } + if prev_thumbprint != thumbprint && idfu_enabled { + println!("Thumbprint mismatch during IDFU, refetching..."); + // Refetch chain info to get the current thumbprint + let fresh = helper_get_cert_chain_info(dev).unwrap(); + let fresh_thumbprint = fresh.data.thumbprint.data_take(); + assert_eq!(fresh_thumbprint, thumbprint, + "Refetched thumbprint should match the latest thread result"); + prev_thumbprint = fresh_thumbprint; + + } else { + assert_eq!(prev_thumbprint, thumbprint); + } + } None => { prev_num_cert = Some(num_cert); prev_thumbprint = thumbprint; From dc18eaf6ed088a177738ea8df71422eb1fdb4f85 Mon Sep 17 00:00:00 2001 From: Siva Parvathi Date: Tue, 4 Aug 2026 21:23:52 +0000 Subject: [PATCH 10/10] Enabled the idfu based retry for attest_key.rs --- .../types/tests/integration/attest_key.rs | 74 ++++++++++++------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/ddi/mbor/types/tests/integration/attest_key.rs b/ddi/mbor/types/tests/integration/attest_key.rs index bd647ce58..83b4a72d6 100644 --- a/ddi/mbor/types/tests/integration/attest_key.rs +++ b/ddi/mbor/types/tests/integration/attest_key.rs @@ -842,34 +842,52 @@ fn test_attest_kbkdf_derived_aes_key() { /// Helper function to get certificate chain pub(crate) fn helper_get_cert_chain(dev: &mut ::Dev) -> Vec> { - tracing::debug!("Getting certificate chain"); - // Gets the cert chain - // 1. Gets the number of certs in the cert chain using DDI command GetCertChainInfo command - // 2. Gets all certs in the cert chain using DDI command GetCertificate where - // cert id is 0 to num_certs - 1. - // 3. Gets the partition id cert using DDI command GetCertificate which is the last cert in the chain - - let result = helper_get_cert_chain_info(dev); - assert!(result.is_ok(), "result {:?}", result); - - let resp = result.unwrap(); - let num_certs = resp.data.num_certs; - - let mut cert_chain: Vec> = Vec::with_capacity(num_certs as usize); - for i in 0..num_certs { - let result = helper_get_certificate(dev, i); - assert!(result.is_ok(), "result {:?}", result); - - let resp = result.unwrap(); - let der = &resp.data.certificate.as_slice(); - print!("cert DER {:?}", der); - - cert_chain.push(der.to_vec()); - } - - tracing::debug!(len = cert_chain.len(), "Done getting cert chain"); - cert_chain -} + let idfu_enabled = std::env::var("IDFU").map(|v| v == "1").unwrap_or(false); + let start = std::time::Instant::now(); + let retry_window = std::time::Duration::from_secs(15); + + loop { + let result = helper_get_cert_chain_info(dev); + assert!(result.is_ok(), "result {:?}", result); + + let resp = result.unwrap(); + let num_certs = resp.data.num_certs; + + let mut cert_chain: Vec> = Vec::with_capacity(num_certs as usize); + let mut got_invalid_cert = false; + + for i in 0..num_certs { + let result = helper_get_certificate(dev, i); + + if idfu_enabled { + if let Err(DdiError::DdiStatus(DdiStatus::InvalidCertificate)) = &result { + got_invalid_cert = true; + break; + } + } + + assert!(result.is_ok(), "result {:?}", result); + + let resp = result.unwrap(); + let der = &resp.data.certificate.as_slice(); + print!("cert DER {:?}", der); + + cert_chain.push(der.to_vec()); + } + + if got_invalid_cert { + if start.elapsed() > retry_window { + panic!("get_certificate still returning InvalidCertificate after {:?}", start.elapsed()); + } + println!("InvalidCertificate in attest_key cert chain fetch, retrying..."); + std::thread::sleep(std::time::Duration::from_millis(500)); + continue; + } + + tracing::debug!(len = cert_chain.len(), "Done getting cert chain"); + return cert_chain; + } + } fn import_rsa_key(dev: &mut ::Dev, session_id: u16) -> (u16, Vec) { let (unwrap_key_id, unwrap_pub_key_der, _) = get_unwrapping_key(dev, session_id);