Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Commit

Permalink
Test: check certificate/challenge/digest response message
Browse files Browse the repository at this point in the history
Signed-off-by: xiaoyuxlu <[email protected]>
  • Loading branch information
xiaoyuxlu committed Sep 8, 2023
1 parent bade3ea commit 5126934
Show file tree
Hide file tree
Showing 19 changed files with 1,509 additions and 19 deletions.
2 changes: 1 addition & 1 deletion test/spdmlib-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ edition = "2021"

[dependencies]
spdmlib = { path = "../../spdmlib", default-features = false, features=["spdm-ring"] }
codec = { path = "../../codec" }
codec = { path = "../../codec", features = ["alloc"] }
log = "0.4.13"
ring = { version = "0.16.20" }
bytes = { version="1", default-features=false }
Expand Down
5 changes: 5 additions & 0 deletions test/spdmlib-test/src/common/crypto_callback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,5 +175,10 @@ fn fake_verify_cert_chain(_cert_chain: &[u8]) -> SpdmResult {
#[test]
// Make sure this is the first test case running by `cargo test`
fn test_0_crypto_init() {
use super::secret_callback::FAKE_SECRET_ASYM_IMPL_INSTANCE;
spdmlib::crypto::aead::register(FAKE_AEAD.clone());
spdmlib::crypto::asym_verify::register(FAKE_ASYM_VERIFY.clone());
spdmlib::crypto::aead::register(FAKE_AEAD.clone());
spdmlib::crypto::rand::register(FAKE_RAND.clone());
spdmlib::secret::asym_sign::register(FAKE_SECRET_ASYM_IMPL_INSTANCE.clone());
}
157 changes: 155 additions & 2 deletions test/spdmlib-test/src/common/device_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
#![allow(unused)]

use async_trait::async_trait;
use spdmlib::common::{SpdmDeviceIo, ST1};
use spdmlib::common::{SpdmDeviceIo, SpdmTransportEncap, ST1};
use spdmlib::config::RECEIVER_BUFFER_SIZE;
use spdmlib::error::{SpdmResult, SPDM_STATUS_ERROR_PEER};
use spdmlib::error::{SpdmResult, SPDM_STATUS_DECAP_FAIL, SPDM_STATUS_ERROR_PEER};
use spdmlib::responder;
use std::cell::RefCell;
use std::collections::VecDeque;
Expand Down Expand Up @@ -246,3 +246,156 @@ fn test_fake_device_io() {
};
executor::block_on(future);
}

pub struct TestTransportEncap;
#[async_trait]
impl SpdmTransportEncap for TestTransportEncap {
async fn encap(
&mut self,
spdm_buffer: Arc<&[u8]>,
transport_buffer: Arc<Mutex<&mut [u8]>>,
secured_message: bool,
) -> SpdmResult<usize> {
// format
// secure_message u8
let mut transport_buffer = transport_buffer.lock();
let len = spdm_buffer.len();
transport_buffer[0] = secured_message as u8;

if transport_buffer.len() < len + 1 {
return Err(SPDM_STATUS_DECAP_FAIL);
}
transport_buffer[1..(1 + len)].copy_from_slice(&spdm_buffer[..]);
Ok(1 + len)
}

async fn decap(
&mut self,
transport_buffer: Arc<&[u8]>,
spdm_buffer: Arc<Mutex<&mut [u8]>>,
) -> SpdmResult<(usize, bool)> {
let mut spdm_buffer = spdm_buffer.lock();
let spdm_buffer_len = transport_buffer.len() - 1;
let secure_message = if transport_buffer[0] == 0 {
false
} else {
true
};
spdm_buffer[0..spdm_buffer_len].copy_from_slice(&transport_buffer[1..]);
Ok((spdm_buffer_len, secure_message))
}

async fn encap_app(
&mut self,
spdm_buffer: Arc<&[u8]>,
app_buffer: Arc<Mutex<&mut [u8]>>,
_is_app_message: bool,
) -> SpdmResult<usize> {
let mut app_buffer = app_buffer.lock();
app_buffer[0..spdm_buffer.len()].copy_from_slice(&spdm_buffer);
Ok(spdm_buffer.len())
}

async fn decap_app(
&mut self,
app_buffer: Arc<&[u8]>,
spdm_buffer: Arc<Mutex<&mut [u8]>>,
) -> SpdmResult<(usize, bool)> {
let mut spdm_buffer = spdm_buffer.lock();
spdm_buffer[0..app_buffer.len()].copy_from_slice(&app_buffer);
Ok((app_buffer.len(), false))
}
fn get_sequence_number_count(&mut self) -> u8 {
todo!()
}

fn get_max_random_count(&mut self) -> u16 {
todo!()
}
}

