Skip to main content

tss_esapi/utils/
mod.rs

1// Copyright 2019 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3//! Utility module
4//!
5//! This module mostly contains helper elements meant to act as either wrappers around FFI-level
6//! structs or builders for them, along with other convenience elements.
7//! The naming structure usually takes the names inherited from the TSS spec and applies Rust
8//! guidelines to them. Structures that are meant to act as builders have `Builder` appended to
9//! type name. Unions are converted to Rust `enum`s by dropping the `TPMU` qualifier and appending
10//! `Union`.
11use 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::{Context, Error, Result, WrapperErrorKind};
23use std::convert::TryFrom;
24use zeroize::Zeroize;
25
26/// Create the [Public] structure for a restricted decryption key.
27///
28/// * `symmetric` - Cipher to be used for decrypting children of the key
29/// * `key_bits` - Size in bits of the decryption key
30/// * `pub_exponent` - Public exponent of the RSA key
31pub fn create_restricted_decryption_rsa_public(
32    symmetric: SymmetricDefinitionObject,
33    rsa_key_bits: RsaKeyBits,
34    rsa_pub_exponent: RsaExponent,
35) -> Result<Public> {
36    let object_attributes = ObjectAttributesBuilder::new()
37        .with_fixed_tpm(true)
38        .with_fixed_parent(true)
39        .with_sensitive_data_origin(true)
40        .with_user_with_auth(true)
41        .with_decrypt(true)
42        .with_sign_encrypt(false)
43        .with_restricted(true)
44        .build()?;
45
46    PublicBuilder::new()
47        .with_public_algorithm(PublicAlgorithm::Rsa)
48        .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
49        .with_object_attributes(object_attributes)
50        .with_rsa_parameters(
51            PublicRsaParametersBuilder::new_restricted_decryption_key(
52                symmetric,
53                rsa_key_bits,
54                rsa_pub_exponent,
55            )
56            .build()?,
57        )
58        .with_rsa_unique_identifier(PublicKeyRsa::default())
59        .build()
60}
61
62/// Create the [Public] structure for an unrestricted encryption/decryption key.
63///
64/// * `symmetric` - Cipher to be used for decrypting children of the key
65/// * `key_bits` - Size in bits of the decryption key
66/// * `pub_exponent` - Public exponent of the RSA key
67pub fn create_unrestricted_encryption_decryption_rsa_public(
68    rsa_key_bits: RsaKeyBits,
69    rsa_pub_exponent: RsaExponent,
70) -> Result<Public> {
71    let object_attributes = ObjectAttributesBuilder::new()
72        .with_fixed_tpm(true)
73        .with_fixed_parent(true)
74        .with_sensitive_data_origin(true)
75        .with_user_with_auth(true)
76        .with_decrypt(true)
77        .with_sign_encrypt(true)
78        .with_restricted(false)
79        .build()?;
80
81    PublicBuilder::new()
82        .with_public_algorithm(PublicAlgorithm::Rsa)
83        .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
84        .with_object_attributes(object_attributes)
85        .with_rsa_parameters(
86            PublicRsaParametersBuilder::new()
87                .with_scheme(RsaScheme::Null)
88                .with_key_bits(rsa_key_bits)
89                .with_exponent(rsa_pub_exponent)
90                .with_is_signing_key(true)
91                .with_is_decryption_key(true)
92                .with_restricted(false)
93                .build()?,
94        )
95        .with_rsa_unique_identifier(PublicKeyRsa::default())
96        .build()
97}
98
99/// Create the [Public] structure for an RSA unrestricted signing key.
100///
101/// * `scheme` - RSA scheme to be used for signing
102/// * `key_bits` - Size in bits of the decryption key
103/// * `pub_exponent` - Public exponent of the RSA key
104pub fn create_unrestricted_signing_rsa_public(
105    scheme: RsaScheme,
106    rsa_key_bits: RsaKeyBits,
107    rsa_pub_exponent: RsaExponent,
108) -> Result<Public> {
109    let object_attributes = ObjectAttributesBuilder::new()
110        .with_fixed_tpm(true)
111        .with_fixed_parent(true)
112        .with_sensitive_data_origin(true)
113        .with_user_with_auth(true)
114        .with_decrypt(false)
115        .with_sign_encrypt(true)
116        .with_restricted(false)
117        .build()?;
118
119    PublicBuilder::new()
120        .with_public_algorithm(PublicAlgorithm::Rsa)
121        .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
122        .with_object_attributes(object_attributes)
123        .with_rsa_parameters(
124            PublicRsaParametersBuilder::new_unrestricted_signing_key(
125                scheme,
126                rsa_key_bits,
127                rsa_pub_exponent,
128            )
129            .build()?,
130        )
131        .with_rsa_unique_identifier(PublicKeyRsa::default())
132        .build()
133}
134
135/// Create the [Public] structure for an RSA unrestricted signing key.
136///
137/// * `scheme` - RSA scheme to be used for signing
138/// * `key_bits` - Size in bits of the decryption key
139/// * `pub_exponent` - Public exponent of the RSA key
140/// * `rsa_public_key` - The public part of the RSA key that is going to be used as unique identifier.
141pub fn create_unrestricted_signing_rsa_public_with_unique(
142    scheme: RsaScheme,
143    rsa_key_bits: RsaKeyBits,
144    rsa_pub_exponent: RsaExponent,
145    rsa_public_key: PublicKeyRsa,
146) -> Result<Public> {
147    let object_attributes = ObjectAttributesBuilder::new()
148        .with_fixed_tpm(true)
149        .with_fixed_parent(true)
150        .with_sensitive_data_origin(true)
151        .with_user_with_auth(true)
152        .with_decrypt(false)
153        .with_sign_encrypt(true)
154        .with_restricted(false)
155        .build()?;
156
157    PublicBuilder::new()
158        .with_public_algorithm(PublicAlgorithm::Rsa)
159        .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
160        .with_object_attributes(object_attributes)
161        .with_rsa_parameters(
162            PublicRsaParametersBuilder::new_unrestricted_signing_key(
163                scheme,
164                rsa_key_bits,
165                rsa_pub_exponent,
166            )
167            .build()?,
168        )
169        .with_rsa_unique_identifier(rsa_public_key)
170        .build()
171}
172
173/// Create the [Public] structure for an ECC unrestricted signing key.
174///
175/// * `scheme` - Asymmetric scheme to be used for signing; *must* be an RSA signing scheme
176/// * `curve` - identifier of the precise curve to be used with the key
177pub fn create_unrestricted_signing_ecc_public(
178    scheme: EccScheme,
179    curve: EccCurve,
180) -> Result<Public> {
181    let object_attributes = ObjectAttributesBuilder::new()
182        .with_fixed_tpm(true)
183        .with_fixed_parent(true)
184        .with_sensitive_data_origin(true)
185        .with_user_with_auth(true)
186        .with_decrypt(false)
187        .with_sign_encrypt(true)
188        .with_restricted(false)
189        .build()?;
190
191    PublicBuilder::new()
192        .with_public_algorithm(PublicAlgorithm::Ecc)
193        .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
194        .with_object_attributes(object_attributes)
195        .with_ecc_parameters(
196            PublicEccParametersBuilder::new_unrestricted_signing_key(scheme, curve).build()?,
197        )
198        .with_ecc_unique_identifier(EccPoint::default())
199        .build()
200}
201
202/// Container for public key values
203///
204/// # Details
205/// This object can be serialized and deserialized
206/// using serde if the `serde` feature is enabled.
207#[derive(Debug, Clone, Zeroize, PartialEq, Eq)]
208#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
209pub enum PublicKey {
210    /// RSA public modulus (see 27.5.3.4 in the Architecture spec)
211    ///
212    /// This is the value extracted from the `unique` part of `TPMT_PUBLIC`.
213    /// The exponent is not included here as the expectation is that the
214    /// exponent is always pinned to 65537 (2^16 + 1).
215    ///
216    /// The modulus is in Big-Endian format.
217    Rsa(Vec<u8>),
218    /// Public elliptic curve point (see 27.5.3.5 in the Architecture spec)
219    ///
220    /// The x and y coordinates are given uncompressed.
221    Ecc { x: Vec<u8>, y: Vec<u8> },
222}
223
224impl TryFrom<Public> for PublicKey {
225    type Error = Error;
226
227    fn try_from(public: Public) -> Result<Self> {
228        match public {
229            Public::Rsa { unique, .. } => Ok(PublicKey::Rsa(unique.as_bytes().to_vec())),
230            Public::Ecc { unique, .. } => Ok(PublicKey::Ecc {
231                x: unique.x().as_bytes().to_vec(),
232                y: unique.y().as_bytes().to_vec(),
233            }),
234            _ => Err(Error::local_error(WrapperErrorKind::WrongValueFromTpm)),
235        }
236    }
237}
238
239fn tpm_int_to_string(num: u32) -> String {
240    num.to_be_bytes()
241        .iter()
242        .filter(|x| **x != 0)
243        .map(|x| char::from(*x))
244        .collect()
245}
246
247/// Get the TPM vendor name
248pub fn get_tpm_vendor(context: &mut Context) -> Result<String> {
249    // Retrieve the TPM property values
250    Ok([
251        PropertyTag::VendorString1,
252        PropertyTag::VendorString2,
253        PropertyTag::VendorString3,
254        PropertyTag::VendorString4,
255    ]
256    .iter()
257    // Retrieve property values
258    .map(|prop_id| context.get_tpm_property(*prop_id))
259    // Collect and return an error if we got one
260    .collect::<Result<Vec<Option<u32>>>>()?
261    .iter()
262    // Filter out the Option::None values
263    .filter_map(|x| *x)
264    // Filter out zero values
265    .filter(|x| *x != 0)
266    // Map through int_to_string
267    .map(tpm_int_to_string)
268    // Collect to a single string
269    .collect())
270}