Add support for RKP to credstore
Call out to keystore and request remotely provisioned attestation keys.
This reduces our dependence on factory-provisioned attestation keys.
Test: CtsIdentityTestCases
Bug: 194696876
Change-Id: Ief07750ef6b2a465060c64207063568b9a51af68
diff --git a/identity/CredentialStore.cpp b/identity/CredentialStore.cpp
index 61a9125..c5c429b 100644
--- a/identity/CredentialStore.cpp
+++ b/identity/CredentialStore.cpp
@@ -17,10 +17,15 @@
#define LOG_TAG "credstore"
#include <algorithm>
+#include <optional>
#include <android-base/logging.h>
-
+#include <android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
+#include <android/hardware/security/keymint/RpcHardwareInfo.h>
+#include <android/security/remoteprovisioning/IRemotelyProvisionedKeyPool.h>
+#include <android/security/remoteprovisioning/RemotelyProvisionedKey.h>
#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
#include "Credential.h"
#include "CredentialData.h"
@@ -32,6 +37,46 @@
namespace android {
namespace security {
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;
+
+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;
+}
+
+} // namespace
CredentialStore::CredentialStore(const std::string& dataPath, sp<IIdentityCredentialStore> hal)
: dataPath_(dataPath), hal_(hal) {}
@@ -44,6 +89,16 @@
}
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 << "'";
+ return false;
+ }
+ }
+
LOG(INFO) << "Connected to Identity Credential HAL with API version " << halApiVersion_
<< " and name '" << hwInfo_.credentialStoreName << "' authored by '"
<< hwInfo_.credentialStoreAuthorName << "' with chunk size " << hwInfo_.dataChunkSize
@@ -90,6 +145,13 @@
return halStatusToGenericError(status);
}
+ if (hwInfo_.isRemoteKeyProvisioningSupported) {
+ status = setRemotelyProvisionedAttestationKey(halWritableCredential.get());
+ if (!status.isOk()) {
+ return halStatusToGenericError(status);
+ }
+ }
+
sp<IWritableCredential> writableCredential = new WritableCredential(
dataPath_, credentialName, docType, false, hwInfo_, halWritableCredential);
*_aidl_return = writableCredential;
@@ -145,6 +207,33 @@
return Status::ok();
}
+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");
+ }
+
+ 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);
+ if (!status.isOk()) {
+ LOG(ERROR) << "Error setting remotely provisioned attestation key on credential";
+ return status;
+ }
+
+ return Status::ok();
+}
+
} // namespace identity
} // namespace security
} // namespace android