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) = ¶meters.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 ¶meters.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(¶ms); 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(¶ms)); 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(¶ms)); 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(¶ms)); 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