1 /* 2 * Copyright (C) 2023 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 #[cfg(test)] 18 mod tests { 19 use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::{ 20 types::{ 21 AesCipherMode::AesCipherMode, CipherModeParameters::CipherModeParameters, 22 KeyLifetime::KeyLifetime, KeyType::KeyType, KeyUse::KeyUse, 23 OperationData::OperationData, SymmetricCryptoParameters::SymmetricCryptoParameters, 24 SymmetricOperation::SymmetricOperation, 25 SymmetricOperationParameters::SymmetricOperationParameters, 26 }, 27 CryptoOperation::CryptoOperation, 28 CryptoOperationErrorAdditionalInfo::CryptoOperationErrorAdditionalInfo, 29 CryptoOperationSet::CryptoOperationSet, 30 IHwCryptoKey::{ 31 DerivedKey::DerivedKey, DerivedKeyParameters::DerivedKeyParameters, 32 DerivedKeyPolicy::DerivedKeyPolicy, DeviceKeyId::DeviceKeyId, 33 DiceBoundDerivationKey::DiceBoundDerivationKey, DiceBoundKeyResult::DiceBoundKeyResult, 34 DiceCurrentBoundKeyResult::DiceCurrentBoundKeyResult, IHwCryptoKey, 35 }, 36 IHwCryptoOperations::IHwCryptoOperations, 37 IOpaqueKey::IOpaqueKey, 38 KeyPolicy::KeyPolicy, 39 OperationParameters::OperationParameters, 40 }; 41 use binder::{Status, StatusCode, Strong}; 42 use rpcbinder::RpcSession; 43 use test::{assert_ok, expect}; 44 use trusty_std::ffi::{CString, FallibleCString}; 45 46 pub(crate) const RUST_DEVICE_KEY_SERVICE_PORT: &str = "com.android.trusty.rust.hwcryptohal.V1"; 47 48 pub(crate) const VERSION_0_DICE_POLICY: [u8; 126] = [ 49 0x83, 0x58, 0x36, 0xa4, 0x01, 0x03, 0x3a, 0x00, 0x01, 0x00, 0x02, 0x58, 0x20, 0x55, 0x51, 50 0xba, 0x39, 0x55, 0xfa, 0x6f, 0x92, 0xbb, 0xf9, 0xed, 0xe1, 0xc0, 0x91, 0x3f, 0x2b, 0xbf, 51 0xb5, 0xb3, 0x93, 0x8a, 0x08, 0x5f, 0x78, 0xa8, 0x00, 0xa2, 0xce, 0x09, 0x99, 0xa9, 0x5e, 52 0x3a, 0x00, 0x01, 0x00, 0x03, 0x01, 0x3a, 0x00, 0x01, 0x00, 0x04, 0x01, 0xa0, 0x58, 0x42, 53 0xda, 0x4f, 0xef, 0x97, 0xf4, 0x19, 0x90, 0xf3, 0x06, 0x1f, 0x06, 0xfe, 0x4d, 0xcb, 0x89, 54 0xcf, 0x6a, 0xa1, 0xd1, 0xf5, 0x34, 0x68, 0x47, 0x17, 0x2d, 0xa2, 0x0e, 0xec, 0xc1, 0xcb, 55 0xac, 0xa4, 0xe1, 0x36, 0x51, 0x88, 0xdb, 0x2e, 0x1c, 0x06, 0xeb, 0xe8, 0x0c, 0xde, 0x56, 56 0xc7, 0xed, 0x17, 0x03, 0x2a, 0x9c, 0x4e, 0x52, 0x65, 0xd6, 0x4e, 0xfb, 0xea, 0xf0, 0x9d, 57 0x49, 0x70, 0x3f, 0x37, 0xf3, 0x33, 58 ]; 59 60 pub(crate) const ENCRYPTION_PAYLOAD: &str = "string to be encrypted"; 61 62 pub(crate) const VERSION_0_ENCRYPTION_KNOWN_VALUE: [u8; 32] = [ 63 0x68, 0xb6, 0xf7, 0xd8, 0x05, 0x91, 0x59, 0x42, 0x2c, 0xd1, 0x07, 0xd7, 0x81, 0xbf, 0xd0, 64 0x31, 0xeb, 0x39, 0x11, 0x68, 0xfc, 0xfb, 0x90, 0xd7, 0x82, 0x04, 0xeb, 0x98, 0x44, 0x4d, 65 0xcf, 0x0a, 66 ]; 67 connect() -> Result<Strong<dyn IHwCryptoKey>, StatusCode>68 fn connect() -> Result<Strong<dyn IHwCryptoKey>, StatusCode> { 69 let port = 70 CString::try_new(RUST_DEVICE_KEY_SERVICE_PORT).expect("Failed to allocate port name"); 71 RpcSession::new().setup_trusty_client(port.as_c_str()) 72 } 73 do_cipher( hw_crypto: &dyn IHwCryptoOperations, key: Strong<dyn IOpaqueKey>, direction: SymmetricOperation, payload: Vec<u8>, ) -> Result<Vec<u8>, Status>74 fn do_cipher( 75 hw_crypto: &dyn IHwCryptoOperations, 76 key: Strong<dyn IOpaqueKey>, 77 direction: SymmetricOperation, 78 payload: Vec<u8>, 79 ) -> Result<Vec<u8>, Status> { 80 let nonce = [0u8; 16]; 81 let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters { 82 nonce: nonce.into(), 83 })); 84 85 let sym_op_params = SymmetricOperationParameters { key: Some(key), direction, parameters }; 86 let op_params = OperationParameters::SymmetricCrypto(sym_op_params); 87 88 let mut cmd_list = Vec::<CryptoOperation>::new(); 89 let data_output = OperationData::DataBuffer(Vec::new()); 90 cmd_list.push(CryptoOperation::DataOutput(data_output)); 91 cmd_list.push(CryptoOperation::SetOperationParameters(op_params)); 92 let input_data = OperationData::DataBuffer(payload); 93 cmd_list.push(CryptoOperation::DataInput(input_data)); 94 cmd_list.push(CryptoOperation::Finish(None)); 95 96 let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list }; 97 let mut crypto_sets = Vec::new(); 98 crypto_sets.push(crypto_op_set); 99 100 let mut additional_error_info = 101 CryptoOperationErrorAdditionalInfo { failingCommandIndex: 0 }; 102 let result = hw_crypto.processCommandList(&mut crypto_sets, &mut additional_error_info); 103 match result { 104 Ok(..) => {} 105 Err(e) => return Err(e), 106 } 107 108 let CryptoOperation::DataOutput(OperationData::DataBuffer(result)) = 109 crypto_sets.remove(0).operations.remove(0) 110 else { 111 panic!("not reachable, we created this object above on the test"); 112 }; 113 114 Ok(result) 115 } 116 encrypt( hw_crypto: &dyn IHwCryptoOperations, key: Strong<dyn IOpaqueKey>, payload: Vec<u8>, ) -> Result<Vec<u8>, Status>117 fn encrypt( 118 hw_crypto: &dyn IHwCryptoOperations, 119 key: Strong<dyn IOpaqueKey>, 120 payload: Vec<u8>, 121 ) -> Result<Vec<u8>, Status> { 122 do_cipher(hw_crypto, key, SymmetricOperation::ENCRYPT, payload) 123 } 124 decrypt( hw_crypto: &dyn IHwCryptoOperations, key: Strong<dyn IOpaqueKey>, payload: Vec<u8>, ) -> Result<Vec<u8>, Status>125 fn decrypt( 126 hw_crypto: &dyn IHwCryptoOperations, 127 key: Strong<dyn IOpaqueKey>, 128 payload: Vec<u8>, 129 ) -> Result<Vec<u8>, Status> { 130 do_cipher(hw_crypto, key, SymmetricOperation::DECRYPT, payload) 131 } 132 133 #[test] generate_new_policy_and_opaque_key()134 fn generate_new_policy_and_opaque_key() { 135 let hw_device_key = connect().expect("couldn't connect to HW Crypto service"); 136 let hw_crypto = 137 hw_device_key.getHwCryptoOperations().expect("couldn't get key crypto ops."); 138 139 // Get the device bound key 140 let device_bound_key = DiceBoundDerivationKey::KeyId(DeviceKeyId::DEVICE_BOUND_KEY); 141 142 // Generate the current derivation key and policy 143 let key_and_policy = 144 assert_ok!(hw_device_key.deriveCurrentDicePolicyBoundKey(&device_bound_key)); 145 let DiceCurrentBoundKeyResult { 146 diceBoundKey: derivation_key1, 147 dicePolicyForKeyVersion: dice_policy, 148 } = key_and_policy; 149 150 expect!(derivation_key1.is_some(), "should have received a key"); 151 expect!(dice_policy.len() > 0, "should have received a DICE policy"); 152 153 // Derive an opaque key from returned current policy and derivation key 154 let policy = KeyPolicy { 155 usage: KeyUse::ENCRYPT_DECRYPT, 156 keyLifetime: KeyLifetime::HARDWARE, 157 keyPermissions: Vec::new(), 158 keyType: KeyType::AES_256_CBC_PKCS7_PADDING, 159 keyManagementKey: false, 160 }; 161 162 let cbor_policy = hwcryptohal_common::policy::cbor_serialize_key_policy(&policy) 163 .expect("couldn't serialize policy"); 164 let key_policy = DerivedKeyPolicy::OpaqueKey(cbor_policy); 165 166 let mut params = DerivedKeyParameters { 167 derivationKey: derivation_key1, 168 keyPolicy: key_policy, 169 context: "context".as_bytes().to_vec(), 170 }; 171 172 let derived_key1 = assert_ok!(hw_device_key.deriveKey(¶ms)); 173 174 // Check key type 175 let derived_key1 = match derived_key1 { 176 DerivedKey::Opaque(k) => k, 177 DerivedKey::ExplicitKey(_) => panic!("wrong type of key received"), 178 }; 179 180 let derived_key1 = derived_key1.expect("key is missing"); 181 182 // Baseline encryption operations 183 let clear_payload = ENCRYPTION_PAYLOAD.as_bytes().to_vec(); 184 185 let encrypted_data = 186 encrypt(hw_crypto.as_ref(), derived_key1.clone(), clear_payload.clone()) 187 .expect("encryption failure"); 188 let clear_data = decrypt(hw_crypto.as_ref(), derived_key1.clone(), encrypted_data.clone()) 189 .expect("decryption failure"); 190 191 assert_eq!(clear_payload, clear_data, "decrypted data mismatch"); 192 193 // Use dice policy to request same derivation key 194 let key_and_policy = 195 assert_ok!(hw_device_key.deriveDicePolicyBoundKey(&device_bound_key, &dice_policy)); 196 let DiceBoundKeyResult { 197 diceBoundKey: derivation_key2, 198 dicePolicyWasCurrent: dice_policy_current, 199 } = key_and_policy; 200 201 expect!(derivation_key2.is_some(), "should have received a key"); 202 expect!(dice_policy_current, "policy should have been current"); 203 204 // Generate derived key 2 205 params.derivationKey = derivation_key2; 206 207 let derived_key2 = assert_ok!(hw_device_key.deriveKey(¶ms)); 208 209 // Check key type 210 let derived_key2 = match derived_key2 { 211 DerivedKey::Opaque(k) => k, 212 DerivedKey::ExplicitKey(_) => panic!("wrong type of key received"), 213 }; 214 215 let derived_key2 = derived_key2.expect("key is missing"); 216 217 let clear_data2 = decrypt(hw_crypto.as_ref(), derived_key2.clone(), encrypted_data.clone()) 218 .expect("decryption failure"); 219 assert_eq!(clear_payload, clear_data2, "decrypted data mismatch"); 220 221 // If we request current dice policy again, we expect the same key, but different 222 // encryption of the returned policy. Note underlying policy is the same (latest), 223 // but encrypted byte array returned will be different 224 225 // Generate the current derivation key and policy again 226 let key_and_policy = 227 assert_ok!(hw_device_key.deriveCurrentDicePolicyBoundKey(&device_bound_key)); 228 let DiceCurrentBoundKeyResult { 229 diceBoundKey: derivation_key3, 230 dicePolicyForKeyVersion: dice_policy3, 231 } = key_and_policy; 232 233 // We expect the dice policy to appear different due to encruption 234 assert_ne!( 235 dice_policy, dice_policy3, 236 "expected dice policies to appear different due to encryption" 237 ); 238 239 // Ensure derived key from this policy matches previously generated derived key 240 params.derivationKey = derivation_key3; 241 242 let derived_key3 = assert_ok!(hw_device_key.deriveKey(¶ms)); 243 244 // Check key type 245 let derived_key3 = match derived_key3 { 246 DerivedKey::Opaque(k) => k, 247 DerivedKey::ExplicitKey(_) => panic!("wrong type of key received"), 248 }; 249 250 let derived_key3 = derived_key3.expect("key is missing"); 251 252 // Try encrypting same clear_payload and verify encrypted result is same 253 let encrypted_data3 = 254 encrypt(hw_crypto.as_ref(), derived_key3.clone(), clear_payload.clone()) 255 .expect("encryption failure"); 256 assert_eq!(encrypted_data3, encrypted_data, "unexpected encrypted data mismatch"); 257 258 // try using key to decrypt earlier encryption result 259 let clear_data3 = decrypt(hw_crypto.as_ref(), derived_key3.clone(), encrypted_data.clone()) 260 .expect("decryption failure"); 261 assert_eq!(clear_data3, clear_payload, "unexpected data mismatch"); 262 } 263 264 #[test] old_dice_policy_generates_old_opaque_key_and_new_policy()265 fn old_dice_policy_generates_old_opaque_key_and_new_policy() { 266 let hw_device_key = connect().expect("couldn't connect to HW Crypto service"); 267 let hw_crypto = 268 hw_device_key.getHwCryptoOperations().expect("couldn't get key crypto ops."); 269 270 // Get the device bound key 271 let device_bound_key = DiceBoundDerivationKey::KeyId(DeviceKeyId::DEVICE_BOUND_KEY); 272 273 // Generate a derived key from version 0 dice policy 274 let key_and_policy = assert_ok!( 275 hw_device_key.deriveDicePolicyBoundKey(&device_bound_key, &VERSION_0_DICE_POLICY) 276 ); 277 let DiceBoundKeyResult { 278 diceBoundKey: derivation_key, 279 dicePolicyWasCurrent: dice_policy_current, 280 } = key_and_policy; 281 282 // We expect version 0 should not be current 283 expect!(!dice_policy_current, "policy not expected to be current"); 284 285 // Generate a key using version 0 dice policy 286 let policy = KeyPolicy { 287 usage: KeyUse::ENCRYPT_DECRYPT, 288 keyLifetime: KeyLifetime::HARDWARE, 289 keyPermissions: Vec::new(), 290 keyType: KeyType::AES_256_CBC_PKCS7_PADDING, 291 keyManagementKey: false, 292 }; 293 294 let cbor_policy = hwcryptohal_common::policy::cbor_serialize_key_policy(&policy) 295 .expect("couldn't serialize policy"); 296 let key_policy = DerivedKeyPolicy::OpaqueKey(cbor_policy); 297 298 let params = DerivedKeyParameters { 299 derivationKey: derivation_key, 300 keyPolicy: key_policy, 301 context: "context".as_bytes().to_vec(), 302 }; 303 304 let derived_key = assert_ok!(hw_device_key.deriveKey(¶ms)); 305 306 // Check key type 307 let derived_key = match derived_key { 308 DerivedKey::Opaque(k) => k, 309 DerivedKey::ExplicitKey(_) => panic!("wrong type of key received"), 310 }; 311 312 let derived_key = derived_key.expect("key is missing"); 313 314 let clear_payload = ENCRYPTION_PAYLOAD.as_bytes().to_vec(); 315 let encrypted_data = 316 encrypt(hw_crypto.as_ref(), derived_key.clone(), clear_payload.clone()) 317 .expect("encryption failure"); 318 319 // Check we got the old key and encryption results match expected for version 0 dice policy 320 assert_eq!( 321 encrypted_data, 322 VERSION_0_ENCRYPTION_KNOWN_VALUE.to_vec(), 323 "Unexpected encryption result" 324 ); 325 } 326 327 #[test] opaque_keys_unique_by_context()328 fn opaque_keys_unique_by_context() { 329 let hw_device_key = connect().expect("couldn't connect to HW Crypto service"); 330 let hw_crypto = 331 hw_device_key.getHwCryptoOperations().expect("couldn't get key crypto ops."); 332 333 // Get the device bound key 334 let device_bound_key = DiceBoundDerivationKey::KeyId(DeviceKeyId::DEVICE_BOUND_KEY); 335 336 // Generate the current derivation key and policy 337 let key_and_policy = 338 assert_ok!(hw_device_key.deriveCurrentDicePolicyBoundKey(&device_bound_key)); 339 let DiceCurrentBoundKeyResult { 340 diceBoundKey: derivation_key, 341 dicePolicyForKeyVersion: dice_policy, 342 } = key_and_policy; 343 344 expect!(derivation_key.is_some(), "should have received a key"); 345 expect!(dice_policy.len() > 0, "should have received a DICE policy"); 346 347 let context1 = "context1"; 348 let context2 = "context2"; 349 350 // Get derived key for context1 351 let policy1 = KeyPolicy { 352 usage: KeyUse::ENCRYPT_DECRYPT, 353 keyLifetime: KeyLifetime::HARDWARE, 354 keyPermissions: Vec::new(), 355 keyType: KeyType::AES_256_CBC_PKCS7_PADDING, 356 keyManagementKey: false, 357 }; 358 359 let cbor_policy1 = hwcryptohal_common::policy::cbor_serialize_key_policy(&policy1) 360 .expect("couldn't serialize policy"); 361 let key_policy1 = DerivedKeyPolicy::OpaqueKey(cbor_policy1); 362 363 let params1 = DerivedKeyParameters { 364 derivationKey: derivation_key.clone(), 365 keyPolicy: key_policy1, 366 context: context1.as_bytes().to_vec(), 367 }; 368 369 let derived_key1 = assert_ok!(hw_device_key.deriveKey(¶ms1)); 370 371 // Check key type 372 let derived_key1 = match derived_key1 { 373 DerivedKey::Opaque(k) => k, 374 DerivedKey::ExplicitKey(_) => panic!("wrong type of key received"), 375 }; 376 377 let derived_key1 = derived_key1.expect("key is missing"); 378 379 // Context1 encryption 380 let clear_payload = ENCRYPTION_PAYLOAD.as_bytes().to_vec(); 381 let encrypted_data1 = 382 encrypt(hw_crypto.as_ref(), derived_key1.clone(), clear_payload.clone()) 383 .expect("encryption failure"); 384 385 // Request key for context2 and verify key is different 386 let policy2 = KeyPolicy { 387 usage: KeyUse::ENCRYPT_DECRYPT, 388 keyLifetime: KeyLifetime::HARDWARE, 389 keyPermissions: Vec::new(), 390 keyType: KeyType::AES_256_CBC_PKCS7_PADDING, 391 keyManagementKey: false, 392 }; 393 394 let cbor_policy2 = hwcryptohal_common::policy::cbor_serialize_key_policy(&policy2) 395 .expect("couldn't serialize policy"); 396 let key_policy2 = DerivedKeyPolicy::OpaqueKey(cbor_policy2); 397 398 let params2 = DerivedKeyParameters { 399 derivationKey: derivation_key.clone(), 400 keyPolicy: key_policy2, 401 context: context2.as_bytes().to_vec(), 402 }; 403 404 let derived_key2 = assert_ok!(hw_device_key.deriveKey(¶ms2)); 405 406 // Check key type 407 let derived_key2 = match derived_key2 { 408 DerivedKey::Opaque(k) => k, 409 DerivedKey::ExplicitKey(_) => panic!("wrong type of key received"), 410 }; 411 412 let derived_key2 = derived_key2.expect("key is missing"); 413 414 // Context2 encryption 415 let encrypted_data2 = 416 encrypt(hw_crypto.as_ref(), derived_key2.clone(), clear_payload.clone()) 417 .expect("encryption failure"); 418 419 // Verify encryption results are different 420 assert_ne!(encrypted_data2, encrypted_data1, "encrypted results should not match"); 421 } 422 } 423