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}