blob: e35208b05356460db23e9d8c163814ea22c9e9f3 [file]
// Licensed under the Apache-2.0 license
//! SPDM Evidence Implementation - AST1060-EVB Reference Implementation
//!
//! Provides device measurements for SPDM attestation operations. This reference
//! implementation returns fixed measurement values for testing and demonstration.
//!
//! ## Architecture
//!
//! - **Fixed measurements:** Two static string measurements
//! - **No hardware integration:** Placeholder for development
//! - **PCR quote generation:** Returns formatted measurement data
//!
//! ## Hardware-Backed Implementations
//!
//! This software implementation serves as a reference. Future hardware-backed
//! versions should:
//! - Integrate with platform boot measurements
//! - Use TPM for PCR values and quotes
//! - Include cryptographic signatures
//! - Implement dynamic measurement log
//!
//! ## Usage
//!
//! ```rust,no_run
//! use ast1060_evidence::Ast1060Evidence;
//! use spdm_lib::platform::evidence::SpdmEvidence;
//!
//! let evidence = Ast1060Evidence::new();
//!
//! // Get PCR quote size
//! let size = evidence.pcr_quote_size(false)?;
//!
//! // Generate PCR quote
//! let mut buffer = vec![0u8; size];
//! let written = evidence.pcr_quote(&mut buffer, false)?;
//! ```
#![no_std]
use spdm_lib::platform::evidence::{SpdmEvidence, SpdmEvidenceError, SpdmEvidenceResult};
/// Fixed measurement data
const MEASUREMENT_1: &[u8] = b"OpenPRoT SPDM Responder";
const MEASUREMENT_2: &[u8] = b"OCP EMEA HELLO WORLD";
/// Total number of measurements
const MEASUREMENT_COUNT: u8 = 2;
/// SPDM evidence implementation for AST1060-EVB.
///
/// Provides fixed measurements for SPDM GET_MEASUREMENTS command.
/// This is a reference implementation for testing and demonstration.
pub struct Ast1060Evidence;
impl Ast1060Evidence {
/// Create a new evidence provider instance.
pub const fn new() -> Self {
Self
}
/// Calculate the total size needed for PCR quote
fn calculate_quote_size(&self, with_pqc_sig: bool) -> usize {
// PCR quote format (simplified):
// - Measurement count (1 byte)
// - For each measurement:
// - Measurement index (1 byte)
// - Measurement size (2 bytes)
// - Measurement data (variable)
// - Optional: Post-quantum signature (if with_pqc_sig)
let mut size = 1; // Measurement count
// Measurement 1
size += 1; // Index
size += 2; // Size field
size += MEASUREMENT_1.len(); // Data
// Measurement 2
size += 1; // Index
size += 2; // Size field
size += MEASUREMENT_2.len(); // Data
// Post-quantum signature (not implemented in this version)
if with_pqc_sig {
// Reserved for future PQC signature support
size += 0;
}
size
}
/// Encode measurements into buffer
fn encode_measurements(&self, buffer: &mut [u8]) -> SpdmEvidenceResult<usize> {
let mut offset = 0;
// Validate buffer size
let required_size = self.calculate_quote_size(false);
if buffer.len() < required_size {
return Err(SpdmEvidenceError::InvalidEvidenceFormat);
}
// Measurement count
buffer[offset] = MEASUREMENT_COUNT;
offset += 1;
// Measurement 1
buffer[offset] = 0; // Index 0
offset += 1;
let len1 = MEASUREMENT_1.len() as u16;
buffer[offset..offset + 2].copy_from_slice(&len1.to_le_bytes());
offset += 2;
buffer[offset..offset + MEASUREMENT_1.len()].copy_from_slice(MEASUREMENT_1);
offset += MEASUREMENT_1.len();
// Measurement 2
buffer[offset] = 1; // Index 1
offset += 1;
let len2 = MEASUREMENT_2.len() as u16;
buffer[offset..offset + 2].copy_from_slice(&len2.to_le_bytes());
offset += 2;
buffer[offset..offset + MEASUREMENT_2.len()].copy_from_slice(MEASUREMENT_2);
offset += MEASUREMENT_2.len();
Ok(offset)
}
}
impl SpdmEvidence for Ast1060Evidence {
fn pcr_quote(&self, buffer: &mut [u8], with_pqc_sig: bool) -> SpdmEvidenceResult<usize> {
if with_pqc_sig {
// Post-quantum signatures not implemented in this version
return Err(SpdmEvidenceError::UnsupportedEvidenceType);
}
self.encode_measurements(buffer)
}
fn pcr_quote_size(&self, with_pqc_sig: bool) -> SpdmEvidenceResult<usize> {
if with_pqc_sig {
// Post-quantum signatures not implemented in this version
return Err(SpdmEvidenceError::UnsupportedEvidenceType);
}
Ok(self.calculate_quote_size(false))
}
}
impl Default for Ast1060Evidence {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new() {
let _evidence = Ast1060Evidence::new();
}
#[test]
fn test_pcr_quote_size() {
let evidence = Ast1060Evidence::new();
// Without PQC signature
let size = evidence.pcr_quote_size(false).unwrap();
// Expected size:
// 1 (count) + 1 (idx1) + 2 (len1) + 23 (data1) + 1 (idx2) + 2 (len2) + 20 (data2)
// = 1 + 26 + 23 = 50
assert_eq!(size, 50);
}
#[test]
fn test_pcr_quote_size_with_pqc() {
let evidence = Ast1060Evidence::new();
// PQC signatures not supported
let result = evidence.pcr_quote_size(true);
assert!(matches!(
result,
Err(SpdmEvidenceError::UnsupportedEvidenceType)
));
}
#[test]
fn test_pcr_quote() {
let evidence = Ast1060Evidence::new();
let mut buffer = [0u8; 100];
let written = evidence.pcr_quote(&mut buffer, false).unwrap();
assert_eq!(written, 50);
// Verify measurement count
assert_eq!(buffer[0], 2);
// Verify measurement 1
assert_eq!(buffer[1], 0); // Index 0
let len1 = u16::from_le_bytes([buffer[2], buffer[3]]);
assert_eq!(len1, 23);
assert_eq!(&buffer[4..27], MEASUREMENT_1);
// Verify measurement 2
assert_eq!(buffer[27], 1); // Index 1
let len2 = u16::from_le_bytes([buffer[28], buffer[29]]);
assert_eq!(len2, 20);
assert_eq!(&buffer[30..50], MEASUREMENT_2);
}
#[test]
fn test_pcr_quote_buffer_too_small() {
let evidence = Ast1060Evidence::new();
let mut buffer = [0u8; 10]; // Too small
let result = evidence.pcr_quote(&mut buffer, false);
assert!(matches!(
result,
Err(SpdmEvidenceError::InvalidEvidenceFormat)
));
}
#[test]
fn test_pcr_quote_with_pqc() {
let evidence = Ast1060Evidence::new();
let mut buffer = [0u8; 100];
// PQC signatures not supported
let result = evidence.pcr_quote(&mut buffer, true);
assert!(matches!(
result,
Err(SpdmEvidenceError::UnsupportedEvidenceType)
));
}
#[test]
fn test_measurement_values() {
assert_eq!(MEASUREMENT_1, b"OpenPRoT SPDM Responder");
assert_eq!(MEASUREMENT_2, b"OCP EMEA HELLO WORLD");
}
#[test]
fn test_measurement_count() {
assert_eq!(MEASUREMENT_COUNT, 2);
}
}