tss_esapi/structures/tagged/
sensitive.rs

1// Copyright 2022 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3use crate::{
4    interface_types::algorithm::PublicAlgorithm,
5    structures::{Auth, Digest, EccParameter, PrivateKeyRsa, SensitiveData, SymmetricKey},
6    traits::{Marshall, UnMarshall},
7    tss2_esys::{TPM2B_SENSITIVE, TPMT_SENSITIVE, TPMU_SENSITIVE_COMPOSITE},
8    Error, Result, WrapperErrorKind,
9};
10use log::error;
11use std::{
12    convert::{TryFrom, TryInto},
13    mem::size_of,
14};
15
16/// Enum describing the Sensitive part of an object.
17///
18/// # Details
19/// This corresponds to TPMT_SENSITIVE
20#[derive(Debug, Clone, Eq, PartialEq)]
21pub enum Sensitive {
22    Rsa {
23        auth_value: Auth,
24        seed_value: Digest,
25        sensitive: PrivateKeyRsa,
26    },
27    Ecc {
28        auth_value: Auth,
29        seed_value: Digest,
30        sensitive: EccParameter,
31    },
32    Bits {
33        auth_value: Auth,
34        seed_value: Digest,
35        sensitive: SensitiveData,
36    },
37    Symmetric {
38        auth_value: Auth,
39        seed_value: Digest,
40        sensitive: SymmetricKey,
41    },
42    // Even though this is included in TPMU_SENSITIVE_COMPOSITE, there is no
43    // selector for it, so it can't be converted back and forth
44    // VendorSpecific {
45    //     auth_value: Auth,
46    //     seed_value: Digest,
47    //     sensitive: PrivateVendorSpecific,
48    // },
49}
50
51impl Sensitive {
52    /// Get the authentication value of the object
53    pub fn auth_value(&self) -> &Auth {
54        match self {
55            Sensitive::Rsa { auth_value, .. }
56            | Sensitive::Ecc { auth_value, .. }
57            | Sensitive::Bits { auth_value, .. }
58            | Sensitive::Symmetric { auth_value, .. } => auth_value,
59        }
60    }
61
62    /// Get the seed value of the object
63    pub fn seed_value(&self) -> &Digest {
64        match self {
65            Sensitive::Rsa { seed_value, .. }
66            | Sensitive::Ecc { seed_value, .. }
67            | Sensitive::Bits { seed_value, .. }
68            | Sensitive::Symmetric { seed_value, .. } => seed_value,
69        }
70    }
71
72    pub fn sensitive_type(&self) -> PublicAlgorithm {
73        match self {
74            Sensitive::Rsa { .. } => PublicAlgorithm::Rsa,
75            Sensitive::Ecc { .. } => PublicAlgorithm::Ecc,
76            Sensitive::Bits { .. } => PublicAlgorithm::KeyedHash,
77            Sensitive::Symmetric { .. } => PublicAlgorithm::SymCipher,
78        }
79    }
80}
81
82impl From<Sensitive> for TPMT_SENSITIVE {
83    fn from(sensitive: Sensitive) -> Self {
84        #[allow(non_snake_case)]
85        let sensitiveType = sensitive.sensitive_type().into();
86        match sensitive {
87            Sensitive::Rsa {
88                auth_value,
89                seed_value,
90                sensitive,
91            } => TPMT_SENSITIVE {
92                sensitiveType,
93                authValue: auth_value.into(),
94                seedValue: seed_value.into(),
95                sensitive: TPMU_SENSITIVE_COMPOSITE {
96                    rsa: sensitive.into(),
97                },
98            },
99            Sensitive::Ecc {
100                auth_value,
101                seed_value,
102                sensitive,
103            } => TPMT_SENSITIVE {
104                sensitiveType,
105                authValue: auth_value.into(),
106                seedValue: seed_value.into(),
107                sensitive: TPMU_SENSITIVE_COMPOSITE {
108                    ecc: sensitive.into(),
109                },
110            },
111            Sensitive::Bits {
112                auth_value,
113                seed_value,
114                sensitive,
115            } => TPMT_SENSITIVE {
116                sensitiveType,
117                authValue: auth_value.into(),
118                seedValue: seed_value.into(),
119                sensitive: TPMU_SENSITIVE_COMPOSITE {
120                    bits: sensitive.into(),
121                },
122            },
123            Sensitive::Symmetric {
124                auth_value,
125                seed_value,
126                sensitive,
127            } => TPMT_SENSITIVE {
128                sensitiveType,
129                authValue: auth_value.into(),
130                seedValue: seed_value.into(),
131                sensitive: TPMU_SENSITIVE_COMPOSITE {
132                    sym: sensitive.into(),
133                },
134            },
135        }
136    }
137}
138
139impl TryFrom<TPMT_SENSITIVE> for Sensitive {
140    type Error = Error;
141
142    fn try_from(tpmt_sensitive: TPMT_SENSITIVE) -> Result<Sensitive> {
143        let sensitive_type = PublicAlgorithm::try_from(tpmt_sensitive.sensitiveType)?;
144        match sensitive_type {
145            PublicAlgorithm::Rsa => Ok(Sensitive::Rsa {
146                auth_value: tpmt_sensitive.authValue.try_into()?,
147                seed_value: tpmt_sensitive.seedValue.try_into()?,
148                sensitive: unsafe { tpmt_sensitive.sensitive.rsa }.try_into()?,
149            }),
150            PublicAlgorithm::Ecc => Ok(Sensitive::Ecc {
151                auth_value: tpmt_sensitive.authValue.try_into()?,
152                seed_value: tpmt_sensitive.seedValue.try_into()?,
153                sensitive: unsafe { tpmt_sensitive.sensitive.ecc }.try_into()?,
154            }),
155            PublicAlgorithm::KeyedHash => Ok(Sensitive::Bits {
156                auth_value: tpmt_sensitive.authValue.try_into()?,
157                seed_value: tpmt_sensitive.seedValue.try_into()?,
158                sensitive: unsafe { tpmt_sensitive.sensitive.bits }.try_into()?,
159            }),
160            PublicAlgorithm::SymCipher => Ok(Sensitive::Symmetric {
161                auth_value: tpmt_sensitive.authValue.try_into()?,
162                seed_value: tpmt_sensitive.seedValue.try_into()?,
163                sensitive: unsafe { tpmt_sensitive.sensitive.sym }.try_into()?,
164            }),
165        }
166    }
167}
168
169impl Marshall for Sensitive {
170    const BUFFER_SIZE: usize = size_of::<TPMT_SENSITIVE>();
171
172    /// Produce a marshalled [`TPMT_SENSITIVE`]
173    ///
174    /// Note: for [TPM2B_SENSITIVE] marshalling use [SensitiveBuffer][`crate::structures::SensitiveBuffer]
175    fn marshall(&self) -> Result<Vec<u8>> {
176        let mut buffer = vec![0; Self::BUFFER_SIZE];
177        let mut offset = 0;
178
179        let ret = Error::from_tss_rc(unsafe {
180            crate::tss2_esys::Tss2_MU_TPMT_SENSITIVE_Marshal(
181                &self.clone().into(),
182                buffer.as_mut_ptr(),
183                Self::BUFFER_SIZE.try_into().map_err(|e| {
184                    error!("Failed to convert size of buffer to TSS size_t type: {}", e);
185                    Error::local_error(WrapperErrorKind::InvalidParam)
186                })?,
187                &mut offset,
188            )
189        });
190
191        if !ret.is_success() {
192            return Err(ret);
193        }
194
195        let checked_offset = usize::try_from(offset).map_err(|e| {
196            error!("Failed to parse offset as usize: {}", e);
197            Error::local_error(WrapperErrorKind::InvalidParam)
198        })?;
199
200        buffer.truncate(checked_offset);
201
202        Ok(buffer)
203    }
204}
205
206impl UnMarshall for Sensitive {
207    /// Unmarshall the structure from [`TPMT_SENSITIVE`]
208    ///
209    /// Note: for [TPM2B_SENSITIVE] marshalling use [SensitiveBuffer][`crate::structures::SensitiveBuffer]
210    fn unmarshall(marshalled_data: &[u8]) -> Result<Self> {
211        let mut dest = TPMT_SENSITIVE::default();
212        let mut offset = 0;
213
214        let ret = Error::from_tss_rc(unsafe {
215            crate::tss2_esys::Tss2_MU_TPMT_SENSITIVE_Unmarshal(
216                marshalled_data.as_ptr(),
217                marshalled_data.len().try_into().map_err(|e| {
218                    error!("Failed to convert length of marshalled data: {}", e);
219                    Error::local_error(WrapperErrorKind::InvalidParam)
220                })?,
221                &mut offset,
222                &mut dest,
223            )
224        });
225
226        if !ret.is_success() {
227            return Err(ret);
228        }
229
230        Sensitive::try_from(dest)
231    }
232}
233
234impl TryFrom<TPM2B_SENSITIVE> for Sensitive {
235    type Error = Error;
236
237    fn try_from(tpm2b_sensitive: TPM2B_SENSITIVE) -> Result<Self> {
238        Sensitive::try_from(tpm2b_sensitive.sensitiveArea)
239    }
240}
241
242impl TryFrom<Sensitive> for TPM2B_SENSITIVE {
243    type Error = Error;
244
245    fn try_from(sensitive: Sensitive) -> Result<Self> {
246        let mut buffer = vec![0; Sensitive::BUFFER_SIZE];
247        let mut size = 0;
248        let sensitive_area = TPMT_SENSITIVE::from(sensitive);
249
250        let ret = Error::from_tss_rc(unsafe {
251            crate::tss2_esys::Tss2_MU_TPMT_SENSITIVE_Marshal(
252                &sensitive_area,
253                buffer.as_mut_ptr(),
254                Sensitive::BUFFER_SIZE.try_into().map_err(|e| {
255                    error!("Failed to convert size of buffer to TSS size_t type: {}", e);
256                    Error::local_error(WrapperErrorKind::InvalidParam)
257                })?,
258                &mut size,
259            )
260        });
261
262        if !ret.is_success() {
263            return Err(ret);
264        }
265
266        Ok(TPM2B_SENSITIVE {
267            size: size.try_into().map_err(|e| {
268                error!(
269                    "Failed to convert size of buffer from TSS size_t type: {}",
270                    e
271                );
272                Error::local_error(WrapperErrorKind::InvalidParam)
273            })?,
274            sensitiveArea: sensitive_area,
275        })
276    }
277}