Skip to main content

tss_esapi/context/tpm_commands/
asymmetric_primitives.rs

1// Copyright 2021 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3use crate::{
4    handles::KeyHandle,
5    structures::Data,
6    structures::{EccPoint, PublicKeyRsa, RsaDecryptionScheme},
7    tss2_esys::{Esys_ECDH_KeyGen, Esys_ECDH_ZGen, Esys_RSA_Decrypt, Esys_RSA_Encrypt},
8    Context, Error, Result,
9};
10use log::error;
11use std::convert::TryFrom;
12use std::ptr::null_mut;
13
14impl Context {
15    /// Perform an asymmetric RSA encryption.
16    pub fn rsa_encrypt(
17        &mut self,
18        key_handle: KeyHandle,
19        message: PublicKeyRsa,
20        in_scheme: RsaDecryptionScheme,
21        label: Data,
22    ) -> Result<PublicKeyRsa> {
23        let mut out_data_ptr = null_mut();
24        let ret = unsafe {
25            Esys_RSA_Encrypt(
26                self.mut_context(),
27                key_handle.into(),
28                self.optional_session_1(),
29                self.optional_session_2(),
30                self.optional_session_3(),
31                &message.into(),
32                &in_scheme.into(),
33                &label.into(),
34                &mut out_data_ptr,
35            )
36        };
37        let ret = Error::from_tss_rc(ret);
38
39        if ret.is_success() {
40            PublicKeyRsa::try_from(Context::ffi_data_to_owned(out_data_ptr))
41        } else {
42            error!("Error when performing RSA encryption: {}", ret);
43            Err(ret)
44        }
45    }
46
47    /// Perform an asymmetric RSA decryption.
48    pub fn rsa_decrypt(
49        &mut self,
50        key_handle: KeyHandle,
51        cipher_text: PublicKeyRsa,
52        in_scheme: RsaDecryptionScheme,
53        label: Data,
54    ) -> Result<PublicKeyRsa> {
55        let mut message_ptr = null_mut();
56        let ret = unsafe {
57            Esys_RSA_Decrypt(
58                self.mut_context(),
59                key_handle.into(),
60                self.required_session_1()?,
61                self.optional_session_2(),
62                self.optional_session_3(),
63                &cipher_text.into(),
64                &in_scheme.into(),
65                &label.into(),
66                &mut message_ptr,
67            )
68        };
69        let ret = Error::from_tss_rc(ret);
70
71        if ret.is_success() {
72            PublicKeyRsa::try_from(Context::ffi_data_to_owned(message_ptr))
73        } else {
74            error!("Error when performing RSA decryption: {}", ret);
75            Err(ret)
76        }
77    }
78
79    /// Generate an ephemeral key pair.
80    ///
81    /// # Arguments
82    /// * `key_handle`- A [KeyHandle] of ECC key which curve parameters will be used
83    ///   to generate the ephemeral key.
84    ///
85    /// # Details
86    /// This command uses the TPM to generate an ephemeral
87    /// key pair. It uses the private ephemeral key and a loaded
88    /// public key to compute the shared secret value.
89    ///
90    /// # Example
91    ///
92    /// ```rust
93    /// # use tss_esapi::{
94    /// #    Context, TctiNameConf,
95    /// #    attributes::{SessionAttributesBuilder, ObjectAttributesBuilder},
96    /// #    constants::SessionType,
97    /// #    interface_types::{
98    /// #        algorithm::{
99    /// #            HashingAlgorithm, PublicAlgorithm, RsaDecryptAlgorithm,
100    /// #        },
101    /// #        ecc::EccCurve,
102    /// #        resource_handles::Hierarchy,
103    /// #   },
104    /// #   structures::{
105    /// #       Auth, Data, EccScheme, PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, KeyDerivationFunctionScheme, EccPoint,
106    /// #        RsaDecryptionScheme, HashScheme, SymmetricDefinition,
107    /// #    },
108    /// # };
109    /// # use std::{env, str::FromStr, convert::TryFrom};
110    /// # // Create context
111    /// # let mut context =
112    /// #     Context::new(
113    /// #         TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
114    /// #     ).expect("Failed to create Context");
115    /// #
116    /// # let session = context
117    /// #     .start_auth_session(
118    /// #         None,
119    /// #         None,
120    /// #         None,
121    /// #         SessionType::Hmac,
122    /// #         SymmetricDefinition::AES_256_CFB,
123    /// #         tss_esapi::interface_types::algorithm::HashingAlgorithm::Sha256,
124    /// #     )
125    /// #     .expect("Failed to create session")
126    /// #     .expect("Received invalid handle");
127    /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
128    /// #     .with_decrypt(true)
129    /// #     .with_encrypt(true)
130    /// #     .build();
131    /// # context.tr_sess_set_attributes(session, session_attributes, session_attributes_mask)
132    /// #     .expect("Failed to set attributes on session");
133    /// # context.set_sessions((Some(session), None, None));
134    /// # let mut random_digest = vec![0u8; 16];
135    /// # getrandom::fill(&mut random_digest).unwrap();
136    /// # let key_auth = Auth::try_from(random_digest).unwrap();
137    /// #
138    /// // Create a key suitable for ECDH key generation
139    /// let ecc_parms = PublicEccParametersBuilder::new()
140    ///     .with_ecc_scheme(
141    ///         EccScheme::EcDh(HashScheme::new(HashingAlgorithm::Sha256)),
142    ///     )
143    ///     .with_curve(EccCurve::NistP256)
144    ///     .with_is_signing_key(false)
145    ///     .with_is_decryption_key(true)
146    ///     .with_restricted(false)
147    ///     .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null)
148    ///     .build()
149    ///     .unwrap();
150    ///
151    /// let object_attributes = ObjectAttributesBuilder::new()
152    ///     .with_fixed_tpm(true)
153    ///     .with_fixed_parent(true)
154    ///     .with_sensitive_data_origin(true)
155    ///     .with_user_with_auth(true)
156    ///     .with_decrypt(true)
157    ///     .with_sign_encrypt(false)
158    ///     .with_restricted(false)
159    ///     .build()
160    ///     .unwrap();
161    ///
162    /// let public = PublicBuilder::new()
163    ///     .with_public_algorithm(PublicAlgorithm::Ecc)
164    ///     .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
165    ///     .with_object_attributes(object_attributes)
166    ///     .with_ecc_parameters(ecc_parms)
167    ///     .with_ecc_unique_identifier(EccPoint::default())
168    ///     .build()
169    ///     .unwrap();
170    ///
171    /// let key_handle = context
172    ///     .create_primary(
173    ///         Hierarchy::Owner,
174    ///         public,
175    ///         Some(key_auth),
176    ///         None,
177    ///         None,
178    ///         None,
179    ///     )
180    ///     .unwrap()
181    ///     .key_handle;
182    ///
183    /// // Generate ephemeral key pair and a shared secret
184    /// let (z_point, pub_point) = context.ecdh_key_gen(key_handle).unwrap();
185    /// ```
186    pub fn ecdh_key_gen(&mut self, key_handle: KeyHandle) -> Result<(EccPoint, EccPoint)> {
187        let mut z_point_ptr = null_mut();
188        let mut pub_point_ptr = null_mut();
189        let ret = unsafe {
190            Esys_ECDH_KeyGen(
191                self.mut_context(),
192                key_handle.into(),
193                self.optional_session_1(),
194                self.optional_session_2(),
195                self.optional_session_3(),
196                &mut z_point_ptr,
197                &mut pub_point_ptr,
198            )
199        };
200
201        let ret = Error::from_tss_rc(ret);
202
203        if ret.is_success() {
204            let z_point = Context::ffi_data_to_owned(z_point_ptr);
205            let pub_point = Context::ffi_data_to_owned(pub_point_ptr);
206            Ok((
207                EccPoint::try_from(z_point.point)?,
208                EccPoint::try_from(pub_point.point)?,
209            ))
210        } else {
211            error!("Error when generating ECDH keypair: {}", ret);
212            Err(ret)
213        }
214    }
215
216    /// Recover Z value from a public point and a private key.
217    ///
218    /// # Arguments
219    /// * `key_handle` - A [KeyHandle] of ECC key which curve parameters will be used
220    ///   to generate the ephemeral key.
221    /// * `in_point` - An [EccPoint] on the curve of the key referenced by `key_handle`
222    ///
223    /// # Details
224    /// This command uses the TPM to recover the Z value from a public point and a private key.
225    /// It will perform the multiplication of the provided `in_point` with the private key and
226    /// return the coordinates of the resultant point.
227    ///
228    /// # Example
229    ///
230    /// ```rust
231    /// # use tss_esapi::{
232    /// #    Context, TctiNameConf,
233    /// #    attributes::{SessionAttributesBuilder, ObjectAttributesBuilder},
234    /// #    constants::SessionType,
235    /// #    interface_types::{
236    /// #        algorithm::{
237    /// #            HashingAlgorithm, PublicAlgorithm, RsaDecryptAlgorithm,
238    /// #        },
239    /// #        ecc::EccCurve,
240    /// #        resource_handles::Hierarchy,
241    /// #   },
242    /// #   structures::{
243    /// #       Auth, Data, EccScheme, PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, KeyDerivationFunctionScheme, EccPoint,
244    /// #        RsaDecryptionScheme, HashScheme, SymmetricDefinition,
245    /// #    },
246    /// # };
247    /// # use std::{env, str::FromStr, convert::TryFrom};
248    /// # // Create context
249    /// # let mut context =
250    /// #     Context::new(
251    /// #         TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
252    /// #     ).expect("Failed to create Context");
253    /// #
254    /// # let session = context
255    /// #     .start_auth_session(
256    /// #         None,
257    /// #         None,
258    /// #         None,
259    /// #         SessionType::Hmac,
260    /// #         SymmetricDefinition::AES_256_CFB,
261    /// #         tss_esapi::interface_types::algorithm::HashingAlgorithm::Sha256,
262    /// #     )
263    /// #     .expect("Failed to create session")
264    /// #     .expect("Received invalid handle");
265    /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
266    /// #     .with_decrypt(true)
267    /// #     .with_encrypt(true)
268    /// #     .build();
269    /// # context.tr_sess_set_attributes(session, session_attributes, session_attributes_mask)
270    /// #     .expect("Failed to set attributes on session");
271    /// # context.set_sessions((Some(session), None, None));
272    /// # let mut random_digest = vec![0u8; 16];
273    /// # getrandom::fill(&mut random_digest).unwrap();
274    /// # let key_auth = Auth::try_from(random_digest).unwrap();
275    /// #
276    /// // Create a key suitable for ECDH key generation
277    /// let ecc_parms = PublicEccParametersBuilder::new()
278    ///     .with_ecc_scheme(
279    ///         EccScheme::EcDh(HashScheme::new(HashingAlgorithm::Sha256)),
280    ///     )
281    ///     .with_curve(EccCurve::NistP256)
282    ///     .with_is_signing_key(false)
283    ///     .with_is_decryption_key(true)
284    ///     .with_restricted(false)
285    ///     .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null)
286    ///     .build()
287    ///     .unwrap();
288    ///
289    /// let object_attributes = ObjectAttributesBuilder::new()
290    ///     .with_fixed_tpm(true)
291    ///     .with_fixed_parent(true)
292    ///     .with_sensitive_data_origin(true)
293    ///     .with_user_with_auth(true)
294    ///     .with_decrypt(true)
295    ///     .with_sign_encrypt(false)
296    ///     .with_restricted(false)
297    ///     .build()
298    ///     .unwrap();
299    ///
300    /// let public = PublicBuilder::new()
301    ///     .with_public_algorithm(PublicAlgorithm::Ecc)
302    ///     .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
303    ///     .with_object_attributes(object_attributes)
304    ///     .with_ecc_parameters(ecc_parms)
305    ///     .with_ecc_unique_identifier(EccPoint::default())
306    ///     .build()
307    ///     .unwrap();
308    ///
309    /// let key_handle = context
310    ///     .create_primary(
311    ///         Hierarchy::Owner,
312    ///         public,
313    ///         Some(key_auth),
314    ///         None,
315    ///         None,
316    ///         None,
317    ///     )
318    ///     .unwrap()
319    ///     .key_handle;
320    ///
321    /// // Generate ephemeral key pair and a shared secret
322    /// let (z_point, pub_point) = context.ecdh_key_gen(key_handle).unwrap();
323    /// let z_point_gen = context.ecdh_z_gen(key_handle, pub_point).unwrap();
324    /// assert_eq!(z_point.x().value(), z_point_gen.x().value());
325    /// ```
326    pub fn ecdh_z_gen(&mut self, key_handle: KeyHandle, in_point: EccPoint) -> Result<EccPoint> {
327        let mut out_point_ptr = null_mut();
328        let ret = unsafe {
329            Esys_ECDH_ZGen(
330                self.mut_context(),
331                key_handle.into(),
332                self.required_session_1()?,
333                self.optional_session_2(),
334                self.optional_session_3(),
335                &in_point.into(),
336                &mut out_point_ptr,
337            )
338        };
339        let ret = Error::from_tss_rc(ret);
340
341        if ret.is_success() {
342            let out_point = Context::ffi_data_to_owned(out_point_ptr);
343            EccPoint::try_from(out_point.point)
344        } else {
345            error!("Error when performing ECDH ZGen: {}", ret);
346            Err(ret)
347        }
348    }
349
350    // Missing function: ECC_Parameters
351    // Missing function: ZGen_2Phase
352}