tss_esapi/context/tpm_commands/attestation_commands.rs
1// Copyright 2021 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3use crate::{
4 handles::{KeyHandle, ObjectHandle},
5 structures::{Attest, AttestBuffer, Data, PcrSelectionList, Signature, SignatureScheme},
6 tss2_esys::{Esys_Certify, Esys_GetTime, Esys_Quote},
7 Context, Error, Result,
8};
9use log::error;
10use std::convert::TryFrom;
11use std::ptr::null_mut;
12
13impl Context {
14 /// Prove that an object is loaded in the TPM
15 ///
16 /// # Arguments
17 /// * `object_handle` - Handle of the object to be certified
18 /// * `signing_key_handle` - Handle of the key used to sign the attestation buffer
19 /// * `qualifying_data` - Qualifying data
20 /// * `signing_scheme` - Signing scheme to use if the scheme for `signing_key_handle` is `Null`.
21 ///
22 /// The object may be any object that is loaded with [Self::load()] or [Self::create_primary()]. An object that
23 /// only has its public area loaded may not be certified.
24 ///
25 /// The `signing_key_handle` must be usable for signing.
26 ///
27 /// If `signing_key_handle` has the Restricted attribute set to `true` then `signing_scheme` must be
28 /// [SignatureScheme::Null].
29 ///
30 /// # Returns
31 /// The command returns a tuple consisting of:
32 /// * `attest_data` - TPM-generated attestation data.
33 /// * `signature` - Signature for the attestation data.
34 ///
35 /// # Errors
36 /// * if the qualifying data provided is too long, a `WrongParamSize` wrapper error will be returned
37 ///
38 /// # Examples
39 ///
40 /// ```rust
41 /// # use tss_esapi::{Context, TctiNameConf};
42 /// # use std::convert::TryFrom;
43 /// # use tss_esapi::{
44 /// # abstraction::cipher::Cipher,
45 /// # handles::KeyHandle,
46 /// # interface_types::{
47 /// # algorithm::{HashingAlgorithm, RsaSchemeAlgorithm, SignatureSchemeAlgorithm},
48 /// # key_bits::RsaKeyBits,
49 /// # resource_handles::Hierarchy,
50 /// # },
51 /// # structures::{
52 /// # RsaExponent, RsaScheme, SymmetricDefinition,
53 /// # },
54 /// # utils::{create_unrestricted_signing_rsa_public, create_restricted_decryption_rsa_public},
55 /// # };
56 /// use std::convert::TryInto;
57 /// use tss_esapi::{
58 /// structures::{Data, SignatureScheme},
59 /// interface_types::session_handles::AuthSession,
60 /// };
61 /// # let mut context =
62 /// # Context::new(
63 /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
64 /// # ).expect("Failed to create Context");
65 /// let qualifying_data = vec![0xff; 16];
66 /// # let signing_key_pub = create_unrestricted_signing_rsa_public(
67 /// # RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256))
68 /// # .expect("Failed to create RSA scheme"),
69 /// # RsaKeyBits::Rsa2048,
70 /// # RsaExponent::default(),
71 /// # )
72 /// # .expect("Failed to create an unrestricted signing rsa public structure");
73 /// # let sign_key_handle = context
74 /// # .execute_with_nullauth_session(|ctx| {
75 /// # ctx.create_primary(Hierarchy::Owner, signing_key_pub, None, None, None, None)
76 /// # })
77 /// # .unwrap()
78 /// # .key_handle;
79 /// # let decryption_key_pub = create_restricted_decryption_rsa_public(
80 /// # Cipher::aes_256_cfb()
81 /// # .try_into()
82 /// # .expect("Failed to create symmetric object"),
83 /// # RsaKeyBits::Rsa2048,
84 /// # RsaExponent::default(),
85 /// # )
86 /// # .expect("Failed to create a restricted decryption rsa public structure");
87 /// # let obj_key_handle = context
88 /// # .execute_with_nullauth_session(|ctx| {
89 /// # ctx.create_primary(
90 /// # Hierarchy::Owner,
91 /// # decryption_key_pub,
92 /// # None,
93 /// # None,
94 /// # None,
95 /// # None,
96 /// # )
97 /// # })
98 /// # .unwrap()
99 /// # .key_handle;
100 /// let (attest, signature) = context
101 /// .execute_with_sessions(
102 /// (
103 /// Some(AuthSession::Password),
104 /// Some(AuthSession::Password),
105 /// None,
106 /// ),
107 /// |ctx| {
108 /// ctx.certify(
109 /// obj_key_handle.into(),
110 /// sign_key_handle,
111 /// Data::try_from(qualifying_data).unwrap(),
112 /// SignatureScheme::Null,
113 /// )
114 /// },
115 /// )
116 /// .expect("Failed to certify object handle");
117 /// ```
118 pub fn certify(
119 &mut self,
120 object_handle: ObjectHandle,
121 signing_key_handle: KeyHandle,
122 qualifying_data: Data,
123 signing_scheme: SignatureScheme,
124 ) -> Result<(Attest, Signature)> {
125 let mut certify_info_ptr = null_mut();
126 let mut signature_ptr = null_mut();
127 let ret = unsafe {
128 Esys_Certify(
129 self.mut_context(),
130 object_handle.into(),
131 signing_key_handle.into(),
132 self.required_session_1()?,
133 self.required_session_2()?,
134 self.optional_session_3(),
135 &qualifying_data.into(),
136 &signing_scheme.into(),
137 &mut certify_info_ptr,
138 &mut signature_ptr,
139 )
140 };
141 let ret = Error::from_tss_rc(ret);
142
143 if ret.is_success() {
144 let certify_info = Context::ffi_data_to_owned(certify_info_ptr);
145 let signature = Context::ffi_data_to_owned(signature_ptr);
146 Ok((
147 Attest::try_from(AttestBuffer::try_from(certify_info)?)?,
148 Signature::try_from(signature)?,
149 ))
150 } else {
151 error!("Error in certifying: {}", ret);
152 Err(ret)
153 }
154 }
155
156 // Missing function: CertifyCreation
157
158 /// Generate a quote on the selected PCRs
159 ///
160 /// # Errors
161 /// * if the qualifying data provided is too long, a `WrongParamSize` wrapper error will be returned
162 pub fn quote(
163 &mut self,
164 signing_key_handle: KeyHandle,
165 qualifying_data: Data,
166 signing_scheme: SignatureScheme,
167 pcr_selection_list: PcrSelectionList,
168 ) -> Result<(Attest, Signature)> {
169 let mut quoted_ptr = null_mut();
170 let mut signature_ptr = null_mut();
171 let ret = unsafe {
172 Esys_Quote(
173 self.mut_context(),
174 signing_key_handle.into(),
175 self.optional_session_1(),
176 self.optional_session_2(),
177 self.optional_session_3(),
178 &qualifying_data.into(),
179 &signing_scheme.into(),
180 &pcr_selection_list.into(),
181 &mut quoted_ptr,
182 &mut signature_ptr,
183 )
184 };
185 let ret = Error::from_tss_rc(ret);
186
187 if ret.is_success() {
188 let quoted = Context::ffi_data_to_owned(quoted_ptr);
189 let signature = Context::ffi_data_to_owned(signature_ptr);
190 Ok((
191 Attest::try_from(AttestBuffer::try_from(quoted)?)?,
192 Signature::try_from(signature)?,
193 ))
194 } else {
195 error!("Error in quoting PCR: {}", ret);
196 Err(ret)
197 }
198 }
199
200 /// Get the current time and clock from the TPM
201 ///
202 /// # Arguments
203 /// * `signing_key_handle` - Handle of the key used to sign the attestation buffer
204 /// * `qualifying_data` - Qualifying data
205 /// * `signing_scheme` - Signing scheme to use if the scheme for `signing_key_handle` is `Null`.
206 ///
207 /// The `signing_key_handle` must be usable for signing.
208 ///
209 /// If `signing_key_handle` has the Restricted attribute set to `true` then `signing_scheme` must be
210 /// [SignatureScheme::Null].
211 ///
212 /// # Returns
213 /// The command returns a tuple consisting of:
214 /// * `attest_data` - TPM-generated attestation data.
215 /// * `signature` - Signature for the attestation data.
216 ///
217 /// # Errors
218 /// * if the qualifying data provided is too long, a `WrongParamSize` wrapper error will be returned
219 ///
220 /// # Examples
221 ///
222 /// ```rust
223 /// # use tss_esapi::{Context, TctiNameConf};
224 /// # use std::convert::TryFrom;
225 /// # use tss_esapi::{
226 /// # abstraction::cipher::Cipher,
227 /// # interface_types::{
228 /// # algorithm::{HashingAlgorithm, RsaSchemeAlgorithm},
229 /// # key_bits::RsaKeyBits,
230 /// # resource_handles::Hierarchy,
231 /// # },
232 /// # structures::{
233 /// # RsaExponent, RsaScheme,
234 /// # },
235 /// # utils::{create_unrestricted_signing_rsa_public, create_restricted_decryption_rsa_public},
236 /// # };
237 /// use std::convert::TryInto;
238 /// use tss_esapi::{
239 /// structures::{Data, SignatureScheme},
240 /// interface_types::session_handles::AuthSession,
241 /// };
242 /// # let mut context =
243 /// # Context::new(
244 /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
245 /// # ).expect("Failed to create Context");
246 /// let qualifying_data = vec![0xff; 16];
247 /// # let signing_key_pub = create_unrestricted_signing_rsa_public(
248 /// # RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256))
249 /// # .expect("Failed to create RSA scheme"),
250 /// # RsaKeyBits::Rsa2048,
251 /// # RsaExponent::default(),
252 /// # )
253 /// # .expect("Failed to create an unrestricted signing rsa public structure");
254 /// # let sign_key_handle = context
255 /// # .execute_with_nullauth_session(|ctx| {
256 /// # ctx.create_primary(Hierarchy::Owner, signing_key_pub, None, None, None, None)
257 /// # })
258 /// # .unwrap()
259 /// # .key_handle;
260 /// let (attest, signature) = context
261 /// .execute_with_sessions(
262 /// (
263 /// Some(AuthSession::Password),
264 /// Some(AuthSession::Password),
265 /// None,
266 /// ),
267 /// |ctx| {
268 /// ctx.get_time(
269 /// sign_key_handle,
270 /// Data::try_from(qualifying_data).unwrap(),
271 /// SignatureScheme::Null,
272 /// )
273 /// },
274 /// )
275 /// .expect("Failed to get tpm time");
276 /// ```
277 pub fn get_time(
278 &mut self,
279 signing_key_handle: KeyHandle,
280 qualifying_data: Data,
281 signing_scheme: SignatureScheme,
282 ) -> Result<(Attest, Signature)> {
283 let mut timeinfo_ptr = null_mut();
284 let mut signature_ptr = null_mut();
285 let ret = unsafe {
286 Esys_GetTime(
287 self.mut_context(),
288 ObjectHandle::Endorsement.into(),
289 signing_key_handle.into(),
290 self.required_session_1()?,
291 self.required_session_2()?,
292 self.optional_session_3(),
293 &qualifying_data.into(),
294 &signing_scheme.into(),
295 &mut timeinfo_ptr,
296 &mut signature_ptr,
297 )
298 };
299
300 let ret = Error::from_tss_rc(ret);
301
302 if ret.is_success() {
303 let timeinfo = Context::ffi_data_to_owned(timeinfo_ptr);
304 let signature = Context::ffi_data_to_owned(signature_ptr);
305 Ok((
306 Attest::try_from(AttestBuffer::try_from(timeinfo)?)?,
307 Signature::try_from(signature)?,
308 ))
309 } else {
310 error!("Error in Get Time: {}", ret);
311 Err(ret)
312 }
313 }
314
315 // Missing function: GetSessionAuditDigest
316 // Missing function: GestCommandAuditDigest
317 // Missing function: CertifyX509
318}