1use alloc::{
6 collections::BTreeMap,
7 string::{String, ToString},
8 vec::Vec,
9};
10use anyhow::{Context as _, Result};
11use hex::{encode as hex_encode, FromHexError};
12use serde::{Deserialize, Serialize};
13use serde_json::{from_str, Value};
14use sha2::Digest;
15
16#[cfg(feature = "borsh_schema")]
17use borsh::BorshSchema;
18#[cfg(feature = "borsh")]
19use borsh::{BorshDeserialize, BorshSerialize};
20
21const INIT_MR: &str = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
22
23fn replay_rtmr(history: Vec<String>) -> Result<String, FromHexError> {
24 if history.is_empty() {
25 return Ok(INIT_MR.to_string());
26 }
27 let mut mr = hex::decode(INIT_MR)?;
28 for content in history {
29 let mut content_bytes = hex::decode(content)?;
30 if content_bytes.len() < 48 {
31 content_bytes.resize(48, 0);
32 }
33 mr.extend_from_slice(&content_bytes);
34 mr = sha2::Sha384::digest(&mr).to_vec();
35 }
36 Ok(hex_encode(mr))
37}
38
39#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize, Deserialize)]
41#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
42#[cfg_attr(feature = "borsh_schema", derive(BorshSchema))]
43pub struct EventLog {
44 pub imr: u32,
46 pub event_type: u32,
48 pub digest: String,
50 pub event: String,
52 pub event_payload: String,
54}
55
56#[derive(Debug, bon::Builder, Serialize, Deserialize)]
58#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
59#[cfg_attr(feature = "borsh_schema", derive(BorshSchema))]
60pub struct TlsKeyConfig {
61 #[builder(into, default = String::new())]
63 pub subject: String,
64 #[builder(default = Vec::new())]
66 pub alt_names: Vec<String>,
67 #[builder(default = false)]
69 pub usage_ra_tls: bool,
70 #[builder(default = true)]
72 pub usage_server_auth: bool,
73 #[builder(default = false)]
75 pub usage_client_auth: bool,
76}
77
78#[derive(Debug, Serialize, Deserialize)]
80#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
81#[cfg_attr(feature = "borsh_schema", derive(BorshSchema))]
82pub struct GetKeyResponse {
83 pub key: String,
85 pub signature_chain: Vec<String>,
87}
88
89impl GetKeyResponse {
90 pub fn decode_key(&self) -> Result<Vec<u8>, FromHexError> {
91 hex::decode(&self.key)
92 }
93
94 pub fn decode_signature_chain(&self) -> Result<Vec<Vec<u8>>, FromHexError> {
95 self.signature_chain.iter().map(hex::decode).collect()
96 }
97}
98
99#[derive(Debug, Serialize, Deserialize)]
101#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
102#[cfg_attr(feature = "borsh_schema", derive(BorshSchema))]
103pub struct GetQuoteResponse {
104 pub quote: String,
106 pub event_log: String,
108 #[serde(default)]
110 pub report_data: String,
111 #[serde(default)]
113 pub vm_config: String,
114}
115
116#[derive(Debug, Serialize, Deserialize)]
118#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
119#[cfg_attr(feature = "borsh_schema", derive(BorshSchema))]
120pub struct AttestResponse {
121 pub attestation: String,
123}
124
125impl AttestResponse {
126 pub fn decode_attestation(&self) -> Result<Vec<u8>, FromHexError> {
127 hex::decode(&self.attestation)
128 }
129}
130
131impl GetQuoteResponse {
132 pub fn decode_quote(&self) -> Result<Vec<u8>, FromHexError> {
133 hex::decode(&self.quote)
134 }
135
136 pub fn decode_event_log(&self) -> Result<Vec<EventLog>, serde_json::Error> {
137 serde_json::from_str(&self.event_log)
138 }
139
140 pub fn replay_rtmrs(&self) -> Result<BTreeMap<u8, String>> {
141 let parsed_event_log: Vec<EventLog> = self.decode_event_log()?;
142 let mut rtmrs = BTreeMap::new();
143 for idx in 0..4 {
144 let mut history = Vec::new();
145 for event in &parsed_event_log {
146 if event.imr == idx {
147 history.push(event.digest.clone());
148 }
149 }
150 rtmrs.insert(
151 idx as u8,
152 replay_rtmr(history)
153 .ok()
154 .context("Invalid digest in event log")?,
155 );
156 }
157 Ok(rtmrs)
158 }
159}
160
161#[derive(Debug, Serialize, Deserialize)]
163#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
164#[cfg_attr(feature = "borsh_schema", derive(BorshSchema))]
165pub struct InfoResponse {
166 pub app_id: String,
168 pub instance_id: String,
170 pub app_cert: String,
172 pub tcb_info: TcbInfo,
174 pub app_name: String,
176 pub device_id: String,
178 #[serde(default)]
180 pub mr_aggregated: String,
181 #[serde(default)]
184 pub os_image_hash: String,
185 pub key_provider_info: String,
187 pub compose_hash: String,
189 #[serde(default)]
191 pub vm_config: String,
192}
193
194impl InfoResponse {
195 pub fn validated_from_value(mut obj: Value) -> Result<Self, serde_json::Error> {
196 if let Some(tcb_info_str) = obj.get("tcb_info").and_then(Value::as_str) {
197 let parsed_tcb_info: TcbInfo = from_str(tcb_info_str)?;
198 obj["tcb_info"] = serde_json::to_value(parsed_tcb_info)?;
199 }
200 serde_json::from_value(obj)
201 }
202}
203
204#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize, Deserialize)]
206#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
207#[cfg_attr(feature = "borsh_schema", derive(BorshSchema))]
208pub struct TcbInfo {
209 pub mrtd: String,
211 pub rtmr0: String,
213 pub rtmr1: String,
215 pub rtmr2: String,
217 pub rtmr3: String,
219 #[serde(default)]
221 pub os_image_hash: String,
222 pub compose_hash: String,
224 pub device_id: String,
226 pub app_compose: String,
228 pub event_log: Vec<EventLog>,
230}
231
232#[derive(Debug, Serialize, Deserialize)]
234#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
235#[cfg_attr(feature = "borsh_schema", derive(BorshSchema))]
236pub struct GetTlsKeyResponse {
237 pub key: String,
239 pub certificate_chain: Vec<String>,
241}
242
243#[derive(Debug, Serialize, Deserialize)]
245#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
246#[cfg_attr(feature = "borsh_schema", derive(BorshSchema))]
247pub struct SignResponse {
248 pub signature: String,
250 pub signature_chain: Vec<String>,
252 pub public_key: String,
254}
255
256impl SignResponse {
257 pub fn decode_signature(&self) -> Result<Vec<u8>, FromHexError> {
259 hex::decode(&self.signature)
260 }
261
262 pub fn decode_public_key(&self) -> Result<Vec<u8>, FromHexError> {
264 hex::decode(&self.public_key)
265 }
266
267 pub fn decode_signature_chain(&self) -> Result<Vec<Vec<u8>>, FromHexError> {
269 self.signature_chain.iter().map(hex::decode).collect()
270 }
271}
272
273#[derive(Debug, Serialize, Deserialize)]
275#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
276#[cfg_attr(feature = "borsh_schema", derive(BorshSchema))]
277pub struct VerifyResponse {
278 pub valid: bool,
280}
281
282#[derive(Debug, Clone, Serialize, Deserialize)]
284#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
285#[cfg_attr(feature = "borsh_schema", derive(BorshSchema))]
286pub struct VersionResponse {
287 pub version: String,
289 pub rev: String,
291}