Merge "Keystore 2.0: Implement storage key upgrade on demand."
diff --git a/keystore2/src/apc.rs b/keystore2/src/apc.rs
index 46b71dd..848b770 100644
--- a/keystore2/src/apc.rs
+++ b/keystore2/src/apc.rs
@@ -28,10 +28,10 @@
     ResponseCode::ResponseCode,
 };
 use android_security_apc::binder::{
-    ExceptionCode, Interface, Result as BinderResult, SpIBinder, Status as BinderStatus, Strong,
+    BinderFeatures, ExceptionCode, Interface, Result as BinderResult, SpIBinder,
+    Status as BinderStatus, Strong, ThreadState,
 };
 use anyhow::{Context, Result};
-use binder::{IBinderInternal, ThreadState};
 use keystore2_apc_compat::ApcHal;
 use keystore2_selinux as selinux;
 use std::time::{Duration, Instant};
@@ -203,11 +203,10 @@
     pub fn new_native_binder(
         confirmation_token_sender: Sender<Vec<u8>>,
     ) -> Result<Strong<dyn IProtectedConfirmation>> {
-        let result = BnProtectedConfirmation::new_binder(Self {
-            state: Arc::new(Mutex::new(ApcState::new(confirmation_token_sender))),
-        });
-        result.as_binder().set_requesting_sid(true);
-        Ok(result)
+        Ok(BnProtectedConfirmation::new_binder(
+            Self { state: Arc::new(Mutex::new(ApcState::new(confirmation_token_sender))) },
+            BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
+        ))
     }
 
     fn result(
diff --git a/keystore2/src/authorization.rs b/keystore2/src/authorization.rs
index 06b5598..ec1edff 100644
--- a/keystore2/src/authorization.rs
+++ b/keystore2/src/authorization.rs
@@ -22,7 +22,7 @@
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
     HardwareAuthToken::HardwareAuthToken,
 };
