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 //! Helper wrapper around RKPD interface.
16
17 use crate::error::{map_binder_status_code, Error, ResponseCode};
18 use crate::globals::get_remotely_provisioned_component_name;
19 use crate::ks_err;
20 use crate::utils::watchdog as wd;
21 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::SecurityLevel::SecurityLevel;
22 use android_security_rkp_aidl::aidl::android::security::rkp::{
23 IGetKeyCallback::BnGetKeyCallback, IGetKeyCallback::ErrorCode::ErrorCode as GetKeyErrorCode,
24 IGetKeyCallback::IGetKeyCallback, IGetRegistrationCallback::BnGetRegistrationCallback,
25 IGetRegistrationCallback::IGetRegistrationCallback, IRegistration::IRegistration,
26 IRemoteProvisioning::IRemoteProvisioning,
27 IStoreUpgradedKeyCallback::BnStoreUpgradedKeyCallback,
28 IStoreUpgradedKeyCallback::IStoreUpgradedKeyCallback,
29 RemotelyProvisionedKey::RemotelyProvisionedKey,
30 };
31 use android_security_rkp_aidl::binder::{BinderFeatures, Interface, Strong};
32 use anyhow::{Context, Result};
33 use std::sync::Mutex;
34 use std::time::Duration;
35 use tokio::sync::oneshot;
36 use tokio::time::timeout;
37
38 // Normally, we block indefinitely when making calls outside of keystore and rely on watchdog to
39 // report deadlocks. However, RKPD is mainline updatable. Also, calls to RKPD may wait on network
40 // for certificates. So, we err on the side of caution and timeout instead.
41 static RKPD_TIMEOUT: Duration = Duration::from_secs(10);
42
tokio_rt() -> tokio::runtime::Runtime43 fn tokio_rt() -> tokio::runtime::Runtime {
44 tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap()
45 }
46
47 /// Thread-safe channel for sending a value once and only once. If a value has
48 /// already been send, subsequent calls to send will noop.
49 struct SafeSender<T> {
50 inner: Mutex<Option<oneshot::Sender<T>>>,
51 }
52
53 impl<T> SafeSender<T> {
new(sender: oneshot::Sender<T>) -> Self54 fn new(sender: oneshot::Sender<T>) -> Self {
55 Self { inner: Mutex::new(Some(sender)) }
56 }
57
send(&self, value: T)58 fn send(&self, value: T) {
59 if let Some(inner) = self.inner.lock().unwrap().take() {
60 // It's possible for the corresponding receiver to time out and be dropped. In this
61 // case send() will fail. This error is not actionable though, so only log the error.
62 if inner.send(value).is_err() {
63 log::error!("SafeSender::send() failed");
64 }
65 }
66 }
67 }
68
69 struct GetRegistrationCallback {
70 registration_tx: SafeSender<Result<binder::Strong<dyn IRegistration>>>,
71 }
72
73 impl GetRegistrationCallback {
new_native_binder( registration_tx: oneshot::Sender<Result<binder::Strong<dyn IRegistration>>>, ) -> Strong<dyn IGetRegistrationCallback>74 pub fn new_native_binder(
75 registration_tx: oneshot::Sender<Result<binder::Strong<dyn IRegistration>>>,
76 ) -> Strong<dyn IGetRegistrationCallback> {
77 let result: Self =
78 GetRegistrationCallback { registration_tx: SafeSender::new(registration_tx) };
79 BnGetRegistrationCallback::new_binder(result, BinderFeatures::default())
80 }
81 }
82
83 impl Interface for GetRegistrationCallback {}
84
85 impl IGetRegistrationCallback for GetRegistrationCallback {
onSuccess(&self, registration: &Strong<dyn IRegistration>) -> binder::Result<()>86 fn onSuccess(&self, registration: &Strong<dyn IRegistration>) -> binder::Result<()> {
87 let _wp = wd::watch_millis("IGetRegistrationCallback::onSuccess", 500);
88 self.registration_tx.send(Ok(registration.clone()));
89 Ok(())
90 }
onCancel(&self) -> binder::Result<()>91 fn onCancel(&self) -> binder::Result<()> {
92 let _wp = wd::watch_millis("IGetRegistrationCallback::onCancel", 500);
93 log::warn!("IGetRegistrationCallback cancelled");
94 self.registration_tx.send(
95 Err(Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR))
96 .context(ks_err!("GetRegistrationCallback cancelled.")),
97 );
98 Ok(())
99 }
onError(&self, description: &str) -> binder::Result<()>100 fn onError(&self, description: &str) -> binder::Result<()> {
101 let _wp = wd::watch_millis("IGetRegistrationCallback::onError", 500);
102 log::error!("IGetRegistrationCallback failed: '{description}'");
103 self.registration_tx.send(
104 Err(Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR))
105 .context(ks_err!("GetRegistrationCallback failed: {:?}", description)),
106 );
107 Ok(())
108 }
109 }
110
111 /// Make a new connection to a IRegistration service.
get_rkpd_registration( security_level: &SecurityLevel, ) -> Result<binder::Strong<dyn IRegistration>>112 async fn get_rkpd_registration(
113 security_level: &SecurityLevel,
114 ) -> Result<binder::Strong<dyn IRegistration>> {
115 let remote_provisioning: Strong<dyn IRemoteProvisioning> =
116 map_binder_status_code(binder::get_interface("remote_provisioning"))
117 .context(ks_err!("Trying to connect to IRemoteProvisioning service."))?;
118
119 let rpc_name = get_remotely_provisioned_component_name(security_level)
120 .context(ks_err!("Trying to get IRPC name."))?;
121
122 let (tx, rx) = oneshot::channel();
123 let cb = GetRegistrationCallback::new_native_binder(tx);
124
125 remote_provisioning
126 .getRegistration(&rpc_name, &cb)
127 .context(ks_err!("Trying to get registration."))?;
128
129 match timeout(RKPD_TIMEOUT, rx).await {
130 Err(e) => {
131 Err(Error::Rc(ResponseCode::SYSTEM_ERROR)).context(ks_err!("Waiting for RKPD: {:?}", e))
132 }
133 Ok(v) => v.unwrap(),
134 }
135 }
136
137 struct GetKeyCallback {
138 key_tx: SafeSender<Result<RemotelyProvisionedKey>>,
139 }
140
141 impl GetKeyCallback {
new_native_binder( key_tx: oneshot::Sender<Result<RemotelyProvisionedKey>>, ) -> Strong<dyn IGetKeyCallback>142 pub fn new_native_binder(
143 key_tx: oneshot::Sender<Result<RemotelyProvisionedKey>>,
144 ) -> Strong<dyn IGetKeyCallback> {
145 let result: Self = GetKeyCallback { key_tx: SafeSender::new(key_tx) };
146 BnGetKeyCallback::new_binder(result, BinderFeatures::default())
147 }
148 }
149
150 impl Interface for GetKeyCallback {}
151
152 impl IGetKeyCallback for GetKeyCallback {
onSuccess(&self, key: &RemotelyProvisionedKey) -> binder::Result<()>153 fn onSuccess(&self, key: &RemotelyProvisionedKey) -> binder::Result<()> {
154 let _wp = wd::watch_millis("IGetKeyCallback::onSuccess", 500);
155 self.key_tx.send(Ok(RemotelyProvisionedKey {
156 keyBlob: key.keyBlob.clone(),
157 encodedCertChain: key.encodedCertChain.clone(),
158 }));
159 Ok(())
160 }
onCancel(&self) -> binder::Result<()>161 fn onCancel(&self) -> binder::Result<()> {
162 let _wp = wd::watch_millis("IGetKeyCallback::onCancel", 500);
163 log::warn!("IGetKeyCallback cancelled");
164 self.key_tx.send(
165 Err(Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR))
166 .context(ks_err!("GetKeyCallback cancelled.")),
167 );
168 Ok(())
169 }
onError(&self, error: GetKeyErrorCode, description: &str) -> binder::Result<()>170 fn onError(&self, error: GetKeyErrorCode, description: &str) -> binder::Result<()> {
171 let _wp = wd::watch_millis("IGetKeyCallback::onError", 500);
172 log::error!("IGetKeyCallback failed: {description}");
173 let rc = match error {
174 GetKeyErrorCode::ERROR_UNKNOWN => ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR,
175 GetKeyErrorCode::ERROR_PERMANENT => ResponseCode::OUT_OF_KEYS_PERMANENT_ERROR,
176 GetKeyErrorCode::ERROR_PENDING_INTERNET_CONNECTIVITY => {
177 ResponseCode::OUT_OF_KEYS_PENDING_INTERNET_CONNECTIVITY
178 }
179 GetKeyErrorCode::ERROR_REQUIRES_SECURITY_PATCH => {
180 ResponseCode::OUT_OF_KEYS_REQUIRES_SYSTEM_UPGRADE
181 }
182 _ => {
183 log::error!("Unexpected error from rkpd: {error:?}");
184 ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR
185 }
186 };
187 self.key_tx.send(Err(Error::Rc(rc)).context(ks_err!(
188 "GetKeyCallback failed: {:?} {:?}",
189 error,
190 description
191 )));
192 Ok(())
193 }
194 }
195
get_rkpd_attestation_key_from_registration_async( registration: &Strong<dyn IRegistration>, caller_uid: u32, ) -> Result<RemotelyProvisionedKey>196 async fn get_rkpd_attestation_key_from_registration_async(
197 registration: &Strong<dyn IRegistration>,
198 caller_uid: u32,
199 ) -> Result<RemotelyProvisionedKey> {
200 let (tx, rx) = oneshot::channel();
201 let cb = GetKeyCallback::new_native_binder(tx);
202
203 registration
204 .getKey(caller_uid.try_into().unwrap(), &cb)
205 .context(ks_err!("Trying to get key."))?;
206
207 match timeout(RKPD_TIMEOUT, rx).await {
208 Err(e) => {
209 // Make a best effort attempt to cancel the timed out request.
210 if let Err(e) = registration.cancelGetKey(&cb) {
211 log::error!("IRegistration::cancelGetKey failed: {:?}", e);
212 }
213 Err(Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR))
214 .context(ks_err!("Waiting for RKPD key timed out: {:?}", e))
215 }
216 Ok(v) => v.unwrap(),
217 }
218 }
219
get_rkpd_attestation_key_async( security_level: &SecurityLevel, caller_uid: u32, ) -> Result<RemotelyProvisionedKey>220 async fn get_rkpd_attestation_key_async(
221 security_level: &SecurityLevel,
222 caller_uid: u32,
223 ) -> Result<RemotelyProvisionedKey> {
224 let registration = get_rkpd_registration(security_level)
225 .await
226 .context(ks_err!("Trying to get to IRegistration service."))?;
227 get_rkpd_attestation_key_from_registration_async(®istration, caller_uid).await
228 }
229
230 struct StoreUpgradedKeyCallback {
231 completer: SafeSender<Result<()>>,
232 }
233
234 impl StoreUpgradedKeyCallback {
new_native_binder( completer: oneshot::Sender<Result<()>>, ) -> Strong<dyn IStoreUpgradedKeyCallback>235 pub fn new_native_binder(
236 completer: oneshot::Sender<Result<()>>,
237 ) -> Strong<dyn IStoreUpgradedKeyCallback> {
238 let result: Self = StoreUpgradedKeyCallback { completer: SafeSender::new(completer) };
239 BnStoreUpgradedKeyCallback::new_binder(result, BinderFeatures::default())
240 }
241 }
242
243 impl Interface for StoreUpgradedKeyCallback {}
244
245 impl IStoreUpgradedKeyCallback for StoreUpgradedKeyCallback {
onSuccess(&self) -> binder::Result<()>246 fn onSuccess(&self) -> binder::Result<()> {
247 let _wp = wd::watch_millis("IGetRegistrationCallback::onSuccess", 500);
248 self.completer.send(Ok(()));
249 Ok(())
250 }
251
onError(&self, error: &str) -> binder::Result<()>252 fn onError(&self, error: &str) -> binder::Result<()> {
253 let _wp = wd::watch_millis("IGetRegistrationCallback::onError", 500);
254 log::error!("IGetRegistrationCallback failed: {error}");
255 self.completer.send(
256 Err(Error::Rc(ResponseCode::SYSTEM_ERROR))
257 .context(ks_err!("Failed to store upgraded key: {:?}", error)),
258 );
259 Ok(())
260 }
261 }
262
store_rkpd_attestation_key_with_registration_async( registration: &Strong<dyn IRegistration>, key_blob: &[u8], upgraded_blob: &[u8], ) -> Result<()>263 async fn store_rkpd_attestation_key_with_registration_async(
264 registration: &Strong<dyn IRegistration>,
265 key_blob: &[u8],
266 upgraded_blob: &[u8],
267 ) -> Result<()> {
268 let (tx, rx) = oneshot::channel();
269 let cb = StoreUpgradedKeyCallback::new_native_binder(tx);
270
271 registration
272 .storeUpgradedKeyAsync(key_blob, upgraded_blob, &cb)
273 .context(ks_err!("Failed to store upgraded blob with RKPD."))?;
274
275 match timeout(RKPD_TIMEOUT, rx).await {
276 Err(e) => Err(Error::Rc(ResponseCode::SYSTEM_ERROR))
277 .context(ks_err!("Waiting for RKPD to complete storing key: {:?}", e)),
278 Ok(v) => v.unwrap(),
279 }
280 }
281
store_rkpd_attestation_key_async( security_level: &SecurityLevel, key_blob: &[u8], upgraded_blob: &[u8], ) -> Result<()>282 async fn store_rkpd_attestation_key_async(
283 security_level: &SecurityLevel,
284 key_blob: &[u8],
285 upgraded_blob: &[u8],
286 ) -> Result<()> {
287 let registration = get_rkpd_registration(security_level)
288 .await
289 .context(ks_err!("Trying to get to IRegistration service."))?;
290 store_rkpd_attestation_key_with_registration_async(®istration, key_blob, upgraded_blob).await
291 }
292
293 /// Get attestation key from RKPD.
get_rkpd_attestation_key( security_level: &SecurityLevel, caller_uid: u32, ) -> Result<RemotelyProvisionedKey>294 pub fn get_rkpd_attestation_key(
295 security_level: &SecurityLevel,
296 caller_uid: u32,
297 ) -> Result<RemotelyProvisionedKey> {
298 let _wp = wd::watch_millis("Calling get_rkpd_attestation_key()", 500);
299 tokio_rt().block_on(get_rkpd_attestation_key_async(security_level, caller_uid))
300 }
301
302 /// Store attestation key in RKPD.
store_rkpd_attestation_key( security_level: &SecurityLevel, key_blob: &[u8], upgraded_blob: &[u8], ) -> Result<()>303 pub fn store_rkpd_attestation_key(
304 security_level: &SecurityLevel,
305 key_blob: &[u8],
306 upgraded_blob: &[u8],
307 ) -> Result<()> {
308 let _wp = wd::watch_millis("Calling store_rkpd_attestation_key()", 500);
309 tokio_rt().block_on(store_rkpd_attestation_key_async(security_level, key_blob, upgraded_blob))
310 }
311
312 #[cfg(test)]
313 mod tests {
314 use super::*;
315 use crate::error::map_km_error;
316 use crate::globals::get_keymint_device;
317 use crate::utils::upgrade_keyblob_if_required_with;
318 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
319 Algorithm::Algorithm, AttestationKey::AttestationKey, KeyParameter::KeyParameter,
320 KeyParameterValue::KeyParameterValue, Tag::Tag,
321 };
322 use android_security_rkp_aidl::aidl::android::security::rkp::IRegistration::BnRegistration;
323 use keystore2_crypto::parse_subject_from_certificate;
324 use std::collections::HashMap;
325 use std::sync::atomic::{AtomicU32, Ordering};
326 use std::sync::{Arc, Mutex};
327
328 struct MockRegistrationValues {
329 key: RemotelyProvisionedKey,
330 latency: Option<Duration>,
331 thread_join_handles: Vec<Option<std::thread::JoinHandle<()>>>,
332 }
333
334 struct MockRegistration(Arc<Mutex<MockRegistrationValues>>);
335
336 impl MockRegistration {
new_native_binder( key: &RemotelyProvisionedKey, latency: Option<Duration>, ) -> Strong<dyn IRegistration>337 pub fn new_native_binder(
338 key: &RemotelyProvisionedKey,
339 latency: Option<Duration>,
340 ) -> Strong<dyn IRegistration> {
341 let result = Self(Arc::new(Mutex::new(MockRegistrationValues {
342 key: RemotelyProvisionedKey {
343 keyBlob: key.keyBlob.clone(),
344 encodedCertChain: key.encodedCertChain.clone(),
345 },
346 latency,
347 thread_join_handles: Vec::new(),
348 })));
349 BnRegistration::new_binder(result, BinderFeatures::default())
350 }
351 }
352
353 impl Drop for MockRegistration {
drop(&mut self)354 fn drop(&mut self) {
355 let mut values = self.0.lock().unwrap();
356 for handle in values.thread_join_handles.iter_mut() {
357 // These are test threads. So, no need to worry too much about error handling.
358 handle.take().unwrap().join().unwrap();
359 }
360 }
361 }
362
363 impl Interface for MockRegistration {}
364
365 impl IRegistration for MockRegistration {
getKey(&self, _: i32, cb: &Strong<dyn IGetKeyCallback>) -> binder::Result<()>366 fn getKey(&self, _: i32, cb: &Strong<dyn IGetKeyCallback>) -> binder::Result<()> {
367 let mut values = self.0.lock().unwrap();
368 let key = RemotelyProvisionedKey {
369 keyBlob: values.key.keyBlob.clone(),
370 encodedCertChain: values.key.encodedCertChain.clone(),
371 };
372 let latency = values.latency;
373 let get_key_cb = cb.clone();
374
375 // Need a separate thread to trigger timeout in the caller.
376 let join_handle = std::thread::spawn(move || {
377 if let Some(duration) = latency {
378 std::thread::sleep(duration);
379 }
380 get_key_cb.onSuccess(&key).unwrap();
381 });
382 values.thread_join_handles.push(Some(join_handle));
383 Ok(())
384 }
385
cancelGetKey(&self, _: &Strong<dyn IGetKeyCallback>) -> binder::Result<()>386 fn cancelGetKey(&self, _: &Strong<dyn IGetKeyCallback>) -> binder::Result<()> {
387 Ok(())
388 }
389
storeUpgradedKeyAsync( &self, _: &[u8], _: &[u8], cb: &Strong<dyn IStoreUpgradedKeyCallback>, ) -> binder::Result<()>390 fn storeUpgradedKeyAsync(
391 &self,
392 _: &[u8],
393 _: &[u8],
394 cb: &Strong<dyn IStoreUpgradedKeyCallback>,
395 ) -> binder::Result<()> {
396 // We are primarily concerned with timing out correctly. Storing the key in this mock
397 // registration isn't particularly interesting, so skip that part.
398 let values = self.0.lock().unwrap();
399 let store_cb = cb.clone();
400 let latency = values.latency;
401
402 std::thread::spawn(move || {
403 if let Some(duration) = latency {
404 std::thread::sleep(duration);
405 }
406 store_cb.onSuccess().unwrap();
407 });
408 Ok(())
409 }
410 }
411
get_mock_registration( key: &RemotelyProvisionedKey, latency: Option<Duration>, ) -> Result<binder::Strong<dyn IRegistration>>412 fn get_mock_registration(
413 key: &RemotelyProvisionedKey,
414 latency: Option<Duration>,
415 ) -> Result<binder::Strong<dyn IRegistration>> {
416 let (tx, rx) = oneshot::channel();
417 let cb = GetRegistrationCallback::new_native_binder(tx);
418 let mock_registration = MockRegistration::new_native_binder(key, latency);
419
420 assert!(cb.onSuccess(&mock_registration).is_ok());
421 tokio_rt().block_on(rx).unwrap()
422 }
423
424 // Using the same key ID makes test cases race with each other. So, we use separate key IDs for
425 // different test cases.
get_next_key_id() -> u32426 fn get_next_key_id() -> u32 {
427 static ID: AtomicU32 = AtomicU32::new(0);
428 ID.fetch_add(1, Ordering::Relaxed)
429 }
430
431 #[test]
test_get_registration_cb_success()432 fn test_get_registration_cb_success() {
433 let key: RemotelyProvisionedKey = Default::default();
434 let registration = get_mock_registration(&key, /*latency=*/ None);
435 assert!(registration.is_ok());
436 }
437
438 #[test]
test_get_registration_cb_cancel()439 fn test_get_registration_cb_cancel() {
440 let (tx, rx) = oneshot::channel();
441 let cb = GetRegistrationCallback::new_native_binder(tx);
442 assert!(cb.onCancel().is_ok());
443
444 let result = tokio_rt().block_on(rx).unwrap();
445 assert_eq!(
446 result.unwrap_err().downcast::<Error>().unwrap(),
447 Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR)
448 );
449 }
450
451 #[test]
test_get_registration_cb_error()452 fn test_get_registration_cb_error() {
453 let (tx, rx) = oneshot::channel();
454 let cb = GetRegistrationCallback::new_native_binder(tx);
455 assert!(cb.onError("error").is_ok());
456
457 let result = tokio_rt().block_on(rx).unwrap();
458 assert_eq!(
459 result.unwrap_err().downcast::<Error>().unwrap(),
460 Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR)
461 );
462 }
463
464 #[test]
test_get_key_cb_success()465 fn test_get_key_cb_success() {
466 let mock_key =
467 RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] };
468 let (tx, rx) = oneshot::channel();
469 let cb = GetKeyCallback::new_native_binder(tx);
470 assert!(cb.onSuccess(&mock_key).is_ok());
471
472 let key = tokio_rt().block_on(rx).unwrap().unwrap();
473 assert_eq!(key, mock_key);
474 }
475
476 #[test]
test_get_key_cb_cancel()477 fn test_get_key_cb_cancel() {
478 let (tx, rx) = oneshot::channel();
479 let cb = GetKeyCallback::new_native_binder(tx);
480 assert!(cb.onCancel().is_ok());
481
482 let result = tokio_rt().block_on(rx).unwrap();
483 assert_eq!(
484 result.unwrap_err().downcast::<Error>().unwrap(),
485 Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR)
486 );
487 }
488
489 #[test]
test_get_key_cb_error()490 fn test_get_key_cb_error() {
491 let error_mapping = HashMap::from([
492 (GetKeyErrorCode::ERROR_UNKNOWN, ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR),
493 (GetKeyErrorCode::ERROR_PERMANENT, ResponseCode::OUT_OF_KEYS_PERMANENT_ERROR),
494 (
495 GetKeyErrorCode::ERROR_PENDING_INTERNET_CONNECTIVITY,
496 ResponseCode::OUT_OF_KEYS_PENDING_INTERNET_CONNECTIVITY,
497 ),
498 (
499 GetKeyErrorCode::ERROR_REQUIRES_SECURITY_PATCH,
500 ResponseCode::OUT_OF_KEYS_REQUIRES_SYSTEM_UPGRADE,
501 ),
502 ]);
503
504 // Loop over the generated list of enum values to better ensure this test stays in
505 // sync with the AIDL.
506 for get_key_error in GetKeyErrorCode::enum_values() {
507 let (tx, rx) = oneshot::channel();
508 let cb = GetKeyCallback::new_native_binder(tx);
509 assert!(cb.onError(get_key_error, "error").is_ok());
510
511 let result = tokio_rt().block_on(rx).unwrap();
512 assert_eq!(
513 result.unwrap_err().downcast::<Error>().unwrap(),
514 Error::Rc(error_mapping[&get_key_error]),
515 );
516 }
517 }
518
519 #[test]
test_store_upgraded_cb_success()520 fn test_store_upgraded_cb_success() {
521 let (tx, rx) = oneshot::channel();
522 let cb = StoreUpgradedKeyCallback::new_native_binder(tx);
523 assert!(cb.onSuccess().is_ok());
524
525 tokio_rt().block_on(rx).unwrap().unwrap();
526 }
527
528 #[test]
test_store_upgraded_key_cb_error()529 fn test_store_upgraded_key_cb_error() {
530 let (tx, rx) = oneshot::channel();
531 let cb = StoreUpgradedKeyCallback::new_native_binder(tx);
532 assert!(cb.onError("oh no! it failed").is_ok());
533
534 let result = tokio_rt().block_on(rx).unwrap();
535 assert_eq!(
536 result.unwrap_err().downcast::<Error>().unwrap(),
537 Error::Rc(ResponseCode::SYSTEM_ERROR)
538 );
539 }
540
541 #[test]
test_get_mock_key_success()542 fn test_get_mock_key_success() {
543 let mock_key =
544 RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] };
545 let registration = get_mock_registration(&mock_key, /*latency=*/ None).unwrap();
546
547 let key = tokio_rt()
548 .block_on(get_rkpd_attestation_key_from_registration_async(®istration, 0))
549 .unwrap();
550 assert_eq!(key, mock_key);
551 }
552
553 #[test]
test_get_mock_key_timeout()554 fn test_get_mock_key_timeout() {
555 let mock_key =
556 RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] };
557 let latency = RKPD_TIMEOUT + Duration::from_secs(1);
558 let registration = get_mock_registration(&mock_key, Some(latency)).unwrap();
559
560 let result =
561 tokio_rt().block_on(get_rkpd_attestation_key_from_registration_async(®istration, 0));
562 assert_eq!(
563 result.unwrap_err().downcast::<Error>().unwrap(),
564 Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR)
565 );
566 }
567
568 #[test]
test_store_mock_key_success()569 fn test_store_mock_key_success() {
570 let mock_key =
571 RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] };
572 let registration = get_mock_registration(&mock_key, /*latency=*/ None).unwrap();
573 tokio_rt()
574 .block_on(store_rkpd_attestation_key_with_registration_async(®istration, &[], &[]))
575 .unwrap();
576 }
577
578 #[test]
test_store_mock_key_timeout()579 fn test_store_mock_key_timeout() {
580 let mock_key =
581 RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] };
582 let latency = RKPD_TIMEOUT + Duration::from_secs(1);
583 let registration = get_mock_registration(&mock_key, Some(latency)).unwrap();
584
585 let result = tokio_rt().block_on(store_rkpd_attestation_key_with_registration_async(
586 ®istration,
587 &[],
588 &[],
589 ));
590 assert_eq!(
591 result.unwrap_err().downcast::<Error>().unwrap(),
592 Error::Rc(ResponseCode::SYSTEM_ERROR)
593 );
594 }
595
596 #[test]
test_get_rkpd_attestation_key()597 fn test_get_rkpd_attestation_key() {
598 binder::ProcessState::start_thread_pool();
599 let key_id = get_next_key_id();
600 let key = get_rkpd_attestation_key(&SecurityLevel::TRUSTED_ENVIRONMENT, key_id).unwrap();
601 assert!(!key.keyBlob.is_empty());
602 assert!(!key.encodedCertChain.is_empty());
603 }
604
605 #[test]
test_get_rkpd_attestation_key_same_caller()606 fn test_get_rkpd_attestation_key_same_caller() {
607 binder::ProcessState::start_thread_pool();
608 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
609 let key_id = get_next_key_id();
610
611 // Multiple calls should return the same key.
612 let first_key = get_rkpd_attestation_key(&sec_level, key_id).unwrap();
613 let second_key = get_rkpd_attestation_key(&sec_level, key_id).unwrap();
614
615 assert_eq!(first_key.keyBlob, second_key.keyBlob);
616 assert_eq!(first_key.encodedCertChain, second_key.encodedCertChain);
617 }
618
619 #[test]
test_get_rkpd_attestation_key_different_caller()620 fn test_get_rkpd_attestation_key_different_caller() {
621 binder::ProcessState::start_thread_pool();
622 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
623 let first_key_id = get_next_key_id();
624 let second_key_id = get_next_key_id();
625
626 // Different callers should be getting different keys.
627 let first_key = get_rkpd_attestation_key(&sec_level, first_key_id).unwrap();
628 let second_key = get_rkpd_attestation_key(&sec_level, second_key_id).unwrap();
629
630 assert_ne!(first_key.keyBlob, second_key.keyBlob);
631 assert_ne!(first_key.encodedCertChain, second_key.encodedCertChain);
632 }
633
634 #[test]
635 // Couple of things to note:
636 // 1. This test must never run with UID of keystore. Otherwise, it can mess up keys stored by
637 // keystore.
638 // 2. Storing and reading the stored key is prone to race condition. So, we only do this in one
639 // test case.
test_store_rkpd_attestation_key()640 fn test_store_rkpd_attestation_key() {
641 binder::ProcessState::start_thread_pool();
642 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
643 let key_id = get_next_key_id();
644 let key = get_rkpd_attestation_key(&SecurityLevel::TRUSTED_ENVIRONMENT, key_id).unwrap();
645 let new_blob: [u8; 8] = rand::random();
646
647 assert!(store_rkpd_attestation_key(&sec_level, &key.keyBlob, &new_blob).is_ok());
648
649 let new_key =
650 get_rkpd_attestation_key(&SecurityLevel::TRUSTED_ENVIRONMENT, key_id).unwrap();
651
652 // Restore original key so that we don't leave RKPD with invalid blobs.
653 assert!(store_rkpd_attestation_key(&sec_level, &new_blob, &key.keyBlob).is_ok());
654 assert_eq!(new_key.keyBlob, new_blob);
655 }
656
657 #[test]
658 // This is a helper for a manual test. We want to check that after a system upgrade RKPD
659 // attestation keys can also be upgraded and stored again with RKPD. The steps are:
660 // 1. Run this test and check in stdout that no key upgrade happened.
661 // 2. Perform a system upgrade.
662 // 3. Run this test and check in stdout that key upgrade did happen.
663 //
664 // Note that this test must be run with that same UID every time. Running as root, i.e. UID 0,
665 // should do the trick. Also, use "--nocapture" flag to get stdout.
test_rkpd_attestation_key_upgrade()666 fn test_rkpd_attestation_key_upgrade() {
667 binder::ProcessState::start_thread_pool();
668 let security_level = SecurityLevel::TRUSTED_ENVIRONMENT;
669 let (keymint, _, _) = get_keymint_device(&security_level).unwrap();
670 let key_id = get_next_key_id();
671 let mut key_upgraded = false;
672
673 let key = get_rkpd_attestation_key(&security_level, key_id).unwrap();
674 assert!(!key.keyBlob.is_empty());
675 assert!(!key.encodedCertChain.is_empty());
676
677 upgrade_keyblob_if_required_with(
678 &*keymint,
679 &key.keyBlob,
680 /*upgrade_params=*/ &[],
681 /*km_op=*/
682 |blob| {
683 let params = vec![
684 KeyParameter {
685 tag: Tag::ALGORITHM,
686 value: KeyParameterValue::Algorithm(Algorithm::AES),
687 },
688 KeyParameter { tag: Tag::KEY_SIZE, value: KeyParameterValue::Integer(128) },
689 ];
690 let attestation_key = AttestationKey {
691 keyBlob: blob.to_vec(),
692 attestKeyParams: vec![],
693 issuerSubjectName: parse_subject_from_certificate(&key.encodedCertChain)
694 .unwrap(),
695 };
696
697 map_km_error(keymint.generateKey(¶ms, Some(&attestation_key)))
698 },
699 /*new_blob_handler=*/
700 |new_blob| {
701 // This handler is only executed if a key upgrade was performed.
702 key_upgraded = true;
703 store_rkpd_attestation_key(&security_level, &key.keyBlob, new_blob).unwrap();
704 Ok(())
705 },
706 )
707 .unwrap();
708
709 if key_upgraded {
710 println!("RKPD key was upgraded and stored with RKPD.");
711 } else {
712 println!("RKPD key was NOT upgraded.");
713 }
714 }
715
716 #[test]
test_stress_get_rkpd_attestation_key()717 fn test_stress_get_rkpd_attestation_key() {
718 binder::ProcessState::start_thread_pool();
719 let key_id = get_next_key_id();
720 let mut threads = vec![];
721 const NTHREADS: u32 = 10;
722 const NCALLS: u32 = 1000;
723
724 for _ in 0..NTHREADS {
725 threads.push(std::thread::spawn(move || {
726 for _ in 0..NCALLS {
727 let key = get_rkpd_attestation_key(&SecurityLevel::TRUSTED_ENVIRONMENT, key_id)
728 .unwrap();
729 assert!(!key.keyBlob.is_empty());
730 assert!(!key.encodedCertChain.is_empty());
731 }
732 }));
733 }
734
735 for t in threads {
736 assert!(t.join().is_ok());
737 }
738 }
739 }
740