1pub mod ecc;
4pub mod keyed_hash;
5pub mod rsa;
6
7use crate::{
8 attributes::ObjectAttributes,
9 interface_types::algorithm::{HashingAlgorithm, PublicAlgorithm},
10 structures::{Digest, EccPoint, PublicKeyRsa, SymmetricCipherParameters},
11 traits::{impl_mu_standard, Marshall},
12 tss2_esys::{TPM2B_PUBLIC, TPMT_PUBLIC},
13 Error, Result, ReturnCode, WrapperErrorKind,
14};
15
16use self::rsa::PublicRsaParameters;
17use ecc::PublicEccParameters;
18use keyed_hash::PublicKeyedHashParameters;
19
20use log::error;
21use std::convert::{TryFrom, TryInto};
22use tss_esapi_sys::{TPMU_PUBLIC_ID, TPMU_PUBLIC_PARMS};
23
24use super::symmetric::SymmetricDefinitionObject;
25
26#[derive(Debug, Clone)]
28pub struct PublicBuilder {
29 public_algorithm: Option<PublicAlgorithm>,
30 object_attributes: Option<ObjectAttributes>,
31 name_hashing_algorithm: Option<HashingAlgorithm>,
32 auth_policy: Option<Digest>,
33 rsa_parameters: Option<PublicRsaParameters>,
34 rsa_unique_identifier: Option<PublicKeyRsa>,
35 keyed_hash_parameters: Option<PublicKeyedHashParameters>,
36 keyed_hash_unique_identifier: Option<Digest>,
37 ecc_parameters: Option<PublicEccParameters>,
38 ecc_unique_identifier: Option<EccPoint>,
39 symmetric_cipher_parameters: Option<SymmetricCipherParameters>,
40 symmetric_cipher_unique_identifier: Option<Digest>,
41}
42
43impl PublicBuilder {
44 pub const fn new() -> Self {
51 PublicBuilder {
52 public_algorithm: None,
53 object_attributes: None,
54 name_hashing_algorithm: None,
55 auth_policy: None,
56 rsa_parameters: None,
57 rsa_unique_identifier: None,
58 keyed_hash_parameters: None,
59 keyed_hash_unique_identifier: None,
60 ecc_parameters: None,
61 ecc_unique_identifier: None,
62 symmetric_cipher_parameters: None,
63 symmetric_cipher_unique_identifier: None,
64 }
65 }
66
67 pub const fn with_public_algorithm(mut self, public_algorithm: PublicAlgorithm) -> Self {
70 self.public_algorithm = Some(public_algorithm);
71 self
72 }
73
74 pub const fn with_object_attributes(mut self, object_attributes: ObjectAttributes) -> Self {
77 self.object_attributes = Some(object_attributes);
78 self
79 }
80
81 pub const fn with_name_hashing_algorithm(
84 mut self,
85 name_hashing_algorithm: HashingAlgorithm,
86 ) -> Self {
87 self.name_hashing_algorithm = Some(name_hashing_algorithm);
88 self
89 }
90
91 pub fn with_auth_policy(mut self, auth_policy: Digest) -> Self {
94 self.auth_policy = Some(auth_policy);
95 self
96 }
97
98 pub fn with_rsa_parameters(mut self, rsa_parameters: PublicRsaParameters) -> Self {
105 self.rsa_parameters = Some(rsa_parameters);
106 self
107 }
108
109 pub fn with_rsa_unique_identifier(mut self, rsa_unique_identifier: PublicKeyRsa) -> Self {
118 self.rsa_unique_identifier = Some(rsa_unique_identifier);
119 self
120 }
121
122 pub fn with_keyed_hash_parameters(
129 mut self,
130 keyed_hash_parameters: PublicKeyedHashParameters,
131 ) -> Self {
132 self.keyed_hash_parameters = Some(keyed_hash_parameters);
133 self
134 }
135
136 pub fn with_keyed_hash_unique_identifier(
143 mut self,
144 keyed_hash_unique_identifier: Digest,
145 ) -> Self {
146 self.keyed_hash_unique_identifier = Some(keyed_hash_unique_identifier);
147 self
148 }
149
150 pub const fn with_ecc_parameters(mut self, ecc_parameters: PublicEccParameters) -> Self {
157 self.ecc_parameters = Some(ecc_parameters);
158 self
159 }
160
161 pub fn with_ecc_unique_identifier(mut self, ecc_unique_identifier: EccPoint) -> Self {
170 self.ecc_unique_identifier = Some(ecc_unique_identifier);
171 self
172 }
173
174 pub const fn with_symmetric_cipher_parameters(
181 mut self,
182 symmetric_cipher_parameters: SymmetricCipherParameters,
183 ) -> Self {
184 self.symmetric_cipher_parameters = Some(symmetric_cipher_parameters);
185 self
186 }
187
188 pub fn with_symmetric_cipher_unique_identifier(
195 mut self,
196 symmetric_cipher_unique_identifier: Digest,
197 ) -> Self {
198 self.symmetric_cipher_unique_identifier = Some(symmetric_cipher_unique_identifier);
199 self
200 }
201
202 pub fn build(self) -> Result<Public> {
209 let algorithm = self.public_algorithm.ok_or_else(|| {
210 error!("Algorithm is required and has not been set in the PublicBuilder");
211 Error::local_error(WrapperErrorKind::ParamsMissing)
212 })?;
213
214 let object_attributes = self.object_attributes.ok_or_else(|| {
215 error!("ObjectAttributes is required and has not been set in the PublicBuilder");
216 Error::local_error(WrapperErrorKind::ParamsMissing)
217 })?;
218
219 let name_hashing_algorithm = self.name_hashing_algorithm.ok_or_else(|| {
220 error!(
221 "The name hashing algorithm is required and has not been set in the PublicBuilder"
222 );
223 Error::local_error(WrapperErrorKind::ParamsMissing)
224 })?;
225
226 let auth_policy = self.auth_policy.unwrap_or_default();
227
228 match algorithm {
229 PublicAlgorithm::Rsa => {
230 Ok(Public::Rsa {
231 object_attributes,
232 name_hashing_algorithm,
233 auth_policy,
234 parameters: self.rsa_parameters.ok_or_else(|| {
235 error!("RSA parameters have not been set in the PublicBuilder even though the RSA algorithm had been selected.");
236 Error::local_error(WrapperErrorKind::ParamsMissing)
237 })?,
238 unique: self.rsa_unique_identifier.ok_or_else(|| {
239 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())");
240 Error::local_error(WrapperErrorKind::ParamsMissing)
241 })?,
242 })
243 },
244 PublicAlgorithm::KeyedHash => {
245 Ok(Public::KeyedHash {
246 object_attributes,
247 name_hashing_algorithm,
248 auth_policy,
249 parameters: self.keyed_hash_parameters.ok_or_else(|| {
250 error!("Keyed hash parameters have not been set in the Public Builder even though the keyed hash algorithm have been selected");
251 Error::local_error(WrapperErrorKind::ParamsMissing)
252 })?,
253 unique: self.keyed_hash_unique_identifier.ok_or_else(|| {
254 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())");
255 Error::local_error(WrapperErrorKind::ParamsMissing)
256 })?,
257 })
258 },
259 PublicAlgorithm::Ecc => {
260 Ok(Public::Ecc {
261 object_attributes,
262 name_hashing_algorithm,
263 auth_policy,
264 parameters: self.ecc_parameters.ok_or_else(|| {
265 error!("ECC parameters have not been set in the Public Builder even though the ECC algorithm have been selected");
266 Error::local_error(WrapperErrorKind::ParamsMissing)
267 })?,
268 unique: self.ecc_unique_identifier.ok_or_else(|| {
269 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())");
270 Error::local_error(WrapperErrorKind::ParamsMissing)
271 })?,
272 })
273 }
274 PublicAlgorithm::SymCipher => {
275 Ok(Public::SymCipher {
276 object_attributes,
277 name_hashing_algorithm,
278 auth_policy,
279 parameters: self.symmetric_cipher_parameters.ok_or_else(|| {
280 error!("Symmetric cipher parameters have not been set in the Public Builder even though the symmetric cipher algorithm have been selected");
281 Error::local_error(WrapperErrorKind::ParamsMissing)
282 })?,
283 unique: self.symmetric_cipher_unique_identifier.ok_or_else(|| {
284 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())");
285 Error::local_error(WrapperErrorKind::ParamsMissing)
286 })?,
287 })
288 }
289 }
290 }
291}
292
293impl Default for PublicBuilder {
294 fn default() -> Self {
295 Self::new()
296 }
297}
298
299#[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) -> Result<SymmetricDefinitionObject> {
381 match self {
382 Public::Rsa { parameters, .. } => Ok(parameters.symmetric_definition_object()),
383 Public::KeyedHash { .. } => Err(Error::local_error(WrapperErrorKind::InvalidParam)),
384 Public::Ecc { parameters, .. } => Ok(parameters.symmetric_definition_object()),
385 Public::SymCipher { parameters, .. } => Ok(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_mu_standard!(Public, TPMT_PUBLIC);
516
517cfg_if::cfg_if! {
518 if #[cfg(feature = "serde")] {
519 use crate::traits::UnMarshall;
520
521 impl serde::Serialize for Public {
522 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
525 where
526 S: serde::Serializer,
527 {
528 let bytes = self.marshall().map_err(serde::ser::Error::custom)?;
529 serializer.serialize_bytes(&bytes)
530 }
531 }
532
533 impl<'de> serde::Deserialize<'de> for Public {
534 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
537 where
538 D: serde::Deserializer<'de>,
539 {
540 let bytes = <Vec<u8>>::deserialize(deserializer)?;
541 Self::unmarshall(&bytes).map_err(serde::de::Error::custom)
542 }
543 }
544 }
545}
546impl TryFrom<TPM2B_PUBLIC> for Public {
547 type Error = Error;
548
549 fn try_from(tpm2b_public: TPM2B_PUBLIC) -> Result<Self> {
550 Public::try_from(tpm2b_public.publicArea)
551 }
552}
553
554impl TryFrom<Public> for TPM2B_PUBLIC {
555 type Error = Error;
556
557 fn try_from(public: Public) -> Result<Self> {
558 let mut buffer = vec![0; Public::BUFFER_SIZE];
559 let mut size = 0;
560 let public_area = TPMT_PUBLIC::from(public);
561
562 ReturnCode::ensure_success(
563 unsafe {
564 crate::tss2_esys::Tss2_MU_TPMT_PUBLIC_Marshal(
565 &public_area,
566 buffer.as_mut_ptr(),
567 Public::BUFFER_SIZE.try_into().map_err(|e| {
568 error!("Failed to convert size of buffer to TSS size_t type: {}", e);
569 Error::local_error(WrapperErrorKind::InvalidParam)
570 })?,
571 &mut size,
572 )
573 },
574 |ret| error!("Failed to marshal Public: {}", ret),
575 )?;
576
577 Ok(TPM2B_PUBLIC {
578 size: size.try_into().map_err(|e| {
579 error!(
580 "Failed to convert size of buffer from TSS size_t type: {}",
581 e
582 );
583 Error::local_error(WrapperErrorKind::InvalidParam)
584 })?,
585 publicArea: public_area,
586 })
587 }
588}