Skip to main content

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::{impl_mu_standard, Marshall},
7    tss2_esys::{TPM2B_SENSITIVE, TPMT_SENSITIVE, TPMU_SENSITIVE_COMPOSITE},
8    Error, Result, ReturnCode, WrapperErrorKind,
9};
10use log::error;
11use std::convert::{TryFrom, TryInto};
12
13/// Enum describing the Sensitive part of an object.
14///
15/// # Details
16/// This corresponds to TPMT_SENSITIVE
17#[derive(Debug, Clone, Eq, PartialEq)]
18pub enum Sensitive {
19    Rsa {
20        auth_value: Auth,
21        seed_value: Digest,
22        sensitive: PrivateKeyRsa,
23    },
24    Ecc {
25        auth_value: Auth,
26        seed_value: Digest,
27        sensitive: EccParameter,
28    },
29    Bits {
30        auth_value: Auth,
31        seed_value: Digest,
32        sensitive: SensitiveData,
33    },
34    Symmetric {
35        auth_value: Auth,
36        seed_value: Digest,
37        sensitive: SymmetricKey,
38    },
39    // Even though this is included in TPMU_SENSITIVE_COMPOSITE, there is no
40    // selector for it, so it can't be converted back and forth
41    // VendorSpecific {
42    //     auth_value: Auth,
43    //     seed_value: Digest,
44    //     sensitive: PrivateVendorSpecific,
45    // },
46}
47
48impl Sensitive {
49    /// Get the authentication value of the object
50    pub fn auth_value(&self) -> &Auth {
51        match self {
52            Sensitive::Rsa { auth_value, .. }
53            | Sensitive::Ecc { auth_value, .. }
54            | Sensitive::Bits { auth_value, .. }
55            | Sensitive::Symmetric { auth_value, .. } => auth_value,
56        }
57    }
58
59    /// Get the seed value of the object
60    pub fn seed_value(&self) -> &Digest {
61        match self {
62            Sensitive::Rsa { seed_value, .. }
63            | Sensitive::Ecc { seed_value, .. }
64            | Sensitive::Bits { seed_value, .. }
65            | Sensitive::Symmetric { seed_value, .. } => seed_value,
66        }
67    }
68
69    pub fn sensitive_type(&self) -> PublicAlgorithm {
70        match self {
71            Sensitive::Rsa { .. } => PublicAlgorithm::Rsa,
72            Sensitive::Ecc { .. } => PublicAlgorithm::Ecc,
73            Sensitive::Bits { .. } => PublicAlgorithm::KeyedHash,
74            Sensitive::Symmetric { .. } => PublicAlgorithm::SymCipher,
75        }
76    }
77}
78
79impl From<Sensitive> for TPMT_SENSITIVE {
80    fn from(sensitive: Sensitive) -> Self {
81        #[allow(non_snake_case)]
82        let sensitiveType = sensitive.sensitive_type().into();
83        match sensitive {
84            Sensitive::Rsa {
85                auth_value,
86                seed_value,
87                sensitive,
88            } => TPMT_SENSITIVE {
89                sensitiveType,
90                authValue: auth_value.into(),
91                seedValue: seed_value.into(),
92                sensitive: TPMU_SENSITIVE_COMPOSITE {
93                    rsa: sensitive.into(),
94                },
95            },
96            Sensitive::Ecc {
97                auth_value,
98                seed_value,
99                sensitive,
100            } => TPMT_SENSITIVE {
101                sensitiveType,
102                authValue: auth_value.into(),
103                seedValue: seed_value.into(),
104                sensitive: TPMU_SENSITIVE_COMPOSITE {
105                    ecc: sensitive.into(),
106                },
107            },
108            Sensitive::Bits {
109                auth_value,
110                seed_value,
111                sensitive,
112            } => TPMT_SENSITIVE {
113                sensitiveType,
114                authValue: auth_value.into(),
115                seedValue: seed_value.into(),
116                sensitive: TPMU_SENSITIVE_COMPOSITE {
117                    bits: sensitive.into(),
118                },
119            },
120            Sensitive::Symmetric {
121                auth_value,
122                seed_value,
123                sensitive,
124            } => TPMT_SENSITIVE {
125                sensitiveType,
126                authValue: auth_value.into(),
127                seedValue: seed_value.into(),
128                sensitive: TPMU_SENSITIVE_COMPOSITE {
129                    sym: sensitive.into(),
130                },
131            },
132        }
133    }
134}
135
136impl TryFrom<TPMT_SENSITIVE> for Sensitive {
137    type Error = Error;
138
139    fn try_from(tpmt_sensitive: TPMT_SENSITIVE) -> Result<Sensitive> {
140        let sensitive_type = PublicAlgorithm::try_from(tpmt_sensitive.sensitiveType)?;
141        match sensitive_type {
142            PublicAlgorithm::Rsa => Ok(Sensitive::Rsa {
143                auth_value: tpmt_sensitive.authValue.try_into()?,
144                seed_value: tpmt_sensitive.seedValue.try_into()?,
145                sensitive: unsafe { tpmt_sensitive.sensitive.rsa }.try_into()?,
146            }),
147            PublicAlgorithm::Ecc => Ok(Sensitive::Ecc {
148                auth_value: tpmt_sensitive.authValue.try_into()?,
149                seed_value: tpmt_sensitive.seedValue.try_into()?,
150                sensitive: unsafe { tpmt_sensitive.sensitive.ecc }.try_into()?,
151            }),
152            PublicAlgorithm::KeyedHash => Ok(Sensitive::Bits {
153                auth_value: tpmt_sensitive.authValue.try_into()?,
154                seed_value: tpmt_sensitive.seedValue.try_into()?,
155                sensitive: unsafe { tpmt_sensitive.sensitive.bits }.try_into()?,
156            }),
157            PublicAlgorithm::SymCipher => Ok(Sensitive::Symmetric {
158                auth_value: tpmt_sensitive.authValue.try_into()?,
159                seed_value: tpmt_sensitive.seedValue.try_into()?,
160                sensitive: unsafe { tpmt_sensitive.sensitive.sym }.try_into()?,
161            }),
162        }
163    }
164}
165
166impl_mu_standard!(Sensitive, TPMT_SENSITIVE);
167
168impl TryFrom<TPM2B_SENSITIVE> for Sensitive {
169    type Error = Error;
170
171    fn try_from(tpm2b_sensitive: TPM2B_SENSITIVE) -> Result<Self> {
172        Sensitive::try_from(tpm2b_sensitive.sensitiveArea)
173    }
174}
175
176impl TryFrom<Sensitive> for TPM2B_SENSITIVE {
177    type Error = Error;
178
179    fn try_from(sensitive: Sensitive) -> Result<Self> {
180        let mut buffer = vec![0; Sensitive::BUFFER_SIZE];
181        let mut size = 0;
182        let sensitive_area = TPMT_SENSITIVE::from(sensitive);
183
184        ReturnCode::ensure_success(
185            unsafe {
186                crate::tss2_esys::Tss2_MU_TPMT_SENSITIVE_Marshal(
187                    &sensitive_area,
188                    buffer.as_mut_ptr(),
189                    Sensitive::BUFFER_SIZE.try_into().map_err(|e| {
190                        error!("Failed to convert size of buffer to TSS size_t type: {}", e);
191                        Error::local_error(WrapperErrorKind::InvalidParam)
192                    })?,
193                    &mut size,
194                )
195            },
196            |ret| {
197                error!("Failed to marshal Sensitive: {}", ret);
198            },
199        )?;
200
201        Ok(TPM2B_SENSITIVE {
202            size: size.try_into().map_err(|e| {
203                error!(
204                    "Failed to convert size of buffer from TSS size_t type: {}",
205                    e
206                );
207                Error::local_error(WrapperErrorKind::InvalidParam)
208            })?,
209            sensitiveArea: sensitive_area,
210        })
211    }
212}