pub struct TestSpdmDeviceIo {
pub rx: Arc<Mutex<VecDeque<u8>>>,
pub tx: Arc<Mutex<VecDeque<u8>>>,
}

impl TestSpdmDeviceIo {
pub fn new(rx: Arc<Mutex<VecDeque<u8>>>, tx: Arc<Mutex<VecDeque<u8>>>) -> Self {
Self { rx, tx }
}
}

#[async_trait]
impl SpdmDeviceIo for TestSpdmDeviceIo {
async fn receive(
&mut self,
out_buffer: Arc<Mutex<&mut [u8]>>,
_timeout: usize,
) -> Result<usize, usize> {
let mut rx = self.rx.lock();
if (rx.len() < 4) {
return Err(0);
}
// Length 4 bytes
let length_buf: Vec<u8> = rx.drain(0..4).collect();
let length =
u32::from_le_bytes([length_buf[0], length_buf[1], length_buf[2], length_buf[3]]);
let length = length as usize;
// Data length bytes
let mut out_buffer = out_buffer.lock();
if out_buffer.len() < length {
return Err(0);
}
for index in 0..length {
out_buffer[index] = rx.pop_front().unwrap();
}
println!("RECV RAW - {:02x?}", &out_buffer[..length]);
Ok(length)
}
async fn send(&mut self, buffer: Arc<&[u8]>) -> SpdmResult {
{
let mut tx = self.tx.lock();
let length = buffer.len() as u32;
tx.extend(length.to_le_bytes());
tx.extend(buffer.iter());
}
println!("SEND RAW - {:02x?}", &buffer);
Ok(())
}

async fn flush_all(&mut self) -> SpdmResult {
Ok(())
}
}

pub fn test_header_generater_callback(secure: u8, spdm_msg: &[u8]) -> VecDeque<u8> {
// This function is used to generate the header
// Note: The same method as device_io and transport encap should be use
// Current implementation is for TestDeviceIo and TestTransportEncap
let mut ret = VecDeque::new();
let length = (spdm_msg.len() + 1) as u32;
ret.extend(length.to_le_bytes());
ret.push_back(secure);
ret.extend(spdm_msg);
ret
}

#[test]
fn test_test_device_io() {
let rx = Arc::new(Mutex::new(VecDeque::<u8>::new()));
let tx = Arc::new(Mutex::new(VecDeque::<u8>::new()));
let rx_shared = Arc::clone(&rx);
let tx_shared = Arc::clone(&tx);
let future = async {
let mut server = TestSpdmDeviceIo::new(rx, tx);
let _ = server.send(Arc::new(b"hello")).await;
};
executor::block_on(future);

let tx = tx_shared.lock();
let res = tx.as_slices();
assert_eq!(
res.0,
[0x05, 0x00, 0x00, 0x00, 0x68, 0x65, 0x6c, 0x6c, 0x6f]
)
}
27 changes: 27 additions & 0 deletions test/spdmlib-test/src/common/secret_callback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ pub static SECRET_PSK_IMPL_INSTANCE: SpdmSecretPsk = SpdmSecretPsk {

pub static SECRET_ASYM_IMPL_INSTANCE: SpdmSecretAsymSign =
SpdmSecretAsymSign { sign_cb: asym_sign };
pub static FAKE_SECRET_ASYM_IMPL_INSTANCE: SpdmSecretAsymSign = SpdmSecretAsymSign {
sign_cb: fake_asym_sign,
};

#[allow(clippy::field_reassign_with_default)]
fn measurement_collection_impl(
Expand Down Expand Up @@ -317,3 +320,27 @@ fn sign_ecdsa_asym_algo(
data: full_signature,
})
}

