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(&params));
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(&params));
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(&params));
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(&params));
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(&params1));
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(&params2));
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