1pub mod ecc;
4pub mod keyed_hash;
5pub mod rsa;
6
7use crate::{
8 attributes::ObjectAttributes,
9 interface_types::algorithm::{HashingAlgorithm, PublicAlgorithm},
10 structures::{
11 Digest, EccPoint, PublicKeyRsa, SymmetricCipherParameters, SymmetricDefinitionObject,
12 },
13 traits::{Marshall, UnMarshall},
14 tss2_esys::{TPM2B_PUBLIC, TPMT_PUBLIC},
15 Error, Result, WrapperErrorKind,
16};
17
18use ecc::PublicEccParameters;
19use keyed_hash::PublicKeyedHashParameters;
20use rsa::PublicRsaParameters;
21
22use log::error;
23use std::{
24 convert::{TryFrom, TryInto},
25 mem::size_of,
26};
27use tss_esapi_sys::{TPMU_PUBLIC_ID, TPMU_PUBLIC_PARMS};
28
29#[derive(Debug, Clone)]
31pub struct PublicBuilder {
32 public_algorithm: Option<PublicAlgorithm>,
33 object_attributes: Option<ObjectAttributes>,
34 name_hashing_algorithm: Option<HashingAlgorithm>,
35 auth_policy: Option<Digest>,
36 rsa_parameters: Option<PublicRsaParameters>,
37 rsa_unique_identifier: Option<PublicKeyRsa>,
38 keyed_hash_parameters: Option<PublicKeyedHashParameters>,
39 keyed_hash_unique_identifier: Option<Digest>,
40 ecc_parameters: Option<PublicEccParameters>,
41 ecc_unique_identifier: Option<EccPoint>,
42 symmetric_cipher_parameters: Option<SymmetricCipherParameters>,
43 symmetric_cipher_unique_identifier: Option<Digest>,
44}
45
46impl PublicBuilder {
47 pub const fn new() -> Self {
54 PublicBuilder {
55 public_algorithm: None,
56 object_attributes: None,
57 name_hashing_algorithm: None,
58 auth_policy: None,
59 rsa_parameters: None,
60 rsa_unique_identifier: None,
61 keyed_hash_parameters: None,
62 keyed_hash_unique_identifier: None,
63 ecc_parameters: None,
64 ecc_unique_identifier: None,
65 symmetric_cipher_parameters: None,
66 symmetric_cipher_unique_identifier: None,
67 }
68 }
69
70 pub const fn with_public_algorithm(mut self, public_algorithm: PublicAlgorithm) -> Self {
73 self.public_algorithm = Some(public_algorithm);
74 self
75 }
76
77 pub const fn with_object_attributes(mut self, object_attributes: ObjectAttributes) -> Self {
80 self.object_attributes = Some(object_attributes);
81 self
82 }
83
84 pub const fn with_name_hashing_algorithm(
87 mut self,
88 name_hashing_algorithm: HashingAlgorithm,
89 ) -> Self {
90 self.name_hashing_algorithm = Some(name_hashing_algorithm);
91 self
92 }
93
94 pub fn with_auth_policy(mut self, auth_policy: Digest) -> Self {
97 self.auth_policy = Some(auth_policy);
98 self
99 }
100
101 pub fn with_rsa_parameters(mut self, rsa_parameters: PublicRsaParameters) -> Self {
108 self.rsa_parameters = Some(rsa_parameters);
109 self
110 }
111
112 pub fn with_rsa_unique_identifier(mut self, rsa_unique_identifier: PublicKeyRsa) -> Self {
121 self.rsa_unique_identifier = Some(rsa_unique_identifier);
122 self
123 }
124
125 pub fn with_keyed_hash_parameters(
132 mut self,
133 keyed_hash_parameters: PublicKeyedHashParameters,
134 ) -> Self {
135 self.keyed_hash_parameters = Some(keyed_hash_parameters);
136 self
137 }
138
139 pub fn with_keyed_hash_unique_identifier(
146 mut self,
147 keyed_hash_unique_identifier: Digest,
148 ) -> Self {
149 self.keyed_hash_unique_identifier = Some(keyed_hash_unique_identifier);
150 self
151 }
152
153 pub const fn with_ecc_parameters(mut self, ecc_parameters: PublicEccParameters) -> Self {
160 self.ecc_parameters = Some(ecc_parameters);
161 self
162 }
163
164 pub fn with_ecc_unique_identifier(mut self, ecc_unique_identifier: EccPoint) -> Self {
173 self.ecc_unique_identifier = Some(ecc_unique_identifier);
174 self
175 }
176
177 pub const fn with_symmetric_cipher_parameters(
184 mut self,
185 symmetric_cipher_parameters: SymmetricCipherParameters,
186 ) -> Self {
187 self.symmetric_cipher_parameters = Some(symmetric_cipher_parameters);
188 self
189 }
190
191 pub fn with_symmetric_cipher_unique_identifier(
198 mut self,
199 symmetric_cipher_unique_identifier: Digest,
200 ) -> Self {
201 self.symmetric_cipher_unique_identifier = Some(symmetric_cipher_unique_identifier);
202 self
203 }
204
205 pub fn build(self) -> Result<Public> {
212 let algorithm = self.public_algorithm.ok_or_else(|| {
213 error!("Algorithm is required and has not been set in the PublicBuilder");
214 Error::local_error(WrapperErrorKind::ParamsMissing)
215 })?;
216
217 let object_attributes = self.object_attributes.ok_or_else(|| {
218 error!("ObjectAttributes is required and has not been set in the PublicBuilder");
219 Error::local_error(WrapperErrorKind::ParamsMissing)
220 })?;
221
222 let name_hashing_algorithm = self.name_hashing_algorithm.ok_or_else(|| {
223 error!(
224 "The name hashing algorithm is required and has not been set in the PublicBuilder"
225 );
226 Error::local_error(WrapperErrorKind::ParamsMissing)
227 })?;
228
229 let auth_policy = self.auth_policy.unwrap_or_default();
230
231 match algorithm {
232 PublicAlgorithm::Rsa => {
233 Ok(Public::Rsa {
234 object_attributes,
235 name_hashing_algorithm,
236 auth_policy,
237 parameters: self.rsa_parameters.ok_or_else(|| {
238 error!("RSA parameters have not been set in the PublicBuilder even though the RSA algorithm had been selected.");
239 Error::local_error(WrapperErrorKind::ParamsMissing)
240 })?,
241 unique: self.rsa_unique_identifier.ok_or_else(|| {
242 error!("RSA unique identifier has not been set in the PublicBuilder even though the RSA algorithm had been selected. Consider using: .with_rsa_unique_identifier(&PublicKeyRsa::default())");
243 Error::local_error(WrapperErrorKind::ParamsMissing)
244 })?,
245 })
246 },
247 PublicAlgorithm::KeyedHash => {
248 Ok(Public::KeyedHash {
249 object_attributes,
250 name_hashing_algorithm,
251 auth_policy,
252 parameters: self.keyed_hash_parameters.ok_or_else(|| {
253 error!("Keyed hash parameters have not been set in the Public Builder even though the keyed hash algorithm have been selected");
254 Error::local_error(WrapperErrorKind::ParamsMissing)
255 })?,
256 unique: self.keyed_hash_unique_identifier.ok_or_else(|| {
257 error!("Keyed hash unique identifier have not been set in the Public Builder even though the keyed hash algorithm have been selected. Consider using: .with_keyed_hash_unique_identifier(&Digest::default())");
258 Error::local_error(WrapperErrorKind::ParamsMissing)
259 })?,
260 })
261 },
262 PublicAlgorithm::Ecc => {
263 Ok(Public::Ecc {
264 object_attributes,
265 name_hashing_algorithm,
266 auth_policy,
267 parameters: self.ecc_parameters.ok_or_else(|| {
268 error!("ECC parameters have not been set in the Public Builder even though the ECC algorithm have been selected");
269 Error::local_error(WrapperErrorKind::ParamsMissing)
270 })?,
271 unique: self.ecc_unique_identifier.ok_or_else(|| {
272 error!("ECC unique identifier have not been set in the Public Builder even though the ECC algorithm have been selected. Consider using: .with_ecc_unique_identifier(&EccPoint::default())");
273 Error::local_error(WrapperErrorKind::ParamsMissing)
274 })?,
275 })
276 }
277 PublicAlgorithm::SymCipher => {
278 Ok(Public::SymCipher {
279 object_attributes,
280 name_hashing_algorithm,
281 auth_policy,
282 parameters: self.symmetric_cipher_parameters.ok_or_else(|| {
283 error!("Symmetric cipher parameters have not been set in the Public Builder even though the symmetric cipher algorithm have been selected");
284 Error::local_error(WrapperErrorKind::ParamsMissing)
285 })?,
286 unique: self.symmetric_cipher_unique_identifier.ok_or_else(|| {
287 error!("Symmetric cipher unique identifier have not been set in the Public Builder even though the symmetric cipher algorithm have been selected. Consider using: .with_symmetric_cipher_unique_identifier(&Digest::default())");
288 Error::local_error(WrapperErrorKind::ParamsMissing)
289 })?,
290 })
291 }
292 }
293 }
294}
295
296impl Default for PublicBuilder {
297 fn default() -> Self {
298 Self::new()
299 }
300}
301
302#[derive(Debug, Clone, Eq, PartialEq)]
307pub enum Public {
308 Rsa {
309 object_attributes: ObjectAttributes,
310 name_hashing_algorithm: HashingAlgorithm,
311 auth_policy: Digest,
312 parameters: PublicRsaParameters,
313 unique: PublicKeyRsa,
314 },
315 KeyedHash {
316 object_attributes: ObjectAttributes,
317 name_hashing_algorithm: HashingAlgorithm,
318 auth_policy: Digest,
319 parameters: PublicKeyedHashParameters,
320 unique: Digest,
321 },
322 Ecc {
323 object_attributes: ObjectAttributes,
324 name_hashing_algorithm: HashingAlgorithm,
325 auth_policy: Digest,
326 parameters: PublicEccParameters,
327 unique: EccPoint,
328 },
329 SymCipher {
330 object_attributes: ObjectAttributes,
331 name_hashing_algorithm: HashingAlgorithm,
332 auth_policy: Digest,
333 parameters: SymmetricCipherParameters,
334 unique: Digest,
335 },
336}
337
338impl Public {
339 pub fn object_attributes(&self) -> ObjectAttributes {
341 match self {
342 Public::Rsa {
343 object_attributes, ..
344 }
345 | Public::KeyedHash {
346 object_attributes, ..
347 }
348 | Public::Ecc {
349 object_attributes, ..
350 }
351 | Public::SymCipher {
352 object_attributes, ..
353 } => *object_attributes,
354 }
355 }
356
357 pub fn name_hashing_algorithm(&self) -> HashingAlgorithm {
359 match self {
360 Public::Rsa {
361 name_hashing_algorithm,
362 ..
363 }
364 | Public::KeyedHash {
365 name_hashing_algorithm,
366 ..
367 }
368 | Public::Ecc {
369 name_hashing_algorithm,
370 ..
371 }
372 | Public::SymCipher {
373 name_hashing_algorithm,
374 ..
375 } => *name_hashing_algorithm,
376 }
377 }
378
379 pub fn symmetric_algorithm(&self) -> Option<SymmetricDefinitionObject> {
381 match self {
382 Public::Rsa { parameters, .. } => Some(parameters.symmetric_definition_object()),
383 Public::KeyedHash { .. } => None,
384 Public::Ecc { parameters, .. } => Some(parameters.symmetric_definition_object()),
385 Public::SymCipher { parameters, .. } => Some(parameters.symmetric_definition_object()),
386 }
387 }
388
389 pub fn auth_policy(&self) -> &Digest {
391 match self {
392 Public::Rsa { auth_policy, .. }
393 | Public::KeyedHash { auth_policy, .. }
394 | Public::Ecc { auth_policy, .. }
395 | Public::SymCipher { auth_policy, .. } => auth_policy,
396 }
397 }
398
399 pub const fn builder() -> PublicBuilder {
401 PublicBuilder::new()
402 }
403}
404
405impl From<Public> for TPMT_PUBLIC {
406 fn from(public: Public) -> Self {
407 match public {
408 Public::Rsa {
409 object_attributes,
410 name_hashing_algorithm,
411 auth_policy,
412 parameters,
413 unique,
414 } => TPMT_PUBLIC {
415 type_: PublicAlgorithm::Rsa.into(),
416 nameAlg: name_hashing_algorithm.into(),
417 objectAttributes: object_attributes.into(),
418 authPolicy: auth_policy.into(),
419 parameters: TPMU_PUBLIC_PARMS {
420 rsaDetail: parameters.into(),
421 },
422 unique: TPMU_PUBLIC_ID { rsa: unique.into() },
423 },
424 Public::KeyedHash {
425 object_attributes,
426 name_hashing_algorithm,
427 auth_policy,
428 parameters,
429 unique,
430 } => TPMT_PUBLIC {
431 type_: PublicAlgorithm::KeyedHash.into(),
432 nameAlg: name_hashing_algorithm.into(),
433 objectAttributes: object_attributes.into(),
434 authPolicy: auth_policy.into(),
435 parameters: TPMU_PUBLIC_PARMS {
436 keyedHashDetail: parameters.into(),
437 },
438 unique: TPMU_PUBLIC_ID {
439 keyedHash: unique.into(),
440 },
441 },
442 Public::Ecc {
443 object_attributes,
444 name_hashing_algorithm,
445 auth_policy,
446 parameters,
447 unique,
448 } => TPMT_PUBLIC {
449 type_: PublicAlgorithm::Ecc.into(),
450 nameAlg: name_hashing_algorithm.into(),
451 objectAttributes: object_attributes.into(),
452 authPolicy: auth_policy.into(),
453 parameters: TPMU_PUBLIC_PARMS {
454 eccDetail: parameters.into(),
455 },
456 unique: TPMU_PUBLIC_ID { ecc: unique.into() },
457 },
458 Public::SymCipher {
459 object_attributes,
460 name_hashing_algorithm,
461 auth_policy,
462 parameters,
463 unique,
464 } => TPMT_PUBLIC {
465 type_: PublicAlgorithm::SymCipher.into(),
466 nameAlg: name_hashing_algorithm.into(),
467 objectAttributes: object_attributes.into(),
468 authPolicy: auth_policy.into(),
469 parameters: TPMU_PUBLIC_PARMS {
470 symDetail: parameters.into(),
471 },
472 unique: TPMU_PUBLIC_ID { sym: unique.into() },
473 },
474 }
475 }
476}
477
478impl TryFrom<TPMT_PUBLIC> for Public {
479 type Error = Error;
480
481 fn try_from(tpmt_public: TPMT_PUBLIC) -> Result<Self> {
482 match PublicAlgorithm::try_from(tpmt_public.type_)? {
483 PublicAlgorithm::Rsa => Ok(Public::Rsa {
484 object_attributes: tpmt_public.objectAttributes.into(),
485 name_hashing_algorithm: tpmt_public.nameAlg.try_into()?,
486 auth_policy: tpmt_public.authPolicy.try_into()?,
487 parameters: unsafe { tpmt_public.parameters.rsaDetail }.try_into()?,
488 unique: unsafe { tpmt_public.unique.rsa }.try_into()?,
489 }),
490 PublicAlgorithm::KeyedHash => Ok(Public::KeyedHash {
491 object_attributes: tpmt_public.objectAttributes.into(),
492 name_hashing_algorithm: tpmt_public.nameAlg.try_into()?,
493 auth_policy: tpmt_public.authPolicy.try_into()?,
494 parameters: unsafe { tpmt_public.parameters.keyedHashDetail }.try_into()?,
495 unique: unsafe { tpmt_public.unique.keyedHash }.try_into()?,
496 }),
497 PublicAlgorithm::Ecc => Ok(Public::Ecc {
498 object_attributes: tpmt_public.objectAttributes.into(),
499 name_hashing_algorithm: tpmt_public.nameAlg.try_into()?,
500 auth_policy: tpmt_public.authPolicy.try_into()?,
501 parameters: unsafe { tpmt_public.parameters.eccDetail }.try_into()?,
502 unique: unsafe { tpmt_public.unique.ecc }.try_into()?,
503 }),
504 PublicAlgorithm::SymCipher => Ok(Public::SymCipher {
505 object_attributes: tpmt_public.objectAttributes.into(),
506 name_hashing_algorithm: tpmt_public.nameAlg.try_into()?,
507 auth_policy: tpmt_public.authPolicy.try_into()?,
508 parameters: unsafe { tpmt_public.parameters.symDetail }.try_into()?,
509 unique: unsafe { tpmt_public.unique.sym }.try_into()?,
510 }),
511 }
512 }
513}
514
515impl Marshall for Public {
516 const BUFFER_SIZE: usize = size_of::<TPMT_PUBLIC>();
517
518 fn marshall(&self) -> Result<Vec<u8>> {
522 let mut buffer = vec![0; Self::BUFFER_SIZE];
523 let mut offset = 0;
524
525 let ret = Error::from_tss_rc(unsafe {
526 crate::tss2_esys::Tss2_MU_TPMT_PUBLIC_Marshal(
527 &self.clone().into(),
528 buffer.as_mut_ptr(),
529 Self::BUFFER_SIZE.try_into().map_err(|e| {
530 error!("Failed to convert size of buffer to TSS size_t type: {}", e);
531 Error::local_error(WrapperErrorKind::InvalidParam)
532 })?,
533 &mut offset,
534 )
535 });
536
537 if !ret.is_success() {
538 return Err(ret);
539 }
540
541 let checked_offset = usize::try_from(offset).map_err(|e| {
542 error!("Failed to parse offset as usize: {}", e);
543 Error::local_error(WrapperErrorKind::InvalidParam)
544 })?;
545
546 buffer.truncate(checked_offset);
547
548 Ok(buffer)
549 }
550}
551
552impl UnMarshall for Public {
553 fn unmarshall(marshalled_data: &[u8]) -> Result<Self> {
557 let mut dest = TPMT_PUBLIC::default();
558 let mut offset = 0;
559
560 let ret = Error::from_tss_rc(unsafe {
561 crate::tss2_esys::Tss2_MU_TPMT_PUBLIC_Unmarshal(
562 marshalled_data.as_ptr(),
563 marshalled_data.len().try_into().map_err(|e| {
564 error!("Failed to convert length of marshalled data: {}", e);
565 Error::local_error(WrapperErrorKind::InvalidParam)
566 })?,
567 &mut offset,
568 &mut dest,
569 )
570 });
571
572 if !ret.is_success() {
573 return Err(ret);
574 }
575
576 Public::try_from(dest)
577 }
578}
579
580impl TryFrom<TPM2B_PUBLIC> for Public {
581 type Error = Error;
582
583 fn try_from(tpm2b_public: TPM2B_PUBLIC) -> Result<Self> {
584 Public::try_from(tpm2b_public.publicArea)
585 }
586}
587
588impl TryFrom<Public> for TPM2B_PUBLIC {
589 type Error = Error;
590
591 fn try_from(public: Public) -> Result<Self> {
592 let mut buffer = vec![0; Public::BUFFER_SIZE];
593 let mut size = 0;
594 let public_area = TPMT_PUBLIC::from(public);
595
596 let ret = Error::from_tss_rc(unsafe {
597 crate::tss2_esys::Tss2_MU_TPMT_PUBLIC_Marshal(
598 &public_area,
599 buffer.as_mut_ptr(),
600 Public::BUFFER_SIZE.try_into().map_err(|e| {
601 error!("Failed to convert size of buffer to TSS size_t type: {}", e);
602 Error::local_error(WrapperErrorKind::InvalidParam)
603 })?,
604 &mut size,
605 )
606 });
607
608 if !ret.is_success() {
609 return Err(ret);
610 }
611
612 Ok(TPM2B_PUBLIC {
613 size: size.try_into().map_err(|e| {
614 error!(
615 "Failed to convert size of buffer from TSS size_t type: {}",
616 e
617 );
618 Error::local_error(WrapperErrorKind::InvalidParam)
619 })?,
620 publicArea: public_area,
621 })
622 }
623}