1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //! Implementation of the `IHwCryptoKey` AIDL interface. It can be use to generate and
18 //! retrieve device specific keys.
19 
20 use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::{
21     types::{
22         ExplicitKeyMaterial::ExplicitKeyMaterial, KeyLifetime::KeyLifetime, KeyType::KeyType,
23         KeyUse::KeyUse, OpaqueKeyToken::OpaqueKeyToken,
24     },
25     IHwCryptoKey::{
26         BnHwCryptoKey, DerivedKey::DerivedKey, DerivedKeyParameters::DerivedKeyParameters,
27         DerivedKeyPolicy::DerivedKeyPolicy, DeviceKeyId::DeviceKeyId,
28         DiceBoundDerivationKey::DiceBoundDerivationKey, DiceBoundKeyResult::DiceBoundKeyResult,
29         DiceCurrentBoundKeyResult::DiceCurrentBoundKeyResult, IHwCryptoKey, KeySlot::KeySlot,
30     },
31     IHwCryptoOperations::IHwCryptoOperations,
32     IOpaqueKey::IOpaqueKey,
33     KeyPolicy::KeyPolicy,
34 };
35 use android_hardware_security_see_hwcrypto::binder;
36 use ciborium::{cbor, Value};
37 use coset::{AsCborValue, CborSerializable, CoseError};
38 use hwcryptohal_common::{cose_enum_gen, err::HwCryptoError, hwcrypto_err};
39 use hwkey::{Hwkey, KdfVersion};
40 use tipc::Uuid;
41 
42 use crate::hwcrypto_operations::HwCryptoOperations;
43 
44 use crate::helpers;
45 use crate::opaque_key::{self, DerivationContext, HkdfOperationType, OpaqueKey};
46 use crate::service_encryption_key::{
47     self, EncryptedContent, EncryptionHeader, EncryptionHeaderKey,
48 };
49 
50 const DEVICE_KEY_CTX: &[u8] = b"device_key_derivation_contextKEK";
51 
52 // enum used for serializing the `VersionContext`
53 cose_enum_gen! {
54     enum VersionContextCoseLabels {
55         Uuid = -65537,
56         Version = -65538,
57     }
58 }
59 
60 // TODO: `ConnectionInformation` will be opaque to the HwCrypto service once we have a connection
61 //        manager.
62 struct ConnectionInformation {
63     uuid: Uuid,
64 }
65 
66 // Mock version object to be used until we have more DICE support. It is based on the trusty version
67 // retrievable from HwKey and the uuid of the caller. `VersionContext`` encryption is similar to
68 // what KeyMint uses to wrap keys.
69 struct VersionContext {
70     uuid: Uuid,
71     version: u32,
72     header: Option<EncryptionHeader>,
73 }
74 
75 impl VersionContext {
get_current_version() -> Result<u32, HwCryptoError>76     fn get_current_version() -> Result<u32, HwCryptoError> {
77         service_encryption_key::get_service_current_version()
78     }
79 
new_current(uuid: Uuid) -> Result<Self, HwCryptoError>80     fn new_current(uuid: Uuid) -> Result<Self, HwCryptoError> {
81         let header = Some(EncryptionHeader::generate(EncryptedContent::DicePolicy)?);
82         let version = Self::get_current_version()?;
83         Ok(VersionContext { uuid, version, header })
84     }
85 
new_current_encrypted(uuid: Uuid) -> Result<Vec<u8>, HwCryptoError>86     fn new_current_encrypted(uuid: Uuid) -> Result<Vec<u8>, HwCryptoError> {
87         let ctx = Self::new_current(uuid)?;
88         Ok(ctx.encrypt_context()?)
89     }
90 
check_version(&self) -> Result<(), HwCryptoError>91     fn check_version(&self) -> Result<(), HwCryptoError> {
92         let current_version = Self::get_current_version()?;
93         if self.version > current_version {
94             return Err(hwcrypto_err!(BAD_PARAMETER, "version is not valid"));
95         }
96         Ok(())
97     }
98 
check_context(&self, connection: ConnectionInformation) -> Result<(), HwCryptoError>99     fn check_context(&self, connection: ConnectionInformation) -> Result<(), HwCryptoError> {
100         if connection.uuid != self.uuid {
101             return Err(hwcrypto_err!(BAD_PARAMETER, "uuid mismatch"));
102         }
103         self.check_version()
104     }
105 
check_encrypted_context( encrypted_ctx: &[u8], connection: ConnectionInformation, ) -> Result<(), HwCryptoError>106     fn check_encrypted_context(
107         encrypted_ctx: &[u8],
108         connection: ConnectionInformation,
109     ) -> Result<(), HwCryptoError> {
110         let context = Self::decrypt_context(encrypted_ctx)?;
111         context.check_context(connection)
112     }
113 
is_context_current(encrypted_ctx: &[u8]) -> Result<bool, HwCryptoError>114     fn is_context_current(encrypted_ctx: &[u8]) -> Result<bool, HwCryptoError> {
115         let context = Self::decrypt_context(encrypted_ctx)?;
116         let current_version = Self::get_current_version()?;
117         Ok(context.version >= current_version)
118     }
119 
decrypt_context(encrypted_context: &[u8]) -> Result<Self, HwCryptoError>120     fn decrypt_context(encrypted_context: &[u8]) -> Result<Self, HwCryptoError> {
121         let (version_ctx_header, decrypted_data) =
122             EncryptionHeader::decrypt_content_service_encryption_key(
123                 encrypted_context,
124                 EncryptionHeaderKey::KeyGenerationContext(DEVICE_KEY_CTX),
125                 EncryptedContent::DicePolicy,
126             )?;
127 
128         let mut version_context =
129             VersionContext::from_cbor_value(Value::from_slice(&decrypted_data[..])?)?;
130         version_context.header = Some(version_ctx_header);
131         Ok(version_context)
132     }
133 
encrypt_context(mut self) -> Result<Vec<u8>, HwCryptoError>134     fn encrypt_context(mut self) -> Result<Vec<u8>, HwCryptoError> {
135         let header = self.header.take().ok_or(hwcrypto_err!(BAD_PARAMETER, "no header found"))?;
136         header.encrypt_content_service_encryption_key(
137             EncryptionHeaderKey::KeyGenerationContext(DEVICE_KEY_CTX),
138             self,
139         )
140     }
141 
get_stable_context(encrypted_context: &[u8]) -> Result<Vec<u8>, HwCryptoError>142     fn get_stable_context(encrypted_context: &[u8]) -> Result<Vec<u8>, HwCryptoError> {
143         let decrypted_context = Self::decrypt_context(encrypted_context)?;
144         Ok(decrypted_context.to_cbor_value()?.to_vec()?)
145     }
146 }
147 
148 impl AsCborValue for VersionContext {
to_cbor_value(self) -> Result<Value, CoseError>149     fn to_cbor_value(self) -> Result<Value, CoseError> {
150         cbor!({
151             (VersionContextCoseLabels::Uuid as i64) => self.uuid.to_string(),
152             (VersionContextCoseLabels::Version as i64) => self.version,
153         })
154         .map_err(|_| CoseError::ExtraneousData)
155     }
156 
from_cbor_value(value: Value) -> Result<Self, CoseError>157     fn from_cbor_value(value: Value) -> Result<Self, CoseError> {
158         let version_context = value.into_map().map_err(|_| CoseError::ExtraneousData)?;
159         let mut uuid: Option<Uuid> = None;
160         let mut version: Option<u32> = None;
161         for (map_key, map_val) in version_context {
162             match map_key {
163                 Value::Integer(key) => {
164                     match key.try_into().map_err(|_| CoseError::EncodeFailed)? {
165                         VersionContextCoseLabels::Uuid => {
166                             let uuid_str =
167                                 map_val.into_text().map_err(|_| CoseError::EncodeFailed)?;
168                             let parsed_uuid = Uuid::new_from_string(&uuid_str)
169                                 .map_err(|_| CoseError::EncodeFailed)?;
170                             uuid = Some(parsed_uuid);
171                         }
172                         VersionContextCoseLabels::Version => {
173                             let parsed_version = map_val
174                                 .into_integer()
175                                 .map_err(|_| CoseError::EncodeFailed)?
176                                 .try_into()
177                                 .map_err(|_| CoseError::ExtraneousData)?;
178                             version = Some(parsed_version);
179                         }
180                     }
181                 }
182                 _ => return Err(CoseError::ExtraneousData),
183             }
184         }
185         let uuid = uuid.ok_or(CoseError::EncodeFailed)?;
186         let version = version.ok_or(CoseError::EncodeFailed)?;
187         // Header travels in the clear, the decoded section only contains the encrypted fields
188         Ok(VersionContext { uuid, version, header: None })
189     }
190 }
191 
192 /// The `IHwCryptoKey` implementation.
193 #[derive(Debug)]
194 pub struct HwCryptoKey {
195     pub(crate) uuid: Uuid,
196 }
197 
198 impl binder::Interface for HwCryptoKey {}
199 
200 impl HwCryptoKey {
new_binder(uuid: Uuid) -> binder::Strong<dyn IHwCryptoKey>201     pub(crate) fn new_binder(uuid: Uuid) -> binder::Strong<dyn IHwCryptoKey> {
202         let hwcrypto_device_key = HwCryptoKey { uuid };
203         BnHwCryptoKey::new_binder(hwcrypto_device_key, binder::BinderFeatures::default())
204     }
205 
206     // check_dice_policy_owner shall only be false for creating internal keys that can be used
207     // to seal content bounded to another party DICE policy
derive_dice_policy_bound_key( &self, derivation_key: &DiceBoundDerivationKey, dice_policy_for_key_version: &[u8], check_dice_policy_owner: bool, ) -> Result<DiceBoundKeyResult, HwCryptoError>208     pub(crate) fn derive_dice_policy_bound_key(
209         &self,
210         derivation_key: &DiceBoundDerivationKey,
211         dice_policy_for_key_version: &[u8],
212         check_dice_policy_owner: bool,
213     ) -> Result<DiceBoundKeyResult, HwCryptoError> {
214         // Verifying provided DICE policy
215         let connection_info = ConnectionInformation { uuid: self.uuid.clone() };
216         if check_dice_policy_owner {
217             VersionContext::check_encrypted_context(dice_policy_for_key_version, connection_info)?;
218         }
219         // Getting back a stable DICE policy for context, so keys derived with the same version will
220         // match
221         let dice_context = VersionContext::get_stable_context(dice_policy_for_key_version)?;
222         let mut op_context = DerivationContext::new(HkdfOperationType::DiceBoundDerivation)?;
223         op_context.add_owned_binary_string(dice_context)?;
224         let concat_context = op_context.create_key_derivation_context()?;
225 
226         // The returned key will only be used for derivation, so fixing tis type to HMAC_SHA256
227         let key_type = KeyType::HMAC_SHA256;
228         let key_size = opaque_key::get_key_size_in_bytes(&key_type)?;
229         // Create an array big enough to hold the bytes of the derived key material
230         let mut derived_key = Vec::<u8>::new();
231         derived_key.try_reserve(key_size)?;
232         derived_key.resize(key_size, 0);
233 
234         match derivation_key {
235             DiceBoundDerivationKey::KeyId(key_id) => {
236                 let hwkey_session = Hwkey::open().map_err(|e| {
237                     hwcrypto_err!(GENERIC_ERROR, "could not connect to hwkey service {:?}", e)
238                 })?;
239                 let session_req = match *key_id {
240                     DeviceKeyId::DEVICE_BOUND_KEY => {
241                         Ok(hwkey_session.derive_key_req().unique_key())
242                     }
243                     _ => Err(hwcrypto_err!(UNSUPPORTED, "unknown key id {:?}", key_id)),
244                 }?;
245 
246                 session_req
247                     .kdf(KdfVersion::Best)
248                     .derive(concat_context.as_slice(), &mut derived_key[..])
249                     .map_err(|e| hwcrypto_err!(GENERIC_ERROR, "failed to derive key {:?}", e))?;
250 
251                 let policy = KeyPolicy {
252                     usage: KeyUse::DERIVE,
253                     keyLifetime: KeyLifetime::HARDWARE,
254                     keyPermissions: Vec::new(),
255                     keyType: key_type,
256                     keyManagementKey: false,
257                 };
258                 // Create a new opaque key from the generated key material
259                 let km = opaque_key::generate_key_material(&policy.keyType, Some(derived_key))?;
260                 let key = opaque_key::OpaqueKey::new_binder(&policy, km, self.uuid.clone())
261                     .map_err(|e| hwcrypto_err!(GENERIC_ERROR, "failed to create key {:?}", e))?;
262                 let dice_policy_current =
263                     VersionContext::is_context_current(dice_policy_for_key_version)?;
264                 Ok(DiceBoundKeyResult {
265                     diceBoundKey: Some(key),
266                     dicePolicyWasCurrent: dice_policy_current,
267                 })
268             }
269             DiceBoundDerivationKey::OpaqueKey(_opaque_key) => Err(hwcrypto_err!(
270                 UNSUPPORTED,
271                 "derivation of DICE bound keys using opaque keys not supported yet"
272             )),
273         }
274     }
275 
check_caller_can_access_keyslot(&self, _keyslot: KeySlot) -> Result<(), HwCryptoError>276     fn check_caller_can_access_keyslot(&self, _keyslot: KeySlot) -> Result<(), HwCryptoError> {
277         // Simple uuid check for host uuid until we have DICE
278         if self.uuid.to_string() == "00000000-0000-0000-0000-000000000000" {
279             Err(hwcrypto_err!(UNAUTHORIZED, "caller do not have permission to access this key"))
280         } else {
281             Ok(())
282         }
283     }
284 }
285 
286 impl IHwCryptoKey for HwCryptoKey {
deriveCurrentDicePolicyBoundKey( &self, derivation_key: &DiceBoundDerivationKey, ) -> binder::Result<DiceCurrentBoundKeyResult>287     fn deriveCurrentDicePolicyBoundKey(
288         &self,
289         derivation_key: &DiceBoundDerivationKey,
290     ) -> binder::Result<DiceCurrentBoundKeyResult> {
291         let dice_policy = VersionContext::new_current_encrypted(self.uuid.clone())?;
292         let derived_key_result =
293             self.derive_dice_policy_bound_key(derivation_key, &dice_policy, true)?;
294         let DiceBoundKeyResult { diceBoundKey: key, dicePolicyWasCurrent: policy_current } =
295             derived_key_result;
296         if !policy_current {
297             return Err(binder::Status::new_exception_str(
298                 binder::ExceptionCode::UNSUPPORTED_OPERATION,
299                 Some("generated a policy that was not the latest"),
300             ));
301         }
302         Ok(DiceCurrentBoundKeyResult { diceBoundKey: key, dicePolicyForKeyVersion: dice_policy })
303     }
304 
deriveDicePolicyBoundKey( &self, derivation_key: &DiceBoundDerivationKey, dice_policy_for_key_version: &[u8], ) -> binder::Result<DiceBoundKeyResult>305     fn deriveDicePolicyBoundKey(
306         &self,
307         derivation_key: &DiceBoundDerivationKey,
308         dice_policy_for_key_version: &[u8],
309     ) -> binder::Result<DiceBoundKeyResult> {
310         Ok(self.derive_dice_policy_bound_key(derivation_key, dice_policy_for_key_version, true)?)
311     }
312 
getCurrentDicePolicy(&self) -> binder::Result<Vec<u8>>313     fn getCurrentDicePolicy(&self) -> binder::Result<Vec<u8>> {
314         Ok(VersionContext::new_current_encrypted(self.uuid.clone())?)
315     }
316 
keyTokenImport( &self, key_token: &OpaqueKeyToken, sealing_dice_policy: &[u8], ) -> binder::Result<binder::Strong<dyn IOpaqueKey>>317     fn keyTokenImport(
318         &self,
319         key_token: &OpaqueKeyToken,
320         sealing_dice_policy: &[u8],
321     ) -> binder::Result<binder::Strong<dyn IOpaqueKey>> {
322         // We derive a normal DICE bound key. This will check that the policy matches
323         // our DICE chain.
324         let DiceBoundKeyResult { diceBoundKey: key, dicePolicyWasCurrent: _ } = self
325             .deriveDicePolicyBoundKey(
326                 &DiceBoundDerivationKey::KeyId(DeviceKeyId::DEVICE_BOUND_KEY),
327                 sealing_dice_policy,
328             )?;
329         let key = key.ok_or(binder::Status::new_exception_str(
330             binder::ExceptionCode::UNSUPPORTED_OPERATION,
331             Some("shouldn't happen, previous operation succeeded"),
332         ))?;
333         let sealing_key: OpaqueKey = (&key).try_into().map_err(|_| {
334             binder::Status::new_exception_str(
335                 binder::ExceptionCode::UNSUPPORTED_OPERATION,
336                 Some("shouldn't happen, opaque key was local"),
337             )
338         })?;
339 
340         Ok(opaque_key::OpaqueKey::import_token(
341             key_token.keyToken.as_slice(),
342             sealing_key,
343             self.uuid.clone(),
344         )?
345         .into())
346     }
347 
deriveKey(&self, parameters: &DerivedKeyParameters) -> binder::Result<DerivedKey>348     fn deriveKey(&self, parameters: &DerivedKeyParameters) -> binder::Result<DerivedKey> {
349         if let DerivedKeyPolicy::ClearKey(policy) = &parameters.keyPolicy {
350             if policy.keySizeBytes <= 0 {
351                 return Err(binder::Status::new_exception_str(
352                     binder::ExceptionCode::UNSUPPORTED_OPERATION,
353                     Some("we do not support keys of length less or equal to 0"),
354                 ));
355             }
356         }
357 
358         let derivation_key: OpaqueKey = parameters
359             .derivationKey
360             .as_ref()
361             .ok_or(binder::Status::new_exception_str(
362                 binder::ExceptionCode::UNSUPPORTED_OPERATION,
363                 Some("didn't receive a derivation key"),
364             ))?
365             .try_into()?;
366 
367         match &parameters.keyPolicy {
368             DerivedKeyPolicy::ClearKey(clear_policy) => {
369                 // Adding key size to the context as well for a similar reason as to add the key
370                 // policy to the context.
371                 let key_size = clear_policy.keySizeBytes.try_into().map_err(|_| {
372                     binder::Status::new_exception_str(
373                         binder::ExceptionCode::UNSUPPORTED_OPERATION,
374                         Some("shouldn't happen, we checked that keySize was positive"),
375                     )
376                 })?;
377 
378                 let derived_key = derivation_key
379                     .derive_clear_key_material(parameters.context.as_slice(), key_size)?;
380                 Ok(DerivedKey::ExplicitKey(derived_key))
381             }
382             DerivedKeyPolicy::OpaqueKey(key_policy) => {
383                 let derived_key = derivation_key.derive_opaque_key(
384                     key_policy,
385                     parameters.context.as_slice(),
386                     self.uuid.clone(),
387                 )?;
388                 Ok(DerivedKey::Opaque(Some(derived_key)))
389             }
390         }
391     }
392 
getHwCryptoOperations(&self) -> binder::Result<binder::Strong<dyn IHwCryptoOperations>>393     fn getHwCryptoOperations(&self) -> binder::Result<binder::Strong<dyn IHwCryptoOperations>> {
394         Ok(HwCryptoOperations::new_binder())
395     }
396 
importClearKey( &self, key_to_be_imported: &ExplicitKeyMaterial, new_key_policy: &KeyPolicy, ) -> binder::Result<binder::Strong<dyn IOpaqueKey>>397     fn importClearKey(
398         &self,
399         key_to_be_imported: &ExplicitKeyMaterial,
400         new_key_policy: &KeyPolicy,
401     ) -> binder::Result<binder::Strong<dyn IOpaqueKey>> {
402         let key_material = helpers::aidl_explicit_key_to_rust_key_material(key_to_be_imported)?;
403         Ok(OpaqueKey::import_key_material(new_key_policy, key_material, self.uuid.clone())?)
404     }
405 
getKeyslotData(&self, keyslot: KeySlot) -> binder::Result<binder::Strong<dyn IOpaqueKey>>406     fn getKeyslotData(&self, keyslot: KeySlot) -> binder::Result<binder::Strong<dyn IOpaqueKey>> {
407         self.check_caller_can_access_keyslot(keyslot)?;
408         match keyslot {
409             KeySlot::KEYMINT_SHARED_HMAC_KEY => {
410                 let key_generator =
411                     EncryptionHeader::generate_with_version(0, EncryptedContent::KeyMaterial);
412                 let mock_hmac_key = key_generator.derive_raw_service_encryption_key(
413                     EncryptionHeaderKey::KeyGenerationContext(b"hmac_key_ctx"),
414                 )?;
415                 let policy = KeyPolicy {
416                     usage: KeyUse::SIGN,
417                     keyLifetime: KeyLifetime::HARDWARE,
418                     keyPermissions: Vec::new(),
419                     keyType: KeyType::HMAC_SHA256,
420                     keyManagementKey: false,
421                 };
422                 OpaqueKey::new_opaque_key_from_raw_bytes(&policy, mock_hmac_key, self.uuid.clone())
423             }
424             _ => Err(binder::Status::new_exception_str(
425                 binder::ExceptionCode::UNSUPPORTED_OPERATION,
426                 Some("Unknown key slot requested"),
427             )),
428         }
429     }
430 }
431 
432 #[cfg(test)]
433 mod tests {
434     use super::*;
435     use crate::hwcrypto_ipc_server::RUST_SERVICE_PORT;
436     use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::{
437         types::{
438             AesCipherMode::AesCipherMode, AesKey::AesKey,
439             CipherModeParameters::CipherModeParameters, HmacKey::HmacKey,
440             HmacOperationParameters::HmacOperationParameters, OperationData::OperationData,
441             SymmetricCryptoParameters::SymmetricCryptoParameters,
442             SymmetricOperation::SymmetricOperation,
443             SymmetricOperationParameters::SymmetricOperationParameters,
444         },
445         CryptoOperation::CryptoOperation,
446         CryptoOperationErrorAdditionalInfo::CryptoOperationErrorAdditionalInfo,
447         CryptoOperationSet::CryptoOperationSet,
448         IHwCryptoKey::ClearKeyPolicy::ClearKeyPolicy,
449         OperationParameters::OperationParameters,
450     };
451     use binder::Strong;
452     use rpcbinder::RpcSession;
453     use test::{assert_ok, expect, expect_eq};
454 
455     #[test]
import_clear_aes_key()456     fn import_clear_aes_key() {
457         let hw_key: Strong<dyn IHwCryptoKey> =
458             RpcSession::new().setup_trusty_client(RUST_SERVICE_PORT).expect("Failed to connect");
459         let hw_crypto = hw_key.getHwCryptoOperations().expect("couldn't get key crypto ops.");
460         let usage = KeyUse::ENCRYPT_DECRYPT;
461         let key_type = KeyType::AES_128_CBC_PKCS7_PADDING;
462         let policy = KeyPolicy {
463             usage,
464             keyLifetime: KeyLifetime::PORTABLE,
465             keyPermissions: Vec::new(),
466             keyType: key_type,
467             keyManagementKey: false,
468         };
469         let aes_key_material: ExplicitKeyMaterial =
470             ExplicitKeyMaterial::Aes(AesKey::Aes128([0; 16]));
471         let key = hw_key.importClearKey(&aes_key_material, &policy).expect("couldn't import key");
472         let nonce = [0u8; 16];
473         let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
474             nonce: nonce.into(),
475         }));
476         let direction = SymmetricOperation::ENCRYPT;
477         let sym_op_params =
478             SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
479         let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
480         let mut cmd_list = Vec::<CryptoOperation>::new();
481         let data_output = OperationData::DataBuffer(Vec::new());
482         cmd_list.push(CryptoOperation::DataOutput(data_output));
483         cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
484         let input_data = OperationData::DataBuffer("string to be encrypted".as_bytes().to_vec());
485         cmd_list.push(CryptoOperation::DataInput(input_data));
486         cmd_list.push(CryptoOperation::Finish(None));
487         let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
488         let mut crypto_sets = Vec::new();
489         crypto_sets.push(crypto_op_set);
490         let mut additional_error_info =
491             CryptoOperationErrorAdditionalInfo { failingCommandIndex: 0 };
492         hw_crypto
493             .processCommandList(&mut crypto_sets, &mut additional_error_info)
494             .expect("couldn't process commands");
495         // Extracting the vector from the command list because of ownership
496         let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) =
497             crypto_sets.remove(0).operations.remove(0)
498         else {
499             panic!("not reachable, we created this object above on the test");
500         };
501 
502         //// Decrypting
503         let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
504             nonce: nonce.into(),
505         }));
506         let direction = SymmetricOperation::DECRYPT;
507         let sym_op_params = SymmetricOperationParameters { key: Some(key), direction, parameters };
508         let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
509         let mut cmd_list = Vec::<CryptoOperation>::new();
510         let data_output = OperationData::DataBuffer(Vec::new());
511         cmd_list.push(CryptoOperation::DataOutput(data_output));
512         cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
513         cmd_list.push(CryptoOperation::DataInput(OperationData::DataBuffer(encrypted_data)));
514         cmd_list.push(CryptoOperation::Finish(None));
515         let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
516         let mut crypto_sets = Vec::new();
517         crypto_sets.push(crypto_op_set);
518         hw_crypto
519             .processCommandList(&mut crypto_sets, &mut additional_error_info)
520             .expect("couldn't process commands");
521         // Extracting the vector from the command list because of ownership
522         let CryptoOperation::DataOutput(OperationData::DataBuffer(decrypted_data)) =
523             crypto_sets.remove(0).operations.remove(0)
524         else {
525             panic!("not reachable, we created this object above on the test");
526         };
527         let decrypted_msg =
528             String::from_utf8(decrypted_data).expect("couldn't decode received message");
529         expect_eq!(decrypted_msg, "string to be encrypted", "couldn't retrieve original message");
530     }
531 
532     #[test]
import_clear_hmac_key()533     fn import_clear_hmac_key() {
534         let hw_key: Strong<dyn IHwCryptoKey> =
535             RpcSession::new().setup_trusty_client(RUST_SERVICE_PORT).expect("Failed to connect");
536         let hw_crypto = hw_key.getHwCryptoOperations().expect("couldn't get key crypto ops.");
537         let usage = KeyUse::SIGN;
538         let key_type = KeyType::HMAC_SHA256;
539         let policy = KeyPolicy {
540             usage,
541             keyLifetime: KeyLifetime::PORTABLE,
542             keyPermissions: Vec::new(),
543             keyType: key_type,
544             keyManagementKey: false,
545         };
546         let aes_key_material: ExplicitKeyMaterial = ExplicitKeyMaterial::Hmac(HmacKey::Sha256([
547             10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
548             10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
549         ]));
550         let key = hw_key.importClearKey(&aes_key_material, &policy).expect("couldn't import key");
551         let hmac_parameters = HmacOperationParameters { key: Some(key) };
552         let op_parameters = OperationParameters::Hmac(hmac_parameters);
553         let mut cmd_list = Vec::<CryptoOperation>::new();
554         let data_output = OperationData::DataBuffer(Vec::new());
555         cmd_list.push(CryptoOperation::DataOutput(data_output));
556         cmd_list.push(CryptoOperation::SetOperationParameters(op_parameters));
557         let input_data = OperationData::DataBuffer(b"test data".to_vec());
558         cmd_list.push(CryptoOperation::DataInput(input_data));
559         cmd_list.push(CryptoOperation::Finish(None));
560         let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
561         let mut crypto_sets = Vec::new();
562         crypto_sets.push(crypto_op_set);
563         let mut additional_error_info =
564             CryptoOperationErrorAdditionalInfo { failingCommandIndex: 0 };
565         hw_crypto
566             .processCommandList(&mut crypto_sets, &mut additional_error_info)
567             .expect("couldn't process commands");
568         // Extracting the vector from the command list because of ownership
569         let CryptoOperation::DataOutput(OperationData::DataBuffer(mac)) =
570             crypto_sets.remove(0).operations.remove(0)
571         else {
572             panic!("not reachable, we created this object above on the test");
573         };
574         let expected_response = [
575             0x1d, 0x07, 0xd7, 0x52, 0xc2, 0x1a, 0x46, 0x73, 0xd8, 0x0b, 0xc4, 0x9b, 0xc8, 0x27,
576             0xbb, 0x9d, 0x9b, 0x36, 0xe8, 0xfc, 0xec, 0xc1, 0x97, 0x21, 0xb2, 0x83, 0x57, 0x4a,
577             0x18, 0x95, 0x5d, 0xfc,
578         ];
579         expect_eq!(mac, expected_response, "Didn't get back expected mac");
580     }
581 
582     #[test]
derived_dice_bound_keys()583     fn derived_dice_bound_keys() {
584         let hw_device_key = HwCryptoKey::new_binder(
585             Uuid::new_from_string("f41a7796-975a-4279-8cc4-b73f8820430d").unwrap(),
586         );
587 
588         let derivation_key = DiceBoundDerivationKey::KeyId(DeviceKeyId::DEVICE_BOUND_KEY);
589         let key_and_policy =
590             assert_ok!(hw_device_key.deriveCurrentDicePolicyBoundKey(&derivation_key));
591         let DiceCurrentBoundKeyResult { diceBoundKey: key, dicePolicyForKeyVersion: policy } =
592             key_and_policy;
593         expect!(key.is_some(), "should have received a key");
594         expect!(policy.len() > 0, "should have received a DICE policy");
595         let key_and_policy =
596             assert_ok!(hw_device_key.deriveDicePolicyBoundKey(&derivation_key, &policy));
597         let DiceBoundKeyResult { diceBoundKey: key, dicePolicyWasCurrent: current_policy } =
598             key_and_policy;
599         expect!(key.is_some(), "should have received a key");
600         expect!(current_policy, "policy should have been current");
601 
602         let derivation_key = DiceBoundDerivationKey::KeyId(DeviceKeyId::DEVICE_BOUND_KEY);
603         let key_and_policy =
604             assert_ok!(hw_device_key.deriveCurrentDicePolicyBoundKey(&derivation_key));
605         let DiceCurrentBoundKeyResult { diceBoundKey: key, dicePolicyForKeyVersion: policy } =
606             key_and_policy;
607         expect!(key.is_some(), "should have received a key");
608         expect!(policy.len() > 0, "should have received a DICE policy");
609         let key_and_policy =
610             assert_ok!(hw_device_key.deriveDicePolicyBoundKey(&derivation_key, &policy));
611         let DiceBoundKeyResult { diceBoundKey: key, dicePolicyWasCurrent: current_policy } =
612             key_and_policy;
613         expect!(key.is_some(), "should have received a key");
614         expect!(current_policy, "policy should have been current");
615     }
616 
617     #[test]
derived_clear_key()618     fn derived_clear_key() {
619         let hw_device_key = HwCryptoKey::new_binder(
620             Uuid::new_from_string("f41a7796-975a-4279-8cc4-b73f8820430d").unwrap(),
621         );
622 
623         let derivation_key = DiceBoundDerivationKey::KeyId(DeviceKeyId::DEVICE_BOUND_KEY);
624         let key_and_policy =
625             assert_ok!(hw_device_key.deriveCurrentDicePolicyBoundKey(&derivation_key));
626         let DiceCurrentBoundKeyResult { diceBoundKey: key, dicePolicyForKeyVersion: policy } =
627             key_and_policy;
628         expect!(key.is_some(), "should have received a key");
629         expect!(policy.len() > 0, "should have received a DICE policy");
630 
631         let clear_key_policy = DerivedKeyPolicy::ClearKey(ClearKeyPolicy { keySizeBytes: 0 });
632         let mut params = DerivedKeyParameters {
633             derivationKey: key,
634             keyPolicy: clear_key_policy,
635             context: "context".as_bytes().to_vec(),
636         };
637         let key = hw_device_key.deriveKey(&params);
638         expect!(key.is_err(), "shouldn't be able to create a key of length 0");
639 
640         let clear_key_policy = DerivedKeyPolicy::ClearKey(ClearKeyPolicy { keySizeBytes: 32 });
641         params.keyPolicy = clear_key_policy;
642         let derived_key = assert_ok!(hw_device_key.deriveKey(&params));
643         let key1 = match derived_key {
644             DerivedKey::ExplicitKey(key) => key,
645             DerivedKey::Opaque(_) => panic!("wrong type of key received"),
646         };
647 
648         let key_and_policy =
649             assert_ok!(hw_device_key.deriveDicePolicyBoundKey(&derivation_key, &policy));
650         let DiceBoundKeyResult { diceBoundKey: key, dicePolicyWasCurrent: current_policy } =
651             key_and_policy;
652         expect!(key.is_some(), "should have received a key");
653         expect!(current_policy, "policy should have been current");
654         params.derivationKey = key;
655         let derived_key = assert_ok!(hw_device_key.deriveKey(&params));
656         let key2 = match derived_key {
657             DerivedKey::ExplicitKey(key) => key,
658             DerivedKey::Opaque(_) => panic!("wrong type of key received"),
659         };
660         expect!(openssl::memcmp::eq(&key1, &key2), "keys should have matched");
661 
662         params.context = "cont3xt".as_bytes().to_vec();
663         let derived_key = assert_ok!(hw_device_key.deriveKey(&params));
664         let key3 = match derived_key {
665             DerivedKey::ExplicitKey(key) => key,
666             DerivedKey::Opaque(_) => panic!("wrong type of key received"),
667         };
668         expect!(!openssl::memcmp::eq(&key1, &key3), "keys shouldn't have matched");
669     }
670 
671     #[test]
create_key_tokens()672     fn create_key_tokens() {
673         let hw_key: Strong<dyn IHwCryptoKey> =
674             RpcSession::new().setup_trusty_client(RUST_SERVICE_PORT).expect("Failed to connect");
675         let hw_crypto = hw_key.getHwCryptoOperations().expect("couldn't get key crypto ops.");
676         let usage = KeyUse::ENCRYPT_DECRYPT;
677         let key_type = KeyType::AES_128_CBC_PKCS7_PADDING;
678         let policy = KeyPolicy {
679             usage,
680             keyLifetime: KeyLifetime::PORTABLE,
681             keyPermissions: Vec::new(),
682             keyType: key_type,
683             keyManagementKey: false,
684         };
685         let aes_key_material: ExplicitKeyMaterial =
686             ExplicitKeyMaterial::Aes(AesKey::Aes128([0; 16]));
687         let key = hw_key.importClearKey(&aes_key_material, &policy).expect("couldn't import key");
688 
689         let sealing_dice_policy =
690             hw_key.getCurrentDicePolicy().expect("couldn't get sealing policy");
691 
692         let token = key.getShareableToken(&sealing_dice_policy);
693         expect!(token.is_ok(), "couldn't get shareadble token");
694         let token = token.unwrap();
695 
696         let nonce = [0u8; 16];
697         let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
698             nonce: nonce.into(),
699         }));
700         let direction = SymmetricOperation::ENCRYPT;
701         let sym_op_params = SymmetricOperationParameters { key: Some(key), direction, parameters };
702         let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
703         let mut cmd_list = Vec::<CryptoOperation>::new();
704         let data_output = OperationData::DataBuffer(Vec::new());
705         cmd_list.push(CryptoOperation::DataOutput(data_output));
706         cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
707         let input_data = OperationData::DataBuffer("string to be encrypted".as_bytes().to_vec());
708         cmd_list.push(CryptoOperation::DataInput(input_data));
709         cmd_list.push(CryptoOperation::Finish(None));
710         let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
711         let mut crypto_sets = Vec::new();
712         crypto_sets.push(crypto_op_set);
713         let mut additional_error_info =
714             CryptoOperationErrorAdditionalInfo { failingCommandIndex: 0 };
715         hw_crypto
716             .processCommandList(&mut crypto_sets, &mut additional_error_info)
717             .expect("couldn't process commands");
718         // Extracting the vector from the command list because of ownership
719         let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) =
720             crypto_sets.remove(0).operations.remove(0)
721         else {
722             panic!("not reachable, we created this object above on the test");
723         };
724 
725         let hw_key: Strong<dyn IHwCryptoKey> =
726             RpcSession::new().setup_trusty_client(RUST_SERVICE_PORT).expect("Failed to connect");
727         let hw_crypto = hw_key.getHwCryptoOperations().expect("couldn't get key crypto ops.");
728         let key = hw_key.keyTokenImport(&token, &sealing_dice_policy);
729         expect!(key.is_ok(), "couldn't import shareable token");
730         let key = key.unwrap();
731 
732         //// Decrypting
733         let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
734             nonce: nonce.into(),
735         }));
736         let direction = SymmetricOperation::DECRYPT;
737         let sym_op_params = SymmetricOperationParameters { key: Some(key), direction, parameters };
738         let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
739         let mut cmd_list = Vec::<CryptoOperation>::new();
740         let data_output = OperationData::DataBuffer(Vec::new());
741         cmd_list.push(CryptoOperation::DataOutput(data_output));
742         cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
743         cmd_list.push(CryptoOperation::DataInput(OperationData::DataBuffer(encrypted_data)));
744         cmd_list.push(CryptoOperation::Finish(None));
745         let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
746         let mut crypto_sets = Vec::new();
747         crypto_sets.push(crypto_op_set);
748         hw_crypto
749             .processCommandList(&mut crypto_sets, &mut additional_error_info)
750             .expect("couldn't process commands");
751         // Extracting the vector from the command list because of ownership
752         let CryptoOperation::DataOutput(OperationData::DataBuffer(decrypted_data)) =
753             crypto_sets.remove(0).operations.remove(0)
754         else {
755             panic!("not reachable, we created this object above on the test");
756         };
757         let decrypted_msg =
758             String::from_utf8(decrypted_data).expect("couldn't decode received message");
759         expect_eq!(decrypted_msg, "string to be encrypted", "couldn't retrieve original message");
760     }
761 
762     #[test]
key_token_import_wrong_policy()763     fn key_token_import_wrong_policy() {
764         let hw_key: Strong<dyn IHwCryptoKey> =
765             RpcSession::new().setup_trusty_client(RUST_SERVICE_PORT).expect("Failed to connect");
766 
767         let aes_key_material: ExplicitKeyMaterial =
768             ExplicitKeyMaterial::Aes(AesKey::Aes128([0; 16]));
769         let usage = KeyUse::ENCRYPT_DECRYPT;
770         let key_type = KeyType::AES_128_CBC_PKCS7_PADDING;
771         let policy = KeyPolicy {
772             usage,
773             keyLifetime: KeyLifetime::PORTABLE,
774             keyPermissions: Vec::new(),
775             keyType: key_type,
776             keyManagementKey: false,
777         };
778         let key = hw_key.importClearKey(&aes_key_material, &policy).expect("couldn't import key");
779 
780         let sealing_dice_policy =
781             hw_key.getCurrentDicePolicy().expect("couldn't get sealing policy");
782 
783         let token = key.getShareableToken(&sealing_dice_policy);
784         expect!(token.is_ok(), "couldn't get shareadble token");
785         let token = token.unwrap();
786 
787         let bad_dice_policy = VersionContext::new_current_encrypted(
788             Uuid::new_from_string("f41a7796-975a-427a-8cc4-a73f8820430d").unwrap(),
789         )
790         .expect("couldn't create DICE policy");
791 
792         let key = hw_key.keyTokenImport(&token, &bad_dice_policy);
793         expect!(key.is_err(), "shouldn't be able to import key using the wrong DICE policy");
794     }
795 
796     #[test]
get_keyslot()797     fn get_keyslot() {
798         let hw_key: Strong<dyn IHwCryptoKey> =
799             RpcSession::new().setup_trusty_client(RUST_SERVICE_PORT).expect("Failed to connect");
800 
801         let key = hw_key.getKeyslotData(KeySlot::KEYMINT_SHARED_HMAC_KEY);
802         expect!(key.is_ok(), "couldn't get key");
803     }
804 
805     #[test]
get_keyslot_form_unautorized_caller()806     fn get_keyslot_form_unautorized_caller() {
807         let hw_key = HwCryptoKey::new_binder(
808             Uuid::new_from_string("00000000-0000-0000-0000-000000000000")
809                 .expect("couldn't create uuid"),
810         );
811         let key = hw_key.getKeyslotData(KeySlot::KEYMINT_SHARED_HMAC_KEY);
812         expect!(key.is_err(), "shouldn't be able to get key");
813     }
814 }
815