1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 //! RKPD tests.
16
17 use super::*;
18 use android_security_rkp_aidl::aidl::android::security::rkp::IRegistration::BnRegistration;
19 use std::sync::atomic::{AtomicU32, Ordering};
20 use std::sync::{Arc, Mutex};
21
22 const DEFAULT_RPC_SERVICE_NAME: &str =
23 "android.hardware.security.keymint.IRemotelyProvisionedComponent/default";
24
25 struct MockRegistrationValues {
26 key: RemotelyProvisionedKey,
27 latency: Option<Duration>,
28 thread_join_handles: Vec<Option<std::thread::JoinHandle<()>>>,
29 }
30
31 struct MockRegistration(Arc<Mutex<MockRegistrationValues>>);
32
33 impl MockRegistration {
new_native_binder( key: &RemotelyProvisionedKey, latency: Option<Duration>, ) -> Strong<dyn IRegistration>34 pub fn new_native_binder(
35 key: &RemotelyProvisionedKey,
36 latency: Option<Duration>,
37 ) -> Strong<dyn IRegistration> {
38 let result = Self(Arc::new(Mutex::new(MockRegistrationValues {
39 key: RemotelyProvisionedKey {
40 keyBlob: key.keyBlob.clone(),
41 encodedCertChain: key.encodedCertChain.clone(),
42 },
43 latency,
44 thread_join_handles: Vec::new(),
45 })));
46 BnRegistration::new_binder(result, BinderFeatures::default())
47 }
48 }
49
50 impl Drop for MockRegistration {
drop(&mut self)51 fn drop(&mut self) {
52 let mut values = self.0.lock().unwrap();
53 for handle in values.thread_join_handles.iter_mut() {
54 // These are test threads. So, no need to worry too much about error handling.
55 handle.take().unwrap().join().unwrap();
56 }
57 }
58 }
59
60 impl Interface for MockRegistration {}
61
62 impl IRegistration for MockRegistration {
getKey(&self, _: i32, cb: &Strong<dyn IGetKeyCallback>) -> binder::Result<()>63 fn getKey(&self, _: i32, cb: &Strong<dyn IGetKeyCallback>) -> binder::Result<()> {
64 let mut values = self.0.lock().unwrap();
65 let key = RemotelyProvisionedKey {
66 keyBlob: values.key.keyBlob.clone(),
67 encodedCertChain: values.key.encodedCertChain.clone(),
68 };
69 let latency = values.latency;
70 let get_key_cb = cb.clone();
71
72 // Need a separate thread to trigger timeout in the caller.
73 let join_handle = std::thread::spawn(move || {
74 if let Some(duration) = latency {
75 std::thread::sleep(duration);
76 }
77 get_key_cb.onSuccess(&key).unwrap();
78 });
79 values.thread_join_handles.push(Some(join_handle));
80 Ok(())
81 }
82
cancelGetKey(&self, _: &Strong<dyn IGetKeyCallback>) -> binder::Result<()>83 fn cancelGetKey(&self, _: &Strong<dyn IGetKeyCallback>) -> binder::Result<()> {
84 Ok(())
85 }
86
storeUpgradedKeyAsync( &self, _: &[u8], _: &[u8], cb: &Strong<dyn IStoreUpgradedKeyCallback>, ) -> binder::Result<()>87 fn storeUpgradedKeyAsync(
88 &self,
89 _: &[u8],
90 _: &[u8],
91 cb: &Strong<dyn IStoreUpgradedKeyCallback>,
92 ) -> binder::Result<()> {
93 // We are primarily concerned with timing out correctly. Storing the key in this mock
94 // registration isn't particularly interesting, so skip that part.
95 let values = self.0.lock().unwrap();
96 let store_cb = cb.clone();
97 let latency = values.latency;
98
99 std::thread::spawn(move || {
100 if let Some(duration) = latency {
101 std::thread::sleep(duration);
102 }
103 store_cb.onSuccess().unwrap();
104 });
105 Ok(())
106 }
107 }
108
get_mock_registration( key: &RemotelyProvisionedKey, latency: Option<Duration>, ) -> Result<binder::Strong<dyn IRegistration>>109 fn get_mock_registration(
110 key: &RemotelyProvisionedKey,
111 latency: Option<Duration>,
112 ) -> Result<binder::Strong<dyn IRegistration>> {
113 let (tx, rx) = oneshot::channel();
114 let cb = GetRegistrationCallback::new_native_binder(tx);
115 let mock_registration = MockRegistration::new_native_binder(key, latency);
116
117 assert!(cb.onSuccess(&mock_registration).is_ok());
118 tokio_rt().block_on(rx).unwrap()
119 }
120
121 // Using the same key ID makes test cases race with each other. So, we use separate key IDs for
122 // different test cases.
get_next_key_id() -> u32123 fn get_next_key_id() -> u32 {
124 static ID: AtomicU32 = AtomicU32::new(0);
125 ID.fetch_add(1, Ordering::Relaxed)
126 }
127
128 #[test]
test_get_registration_cb_success()129 fn test_get_registration_cb_success() {
130 let key: RemotelyProvisionedKey = Default::default();
131 let registration = get_mock_registration(&key, /*latency=*/ None);
132 assert!(registration.is_ok());
133 }
134
135 #[test]
test_get_registration_cb_cancel()136 fn test_get_registration_cb_cancel() {
137 let (tx, rx) = oneshot::channel();
138 let cb = GetRegistrationCallback::new_native_binder(tx);
139 assert!(cb.onCancel().is_ok());
140
141 let result = tokio_rt().block_on(rx).unwrap();
142 assert_eq!(result.unwrap_err().downcast::<Error>().unwrap(), Error::RequestCancelled);
143 }
144
145 #[test]
test_get_registration_cb_error()146 fn test_get_registration_cb_error() {
147 let (tx, rx) = oneshot::channel();
148 let cb = GetRegistrationCallback::new_native_binder(tx);
149 assert!(cb.onError("error").is_ok());
150
151 let result = tokio_rt().block_on(rx).unwrap();
152 assert_eq!(result.unwrap_err().downcast::<Error>().unwrap(), Error::GetRegistrationFailed);
153 }
154
155 #[test]
test_get_key_cb_success()156 fn test_get_key_cb_success() {
157 let mock_key =
158 RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] };
159 let (tx, rx) = oneshot::channel();
160 let cb = GetKeyCallback::new_native_binder(tx);
161 assert!(cb.onSuccess(&mock_key).is_ok());
162
163 let key = tokio_rt().block_on(rx).unwrap().unwrap();
164 assert_eq!(key, mock_key);
165 }
166
167 #[test]
test_get_key_cb_cancel()168 fn test_get_key_cb_cancel() {
169 let (tx, rx) = oneshot::channel();
170 let cb = GetKeyCallback::new_native_binder(tx);
171 assert!(cb.onCancel().is_ok());
172
173 let result = tokio_rt().block_on(rx).unwrap();
174 assert_eq!(result.unwrap_err().downcast::<Error>().unwrap(), Error::RequestCancelled);
175 }
176
177 #[test]
test_get_key_cb_error()178 fn test_get_key_cb_error() {
179 for get_key_error in GetKeyErrorCode::enum_values() {
180 let (tx, rx) = oneshot::channel();
181 let cb = GetKeyCallback::new_native_binder(tx);
182 assert!(cb.onError(get_key_error, "error").is_ok());
183
184 let result = tokio_rt().block_on(rx).unwrap();
185 assert_eq!(
186 result.unwrap_err().downcast::<Error>().unwrap(),
187 Error::GetKeyFailed(get_key_error),
188 );
189 }
190 }
191
192 #[test]
test_store_upgraded_cb_success()193 fn test_store_upgraded_cb_success() {
194 let (tx, rx) = oneshot::channel();
195 let cb = StoreUpgradedKeyCallback::new_native_binder(tx);
196 assert!(cb.onSuccess().is_ok());
197
198 tokio_rt().block_on(rx).unwrap().unwrap();
199 }
200
201 #[test]
test_store_upgraded_key_cb_error()202 fn test_store_upgraded_key_cb_error() {
203 let (tx, rx) = oneshot::channel();
204 let cb = StoreUpgradedKeyCallback::new_native_binder(tx);
205 assert!(cb.onError("oh no! it failed").is_ok());
206
207 let result = tokio_rt().block_on(rx).unwrap();
208 assert_eq!(result.unwrap_err().downcast::<Error>().unwrap(), Error::StoreUpgradedKeyFailed);
209 }
210
211 #[test]
test_get_mock_key_success()212 fn test_get_mock_key_success() {
213 let mock_key =
214 RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] };
215 let registration = get_mock_registration(&mock_key, /*latency=*/ None).unwrap();
216
217 let key = tokio_rt()
218 .block_on(get_rkpd_attestation_key_from_registration_async(®istration, 0))
219 .unwrap();
220 assert_eq!(key, mock_key);
221 }
222
223 #[test]
test_get_mock_key_timeout()224 fn test_get_mock_key_timeout() {
225 let mock_key =
226 RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] };
227 let latency = RKPD_TIMEOUT + Duration::from_secs(1);
228 let registration = get_mock_registration(&mock_key, Some(latency)).unwrap();
229
230 let result =
231 tokio_rt().block_on(get_rkpd_attestation_key_from_registration_async(®istration, 0));
232 assert_eq!(result.unwrap_err().downcast::<Error>().unwrap(), Error::RetryableTimeout);
233 }
234
235 #[test]
test_store_mock_key_success()236 fn test_store_mock_key_success() {
237 let mock_key =
238 RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] };
239 let registration = get_mock_registration(&mock_key, /*latency=*/ None).unwrap();
240 tokio_rt()
241 .block_on(store_rkpd_attestation_key_with_registration_async(®istration, &[], &[]))
242 .unwrap();
243 }
244
245 #[test]
test_store_mock_key_timeout()246 fn test_store_mock_key_timeout() {
247 let mock_key =
248 RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] };
249 let latency = RKPD_TIMEOUT + Duration::from_secs(1);
250 let registration = get_mock_registration(&mock_key, Some(latency)).unwrap();
251
252 let result = tokio_rt().block_on(store_rkpd_attestation_key_with_registration_async(
253 ®istration,
254 &[],
255 &[],
256 ));
257 assert_eq!(result.unwrap_err().downcast::<Error>().unwrap(), Error::Timeout);
258 }
259
260 #[test]
test_get_rkpd_attestation_key()261 fn test_get_rkpd_attestation_key() {
262 binder::ProcessState::start_thread_pool();
263 let key_id = get_next_key_id();
264 let key = get_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, key_id).unwrap();
265 assert!(!key.keyBlob.is_empty());
266 assert!(!key.encodedCertChain.is_empty());
267 }
268
269 #[test]
test_get_rkpd_attestation_key_same_caller()270 fn test_get_rkpd_attestation_key_same_caller() {
271 binder::ProcessState::start_thread_pool();
272 let key_id = get_next_key_id();
273
274 // Multiple calls should return the same key.
275 let first_key = get_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, key_id).unwrap();
276 let second_key = get_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, key_id).unwrap();
277
278 assert_eq!(first_key.keyBlob, second_key.keyBlob);
279 assert_eq!(first_key.encodedCertChain, second_key.encodedCertChain);
280 }
281
282 #[test]
test_get_rkpd_attestation_key_different_caller()283 fn test_get_rkpd_attestation_key_different_caller() {
284 binder::ProcessState::start_thread_pool();
285 let first_key_id = get_next_key_id();
286 let second_key_id = get_next_key_id();
287
288 // Different callers should be getting different keys.
289 let first_key = get_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, first_key_id).unwrap();
290 let second_key = get_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, second_key_id).unwrap();
291
292 assert_ne!(first_key.keyBlob, second_key.keyBlob);
293 assert_ne!(first_key.encodedCertChain, second_key.encodedCertChain);
294 }
295
296 #[test]
297 // Couple of things to note:
298 // 1. This test must never run with UID of keystore. Otherwise, it can mess up keys stored by
299 // keystore.
300 // 2. Storing and reading the stored key is prone to race condition. So, we only do this in one
301 // test case.
test_store_rkpd_attestation_key()302 fn test_store_rkpd_attestation_key() {
303 binder::ProcessState::start_thread_pool();
304 let key_id = get_next_key_id();
305 let key = get_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, key_id).unwrap();
306 let new_blob: [u8; 8] = rand::random();
307
308 assert!(store_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, &key.keyBlob, &new_blob).is_ok());
309
310 let new_key = get_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, key_id).unwrap();
311
312 // Restore original key so that we don't leave RKPD with invalid blobs.
313 assert!(store_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, &new_blob, &key.keyBlob).is_ok());
314 assert_eq!(new_key.keyBlob, new_blob);
315 }
316
317 #[test]
test_stress_get_rkpd_attestation_key()318 fn test_stress_get_rkpd_attestation_key() {
319 binder::ProcessState::start_thread_pool();
320 let key_id = get_next_key_id();
321 let mut threads = vec![];
322 const NTHREADS: u32 = 10;
323 const NCALLS: u32 = 1000;
324
325 for _ in 0..NTHREADS {
326 threads.push(std::thread::spawn(move || {
327 for _ in 0..NCALLS {
328 let key = get_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, key_id).unwrap();
329 assert!(!key.keyBlob.is_empty());
330 assert!(!key.encodedCertChain.is_empty());
331 }
332 }));
333 }
334
335 for t in threads {
336 assert!(t.join().is_ok());
337 }
338 }
339