use crate::{
certs::{csv::Certificate, Usage, Verifiable},
crypto::{sig::ecdsa, PublicKey, Signature},
util::*,
};
use hex::encode;
use log::*;
use serde::{Deserialize, Serialize};
use std::ffi::c_void;
use std::io::Write;
#[repr(C)]
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub struct Body {
pub version: u32,
pub chip_id: [u8; 16],
#[serde(with = "serde_bytes")]
pub user_data: [u8; 64],
pub measure: [u8; 32],
#[serde(with = "serde_bytes")]
pub reserved: [u8; 128],
pub sig_usage: u32,
pub sig_algo: u32,
}
impl Default for Body {
fn default() -> Self {
Self {
version: Default::default(),
chip_id: Default::default(),
user_data: [0u8; 64],
measure: Default::default(),
reserved: [0u8; 128],
sig_usage: Default::default(),
sig_algo: Default::default(),
}
}
}
impl Body {
pub fn print_fields(&self) {
trace!("Version: {}", self.version);
trace!("Chip ID: {}", String::from_utf8_lossy(&self.chip_id));
trace!("User data: {}", encode(self.user_data));
trace!("Measure: {:?}", self.measure);
trace!("Signature Usage: {}", self.sig_usage);
trace!("Signature Algorithm: {}", self.sig_algo);
}
}
#[repr(C)]
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct AttestationReport {
pub body: Body,
pub sig: ecdsa::Signature,
}
impl AttestationReport {
pub fn print_report(&self) {
self.body.print_fields();
self.sig.print_fields();
}
}
impl Default for AttestationReport {
fn default() -> Self {
Self {
body: Default::default(),
sig: Default::default(),
}
}
}
#[repr(C)]
#[derive(Debug, serde::Deserialize)]
pub struct AttestationResponse {
pub report_size: u32,
pub reserved: [u8; 28],
pub report: AttestationReport,
}
impl Default for AttestationResponse {
fn default() -> Self {
Self {
report_size: 0,
reserved: [0u8; 28],
report: AttestationReport::default(),
}
}
}
impl AttestationResponse {
pub unsafe fn from_raw<'a>(ptr: *mut c_void) -> Option<&'a mut Self> {
if ptr.is_null() {
None
} else {
Some(&mut *(ptr as *mut Self))
}
}
}
impl codicon::Encoder<crate::Body> for AttestationReport {
type Error = std::io::Error;
fn encode(&self, mut writer: impl Write, _: crate::Body) -> Result<(), std::io::Error> {
writer.save(&self.body)
}
}
impl TryFrom<&AttestationReport> for Signature {
type Error = std::io::Error;
#[inline]
fn try_from(value: &AttestationReport) -> Result<Self, std::io::Error> {
let sig = Vec::try_from(&value.sig)?;
Ok(Self {
sig,
id: None,
usage: Usage::CEK,
algo: None,
})
}
}
impl Verifiable for (&Certificate, &AttestationReport) {
type Output = ();
fn verify(self) -> Result<(), std::io::Error> {
let key: PublicKey = self.0.try_into()?;
let sig: Signature = self.1.try_into()?;
key.verify(
self.1,
&self.0.body.data.user_id[..self.0.body.data.uid_size as usize],
&sig,
)
}
}