mirror of
https://github.com/matter-labs/teepot.git
synced 2025-07-21 23:23:57 +02:00
feat(intel-dcap-api): add comprehensive testing infrastructure and examples
- Add mock tests using real Intel API response data (25 tests) - Create fetch_test_data tool to retrieve real API responses for testing - Add integration_test example covering 17 API endpoints - Add common_usage example demonstrating attestation verification patterns - Add issuer chain validation checks to ensure signature verification is possible - Add comprehensive documentation in CLAUDE.md The test suite now covers all major Intel DCAP API functionality including TCB info, enclave identities, PCK CRLs, FMSPCs, and evaluation data numbers for both SGX and TDX platforms across API v3 and v4. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Harald Hoyer <harald@matterlabs.dev>
This commit is contained in:
parent
aeff962224
commit
205113ecfa
31 changed files with 4027 additions and 0 deletions
182
crates/intel-dcap-api/examples/common_usage.rs
Normal file
182
crates/intel-dcap-api/examples/common_usage.rs
Normal file
|
@ -0,0 +1,182 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright (c) 2025 Matter Labs
|
||||
|
||||
use intel_dcap_api::{ApiClient, CaType, IntelApiError, UpdateType};
|
||||
|
||||
/// Common usage patterns for the Intel DCAP API client
|
||||
///
|
||||
/// This example demonstrates typical use cases for attestation verification.
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Create a client (defaults to V4 API)
|
||||
let client = ApiClient::new()?;
|
||||
|
||||
// Example 1: Get TCB info for quote verification
|
||||
println!("Example 1: Getting TCB info for SGX quote verification");
|
||||
println!("======================================================");
|
||||
|
||||
let fmspc = "00906ED50000"; // From SGX quote
|
||||
|
||||
match client.get_sgx_tcb_info(fmspc, None, None).await {
|
||||
Ok(response) => {
|
||||
// Critical: Check that issuer chain is present for signature verification
|
||||
if response.issuer_chain.is_empty() {
|
||||
println!("✗ Error: Empty issuer chain - cannot verify TCB info signature!");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
println!("✓ Retrieved TCB info for FMSPC: {}", fmspc);
|
||||
|
||||
// Parse the TCB info
|
||||
let tcb_info: serde_json::Value = serde_json::from_str(&response.tcb_info_json)?;
|
||||
|
||||
// Extract useful information
|
||||
if let Some(tcb_levels) = tcb_info["tcbInfo"]["tcbLevels"].as_array() {
|
||||
println!(" Found {} TCB levels", tcb_levels.len());
|
||||
|
||||
// Show the latest TCB level
|
||||
if let Some(latest) = tcb_levels.first() {
|
||||
println!(" Latest TCB level:");
|
||||
if let Some(status) = latest["tcbStatus"].as_str() {
|
||||
println!(" Status: {}", status);
|
||||
}
|
||||
if let Some(date) = latest["tcbDate"].as_str() {
|
||||
println!(" Date: {}", date);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The issuer chain is needed to verify the signature
|
||||
println!(
|
||||
" Issuer chain length: {} bytes",
|
||||
response.issuer_chain.len()
|
||||
);
|
||||
// Verify we have certificate chain for signature verification
|
||||
let cert_count = response.issuer_chain.matches("BEGIN CERTIFICATE").count();
|
||||
println!(" Certificate chain contains {} certificates", cert_count);
|
||||
}
|
||||
Err(IntelApiError::ApiError {
|
||||
status,
|
||||
error_message,
|
||||
..
|
||||
}) => {
|
||||
println!(
|
||||
"✗ API Error {}: {}",
|
||||
status,
|
||||
error_message.unwrap_or_default()
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Error: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
println!();
|
||||
|
||||
// Example 2: Get QE identity for enclave verification
|
||||
println!("Example 2: Getting QE identity for enclave verification");
|
||||
println!("======================================================");
|
||||
|
||||
match client.get_sgx_qe_identity(None, None).await {
|
||||
Ok(response) => {
|
||||
// Critical: Check that issuer chain is present for signature verification
|
||||
if response.issuer_chain.is_empty() {
|
||||
println!("✗ Error: Empty issuer chain - cannot verify QE identity signature!");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
println!("✓ Retrieved QE identity");
|
||||
println!(
|
||||
" Issuer chain length: {} bytes",
|
||||
response.issuer_chain.len()
|
||||
);
|
||||
|
||||
let identity: serde_json::Value =
|
||||
serde_json::from_str(&response.enclave_identity_json)?;
|
||||
|
||||
if let Some(enclave_id) = identity["enclaveIdentity"]["id"].as_str() {
|
||||
println!(" Enclave ID: {}", enclave_id);
|
||||
}
|
||||
|
||||
if let Some(version) = identity["enclaveIdentity"]["version"].as_u64() {
|
||||
println!(" Version: {}", version);
|
||||
}
|
||||
|
||||
if let Some(mrsigner) = identity["enclaveIdentity"]["mrsigner"].as_str() {
|
||||
println!(" MRSIGNER: {}...", &mrsigner[..16]);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Failed to get QE identity: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
println!();
|
||||
|
||||
// Example 3: Check certificate revocation
|
||||
println!("Example 3: Checking certificate revocation status");
|
||||
println!("================================================");
|
||||
|
||||
match client.get_pck_crl(CaType::Processor, None).await {
|
||||
Ok(response) => {
|
||||
// Critical: Check that issuer chain is present for CRL verification
|
||||
if response.issuer_chain.is_empty() {
|
||||
println!("✗ Error: Empty issuer chain - cannot verify CRL signature!");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
println!("✓ Retrieved PCK CRL");
|
||||
println!(
|
||||
" Issuer chain length: {} bytes",
|
||||
response.issuer_chain.len()
|
||||
);
|
||||
|
||||
let crl_pem = String::from_utf8_lossy(&response.crl_data);
|
||||
|
||||
// In real usage, you would parse this CRL and check if a certificate is revoked
|
||||
if crl_pem.contains("BEGIN X509 CRL") {
|
||||
println!(" CRL format: PEM");
|
||||
println!(" CRL size: {} bytes", crl_pem.len());
|
||||
|
||||
// Count the revoked certificates (naive approach)
|
||||
let revoked_count = crl_pem.matches("Serial Number:").count();
|
||||
println!(" Approximate revoked certificates: {}", revoked_count);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Failed to get CRL: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
println!();
|
||||
|
||||
// Example 4: Early update for testing
|
||||
println!("Example 4: Getting early TCB update (for testing)");
|
||||
println!("================================================");
|
||||
|
||||
match client
|
||||
.get_sgx_tcb_info(fmspc, Some(UpdateType::Early), None)
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
println!("✓ Retrieved early TCB update");
|
||||
|
||||
let tcb_info: serde_json::Value = serde_json::from_str(&response.tcb_info_json)?;
|
||||
|
||||
if let Some(next_update) = tcb_info["tcbInfo"]["nextUpdate"].as_str() {
|
||||
println!(" Next update: {}", next_update);
|
||||
}
|
||||
}
|
||||
Err(IntelApiError::ApiError { status, .. }) if status.as_u16() == 404 => {
|
||||
println!(" No early update available (this is normal)");
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Error: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
println!();
|
||||
println!("Done! These examples show common patterns for attestation verification.");
|
||||
|
||||
Ok(())
|
||||
}
|
515
crates/intel-dcap-api/examples/fetch_test_data.rs
Normal file
515
crates/intel-dcap-api/examples/fetch_test_data.rs
Normal file
|
@ -0,0 +1,515 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright (c) 2025 Matter Labs
|
||||
|
||||
use base64::{engine::general_purpose, Engine as _};
|
||||
use intel_dcap_api::{ApiClient, ApiVersion, CaType, CrlEncoding, PlatformFilter, UpdateType};
|
||||
use std::{fs, path::Path};
|
||||
|
||||
/// Fetch real data from Intel API and save it as JSON files
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Create test data directory
|
||||
let test_data_dir = Path::new("tests/test_data");
|
||||
fs::create_dir_all(test_data_dir)?;
|
||||
|
||||
let client = ApiClient::new()?;
|
||||
|
||||
println!("Fetching real test data from Intel API...");
|
||||
|
||||
// Keep track of successful fetches
|
||||
let mut successes: Vec<String> = Vec::new();
|
||||
let mut failures: Vec<String> = Vec::new();
|
||||
|
||||
// 1. Fetch SGX TCB info
|
||||
println!("\n1. Fetching SGX TCB info...");
|
||||
match client
|
||||
.get_sgx_tcb_info("00606A6A0000", Some(UpdateType::Standard), None)
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"tcb_info_json": response.tcb_info_json,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("sgx_tcb_info.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("SGX TCB info".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("SGX TCB info: {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Fetch TDX TCB info
|
||||
println!("\n2. Fetching TDX TCB info...");
|
||||
match client
|
||||
.get_tdx_tcb_info("00806F050000", Some(UpdateType::Standard), None)
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"tcb_info_json": response.tcb_info_json,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("tdx_tcb_info.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("TDX TCB info".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("TDX TCB info: {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Fetch PCK CRL for processor
|
||||
println!("\n3. Fetching PCK CRL (processor)...");
|
||||
match client.get_pck_crl(CaType::Processor, None).await {
|
||||
Ok(response) => {
|
||||
let crl_string = String::from_utf8_lossy(&response.crl_data);
|
||||
let data = serde_json::json!({
|
||||
"crl_data": crl_string,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("pck_crl_processor.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("PCK CRL (processor)".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("PCK CRL (processor): {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Fetch PCK CRL for platform
|
||||
println!("\n4. Fetching PCK CRL (platform)...");
|
||||
match client.get_pck_crl(CaType::Platform, None).await {
|
||||
Ok(response) => {
|
||||
let crl_string = String::from_utf8_lossy(&response.crl_data);
|
||||
let data = serde_json::json!({
|
||||
"crl_data": crl_string,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("pck_crl_platform.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("PCK CRL (platform)".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("PCK CRL (platform): {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Fetch SGX QE identity
|
||||
println!("\n5. Fetching SGX QE identity...");
|
||||
match client.get_sgx_qe_identity(None, None).await {
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"enclave_identity_json": response.enclave_identity_json,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("sgx_qe_identity.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("SGX QE identity".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("SGX QE identity: {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 6. Fetch SGX QVE identity
|
||||
println!("\n6. Fetching SGX QVE identity...");
|
||||
match client.get_sgx_qve_identity(None, None).await {
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"enclave_identity_json": response.enclave_identity_json,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("sgx_qve_identity.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("SGX QVE identity".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("SGX QVE identity: {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 7. Fetch TDX QE identity
|
||||
println!("\n7. Fetching TDX QE identity...");
|
||||
match client.get_tdx_qe_identity(None, None).await {
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"enclave_identity_json": response.enclave_identity_json,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("tdx_qe_identity.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("TDX QE identity".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("TDX QE identity: {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 8. Try an alternative FMSPC
|
||||
println!("\n8. Fetching alternative SGX TCB info...");
|
||||
match client.get_sgx_tcb_info("00906ED50000", None, None).await {
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"tcb_info_json": response.tcb_info_json,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("sgx_tcb_info_alt.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("Alternative SGX TCB info".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("Alternative SGX TCB info: {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 9. Fetch PCK certificate
|
||||
println!("\n9. Attempting to fetch PCK certificate...");
|
||||
let ppid = "3d6dd97e96f84536a2267e727dd860e4fdd3ffa3e319db41e8f69c9a43399e7b7ce97d7eb3bd05b0a58bdb5b90a0e218";
|
||||
let cpusvn = "0606060606060606060606060606060606060606060606060606060606060606";
|
||||
let pcesvn = "0a00";
|
||||
let pceid = "0000";
|
||||
|
||||
match client
|
||||
.get_pck_certificate_by_ppid(ppid, cpusvn, pcesvn, pceid, None, None)
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"pck_cert_pem": response.pck_cert_pem,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
"tcbm": response.tcbm,
|
||||
"fmspc": response.fmspc,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("pck_cert.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("PCK certificate".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("PCK certificate: {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 10. Fetch SGX QAE identity
|
||||
println!("\n10. Fetching SGX QAE identity...");
|
||||
match client.get_sgx_qae_identity(None, None).await {
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"enclave_identity_json": response.enclave_identity_json,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("sgx_qae_identity.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("SGX QAE identity".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("SGX QAE identity: {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 11. Fetch FMSPCs
|
||||
println!("\n11. Fetching FMSPCs...");
|
||||
match client.get_fmspcs(Some(PlatformFilter::All)).await {
|
||||
Ok(fmspcs_json) => {
|
||||
let data = serde_json::json!({
|
||||
"fmspcs_json": fmspcs_json,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("fmspcs.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("FMSPCs".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("FMSPCs: {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 12. Fetch SGX TCB evaluation data numbers
|
||||
println!("\n12. Fetching SGX TCB evaluation data numbers...");
|
||||
match client.get_sgx_tcb_evaluation_data_numbers().await {
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"tcb_evaluation_data_numbers_json": response.tcb_evaluation_data_numbers_json,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("sgx_tcb_eval_nums.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("SGX TCB evaluation data numbers".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("SGX TCB evaluation data numbers: {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 13. Fetch TDX TCB evaluation data numbers
|
||||
println!("\n13. Fetching TDX TCB evaluation data numbers...");
|
||||
match client.get_tdx_tcb_evaluation_data_numbers().await {
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"tcb_evaluation_data_numbers_json": response.tcb_evaluation_data_numbers_json,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("tdx_tcb_eval_nums.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("TDX TCB evaluation data numbers".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("TDX TCB evaluation data numbers: {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 14. Fetch PCK CRL with DER encoding
|
||||
println!("\n14. Fetching PCK CRL (processor, DER encoding)...");
|
||||
match client
|
||||
.get_pck_crl(CaType::Processor, Some(CrlEncoding::Der))
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
// For DER, save as base64
|
||||
let crl_base64 = general_purpose::STANDARD.encode(&response.crl_data);
|
||||
let data = serde_json::json!({
|
||||
"crl_data_base64": crl_base64,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("pck_crl_processor_der.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("PCK CRL (processor, DER)".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("PCK CRL (processor, DER): {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 15. Try different update types
|
||||
println!("\n15. Fetching SGX TCB info with Early update...");
|
||||
match client
|
||||
.get_sgx_tcb_info("00906ED50000", Some(UpdateType::Early), None)
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"tcb_info_json": response.tcb_info_json,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("sgx_tcb_info_early.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("SGX TCB info (Early update)".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("SGX TCB info (Early update): {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 16. Try with specific TCB evaluation data number
|
||||
println!("\n16. Fetching TDX TCB info with specific evaluation number...");
|
||||
match client
|
||||
.get_tdx_tcb_info("00806F050000", None, Some(17))
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"tcb_info_json": response.tcb_info_json,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("tdx_tcb_info_eval17.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("TDX TCB info (eval number 17)".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("TDX TCB info (eval number 17): {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 17. Try different FMSPCs
|
||||
println!("\n17. Fetching more SGX TCB info variations...");
|
||||
let test_fmspcs = vec!["00906ED50000", "00906C0F0000", "00A06F050000"];
|
||||
for fmspc in test_fmspcs {
|
||||
match client.get_sgx_tcb_info(fmspc, None, None).await {
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"tcb_info_json": response.tcb_info_json,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join(format!("sgx_tcb_info_{}.json", fmspc)),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push(format!("SGX TCB info (FMSPC: {})", fmspc));
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("SGX TCB info (FMSPC: {}): {}", fmspc, e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 18. Try FMSPCs with different platform filters
|
||||
println!("\n18. Fetching FMSPCs with different platform filters...");
|
||||
match client.get_fmspcs(None).await {
|
||||
Ok(fmspcs_json) => {
|
||||
let data = serde_json::json!({
|
||||
"fmspcs_json": fmspcs_json,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("fmspcs_no_filter.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("FMSPCs (no filter)".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("FMSPCs (no filter): {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
match client.get_fmspcs(Some(PlatformFilter::All)).await {
|
||||
Ok(fmspcs_json) => {
|
||||
let data = serde_json::json!({
|
||||
"fmspcs_json": fmspcs_json,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("fmspcs_all_platforms.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("FMSPCs (all platforms)".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("FMSPCs (all platforms): {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 19. Try PCK certificates with different parameters (encrypted PPID)
|
||||
println!("\n19. Attempting to fetch PCK certificates with different params...");
|
||||
// Try with a different encrypted PPID format
|
||||
let encrypted_ppid = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
|
||||
let pceid = "0000";
|
||||
|
||||
match client
|
||||
.get_pck_certificates_by_ppid(encrypted_ppid, pceid, None, None)
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"pck_certificates_json": response.pck_certs_json,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
"fmspc": response.fmspc,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("pck_certificates.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("PCK certificates (by PPID)".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("PCK certificates (by PPID): {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// 20. Try TDX TCB info with different FMSPCs
|
||||
println!("\n20. Fetching TDX TCB info variations...");
|
||||
let tdx_fmspcs = vec!["00806F050000", "00A06F050000", "00606A0000000"];
|
||||
for fmspc in tdx_fmspcs {
|
||||
match client.get_tdx_tcb_info(fmspc, None, None).await {
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"tcb_info_json": response.tcb_info_json,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join(format!("tdx_tcb_info_{}.json", fmspc)),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push(format!("TDX TCB info (FMSPC: {})", fmspc));
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("TDX TCB info (FMSPC: {}): {}", fmspc, e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 21. Try with V3 API for some endpoints
|
||||
println!("\n21. Testing V3 API endpoints...");
|
||||
let v3_client =
|
||||
ApiClient::new_with_options("https://api.trustedservices.intel.com", ApiVersion::V3)?;
|
||||
|
||||
match v3_client.get_sgx_tcb_info("00906ED50000", None, None).await {
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"tcb_info_json": response.tcb_info_json,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("sgx_tcb_info_v3.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("SGX TCB info (V3 API)".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("SGX TCB info (V3 API): {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
match v3_client.get_sgx_qe_identity(None, None).await {
|
||||
Ok(response) => {
|
||||
let data = serde_json::json!({
|
||||
"enclave_identity_json": response.enclave_identity_json,
|
||||
"issuer_chain": response.issuer_chain,
|
||||
});
|
||||
fs::write(
|
||||
test_data_dir.join("sgx_qe_identity_v3.json"),
|
||||
serde_json::to_string_pretty(&data)?,
|
||||
)?;
|
||||
successes.push("SGX QE identity (V3 API)".to_string());
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("SGX QE identity (V3 API): {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
println!("\n\nTest data fetching complete!");
|
||||
println!("\nSuccessful fetches:");
|
||||
for s in &successes {
|
||||
println!(" ✓ {}", s);
|
||||
}
|
||||
|
||||
if !failures.is_empty() {
|
||||
println!("\nFailed fetches:");
|
||||
for f in &failures {
|
||||
println!(" ✗ {}", f);
|
||||
}
|
||||
}
|
||||
|
||||
println!("\nData saved in: {}", test_data_dir.display());
|
||||
|
||||
Ok(())
|
||||
}
|
495
crates/intel-dcap-api/examples/integration_test.rs
Normal file
495
crates/intel-dcap-api/examples/integration_test.rs
Normal file
|
@ -0,0 +1,495 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright (c) 2025 Matter Labs
|
||||
|
||||
use intel_dcap_api::{
|
||||
ApiClient, ApiVersion, CaType, CrlEncoding, IntelApiError, PlatformFilter, UpdateType,
|
||||
};
|
||||
use std::time::Duration;
|
||||
use tokio::time::sleep;
|
||||
|
||||
/// Comprehensive integration test example demonstrating most Intel DCAP API client functions
|
||||
///
|
||||
/// This example shows how to use various endpoints of the Intel Trusted Services API.
|
||||
/// Note: Some operations may fail with 404 or 400 errors if the data doesn't exist on Intel's servers.
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Intel DCAP API Integration Test Example ===\n");
|
||||
|
||||
// Create clients for both V3 and V4 APIs
|
||||
let v4_client = ApiClient::new()?;
|
||||
let v3_client =
|
||||
ApiClient::new_with_options("https://api.trustedservices.intel.com", ApiVersion::V3)?;
|
||||
|
||||
// Track successes and failures
|
||||
let mut results = Vec::new();
|
||||
|
||||
// Test FMSPC - commonly used for TCB lookups
|
||||
let test_fmspc = "00906ED50000";
|
||||
let test_fmspc_tdx = "00806F050000";
|
||||
|
||||
println!("1. Testing TCB Info Endpoints...");
|
||||
println!("================================");
|
||||
|
||||
// 1.1 SGX TCB Info (V4)
|
||||
print!(" - SGX TCB Info (V4): ");
|
||||
match v4_client.get_sgx_tcb_info(test_fmspc, None, None).await {
|
||||
Ok(response) => {
|
||||
if response.issuer_chain.is_empty() {
|
||||
println!("✗ Failed: Empty issuer chain");
|
||||
results.push(("SGX TCB Info (V4)", false));
|
||||
} else {
|
||||
println!("✓ Success");
|
||||
println!(" FMSPC: {}", test_fmspc);
|
||||
println!(" Issuer chain: {} bytes", response.issuer_chain.len());
|
||||
let tcb_info: serde_json::Value = serde_json::from_str(&response.tcb_info_json)?;
|
||||
if let Some(version) = tcb_info["tcbInfo"]["version"].as_u64() {
|
||||
println!(" TCB Info Version: {}", version);
|
||||
}
|
||||
results.push(("SGX TCB Info (V4)", true));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Failed: {:?}", e);
|
||||
results.push(("SGX TCB Info (V4)", false));
|
||||
}
|
||||
}
|
||||
|
||||
// Add small delay between requests to be nice to the API
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
|
||||
// 1.2 SGX TCB Info (V3)
|
||||
print!(" - SGX TCB Info (V3): ");
|
||||
match v3_client.get_sgx_tcb_info(test_fmspc, None, None).await {
|
||||
Ok(response) => {
|
||||
if response.issuer_chain.is_empty() {
|
||||
println!("✗ Failed: Empty issuer chain");
|
||||
results.push(("SGX TCB Info (V3)", false));
|
||||
} else {
|
||||
println!("✓ Success");
|
||||
println!(" Issuer chain: {} bytes", response.issuer_chain.len());
|
||||
results.push(("SGX TCB Info (V3)", true));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Failed: {:?}", e);
|
||||
results.push(("SGX TCB Info (V3)", false));
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
|
||||
// 1.3 TDX TCB Info
|
||||
print!(" - TDX TCB Info: ");
|
||||
match v4_client.get_tdx_tcb_info(test_fmspc_tdx, None, None).await {
|
||||
Ok(response) => {
|
||||
if response.issuer_chain.is_empty() {
|
||||
println!("✗ Failed: Empty issuer chain");
|
||||
results.push(("TDX TCB Info", false));
|
||||
} else {
|
||||
println!("✓ Success");
|
||||
println!(" Issuer chain: {} bytes", response.issuer_chain.len());
|
||||
let tcb_info: serde_json::Value = serde_json::from_str(&response.tcb_info_json)?;
|
||||
if let Some(id) = tcb_info["tcbInfo"]["id"].as_str() {
|
||||
println!(" Platform: {}", id);
|
||||
}
|
||||
results.push(("TDX TCB Info", true));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Failed: {:?}", e);
|
||||
results.push(("TDX TCB Info", false));
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
|
||||
// 1.4 SGX TCB Info with Early Update
|
||||
print!(" - SGX TCB Info (Early Update): ");
|
||||
match v4_client
|
||||
.get_sgx_tcb_info(test_fmspc, Some(UpdateType::Early), None)
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
if response.issuer_chain.is_empty() {
|
||||
println!("✗ Failed: Empty issuer chain");
|
||||
results.push(("SGX TCB Info (Early)", false));
|
||||
} else {
|
||||
println!("✓ Success");
|
||||
println!(" Issuer chain: {} bytes", response.issuer_chain.len());
|
||||
results.push(("SGX TCB Info (Early)", true));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Failed: {:?}", e);
|
||||
results.push(("SGX TCB Info (Early)", false));
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
|
||||
println!("\n2. Testing Enclave Identity Endpoints...");
|
||||
println!("========================================");
|
||||
|
||||
// 2.1 SGX QE Identity
|
||||
print!(" - SGX QE Identity: ");
|
||||
match v4_client.get_sgx_qe_identity(None, None).await {
|
||||
Ok(response) => {
|
||||
if response.issuer_chain.is_empty() {
|
||||
println!("✗ Failed: Empty issuer chain");
|
||||
results.push(("SGX QE Identity", false));
|
||||
} else {
|
||||
println!("✓ Success");
|
||||
println!(" Issuer chain: {} bytes", response.issuer_chain.len());
|
||||
let identity: serde_json::Value =
|
||||
serde_json::from_str(&response.enclave_identity_json)?;
|
||||
if let Some(id) = identity["enclaveIdentity"]["id"].as_str() {
|
||||
println!(" Enclave ID: {}", id);
|
||||
}
|
||||
results.push(("SGX QE Identity", true));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Failed: {:?}", e);
|
||||
results.push(("SGX QE Identity", false));
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
|
||||
// 2.2 SGX QVE Identity
|
||||
print!(" - SGX QVE Identity: ");
|
||||
match v4_client.get_sgx_qve_identity(None, None).await {
|
||||
Ok(response) => {
|
||||
if response.issuer_chain.is_empty() {
|
||||
println!("✗ Failed: Empty issuer chain");
|
||||
results.push(("SGX QVE Identity", false));
|
||||
} else {
|
||||
println!("✓ Success");
|
||||
println!(" Issuer chain: {} bytes", response.issuer_chain.len());
|
||||
results.push(("SGX QVE Identity", true));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Failed: {:?}", e);
|
||||
results.push(("SGX QVE Identity", false));
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
|
||||
// 2.3 SGX QAE Identity
|
||||
print!(" - SGX QAE Identity: ");
|
||||
match v4_client.get_sgx_qae_identity(None, None).await {
|
||||
Ok(response) => {
|
||||
if response.issuer_chain.is_empty() {
|
||||
println!("✗ Failed: Empty issuer chain");
|
||||
results.push(("SGX QAE Identity", false));
|
||||
} else {
|
||||
println!("✓ Success");
|
||||
println!(" Issuer chain: {} bytes", response.issuer_chain.len());
|
||||
results.push(("SGX QAE Identity", true));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Failed: {:?}", e);
|
||||
results.push(("SGX QAE Identity", false));
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
|
||||
// 2.4 TDX QE Identity (V4 only)
|
||||
print!(" - TDX QE Identity: ");
|
||||
match v4_client.get_tdx_qe_identity(None, None).await {
|
||||
Ok(response) => {
|
||||
if response.issuer_chain.is_empty() {
|
||||
println!("✗ Failed: Empty issuer chain");
|
||||
results.push(("TDX QE Identity", false));
|
||||
} else {
|
||||
println!("✓ Success");
|
||||
println!(" Issuer chain: {} bytes", response.issuer_chain.len());
|
||||
results.push(("TDX QE Identity", true));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Failed: {:?}", e);
|
||||
results.push(("TDX QE Identity", false));
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
|
||||
println!("\n3. Testing PCK CRL Endpoints...");
|
||||
println!("================================");
|
||||
|
||||
// 3.1 PCK CRL - Processor (PEM)
|
||||
print!(" - PCK CRL (Processor, PEM): ");
|
||||
match v4_client.get_pck_crl(CaType::Processor, None).await {
|
||||
Ok(response) => {
|
||||
if response.issuer_chain.is_empty() {
|
||||
println!("✗ Failed: Empty issuer chain");
|
||||
results.push(("PCK CRL (Processor)", false));
|
||||
} else {
|
||||
println!("✓ Success");
|
||||
println!(" Issuer chain: {} bytes", response.issuer_chain.len());
|
||||
let crl_str = String::from_utf8_lossy(&response.crl_data);
|
||||
if crl_str.contains("BEGIN X509 CRL") {
|
||||
println!(" Format: PEM");
|
||||
}
|
||||
results.push(("PCK CRL (Processor)", true));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Failed: {:?}", e);
|
||||
results.push(("PCK CRL (Processor)", false));
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
|
||||
// 3.2 PCK CRL - Platform (DER)
|
||||
print!(" - PCK CRL (Platform, DER): ");
|
||||
match v4_client
|
||||
.get_pck_crl(CaType::Platform, Some(CrlEncoding::Der))
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
if response.issuer_chain.is_empty() {
|
||||
println!("✗ Failed: Empty issuer chain");
|
||||
results.push(("PCK CRL (Platform, DER)", false));
|
||||
} else {
|
||||
println!("✓ Success");
|
||||
println!(" Issuer chain: {} bytes", response.issuer_chain.len());
|
||||
println!(" CRL size: {} bytes", response.crl_data.len());
|
||||
results.push(("PCK CRL (Platform, DER)", true));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Failed: {:?}", e);
|
||||
results.push(("PCK CRL (Platform, DER)", false));
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
|
||||
println!("\n4. Testing FMSPC Endpoints (V4 only)...");
|
||||
println!("=======================================");
|
||||
|
||||
// 4.1 Get FMSPCs (no filter)
|
||||
print!(" - Get FMSPCs (no filter): ");
|
||||
match v4_client.get_fmspcs(None).await {
|
||||
Ok(fmspcs_json) => {
|
||||
println!("✓ Success");
|
||||
let fmspcs: serde_json::Value = serde_json::from_str(&fmspcs_json)?;
|
||||
if let Some(arr) = fmspcs.as_array() {
|
||||
println!(" Total FMSPCs: {}", arr.len());
|
||||
// Show first few FMSPCs
|
||||
for (i, fmspc) in arr.iter().take(3).enumerate() {
|
||||
if let (Some(fmspc_val), Some(platform)) =
|
||||
(fmspc["fmspc"].as_str(), fmspc["platform"].as_str())
|
||||
{
|
||||
println!(" [{}] {} - {}", i + 1, fmspc_val, platform);
|
||||
}
|
||||
}
|
||||
if arr.len() > 3 {
|
||||
println!(" ... and {} more", arr.len() - 3);
|
||||
}
|
||||
}
|
||||
results.push(("Get FMSPCs", true));
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Failed: {:?}", e);
|
||||
results.push(("Get FMSPCs", false));
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
|
||||
// 4.2 Get FMSPCs with platform filter
|
||||
print!(" - Get FMSPCs (All platforms): ");
|
||||
match v4_client.get_fmspcs(Some(PlatformFilter::All)).await {
|
||||
Ok(_) => {
|
||||
println!("✓ Success");
|
||||
results.push(("Get FMSPCs (filtered)", true));
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Failed: {:?}", e);
|
||||
results.push(("Get FMSPCs (filtered)", false));
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
|
||||
println!("\n5. Testing TCB Evaluation Data Numbers (V4 only)...");
|
||||
println!("===================================================");
|
||||
|
||||
// 5.1 SGX TCB Evaluation Data Numbers
|
||||
print!(" - SGX TCB Evaluation Data Numbers: ");
|
||||
match v4_client.get_sgx_tcb_evaluation_data_numbers().await {
|
||||
Ok(response) => {
|
||||
if response.issuer_chain.is_empty() {
|
||||
println!("✗ Failed: Empty issuer chain");
|
||||
results.push(("SGX TCB Eval Numbers", false));
|
||||
} else {
|
||||
println!("✓ Success");
|
||||
println!(" Issuer chain: {} bytes", response.issuer_chain.len());
|
||||
let data: serde_json::Value =
|
||||
serde_json::from_str(&response.tcb_evaluation_data_numbers_json)?;
|
||||
if let Some(sgx_data) = data.get("sgx") {
|
||||
println!(
|
||||
" SGX entries: {}",
|
||||
sgx_data.as_array().map(|a| a.len()).unwrap_or(0)
|
||||
);
|
||||
}
|
||||
results.push(("SGX TCB Eval Numbers", true));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Failed: {:?}", e);
|
||||
results.push(("SGX TCB Eval Numbers", false));
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
|
||||
// 5.2 TDX TCB Evaluation Data Numbers
|
||||
print!(" - TDX TCB Evaluation Data Numbers: ");
|
||||
match v4_client.get_tdx_tcb_evaluation_data_numbers().await {
|
||||
Ok(response) => {
|
||||
if response.issuer_chain.is_empty() {
|
||||
println!("✗ Failed: Empty issuer chain");
|
||||
results.push(("TDX TCB Eval Numbers", false));
|
||||
} else {
|
||||
println!("✓ Success");
|
||||
println!(" Issuer chain: {} bytes", response.issuer_chain.len());
|
||||
let data: serde_json::Value =
|
||||
serde_json::from_str(&response.tcb_evaluation_data_numbers_json)?;
|
||||
if let Some(tdx_data) = data.get("tdx") {
|
||||
println!(
|
||||
" TDX entries: {}",
|
||||
tdx_data.as_array().map(|a| a.len()).unwrap_or(0)
|
||||
);
|
||||
}
|
||||
results.push(("TDX TCB Eval Numbers", true));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Failed: {:?}", e);
|
||||
results.push(("TDX TCB Eval Numbers", false));
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
|
||||
println!("\n6. Testing PCK Certificate Endpoints...");
|
||||
println!("=======================================");
|
||||
|
||||
/* // 6.1 PCK Certificate by PPID (usually requires valid data)
|
||||
print!(" - PCK Certificate by PPID: ");
|
||||
let test_ppid = "0000000000000000000000000000000000000000000000000000000000000000";
|
||||
let test_cpusvn = "00000000000000000000000000000000";
|
||||
let test_pcesvn = "0000";
|
||||
let test_pceid = "0000";
|
||||
|
||||
match v4_client
|
||||
.get_pck_certificate_by_ppid(test_ppid, test_cpusvn, test_pcesvn, test_pceid, None, None)
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
println!("✓ Success");
|
||||
results.push(("PCK Certificate", true));
|
||||
}
|
||||
Err(e) => {
|
||||
// Expected to fail with test data
|
||||
match &e {
|
||||
IntelApiError::ApiError { status, .. } => {
|
||||
println!("✗ Failed (Expected): HTTP {}", status);
|
||||
}
|
||||
_ => println!("✗ Failed: {:?}", e),
|
||||
}
|
||||
results.push(("PCK Certificate", false));
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
*/
|
||||
println!("\n7. Testing API Version Compatibility...");
|
||||
println!("=======================================");
|
||||
|
||||
// 7.1 Try V4-only endpoint on V3
|
||||
print!(" - V4-only endpoint on V3 (should fail): ");
|
||||
match v3_client.get_fmspcs(None).await {
|
||||
Ok(_) => {
|
||||
println!("✗ Unexpected success!");
|
||||
results.push(("V3/V4 compatibility check", false));
|
||||
}
|
||||
Err(IntelApiError::UnsupportedApiVersion(_)) => {
|
||||
println!("✓ Correctly rejected");
|
||||
results.push(("V3/V4 compatibility check", true));
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Wrong error: {:?}", e);
|
||||
results.push(("V3/V4 compatibility check", false));
|
||||
}
|
||||
}
|
||||
|
||||
println!("\n8. Testing Error Handling...");
|
||||
println!("============================");
|
||||
|
||||
// 8.1 Invalid FMSPC
|
||||
print!(" - Invalid FMSPC format: ");
|
||||
match v4_client.get_sgx_tcb_info("invalid", None, None).await {
|
||||
Ok(_) => {
|
||||
println!("✗ Unexpected success!");
|
||||
results.push(("Error handling", false));
|
||||
}
|
||||
Err(IntelApiError::ApiError {
|
||||
status,
|
||||
error_code,
|
||||
error_message,
|
||||
..
|
||||
}) => {
|
||||
println!("✓ Correctly handled");
|
||||
println!(" Status: {}", status);
|
||||
if let Some(code) = error_code {
|
||||
println!(" Error Code: {}", code);
|
||||
}
|
||||
if let Some(msg) = error_message {
|
||||
println!(" Error Message: {}", msg);
|
||||
}
|
||||
results.push(("Error handling", true));
|
||||
}
|
||||
Err(e) => {
|
||||
println!("✗ Unexpected error: {:?}", e);
|
||||
results.push(("Error handling", false));
|
||||
}
|
||||
}
|
||||
|
||||
// Summary
|
||||
println!("\n\n=== Summary ===");
|
||||
println!("===============");
|
||||
|
||||
let total = results.len();
|
||||
let successful = results.iter().filter(|(_, success)| *success).count();
|
||||
let failed = total - successful;
|
||||
|
||||
println!("Total tests: {}", total);
|
||||
println!(
|
||||
"Successful: {} ({}%)",
|
||||
successful,
|
||||
(successful * 100) / total
|
||||
);
|
||||
println!("Failed: {} ({}%)", failed, (failed * 100) / total);
|
||||
|
||||
println!("\nDetailed Results:");
|
||||
for (test, success) in &results {
|
||||
println!(" {} {}", if *success { "✓" } else { "✗" }, test);
|
||||
}
|
||||
|
||||
println!("\nNote: Some failures are expected due to:");
|
||||
println!("- Test data not existing on Intel servers");
|
||||
println!("- PCK operations requiring valid platform data");
|
||||
println!("- Subscription key requirements for certain endpoints");
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue