1use crate::attributes::ObjectAttributesBuilder;
12use crate::constants::PropertyTag;
13use crate::interface_types::{
14 algorithm::{HashingAlgorithm, PublicAlgorithm},
15 ecc::EccCurve,
16 key_bits::RsaKeyBits,
17};
18use crate::structures::{
19 EccPoint, EccScheme, Public, PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa,
20 PublicRsaParametersBuilder, RsaExponent, RsaScheme, SymmetricDefinitionObject,
21};
22use crate::tss2_esys::*;
23use crate::{Context, Error, Result, WrapperErrorKind};
24use zeroize::Zeroize;
25
26use serde::{Deserialize, Serialize};
27use std::convert::{TryFrom, TryInto};
28
29#[derive(Debug, Serialize, Deserialize, Clone, Zeroize)]
36#[zeroize(drop)]
37pub struct TpmsContext {
38 sequence: u64,
39 saved_handle: TPMI_DH_CONTEXT,
40 hierarchy: TPMI_RH_HIERARCHY,
41 context_blob: Vec<u8>,
42}
43
44impl TpmsContext {
45 pub fn context_blob(&self) -> &Vec<u8> {
47 &self.context_blob
48 }
49}
50
51impl TryFrom<TPMS_CONTEXT> for TpmsContext {
53 type Error = Error;
54
55 fn try_from(tss2_context: TPMS_CONTEXT) -> Result<Self> {
56 let mut context = TpmsContext {
57 sequence: tss2_context.sequence,
58 saved_handle: tss2_context.savedHandle,
59 hierarchy: tss2_context.hierarchy,
60 context_blob: tss2_context.contextBlob.buffer.to_vec(),
61 };
62 context
63 .context_blob
64 .truncate(tss2_context.contextBlob.size.into());
65 Ok(context)
66 }
67}
68
69#[allow(clippy::needless_update)]
70impl TryFrom<TpmsContext> for TPMS_CONTEXT {
71 type Error = Error;
72
73 fn try_from(context: TpmsContext) -> Result<Self> {
74 let buffer_size = context.context_blob.len();
75 if buffer_size > 5188 {
76 return Err(Error::local_error(WrapperErrorKind::WrongParamSize));
77 }
78 let mut buffer = [0_u8; 5188];
79 for (i, val) in context.context_blob.iter().enumerate() {
80 buffer[i] = *val;
81 }
82 Ok(TPMS_CONTEXT {
83 sequence: context.sequence,
84 savedHandle: context.saved_handle,
85 hierarchy: context.hierarchy,
86 contextBlob: TPM2B_CONTEXT_DATA {
87 size: buffer_size.try_into().unwrap(), buffer,
89 },
90 ..Default::default()
91 })
92 }
93}
94
95pub fn create_restricted_decryption_rsa_public(
101 symmetric: SymmetricDefinitionObject,
102 rsa_key_bits: RsaKeyBits,
103 rsa_pub_exponent: RsaExponent,
104) -> Result<Public> {
105 let object_attributes = ObjectAttributesBuilder::new()
106 .with_fixed_tpm(true)
107 .with_fixed_parent(true)
108 .with_sensitive_data_origin(true)
109 .with_user_with_auth(true)
110 .with_decrypt(true)
111 .with_sign_encrypt(false)
112 .with_restricted(true)
113 .build()?;
114
115 PublicBuilder::new()
116 .with_public_algorithm(PublicAlgorithm::Rsa)
117 .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
118 .with_object_attributes(object_attributes)
119 .with_rsa_parameters(
120 PublicRsaParametersBuilder::new_restricted_decryption_key(
121 symmetric,
122 rsa_key_bits,
123 rsa_pub_exponent,
124 )
125 .build()?,
126 )
127 .with_rsa_unique_identifier(PublicKeyRsa::default())
128 .build()
129}
130
131pub fn create_unrestricted_encryption_decryption_rsa_public(
137 rsa_key_bits: RsaKeyBits,
138 rsa_pub_exponent: RsaExponent,
139) -> Result<Public> {
140 let object_attributes = ObjectAttributesBuilder::new()
141 .with_fixed_tpm(true)
142 .with_fixed_parent(true)
143 .with_sensitive_data_origin(true)
144 .with_user_with_auth(true)
145 .with_decrypt(true)
146 .with_sign_encrypt(true)
147 .with_restricted(false)
148 .build()?;
149
150 PublicBuilder::new()
151 .with_public_algorithm(PublicAlgorithm::Rsa)
152 .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
153 .with_object_attributes(object_attributes)
154 .with_rsa_parameters(
155 PublicRsaParametersBuilder::new()
156 .with_scheme(RsaScheme::Null)
157 .with_key_bits(rsa_key_bits)
158 .with_exponent(rsa_pub_exponent)
159 .with_is_signing_key(true)
160 .with_is_decryption_key(true)
161 .with_restricted(false)
162 .build()?,
163 )
164 .with_rsa_unique_identifier(PublicKeyRsa::default())
165 .build()
166}
167
168pub fn create_unrestricted_signing_rsa_public(
174 scheme: RsaScheme,
175 rsa_key_bits: RsaKeyBits,
176 rsa_pub_exponent: RsaExponent,
177) -> Result<Public> {
178 let object_attributes = ObjectAttributesBuilder::new()
179 .with_fixed_tpm(true)
180 .with_fixed_parent(true)
181 .with_sensitive_data_origin(true)
182 .with_user_with_auth(true)
183 .with_decrypt(false)
184 .with_sign_encrypt(true)
185 .with_restricted(false)
186 .build()?;
187
188 PublicBuilder::new()
189 .with_public_algorithm(PublicAlgorithm::Rsa)
190 .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
191 .with_object_attributes(object_attributes)
192 .with_rsa_parameters(
193 PublicRsaParametersBuilder::new_unrestricted_signing_key(
194 scheme,
195 rsa_key_bits,
196 rsa_pub_exponent,
197 )
198 .build()?,
199 )
200 .with_rsa_unique_identifier(PublicKeyRsa::default())
201 .build()
202}
203
204pub fn create_unrestricted_signing_rsa_public_with_unique(
211 scheme: RsaScheme,
212 rsa_key_bits: RsaKeyBits,
213 rsa_pub_exponent: RsaExponent,
214 rsa_public_key: PublicKeyRsa,
215) -> Result<Public> {
216 let object_attributes = ObjectAttributesBuilder::new()
217 .with_fixed_tpm(true)
218 .with_fixed_parent(true)
219 .with_sensitive_data_origin(true)
220 .with_user_with_auth(true)
221 .with_decrypt(false)
222 .with_sign_encrypt(true)
223 .with_restricted(false)
224 .build()?;
225
226 PublicBuilder::new()
227 .with_public_algorithm(PublicAlgorithm::Rsa)
228 .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
229 .with_object_attributes(object_attributes)
230 .with_rsa_parameters(
231 PublicRsaParametersBuilder::new_unrestricted_signing_key(
232 scheme,
233 rsa_key_bits,
234 rsa_pub_exponent,
235 )
236 .build()?,
237 )
238 .with_rsa_unique_identifier(rsa_public_key)
239 .build()
240}
241
242pub fn create_unrestricted_signing_ecc_public(
247 scheme: EccScheme,
248 curve: EccCurve,
249) -> Result<Public> {
250 let object_attributes = ObjectAttributesBuilder::new()
251 .with_fixed_tpm(true)
252 .with_fixed_parent(true)
253 .with_sensitive_data_origin(true)
254 .with_user_with_auth(true)
255 .with_decrypt(false)
256 .with_sign_encrypt(true)
257 .with_restricted(false)
258 .build()?;
259
260 PublicBuilder::new()
261 .with_public_algorithm(PublicAlgorithm::Ecc)
262 .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
263 .with_object_attributes(object_attributes)
264 .with_ecc_parameters(
265 PublicEccParametersBuilder::new_unrestricted_signing_key(scheme, curve).build()?,
266 )
267 .with_ecc_unique_identifier(EccPoint::default())
268 .build()
269}
270
271#[derive(Debug, Clone, Serialize, Deserialize, Zeroize, PartialEq, Eq)]
273pub enum PublicKey {
274 Rsa(Vec<u8>),
282 Ecc { x: Vec<u8>, y: Vec<u8> },
286}
287
288impl TryFrom<Public> for PublicKey {
289 type Error = Error;
290
291 fn try_from(public: Public) -> Result<Self> {
292 match public {
293 Public::Rsa { unique, .. } => Ok(PublicKey::Rsa(unique.value().to_vec())),
294 Public::Ecc { unique, .. } => Ok(PublicKey::Ecc {
295 x: unique.x().value().to_vec(),
296 y: unique.y().value().to_vec(),
297 }),
298 _ => Err(Error::local_error(WrapperErrorKind::WrongValueFromTpm)),
299 }
300 }
301}
302
303fn tpm_int_to_string(num: u32) -> String {
304 num.to_be_bytes()
305 .iter()
306 .filter(|x| **x != 0)
307 .map(|x| char::from(*x))
308 .collect()
309}
310
311pub fn get_tpm_vendor(context: &mut Context) -> Result<String> {
313 Ok([
315 PropertyTag::VendorString1,
316 PropertyTag::VendorString2,
317 PropertyTag::VendorString3,
318 PropertyTag::VendorString4,
319 ]
320 .iter()
321 .map(|prop_id| context.get_tpm_property(*prop_id))
323 .collect::<Result<Vec<Option<u32>>>>()?
325 .iter()
326 .filter_map(|x| *x)
328 .filter(|x| *x != 0)
330 .map(tpm_int_to_string)
332 .collect())
334}