@@ -15,7 +15,7 @@ use crate::{
1515 Esys_ActivateCredential , Esys_Create , Esys_Load , Esys_LoadExternal , Esys_MakeCredential ,
1616 Esys_ObjectChangeAuth , Esys_ReadPublic , Esys_Unseal ,
1717 } ,
18- Context , Result , ReturnCode ,
18+ Context , Error , Result , ReturnCode , WrapperErrorKind ,
1919} ;
2020use create_command_input:: CreateCommandInputHandler ;
2121use create_command_output:: CreateCommandOutputHandler ;
@@ -123,22 +123,126 @@ impl Context {
123123 }
124124
125125 /// Load an external key into the TPM and return its new handle.
126+ ///
127+ /// # Details
128+ /// This command is used to load an object that is not a Protected Object into the TPM. The command allows
129+ /// loading of a public area or both a public and sensitive area.
130+ ///
131+ /// # Arguments
132+ /// * `private` - The optional sensitive portion of the object.
133+ /// * `public` - The public portion of the object.
134+ /// * `hierarchy` - The hierarchy with which the object area is associated.
135+ ///
136+ /// # Returns
137+ /// The handle to the loaded key.
138+ ///
139+ /// # Example
140+ ///
141+ /// ```rust
142+ /// # use tss_esapi::{
143+ /// # Context, TctiNameConf,
144+ /// # attributes::ObjectAttributesBuilder,
145+ /// # constants::SessionType,
146+ /// # interface_types::{
147+ /// # algorithm::{HashingAlgorithm, PublicAlgorithm, RsaSchemeAlgorithm},
148+ /// # key_bits::RsaKeyBits,
149+ /// # reserved_handles::Hierarchy,
150+ /// # },
151+ /// # structures::{
152+ /// # Public, PublicBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaScheme,
153+ /// # SymmetricDefinition,
154+ /// # },
155+ /// # };
156+ /// #
157+ /// # const KEY: [u8; 256] = [
158+ /// # 231, 97, 201, 180, 0, 1, 185, 150, 85, 90, 174, 188, 105, 133, 188, 3, 206, 5, 222, 71, 185, 1,
159+ /// # 209, 243, 36, 130, 250, 116, 17, 0, 24, 4, 25, 225, 250, 198, 245, 210, 140, 23, 139, 169, 15,
160+ /// # 193, 4, 145, 52, 138, 149, 155, 238, 36, 74, 152, 179, 108, 200, 248, 250, 100, 115, 214, 166,
161+ /// # 165, 1, 27, 51, 11, 11, 244, 218, 157, 3, 174, 171, 142, 45, 8, 9, 36, 202, 171, 165, 43, 208,
162+ /// # 186, 232, 15, 241, 95, 81, 174, 189, 30, 213, 47, 86, 115, 239, 49, 214, 235, 151, 9, 189, 174,
163+ /// # 144, 238, 200, 201, 241, 157, 43, 37, 6, 96, 94, 152, 159, 205, 54, 9, 181, 14, 35, 246, 49,
164+ /// # 150, 163, 118, 242, 59, 54, 42, 221, 215, 248, 23, 18, 223, 179, 229, 0, 204, 65, 69, 166, 180,
165+ /// # 11, 49, 131, 96, 163, 96, 158, 7, 109, 119, 208, 17, 237, 125, 187, 121, 94, 65, 2, 86, 105,
166+ /// # 68, 51, 197, 73, 108, 185, 231, 126, 199, 81, 1, 251, 211, 45, 47, 15, 113, 135, 197, 152, 239,
167+ /// # 180, 111, 18, 192, 136, 222, 11, 99, 41, 248, 205, 253, 209, 56, 214, 32, 225, 3, 49, 161, 58,
168+ /// # 57, 190, 69, 86, 95, 185, 184, 155, 76, 8, 122, 104, 81, 222, 234, 246, 40, 98, 182, 90, 160,
169+ /// # 111, 74, 102, 36, 148, 99, 69, 207, 214, 104, 87, 128, 238, 26, 121, 107, 166, 4, 64, 5, 210,
170+ /// # 164, 162, 189,
171+ /// # ];
172+ /// #
173+ /// # // Create context
174+ /// # let mut context =
175+ /// # Context::new(
176+ /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
177+ /// # ).expect("Failed to create Context");
178+ /// #
179+ /// # let session = context
180+ /// # .start_auth_session(
181+ /// # None,
182+ /// # None,
183+ /// # None,
184+ /// # SessionType::Hmac,
185+ /// # SymmetricDefinition::AES_256_CFB,
186+ /// # tss_esapi::interface_types::algorithm::HashingAlgorithm::Sha256,
187+ /// # )
188+ /// # .expect("Failed to create session")
189+ /// # .expect("Received invalid handle");
190+ /// #
191+ /// let object_attributes = ObjectAttributesBuilder::new()
192+ /// .with_user_with_auth(true)
193+ /// .with_decrypt(false)
194+ /// .with_sign_encrypt(true)
195+ /// .with_restricted(false)
196+ /// .build()
197+ /// .expect("Failed to build object attributes");
198+ ///
199+ /// let public = PublicBuilder::new()
200+ /// .with_public_algorithm(PublicAlgorithm::Rsa)
201+ /// .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
202+ /// .with_object_attributes(object_attributes)
203+ /// .with_rsa_parameters(
204+ /// PublicRsaParametersBuilder::new_unrestricted_signing_key(
205+ /// RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256))
206+ /// .expect("Failed to create rsa scheme"),
207+ /// RsaKeyBits::Rsa2048,
208+ /// Default::default(),
209+ /// )
210+ /// .build()
211+ /// .expect("Failed to create rsa parameters for public structure"),
212+ /// )
213+ /// .with_rsa_unique_identifier(
214+ /// PublicKeyRsa::from_bytes(&KEY[..256])
215+ /// .expect("Failed to create Public RSA key from buffer"),
216+ /// )
217+ /// .build()
218+ /// .expect("Failed to build Public structure");
219+ ///
220+ /// // Load public key into Owner hierarchy.
221+ /// let key_handle = context.load_external(None, public, Hierarchy::Owner)
222+ /// .expect("The load_external should have returned a valid key handle.");
223+ /// ```
126224 pub fn load_external (
127225 & mut self ,
128- private : Sensitive ,
226+ private : Option < Sensitive > ,
129227 public : Public ,
130228 hierarchy : Hierarchy ,
131229 ) -> Result < KeyHandle > {
230+ if ( hierarchy != Hierarchy :: Null ) && private. is_some ( ) {
231+ error ! ( "Only NULL hierarchy is valid in load_external when loading both private and public part." ) ;
232+ return Err ( Error :: local_error ( WrapperErrorKind :: InvalidParam ) ) ;
233+ }
132234 let mut object_handle = ObjectHandle :: None . into ( ) ;
235+ let potential_private_in = private. map ( |v| v. try_into ( ) ) . transpose ( ) ?;
236+ let public_in = public. try_into ( ) ?;
133237 ReturnCode :: ensure_success (
134238 unsafe {
135239 Esys_LoadExternal (
136240 self . mut_context ( ) ,
137241 self . optional_session_1 ( ) ,
138242 self . optional_session_2 ( ) ,
139243 self . optional_session_3 ( ) ,
140- & private . try_into ( ) ? ,
141- & public . try_into ( ) ? ,
244+ potential_private_in . as_ref ( ) . map_or_else ( null , |v| v ) ,
245+ & public_in ,
142246 if cfg ! ( hierarchy_is_esys_tr) {
143247 ObjectHandle :: from ( hierarchy) . into ( )
144248 } else {
@@ -158,41 +262,6 @@ impl Context {
158262 Ok ( key_handle)
159263 }
160264
161- /// Load the public part of an external key and return its new handle.
162- pub fn load_external_public (
163- & mut self ,
164- public : Public ,
165- hierarchy : Hierarchy ,
166- ) -> Result < KeyHandle > {
167- let mut object_handle = ObjectHandle :: None . into ( ) ;
168- ReturnCode :: ensure_success (
169- unsafe {
170- Esys_LoadExternal (
171- self . mut_context ( ) ,
172- self . optional_session_1 ( ) ,
173- self . optional_session_2 ( ) ,
174- self . optional_session_3 ( ) ,
175- null ( ) ,
176- & public. try_into ( ) ?,
177- if cfg ! ( hierarchy_is_esys_tr) {
178- ObjectHandle :: from ( hierarchy) . into ( )
179- } else {
180- TpmHandle :: from ( hierarchy) . into ( )
181- } ,
182- & mut object_handle,
183- )
184- } ,
185- |ret| {
186- error ! ( "Error in loading external public object: {:#010X}" , ret) ;
187- } ,
188- ) ?;
189-
190- let key_handle = KeyHandle :: from ( object_handle) ;
191- self . handle_manager
192- . add_handle ( key_handle. into ( ) , HandleDropAction :: Flush ) ?;
193- Ok ( key_handle)
194- }
195-
196265 /// Read the public part of a key currently in the TPM and return it.
197266 pub fn read_public ( & mut self , key_handle : KeyHandle ) -> Result < ( Public , Name , Name ) > {
198267 let mut out_public_ptr = null_mut ( ) ;
0 commit comments