Merge "prng_seeder is a bootstrap process in microdroid"
diff --git a/identity/Android.bp b/identity/Android.bp
index 9117b7f..7b81685 100644
--- a/identity/Android.bp
+++ b/identity/Android.bp
@@ -32,35 +32,39 @@
     ],
 
     srcs: [
-        "main.cpp",
-        "CredentialStore.cpp",
-        "CredentialStoreFactory.cpp",
-        "WritableCredential.cpp",
         "Credential.cpp",
         "CredentialData.cpp",
+        "CredentialStore.cpp",
+        "CredentialStoreFactory.cpp",
+        "RemotelyProvisionedKey.cpp",
         "Session.cpp",
         "Util.cpp",
+        "WritableCredential.cpp",
+        "main.cpp",
     ],
     init_rc: ["credstore.rc"],
     shared_libs: [
+        "android.hardware.identity-support-lib",
+        "android.hardware.keymaster@4.0",
+        "android.security.authorization-ndk",
+	"android.security.remoteprovisioning-cpp",
         "libbase",
         "libbinder",
         "libbinder_ndk",
-        "android.hardware.keymaster@4.0",
         "libcredstore_aidl",
         "libcrypto",
-        "libutils",
         "libhidlbase",
-        "android.hardware.identity-support-lib",
         "libkeymaster4support",
         "libkeystore-attestation-application-id",
-        "android.security.authorization-ndk",
-        "android.security.remoteprovisioning-cpp",
+        "libutils",
         "libutilscallstack",
+        "libvintf",
+	"server_configurable_flags",
     ],
     static_libs: [
         "android.hardware.security.rkp-V3-cpp",
         "android.hardware.keymaster-V3-cpp",
+        "android.security.rkp_aidl-cpp",
         "libcppbor_external",
     ],
 }
diff --git a/identity/CredentialStore.cpp b/identity/CredentialStore.cpp
index c5c429b..eb9bdb6 100644
--- a/identity/CredentialStore.cpp
+++ b/identity/CredentialStore.cpp
@@ -26,6 +26,8 @@
 #include <android/security/remoteprovisioning/RemotelyProvisionedKey.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
+#include <server_configurable_flags/get_flags.h>
+#include <vintf/VintfObject.h>
 
 #include "Credential.h"
 #include "CredentialData.h"