fn fake_asym_sign(
base_hash_algo: SpdmBaseHashAlgo,
base_asym_algo: SpdmBaseAsymAlgo,
data: &[u8],
) -> Option<SpdmSignatureStruct> {
match (base_hash_algo, base_asym_algo) {
(SpdmBaseHashAlgo::TPM_ALG_SHA_256, SpdmBaseAsymAlgo::TPM_ALG_ECDSA_ECC_NIST_P256) => {
Some(SpdmSignatureStruct {
data_size: 64,
data: [0x5a; SPDM_MAX_ASYM_KEY_SIZE],
})
}
(SpdmBaseHashAlgo::TPM_ALG_SHA_384, SpdmBaseAsymAlgo::TPM_ALG_ECDSA_ECC_NIST_P384) => {
Some(SpdmSignatureStruct {
data_size: 96,
data: [0x5a; SPDM_MAX_ASYM_KEY_SIZE],
})
}
_ => {
panic!();
}
}
}
126 changes: 122 additions & 4 deletions test/spdmlib-test/src/common/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,29 @@

#![allow(unused)]

use super::device_io::TestSpdmDeviceIo;
use super::USE_ECDSA;
use crate::common::device_io::MySpdmDeviceIo;
use crate::common::device_io::{MySpdmDeviceIo, TestTransportEncap};
use crate::common::secret_callback::SECRET_ASYM_IMPL_INSTANCE;
use crate::common::transport::PciDoeTransportEncap;
use codec::{Reader, Writer};
use codec::{Codec, Reader, Writer};
use spdmlib::common::{
SpdmCodec, SpdmConfigInfo, SpdmContext, SpdmDeviceIo, SpdmOpaqueSupport, SpdmProvisionInfo,
SpdmTransportEncap, DMTF_SECURE_SPDM_VERSION_10, DMTF_SECURE_SPDM_VERSION_11,
SpdmTransportEncap, DMTF_SECURE_SPDM_VERSION_10, DMTF_SECURE_SPDM_VERSION_11, ST1,
};
use spdmlib::config;
use spdmlib::config::MAX_SPDM_MSG_SIZE;
use spdmlib::crypto;
use spdmlib::message::SpdmMessage;
use spdmlib::protocol::*;
use spdmlib::{config, responder};
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

use spin::Mutex;
extern crate alloc;
use alloc::boxed::Box;
use alloc::collections::VecDeque;
use alloc::sync::Arc;
use core::ops::DerefMut;

Expand Down Expand Up @@ -395,3 +400,116 @@ pub fn get_rsp_cert_chain_buff() -> SpdmCertChainBuffer {
SpdmCertChainBuffer::new(cert_chain, root_cert_hash.as_ref())
.expect("Create format certificate chain failed.")
}

#[derive(Debug, PartialEq, Eq)]
pub struct TestSpdmMessage {
pub message: crate::protocol::Message,
pub secure: u8, // secure message
}

#[derive(Debug, PartialEq, Eq)]
pub struct TestCase {
pub input: Vec<TestSpdmMessage>,
pub expected: Vec<TestSpdmMessage>,
}

