Skip to main content

csv_rs/api/dcu/
types.rs

1// Copyright (C) Hygon Info Technologies Ltd.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6use crate::{
7    certs::{csv::Certificate, Usage, Verifiable},
8    crypto::{sig::ecdsa, PublicKey, Signature},
9    util::*,
10};
11
12use hex::encode;
13use log::*;
14use serde::{Deserialize, Serialize};
15use std::ffi::c_void;
16use std::io::Write;
17
18/// A structure representing the body of an attestation report.
19/// This is marked with `repr(C)` for C compatibility and can be serialized/deserialized.
20#[repr(C)]
21#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
22pub struct Body {
23    /// Version number of the attestation report format
24    pub version: u32,
25    /// Unique identifier of the hardware chip (16 bytes)
26    pub chip_id: [u8; 16],
27    /// User data value (64 bytes)
28    #[serde(with = "serde_bytes")]
29    pub user_data: [u8; 64],
30    /// Measurement data (32 bytes)
31    pub measure: [u8; 32],
32    /// Reserved data (128 bytes)
33    #[serde(with = "serde_bytes")]
34    pub reserved: [u8; 128],
35    /// Indicates the purpose/usage of the signature
36    pub sig_usage: u32,
37    /// Algorithm used for generating the signature
38    pub sig_algo: u32,
39}
40
41impl Default for Body {
42    /// Creates a default Body with all fields zero-initialized
43    fn default() -> Self {
44        Self {
45            version: Default::default(),
46            chip_id: Default::default(),
47            user_data: [0u8; 64],
48            measure: Default::default(),
49            reserved: [0u8; 128],
50            sig_usage: Default::default(),
51            sig_algo: Default::default(),
52        }
53    }
54}
55
56impl Body {
57    /// Prints each field of the `Body` struct in human-readable format
58    pub fn print_fields(&self) {
59        trace!("Version: {}", self.version);
60        trace!("Chip ID: {}", String::from_utf8_lossy(&self.chip_id));
61        trace!("User data: {}", encode(self.user_data));
62        trace!("Measure: {:?}", self.measure);
63        trace!("Signature Usage: {}", self.sig_usage);
64        trace!("Signature Algorithm: {}", self.sig_algo);
65    }
66}
67
68/// This structure contains both the report body and its cryptographic signature.
69#[repr(C)]
70#[derive(Debug, Serialize, Deserialize, Clone)]
71pub struct AttestationReport {
72    /// The main content of the attestation report
73    pub body: Body,
74    /// ECDSA signature verifying the report authenticity
75    pub sig: ecdsa::Signature,
76}
77
78impl AttestationReport {
79    /// Prints both the body and signature fields of the attestation report
80    pub fn print_report(&self) {
81        self.body.print_fields();
82        self.sig.print_fields();
83    }
84}
85
86impl Default for AttestationReport {
87    /// Creates a default AttestationReport with empty body and signature
88    fn default() -> Self {
89        Self {
90            body: Default::default(),
91            sig: Default::default(),
92        }
93    }
94}
95
96/// Response structure containing the attestation report from the dcu devices
97#[repr(C)]
98#[derive(Debug, serde::Deserialize)]
99pub struct AttestationResponse {
100    /// Size of the contained report in bytes
101    pub report_size: u32,
102    /// Reserved space for future extensions (28 bytes)
103    pub reserved: [u8; 28],
104    /// The actual attestation report data
105    pub report: AttestationReport,
106}
107
108impl Default for AttestationResponse {
109    /// Creates a default response with zero-sized report and empty fields
110    fn default() -> Self {
111        Self {
112            report_size: 0,
113            reserved: [0u8; 28],
114            report: AttestationReport::default(),
115        }
116    }
117}
118
119impl AttestationResponse {
120    /// Safely constructs a mutable reference from a raw C pointer
121    /// # Safety
122    /// Caller must ensure the pointer is valid and properly aligned
123    pub unsafe fn from_raw<'a>(ptr: *mut c_void) -> Option<&'a mut Self> {
124        if ptr.is_null() {
125            None
126        } else {
127            Some(&mut *(ptr as *mut Self))
128        }
129    }
130}
131
132/// Implementation of encoding functionality for AttestationReport
133impl codicon::Encoder<crate::Body> for AttestationReport {
134    type Error = std::io::Error;
135
136    /// Encodes the report body into the writer
137    fn encode(&self, mut writer: impl Write, _: crate::Body) -> Result<(), std::io::Error> {
138        writer.save(&self.body)
139    }
140}
141
142impl TryFrom<&AttestationReport> for Signature {
143    type Error = std::io::Error;
144
145    /// Attempts to convert an AttestationReport into a Signature structure
146    #[inline]
147    fn try_from(value: &AttestationReport) -> Result<Self, std::io::Error> {
148        let sig = Vec::try_from(&value.sig)?;
149        Ok(Self {
150            sig,
151            id: None,
152            usage: Usage::CEK,
153            algo: None,
154        })
155    }
156}
157
158/// Implementation of verification for a certificate and attestation report pair
159impl Verifiable for (&Certificate, &AttestationReport) {
160    type Output = ();
161
162    /// Verifies the attestation report using the provided certificate
163    fn verify(self) -> Result<(), std::io::Error> {
164        let key: PublicKey = self.0.try_into()?;
165        let sig: Signature = self.1.try_into()?;
166        key.verify(
167            self.1,
168            &self.0.body.data.user_id[..self.0.body.data.uid_size as usize],
169            &sig,
170        )
171    }
172}