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 use android_hardware_security_secretkeeper::aidl::android::hardware::security::secretkeeper::ISecretkeeper::ISecretkeeper;
18 use android_hardware_security_secretkeeper::aidl::android::hardware::security::secretkeeper::SecretId::SecretId;
19 use authgraph_vts_test as ag_vts;
20 use authgraph_boringssl as boring;
21 use authgraph_core::key;
22 use coset::{CborOrdering, CborSerializable, CoseEncrypt0, CoseKey};
23 use dice_policy_builder::{TargetEntry, ConstraintSpec, ConstraintType, MissingAction, WILDCARD_FULL_ARRAY, policy_for_dice_chain};
24 use rdroidtest::{ignore_if, rdroidtest};
25 use secretkeeper_client::dice::OwnedDiceArtifactsWithExplicitKey;
26 use secretkeeper_client::{SkSession, Error as SkClientError};
27 use secretkeeper_core::cipher;
28 use secretkeeper_comm::data_types::error::SecretkeeperError;
29 use secretkeeper_comm::data_types::request::Request;
30 use secretkeeper_comm::data_types::request_response_impl::{
31     GetVersionRequest, GetVersionResponse, GetSecretRequest, GetSecretResponse, StoreSecretRequest,
32     StoreSecretResponse };
33 use secretkeeper_comm::data_types::{Id, Secret, SeqNum};
34 use secretkeeper_comm::data_types::response::Response;
35 use secretkeeper_comm::data_types::packet::{ResponsePacket, ResponseType};
36 use secretkeeper_test::{
37     AUTHORITY_HASH, MODE, CONFIG_DESC, SECURITY_VERSION, SUBCOMPONENT_AUTHORITY_HASH,
38     SUBCOMPONENT_DESCRIPTORS, SUBCOMPONENT_SECURITY_VERSION,
39     dice_sample::{make_explicit_owned_dice_for_uds, make_explicit_owned_dice, make_large_explicit_owned_dice, CDI_SIZE}
40 };
41 use std::fs;
42 use std::path::Path;
43 
44 const SECRETKEEPER_SERVICE: &str = "android.hardware.security.secretkeeper.ISecretkeeper";
45 const CURRENT_VERSION: u64 = 1;
46 const SECRETKEEPER_KEY_HOST_DT: &str =
47     "/proc/device-tree/avf/reference/avf/secretkeeper_public_key";
48 
49 // Random bytes (of ID_SIZE/SECRET_SIZE) generated for tests.
50 const ID_EXAMPLE: Id = Id([
51     0xF1, 0xB2, 0xED, 0x3B, 0xD1, 0xBD, 0xF0, 0x7D, 0xE1, 0xF0, 0x01, 0xFC, 0x61, 0x71, 0xD3, 0x42,
52     0xE5, 0x8A, 0xAF, 0x33, 0x6C, 0x11, 0xDC, 0xC8, 0x6F, 0xAE, 0x12, 0x5C, 0x26, 0x44, 0x6B, 0x86,
53     0xCC, 0x24, 0xFD, 0xBF, 0x91, 0x4A, 0x54, 0x84, 0xF9, 0x01, 0x59, 0x25, 0x70, 0x89, 0x38, 0x8D,
54     0x5E, 0xE6, 0x91, 0xDF, 0x68, 0x60, 0x69, 0x26, 0xBE, 0xFE, 0x79, 0x58, 0xF7, 0xEA, 0x81, 0x7D,
55 ]);
56 const ID_EXAMPLE_2: Id = Id([
57     0x6A, 0xCC, 0xB1, 0xEB, 0xBB, 0xAB, 0xE3, 0xEA, 0x44, 0xBD, 0xDC, 0x75, 0x75, 0x7D, 0xC0, 0xE5,
58     0xC7, 0x86, 0x41, 0x56, 0x39, 0x66, 0x96, 0x10, 0xCB, 0x43, 0x10, 0x79, 0x03, 0xDC, 0xE6, 0x9F,
59     0x12, 0x2B, 0xEF, 0x28, 0x9C, 0x1E, 0x32, 0x46, 0x5F, 0xA3, 0xE7, 0x8D, 0x53, 0x63, 0xE8, 0x30,
60     0x5A, 0x17, 0x6F, 0xEF, 0x42, 0xD6, 0x58, 0x7A, 0xF0, 0xCB, 0xD4, 0x40, 0x58, 0x96, 0x32, 0xF4,
61 ]);
62 const ID_NOT_STORED: Id = Id([
63     0x56, 0xD0, 0x4E, 0xAA, 0xC1, 0x7B, 0x55, 0x6B, 0xA0, 0x2C, 0x65, 0x43, 0x39, 0x0A, 0x6C, 0xE9,
64     0x1F, 0xD0, 0x0E, 0x20, 0x3E, 0xFB, 0xF5, 0xF9, 0x3F, 0x5B, 0x11, 0x1B, 0x18, 0x73, 0xF6, 0xBB,
65     0xAB, 0x9F, 0xF2, 0xD6, 0xBD, 0xBA, 0x25, 0x68, 0x22, 0x30, 0xF2, 0x1F, 0x90, 0x05, 0xF3, 0x64,
66     0xE7, 0xEF, 0xC6, 0xB6, 0xA0, 0x85, 0xC9, 0x40, 0x40, 0xF0, 0xB4, 0xB9, 0xD8, 0x28, 0xEE, 0x9C,
67 ]);
68 const SECRET_EXAMPLE: Secret = Secret([
69     0xA9, 0x89, 0x97, 0xFE, 0xAE, 0x97, 0x55, 0x4B, 0x32, 0x35, 0xF0, 0xE8, 0x93, 0xDA, 0xEA, 0x24,
70     0x06, 0xAC, 0x36, 0x8B, 0x3C, 0x95, 0x50, 0x16, 0x67, 0x71, 0x65, 0x26, 0xEB, 0xD0, 0xC3, 0x98,
71 ]);
72 
73 // Android expects the public key of Secretkeeper instance to be present in the Linux device tree.
74 // This allows clients to (cryptographically) verify that they are indeed talking to the real
75 // secretkeeper.
76 // Note that this is the identity of the `default` instance (and not `nonsecure`)!
get_secretkeeper_identity() -> Option<CoseKey>77 fn get_secretkeeper_identity() -> Option<CoseKey> {
78     let path = Path::new(SECRETKEEPER_KEY_HOST_DT);
79     if path.exists() {
80         let key = fs::read(path).unwrap();
81         let mut key = CoseKey::from_slice(&key).unwrap();
82         key.canonicalize(CborOrdering::Lexicographic);
83         Some(key)
84     } else {
85         None
86     }
87 }
88 
get_instances() -> Vec<(String, String)>89 fn get_instances() -> Vec<(String, String)> {
90     // Determine which instances are available.
91     binder::get_declared_instances(SECRETKEEPER_SERVICE)
92         .unwrap_or_default()
93         .into_iter()
94         .map(|v| (v.clone(), v))
95         .collect()
96 }
97 
get_connection(instance: &str) -> binder::Strong<dyn ISecretkeeper>98 fn get_connection(instance: &str) -> binder::Strong<dyn ISecretkeeper> {
99     let name = format!("{SECRETKEEPER_SERVICE}/{instance}");
100     binder::get_interface(&name).unwrap()
101 }
102 
103 /// Secretkeeper client information.
104 #[derive(Debug)]
105 struct SkClient {
106     sk: binder::Strong<dyn ISecretkeeper>,
107     session: SkSession,
108     dice_artifacts: OwnedDiceArtifactsWithExplicitKey,
109 }
110 
111 impl Drop for SkClient {
drop(&mut self)112     fn drop(&mut self) {
113         // Delete any IDs that may be left over.
114         self.delete(&[&ID_EXAMPLE, &ID_EXAMPLE_2]);
115     }
116 }
117 
118 impl SkClient {
119     /// Create an `SkClient` using the default `OwnedDiceArtifactsWithExplicitKey` for identity.
new(instance: &str) -> Result<Self, SkClientError>120     fn new(instance: &str) -> Result<Self, SkClientError> {
121         let default_dice = make_explicit_owned_dice(/*Security version in a node */ 5);
122         Self::create(instance, default_dice, None)
123     }
124 
125     /// Create an `SkClient` using given `OwnedDiceArtifactsWithExplicitKey` as client identity.
with_identity( instance: &str, dice_artifacts: OwnedDiceArtifactsWithExplicitKey, ) -> Result<Self, SkClientError>126     fn with_identity(
127         instance: &str,
128         dice_artifacts: OwnedDiceArtifactsWithExplicitKey,
129     ) -> Result<Self, SkClientError> {
130         Self::create(instance, dice_artifacts, None)
131     }
132 
133     /// Create an `SkClient` with default client identity, requiring Secretkeeper's identity to be
134     /// matched against given `expected_sk_key`.
with_expected_sk_identity( instance: &str, expected_sk_key: coset::CoseKey, ) -> Result<Self, SkClientError>135     fn with_expected_sk_identity(
136         instance: &str,
137         expected_sk_key: coset::CoseKey,
138     ) -> Result<Self, SkClientError> {
139         let default_dice = make_explicit_owned_dice(/*Security version in a node */ 5);
140         Self::create(instance, default_dice, Some(expected_sk_key))
141     }
142 
create( instance: &str, dice_artifacts: OwnedDiceArtifactsWithExplicitKey, expected_sk_key: Option<coset::CoseKey>, ) -> Result<Self, SkClientError>143     fn create(
144         instance: &str,
145         dice_artifacts: OwnedDiceArtifactsWithExplicitKey,
146         expected_sk_key: Option<coset::CoseKey>,
147     ) -> Result<Self, SkClientError> {
148         let sk = get_connection(instance);
149         Ok(Self {
150             sk: sk.clone(),
151             session: SkSession::new(sk, &dice_artifacts, expected_sk_key)?,
152             dice_artifacts,
153         })
154     }
155 
156     /// This method is wrapper that use `SkSession::secret_management_request` which handles
157     /// encryption and decryption.
secret_management_request(&mut self, req_data: &[u8]) -> Result<Vec<u8>, Error>158     fn secret_management_request(&mut self, req_data: &[u8]) -> Result<Vec<u8>, Error> {
159         Ok(self.session.secret_management_request(req_data)?)
160     }
161 
162     /// Unlike the method [`secret_management_request`], this method directly uses
163     /// `cipher::encrypt_message` & `cipher::decrypt_message`, allowing finer control of request
164     /// & response aad.
secret_management_request_custom_aad( &self, req_data: &[u8], req_aad: &[u8], expected_res_aad: &[u8], ) -> Result<Vec<u8>, Error>165     fn secret_management_request_custom_aad(
166         &self,
167         req_data: &[u8],
168         req_aad: &[u8],
169         expected_res_aad: &[u8],
170     ) -> Result<Vec<u8>, Error> {
171         let aes_gcm = boring::BoringAes;
172         let rng = boring::BoringRng;
173         let request_bytes = cipher::encrypt_message(
174             &aes_gcm,
175             &rng,
176             self.session.encryption_key(),
177             self.session.session_id(),
178             &req_data,
179             req_aad,
180         )
181         .map_err(|e| secretkeeper_client::Error::CipherError(e))?;
182 
183         // Binder call!
184         let response_bytes = self.sk.processSecretManagementRequest(&request_bytes)?;
185 
186         let response_encrypt0 = CoseEncrypt0::from_slice(&response_bytes)?;
187         Ok(cipher::decrypt_message(
188             &aes_gcm,
189             self.session.decryption_key(),
190             &response_encrypt0,
191             expected_res_aad,
192         )
193         .map_err(|e| secretkeeper_client::Error::CipherError(e))?)
194     }
195 
196     /// Helper method to store a secret. This uses the default compatible sealing_policy on
197     /// dice_chain.
store(&mut self, id: &Id, secret: &Secret) -> Result<(), Error>198     fn store(&mut self, id: &Id, secret: &Secret) -> Result<(), Error> {
199         let sealing_policy = sealing_policy(
200             self.dice_artifacts.explicit_key_dice_chain().ok_or(Error::UnexpectedError)?,
201         );
202         let store_request =
203             StoreSecretRequest { id: id.clone(), secret: secret.clone(), sealing_policy };
204         let store_request = store_request.serialize_to_packet().to_vec()?;
205 
206         let store_response = self.secret_management_request(&store_request)?;
207         let store_response = ResponsePacket::from_slice(&store_response)?;
208 
209         assert_eq!(store_response.response_type()?, ResponseType::Success);
210         // Really just checking that the response is indeed StoreSecretResponse
211         let _ = StoreSecretResponse::deserialize_from_packet(store_response)?;
212         Ok(())
213     }
214 
215     /// Helper method to get a secret.
get(&mut self, id: &Id) -> Result<Secret, Error>216     fn get(&mut self, id: &Id) -> Result<Secret, Error> {
217         self.get_update_policy(id, None)
218     }
219 
220     /// Helper method to get a secret, updating the sealing policy along the way.
get_update_policy( &mut self, id: &Id, updated_sealing_policy: Option<Vec<u8>>, ) -> Result<Secret, Error>221     fn get_update_policy(
222         &mut self,
223         id: &Id,
224         updated_sealing_policy: Option<Vec<u8>>,
225     ) -> Result<Secret, Error> {
226         let get_request = GetSecretRequest { id: id.clone(), updated_sealing_policy };
227         let get_request = get_request.serialize_to_packet().to_vec()?;
228 
229         let get_response = self.secret_management_request(&get_request)?;
230         let get_response = ResponsePacket::from_slice(&get_response)?;
231 
232         if get_response.response_type()? == ResponseType::Success {
233             let get_response = *GetSecretResponse::deserialize_from_packet(get_response)?;
234             Ok(Secret(get_response.secret.0))
235         } else {
236             let err = *SecretkeeperError::deserialize_from_packet(get_response)?;
237             Err(Error::SecretkeeperError(err))
238         }
239     }
240 
241     /// Helper method to delete secrets.
delete(&self, ids: &[&Id])242     fn delete(&self, ids: &[&Id]) {
243         let ids: Vec<SecretId> = ids.iter().map(|id| SecretId { id: id.0 }).collect();
244         self.sk.deleteIds(&ids).unwrap();
245     }
246 
247     /// Helper method to delete everything.
delete_all(&self)248     fn delete_all(&self) {
249         self.sk.deleteAll().unwrap();
250     }
251 }
252 
253 #[derive(Debug)]
254 enum Error {
255     // Errors from Secretkeeper API errors. These are thrown by core SecretManagement and
256     // not visible without decryption.
257     SecretkeeperError(SecretkeeperError),
258     InfraError(secretkeeper_client::Error),
259     UnexpectedError,
260 }
261 
262 impl From<secretkeeper_client::Error> for Error {
from(e: secretkeeper_client::Error) -> Self263     fn from(e: secretkeeper_client::Error) -> Self {
264         Self::InfraError(e)
265     }
266 }
267 
268 impl From<SecretkeeperError> for Error {
from(e: SecretkeeperError) -> Self269     fn from(e: SecretkeeperError) -> Self {
270         Self::SecretkeeperError(e)
271     }
272 }
273 
274 impl From<coset::CoseError> for Error {
from(e: coset::CoseError) -> Self275     fn from(e: coset::CoseError) -> Self {
276         Self::InfraError(secretkeeper_client::Error::from(e))
277     }
278 }
279 
280 impl From<binder::Status> for Error {
from(s: binder::Status) -> Self281     fn from(s: binder::Status) -> Self {
282         Self::InfraError(secretkeeper_client::Error::from(s))
283     }
284 }
285 
286 impl From<secretkeeper_comm::data_types::error::Error> for Error {
from(e: secretkeeper_comm::data_types::error::Error) -> Self287     fn from(e: secretkeeper_comm::data_types::error::Error) -> Self {
288         Self::InfraError(secretkeeper_client::Error::from(e))
289     }
290 }
291 
292 // Assert that the error is `EntryNotFound`.
assert_entry_not_found(res: Result<Secret, Error>)293 fn assert_entry_not_found(res: Result<Secret, Error>) {
294     assert_result_matches(res, SecretkeeperError::EntryNotFound)
295 }
296 
297 // Assert that the error is `DicePolicyError`.
assert_dice_policy_error(res: Result<Secret, Error>)298 fn assert_dice_policy_error(res: Result<Secret, Error>) {
299     assert_result_matches(res, SecretkeeperError::DicePolicyError)
300 }
301 
assert_result_matches(res: Result<Secret, Error>, want: SecretkeeperError)302 fn assert_result_matches(res: Result<Secret, Error>, want: SecretkeeperError) {
303     match res {
304         Err(Error::SecretkeeperError(e)) if e == want => {}
305         Err(got) => panic!("unexpected error {got:?}, expected {want:?}"),
306         Ok(_) => panic!("unexpected success instead of {want:?}"),
307     }
308 }
309 
310 /// Construct a sealing policy on the dice chain. This method uses the following set of
311 /// constraints which are compatible with sample DICE chains used in VTS.
312 /// 1. ExactMatch on AUTHORITY_HASH (non-optional).
313 /// 2. ExactMatch on MODE (non-optional).
314 /// 3. GreaterOrEqual on SECURITY_VERSION (optional).
315 /// 4. The DiceChainEntry corresponding to "AVB" contains SubcomponentDescriptor, for each of those:
316 ///     a) GreaterOrEqual on SECURITY_VERSION (Required)
317 //      b) ExactMatch on AUTHORITY_HASH (Required).
sealing_policy(dice: &[u8]) -> Vec<u8>318 fn sealing_policy(dice: &[u8]) -> Vec<u8> {
319     let constraint_spec = vec![
320         ConstraintSpec::new(
321             ConstraintType::ExactMatch,
322             vec![AUTHORITY_HASH],
323             MissingAction::Fail,
324             TargetEntry::All,
325         ),
326         ConstraintSpec::new(
327             ConstraintType::ExactMatch,
328             vec![MODE],
329             MissingAction::Fail,
330             TargetEntry::All,
331         ),
332         ConstraintSpec::new(
333             ConstraintType::GreaterOrEqual,
334             vec![CONFIG_DESC, SECURITY_VERSION],
335             MissingAction::Ignore,
336             TargetEntry::All,
337         ),
338         ConstraintSpec::new(
339             ConstraintType::GreaterOrEqual,
340             vec![
341                 CONFIG_DESC,
342                 SUBCOMPONENT_DESCRIPTORS,
343                 WILDCARD_FULL_ARRAY,
344                 SUBCOMPONENT_SECURITY_VERSION,
345             ],
346             MissingAction::Fail,
347             TargetEntry::ByName("AVB".to_string()),
348         ),
349         ConstraintSpec::new(
350             ConstraintType::ExactMatch,
351             vec![
352                 CONFIG_DESC,
353                 SUBCOMPONENT_DESCRIPTORS,
354                 WILDCARD_FULL_ARRAY,
355                 SUBCOMPONENT_AUTHORITY_HASH,
356             ],
357             MissingAction::Fail,
358             TargetEntry::ByName("AVB".to_string()),
359         ),
360     ];
361 
362     policy_for_dice_chain(dice, constraint_spec).unwrap().to_vec().unwrap()
363 }
364 
365 /// Perform AuthGraph key exchange, returning the session keys and session ID.
authgraph_key_exchange(sk: binder::Strong<dyn ISecretkeeper>) -> ([key::AesKey; 2], Vec<u8>)366 fn authgraph_key_exchange(sk: binder::Strong<dyn ISecretkeeper>) -> ([key::AesKey; 2], Vec<u8>) {
367     let sink = sk.getAuthGraphKe().expect("failed to get AuthGraph");
368     let mut source = ag_vts::test_ag_participant().expect("failed to create a local source");
369     ag_vts::sink::test_mainline(&mut source, sink)
370 }
371 
372 // Test that the AuthGraph instance returned by SecretKeeper correctly performs
373 // mainline key exchange against a local source implementation.
374 #[rdroidtest(get_instances())]
authgraph_mainline(instance: String)375 fn authgraph_mainline(instance: String) {
376     let sk = get_connection(&instance);
377     let (_aes_keys, _session_id) = authgraph_key_exchange(sk);
378 }
379 
380 // Test that the AuthGraph instance returned by SecretKeeper correctly rejects
381 // a corrupted session ID signature.
382 #[rdroidtest(get_instances())]
authgraph_corrupt_sig(instance: String)383 fn authgraph_corrupt_sig(instance: String) {
384     let sk = get_connection(&instance);
385     let sink = sk.getAuthGraphKe().expect("failed to get AuthGraph");
386     let mut source = ag_vts::test_ag_participant().expect("failed to create a local source");
387     ag_vts::sink::test_corrupt_sig(&mut source, sink);
388 }
389 
390 // Test that the AuthGraph instance returned by SecretKeeper correctly detects
391 // when corrupted keys are returned to it.
392 #[rdroidtest(get_instances())]
authgraph_corrupt_keys(instance: String)393 fn authgraph_corrupt_keys(instance: String) {
394     let sk = get_connection(&instance);
395     let sink = sk.getAuthGraphKe().expect("failed to get AuthGraph");
396     let mut source = ag_vts::test_ag_participant().expect("failed to create a local source");
397     ag_vts::sink::test_corrupt_keys(&mut source, sink);
398 }
399 
400 // TODO(b/2797757): Add tests that match different HAL defined objects (like request/response)
401 // with expected bytes.
402 
403 #[rdroidtest(get_instances())]
secret_management_get_version(instance: String)404 fn secret_management_get_version(instance: String) {
405     let mut sk_client = SkClient::new(&instance).unwrap();
406 
407     let request = GetVersionRequest {};
408     let request_packet = request.serialize_to_packet();
409     let request_bytes = request_packet.to_vec().unwrap();
410 
411     let response_bytes = sk_client.secret_management_request(&request_bytes).unwrap();
412 
413     let response_packet = ResponsePacket::from_slice(&response_bytes).unwrap();
414     assert_eq!(response_packet.response_type().unwrap(), ResponseType::Success);
415     let get_version_response =
416         *GetVersionResponse::deserialize_from_packet(response_packet).unwrap();
417     assert_eq!(get_version_response.version, CURRENT_VERSION);
418 }
419 
420 #[rdroidtest(get_instances())]
secret_management_malformed_request(instance: String)421 fn secret_management_malformed_request(instance: String) {
422     let mut sk_client = SkClient::new(&instance).unwrap();
423 
424     let request = GetVersionRequest {};
425     let request_packet = request.serialize_to_packet();
426     let mut request_bytes = request_packet.to_vec().unwrap();
427 
428     // Deform the request
429     request_bytes[0] = !request_bytes[0];
430 
431     let response_bytes = sk_client.secret_management_request(&request_bytes).unwrap();
432 
433     let response_packet = ResponsePacket::from_slice(&response_bytes).unwrap();
434     assert_eq!(response_packet.response_type().unwrap(), ResponseType::Error);
435     let err = *SecretkeeperError::deserialize_from_packet(response_packet).unwrap();
436     assert_eq!(err, SecretkeeperError::RequestMalformed);
437 }
438 
439 #[rdroidtest(get_instances())]
secret_management_store_get_secret_found(instance: String)440 fn secret_management_store_get_secret_found(instance: String) {
441     let mut sk_client = SkClient::new(&instance).unwrap();
442 
443     sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
444 
445     // Get the secret that was just stored
446     assert_eq!(sk_client.get(&ID_EXAMPLE).unwrap(), SECRET_EXAMPLE);
447 }
448 
449 #[rdroidtest(get_instances())]
secret_management_store_get_secret_not_found(instance: String)450 fn secret_management_store_get_secret_not_found(instance: String) {
451     let mut sk_client = SkClient::new(&instance).unwrap();
452 
453     // Store a secret (corresponding to an id).
454     sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
455 
456     // Get the secret that was never stored
457     assert_entry_not_found(sk_client.get(&ID_NOT_STORED));
458 }
459 
460 /// A secret stored in one session should be accessible from a different session
461 /// as long as the client has the same identity.
462 #[rdroidtest(get_instances())]
secretkeeper_get_secret_across_sessions_with_same_identity(instance: String)463 fn secretkeeper_get_secret_across_sessions_with_same_identity(instance: String) {
464     // Store a secret with one session.  Note that we need to hang on to the
465     // test client because it auto-deletes entries on drop.
466     let mut sk_client1 = SkClient::new(&instance).unwrap();
467     sk_client1.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
468     assert_eq!(sk_client1.get(&ID_EXAMPLE).unwrap(), SECRET_EXAMPLE);
469 
470     // Retrieve the secret using a different session (that has the same identity).
471     let mut sk_client2 = SkClient::new(&instance).unwrap();
472     assert_eq!(sk_client2.get(&ID_EXAMPLE).unwrap(), SECRET_EXAMPLE);
473 }
474 
475 /// A secret stored in one session should not be accessible from a different session
476 /// if the client has a different identity.
477 #[rdroidtest(get_instances())]
secretkeeper_no_secret_across_sessions_with_different_identity(instance: String)478 fn secretkeeper_no_secret_across_sessions_with_different_identity(instance: String) {
479     // Store a secret with one session.  Note that we need to hang on to the
480     // test client because it auto-deletes entries on drop.
481     let mut sk_client1 = SkClient::new(&instance).unwrap();
482     sk_client1.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
483     assert_eq!(sk_client1.get(&ID_EXAMPLE).unwrap(), SECRET_EXAMPLE);
484 
485     // Fail to retrieve the secret using a different session that has a different identity.
486     pub const ALT_UDS: &[u8; CDI_SIZE] = &[
487         0x66, 0x4f, 0xab, 0xa9, 0xa5, 0xad, 0x0f, 0x5e, 0x15, 0xc3, 0x12, 0xf7, 0x77, 0x45, 0xfa,
488         0x56, 0x18, 0x6a, 0xa6, 0x34, 0xb6, 0x7c, 0x82, 0x7b, 0x89, 0x4c, 0xc5, 0x52, 0xd3, 0x27,
489         0x36, 0x8e,
490     ];
491     let alt_identity = make_explicit_owned_dice_for_uds(5, ALT_UDS);
492     let mut sk_client2 = SkClient::with_identity(&instance, alt_identity).unwrap();
493     assert_dice_policy_error(sk_client2.get(&ID_EXAMPLE));
494 }
495 
496 #[rdroidtest(get_instances())]
secretkeeper_store_delete_ids(instance: String)497 fn secretkeeper_store_delete_ids(instance: String) {
498     let mut sk_client = SkClient::new(&instance).unwrap();
499 
500     sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
501     sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE).unwrap();
502     sk_client.delete(&[&ID_EXAMPLE]);
503     assert_entry_not_found(sk_client.get(&ID_EXAMPLE));
504     assert_eq!(sk_client.get(&ID_EXAMPLE_2).unwrap(), SECRET_EXAMPLE);
505 
506     sk_client.delete(&[&ID_EXAMPLE_2]);
507 
508     assert_entry_not_found(sk_client.get(&ID_EXAMPLE));
509     assert_entry_not_found(sk_client.get(&ID_EXAMPLE_2));
510 }
511 
512 #[rdroidtest(get_instances())]
secretkeeper_store_delete_multiple_ids(instance: String)513 fn secretkeeper_store_delete_multiple_ids(instance: String) {
514     let mut sk_client = SkClient::new(&instance).unwrap();
515 
516     sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
517     sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE).unwrap();
518     sk_client.delete(&[&ID_EXAMPLE, &ID_EXAMPLE_2]);
519 
520     assert_entry_not_found(sk_client.get(&ID_EXAMPLE));
521     assert_entry_not_found(sk_client.get(&ID_EXAMPLE_2));
522 }
523 #[rdroidtest(get_instances())]
secretkeeper_store_delete_duplicate_ids(instance: String)524 fn secretkeeper_store_delete_duplicate_ids(instance: String) {
525     let mut sk_client = SkClient::new(&instance).unwrap();
526 
527     sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
528     sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE).unwrap();
529     // Delete the same secret twice.
530     sk_client.delete(&[&ID_EXAMPLE, &ID_EXAMPLE]);
531 
532     assert_entry_not_found(sk_client.get(&ID_EXAMPLE));
533     assert_eq!(sk_client.get(&ID_EXAMPLE_2).unwrap(), SECRET_EXAMPLE);
534 }
535 
536 #[rdroidtest(get_instances())]
secretkeeper_store_delete_nonexistent(instance: String)537 fn secretkeeper_store_delete_nonexistent(instance: String) {
538     let mut sk_client = SkClient::new(&instance).unwrap();
539 
540     sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
541     sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE).unwrap();
542     sk_client.delete(&[&ID_NOT_STORED]);
543 
544     assert_eq!(sk_client.get(&ID_EXAMPLE).unwrap(), SECRET_EXAMPLE);
545     assert_eq!(sk_client.get(&ID_EXAMPLE_2).unwrap(), SECRET_EXAMPLE);
546     assert_entry_not_found(sk_client.get(&ID_NOT_STORED));
547 }
548 
549 // Don't run deleteAll() on a secure device, as it might affect real secrets.
550 #[rdroidtest(get_instances())]
551 #[ignore_if(|p| p != "nonsecure")]
secretkeeper_store_delete_all(instance: String)552 fn secretkeeper_store_delete_all(instance: String) {
553     let mut sk_client = SkClient::new(&instance).unwrap();
554 
555     sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
556     sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE).unwrap();
557 
558     sk_client.delete_all();
559 
560     assert_entry_not_found(sk_client.get(&ID_EXAMPLE));
561     assert_entry_not_found(sk_client.get(&ID_EXAMPLE_2));
562 
563     // Store a new secret (corresponding to an id).
564     sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
565 
566     // Get the restored secret.
567     assert_eq!(sk_client.get(&ID_EXAMPLE).unwrap(), SECRET_EXAMPLE);
568 
569     // (Try to) Get the secret that was never stored
570     assert_entry_not_found(sk_client.get(&ID_NOT_STORED));
571 }
572 
573 // This tests creates lots of sessions one after another, to confirm that the Secretkeeper
574 // instance doesn't have unbounded internal state. (Instead, it should drop older sessions
575 // and the clients using those sessions would need to re-establish a new session.)
576 #[rdroidtest(get_instances())]
secretkeeper_many_sessions_serial(instance: String)577 fn secretkeeper_many_sessions_serial(instance: String) {
578     const SESSION_COUNT: usize = 32;
579     let mut sk_clients = Vec::new();
580     for idx in 0..SESSION_COUNT {
581         let identity = make_large_explicit_owned_dice(5);
582         let mut sk_client = SkClient::with_identity(&instance, identity)
583             .expect(&format!("failed to establish session {idx}"));
584         sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
585         sk_clients.push(sk_client);
586     }
587 }
588 
589 // This tests creates lots of sessions in parallel.  Some of these session are expected
590 // to fail, but the Secretkeeper TA should survive the experience.
591 #[rdroidtest(get_instances())]
secretkeeper_many_sessions_parallel(instance: String)592 fn secretkeeper_many_sessions_parallel(instance: String) {
593     const SESSION_COUNT: usize = 32;
594 
595     let mut handles = Vec::<std::thread::JoinHandle<()>>::new();
596     for idx in 0..SESSION_COUNT {
597         let instance = instance.clone();
598         handles.push(std::thread::spawn(move || {
599             // In each thread, create a session and use it.  This may (legitimately) fail at any
600             // moment.
601             let _result = use_sk_may_fail(instance, idx);
602         }));
603     }
604 
605     // Wait for all activity to quiesce.
606     for handle in handles {
607         let _result = handle.join();
608     }
609 
610     // Now that all the parallel activity is done, should still be able to interact with
611     // Secretkeeper.
612     let mut sk_client = SkClient::new(&instance).unwrap();
613     sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
614     assert_eq!(sk_client.get(&ID_EXAMPLE).unwrap(), SECRET_EXAMPLE);
615 
616     // Remove any IDs that might have been stored in the test.
617     for idx in 0..SESSION_COUNT {
618         let mut id = ID_EXAMPLE.clone();
619         id.0[0] = idx as u8;
620         sk_client.delete(&[&id]);
621     }
622 }
623 
use_sk_may_fail(instance: String, idx: usize) -> Result<(), Error>624 fn use_sk_may_fail(instance: String, idx: usize) -> Result<(), Error> {
625     let identity = make_large_explicit_owned_dice(5);
626     let mut sk_client = SkClient::with_identity(&instance, identity)?;
627     let mut id = ID_EXAMPLE.clone();
628     id.0[0] = idx as u8;
629 
630     sk_client.store(&id, &SECRET_EXAMPLE)?;
631     let result = sk_client.get(&id)?;
632     assert_eq!(result, SECRET_EXAMPLE);
633     Ok(())
634 }
635 
636 // This test checks that Secretkeeper uses the expected [`RequestSeqNum`] as aad while
637 // decrypting requests and the responses are encrypted with correct [`ResponseSeqNum`] for the
638 // first few messages.
639 #[rdroidtest(get_instances())]
secret_management_replay_protection_seq_num(instance: String)640 fn secret_management_replay_protection_seq_num(instance: String) {
641     let dice_chain = make_explicit_owned_dice(/*Security version in a node */ 5);
642     let sealing_policy = sealing_policy(dice_chain.explicit_key_dice_chain().unwrap());
643     let sk_client = SkClient::with_identity(&instance, dice_chain).unwrap();
644     // Construct encoded request packets for the test
645     let (req_1, req_2, req_3) = construct_secret_management_requests(sealing_policy);
646 
647     // Lets now construct the seq_numbers(in request & expected in response)
648     let mut seq_a = SeqNum::new();
649     let [seq_0, seq_1, seq_2] = std::array::from_fn(|_| seq_a.get_then_increment().unwrap());
650 
651     // Check first request/response is successful
652     let res = ResponsePacket::from_slice(
653         &sk_client.secret_management_request_custom_aad(&req_1, &seq_0, &seq_0).unwrap(),
654     )
655     .unwrap();
656     assert_eq!(res.response_type().unwrap(), ResponseType::Success);
657 
658     // Check 2nd request/response is successful
659     let res = ResponsePacket::from_slice(
660         &sk_client.secret_management_request_custom_aad(&req_2, &seq_1, &seq_1).unwrap(),
661     )
662     .unwrap();
663     assert_eq!(res.response_type().unwrap(), ResponseType::Success);
664 
665     // Check 3rd request/response is successful
666     let res = ResponsePacket::from_slice(
667         &sk_client.secret_management_request_custom_aad(&req_3, &seq_2, &seq_2).unwrap(),
668     )
669     .unwrap();
670     assert_eq!(res.response_type().unwrap(), ResponseType::Success);
671 }
672 
673 // This test checks that Secretkeeper uses fresh [`RequestSeqNum`] & [`ResponseSeqNum`]
674 // for new sessions.
675 #[rdroidtest(get_instances())]
secret_management_replay_protection_seq_num_per_session(instance: String)676 fn secret_management_replay_protection_seq_num_per_session(instance: String) {
677     let dice_chain = make_explicit_owned_dice(/*Security version in a node */ 5);
678     let sealing_policy = sealing_policy(dice_chain.explicit_key_dice_chain().unwrap());
679     let sk_client = SkClient::with_identity(&instance, dice_chain).unwrap();
680 
681     // Construct encoded request packets for the test
682     let (req_1, _, _) = construct_secret_management_requests(sealing_policy);
683 
684     // Lets now construct the seq_number (in request & expected in response)
685     let mut seq_a = SeqNum::new();
686     let seq_0 = seq_a.get_then_increment().unwrap();
687     // Check first request/response is successful
688     let res = ResponsePacket::from_slice(
689         &sk_client.secret_management_request_custom_aad(&req_1, &seq_0, &seq_0).unwrap(),
690     )
691     .unwrap();
692     assert_eq!(res.response_type().unwrap(), ResponseType::Success);
693 
694     // Start another session
695     let sk_client_diff = SkClient::new(&instance).unwrap();
696     // Check first request/response is with seq_0 is successful
697     let res = ResponsePacket::from_slice(
698         &sk_client_diff.secret_management_request_custom_aad(&req_1, &seq_0, &seq_0).unwrap(),
699     )
700     .unwrap();
701     assert_eq!(res.response_type().unwrap(), ResponseType::Success);
702 }
703 
704 // This test checks that Secretkeeper rejects requests with out of order [`RequestSeqNum`]
705 // TODO(b/317416663): This test fails, when HAL is not present in the device. Refactor to fix this.
706 #[rdroidtest(get_instances())]
secret_management_replay_protection_out_of_seq_req_not_accepted(instance: String)707 fn secret_management_replay_protection_out_of_seq_req_not_accepted(instance: String) {
708     let dice_chain = make_explicit_owned_dice(/*Security version in a node */ 5);
709     let sealing_policy = sealing_policy(dice_chain.explicit_key_dice_chain().unwrap());
710     let sk_client = SkClient::with_identity(&instance, dice_chain).unwrap();
711 
712     // Construct encoded request packets for the test
713     let (req_1, req_2, _) = construct_secret_management_requests(sealing_policy);
714 
715     // Lets now construct the seq_numbers(in request & expected in response)
716     let mut seq_a = SeqNum::new();
717     let [seq_0, seq_1, seq_2] = std::array::from_fn(|_| seq_a.get_then_increment().unwrap());
718 
719     // Assume First request/response is successful
720     sk_client.secret_management_request_custom_aad(&req_1, &seq_0, &seq_0).unwrap();
721 
722     // Check 2nd request/response with skipped seq_num in request is a binder error
723     let res = sk_client
724         .secret_management_request_custom_aad(&req_2, /*Skipping seq_1*/ &seq_2, &seq_1);
725     let err = res.expect_err("Out of Seq messages accepted!");
726     // Incorrect sequence numbers lead to failed decryption. The resultant error should be
727     // thrown in clear text & wrapped in Binder errors.
728     assert!(matches!(err, Error::InfraError(secretkeeper_client::Error::BinderStatus(_e))));
729 }
730 
731 // This test checks DICE policy based access control of Secretkeeper.
732 #[rdroidtest(get_instances())]
secret_management_policy_gate(instance: String)733 fn secret_management_policy_gate(instance: String) {
734     let dice_chain = make_explicit_owned_dice(/*Security version in a node */ 100);
735     let mut sk_client_original = SkClient::with_identity(&instance, dice_chain).unwrap();
736     sk_client_original.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
737     assert_eq!(sk_client_original.get(&ID_EXAMPLE).unwrap(), SECRET_EXAMPLE);
738 
739     // Start a session with higher security_version & get the stored secret.
740     let dice_chain_upgraded = make_explicit_owned_dice(/*Security version in a node */ 101);
741     let mut sk_client_upgraded = SkClient::with_identity(&instance, dice_chain_upgraded).unwrap();
742     assert_eq!(sk_client_upgraded.get(&ID_EXAMPLE).unwrap(), SECRET_EXAMPLE);
743 
744     // Start a session with lower security_version (This should be denied access to the secret).
745     let dice_chain_downgraded = make_explicit_owned_dice(/*Security version in a node */ 99);
746     let mut sk_client_downgraded =
747         SkClient::with_identity(&instance, dice_chain_downgraded).unwrap();
748     assert_dice_policy_error(sk_client_downgraded.get(&ID_EXAMPLE));
749 
750     // Now get the secret with the later version, and upgrade the sealing policy along the way.
751     let sealing_policy =
752         sealing_policy(sk_client_upgraded.dice_artifacts.explicit_key_dice_chain().unwrap());
753     assert_eq!(
754         sk_client_upgraded.get_update_policy(&ID_EXAMPLE, Some(sealing_policy)).unwrap(),
755         SECRET_EXAMPLE
756     );
757 
758     // The original version of the client should no longer be able to retrieve the secret.
759     assert_dice_policy_error(sk_client_original.get(&ID_EXAMPLE));
760 }
761 
762 // This test checks that the identity of Secretkeeper (in context of AuthGraph key exchange) is
763 // same as the one advertized in Linux device tree. This is only expected from `default` instance.
764 #[rdroidtest(get_instances())]
765 #[ignore_if(|p| p != "default")]
secretkeeper_check_identity(instance: String)766 fn secretkeeper_check_identity(instance: String) {
767     let sk_key = get_secretkeeper_identity()
768         .expect("Failed to extract identity of default instance from device tree");
769     // Create a session with this expected identity. This succeeds only if the identity used by
770     // Secretkeeper is sk_key.
771     let _ = SkClient::with_expected_sk_identity(&instance, sk_key).unwrap();
772     // Create a session using any other expected sk identity, this should fail. Note that the
773     // failure arises from validation which happens at the local participant.
774     let mut any_other_key = CoseKey::default();
775     any_other_key.canonicalize(CborOrdering::Lexicographic);
776     let err = SkClient::with_expected_sk_identity(&instance, any_other_key).unwrap_err();
777     assert!(matches!(
778         err,
779         SkClientError::AuthgraphError(authgraph_core::error::Error(
780             authgraph_wire::ErrorCode::InvalidPeerKeKey,
781             _
782         ))
783     ));
784 }
785 
786 // Helper method that constructs 3 SecretManagement requests. Callers would usually not care about
787 // what each of the request concretely is.
construct_secret_management_requests(sealing_policy: Vec<u8>) -> (Vec<u8>, Vec<u8>, Vec<u8>)788 fn construct_secret_management_requests(sealing_policy: Vec<u8>) -> (Vec<u8>, Vec<u8>, Vec<u8>) {
789     let version_request = GetVersionRequest {};
790     let version_request = version_request.serialize_to_packet().to_vec().unwrap();
791     let store_request =
792         StoreSecretRequest { id: ID_EXAMPLE, secret: SECRET_EXAMPLE, sealing_policy };
793     let store_request = store_request.serialize_to_packet().to_vec().unwrap();
794     let get_request = GetSecretRequest { id: ID_EXAMPLE, updated_sealing_policy: None };
795     let get_request = get_request.serialize_to_packet().to_vec().unwrap();
796     (version_request, store_request, get_request)
797 }
798 
799 rdroidtest::test_main!();
800