1use crate::{
4 context::handle_manager::HandleDropAction,
5 handles::{KeyHandle, ObjectHandle, TpmHandle},
6 interface_types::resource_handles::Hierarchy,
7 structures::{
8 Auth, CreateKeyResult, CreationData, CreationTicket, Data, Digest, EncryptedSecret,
9 IdObject, Name, PcrSelectionList, Private, Public, Sensitive, SensitiveData,
10 },
11 tss2_esys::{
12 Esys_ActivateCredential, Esys_Create, Esys_Load, Esys_LoadExternal, Esys_MakeCredential,
13 Esys_ObjectChangeAuth, Esys_ReadPublic, Esys_Unseal, TPM2B_SENSITIVE_CREATE,
14 TPMS_SENSITIVE_CREATE,
15 },
16 Context, Error, Result,
17};
18use log::error;
19use std::{
20 convert::{TryFrom, TryInto},
21 mem::size_of,
22 ptr::{null, null_mut},
23};
24
25impl Context {
26 #[allow(clippy::too_many_arguments)]
46 pub fn create(
47 &mut self,
48 parent_handle: KeyHandle,
49 public: Public,
50 auth_value: Option<Auth>,
51 sensitive_data: Option<SensitiveData>,
52 outside_info: Option<Data>,
53 creation_pcrs: Option<PcrSelectionList>,
54 ) -> Result<CreateKeyResult> {
55 let sensitive_create = TPM2B_SENSITIVE_CREATE {
56 #[allow(unused_qualifications)]
57 size: size_of::<TPMS_SENSITIVE_CREATE>().try_into().unwrap(), sensitive: TPMS_SENSITIVE_CREATE {
59 userAuth: auth_value.unwrap_or_default().into(),
60 data: sensitive_data.unwrap_or_default().into(),
61 },
62 };
63 let creation_pcrs = PcrSelectionList::list_from_option(creation_pcrs);
64
65 let mut out_public_ptr = null_mut();
66 let mut out_private_ptr = null_mut();
67 let mut creation_data_ptr = null_mut();
68 let mut creation_hash_ptr = null_mut();
69 let mut creation_ticket_ptr = null_mut();
70
71 let ret = unsafe {
72 Esys_Create(
73 self.mut_context(),
74 parent_handle.into(),
75 self.optional_session_1(),
76 self.optional_session_2(),
77 self.optional_session_3(),
78 &sensitive_create,
79 &public.try_into()?,
80 &outside_info.unwrap_or_default().into(),
81 &creation_pcrs.into(),
82 &mut out_private_ptr,
83 &mut out_public_ptr,
84 &mut creation_data_ptr,
85 &mut creation_hash_ptr,
86 &mut creation_ticket_ptr,
87 )
88 };
89 let ret = Error::from_tss_rc(ret);
90
91 if ret.is_success() {
92 let out_private_owned = Context::ffi_data_to_owned(out_private_ptr);
93 let out_public_owned = Context::ffi_data_to_owned(out_public_ptr);
94 let creation_data_owned = Context::ffi_data_to_owned(creation_data_ptr);
95 let creation_hash_owned = Context::ffi_data_to_owned(creation_hash_ptr);
96 let creation_ticket_owned = Context::ffi_data_to_owned(creation_ticket_ptr);
97 Ok(CreateKeyResult {
98 out_private: Private::try_from(out_private_owned)?,
99 out_public: Public::try_from(out_public_owned)?,
100 creation_data: CreationData::try_from(creation_data_owned)?,
101 creation_hash: Digest::try_from(creation_hash_owned)?,
102 creation_ticket: CreationTicket::try_from(creation_ticket_owned)?,
103 })
104 } else {
105 error!("Error in creating derived key: {}", ret);
106 Err(ret)
107 }
108 }
109
110 pub fn load(
112 &mut self,
113 parent_handle: KeyHandle,
114 private: Private,
115 public: Public,
116 ) -> Result<KeyHandle> {
117 let mut object_handle = ObjectHandle::None.into();
118 let ret = unsafe {
119 Esys_Load(
120 self.mut_context(),
121 parent_handle.into(),
122 self.optional_session_1(),
123 self.optional_session_2(),
124 self.optional_session_3(),
125 &private.into(),
126 &public.try_into()?,
127 &mut object_handle,
128 )
129 };
130 let ret = Error::from_tss_rc(ret);
131 if ret.is_success() {
132 let key_handle = KeyHandle::from(object_handle);
133 self.handle_manager
134 .add_handle(key_handle.into(), HandleDropAction::Flush)?;
135 Ok(key_handle)
136 } else {
137 error!("Error in loading: {}", ret);
138 Err(ret)
139 }
140 }
141
142 pub fn load_external(
144 &mut self,
145 private: Sensitive,
146 public: Public,
147 hierarchy: Hierarchy,
148 ) -> Result<KeyHandle> {
149 let mut object_handle = ObjectHandle::None.into();
150 let ret = unsafe {
151 #[allow(unexpected_cfgs)]
152 Esys_LoadExternal(
153 self.mut_context(),
154 self.optional_session_1(),
155 self.optional_session_2(),
156 self.optional_session_3(),
157 &private.try_into()?,
158 &public.try_into()?,
159 if cfg!(tpm2_tss_version = "2") {
160 TpmHandle::from(hierarchy).into()
161 } else {
162 ObjectHandle::from(hierarchy).into()
163 },
164 &mut object_handle,
165 )
166 };
167
168 let ret = Error::from_tss_rc(ret);
169
170 if ret.is_success() {
171 let key_handle = KeyHandle::from(object_handle);
172 self.handle_manager
173 .add_handle(key_handle.into(), HandleDropAction::Flush)?;
174 Ok(key_handle)
175 } else {
176 error!("Error in loading external object: {}", ret);
177 Err(ret)
178 }
179 }
180
181 pub fn load_external_public(
183 &mut self,
184 public: Public,
185 hierarchy: Hierarchy,
186 ) -> Result<KeyHandle> {
187 let mut object_handle = ObjectHandle::None.into();
188 let ret = unsafe {
189 #[allow(unexpected_cfgs)]
190 Esys_LoadExternal(
191 self.mut_context(),
192 self.optional_session_1(),
193 self.optional_session_2(),
194 self.optional_session_3(),
195 null(),
196 &public.try_into()?,
197 if cfg!(tpm2_tss_version = "2") {
198 TpmHandle::from(hierarchy).into()
199 } else {
200 ObjectHandle::from(hierarchy).into()
201 },
202 &mut object_handle,
203 )
204 };
205
206 let ret = Error::from_tss_rc(ret);
207
208 if ret.is_success() {
209 let key_handle = KeyHandle::from(object_handle);
210 self.handle_manager
211 .add_handle(key_handle.into(), HandleDropAction::Flush)?;
212 Ok(key_handle)
213 } else {
214 error!("Error in loading external public object: {}", ret);
215 Err(ret)
216 }
217 }
218
219 pub fn read_public(&mut self, key_handle: KeyHandle) -> Result<(Public, Name, Name)> {
221 let mut out_public_ptr = null_mut();
222 let mut name_ptr = null_mut();
223 let mut qualified_name_ptr = null_mut();
224 let ret = unsafe {
225 Esys_ReadPublic(
226 self.mut_context(),
227 key_handle.into(),
228 self.optional_session_1(),
229 self.optional_session_2(),
230 self.optional_session_3(),
231 &mut out_public_ptr,
232 &mut name_ptr,
233 &mut qualified_name_ptr,
234 )
235 };
236 let ret = Error::from_tss_rc(ret);
237
238 if ret.is_success() {
239 Ok((
240 Public::try_from(Context::ffi_data_to_owned(out_public_ptr))?,
241 Name::try_from(Context::ffi_data_to_owned(name_ptr))?,
242 Name::try_from(Context::ffi_data_to_owned(qualified_name_ptr))?,
243 ))
244 } else {
245 error!("Error in reading public part of object: {}", ret);
246 Err(ret)
247 }
248 }
249
250 pub fn activate_credential(
252 &mut self,
253 activate_handle: KeyHandle,
254 key_handle: KeyHandle,
255 credential_blob: IdObject,
256 secret: EncryptedSecret,
257 ) -> Result<Digest> {
258 let mut cert_info_ptr = null_mut();
259 let ret = unsafe {
260 Esys_ActivateCredential(
261 self.mut_context(),
262 activate_handle.into(),
263 key_handle.into(),
264 self.required_session_1()?,
265 self.required_session_2()?,
266 self.optional_session_3(),
267 &credential_blob.into(),
268 &secret.into(),
269 &mut cert_info_ptr,
270 )
271 };
272
273 let ret = Error::from_tss_rc(ret);
274
275 if ret.is_success() {
276 Digest::try_from(Context::ffi_data_to_owned(cert_info_ptr))
277 } else {
278 error!("Error when activating credential: {}", ret);
279 Err(ret)
280 }
281 }
282
283 pub fn make_credential(
287 &mut self,
288 key_handle: KeyHandle,
289 credential: Digest,
290 object_name: Name,
291 ) -> Result<(IdObject, EncryptedSecret)> {
292 let mut credential_blob_ptr = null_mut();
293 let mut secret_ptr = null_mut();
294 let ret = unsafe {
295 Esys_MakeCredential(
296 self.mut_context(),
297 key_handle.into(),
298 self.optional_session_1(),
299 self.optional_session_2(),
300 self.optional_session_3(),
301 &credential.into(),
302 object_name.as_ref(),
303 &mut credential_blob_ptr,
304 &mut secret_ptr,
305 )
306 };
307
308 let ret = Error::from_tss_rc(ret);
309
310 if ret.is_success() {
311 Ok((
312 IdObject::try_from(Context::ffi_data_to_owned(credential_blob_ptr))?,
313 EncryptedSecret::try_from(Context::ffi_data_to_owned(secret_ptr))?,
314 ))
315 } else {
316 error!("Error when making credential: {}", ret);
317 Err(ret)
318 }
319 }
320
321 pub fn unseal(&mut self, item_handle: ObjectHandle) -> Result<SensitiveData> {
323 let mut out_data_ptr = null_mut();
324
325 let ret = unsafe {
326 Esys_Unseal(
327 self.mut_context(),
328 item_handle.into(),
329 self.optional_session_1(),
330 self.optional_session_2(),
331 self.optional_session_3(),
332 &mut out_data_ptr,
333 )
334 };
335 let ret = Error::from_tss_rc(ret);
336
337 if ret.is_success() {
338 SensitiveData::try_from(Context::ffi_data_to_owned(out_data_ptr))
339 } else {
340 error!("Error in unsealing: {}", ret);
341 Err(ret)
342 }
343 }
344
345 pub fn object_change_auth(
347 &mut self,
348 object_handle: ObjectHandle,
349 parent_handle: ObjectHandle,
350 new_auth: Auth,
351 ) -> Result<Private> {
352 let mut out_private_ptr = null_mut();
353 let ret = unsafe {
354 Esys_ObjectChangeAuth(
355 self.mut_context(),
356 object_handle.into(),
357 parent_handle.into(),
358 self.required_session_1()?,
359 self.optional_session_2(),
360 self.optional_session_3(),
361 &new_auth.into(),
362 &mut out_private_ptr,
363 )
364 };
365 let ret = Error::from_tss_rc(ret);
366 if ret.is_success() {
367 Private::try_from(Context::ffi_data_to_owned(out_private_ptr))
368 } else {
369 error!("Error changing object auth: {}", ret);
370 Err(ret)
371 }
372 }
373
374 }