Skip to main content

tss_esapi/structures/tagged/
public.rs

1// Copyright 2021 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3pub 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/// A builder for the [Public] type.
27#[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    /// Creates a new [PublicBuilder]
45    ///
46    /// # Details
47    /// Builds the [Public] type using the provided parameters. Parameters
48    /// associated with other algorithms then the provided public algorithm
49    /// will be ignored.
50    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    /// Adds the public algorithm for the [Public] structure
68    /// to the builder.
69    pub const fn with_public_algorithm(mut self, public_algorithm: PublicAlgorithm) -> Self {
70        self.public_algorithm = Some(public_algorithm);
71        self
72    }
73
74    /// Adds the attributes of the [Public] structure
75    /// to the builder
76    pub const fn with_object_attributes(mut self, object_attributes: ObjectAttributes) -> Self {
77        self.object_attributes = Some(object_attributes);
78        self
79    }
80
81    /// Adds the name hash algorithm for the [Public] structure
82    /// to the builder.
83    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    /// Adds the auth policy for the [Public] structure
92    /// to the builder
93    pub fn with_auth_policy(mut self, auth_policy: Digest) -> Self {
94        self.auth_policy = Some(auth_policy);
95        self
96    }
97
98    /// Adds the RSA parameters for the [Public] structure
99    /// to the builder.
100    ///
101    /// # Details
102    /// This is required if the public algorithm is set to
103    /// [Rsa][`crate::interface_types::algorithm::PublicAlgorithm::Rsa].
104    pub fn with_rsa_parameters(mut self, rsa_parameters: PublicRsaParameters) -> Self {
105        self.rsa_parameters = Some(rsa_parameters);
106        self
107    }
108
109    /// Adds the RSA unique identifier for the [Public] structure
110    /// to the builder.
111    ///
112    /// # Details
113    /// This is required if the public algorithm is set to
114    /// [Rsa][`crate::interface_types::algorithm::PublicAlgorithm::Rsa].
115    ///
116    /// The unique identifier is the public key.
117    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    /// Adds the keyed hash parameters for the [Public] structure
123    /// to the builder.
124    ///
125    /// # Details
126    /// This is required if the public algorithm is set to
127    /// [KeyedHash][`crate::interface_types::algorithm::PublicAlgorithm::KeyedHash].
128    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    /// Adds the keyed hash unique identifier for the [Public] structure
137    /// to the builder.
138    ///
139    /// # Details
140    /// This is required if the public algorithm is set to
141    /// [KeyedHash][`crate::interface_types::algorithm::PublicAlgorithm::KeyedHash].
142    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    /// Adds the ECC parameters for the [Public] structure
151    /// to the builder.
152    ///
153    /// # Details
154    /// This is required if the public algorithm is set to
155    /// [Ecc][`crate::interface_types::algorithm::PublicAlgorithm::Ecc].
156    pub const fn with_ecc_parameters(mut self, ecc_parameters: PublicEccParameters) -> Self {
157        self.ecc_parameters = Some(ecc_parameters);
158        self
159    }
160
161    /// Adds the ECC unique identifier for the [Public] structure
162    /// to the builder.
163    ///
164    /// # Details
165    /// This is required if the public algorithm is set to
166    /// [Ecc][`crate::interface_types::algorithm::PublicAlgorithm::Ecc].
167    ///
168    /// The unique identifier is a ecc point.
169    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    /// Adds the symmetric cipher parameters for the [Public] structure
175    /// to the builder.
176    ///
177    /// # Details
178    /// This is required if the public algorithm is set to
179    /// [SymCipher][`crate::interface_types::algorithm::PublicAlgorithm::SymCipher].
180    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    /// Adds the symmetric cipher unique identifier for the [Public] structure
189    /// to the builder.
190    ///
191    /// # Details
192    /// This is required if the public algorithm is set to
193    /// [SymCipher][`crate::interface_types::algorithm::PublicAlgorithm::SymCipher].
194    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    /// Builds the [Public] structure.
203    ///
204    /// # Errors
205    /// Will return error if the public algorithm, object attributes or name
206    /// hashing algorithm have not been set or if the parameters and unique identifier
207    /// does not match the selected public algorithm.
208    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/// Enum representing the Public structure.
300///
301/// # Details
302/// This corresponds to TPMT_PUBLIC
303///
304/// This object can be serialized and deserialized
305/// using serde if the `serde` feature is enabled.
306#[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    /// Returns the object attributes
340    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    /// Returns the name hashing algorithm
358    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    /// Returns the name symmetric definition object if available
380    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    /// Returns the auth policy digest.
390    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    /// Get a builder for this structure
400    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            /// Serialize the [Public] data into it's bytes representation of the TCG
523            /// TPMT_PUBLIC structure.
524            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            /// Deserialise the [Public] data from it's bytes representation of the TCG
535            /// TPMT_PUBLIC structure.
536            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}