@@ -8,19 +8,150 @@ use crate::{
88 Context , Result , ReturnCode ,
99} ;
1010use log:: error;
11- use std:: convert:: TryFrom ;
1211use std:: ptr:: null_mut;
12+ use std:: { convert:: TryFrom , ptr:: null} ;
1313
1414impl Context {
1515 /// Perform an asymmetric RSA encryption.
16+ ///
17+ /// # Arguments
18+ ///
19+ /// * `key_handle` - A [KeyHandle] to to public portion of RSA key to use for encryption.
20+ /// * `message` - The message to be encrypted.
21+ /// * `in_scheme` - The padding scheme to use if scheme associated with
22+ /// the `key_handle` is [RsaDecryptionScheme::Null].
23+ /// * `label` - An optional label to be associated with the message.
24+ ///
25+ /// # Details
26+ ///
27+ /// *From the specification*
28+ /// > This command performs RSA encryption using the indicated padding scheme
29+ /// > according to IETF [RFC 8017](https://www.rfc-editor.org/rfc/rfc8017).
30+ ///
31+ /// > The label parameter is optional. If provided (label.size != 0) then the TPM shall return TPM_RC_VALUE if
32+ /// > the last octet in label is not zero. The terminating octet of zero is included in the label used in the padding
33+ /// > scheme.
34+ /// > If the scheme does not use a label, the TPM will still verify that label is properly formatted if label is
35+ /// > present.
36+ ///
37+ /// # Returns
38+ ///
39+ /// The encrypted output.
40+ ///
41+ /// # Example
42+ ///
43+ /// ```rust
44+ /// # use tss_esapi::{
45+ /// # Context, TctiNameConf,
46+ /// # attributes::{SessionAttributesBuilder, ObjectAttributesBuilder},
47+ /// # constants::SessionType,
48+ /// # interface_types::{
49+ /// # algorithm::{
50+ /// # HashingAlgorithm, PublicAlgorithm, RsaDecryptAlgorithm,
51+ /// # },
52+ /// # key_bits::RsaKeyBits,
53+ /// # reserved_handles::Hierarchy,
54+ /// # },
55+ /// # structures::{
56+ /// # Auth, Data, RsaScheme, PublicBuilder, PublicRsaParametersBuilder, PublicKeyRsa,
57+ /// # RsaDecryptionScheme, HashScheme, SymmetricDefinition, RsaExponent,
58+ /// # },
59+ /// # };
60+ /// # use std::{env, str::FromStr, convert::TryFrom};
61+ /// # // Create context
62+ /// # let mut context =
63+ /// # Context::new(
64+ /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
65+ /// # ).expect("Failed to create Context");
66+ /// #
67+ /// # let session = context
68+ /// # .start_auth_session(
69+ /// # None,
70+ /// # None,
71+ /// # None,
72+ /// # SessionType::Hmac,
73+ /// # SymmetricDefinition::AES_256_CFB,
74+ /// # tss_esapi::interface_types::algorithm::HashingAlgorithm::Sha256,
75+ /// # )
76+ /// # .expect("Failed to create session")
77+ /// # .expect("Received invalid handle");
78+ /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
79+ /// # .with_decrypt(true)
80+ /// # .with_encrypt(true)
81+ /// # .build();
82+ /// # context.tr_sess_set_attributes(session, session_attributes, session_attributes_mask)
83+ /// # .expect("Failed to set attributes on session");
84+ /// # context.set_sessions((Some(session), None, None));
85+ /// # let mut random_digest = vec![0u8; 16];
86+ /// # getrandom::getrandom(&mut random_digest).unwrap();
87+ /// # let key_auth = Auth::from_bytes(random_digest.as_slice()).unwrap();
88+ /// #
89+ /// # let object_attributes = ObjectAttributesBuilder::new()
90+ /// # .with_fixed_tpm(true)
91+ /// # .with_fixed_parent(true)
92+ /// # .with_sensitive_data_origin(true)
93+ /// # .with_user_with_auth(true)
94+ /// # .with_decrypt(true)
95+ /// # .with_sign_encrypt(true)
96+ /// # .with_restricted(false)
97+ /// # .build()
98+ /// # .expect("Should be able to build object attributes when the attributes are not conflicting.");
99+ /// #
100+ /// # let key_pub = PublicBuilder::new()
101+ /// # .with_public_algorithm(PublicAlgorithm::Rsa)
102+ /// # .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
103+ /// # .with_object_attributes(object_attributes)
104+ /// # .with_rsa_parameters(
105+ /// # PublicRsaParametersBuilder::new()
106+ /// # .with_scheme(RsaScheme::Null)
107+ /// # .with_key_bits(RsaKeyBits::Rsa2048)
108+ /// # .with_exponent(RsaExponent::default())
109+ /// # .with_is_signing_key(true)
110+ /// # .with_is_decryption_key(true)
111+ /// # .with_restricted(false)
112+ /// # .build()
113+ /// # .expect("Should be possible to build valid RSA parameters")
114+ /// # )
115+ /// # .with_rsa_unique_identifier(PublicKeyRsa::default())
116+ /// # .build()
117+ /// # .expect("Should be possible to build a valid Public object.");
118+ /// #
119+ /// # let key_handle = context
120+ /// # .create_primary(
121+ /// # Hierarchy::Owner,
122+ /// # key_pub,
123+ /// # None,
124+ /// # None,
125+ /// # None,
126+ /// # None,
127+ /// # )
128+ /// # .expect("Should be possible to create primary key from using valid Public object.")
129+ /// # .key_handle;
130+ /// // Because the key was created with RsaScheme::Null it is possible to
131+ /// // provide a scheme for the rsa_encrypt function to use.
132+ /// let scheme =
133+ /// RsaDecryptionScheme::create(RsaDecryptAlgorithm::Oaep, Some(HashingAlgorithm::Sha256))
134+ /// .expect("Failed to create rsa decryption scheme");
135+ /// let plain_text_bytes = vec![1, 2, 3, 4];
136+ /// let message_in = PublicKeyRsa::try_from(plain_text_bytes.clone())
137+ /// .expect("Should be possible to create a PublicKeyRsa object from valid bytes.");
138+ /// let cipher_text = context.rsa_encrypt(key_handle, message_in, scheme, None)
139+ /// .expect("Should be possible to call rsa_encrypt using valid arguments.");
140+ /// # let message_out = context.rsa_decrypt(key_handle, cipher_text, scheme, None)
141+ /// # .expect("Should be possible to call rsa_decrypt using valid arguments.");
142+ /// # let decrypted_bytes = message_out.as_bytes();
143+ /// # assert_eq!(plain_text_bytes, decrypted_bytes);
144+ /// ```
16145 pub fn rsa_encrypt (
17146 & mut self ,
18147 key_handle : KeyHandle ,
19148 message : PublicKeyRsa ,
20149 in_scheme : RsaDecryptionScheme ,
21- label : Data ,
150+ label : impl Into < Option < Data > > ,
22151 ) -> Result < PublicKeyRsa > {
23152 let mut out_data_ptr = null_mut ( ) ;
153+ let potential_label = label. into ( ) . map ( |v| v. into ( ) ) ;
154+ let label_ptr = potential_label. as_ref ( ) . map_or_else ( null, |v| v) ;
24155 ReturnCode :: ensure_success (
25156 unsafe {
26157 Esys_RSA_Encrypt (
@@ -31,7 +162,7 @@ impl Context {
31162 self . optional_session_3 ( ) ,
32163 & message. into ( ) ,
33164 & in_scheme. into ( ) ,
34- & label . into ( ) ,
165+ label_ptr ,
35166 & mut out_data_ptr,
36167 )
37168 } ,
@@ -43,14 +174,143 @@ impl Context {
43174 }
44175
45176 /// Perform an asymmetric RSA decryption.
177+ ///
178+ /// # Arguments
179+ ///
180+ /// * `key_handle` - A [KeyHandle] of the RSA key to use for decryption.
181+ /// * `cipher_text` - The cipher text to be decrypted.
182+ /// * `in_scheme` - The padding scheme to use if scheme associated with
183+ /// the `key_handle` is [RsaDecryptionScheme::Null].
184+ /// * `label` - An optional label whose association with the message is to be verified.
185+ ///
186+ /// # Details
187+ ///
188+ /// *From the specification*
189+ /// > This command performs RSA decryption using the indicated padding scheme according to IETF RFC
190+ /// > 8017 ((PKCS#1).
191+ ///
192+ /// > If a label is used in the padding process of the scheme during encryption, the label parameter is required
193+ /// > to be present in the decryption process and label is required to be the same in both cases. If label is not
194+ /// > the same, the decrypt operation is very likely to fail.
195+ ///
196+ /// # Returns
197+ ///
198+ /// The decrypted output.
199+ ///
200+ /// # Example
201+ ///
202+ /// ```rust
203+ /// # use tss_esapi::{
204+ /// # Context, TctiNameConf,
205+ /// # attributes::{SessionAttributesBuilder, ObjectAttributesBuilder},
206+ /// # constants::SessionType,
207+ /// # interface_types::{
208+ /// # algorithm::{
209+ /// # HashingAlgorithm, PublicAlgorithm, RsaDecryptAlgorithm,
210+ /// # },
211+ /// # key_bits::RsaKeyBits,
212+ /// # reserved_handles::Hierarchy,
213+ /// # },
214+ /// # structures::{
215+ /// # Auth, Data, RsaScheme, PublicBuilder, PublicRsaParametersBuilder, PublicKeyRsa,
216+ /// # RsaDecryptionScheme, HashScheme, SymmetricDefinition, RsaExponent,
217+ /// # },
218+ /// # };
219+ /// # use std::{env, str::FromStr, convert::TryFrom};
220+ /// # // Create context
221+ /// # let mut context =
222+ /// # Context::new(
223+ /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
224+ /// # ).expect("Failed to create Context");
225+ /// #
226+ /// # let session = context
227+ /// # .start_auth_session(
228+ /// # None,
229+ /// # None,
230+ /// # None,
231+ /// # SessionType::Hmac,
232+ /// # SymmetricDefinition::AES_256_CFB,
233+ /// # tss_esapi::interface_types::algorithm::HashingAlgorithm::Sha256,
234+ /// # )
235+ /// # .expect("Failed to create session")
236+ /// # .expect("Received invalid handle");
237+ /// # let (session_attributes, session_attributes_mask) = SessionAttributesBuilder::new()
238+ /// # .with_decrypt(true)
239+ /// # .with_encrypt(true)
240+ /// # .build();
241+ /// # context.tr_sess_set_attributes(session, session_attributes, session_attributes_mask)
242+ /// # .expect("Failed to set attributes on session");
243+ /// # context.set_sessions((Some(session), None, None));
244+ /// # let mut random_digest = vec![0u8; 16];
245+ /// # getrandom::getrandom(&mut random_digest).unwrap();
246+ /// # let key_auth = Auth::from_bytes(random_digest.as_slice()).unwrap();
247+ /// #
248+ /// # let object_attributes = ObjectAttributesBuilder::new()
249+ /// # .with_fixed_tpm(true)
250+ /// # .with_fixed_parent(true)
251+ /// # .with_sensitive_data_origin(true)
252+ /// # .with_user_with_auth(true)
253+ /// # .with_decrypt(true)
254+ /// # .with_sign_encrypt(true)
255+ /// # .with_restricted(false)
256+ /// # .build()
257+ /// # .expect("Should be able to build object attributes when the attributes are not conflicting.");
258+ /// #
259+ /// # let key_pub = PublicBuilder::new()
260+ /// # .with_public_algorithm(PublicAlgorithm::Rsa)
261+ /// # .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
262+ /// # .with_object_attributes(object_attributes)
263+ /// # .with_rsa_parameters(
264+ /// # PublicRsaParametersBuilder::new()
265+ /// # .with_scheme(RsaScheme::Null)
266+ /// # .with_key_bits(RsaKeyBits::Rsa2048)
267+ /// # .with_exponent(RsaExponent::default())
268+ /// # .with_is_signing_key(true)
269+ /// # .with_is_decryption_key(true)
270+ /// # .with_restricted(false)
271+ /// # .build()
272+ /// # .expect("Should be possible to build valid RSA parameters")
273+ /// # )
274+ /// # .with_rsa_unique_identifier(PublicKeyRsa::default())
275+ /// # .build()
276+ /// # .expect("Should be possible to build a valid Public object.");
277+ /// #
278+ /// # let key_handle = context
279+ /// # .create_primary(
280+ /// # Hierarchy::Owner,
281+ /// # key_pub,
282+ /// # None,
283+ /// # None,
284+ /// # None,
285+ /// # None,
286+ /// # )
287+ /// # .expect("Should be possible to create primary key from using valid Public object.")
288+ /// # .key_handle;
289+ /// # let scheme =
290+ /// # RsaDecryptionScheme::create(RsaDecryptAlgorithm::RsaEs, None)
291+ /// # .expect("Failed to create rsa decryption scheme");
292+ /// # let plain_text_bytes = vec![4, 3, 2, 1, 0];
293+ /// # let message_in = PublicKeyRsa::try_from(plain_text_bytes.clone())
294+ /// # .expect("Should be possible to create a PublicKeyRsa object from valid bytes.");
295+ /// # let label = Data::default();
296+ /// # let cipher_text = context.rsa_encrypt(key_handle, message_in, scheme, label.clone())
297+ /// # .expect("Should be possible to call rsa_encrypt using valid arguments.");
298+ /// // label text needs to be the same as the on used when data was encrypted.
299+ /// let message_out = context.rsa_decrypt(key_handle, cipher_text, scheme, label)
300+ /// .expect("Should be possible to call rsa_decrypt using valid arguments.");
301+ /// let decrypted_bytes = message_out.as_bytes();
302+ /// # assert_eq!(plain_text_bytes, decrypted_bytes);
303+ /// ```
46304 pub fn rsa_decrypt (
47305 & mut self ,
48306 key_handle : KeyHandle ,
49307 cipher_text : PublicKeyRsa ,
50308 in_scheme : RsaDecryptionScheme ,
51- label : Data ,
309+ label : impl Into < Option < Data > > ,
52310 ) -> Result < PublicKeyRsa > {
53311 let mut message_ptr = null_mut ( ) ;
312+ let potential_label = label. into ( ) . map ( |v| v. into ( ) ) ;
313+ let label_ptr = potential_label. as_ref ( ) . map_or_else ( null, |v| v) ;
54314 ReturnCode :: ensure_success (
55315 unsafe {
56316 Esys_RSA_Decrypt (
@@ -61,7 +321,7 @@ impl Context {
61321 self . optional_session_3 ( ) ,
62322 & cipher_text. into ( ) ,
63323 & in_scheme. into ( ) ,
64- & label . into ( ) ,
324+ label_ptr ,
65325 & mut message_ptr,
66326 )
67327 } ,
0 commit comments