impl TestCase {
pub fn config() -> (SpdmConfigInfo, SpdmProvisionInfo) {
create_info()
}

pub fn input_to_vec(&self, cb: fn(secure: u8, bufer: &[u8]) -> VecDeque<u8>) -> VecDeque<u8> {
let mut ret = VecDeque::new();
for data in &self.input {
let mut buffer = vec![0u8; MAX_SPDM_MSG_SIZE];
let writer = &mut Writer::init(&mut buffer[..]);
let len = data
.message
.encode(writer)
.expect("Error to encode input message");
ret.extend((cb)(data.secure, &buffer[..len]).iter())
}
ret
}
pub fn expected_to_vec(
&self,
cb: fn(secure: u8, bufer: &[u8]) -> VecDeque<u8>,
) -> VecDeque<u8> {
let mut ret = VecDeque::new();
for data in &self.expected {
let mut buffer = vec![0u8; MAX_SPDM_MSG_SIZE];
let writer = &mut Writer::init(&mut buffer[..]);
let len = data
.message
.encode(writer)
.expect("Error to encode input message");
ret.extend((cb)(data.secure, &buffer[..len]).iter())
}
ret
}

pub fn get_certificate_chain_buffer(
hash_algo: SpdmBaseHashAlgo,
cert_chain: &[u8],
) -> SpdmCertChainBuffer {
let (root_cert_begin, root_cert_end) =
crypto::cert_operation::get_cert_from_cert_chain(cert_chain, 0)
.expect("Get provisioned root cert failed");

let root_cert_hash =
crypto::hash::hash_all(hash_algo, &cert_chain[root_cert_begin..root_cert_end])
.expect("Must provide hash algo");
SpdmCertChainBuffer::new(cert_chain, root_cert_hash.as_ref())
.expect("Create format certificate chain failed.")
}
}

pub struct ResponderRunner;
impl ResponderRunner {
pub fn run(case: TestCase, cb: fn(secure: u8, bufer: &[u8]) -> VecDeque<u8>) -> bool {
use super::secret_callback::FAKE_SECRET_ASYM_IMPL_INSTANCE;
use crate::common::crypto_callback::{FAKE_AEAD, FAKE_ASYM_VERIFY, FAKE_RAND};
spdmlib::crypto::aead::register(FAKE_AEAD.clone());
spdmlib::crypto::rand::register(FAKE_RAND.clone());
spdmlib::crypto::asym_verify::register(FAKE_ASYM_VERIFY.clone());
spdmlib::secret::asym_sign::register(FAKE_SECRET_ASYM_IMPL_INSTANCE.clone());

let mut output = Arc::new(Mutex::new(VecDeque::<u8>::new()));
let mut rx = Arc::new(Mutex::new(case.input_to_vec(cb)));
let mut output_ref = Arc::clone(&output);
log::debug!("intput : {:02x?}", rx.lock().make_contiguous());
let future = async {
let mut device_io = TestSpdmDeviceIo::new(rx, output_ref);
let mut transport_encap = TestTransportEncap;
let (config_info, provision_info) = TestCase::config();
let mut context = responder::ResponderContext::new(
Arc::new(Mutex::new(device_io)),
Arc::new(Mutex::new(transport_encap)),
config_info,
provision_info,
);
let raw_packet = &mut [0u8; spdmlib::config::RECEIVER_BUFFER_SIZE];
loop {
let result = context.process_message(false, &[0], raw_packet).await;
match result {
Err(nread) => {
if nread == 0 {
break;
}
}
Ok(_) => continue,
}
}
};
executor::block_on(future);
// Check Result
// output and case.expected
let mut expected = case.expected_to_vec(cb);
let mut output = output.lock();
let output = output.make_contiguous();
let expected = expected.make_contiguous();
log::debug!("output : {:02x?}\n", output);
log::debug!("expected: {:02x?}\n", expected);
output == expected
}
}
1 change: 1 addition & 0 deletions test/spdmlib-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#![forbid(unsafe_code)]

pub mod common;
pub mod protocol;

#[cfg(test)]
mod test_client_server;
Expand Down
Loading

0 comments on commit 5126934

Please sign in to comment.