-use android_security_authorization::binder::{ExceptionCode, Interface, Result as BinderResult,
+use android_security_authorization::binder::{BinderFeatures,ExceptionCode, Interface, Result as BinderResult,
      Strong, Status as BinderStatus};
 use android_security_authorization::aidl::android::security::authorization::{
     IKeystoreAuthorization::BnKeystoreAuthorization, IKeystoreAuthorization::IKeystoreAuthorization,
@@ -32,7 +32,6 @@
 use android_system_keystore2::aidl::android::system::keystore2::{
     ResponseCode::ResponseCode as KsResponseCode };
 use anyhow::{Context, Result};
-use binder::IBinderInternal;
 use keystore2_crypto::Password;
 use keystore2_selinux as selinux;
 
@@ -112,13 +111,14 @@
 impl AuthorizationManager {
     /// Create a new instance of Keystore Authorization service.
     pub fn new_native_binder() -> Result<Strong<dyn IKeystoreAuthorization>> {
-        let result = BnKeystoreAuthorization::new_binder(Self);
-        result.as_binder().set_requesting_sid(true);
-        Ok(result)
+        Ok(BnKeystoreAuthorization::new_binder(
+            Self,
+            BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
+        ))
     }
 
     fn add_auth_token(&self, auth_token: &HardwareAuthToken) -> Result<()> {
-        //check keystore permission
+        // Check keystore permission.
         check_keystore_permission(KeystorePerm::add_auth()).context("In add_auth_token.")?;
 
         ENFORCEMENTS.add_auth_token(auth_token.clone())?;
@@ -133,8 +133,8 @@
     ) -> Result<()> {
         match (lock_screen_event, password) {
             (LockScreenEvent::UNLOCK, Some(password)) => {
-                //This corresponds to the unlock() method in legacy keystore API.
-                //check permission
+                // This corresponds to the unlock() method in legacy keystore API.
+                // check permission
                 check_keystore_permission(KeystorePerm::unlock())
                     .context("In on_lock_screen_event: Unlock with password.")?;
                 ENFORCEMENTS.set_device_locked(user_id, false);
@@ -201,7 +201,7 @@
         check_keystore_permission(KeystorePerm::get_auth_token())
             .context("In get_auth_tokens_for_credstore.")?;
 
-        // if the challenge is zero, return error
+        // If the challenge is zero, return error
         if challenge == 0 {
             return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT))
                 .context("In get_auth_tokens_for_credstore. Challenge can not be zero.");
diff --git a/keystore2/src/enforcements.rs b/keystore2/src/enforcements.rs
index 7993c88..378b72f 100644
--- a/keystore2/src/enforcements.rs
+++ b/keystore2/src/enforcements.rs
@@ -61,47 +61,54 @@
     state: AuthRequestState,
     /// This need to be set to Some to fulfill a AuthRequestState::OpAuth or
     /// AuthRequestState::TimeStampedOpAuth.
-    hat: Option<HardwareAuthToken>,
+    hat: Mutex<Option<HardwareAuthToken>>,
 }
 
+unsafe impl Sync for AuthRequest {}
+
 impl AuthRequest {
-    fn op_auth() -> Arc<Mutex<Self>> {
-        Arc::new(Mutex::new(Self { state: AuthRequestState::OpAuth, hat: None }))
+    fn op_auth() -> Arc<Self> {
+        Arc::new(Self { state: AuthRequestState::OpAuth, hat: Mutex::new(None) })
     }
 
-    fn timestamped_op_auth(receiver: Receiver<Result<TimeStampToken, Error>>) -> Arc<Mutex<Self>> {
-        Arc::new(Mutex::new(Self {
+    fn timestamped_op_auth(receiver: Receiver<Result<TimeStampToken, Error>>) -> Arc<Self> {
+        Arc::new(Self {
             state: AuthRequestState::TimeStampedOpAuth(receiver),
-            hat: None,
-        }))
+            hat: Mutex::new(None),
+        })
     }
 
     fn timestamp(
         hat: HardwareAuthToken,
         receiver: Receiver<Result<TimeStampToken, Error>>,
-    ) -> Arc<Mutex<Self>> {
-        Arc::new(Mutex::new(Self { state: AuthRequestState::TimeStamp(receiver), hat: Some(hat) }))
+    ) -> Arc<Self> {
+        Arc::new(Self { state: AuthRequestState::TimeStamp(receiver), hat: Mutex::new(Some(hat)) })
     }
 
-    fn add_auth_token(&mut self, hat: HardwareAuthToken) {
-        self.hat = Some(hat)
+    fn add_auth_token(&self, hat: HardwareAuthToken) {
+        *self.hat.lock().unwrap() = Some(hat)
     }
 
-    fn get_auth_tokens(&mut self) -> Result<(HardwareAuthToken, Option<TimeStampToken>)> {
-        match (&self.state, self.hat.is_some()) {
-            (AuthRequestState::OpAuth, true) => Ok((self.hat.take().unwrap(), None)),
-            (AuthRequestState::TimeStampedOpAuth(recv), true)
-            | (AuthRequestState::TimeStamp(recv), true) => {
+    fn get_auth_tokens(&self) -> Result<(HardwareAuthToken, Option<TimeStampToken>)> {
+        let hat = self
+            .hat
+            .lock()
+            .unwrap()
+            .take()
+            .ok_or(Error::Km(ErrorCode::KEY_USER_NOT_AUTHENTICATED))
+            .context("In get_auth_tokens: No operation auth token received.")?;
+
+        let tst = match &self.state {
+            AuthRequestState::TimeStampedOpAuth(recv) | AuthRequestState::TimeStamp(recv) => {
                 let result = recv.recv().context("In get_auth_tokens: Sender disconnected.")?;
-                let tst = result.context(concat!(
+                Some(result.context(concat!(
                     "In get_auth_tokens: Worker responded with error ",
                     "from generating timestamp token."
-                ))?;
-                Ok((self.hat.take().unwrap(), Some(tst)))
+                ))?)
             }
-            (_, false) => Err(Error::Km(ErrorCode::KEY_USER_NOT_AUTHENTICATED))
-                .context("In get_auth_tokens: No operation auth token received."),
-        }
+            AuthRequestState::OpAuth => None,
+        };
+        Ok((hat, tst))
     }
 }
 
@@ -127,7 +134,7 @@
     /// We block on timestamp tokens, because we can always make progress on these requests.
     /// The per-op auth tokens might never come, which means we fail if the client calls
     /// update or finish before we got a per-op auth token.
-    Waiting(Arc<Mutex<AuthRequest>>),
+    Waiting(Arc<AuthRequest>),
     /// In this state we have gotten all of the required tokens, we just cache them to
     /// be used when the operation progresses.
     Token(HardwareAuthToken, Option<TimeStampToken>),
@@ -169,9 +176,15 @@
     const CLEANUP_PERIOD: u8 = 25;
 
     pub fn add_auth_token(&self, hat: HardwareAuthToken) {
-        let mut map = self.map_and_cleanup_counter.lock().unwrap();
-        let (ref mut map, _) = *map;
-        if let Some((_, recv)) = map.remove_entry(&hat.challenge) {
+        let recv = {
+            // Limit the scope of the mutex guard, so that it is not held while the auth token is
+            // added.
+            let mut map = self.map_and_cleanup_counter.lock().unwrap();
+            let (ref mut map, _) = *map;
+            map.remove_entry(&hat.challenge)
+        };
+
+        if let Some((_, recv)) = recv {
             recv.add_auth_token(hat);
         }
     }
@@ -191,7 +204,7 @@
 }
 
 #[derive(Debug)]
-struct TokenReceiver(Weak<Mutex<AuthRequest>>);
+struct TokenReceiver(Weak<AuthRequest>);
 
 impl TokenReceiver {
     fn is_obsolete(&self) -> bool {
@@ -200,8 +213,7 @@
 
     fn add_auth_token(&self, hat: HardwareAuthToken) {
         if let Some(state_arc) = self.0.upgrade() {
-            let mut state = state_arc.lock().unwrap();
-            state.add_auth_token(hat);
+            state_arc.add_auth_token(hat);
         }
     }
 }
@@ -326,8 +338,7 @@
     /// tokens into the DeferredAuthState::Token state for future use.
     fn get_auth_tokens(&mut self) -> Result<(Option<HardwareAuthToken>, Option<TimeStampToken>)> {
         let deferred_tokens = if let DeferredAuthState::Waiting(ref auth_request) = self.state {
-            let mut state = auth_request.lock().unwrap();
-            Some(state.get_auth_tokens().context("In AuthInfo::get_auth_tokens.")?)
+            Some(auth_request.get_auth_tokens().context("In AuthInfo::get_auth_tokens.")?)
         } else {
             None
         };
diff --git a/keystore2/src/error.rs b/keystore2/src/error.rs
index 465dcfa..d1b2ffb 100644
--- a/keystore2/src/error.rs
+++ b/keystore2/src/error.rs
@@ -140,7 +140,7 @@
 /// This function should be used by Keystore service calls to translate error conditions
 /// into service specific exceptions.
 ///
-/// All error conditions get logged by this function.
+/// All error conditions get logged by this function, except for KEY_NOT_FOUND error.
 ///
 /// All `Error::Rc(x)` and `Error::Km(x)` variants get mapped onto a service specific error
 /// code of x. This is possible because KeyMint `ErrorCode` errors are always negative and
@@ -174,7 +174,13 @@
     map_err_with(
         result,
         |e| {
-            log::error!("{:?}", e);
+            // Make the key not found errors silent.
+            if !matches!(
+                e.root_cause().downcast_ref::<Error>(),
+                Some(Error::Rc(ResponseCode::KEY_NOT_FOUND))
+            ) {
+                log::error!("{:?}", e);
+            }
             e
         },
         handle_ok,
diff --git a/keystore2/src/legacy_migrator.rs b/keystore2/src/legacy_migrator.rs
index e5bcae4..5e0d573 100644
--- a/keystore2/src/legacy_migrator.rs
+++ b/keystore2/src/legacy_migrator.rs
@@ -420,7 +420,7 @@
             .context("In list_uid: Trying to list legacy entries.")
     }
 
-    /// This is a key migration request that can run in the migrator thread. This should
+    /// This is a key migration request that must run in the migrator thread. This must
     /// be passed to do_serialized.
     fn check_and_migrate(&mut self, uid: u32, mut key: KeyDescriptor) -> Result<()> {
         let alias = key.alias.clone().ok_or_else(|| {
diff --git a/keystore2/src/maintenance.rs b/keystore2/src/maintenance.rs
index 1691f9d..9e7576e 100644
--- a/keystore2/src/maintenance.rs
+++ b/keystore2/src/maintenance.rs
@@ -29,13 +29,14 @@
     IKeystoreMaintenance::{BnKeystoreMaintenance, IKeystoreMaintenance},
     UserState::UserState as AidlUserState,
 };
-use android_security_maintenance::binder::{Interface, Result as BinderResult};
+use android_security_maintenance::binder::{
+    BinderFeatures, Interface, Result as BinderResult, Strong, ThreadState,
+};
 use android_system_keystore2::aidl::android::system::keystore2::ResponseCode::ResponseCode;
 use android_system_keystore2::aidl::android::system::keystore2::{
     Domain::Domain, KeyDescriptor::KeyDescriptor,
 };
 use anyhow::{Context, Result};
-use binder::{IBinderInternal, Strong, ThreadState};
 use keystore2_crypto::Password;
 
 /// This struct is defined to implement the aforementioned AIDL interface.
@@ -45,9 +46,10 @@
 impl Maintenance {
     /// Create a new instance of Keystore User Manager service.
     pub fn new_native_binder() -> Result<Strong<dyn IKeystoreMaintenance>> {
-        let result = BnKeystoreMaintenance::new_binder(Self);
-        result.as_binder().set_requesting_sid(true);
-        Ok(result)
+        Ok(BnKeystoreMaintenance::new_binder(
+            Self,
+            BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
+        ))
     }
 
     fn on_user_password_changed(user_id: i32, password: Option<Password>) -> Result<()> {
diff --git a/keystore2/src/metrics.rs b/keystore2/src/metrics.rs
index 71c2f3f..5b66307 100644
--- a/keystore2/src/metrics.rs
+++ b/keystore2/src/metrics.rs
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 //! This module provides convenience functions for keystore2 logging.
+use crate::async_task::AsyncTask;
 use crate::error::get_error_code;
 use crate::globals::DB;
 use crate::key_parameter::KeyParameterValue as KsKeyParamValue;
@@ -25,6 +26,7 @@
 };
 use anyhow::Result;
 use keystore2_system_property::PropertyWatcher;
+use lazy_static::lazy_static;
 use statslog_rust::{
     keystore2_key_creation_event_reported::{
         Algorithm as StatsdAlgorithm, EcCurve as StatsdEcCurve, KeyOrigin as StatsdKeyOrigin,
@@ -40,6 +42,11 @@
 use statslog_rust_header::Atoms;
 use statspull_rust::{set_pull_atom_callback, StatsPullResult};
 
+lazy_static! {
+    /// Background thread which handles logging via statsd
+    static ref STATSD_LOGS_HANDLER: AsyncTask = Default::default();
+}
+
 fn create_default_key_creation_atom() -> Keystore2KeyCreationEventReported {
     // If a value is not present, fields represented by bitmaps and i32 fields
     // will take 0, except error_code which defaults to 1 indicating NO_ERROR and key_size,
@@ -88,14 +95,13 @@
     let key_creation_event_stats =
         construct_key_creation_event_stats(sec_level, key_params, result);
 
-    let logging_result = key_creation_event_stats.stats_write();
+    STATSD_LOGS_HANDLER.queue_lo(move |_| {
+        let logging_result = key_creation_event_stats.stats_write();
 
-    if let Err(e) = logging_result {
-        log::error!(
-            "In log_key_creation_event_stats. Error in logging key creation event. {:?}",
-            e
-        );
-    }
+        if let Err(e) = logging_result {
+            log::error!("Error in logging key creation event in the async task. {:?}", e);
+        }
+    });
 }
 
 /// Log key operation events via statsd API.
@@ -114,14 +120,13 @@
         key_upgraded,
     );
 
-    let logging_result = key_operation_event_stats.stats_write();
+    STATSD_LOGS_HANDLER.queue_lo(move |_| {
+        let logging_result = key_operation_event_stats.stats_write();
 
-    if let Err(e) = logging_result {
-        log::error!(
-            "In log_key_operation_event_stats. Error in logging key operation event. {:?}",
-            e
-        );
-    }
+        if let Err(e) = logging_result {
+            log::error!("Error in logging key operation event in the async task. {:?}", e);
+        }
+    });
 }
 
 fn construct_key_creation_event_stats<U>(
diff --git a/keystore2/src/operation.rs b/keystore2/src/operation.rs
index c2539a7..0b5c77a 100644
--- a/keystore2/src/operation.rs
+++ b/keystore2/src/operation.rs
@@ -133,11 +133,11 @@
     IKeyMintOperation::IKeyMintOperation, KeyParameter::KeyParameter, KeyPurpose::KeyPurpose,
     SecurityLevel::SecurityLevel,
 };
+use android_hardware_security_keymint::binder::BinderFeatures;
 use android_system_keystore2::aidl::android::system::keystore2::{
     IKeystoreOperation::BnKeystoreOperation, IKeystoreOperation::IKeystoreOperation,
 };
 use anyhow::{anyhow, Context, Result};
-use binder::IBinderInternal;
 use std::{
     collections::HashMap,
     sync::{Arc, Mutex, MutexGuard, Weak},
@@ -783,16 +783,16 @@
 
 impl KeystoreOperation {
     /// Creates a new operation instance wrapped in a
-    /// BnKeystoreOperation proxy object. It also
-    /// calls `IBinderInternal::set_requesting_sid` on the new interface, because
+    /// BnKeystoreOperation proxy object. It also enables
+    /// `BinderFeatures::set_requesting_sid` on the new interface, because
     /// we need it for checking Keystore permissions.
     pub fn new_native_binder(
         operation: Arc<Operation>,
     ) -> binder::public_api::Strong<dyn IKeystoreOperation> {
-        let result =
-            BnKeystoreOperation::new_binder(Self { operation: Mutex::new(Some(operation)) });
-        result.as_binder().set_requesting_sid(true);
-        result
+        BnKeystoreOperation::new_binder(
+            Self { operation: Mutex::new(Some(operation)) },
+            BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
+        )
     }
 
     /// Grabs the outer operation mutex and calls `f` on the locked operation.
diff --git a/keystore2/src/remote_provisioning.rs b/keystore2/src/remote_provisioning.rs
index f99805d..f8ee369 100644
--- a/keystore2/src/remote_provisioning.rs
+++ b/keystore2/src/remote_provisioning.rs
@@ -34,7 +34,7 @@
     AttestationPoolStatus::AttestationPoolStatus, IRemoteProvisioning::BnRemoteProvisioning,
     IRemoteProvisioning::IRemoteProvisioning,
 };
-use android_security_remoteprovisioning::binder::Strong;
+use android_security_remoteprovisioning::binder::{BinderFeatures, Strong};
 use android_system_keystore2::aidl::android::system::keystore2::{
     Domain::Domain, KeyDescriptor::KeyDescriptor,
 };
@@ -233,7 +233,7 @@
         if let Ok(dev) = get_remotely_provisioned_component(&SecurityLevel::STRONGBOX) {
             result.device_by_sec_level.insert(SecurityLevel::STRONGBOX, dev);
         }
-        Ok(BnRemoteProvisioning::new_binder(result))
+        Ok(BnRemoteProvisioning::new_binder(result, BinderFeatures::default()))
     }
 
     /// Populates the AttestationPoolStatus parcelable with information about how many
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index 117b48c..03514b3 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -22,6 +22,7 @@
     KeyMintHardwareInfo::KeyMintHardwareInfo, KeyParameter::KeyParameter,
     KeyParameterValue::KeyParameterValue, SecurityLevel::SecurityLevel, Tag::Tag,
 };
+use android_hardware_security_keymint::binder::{BinderFeatures, Strong, ThreadState};
 use android_system_keystore2::aidl::android::system::keystore2::{
     AuthenticatorSpec::AuthenticatorSpec, CreateOperationResponse::CreateOperationResponse,
     Domain::Domain, EphemeralStorageKeyResponse::EphemeralStorageKeyResponse,
@@ -57,7 +58,6 @@
     utils::key_characteristics_to_internal,
 };
 use anyhow::{anyhow, Context, Result};
-use binder::{IBinderInternal, Strong, ThreadState};
 
 /// Implementation of the IKeystoreSecurityLevel Interface.
 pub struct KeystoreSecurityLevel {
@@ -79,8 +79,8 @@
 
 impl KeystoreSecurityLevel {
     /// Creates a new security level instance wrapped in a
-    /// BnKeystoreSecurityLevel proxy object. It also
-    /// calls `IBinderInternal::set_requesting_sid` on the new interface, because
+    /// BnKeystoreSecurityLevel proxy object. It also enables
+    /// `BinderFeatures::set_requesting_sid` on the new interface, because
     /// we need it for checking keystore permissions.
     pub fn new_native_binder(
         security_level: SecurityLevel,
@@ -88,16 +88,18 @@
     ) -> Result<(Strong<dyn IKeystoreSecurityLevel>, Uuid)> {
         let (dev, hw_info, km_uuid) = get_keymint_device(&security_level)
             .context("In KeystoreSecurityLevel::new_native_binder.")?;
-        let result = BnKeystoreSecurityLevel::new_binder(Self {
-            security_level,
-            keymint: dev,
-            hw_info,
-            km_uuid,
-            operation_db: OperationDb::new(),
-            rem_prov_state: RemProvState::new(security_level, km_uuid),
-            id_rotation_state,
-        });
-        result.as_binder().set_requesting_sid(true);
+        let result = BnKeystoreSecurityLevel::new_binder(
+            Self {
+                security_level,
+                keymint: dev,
+                hw_info,
+                km_uuid,
+                operation_db: OperationDb::new(),
+                rem_prov_state: RemProvState::new(security_level, km_uuid),
+                id_rotation_state,
+            },
+            BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
+        );
         Ok((result, km_uuid))
     }
 
diff --git a/keystore2/src/service.rs b/keystore2/src/service.rs
index 1debe1b..8d3b66e 100644
--- a/keystore2/src/service.rs
+++ b/keystore2/src/service.rs
@@ -37,13 +37,13 @@
     id_rotation::IdRotationState,
 };
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::SecurityLevel::SecurityLevel;
+use android_hardware_security_keymint::binder::{BinderFeatures, Strong, ThreadState};
 use android_system_keystore2::aidl::android::system::keystore2::{
     Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel,
     IKeystoreService::BnKeystoreService, IKeystoreService::IKeystoreService,
     KeyDescriptor::KeyDescriptor, KeyEntryResponse::KeyEntryResponse, KeyMetadata::KeyMetadata,
 };
 use anyhow::{Context, Result};
-use binder::{IBinderInternal, Strong, ThreadState};
 use error::Error;
 use keystore2_selinux as selinux;
 
@@ -90,9 +90,10 @@
                 "In KeystoreService::new_native_binder: Trying to initialize the legacy migrator.",
             )?;
 
-        let result = BnKeystoreService::new_binder(result);
-        result.as_binder().set_requesting_sid(true);
-        Ok(result)
+        Ok(BnKeystoreService::new_binder(
+            result,
+            BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
+        ))
     }
 
     fn uuid_to_sec_level(&self, uuid: &Uuid) -> SecurityLevel {
diff --git a/keystore2/vpnprofilestore/lib.rs b/keystore2/vpnprofilestore/lib.rs
index 5123837..d92e045 100644
--- a/keystore2/vpnprofilestore/lib.rs
+++ b/keystore2/vpnprofilestore/lib.rs
@@ -18,9 +18,11 @@
     IVpnProfileStore::BnVpnProfileStore, IVpnProfileStore::IVpnProfileStore,
     IVpnProfileStore::ERROR_PROFILE_NOT_FOUND, IVpnProfileStore::ERROR_SYSTEM_ERROR,
 };
-use android_security_vpnprofilestore::binder::{Result as BinderResult, Status as BinderStatus};
+use android_security_vpnprofilestore::binder::{
+    BinderFeatures, ExceptionCode, Result as BinderResult, Status as BinderStatus, Strong,
+    ThreadState,
+};
 use anyhow::{Context, Result};
-use binder::{ExceptionCode, Strong, ThreadState};
 use keystore2::{async_task::AsyncTask, legacy_blob::LegacyBlobLoader};
 use rusqlite::{
     params, Connection, OptionalExtension, Transaction, TransactionBehavior, NO_PARAMS,
@@ -173,7 +175,7 @@
 /// This function should be used by vpnprofilestore service calls to translate error conditions
 /// into service specific exceptions.
 ///
-/// All error conditions get logged by this function.
+/// All error conditions get logged by this function, except for ERROR_PROFILE_NOT_FOUND error.
 ///
 /// `Error::Error(x)` variants get mapped onto a service specific error code of `x`.
 ///
@@ -188,12 +190,16 @@
 {
     result.map_or_else(
         |e| {
-            log::error!("{:?}", e);
             let root_cause = e.root_cause();
-            let rc = match root_cause.downcast_ref::<Error>() {
-                Some(Error::Error(e)) => *e,
-                Some(Error::Binder(_, _)) | None => ERROR_SYSTEM_ERROR,
+            let (rc, log_error) = match root_cause.downcast_ref::<Error>() {
+                // Make the profile not found errors silent.
+                Some(Error::Error(ERROR_PROFILE_NOT_FOUND)) => (ERROR_PROFILE_NOT_FOUND, false),
+                Some(Error::Error(e)) => (*e, true),
+                Some(Error::Binder(_, _)) | None => (ERROR_SYSTEM_ERROR, true),
             };
+            if log_error {
+                log::error!("{:?}", e);
+            }
             Err(BinderStatus::new_service_specific_error(rc, None))
         },
         handle_ok,
@@ -220,7 +226,7 @@
 
         let result = Self { db_path, async_task: Default::default() };
         result.init_shelf(path);
-        BnVpnProfileStore::new_binder(result)
+        BnVpnProfileStore::new_binder(result, BinderFeatures::default())
     }
 
     fn open_db(&self) -> Result<DB> {
diff --git a/provisioner/Android.bp b/provisioner/Android.bp
index d3f06fe..12a21d1 100644
--- a/provisioner/Android.bp
+++ b/provisioner/Android.bp
@@ -51,3 +51,19 @@
         "android.security.provisioner-java",
     ],
 }
+
+cc_binary {
+    name: "rkp_factory_extraction_tool",
+    srcs: ["rkp_factory_extraction_tool.cpp"],
+    shared_libs: [
+        "android.hardware.security.keymint-V1-ndk_platform",
+        "libbinder",
+        "libbinder_ndk",
+        "libcppbor_external",
+        "libcppcose_rkp",
+        "libcrypto",
+        "liblog",
+        "libvintf",
+    ],
+    //export_include_dirs: ["include"],
+}
diff --git a/provisioner/rkp_factory_extraction_tool.cpp b/provisioner/rkp_factory_extraction_tool.cpp
new file mode 100644
index 0000000..d4842b1
--- /dev/null
+++ b/provisioner/rkp_factory_extraction_tool.cpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+#include <vector>
+
+#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
+#include <android/binder_manager.h>
+#include <cppbor.h>
+#include <keymaster/cppcose/cppcose.h>
+#include <log/log.h>
+#include <vintf/VintfObject.h>
+
+using std::set;
+using std::string;
+using std::vector;
+
+using aidl::android::hardware::security::keymint::DeviceInfo;
+using aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent;
+using aidl::android::hardware::security::keymint::MacedPublicKey;
+using aidl::android::hardware::security::keymint::ProtectedData;
+
+using android::vintf::HalManifest;
+using android::vintf::VintfObject;
+
+using namespace cppbor;
+using namespace cppcose;
+
+namespace {
+
+const string kPackage = "android.hardware.security.keymint";
+const string kInterface = "IRemotelyProvisionedComponent";
+const string kFormattedName = kPackage + "." + kInterface + "/";
+
+ErrMsgOr<vector<uint8_t>> generateEekChain(size_t length, const vector<uint8_t>& eekId) {
+    auto eekChain = cppbor::Array();
+
+    vector<uint8_t> prevPrivKey;
+    for (size_t i = 0; i < length - 1; ++i) {
+        vector<uint8_t> pubKey(ED25519_PUBLIC_KEY_LEN);
+        vector<uint8_t> privKey(ED25519_PRIVATE_KEY_LEN);
+
+        ED25519_keypair(pubKey.data(), privKey.data());
+
+        // The first signing key is self-signed.
+        if (prevPrivKey.empty()) prevPrivKey = privKey;
+
+        auto coseSign1 = constructCoseSign1(prevPrivKey,
+                                            cppbor::Map() /* payload CoseKey */
+                                                .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
+                                                .add(CoseKey::ALGORITHM, EDDSA)
+                                                .add(CoseKey::CURVE, ED25519)
+                                                .add(CoseKey::PUBKEY_X, pubKey)
+                                                .canonicalize()
+                                                .encode(),
+                                            {} /* AAD */);
+        if (!coseSign1) return coseSign1.moveMessage();
+        eekChain.add(coseSign1.moveValue());
+
+        prevPrivKey = privKey;
+    }
+
+    vector<uint8_t> pubKey(X25519_PUBLIC_VALUE_LEN);
+    vector<uint8_t> privKey(X25519_PRIVATE_KEY_LEN);
+    X25519_keypair(pubKey.data(), privKey.data());
+
+    auto coseSign1 = constructCoseSign1(prevPrivKey,
+                                        cppbor::Map() /* payload CoseKey */
+                                            .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
+                                            .add(CoseKey::KEY_ID, eekId)
+                                            .add(CoseKey::ALGORITHM, ECDH_ES_HKDF_256)
+                                            .add(CoseKey::CURVE, cppcose::X25519)
+                                            .add(CoseKey::PUBKEY_X, pubKey)
+                                            .canonicalize()
+                                            .encode(),
+                                        {} /* AAD */);
+    if (!coseSign1) return coseSign1.moveMessage();
+    eekChain.add(coseSign1.moveValue());
+
+    return eekChain.encode();
+}
+
+std::vector<uint8_t> getChallenge() {
+    return std::vector<uint8_t>(0);
+}
+
+std::vector<uint8_t> composeCertificateRequest(ProtectedData&& protectedData,
+                                               DeviceInfo&& deviceInfo) {
+    Array emptyMacedKeysToSign;
+    emptyMacedKeysToSign
+        .add(std::vector<uint8_t>(0))   // empty protected headers as bstr
+        .add(Map())                     // empty unprotected headers
+        .add(Null())                    // nil for the payload
+        .add(std::vector<uint8_t>(0));  // empty tag as bstr
+    Array certificateRequest;
+    certificateRequest.add(EncodedItem(std::move(deviceInfo.deviceInfo)))
+        .add(getChallenge())  // fake challenge
+        .add(EncodedItem(std::move(protectedData.protectedData)))
+        .add(std::move(emptyMacedKeysToSign));
+    return certificateRequest.encode();
+}
+
+int32_t errorMsg(string name) {
+    std::cerr << "Failed for rkp instance: " << name;
+    return -1;
+}
+
+}  // namespace
+
+int main() {
+    std::shared_ptr<const HalManifest> manifest = VintfObject::GetDeviceHalManifest();
+    set<string> rkpNames = manifest->getAidlInstances(kPackage, kInterface);
+    for (auto name : rkpNames) {
+        string fullName = kFormattedName + name;
+        if (!AServiceManager_isDeclared(fullName.c_str())) {
+            ALOGE("Could not find the following instance declared in the manifest: %s\n",
+                  fullName.c_str());
+            return errorMsg(name);
+        }
+        AIBinder* rkpAiBinder = AServiceManager_getService(fullName.c_str());
+        ::ndk::SpAIBinder rkp_binder(rkpAiBinder);
+        auto rkp_service = IRemotelyProvisionedComponent::fromBinder(rkp_binder);
+        std::vector<uint8_t> keysToSignMac;
+        std::vector<MacedPublicKey> emptyKeys;
+
+        // Replace this eek chain generation with the actual production GEEK
+        std::vector<uint8_t> eekId(10);  // replace with real KID later (EEK fingerprint)
+        auto eekOrErr = generateEekChain(3 /* chainlength */, eekId);
+        if (!eekOrErr) {
+            ALOGE("Failed to generate test EEK somehow: %s", eekOrErr.message().c_str());
+            return errorMsg(name);
+        }
+
+        std::vector<uint8_t> eek = eekOrErr.moveValue();
+        DeviceInfo deviceInfo;
+        ProtectedData protectedData;
+        if (rkp_service) {
+            ALOGE("extracting bundle");
+            ::ndk::ScopedAStatus status = rkp_service->generateCertificateRequest(
+                true /* testMode */, emptyKeys, eek, getChallenge(), &deviceInfo, &protectedData,
+                &keysToSignMac);
+            if (!status.isOk()) {
+                ALOGE("Bundle extraction failed. Error code: %d", status.getServiceSpecificError());
+                return errorMsg(name);
+            }
+            std::cout << "\n";
+            std::vector<uint8_t> certificateRequest =
+                composeCertificateRequest(std::move(protectedData), std::move(deviceInfo));
+            std::copy(certificateRequest.begin(), certificateRequest.end(),
+                      std::ostream_iterator<char>(std::cout));
+        }
+    }
+}