tss_esapi/structures/attestation/
attest.rs1use crate::{
5 constants::tss::TPM2_GENERATED_VALUE,
6 interface_types::structure_tags::AttestationType,
7 structures::{AttestInfo, ClockInfo, Data, Name},
8 traits::{Marshall, UnMarshall},
9 tss2_esys::TPMS_ATTEST,
10 Error, Result, WrapperErrorKind,
11};
12use log::error;
13use std::{
14 convert::{TryFrom, TryInto},
15 mem::size_of,
16};
17
18#[derive(Debug, Clone)]
23pub struct Attest {
24 attestation_type: AttestationType,
25 qualified_signer: Name,
26 extra_data: Data,
27 clock_info: ClockInfo,
28 firmware_version: u64,
29 attested: AttestInfo,
30}
31
32impl Attest {
33 pub const fn attestation_type(&self) -> AttestationType {
35 self.attestation_type
36 }
37
38 pub const fn qualified_signer(&self) -> &Name {
40 &self.qualified_signer
41 }
42
43 pub const fn extra_data(&self) -> &Data {
45 &self.extra_data
46 }
47
48 pub const fn clock_info(&self) -> &ClockInfo {
50 &self.clock_info
51 }
52
53 pub const fn firmware_version(&self) -> u64 {
55 self.firmware_version
56 }
57
58 pub const fn attested(&self) -> &AttestInfo {
60 &self.attested
61 }
62}
63
64impl From<Attest> for TPMS_ATTEST {
65 fn from(attest: Attest) -> Self {
66 TPMS_ATTEST {
67 magic: TPM2_GENERATED_VALUE,
68 type_: attest.attestation_type.into(),
69 qualifiedSigner: attest.qualified_signer.into(),
70 extraData: attest.extra_data.into(),
71 clockInfo: attest.clock_info.into(),
72 firmwareVersion: attest.firmware_version,
73 attested: attest.attested.into(),
74 }
75 }
76}
77
78impl TryFrom<TPMS_ATTEST> for Attest {
79 type Error = Error;
80
81 fn try_from(tpms_attest: TPMS_ATTEST) -> Result<Self> {
82 if tpms_attest.magic != TPM2_GENERATED_VALUE {
83 return Err(Error::local_error(WrapperErrorKind::InvalidParam));
84 }
85
86 let attestation_type = AttestationType::try_from(tpms_attest.type_)?;
87 Ok(Attest {
88 attestation_type,
89 qualified_signer: Name::try_from(tpms_attest.qualifiedSigner)?,
90 extra_data: Data::try_from(tpms_attest.extraData)?,
91 clock_info: ClockInfo::try_from(tpms_attest.clockInfo)?,
92 firmware_version: tpms_attest.firmwareVersion,
93 attested: match attestation_type {
94 AttestationType::Certify => AttestInfo::Certify {
95 info: unsafe { tpms_attest.attested.certify }.try_into()?,
96 },
97 AttestationType::Quote => AttestInfo::Quote {
98 info: unsafe { tpms_attest.attested.quote }.try_into()?,
99 },
100 AttestationType::SessionAudit => AttestInfo::SessionAudit {
101 info: unsafe { tpms_attest.attested.sessionAudit }.try_into()?,
102 },
103 AttestationType::CommandAudit => AttestInfo::CommandAudit {
104 info: unsafe { tpms_attest.attested.commandAudit }.try_into()?,
105 },
106 AttestationType::Time => AttestInfo::Time {
107 info: unsafe { tpms_attest.attested.time }.try_into()?,
108 },
109 AttestationType::Creation => AttestInfo::Creation {
110 info: unsafe { tpms_attest.attested.creation }.try_into()?,
111 },
112 AttestationType::Nv => AttestInfo::Nv {
113 info: unsafe { tpms_attest.attested.nv }.try_into()?,
114 },
115 AttestationType::NvDigest => {
116 error!("NvDigest attestation type is currently not supported");
117 return Err(Error::local_error(WrapperErrorKind::UnsupportedParam));
118 }
119 },
120 })
121 }
122}
123
124impl Marshall for Attest {
125 const BUFFER_SIZE: usize = size_of::<TPMS_ATTEST>();
126
127 fn marshall(&self) -> Result<Vec<u8>> {
129 let mut buffer = vec![0; Self::BUFFER_SIZE];
130 let mut offset = 0;
131
132 let ret = Error::from_tss_rc(unsafe {
133 crate::tss2_esys::Tss2_MU_TPMS_ATTEST_Marshal(
134 &self.clone().into(),
135 buffer.as_mut_ptr(),
136 Self::BUFFER_SIZE.try_into().map_err(|e| {
137 error!("Failed to convert size of buffer to TSS size_t type: {}", e);
138 Error::local_error(WrapperErrorKind::InvalidParam)
139 })?,
140 &mut offset,
141 )
142 });
143
144 if !ret.is_success() {
145 return Err(ret);
146 }
147
148 let checked_offset = usize::try_from(offset).map_err(|e| {
149 error!("Failed to parse offset as usize: {}", e);
150 Error::local_error(WrapperErrorKind::InvalidParam)
151 })?;
152
153 buffer.truncate(checked_offset);
154
155 Ok(buffer)
156 }
157}
158
159impl UnMarshall for Attest {
160 fn unmarshall(marshalled_data: &[u8]) -> Result<Self> {
162 let mut dest = TPMS_ATTEST::default();
163 let mut offset = 0;
164
165 let ret = Error::from_tss_rc(unsafe {
166 crate::tss2_esys::Tss2_MU_TPMS_ATTEST_Unmarshal(
167 marshalled_data.as_ptr(),
168 marshalled_data.len().try_into().map_err(|e| {
169 error!("Failed to convert length of marshalled data: {}", e);
170 Error::local_error(WrapperErrorKind::InvalidParam)
171 })?,
172 &mut offset,
173 &mut dest,
174 )
175 });
176
177 if !ret.is_success() {
178 return Err(ret);
179 }
180
181 Attest::try_from(dest)
182 }
183}