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 android_security_rkp_aidl::aidl::android::security::rkp::{ 18 IGetKeyCallback::BnGetKeyCallback, IGetKeyCallback::ErrorCode::ErrorCode as GetKeyErrorCode, 19 IGetKeyCallback::IGetKeyCallback, IGetRegistrationCallback::BnGetRegistrationCallback, 20 IGetRegistrationCallback::IGetRegistrationCallback, IRegistration::IRegistration, 21 IRemoteProvisioning::IRemoteProvisioning, 22 IStoreUpgradedKeyCallback::BnStoreUpgradedKeyCallback, 23 IStoreUpgradedKeyCallback::IStoreUpgradedKeyCallback, 24 RemotelyProvisionedKey::RemotelyProvisionedKey, 25 }; 26 use anyhow::{Context, Result}; 27 use binder::{BinderFeatures, Interface, StatusCode, Strong}; 28 use message_macro::source_location_msg; 29 use std::sync::Mutex; 30 use std::time::Duration; 31 use tokio::sync::oneshot; 32 use tokio::time::timeout; 33 34 // Normally, we block indefinitely when making calls outside of keystore and rely on watchdog to 35 // report deadlocks. However, RKPD is mainline updatable. Also, calls to RKPD may wait on network 36 // for certificates. So, we err on the side of caution and timeout instead. 37 static RKPD_TIMEOUT: Duration = Duration::from_secs(10); 38 tokio_rt() -> tokio::runtime::Runtime39 fn tokio_rt() -> tokio::runtime::Runtime { 40 tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap() 41 } 42 43 /// Errors occurred during the interaction with RKPD. 44 #[derive(Debug, Clone, Copy, thiserror::Error, PartialEq, Eq)] 45 pub enum Error { 46 /// An RKPD request gets cancelled. 47 #[error("An RKPD request gets cancelled")] 48 RequestCancelled, 49 50 /// Failed to get registration. 51 #[error("Failed to get registration")] 52 GetRegistrationFailed, 53 54 /// Failed to get key. 55 #[error("Failed to get key: {0:?}")] 56 GetKeyFailed(GetKeyErrorCode), 57 58 /// Failed to store upgraded key. 59 #[error("Failed to store upgraded key")] 60 StoreUpgradedKeyFailed, 61 62 /// Retryable timeout when waiting for a callback. 63 #[error("Retryable timeout when waiting for a callback")] 64 RetryableTimeout, 65 66 /// Timeout when waiting for a callback. 67 #[error("Timeout when waiting for a callback")] 68 Timeout, 69 70 /// Wraps a Binder status code. 71 #[error("Binder transaction error {0:?}")] 72 BinderTransaction(StatusCode), 73 } 74 75 impl From<StatusCode> for Error { from(s: StatusCode) -> Self76 fn from(s: StatusCode) -> Self { 77 Self::BinderTransaction(s) 78 } 79 } 80 81 /// Thread-safe channel for sending a value once and only once. If a value has 82 /// already been send, subsequent calls to send will noop. 83 struct SafeSender<T> { 84 inner: Mutex<Option<oneshot::Sender<T>>>, 85 } 86 87 impl<T> SafeSender<T> { new(sender: oneshot::Sender<T>) -> Self88 fn new(sender: oneshot::Sender<T>) -> Self { 89 Self { inner: Mutex::new(Some(sender)) } 90 } 91 send(&self, value: T)92 fn send(&self, value: T) { 93 if let Some(inner) = self.inner.lock().unwrap().take() { 94 // It's possible for the corresponding receiver to time out and be dropped. In this 95 // case send() will fail. This error is not actionable though, so only log the error. 96 if inner.send(value).is_err() { 97 log::error!("SafeSender::send() failed"); 98 } 99 } 100 } 101 } 102 103 struct GetRegistrationCallback { 104 registration_tx: SafeSender<Result<binder::Strong<dyn IRegistration>>>, 105 } 106 107 impl GetRegistrationCallback { new_native_binder( registration_tx: oneshot::Sender<Result<binder::Strong<dyn IRegistration>>>, ) -> Strong<dyn IGetRegistrationCallback>108 pub fn new_native_binder( 109 registration_tx: oneshot::Sender<Result<binder::Strong<dyn IRegistration>>>, 110 ) -> Strong<dyn IGetRegistrationCallback> { 111 let result: Self = 112 GetRegistrationCallback { registration_tx: SafeSender::new(registration_tx) }; 113 BnGetRegistrationCallback::new_binder(result, BinderFeatures::default()) 114 } 115 } 116 117 impl Interface for GetRegistrationCallback {} 118 119 impl IGetRegistrationCallback for GetRegistrationCallback { onSuccess(&self, registration: &Strong<dyn IRegistration>) -> binder::Result<()>120 fn onSuccess(&self, registration: &Strong<dyn IRegistration>) -> binder::Result<()> { 121 self.registration_tx.send(Ok(registration.clone())); 122 Ok(()) 123 } onCancel(&self) -> binder::Result<()>124 fn onCancel(&self) -> binder::Result<()> { 125 log::warn!("IGetRegistrationCallback cancelled"); 126 self.registration_tx.send( 127 Err(Error::RequestCancelled) 128 .context(source_location_msg!("GetRegistrationCallback cancelled.")), 129 ); 130 Ok(()) 131 } onError(&self, description: &str) -> binder::Result<()>132 fn onError(&self, description: &str) -> binder::Result<()> { 133 log::error!("IGetRegistrationCallback failed: '{description}'"); 134 self.registration_tx.send( 135 Err(Error::GetRegistrationFailed) 136 .context(source_location_msg!("GetRegistrationCallback failed: {:?}", description)), 137 ); 138 Ok(()) 139 } 140 } 141 142 /// Make a new connection to a IRegistration service. get_rkpd_registration(rpc_name: &str) -> Result<binder::Strong<dyn IRegistration>>143 async fn get_rkpd_registration(rpc_name: &str) -> Result<binder::Strong<dyn IRegistration>> { 144 let remote_provisioning: Strong<dyn IRemoteProvisioning> = 145 binder::get_interface("remote_provisioning") 146 .map_err(Error::from) 147 .context(source_location_msg!("Trying to connect to IRemoteProvisioning service."))?; 148 149 let (tx, rx) = oneshot::channel(); 150 let cb = GetRegistrationCallback::new_native_binder(tx); 151 152 remote_provisioning 153 .getRegistration(rpc_name, &cb) 154 .context(source_location_msg!("Trying to get registration."))?; 155 156 match timeout(RKPD_TIMEOUT, rx).await { 157 Err(e) => Err(Error::Timeout).context(source_location_msg!("Waiting for RKPD: {:?}", e)), 158 Ok(v) => v.unwrap(), 159 } 160 } 161 162 struct GetKeyCallback { 163 key_tx: SafeSender<Result<RemotelyProvisionedKey>>, 164 } 165 166 impl GetKeyCallback { new_native_binder( key_tx: oneshot::Sender<Result<RemotelyProvisionedKey>>, ) -> Strong<dyn IGetKeyCallback>167 pub fn new_native_binder( 168 key_tx: oneshot::Sender<Result<RemotelyProvisionedKey>>, 169 ) -> Strong<dyn IGetKeyCallback> { 170 let result: Self = GetKeyCallback { key_tx: SafeSender::new(key_tx) }; 171 BnGetKeyCallback::new_binder(result, BinderFeatures::default()) 172 } 173 } 174 175 impl Interface for GetKeyCallback {} 176 177 impl IGetKeyCallback for GetKeyCallback { onSuccess(&self, key: &RemotelyProvisionedKey) -> binder::Result<()>178 fn onSuccess(&self, key: &RemotelyProvisionedKey) -> binder::Result<()> { 179 self.key_tx.send(Ok(RemotelyProvisionedKey { 180 keyBlob: key.keyBlob.clone(), 181 encodedCertChain: key.encodedCertChain.clone(), 182 })); 183 Ok(()) 184 } onCancel(&self) -> binder::Result<()>185 fn onCancel(&self) -> binder::Result<()> { 186 log::warn!("IGetKeyCallback cancelled"); 187 self.key_tx.send( 188 Err(Error::RequestCancelled).context(source_location_msg!("GetKeyCallback cancelled.")), 189 ); 190 Ok(()) 191 } onError(&self, error: GetKeyErrorCode, description: &str) -> binder::Result<()>192 fn onError(&self, error: GetKeyErrorCode, description: &str) -> binder::Result<()> { 193 log::error!("IGetKeyCallback failed: {description}"); 194 self.key_tx.send(Err(Error::GetKeyFailed(error)).context(source_location_msg!( 195 "GetKeyCallback failed: {:?} {:?}", 196 error, 197 description 198 ))); 199 Ok(()) 200 } 201 } 202 get_rkpd_attestation_key_from_registration_async( registration: &Strong<dyn IRegistration>, caller_uid: u32, ) -> Result<RemotelyProvisionedKey>203 async fn get_rkpd_attestation_key_from_registration_async( 204 registration: &Strong<dyn IRegistration>, 205 caller_uid: u32, 206 ) -> Result<RemotelyProvisionedKey> { 207 let (tx, rx) = oneshot::channel(); 208 let cb = GetKeyCallback::new_native_binder(tx); 209 210 registration 211 .getKey(caller_uid.try_into().unwrap(), &cb) 212 .context(source_location_msg!("Trying to get key."))?; 213 214 match timeout(RKPD_TIMEOUT, rx).await { 215 Err(e) => { 216 // Make a best effort attempt to cancel the timed out request. 217 if let Err(e) = registration.cancelGetKey(&cb) { 218 log::error!("IRegistration::cancelGetKey failed: {:?}", e); 219 } 220 Err(Error::RetryableTimeout) 221 .context(source_location_msg!("Waiting for RKPD key timed out: {:?}", e)) 222 } 223 Ok(v) => v.unwrap(), 224 } 225 } 226 get_rkpd_attestation_key_async( rpc_name: &str, caller_uid: u32, ) -> Result<RemotelyProvisionedKey>227 async fn get_rkpd_attestation_key_async( 228 rpc_name: &str, 229 caller_uid: u32, 230 ) -> Result<RemotelyProvisionedKey> { 231 let registration = get_rkpd_registration(rpc_name) 232 .await 233 .context(source_location_msg!("Trying to get to IRegistration service."))?; 234 get_rkpd_attestation_key_from_registration_async(®istration, caller_uid).await 235 } 236 237 struct StoreUpgradedKeyCallback { 238 completer: SafeSender<Result<()>>, 239 } 240 241 impl StoreUpgradedKeyCallback { new_native_binder( completer: oneshot::Sender<Result<()>>, ) -> Strong<dyn IStoreUpgradedKeyCallback>242 pub fn new_native_binder( 243 completer: oneshot::Sender<Result<()>>, 244 ) -> Strong<dyn IStoreUpgradedKeyCallback> { 245 let result: Self = StoreUpgradedKeyCallback { completer: SafeSender::new(completer) }; 246 BnStoreUpgradedKeyCallback::new_binder(result, BinderFeatures::default()) 247 } 248 } 249 250 impl Interface for StoreUpgradedKeyCallback {} 251 252 impl IStoreUpgradedKeyCallback for StoreUpgradedKeyCallback { onSuccess(&self) -> binder::Result<()>253 fn onSuccess(&self) -> binder::Result<()> { 254 self.completer.send(Ok(())); 255 Ok(()) 256 } 257 onError(&self, error: &str) -> binder::Result<()>258 fn onError(&self, error: &str) -> binder::Result<()> { 259 log::error!("IStoreUpgradedKeyCallback failed: {error}"); 260 self.completer.send( 261 Err(Error::StoreUpgradedKeyFailed) 262 .context(source_location_msg!("Failed to store upgraded key: {:?}", error)), 263 ); 264 Ok(()) 265 } 266 } 267 store_rkpd_attestation_key_with_registration_async( registration: &Strong<dyn IRegistration>, key_blob: &[u8], upgraded_blob: &[u8], ) -> Result<()>268 async fn store_rkpd_attestation_key_with_registration_async( 269 registration: &Strong<dyn IRegistration>, 270 key_blob: &[u8], 271 upgraded_blob: &[u8], 272 ) -> Result<()> { 273 let (tx, rx) = oneshot::channel(); 274 let cb = StoreUpgradedKeyCallback::new_native_binder(tx); 275 276 registration 277 .storeUpgradedKeyAsync(key_blob, upgraded_blob, &cb) 278 .context(source_location_msg!("Failed to store upgraded blob with RKPD."))?; 279 280 match timeout(RKPD_TIMEOUT, rx).await { 281 Err(e) => Err(Error::Timeout) 282 .context(source_location_msg!("Waiting for RKPD to complete storing key: {:?}", e)), 283 Ok(v) => v.unwrap(), 284 } 285 } 286 store_rkpd_attestation_key_async( rpc_name: &str, key_blob: &[u8], upgraded_blob: &[u8], ) -> Result<()>287 async fn store_rkpd_attestation_key_async( 288 rpc_name: &str, 289 key_blob: &[u8], 290 upgraded_blob: &[u8], 291 ) -> Result<()> { 292 let registration = get_rkpd_registration(rpc_name) 293 .await 294 .context(source_location_msg!("Trying to get to IRegistration service."))?; 295 store_rkpd_attestation_key_with_registration_async(®istration, key_blob, upgraded_blob).await 296 } 297 298 /// Get attestation key from RKPD. get_rkpd_attestation_key(rpc_name: &str, caller_uid: u32) -> Result<RemotelyProvisionedKey>299 pub fn get_rkpd_attestation_key(rpc_name: &str, caller_uid: u32) -> Result<RemotelyProvisionedKey> { 300 tokio_rt().block_on(get_rkpd_attestation_key_async(rpc_name, caller_uid)) 301 } 302 303 /// Store attestation key in RKPD. store_rkpd_attestation_key( rpc_name: &str, key_blob: &[u8], upgraded_blob: &[u8], ) -> Result<()>304 pub fn store_rkpd_attestation_key( 305 rpc_name: &str, 306 key_blob: &[u8], 307 upgraded_blob: &[u8], 308 ) -> Result<()> { 309 tokio_rt().block_on(store_rkpd_attestation_key_async(rpc_name, key_blob, upgraded_blob)) 310 } 311 312 #[cfg(test)] 313 mod tests { 314 use super::*; 315 use android_security_rkp_aidl::aidl::android::security::rkp::IRegistration::BnRegistration; 316 use std::sync::atomic::{AtomicU32, Ordering}; 317 use std::sync::{Arc, Mutex}; 318 319 const DEFAULT_RPC_SERVICE_NAME: &str = 320 "android.hardware.security.keymint.IRemotelyProvisionedComponent/default"; 321 322 struct MockRegistrationValues { 323 key: RemotelyProvisionedKey, 324 latency: Option<Duration>, 325 thread_join_handles: Vec<Option<std::thread::JoinHandle<()>>>, 326 } 327 328 struct MockRegistration(Arc<Mutex<MockRegistrationValues>>); 329 330 impl MockRegistration { new_native_binder( key: &RemotelyProvisionedKey, latency: Option<Duration>, ) -> Strong<dyn IRegistration>331 pub fn new_native_binder( 332 key: &RemotelyProvisionedKey, 333 latency: Option<Duration>, 334 ) -> Strong<dyn IRegistration> { 335 let result = Self(Arc::new(Mutex::new(MockRegistrationValues { 336 key: RemotelyProvisionedKey { 337 keyBlob: key.keyBlob.clone(), 338 encodedCertChain: key.encodedCertChain.clone(), 339 }, 340 latency, 341 thread_join_handles: Vec::new(), 342 }))); 343 BnRegistration::new_binder(result, BinderFeatures::default()) 344 } 345 } 346 347 impl Drop for MockRegistration { drop(&mut self)348 fn drop(&mut self) { 349 let mut values = self.0.lock().unwrap(); 350 for handle in values.thread_join_handles.iter_mut() { 351 // These are test threads. So, no need to worry too much about error handling. 352 handle.take().unwrap().join().unwrap(); 353 } 354 } 355 } 356 357 impl Interface for MockRegistration {} 358 359 impl IRegistration for MockRegistration { getKey(&self, _: i32, cb: &Strong<dyn IGetKeyCallback>) -> binder::Result<()>360 fn getKey(&self, _: i32, cb: &Strong<dyn IGetKeyCallback>) -> binder::Result<()> { 361 let mut values = self.0.lock().unwrap(); 362 let key = RemotelyProvisionedKey { 363 keyBlob: values.key.keyBlob.clone(), 364 encodedCertChain: values.key.encodedCertChain.clone(), 365 }; 366 let latency = values.latency; 367 let get_key_cb = cb.clone(); 368 369 // Need a separate thread to trigger timeout in the caller. 370 let join_handle = std::thread::spawn(move || { 371 if let Some(duration) = latency { 372 std::thread::sleep(duration); 373 } 374 get_key_cb.onSuccess(&key).unwrap(); 375 }); 376 values.thread_join_handles.push(Some(join_handle)); 377 Ok(()) 378 } 379 cancelGetKey(&self, _: &Strong<dyn IGetKeyCallback>) -> binder::Result<()>380 fn cancelGetKey(&self, _: &Strong<dyn IGetKeyCallback>) -> binder::Result<()> { 381 Ok(()) 382 } 383 storeUpgradedKeyAsync( &self, _: &[u8], _: &[u8], cb: &Strong<dyn IStoreUpgradedKeyCallback>, ) -> binder::Result<()>384 fn storeUpgradedKeyAsync( 385 &self, 386 _: &[u8], 387 _: &[u8], 388 cb: &Strong<dyn IStoreUpgradedKeyCallback>, 389 ) -> binder::Result<()> { 390 // We are primarily concerned with timing out correctly. Storing the key in this mock 391 // registration isn't particularly interesting, so skip that part. 392 let values = self.0.lock().unwrap(); 393 let store_cb = cb.clone(); 394 let latency = values.latency; 395 396 std::thread::spawn(move || { 397 if let Some(duration) = latency { 398 std::thread::sleep(duration); 399 } 400 store_cb.onSuccess().unwrap(); 401 }); 402 Ok(()) 403 } 404 } 405 get_mock_registration( key: &RemotelyProvisionedKey, latency: Option<Duration>, ) -> Result<binder::Strong<dyn IRegistration>>406 fn get_mock_registration( 407 key: &RemotelyProvisionedKey, 408 latency: Option<Duration>, 409 ) -> Result<binder::Strong<dyn IRegistration>> { 410 let (tx, rx) = oneshot::channel(); 411 let cb = GetRegistrationCallback::new_native_binder(tx); 412 let mock_registration = MockRegistration::new_native_binder(key, latency); 413 414 assert!(cb.onSuccess(&mock_registration).is_ok()); 415 tokio_rt().block_on(rx).unwrap() 416 } 417 418 // Using the same key ID makes test cases race with each other. So, we use separate key IDs for 419 // different test cases. get_next_key_id() -> u32420 fn get_next_key_id() -> u32 { 421 static ID: AtomicU32 = AtomicU32::new(0); 422 ID.fetch_add(1, Ordering::Relaxed) 423 } 424 425 #[test] test_get_registration_cb_success()426 fn test_get_registration_cb_success() { 427 let key: RemotelyProvisionedKey = Default::default(); 428 let registration = get_mock_registration(&key, /*latency=*/ None); 429 assert!(registration.is_ok()); 430 } 431 432 #[test] test_get_registration_cb_cancel()433 fn test_get_registration_cb_cancel() { 434 let (tx, rx) = oneshot::channel(); 435 let cb = GetRegistrationCallback::new_native_binder(tx); 436 assert!(cb.onCancel().is_ok()); 437 438 let result = tokio_rt().block_on(rx).unwrap(); 439 assert_eq!(result.unwrap_err().downcast::<Error>().unwrap(), Error::RequestCancelled); 440 } 441 442 #[test] test_get_registration_cb_error()443 fn test_get_registration_cb_error() { 444 let (tx, rx) = oneshot::channel(); 445 let cb = GetRegistrationCallback::new_native_binder(tx); 446 assert!(cb.onError("error").is_ok()); 447 448 let result = tokio_rt().block_on(rx).unwrap(); 449 assert_eq!(result.unwrap_err().downcast::<Error>().unwrap(), Error::GetRegistrationFailed); 450 } 451 452 #[test] test_get_key_cb_success()453 fn test_get_key_cb_success() { 454 let mock_key = 455 RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] }; 456 let (tx, rx) = oneshot::channel(); 457 let cb = GetKeyCallback::new_native_binder(tx); 458 assert!(cb.onSuccess(&mock_key).is_ok()); 459 460 let key = tokio_rt().block_on(rx).unwrap().unwrap(); 461 assert_eq!(key, mock_key); 462 } 463 464 #[test] test_get_key_cb_cancel()465 fn test_get_key_cb_cancel() { 466 let (tx, rx) = oneshot::channel(); 467 let cb = GetKeyCallback::new_native_binder(tx); 468 assert!(cb.onCancel().is_ok()); 469 470 let result = tokio_rt().block_on(rx).unwrap(); 471 assert_eq!(result.unwrap_err().downcast::<Error>().unwrap(), Error::RequestCancelled); 472 } 473 474 #[test] test_get_key_cb_error()475 fn test_get_key_cb_error() { 476 for get_key_error in GetKeyErrorCode::enum_values() { 477 let (tx, rx) = oneshot::channel(); 478 let cb = GetKeyCallback::new_native_binder(tx); 479 assert!(cb.onError(get_key_error, "error").is_ok()); 480 481 let result = tokio_rt().block_on(rx).unwrap(); 482 assert_eq!( 483 result.unwrap_err().downcast::<Error>().unwrap(), 484 Error::GetKeyFailed(get_key_error), 485 ); 486 } 487 } 488 489 #[test] test_store_upgraded_cb_success()490 fn test_store_upgraded_cb_success() { 491 let (tx, rx) = oneshot::channel(); 492 let cb = StoreUpgradedKeyCallback::new_native_binder(tx); 493 assert!(cb.onSuccess().is_ok()); 494 495 tokio_rt().block_on(rx).unwrap().unwrap(); 496 } 497 498 #[test] test_store_upgraded_key_cb_error()499 fn test_store_upgraded_key_cb_error() { 500 let (tx, rx) = oneshot::channel(); 501 let cb = StoreUpgradedKeyCallback::new_native_binder(tx); 502 assert!(cb.onError("oh no! it failed").is_ok()); 503 504 let result = tokio_rt().block_on(rx).unwrap(); 505 assert_eq!(result.unwrap_err().downcast::<Error>().unwrap(), Error::StoreUpgradedKeyFailed); 506 } 507 508 #[test] test_get_mock_key_success()509 fn test_get_mock_key_success() { 510 let mock_key = 511 RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] }; 512 let registration = get_mock_registration(&mock_key, /*latency=*/ None).unwrap(); 513 514 let key = tokio_rt() 515 .block_on(get_rkpd_attestation_key_from_registration_async(®istration, 0)) 516 .unwrap(); 517 assert_eq!(key, mock_key); 518 } 519 520 #[test] test_get_mock_key_timeout()521 fn test_get_mock_key_timeout() { 522 let mock_key = 523 RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] }; 524 let latency = RKPD_TIMEOUT + Duration::from_secs(1); 525 let registration = get_mock_registration(&mock_key, Some(latency)).unwrap(); 526 527 let result = 528 tokio_rt().block_on(get_rkpd_attestation_key_from_registration_async(®istration, 0)); 529 assert_eq!(result.unwrap_err().downcast::<Error>().unwrap(), Error::RetryableTimeout); 530 } 531 532 #[test] test_store_mock_key_success()533 fn test_store_mock_key_success() { 534 let mock_key = 535 RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] }; 536 let registration = get_mock_registration(&mock_key, /*latency=*/ None).unwrap(); 537 tokio_rt() 538 .block_on(store_rkpd_attestation_key_with_registration_async(®istration, &[], &[])) 539 .unwrap(); 540 } 541 542 #[test] test_store_mock_key_timeout()543 fn test_store_mock_key_timeout() { 544 let mock_key = 545 RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] }; 546 let latency = RKPD_TIMEOUT + Duration::from_secs(1); 547 let registration = get_mock_registration(&mock_key, Some(latency)).unwrap(); 548 549 let result = tokio_rt().block_on(store_rkpd_attestation_key_with_registration_async( 550 ®istration, 551 &[], 552 &[], 553 )); 554 assert_eq!(result.unwrap_err().downcast::<Error>().unwrap(), Error::Timeout); 555 } 556 557 #[test] test_get_rkpd_attestation_key()558 fn test_get_rkpd_attestation_key() { 559 binder::ProcessState::start_thread_pool(); 560 let key_id = get_next_key_id(); 561 let key = get_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, key_id).unwrap(); 562 assert!(!key.keyBlob.is_empty()); 563 assert!(!key.encodedCertChain.is_empty()); 564 } 565 566 #[test] test_get_rkpd_attestation_key_same_caller()567 fn test_get_rkpd_attestation_key_same_caller() { 568 binder::ProcessState::start_thread_pool(); 569 let key_id = get_next_key_id(); 570 571 // Multiple calls should return the same key. 572 let first_key = get_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, key_id).unwrap(); 573 let second_key = get_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, key_id).unwrap(); 574 575 assert_eq!(first_key.keyBlob, second_key.keyBlob); 576 assert_eq!(first_key.encodedCertChain, second_key.encodedCertChain); 577 } 578 579 #[test] test_get_rkpd_attestation_key_different_caller()580 fn test_get_rkpd_attestation_key_different_caller() { 581 binder::ProcessState::start_thread_pool(); 582 let first_key_id = get_next_key_id(); 583 let second_key_id = get_next_key_id(); 584 585 // Different callers should be getting different keys. 586 let first_key = get_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, first_key_id).unwrap(); 587 let second_key = get_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, second_key_id).unwrap(); 588 589 assert_ne!(first_key.keyBlob, second_key.keyBlob); 590 assert_ne!(first_key.encodedCertChain, second_key.encodedCertChain); 591 } 592 593 #[test] 594 // Couple of things to note: 595 // 1. This test must never run with UID of keystore. Otherwise, it can mess up keys stored by 596 // keystore. 597 // 2. Storing and reading the stored key is prone to race condition. So, we only do this in one 598 // test case. test_store_rkpd_attestation_key()599 fn test_store_rkpd_attestation_key() { 600 binder::ProcessState::start_thread_pool(); 601 let key_id = get_next_key_id(); 602 let key = get_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, key_id).unwrap(); 603 let new_blob: [u8; 8] = rand::random(); 604 605 assert!( 606 store_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, &key.keyBlob, &new_blob).is_ok() 607 ); 608 609 let new_key = get_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, key_id).unwrap(); 610 611 // Restore original key so that we don't leave RKPD with invalid blobs. 612 assert!( 613 store_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, &new_blob, &key.keyBlob).is_ok() 614 ); 615 assert_eq!(new_key.keyBlob, new_blob); 616 } 617 618 #[test] test_stress_get_rkpd_attestation_key()619 fn test_stress_get_rkpd_attestation_key() { 620 binder::ProcessState::start_thread_pool(); 621 let key_id = get_next_key_id(); 622 let mut threads = vec![]; 623 const NTHREADS: u32 = 10; 624 const NCALLS: u32 = 1000; 625 626 for _ in 0..NTHREADS { 627 threads.push(std::thread::spawn(move || { 628 for _ in 0..NCALLS { 629 let key = get_rkpd_attestation_key(DEFAULT_RPC_SERVICE_NAME, key_id).unwrap(); 630 assert!(!key.keyBlob.is_empty()); 631 assert!(!key.encodedCertChain.is_empty()); 632 } 633 })); 634 } 635 636 for t in threads { 637 assert!(t.join().is_ok()); 638 } 639 } 640 } 641