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