@@ -39,41 +41,14 @@
 namespace identity {
 namespace {
 
-using ::android::hardware::security::keymint::IRemotelyProvisionedComponent;
-using ::android::hardware::security::keymint::RpcHardwareInfo;
 using ::android::security::remoteprovisioning::IRemotelyProvisionedKeyPool;
-using ::android::security::remoteprovisioning::RemotelyProvisionedKey;
+using ::android::security::rkp::IRemoteProvisioning;
 
-std::optional<std::string>
-getRemotelyProvisionedComponentId(const sp<IIdentityCredentialStore>& hal) {
-    auto init = [](const sp<IIdentityCredentialStore>& hal) -> std::optional<std::string> {
-        sp<IRemotelyProvisionedComponent> remotelyProvisionedComponent;
-        Status status = hal->getRemotelyProvisionedComponent(&remotelyProvisionedComponent);
-        if (!status.isOk()) {
-            LOG(ERROR) << "Error getting remotely provisioned component: " << status;
-            return std::nullopt;
-        }
-
-        RpcHardwareInfo rpcHwInfo;
-        status = remotelyProvisionedComponent->getHardwareInfo(&rpcHwInfo);
-        if (!status.isOk()) {
-            LOG(ERROR) << "Error getting remotely provisioned component hardware info: " << status;
-            return std::nullopt;
-        }
-
-        if (!rpcHwInfo.uniqueId) {
-            LOG(ERROR) << "Remotely provisioned component is missing a unique id, which is "
-                       << "required for credential key remotely provisioned attestation keys. "
-                       << "This is a bug in the vendor implementation.";
-            return std::nullopt;
-        }
-
-        // This id is required to later fetch remotely provisioned attestation keys.
-        return *rpcHwInfo.uniqueId;
-    };
-
-    static std::optional<std::string> id = init(hal);
-    return id;
+bool useRkpd() {
+    std::string useRkpdFlagValue = server_configurable_flags::GetServerConfigurableFlag(
+        "remote_key_provisioning_native", "enable_rkpd",
+        /*default_value=*/"false");
+    return useRkpdFlagValue == "true";
 }
 
 }  // namespace
@@ -90,13 +65,30 @@
     halApiVersion_ = hal_->getInterfaceVersion();
 
     if (hwInfo_.isRemoteKeyProvisioningSupported) {
-        keyPool_ = android::waitForService<IRemotelyProvisionedKeyPool>(
-            IRemotelyProvisionedKeyPool::descriptor);
-        if (keyPool_.get() == nullptr) {
-            LOG(ERROR) << "Error getting IRemotelyProvisionedKeyPool HAL with service name '"
-                       << IRemotelyProvisionedKeyPool::descriptor << "'";
+        status = hal_->getRemotelyProvisionedComponent(&rpc_);
+        if (!status.isOk()) {
+            LOG(ERROR) << "Error getting remotely provisioned component: " << status;
             return false;
         }
+        useRkpd_ = useRkpd();
+
+        if (useRkpd_) {
+            uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
+            auto rpcKeyFuture = getRpcKeyFuture(rpc_, callingUid);
+            if (!rpcKeyFuture) {
+                LOG(ERROR) << "Error in getRpcKeyFuture()";
+                return false;
+            }
+            rpcKeyFuture_ = std::move(*rpcKeyFuture);
+        } else {
+            keyPool_ = android::waitForService<IRemotelyProvisionedKeyPool>(
+                IRemotelyProvisionedKeyPool::descriptor);
+            if (!keyPool_) {
+                LOG(ERROR) << "Error getting IRemotelyProvisionedKeyPool HAL with service name '"
+                           << IRemotelyProvisionedKeyPool::descriptor << "'";
+                return false;
+            }
+        }
     }
 
     LOG(INFO) << "Connected to Identity Credential HAL with API version " << halApiVersion_
@@ -209,28 +201,54 @@
 
 Status CredentialStore::setRemotelyProvisionedAttestationKey(
     IWritableIdentityCredential* halWritableCredential) {
-    std::optional<std::string> rpcId = getRemotelyProvisionedComponentId(hal_);
-    if (!rpcId) {
-        return Status::fromServiceSpecificError(ERROR_GENERIC,
-                                                "Error getting remotely provisioned component id");
+    std::vector<uint8_t> keyBlob;
+    std::vector<uint8_t> encodedCertChain;
+    Status status;
+
+    if (useRkpd_) {
+        if (rpcKeyFuture_.wait_for(std::chrono::seconds(10)) != std::future_status::ready) {
+            return Status::fromServiceSpecificError(
+                ERROR_GENERIC, "Waiting for remotely provisioned attestation key timed out");
+        }
+
+        std::optional<::android::security::rkp::RemotelyProvisionedKey> key = rpcKeyFuture_.get();
+        if (!key) {
+            return Status::fromServiceSpecificError(
+                ERROR_GENERIC, "Failed to get remotely provisioned attestation key");
+        }
+
+        if (key->keyBlob.empty()) {
+            return Status::fromServiceSpecificError(
+                ERROR_GENERIC, "Remotely provisioned attestation key blob is empty");
+        }
+
+        keyBlob = std::move(key->keyBlob);
+        encodedCertChain = std::move(key->encodedCertChain);
+    } else {
+        std::optional<std::string> rpcId = getRpcId(rpc_);
+        if (!rpcId) {
+            return Status::fromServiceSpecificError(
+                ERROR_GENERIC, "Error getting remotely provisioned component id");
+        }
+
+        uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
+        ::android::security::remoteprovisioning::RemotelyProvisionedKey key;
+        Status status = keyPool_->getAttestationKey(callingUid, *rpcId, &key);
+        if (!status.isOk()) {
+            LOG(WARNING) << "Unable to fetch remotely provisioned attestation key, falling back "
+                         << "to the factory-provisioned attestation key.";
+            return Status::ok();
+        }
+
+        keyBlob = std::move(key.keyBlob);
+        encodedCertChain = std::move(key.encodedCertChain);
     }
 
-    uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
-    RemotelyProvisionedKey key;
-    Status status = keyPool_->getAttestationKey(callingUid, *rpcId, &key);
-    if (!status.isOk()) {
-        LOG(WARNING) << "Unable to fetch remotely provisioned attestation key, falling back "
-                     << "to the factory-provisioned attestation key.";
-        return Status::ok();
-    }
-
-    status = halWritableCredential->setRemotelyProvisionedAttestationKey(key.keyBlob,
-                                                                         key.encodedCertChain);
+    status = halWritableCredential->setRemotelyProvisionedAttestationKey(keyBlob, encodedCertChain);
     if (!status.isOk()) {
         LOG(ERROR) << "Error setting remotely provisioned attestation key on credential";
         return status;
     }
-
     return Status::ok();
 }
 
diff --git a/identity/CredentialStore.h b/identity/CredentialStore.h
index df7928e..495841b 100644
--- a/identity/CredentialStore.h
+++ b/identity/CredentialStore.h
@@ -17,12 +17,16 @@
 #ifndef SYSTEM_SECURITY_CREDENTIAL_STORE_H_
 #define SYSTEM_SECURITY_CREDENTIAL_STORE_H_
 
+#include <future>
 #include <string>
 #include <vector>
 
 #include <android/hardware/identity/IIdentityCredentialStore.h>
 #include <android/security/identity/BnCredentialStore.h>
 #include <android/security/remoteprovisioning/IRemotelyProvisionedKeyPool.h>
+#include <android/security/rkp/IRemoteProvisioning.h>
+
+#include "RemotelyProvisionedKey.h"
 
 namespace android {
 namespace security {
@@ -39,6 +43,7 @@
 using ::android::hardware::identity::IIdentityCredentialStore;
 using ::android::hardware::identity::IPresentationSession;
 using ::android::hardware::identity::IWritableIdentityCredential;
+using ::android::hardware::security::keymint::IRemotelyProvisionedComponent;
 using ::android::security::remoteprovisioning::IRemotelyProvisionedKeyPool;
 
 class CredentialStore : public BnCredentialStore {
@@ -73,9 +78,12 @@
     sp<IIdentityCredentialStore> hal_;
     int halApiVersion_;
 
-    sp<IRemotelyProvisionedKeyPool> keyPool_;
-
     HardwareInformation hwInfo_;
+
+    bool useRkpd_;
+    sp<IRemotelyProvisionedComponent> rpc_;
+    sp<IRemotelyProvisionedKeyPool> keyPool_;
+    std::future<std::optional<RemotelyProvisionedKey>> rpcKeyFuture_;
 };
 
 }  // namespace identity
diff --git a/identity/RemotelyProvisionedKey.cpp b/identity/RemotelyProvisionedKey.cpp
new file mode 100644
index 0000000..46a42f4
--- /dev/null
+++ b/identity/RemotelyProvisionedKey.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#define LOG_TAG "credstore"
+
+#include <atomic>
+
+#include <android-base/logging.h>
+#include <android/security/rkp/BnGetKeyCallback.h>
+#include <android/security/rkp/BnGetRegistrationCallback.h>
+#include <android/security/rkp/IRemoteProvisioning.h>
+#include <binder/IServiceManager.h>
+#include <binder/Status.h>
+#include <vintf/VintfObject.h>
+
+#include "RemotelyProvisionedKey.h"
+
+namespace android {
+namespace security {
+namespace identity {
+namespace {
+
+using ::android::binder::Status;
+using ::android::hardware::security::keymint::IRemotelyProvisionedComponent;
+using ::android::hardware::security::keymint::RpcHardwareInfo;
+using ::android::security::rkp::BnGetKeyCallback;
+using ::android::security::rkp::BnGetRegistrationCallback;
+using ::android::security::rkp::IRegistration;
+using ::android::security::rkp::IRemoteProvisioning;
+using ::android::security::rkp::RemotelyProvisionedKey;
+
+std::optional<String16> findRpcNameById(std::string_view targetRpcId) {
+    auto deviceManifest = vintf::VintfObject::GetDeviceHalManifest();
+    auto instances = deviceManifest->getAidlInstances("android.hardware.security.keymint",
+                                                      "IRemotelyProvisionedComponent");
+    for (const std::string& instance : instances) {
+        auto rpcName =
+            IRemotelyProvisionedComponent::descriptor + String16("/") + String16(instance.c_str());
+        sp<IRemotelyProvisionedComponent> rpc =
+            android::waitForService<IRemotelyProvisionedComponent>(rpcName);
+
+        auto rpcId = getRpcId(rpc);
+        if (!rpcId) {
+            continue;
+        }
+        if (*rpcId == targetRpcId) {
+            return rpcName;
+        }
+    }
+
+    LOG(ERROR) << "Remotely provisioned component with given unique ID: " << targetRpcId
+               << " not found";
+    return std::nullopt;
+}
+
+std::optional<String16> getRpcName(const sp<IRemotelyProvisionedComponent>& rpc) {
+    std::optional<std::string> targetRpcId = getRpcId(rpc);
+    if (!targetRpcId) {
+        return std::nullopt;
+    }
+    return findRpcNameById(*targetRpcId);
+}
+
+class GetKeyCallback : public BnGetKeyCallback {
+  public:
+    GetKeyCallback(std::promise<std::optional<RemotelyProvisionedKey>> keyPromise)
+        : keyPromise_(std::move(keyPromise)), called_() {}
+
+    Status onSuccess(const RemotelyProvisionedKey& key) override {
+        if (called_.test_and_set()) {
+            return Status::ok();
+        }
+        keyPromise_.set_value(key);
+        return Status::ok();
+    }
+    Status onCancel() override {
+        if (called_.test_and_set()) {
+            return Status::ok();
+        }
+        LOG(ERROR) << "GetKeyCallback cancelled";
+        keyPromise_.set_value(std::nullopt);
+        return Status::ok();
+    }
+    Status onError(const String16& error) override {
+        if (called_.test_and_set()) {
+            return Status::ok();
+        }
+        LOG(ERROR) << "GetKeyCallback failed: " << error;
+        keyPromise_.set_value(std::nullopt);
+        return Status::ok();
+    }
+
+  private:
+    std::promise<std::optional<RemotelyProvisionedKey>> keyPromise_;
+    // This callback can only be called into once
+    std::atomic_flag called_;
+};
+
+class GetRegistrationCallback : public BnGetRegistrationCallback {
+  public:
+    GetRegistrationCallback(std::promise<std::optional<RemotelyProvisionedKey>> keyPromise,
+                            uint32_t keyId)
+        : keyPromise_(std::move(keyPromise)), keyId_(keyId), called_() {}
+
+    Status onSuccess(const sp<IRegistration>& registration) override {
+        if (called_.test_and_set()) {
+            return Status::ok();
+        }
+        auto cb = sp<GetKeyCallback>::make(std::move(keyPromise_));
+        auto status = registration->getKey(keyId_, cb);
+        if (!status.isOk()) {
+            cb->onError(String16("Failed to register GetKeyCallback"));
+        }
+        return Status::ok();
+    }
+    Status onCancel() override {
+        if (called_.test_and_set()) {
+            return Status::ok();
+        }
+        LOG(ERROR) << "GetRegistrationCallback cancelled";
+        keyPromise_.set_value(std::nullopt);
+        return Status::ok();
+    }
+    Status onError(const String16& error) override {
+        if (called_.test_and_set()) {
+            return Status::ok();
+        }
+        LOG(ERROR) << "GetRegistrationCallback failed: " << error;
+        keyPromise_.set_value(std::nullopt);
+        return Status::ok();
+    }
+
+  private:
+    std::promise<std::optional<RemotelyProvisionedKey>> keyPromise_;
+    int32_t keyId_;
+    // This callback can only be called into once
+    std::atomic_flag called_;
+};
+
+}  // namespace
+
+std::optional<std::string> getRpcId(const sp<IRemotelyProvisionedComponent>& rpc) {
+    RpcHardwareInfo rpcHwInfo;
+    Status status = rpc->getHardwareInfo(&rpcHwInfo);
+    if (!status.isOk()) {
+        LOG(ERROR) << "Error getting remotely provisioned component hardware info: " << status;
+        return std::nullopt;
+    }
+
+    if (!rpcHwInfo.uniqueId) {
+        LOG(ERROR) << "Remotely provisioned component is missing a unique id, which is "
+                   << "required for credential key remotely provisioned attestation keys. "
+                   << "This is a bug in the vendor implementation.";
+        return std::nullopt;
+    }
+
+    return *rpcHwInfo.uniqueId;
+}
+
+std::optional<std::future<std::optional<RemotelyProvisionedKey>>>
+getRpcKeyFuture(const sp<IRemotelyProvisionedComponent>& rpc, int32_t keyId) {
+    std::promise<std::optional<RemotelyProvisionedKey>> keyPromise;
+    auto keyFuture = keyPromise.get_future();
+
+    auto rpcName = getRpcName(rpc);
+    if (!rpcName) {
+        LOG(ERROR) << "Failed to get IRemotelyProvisionedComponent name";
+        return std::nullopt;
+    }
+
+    sp<IRemoteProvisioning> remoteProvisioning =
+        android::waitForService<IRemoteProvisioning>(IRemoteProvisioning::descriptor);
+    if (!remoteProvisioning) {
+        LOG(ERROR) << "Failed to get IRemoteProvisioning HAL";
+        return std::nullopt;
+    }
+
+    auto cb = sp<GetRegistrationCallback>::make(std::move(keyPromise), keyId);
+    Status status = remoteProvisioning->getRegistration(*rpcName, cb);
+    if (!status.isOk()) {
+        LOG(ERROR) << "Failed getRegistration()";
+        return std::nullopt;
+    }
+
+    return keyFuture;
+}
+
+}  // namespace identity
+}  // namespace security
+}  // namespace android
diff --git a/identity/RemotelyProvisionedKey.h b/identity/RemotelyProvisionedKey.h
new file mode 100644
index 0000000..e7ddfca
--- /dev/null
+++ b/identity/RemotelyProvisionedKey.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2022, 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.
+ */
+
+#pragma once
+
+#include <future>
+#include <optional>
+
+#include <android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
+
+namespace android {
+namespace security {
+namespace identity {
+
+using ::android::hardware::security::keymint::IRemotelyProvisionedComponent;
+using ::android::security::rkp::RemotelyProvisionedKey;
+
+std::optional<std::string> getRpcId(const sp<IRemotelyProvisionedComponent>& rpc);
+
+std::optional<std::future<std::optional<RemotelyProvisionedKey>>>
+getRpcKeyFuture(const sp<IRemotelyProvisionedComponent>& rpc, int32_t keyId);
+
+}  // namespace identity
+}  // namespace security
+}  // namespace android
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index 51ce9d1..fa80563 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -41,8 +41,10 @@
         "android.security.maintenance-rust",
         "android.security.metrics-rust",
         "android.security.remoteprovisioning-rust",
+        "android.security.rkp_aidl-rust",
         "libanyhow",
         "libbinder_rs",
+        "libfutures",
         "libkeystore2_aaid-rust",
         "libkeystore2_apc_compat-rust",
         "libkeystore2_crypto_rust",
diff --git a/keystore2/src/attestation_key_utils.rs b/keystore2/src/attestation_key_utils.rs
index 94f3e4c..d01cf86 100644
--- a/keystore2/src/attestation_key_utils.rs
+++ b/keystore2/src/attestation_key_utils.rs
@@ -40,6 +40,10 @@
         attestation_key: AttestationKey,
         attestation_certs: Certificate,
     },
+    RkpdProvisioned {
+        attestation_key: AttestationKey,
+        attestation_certs: Certificate,
+    },
     UserGenerated {
         key_id_guard: KeyIdGuard,
         blob: Vec<u8>,
@@ -48,6 +52,12 @@
     },
 }
 
+fn use_rkpd() -> bool {
+    let property_name = "persist.device_config.remote_key_provisioning_native.enable_rkpd";
+    let default_value = false;
+    rustutils::system_properties::read_bool(property_name, default_value).unwrap_or(default_value)
+}
+
 /// This function loads and, optionally, assigns the caller's remote provisioned
 /// attestation key if a challenge is present. Alternatively, if `attest_key_descriptor` is given,
 /// it loads the user generated attestation key from the database.
@@ -64,18 +74,34 @@
         params.iter().any(|kp| kp.tag == Tag::DEVICE_UNIQUE_ATTESTATION);
     match attest_key_descriptor {
         // Do not select an RKP key if DEVICE_UNIQUE_ATTESTATION is present.
-        None if challenge_present && !is_device_unique_attestation => rem_prov_state
-            .get_remotely_provisioned_attestation_key_and_certs(key, caller_uid, params, db)
-            .context(ks_err!("Trying to get remotely provisioned attestation key."))
-            .map(|result| {
-                result.map(|(key_id_guard, attestation_key, attestation_certs)| {
-                    AttestationKeyInfo::RemoteProvisioned {
-                        key_id_guard,
-                        attestation_key,
-                        attestation_certs,
-                    }
-                })
-            }),
+        None if challenge_present && !is_device_unique_attestation => {
+            if use_rkpd() {
+                rem_prov_state
+                    .get_rkpd_attestation_key_and_certs(key, caller_uid, params)
+                    .context(ks_err!("Trying to get attestation key from RKPD."))
+                    .map(|result| {
+                        result.map(|(attestation_key, attestation_certs)| {
+                            AttestationKeyInfo::RkpdProvisioned {
+                                attestation_key,
+                                attestation_certs,
+                            }
+                        })
+                    })
+            } else {
+                rem_prov_state
+                    .get_remotely_provisioned_attestation_key_and_certs(key, caller_uid, params, db)
+                    .context(ks_err!("Trying to get remotely provisioned attestation key."))
+                    .map(|result| {
+                        result.map(|(key_id_guard, attestation_key, attestation_certs)| {
+                            AttestationKeyInfo::RemoteProvisioned {
+                                key_id_guard,
+                                attestation_key,
+                                attestation_certs,
+                            }
+                        })
+                    })
+            }
+        }
         None => Ok(None),
         Some(attest_key) => get_user_generated_attestation_key(attest_key, caller_uid, db)
             .context(ks_err!("Trying to load attest key"))
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
index 425812f..ed59578 100644
--- a/keystore2/src/globals.rs
+++ b/keystore2/src/globals.rs
@@ -441,13 +441,12 @@
 static REMOTE_PROVISIONING_HAL_SERVICE_NAME: &str =
     "android.hardware.security.keymint.IRemotelyProvisionedComponent";
 
-fn connect_remotely_provisioned_component(
-    security_level: &SecurityLevel,
-) -> Result<Strong<dyn IRemotelyProvisionedComponent>> {
+/// Get the service name of a remotely provisioned component corresponding to given security level.
+pub fn get_remotely_provisioned_component_name(security_level: &SecurityLevel) -> Result<String> {
     let remotely_prov_instances =
         get_aidl_instances("android.hardware.security.keymint", 1, "IRemotelyProvisionedComponent");
 
-    let service_name = match *security_level {
+    match *security_level {
         SecurityLevel::TRUSTED_ENVIRONMENT => {
             if remotely_prov_instances.iter().any(|instance| *instance == "default") {
                 Some(format!("{}/default", REMOTE_PROVISIONING_HAL_SERVICE_NAME))
@@ -465,8 +464,13 @@
         _ => None,
     }
     .ok_or(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))
-    .context(ks_err!())?;
+    .context(ks_err!())
+}
 
+fn connect_remotely_provisioned_component(
+    security_level: &SecurityLevel,
+) -> Result<Strong<dyn IRemotelyProvisionedComponent>> {
+    let service_name = get_remotely_provisioned_component_name(security_level)?;
     let rem_prov_hal: Strong<dyn IRemotelyProvisionedComponent> =
         map_binder_status_code(binder::get_interface(&service_name))
             .context(ks_err!("Trying to connect to RemotelyProvisionedComponent service."))?;
diff --git a/keystore2/src/lib.rs b/keystore2/src/lib.rs
index 0b830be..9794889 100644
--- a/keystore2/src/lib.rs
+++ b/keystore2/src/lib.rs
@@ -38,6 +38,7 @@
 pub mod permission;
 pub mod raw_device;
 pub mod remote_provisioning;
+pub mod rkpd_client;
 pub mod security_level;
 pub mod service;
 pub mod shared_secret_negotiation;
diff --git a/keystore2/src/remote_provisioning.rs b/keystore2/src/remote_provisioning.rs
index fec1b92..cb2962a 100644
--- a/keystore2/src/remote_provisioning.rs
+++ b/keystore2/src/remote_provisioning.rs
@@ -53,6 +53,7 @@
 use crate::ks_err;
 use crate::metrics_store::log_rkp_error_stats;
 use crate::permission::KeystorePerm;
+use crate::rkpd_client::get_rkpd_attestation_key;
 use crate::utils::{check_keystore_permission, watchdog as wd};
 use android_security_metrics::aidl::android::security::metrics::RkpError::RkpError as MetricsRkpError;
 
@@ -184,7 +185,47 @@
             }
         }
     }
+
+    /// Fetches attestation key and corresponding certificates from RKPD.
+    pub fn get_rkpd_attestation_key_and_certs(
+        &self,
+        key: &KeyDescriptor,
+        caller_uid: u32,
+        params: &[KeyParameter],
+    ) -> Result<Option<(AttestationKey, Certificate)>> {
+        if !self.is_asymmetric_key(params) || key.domain != Domain::APP {
+            Ok(None)
+        } else {
+            match get_rkpd_attestation_key(&self.security_level, caller_uid) {
+                Err(e) => {
+                    if self.is_rkp_only() {
+                        log::error!("Error occurred: {:?}", e);
+                        return Err(e);
+                    }
+                    log::warn!("Error occurred: {:?}", e);
+                    log_rkp_error_stats(
+                        MetricsRkpError::FALL_BACK_DURING_HYBRID,
+                        &self.security_level,
+                    );
+                    Ok(None)
+                }
+                Ok(rkpd_key) => Ok(Some((
+                    AttestationKey {
+                        keyBlob: rkpd_key.keyBlob,
+                        attestKeyParams: vec![],
+                        // Batch certificate is at the beginning of the certificate chain.
+                        issuerSubjectName: parse_subject_from_certificate(
+                            &rkpd_key.encodedCertChain,
+                        )
+                        .context(ks_err!("Failed to parse subject."))?,
+                    },
+                    Certificate { encodedCertificate: rkpd_key.encodedCertChain },
+                ))),
+            }
+        }
+    }
 }
+
 /// Implementation of the IRemoteProvisioning service.
 #[derive(Default)]
 pub struct RemoteProvisioningService {
diff --git a/keystore2/src/rkpd_client.rs b/keystore2/src/rkpd_client.rs
new file mode 100644
index 0000000..2d1b23b
--- /dev/null
+++ b/keystore2/src/rkpd_client.rs
@@ -0,0 +1,387 @@
+// Copyright 2022, 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.
+
+//! Helper wrapper around RKPD interface.
+
+use crate::error::{map_binder_status_code, map_or_log_err, Error, ErrorCode};
+use crate::globals::get_remotely_provisioned_component_name;
+use crate::ks_err;
+use crate::utils::watchdog as wd;
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::SecurityLevel::SecurityLevel;
+use android_security_rkp_aidl::aidl::android::security::rkp::{
+    IGetKeyCallback::BnGetKeyCallback, IGetKeyCallback::IGetKeyCallback,
+    IGetRegistrationCallback::BnGetRegistrationCallback,
+    IGetRegistrationCallback::IGetRegistrationCallback, IRegistration::IRegistration,
+    IRemoteProvisioning::IRemoteProvisioning, RemotelyProvisionedKey::RemotelyProvisionedKey,
+};
+use android_security_rkp_aidl::binder::{BinderFeatures, Interface, Strong};
+use anyhow::{Context, Result};
+use futures::channel::oneshot;
+use futures::executor::block_on;
+use std::sync::Mutex;
+
+type RegistrationSender = oneshot::Sender<Result<binder::Strong<dyn IRegistration>>>;
+
+struct GetRegistrationCallback {
+    registration_tx: Mutex<Option<RegistrationSender>>,
+}
+
+impl GetRegistrationCallback {
+    pub fn new_native_binder(
+        registration_tx: RegistrationSender,
+    ) -> Result<Strong<dyn IGetRegistrationCallback>> {
+        let result: Self =
+            GetRegistrationCallback { registration_tx: Mutex::new(Some(registration_tx)) };
+        Ok(BnGetRegistrationCallback::new_binder(result, BinderFeatures::default()))
+    }
+    fn on_success(&self, registration: &binder::Strong<dyn IRegistration>) -> Result<()> {
+        if let Some(tx) = self.registration_tx.lock().unwrap().take() {
+            tx.send(Ok(registration.clone())).unwrap();
+        }
+        Ok(())
+    }
+    fn on_cancel(&self) -> Result<()> {
+        if let Some(tx) = self.registration_tx.lock().unwrap().take() {
+            tx.send(
+                Err(Error::Km(ErrorCode::OPERATION_CANCELLED))
+                    .context(ks_err!("GetRegistrationCallback cancelled.")),
+            )
+            .unwrap();
+        }
+        Ok(())
+    }
+    fn on_error(&self, error: &str) -> Result<()> {
+        if let Some(tx) = self.registration_tx.lock().unwrap().take() {
+            tx.send(
+                Err(Error::Km(ErrorCode::UNKNOWN_ERROR))
+                    .context(ks_err!("GetRegistrationCallback failed: {:?}", error)),
+            )
+            .unwrap();
+        }
+        Ok(())
+    }
+}
+
+impl Interface for GetRegistrationCallback {}
+
+impl IGetRegistrationCallback for GetRegistrationCallback {
+    fn onSuccess(&self, registration: &Strong<dyn IRegistration>) -> binder::Result<()> {
+        let _wp = wd::watch_millis("IGetRegistrationCallback::onSuccess", 500);
+        map_or_log_err(self.on_success(registration), Ok)
+    }
+    fn onCancel(&self) -> binder::Result<()> {
+        let _wp = wd::watch_millis("IGetRegistrationCallback::onCancel", 500);
+        map_or_log_err(self.on_cancel(), Ok)
+    }
+    fn onError(&self, error: &str) -> binder::Result<()> {
+        let _wp = wd::watch_millis("IGetRegistrationCallback::onError", 500);
+        map_or_log_err(self.on_error(error), Ok)
+    }
+}
+
+/// Make a new connection to a IRegistration service.
+async fn get_rkpd_registration(
+    security_level: &SecurityLevel,
+) -> Result<binder::Strong<dyn IRegistration>> {
+    let remote_provisioning: Strong<dyn IRemoteProvisioning> =
+        map_binder_status_code(binder::get_interface("remote_provisioning"))
+            .context(ks_err!("Trying to connect to IRemoteProvisioning service."))?;
+
+    let rpc_name = get_remotely_provisioned_component_name(security_level)
+        .context(ks_err!("Trying to get IRPC name."))?;
+
+    let (tx, rx) = oneshot::channel();
+    let cb = GetRegistrationCallback::new_native_binder(tx)
+        .context(ks_err!("Trying to create a IGetRegistrationCallback."))?;
+
+    remote_provisioning
+        .getRegistration(&rpc_name, &cb)
+        .context(ks_err!("Trying to get registration."))?;
+
+    rx.await.unwrap()
+}
+
+type KeySender = oneshot::Sender<Result<RemotelyProvisionedKey>>;
+
+struct GetKeyCallback {
+    key_tx: Mutex<Option<KeySender>>,
+}
+
+impl GetKeyCallback {
+    pub fn new_native_binder(key_tx: KeySender) -> Result<Strong<dyn IGetKeyCallback>> {
+        let result: Self = GetKeyCallback { key_tx: Mutex::new(Some(key_tx)) };
+        Ok(BnGetKeyCallback::new_binder(result, BinderFeatures::default()))
+    }
+    fn on_success(&self, key: &RemotelyProvisionedKey) -> Result<()> {
+        if let Some(tx) = self.key_tx.lock().unwrap().take() {
+            tx.send(Ok(RemotelyProvisionedKey {
+                keyBlob: key.keyBlob.clone(),
+                encodedCertChain: key.encodedCertChain.clone(),
+            }))
+            .unwrap();
+        }
+        Ok(())
+    }
+    fn on_cancel(&self) -> Result<()> {
+        if let Some(tx) = self.key_tx.lock().unwrap().take() {
+            tx.send(
+                Err(Error::Km(ErrorCode::OPERATION_CANCELLED))
+                    .context(ks_err!("GetKeyCallback cancelled.")),
+            )
+            .unwrap();
+        }
+        Ok(())
+    }
+    fn on_error(&self, error: &str) -> Result<()> {
+        if let Some(tx) = self.key_tx.lock().unwrap().take() {
+            tx.send(
+                Err(Error::Km(ErrorCode::UNKNOWN_ERROR))
+                    .context(ks_err!("GetKeyCallback failed: {:?}", error)),
+            )
+            .unwrap();
+        }
+        Ok(())
+    }
+}
+
+impl Interface for GetKeyCallback {}
+
+impl IGetKeyCallback for GetKeyCallback {
+    fn onSuccess(&self, key: &RemotelyProvisionedKey) -> binder::Result<()> {
+        let _wp = wd::watch_millis("IGetKeyCallback::onSuccess", 500);
+        map_or_log_err(self.on_success(key), Ok)
+    }
+    fn onCancel(&self) -> binder::Result<()> {
+        let _wp = wd::watch_millis("IGetKeyCallback::onCancel", 500);
+        map_or_log_err(self.on_cancel(), Ok)
+    }
+    fn onError(&self, error: &str) -> binder::Result<()> {
+        let _wp = wd::watch_millis("IGetKeyCallback::onError", 500);
+        map_or_log_err(self.on_error(error), Ok)
+    }
+}
+
+async fn get_rkpd_attestation_key_async(
+    security_level: &SecurityLevel,
+    caller_uid: u32,
+) -> Result<RemotelyProvisionedKey> {
+    let registration = get_rkpd_registration(security_level)
+        .await
+        .context(ks_err!("Trying to get to IRegistration service."))?;
+
+    let (tx, rx) = oneshot::channel();
+    let cb = GetKeyCallback::new_native_binder(tx)
+        .context(ks_err!("Trying to create a IGetKeyCallback."))?;
+
+    registration
+        .getKey(caller_uid.try_into().unwrap(), &cb)
+        .context(ks_err!("Trying to get key."))?;
+
+    rx.await.unwrap()
+}
+
+async fn store_rkpd_attestation_key_async(
+    security_level: &SecurityLevel,
+    key_blob: &[u8],
+    upgraded_blob: &[u8],
+) -> Result<()> {
+    let registration = get_rkpd_registration(security_level)
+        .await
+        .context(ks_err!("Trying to get to IRegistration service."))?;
+
+    registration
+        .storeUpgradedKey(key_blob, upgraded_blob)
+        .context(ks_err!("Failed to store upgraded blob with RKPD."))?;
+    Ok(())
+}
+
+/// Get attestation key from RKPD.
+pub fn get_rkpd_attestation_key(
+    security_level: &SecurityLevel,
+    caller_uid: u32,
+) -> Result<RemotelyProvisionedKey> {
+    let _wp = wd::watch_millis("Calling get_rkpd_attestation_key()", 500);
+    block_on(get_rkpd_attestation_key_async(security_level, caller_uid))
+}
+
+/// Store attestation key in RKPD.
+pub fn store_rkpd_attestation_key(
+    security_level: &SecurityLevel,
+    key_blob: &[u8],
+    upgraded_blob: &[u8],
+) -> Result<()> {
+    let _wp = wd::watch_millis("Calling store_rkpd_attestation_key()", 500);
+    block_on(store_rkpd_attestation_key_async(security_level, key_blob, upgraded_blob))
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use android_security_rkp_aidl::aidl::android::security::rkp::IRegistration::BnRegistration;
+    use std::sync::Arc;
+
+    #[derive(Default)]
+    struct MockRegistrationValues {
+        _key: RemotelyProvisionedKey,
+    }
+
+    #[derive(Default)]
+    struct MockRegistration(Arc<Mutex<MockRegistrationValues>>);
+
+    impl MockRegistration {
+        pub fn new_native_binder() -> Strong<dyn IRegistration> {
+            let result: Self = Default::default();
+            BnRegistration::new_binder(result, BinderFeatures::default())
+        }
+    }
+
+    impl Interface for MockRegistration {}
+
+    impl IRegistration for MockRegistration {
+        fn getKey(&self, _: i32, _: &Strong<dyn IGetKeyCallback>) -> binder::Result<()> {
+            todo!()
+        }
+
+        fn cancelGetKey(&self, _: &Strong<dyn IGetKeyCallback>) -> binder::Result<()> {
+            todo!()
+        }
+
+        fn storeUpgradedKey(&self, _: &[u8], _: &[u8]) -> binder::Result<()> {
+            todo!()
+        }
+    }
+
+    fn get_mock_registration() -> Result<binder::Strong<dyn IRegistration>> {
+        let (tx, rx) = oneshot::channel();
+        let cb = GetRegistrationCallback::new_native_binder(tx).unwrap();
+        let mock_registration = MockRegistration::new_native_binder();
+
+        assert!(cb.onSuccess(&mock_registration).is_ok());
+        block_on(rx).unwrap()
+    }
+
+    #[test]
+    fn test_get_registration_cb_success() {
+        let registration = get_mock_registration();
+        assert!(registration.is_ok());
+    }
+
+    #[test]
+    fn test_get_registration_cb_cancel() {
+        let (tx, rx) = oneshot::channel();
+        let cb = GetRegistrationCallback::new_native_binder(tx).unwrap();
+        assert!(cb.onCancel().is_ok());
+
+        let result = block_on(rx).unwrap();
+        assert_eq!(
+            result.unwrap_err().downcast::<Error>().unwrap(),
+            Error::Km(ErrorCode::OPERATION_CANCELLED)
+        );
+    }
+
+    #[test]
+    fn test_get_registration_cb_error() {
+        let (tx, rx) = oneshot::channel();
+        let cb = GetRegistrationCallback::new_native_binder(tx).unwrap();
+        assert!(cb.onError("error").is_ok());
+
+        let result = block_on(rx).unwrap();
+        assert_eq!(
+            result.unwrap_err().downcast::<Error>().unwrap(),
+            Error::Km(ErrorCode::UNKNOWN_ERROR)
+        );
+    }
+
+    #[test]
+    fn test_get_key_cb_success() {
+        let mock_key =
+            RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] };
+        let (tx, rx) = oneshot::channel();
+        let cb = GetKeyCallback::new_native_binder(tx).unwrap();
+        assert!(cb.onSuccess(&mock_key).is_ok());
+
+        let key = block_on(rx).unwrap().unwrap();
+        assert_eq!(key, mock_key);
+    }
+
+    #[test]
+    fn test_get_key_cb_cancel() {
+        let (tx, rx) = oneshot::channel();
+        let cb = GetKeyCallback::new_native_binder(tx).unwrap();
+        assert!(cb.onCancel().is_ok());
+
+        let result = block_on(rx).unwrap();
+        assert_eq!(
+            result.unwrap_err().downcast::<Error>().unwrap(),
+            Error::Km(ErrorCode::OPERATION_CANCELLED)
+        );
+    }
+
+    #[test]
+    fn test_get_key_cb_error() {
+        let (tx, rx) = oneshot::channel();
+        let cb = GetKeyCallback::new_native_binder(tx).unwrap();
+        assert!(cb.onError("error").is_ok());
+
+        let result = block_on(rx).unwrap();
+        assert_eq!(
+            result.unwrap_err().downcast::<Error>().unwrap(),
+            Error::Km(ErrorCode::UNKNOWN_ERROR)
+        );
+    }
+
+    #[test]
+    #[ignore]
+    fn test_get_rkpd_attestation_key() {
+        let key = get_rkpd_attestation_key(&SecurityLevel::TRUSTED_ENVIRONMENT, 0).unwrap();
+        assert!(!key.keyBlob.is_empty());
+        assert!(!key.encodedCertChain.is_empty());
+    }
+
+    #[test]
+    #[ignore]
+    fn test_get_rkpd_attestation_key_same_caller() {
+        let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
+        let caller_uid = 0;
+
+        // Multiple calls should return the same key.
+        let first_key = get_rkpd_attestation_key(&sec_level, caller_uid).unwrap();
+        let second_key = get_rkpd_attestation_key(&sec_level, caller_uid).unwrap();
+
+        assert_eq!(first_key.keyBlob, second_key.keyBlob);
+        assert_eq!(first_key.encodedCertChain, second_key.encodedCertChain);
+    }
+
+    #[test]
+    #[ignore]
+    fn test_get_rkpd_attestation_key_different_caller() {
+        let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
+
+        // Different callers should be getting different keys.
+        let first_key = get_rkpd_attestation_key(&sec_level, 1).unwrap();
+        let second_key = get_rkpd_attestation_key(&sec_level, 2).unwrap();
+
+        assert_ne!(first_key.keyBlob, second_key.keyBlob);
+        assert_ne!(first_key.encodedCertChain, second_key.encodedCertChain);
+    }
+
+    #[test]
+    #[ignore]
+    fn test_store_rkpd_attestation_key() {
+        let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
+        let key = get_rkpd_attestation_key(&SecurityLevel::TRUSTED_ENVIRONMENT, 0).unwrap();
+
+        assert!(store_rkpd_attestation_key(&sec_level, &key.keyBlob, &key.keyBlob).is_ok());
+    }
+}
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index 66fcb26..b928fb0 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -26,6 +26,7 @@
 use crate::ks_err;
 use crate::metrics_store::log_key_creation_event_stats;
 use crate::remote_provisioning::RemProvState;
+use crate::rkpd_client::store_rkpd_attestation_key;
 use crate::super_key::{KeyBlob, SuperKeyManager};
 use crate::utils::{
     check_device_attestation_permissions, check_key_permission,
@@ -616,6 +617,30 @@
                     result.certificateChain.push(attestation_certs);
                     result
                 }),
+            Some(AttestationKeyInfo::RkpdProvisioned { attestation_key, attestation_certs }) => {
+                self.upgrade_rkpd_keyblob_if_required_with(&attestation_key.keyBlob, &[], |blob| {
+                    map_km_error({
+                        let _wp = self.watch_millis(
+                            concat!(
+                                "In KeystoreSecurityLevel::generate_key (RkpdProvisioned): ",
+                                "calling generate_key.",
+                            ),
+                            5000, // Generate can take a little longer.
+                        );
+                        let dynamic_attest_key = Some(AttestationKey {
+                            keyBlob: blob.to_vec(),
+                            attestKeyParams: vec![],
+                            issuerSubjectName: attestation_key.issuerSubjectName.clone(),
+                        });
+                        self.keymint.generateKey(&params, dynamic_attest_key.as_ref())
+                    })
+                })
+                .context("While generating Key with remote provisioned attestation key.")
+                .map(|(mut result, _)| {
+                    result.certificateChain.push(attestation_certs);
+                    result
+                })
+            }
             None => map_km_error({
                 let _wp = self.watch_millis(
                     concat!(
@@ -888,6 +913,28 @@
         Ok((v, upgraded_blob))
     }
 
+    fn upgrade_rkpd_keyblob_if_required_with<T, F>(
+        &self,
+        key_blob: &[u8],
+        params: &[KeyParameter],
+        f: F,
+    ) -> Result<(T, Option<Vec<u8>>)>
+    where
+        F: Fn(&[u8]) -> Result<T, Error>,
+    {
+        crate::utils::upgrade_keyblob_if_required_with(
+            &*self.keymint,
+            key_blob,
+            params,
+            f,
+            |upgraded_blob| {
+                store_rkpd_attestation_key(&self.security_level, key_blob, upgraded_blob)
+                    .context(ks_err!("Failed store_rkpd_attestation_key()."))
+            },
+        )
+        .context(ks_err!())
+    }
+
     fn convert_storage_key_to_ephemeral(
         &self,
         storage_key: &KeyDescriptor,