Add remote key provisioning to the IC HAL
The IIdentityCredentialStore can now advertise the correct
IRemotelyProvisionedComponent that is used for getting remotely
provisioned attestation keys.
IWritableIdentityCredential has a new method so it can accept remotely
provisioned keys.
Update the VTS tests to check the new RKP functionality.
Support RKP in the default identity cred service
Test: VtsHalIdentityTargetTest
Bug: 194696876
Change-Id: I96dcf3027e0f21790c35900ddf8cc0953bd3b1ca
diff --git a/identity/aidl/default/common/IdentityCredential.cpp b/identity/aidl/default/common/IdentityCredential.cpp
index 7678ecb..ff80752 100644
--- a/identity/aidl/default/common/IdentityCredential.cpp
+++ b/identity/aidl/default/common/IdentityCredential.cpp
@@ -1012,8 +1012,8 @@
IIdentityCredentialStore::STATUS_FAILED, "Error creating provisioning proxy"));
}
shared_ptr<WritableIdentityCredential> wc =
- ndk::SharedRefBase::make<WritableIdentityCredential>(provisioningHwProxy, docType_,
- testCredential_);
+ ndk::SharedRefBase::make<WritableIdentityCredential>(
+ provisioningHwProxy, docType_, testCredential_, hardwareInformation_);
if (!wc->initializeForUpdate(encryptedCredentialKeys_)) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_FAILED,
diff --git a/identity/aidl/default/common/IdentityCredential.h b/identity/aidl/default/common/IdentityCredential.h
index 2935fb8..5929829 100644
--- a/identity/aidl/default/common/IdentityCredential.h
+++ b/identity/aidl/default/common/IdentityCredential.h
@@ -48,11 +48,13 @@
public:
IdentityCredential(sp<SecureHardwareProxyFactory> hwProxyFactory,
const vector<uint8_t>& credentialData,
- std::shared_ptr<PresentationSession> session)
+ std::shared_ptr<PresentationSession> session,
+ HardwareInformation hardwareInformation)
: hwProxyFactory_(hwProxyFactory),
credentialData_(credentialData),
session_(std::move(session)),
numStartRetrievalCalls_(0),
+ hardwareInformation_(std::move(hardwareInformation)),
expectedDeviceNameSpacesSize_(0) {}
// Parses and decrypts credentialData_, return a status code from
@@ -103,6 +105,7 @@
vector<uint8_t> credentialData_;
shared_ptr<PresentationSession> session_;
int numStartRetrievalCalls_;
+ HardwareInformation hardwareInformation_;
// Set by initialize()
string docType_;
diff --git a/identity/aidl/default/common/IdentityCredentialStore.cpp b/identity/aidl/default/common/IdentityCredentialStore.cpp
index 4703ffe..bbc2cef 100644
--- a/identity/aidl/default/common/IdentityCredentialStore.cpp
+++ b/identity/aidl/default/common/IdentityCredentialStore.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "IdentityCredentialStore"
#include <android-base/logging.h>
+#include <android/binder_manager.h>
#include "IdentityCredential.h"
#include "IdentityCredentialStore.h"
@@ -25,15 +26,24 @@
namespace aidl::android::hardware::identity {
+using ::aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent;
+
+IdentityCredentialStore::IdentityCredentialStore(sp<SecureHardwareProxyFactory> hwProxyFactory,
+ optional<string> remotelyProvisionedComponent)
+ : hwProxyFactory_(hwProxyFactory),
+ remotelyProvisionedComponentName_(remotelyProvisionedComponent) {
+ hardwareInformation_.credentialStoreName = "Identity Credential Reference Implementation";
+ hardwareInformation_.credentialStoreAuthorName = "Google";
+ hardwareInformation_.dataChunkSize = kGcmChunkSize;
+ hardwareInformation_.isDirectAccess = false;
+ hardwareInformation_.supportedDocTypes = {};
+ hardwareInformation_.isRemoteKeyProvisioningSupported =
+ remotelyProvisionedComponentName_.has_value();
+}
+
ndk::ScopedAStatus IdentityCredentialStore::getHardwareInformation(
HardwareInformation* hardwareInformation) {
- HardwareInformation hw;
- hw.credentialStoreName = "Identity Credential Reference Implementation";
- hw.credentialStoreAuthorName = "Google";
- hw.dataChunkSize = kGcmChunkSize;
- hw.isDirectAccess = false;
- hw.supportedDocTypes = {};
- *hardwareInformation = hw;
+ *hardwareInformation = hardwareInformation_;
return ndk::ScopedAStatus::ok();
}
@@ -42,7 +52,8 @@
shared_ptr<IWritableIdentityCredential>* outWritableCredential) {
sp<SecureHardwareProvisioningProxy> hwProxy = hwProxyFactory_->createProvisioningProxy();
shared_ptr<WritableIdentityCredential> wc =
- ndk::SharedRefBase::make<WritableIdentityCredential>(hwProxy, docType, testCredential);
+ ndk::SharedRefBase::make<WritableIdentityCredential>(hwProxy, docType, testCredential,
+ hardwareInformation_);
if (!wc->initialize()) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_FAILED,
@@ -63,7 +74,7 @@
}
shared_ptr<IdentityCredential> credential = ndk::SharedRefBase::make<IdentityCredential>(
- hwProxyFactory_, credentialData, nullptr /* session */);
+ hwProxyFactory_, credentialData, nullptr /* session */, hardwareInformation_);
auto ret = credential->initialize();
if (ret != IIdentityCredentialStore::STATUS_OK) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -83,8 +94,8 @@
}
sp<SecureHardwareSessionProxy> hwProxy = hwProxyFactory_->createSessionProxy();
- shared_ptr<PresentationSession> session =
- ndk::SharedRefBase::make<PresentationSession>(hwProxyFactory_, hwProxy);
+ shared_ptr<PresentationSession> session = ndk::SharedRefBase::make<PresentationSession>(
+ hwProxyFactory_, hwProxy, hardwareInformation_);
auto ret = session->initialize();
if (ret != IIdentityCredentialStore::STATUS_OK) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -94,4 +105,23 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus IdentityCredentialStore::getRemotelyProvisionedComponent(
+ shared_ptr<IRemotelyProvisionedComponent>* outRemotelyProvisionedComponent) {
+ if (!remotelyProvisionedComponentName_) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(
+ EX_UNSUPPORTED_OPERATION, "Remote key provisioning is not supported"));
+ }
+
+ ndk::SpAIBinder binder(
+ AServiceManager_waitForService(remotelyProvisionedComponentName_->c_str()));
+ if (binder.get() == nullptr) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED,
+ "Unable to get remotely provisioned component"));
+ }
+
+ *outRemotelyProvisionedComponent = IRemotelyProvisionedComponent::fromBinder(binder);
+ return ndk::ScopedAStatus::ok();
+}
+
} // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/common/IdentityCredentialStore.h b/identity/aidl/default/common/IdentityCredentialStore.h
index 77b894d..dd1261b 100644
--- a/identity/aidl/default/common/IdentityCredentialStore.h
+++ b/identity/aidl/default/common/IdentityCredentialStore.h
@@ -18,6 +18,7 @@
#define ANDROID_HARDWARE_IDENTITY_IDENTITYCREDENTIALSTORE_H
#include <aidl/android/hardware/identity/BnIdentityCredentialStore.h>
+#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
#include "SecureHardwareProxy.h"
@@ -25,14 +26,18 @@
using ::android::sp;
using ::android::hardware::identity::SecureHardwareProxyFactory;
+using ::std::optional;
using ::std::shared_ptr;
using ::std::string;
using ::std::vector;
class IdentityCredentialStore : public BnIdentityCredentialStore {
public:
- IdentityCredentialStore(sp<SecureHardwareProxyFactory> hwProxyFactory)
- : hwProxyFactory_(hwProxyFactory) {}
+ // If remote key provisioning is supported, pass the service name for the correct
+ // IRemotelyProvisionedComponent to the remotelyProvisionedComponent parameter. Else
+ // pass std::nullopt to indicate remote key provisioning is not supported.
+ IdentityCredentialStore(sp<SecureHardwareProxyFactory> hwProxyFactory,
+ optional<string> remotelyProvisionedComponent);
// The GCM chunk size used by this implementation is 64 KiB.
static constexpr size_t kGcmChunkSize = 64 * 1024;
@@ -50,8 +55,14 @@
ndk::ScopedAStatus createPresentationSession(
CipherSuite cipherSuite, shared_ptr<IPresentationSession>* outSession) override;
+ ndk::ScopedAStatus getRemotelyProvisionedComponent(
+ shared_ptr<::aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent>*
+ outRemotelyProvisionedComponent) override;
+
private:
sp<SecureHardwareProxyFactory> hwProxyFactory_;
+ optional<string> remotelyProvisionedComponentName_;
+ HardwareInformation hardwareInformation_;
};
} // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/common/PresentationSession.cpp b/identity/aidl/default/common/PresentationSession.cpp
index fbd8972..2eb7f2e 100644
--- a/identity/aidl/default/common/PresentationSession.cpp
+++ b/identity/aidl/default/common/PresentationSession.cpp
@@ -122,8 +122,8 @@
ndk::ScopedAStatus PresentationSession::getCredential(
const vector<uint8_t>& credentialData, shared_ptr<IIdentityCredential>* outCredential) {
shared_ptr<PresentationSession> p = ref<PresentationSession>();
- shared_ptr<IdentityCredential> credential =
- ndk::SharedRefBase::make<IdentityCredential>(hwProxyFactory_, credentialData, p);
+ shared_ptr<IdentityCredential> credential = ndk::SharedRefBase::make<IdentityCredential>(
+ hwProxyFactory_, credentialData, p, hardwareInformation_);
int ret = credential->initialize();
if (ret != IIdentityCredentialStore::STATUS_OK) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
diff --git a/identity/aidl/default/common/PresentationSession.h b/identity/aidl/default/common/PresentationSession.h
index 76ca67b..4cb174a 100644
--- a/identity/aidl/default/common/PresentationSession.h
+++ b/identity/aidl/default/common/PresentationSession.h
@@ -38,8 +38,11 @@
class PresentationSession : public BnPresentationSession {
public:
PresentationSession(sp<SecureHardwareProxyFactory> hwProxyFactory,
- sp<SecureHardwareSessionProxy> hwProxy)
- : hwProxyFactory_(std::move(hwProxyFactory)), hwProxy_(std::move(hwProxy)) {}
+ sp<SecureHardwareSessionProxy> hwProxy,
+ HardwareInformation hardwareInformation)
+ : hwProxyFactory_(std::move(hwProxyFactory)),
+ hwProxy_(std::move(hwProxy)),
+ hardwareInformation_(std::move(hardwareInformation)) {}
virtual ~PresentationSession();
@@ -65,6 +68,7 @@
// Set by constructor
sp<SecureHardwareProxyFactory> hwProxyFactory_;
sp<SecureHardwareSessionProxy> hwProxy_;
+ HardwareInformation hardwareInformation_;
// Set by initialize()
uint64_t id_;
diff --git a/identity/aidl/default/common/SecureHardwareProxy.h b/identity/aidl/default/common/SecureHardwareProxy.h
index a580444..9f63ad8 100644
--- a/identity/aidl/default/common/SecureHardwareProxy.h
+++ b/identity/aidl/default/common/SecureHardwareProxy.h
@@ -82,6 +82,18 @@
virtual optional<vector<uint8_t>> createCredentialKey(const vector<uint8_t>& challenge,
const vector<uint8_t>& applicationId) = 0;
+ // Returns public key certificate with a remotely provisioned attestation key.
+ //
+ // This returns a single certificate that is signed by the given |attestationKeyBlob|.
+ // The implementation of eicOpsCreateCredentialKey() on the TA side must coordinate
+ // with its corresponding keymint implementation to sign using the attestation key. The
+ // |attestationKeyCert| parameter is the certificates for |attestationKeyBlob|,
+ // formatted as concatenated, DER-encoded, X.509 certificates.
+ virtual optional<vector<uint8_t>> createCredentialKeyUsingRkp(
+ const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+ const vector<uint8_t>& attestationKeyBlob,
+ const vector<uint8_t>& attestationKeyCert) = 0;
+
virtual bool startPersonalization(int accessControlProfileCount, const vector<int>& entryCounts,
const string& docType,
size_t expectedProofOfProvisioningSize) = 0;
diff --git a/identity/aidl/default/common/WritableIdentityCredential.cpp b/identity/aidl/default/common/WritableIdentityCredential.cpp
index 200ee61..e420a7b 100644
--- a/identity/aidl/default/common/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/common/WritableIdentityCredential.cpp
@@ -79,8 +79,15 @@
IIdentityCredentialStore::STATUS_INVALID_DATA, "Challenge can not be empty"));
}
- optional<vector<uint8_t>> certChain =
- hwProxy_->createCredentialKey(attestationChallenge, attestationApplicationId);
+ optional<vector<uint8_t>> certChain;
+ if (attestationKeyBlob_ && attestationCertificateChain_) {
+ certChain = hwProxy_->createCredentialKeyUsingRkp(
+ attestationChallenge, attestationApplicationId, *attestationKeyBlob_,
+ attestationCertificateChain_->at(0));
+ } else {
+ certChain = hwProxy_->createCredentialKey(attestationChallenge, attestationApplicationId);
+ }
+
if (!certChain) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_FAILED,
@@ -95,8 +102,14 @@
}
*outCertificateChain = vector<Certificate>();
- for (const vector<uint8_t>& cert : certs.value()) {
- Certificate c = Certificate();
+ for (vector<uint8_t>& cert : certs.value()) {
+ Certificate c;
+ c.encodedCertificate = std::move(cert);
+ outCertificateChain->push_back(std::move(c));
+ }
+
+ for (const vector<uint8_t>& cert : *attestationCertificateChain_) {
+ Certificate c;
c.encodedCertificate = cert;
outCertificateChain->push_back(std::move(c));
}
@@ -402,4 +415,36 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus WritableIdentityCredential::setRemotelyProvisionedAttestationKey(
+ const vector<uint8_t>& attestationKeyBlob,
+ const vector<uint8_t>& attestationCertificateChain) {
+ if (!hardwareInformation_.isRemoteKeyProvisioningSupported) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(
+ EX_UNSUPPORTED_OPERATION, "Remote key provisioning is not supported"));
+ }
+
+ if (attestationKeyBlob.empty() || attestationCertificateChain.empty()) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED,
+ "Empty data passed to setRemotlyProvisionedAttestationKey"));
+ }
+
+ if (attestationKeyBlob_.has_value()) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED, "Attestation key already set"));
+ }
+
+ optional<vector<vector<uint8_t>>> certs =
+ support::certificateChainSplit(attestationCertificateChain);
+ if (!certs) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED,
+ "Error splitting chain into separate certificates"));
+ }
+
+ attestationKeyBlob_ = attestationKeyBlob;
+ attestationCertificateChain_ = *certs;
+ return ndk::ScopedAStatus::ok();
+}
+
} // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/common/WritableIdentityCredential.h b/identity/aidl/default/common/WritableIdentityCredential.h
index 36ad430..39d32c9 100644
--- a/identity/aidl/default/common/WritableIdentityCredential.h
+++ b/identity/aidl/default/common/WritableIdentityCredential.h
@@ -30,6 +30,7 @@
using ::android::sp;
using ::android::hardware::identity::SecureHardwareProvisioningProxy;
+using ::std::optional;
using ::std::set;
using ::std::string;
using ::std::vector;
@@ -41,8 +42,11 @@
// For an updated credential, call initializeForUpdate() right after construction.
//
WritableIdentityCredential(sp<SecureHardwareProvisioningProxy> hwProxy, const string& docType,
- bool testCredential)
- : hwProxy_(hwProxy), docType_(docType), testCredential_(testCredential) {}
+ bool testCredential, HardwareInformation hardwareInformation)
+ : hwProxy_(hwProxy),
+ docType_(docType),
+ testCredential_(testCredential),
+ hardwareInformation_(std::move(hardwareInformation)) {}
~WritableIdentityCredential();
@@ -78,11 +82,16 @@
vector<uint8_t>* outCredentialData,
vector<uint8_t>* outProofOfProvisioningSignature) override;
+ ndk::ScopedAStatus setRemotelyProvisionedAttestationKey(
+ const vector<uint8_t>& attestationKeyBlob,
+ const vector<uint8_t>& attestationCertificateChain) override;
+
private:
// Set by constructor.
sp<SecureHardwareProvisioningProxy> hwProxy_;
string docType_;
bool testCredential_;
+ HardwareInformation hardwareInformation_;
// This is set in initialize().
bool startPersonalizationCalled_;
@@ -109,6 +118,10 @@
vector<int32_t> entryAccessControlProfileIds_;
vector<uint8_t> entryBytes_;
set<string> allNameSpaces_;
+
+ // Remotely provisioned attestation data, set via setRemotelyProvisionedAttestationKey
+ optional<vector<uint8_t>> attestationKeyBlob_;
+ optional<vector<vector<uint8_t>>> attestationCertificateChain_;
};
} // namespace aidl::android::hardware::identity