Merge changes I0049d5ba,I28ebc5a2
* changes:
identity: Replace RemotelyProvisionedKey with librkp_support
Add helper library to get remotely provisioned key
diff --git a/identity/Android.bp b/identity/Android.bp
index ecf667d..f4fcc0a 100644
--- a/identity/Android.bp
+++ b/identity/Android.bp
@@ -36,7 +36,6 @@
"CredentialData.cpp",
"CredentialStore.cpp",
"CredentialStoreFactory.cpp",
- "RemotelyProvisionedKey.cpp",
"Session.cpp",
"Util.cpp",
"WritableCredential.cpp",
@@ -55,6 +54,7 @@
"libhidlbase",
"libkeymaster4support",
"libkeystore-attestation-application-id",
+ "librkp_support",
"libutils",
"libutilscallstack",
"libvintf",
diff --git a/identity/CredentialStore.cpp b/identity/CredentialStore.cpp
index e200cb5..cb2e8c7 100644
--- a/identity/CredentialStore.cpp
+++ b/identity/CredentialStore.cpp
@@ -24,12 +24,12 @@
#include <android/hardware/security/keymint/RpcHardwareInfo.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
+#include <rkp/support/rkpd_client.h>
#include <vintf/VintfObject.h>
#include "Credential.h"
#include "CredentialData.h"
#include "CredentialStore.h"
-#include "RemotelyProvisionedKey.h"
#include "Session.h"
#include "Util.h"
#include "WritableCredential.h"
@@ -39,7 +39,8 @@
namespace identity {
namespace {
-using ::android::security::rkp::IRemoteProvisioning;
+using ::android::security::rkp::RemotelyProvisionedKey;
+using ::android::security::rkp::support::getRpcKey;
} // namespace
@@ -183,17 +184,7 @@
LOG(INFO) << "Fetching attestation key from RKPD";
uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
- auto rpcKeyFuture = getRpcKeyFuture(rpc_, callingUid);
- if (!rpcKeyFuture) {
- return Status::fromServiceSpecificError(ERROR_GENERIC, "Error in getRpcKeyFuture()");
- }
-
- 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();
+ std::optional<RemotelyProvisionedKey> key = getRpcKey(rpc_, callingUid);
if (!key) {
return Status::fromServiceSpecificError(
ERROR_GENERIC, "Failed to get remotely provisioned attestation key");
diff --git a/identity/CredentialStore.h b/identity/CredentialStore.h
index 32c9975..8bc02e8 100644
--- a/identity/CredentialStore.h
+++ b/identity/CredentialStore.h
@@ -22,7 +22,6 @@
#include <android/hardware/identity/IIdentityCredentialStore.h>
#include <android/security/identity/BnCredentialStore.h>
-#include <android/security/rkp/IRemoteProvisioning.h>
namespace android {
namespace security {
diff --git a/provisioner/support/Android.bp b/provisioner/support/Android.bp
new file mode 100644
index 0000000..778b1e0
--- /dev/null
+++ b/provisioner/support/Android.bp
@@ -0,0 +1,64 @@
+// Copyright (C) 2023 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.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["system_security_license"],
+}
+
+cc_defaults {
+ name: "librkp_support_defaults",
+ static_libs: [
+ "android.hardware.security.rkp-V3-cpp",
+ "android.security.rkp_aidl-cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libutils",
+ "libvintf",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+}
+
+cc_library {
+ name: "librkp_support",
+ defaults: ["librkp_support_defaults"],
+ srcs: [
+ "rkpd_client.cpp",
+ ],
+ export_include_dirs: ["include"],
+}
+
+cc_test {
+ name: "librkp_support_test",
+ defaults: [
+ "librkp_support_defaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["test.cpp"],
+ static_libs: [
+ "librkp_support",
+ ],
+ test_suites: ["general-tests"],
+ require_root: true,
+}
diff --git a/provisioner/support/TEST_MAPPING b/provisioner/support/TEST_MAPPING
new file mode 100644
index 0000000..fc30104
--- /dev/null
+++ b/provisioner/support/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "librkp_support_test"
+ }
+ ]
+}
diff --git a/identity/RemotelyProvisionedKey.h b/provisioner/support/include/rkp/support/rkpd_client.h
similarity index 66%
rename from identity/RemotelyProvisionedKey.h
rename to provisioner/support/include/rkp/support/rkpd_client.h
index e7ddfca..5a7fe6e 100644
--- a/identity/RemotelyProvisionedKey.h
+++ b/provisioner/support/include/rkp/support/rkpd_client.h
@@ -20,19 +20,20 @@
#include <optional>
#include <android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
+#include <android/security/rkp/RemotelyProvisionedKey.h>
-namespace android {
-namespace security {
-namespace identity {
+namespace android::security::rkp::support {
using ::android::hardware::security::keymint::IRemotelyProvisionedComponent;
using ::android::security::rkp::RemotelyProvisionedKey;
-std::optional<std::string> getRpcId(const sp<IRemotelyProvisionedComponent>& rpc);
-
+// Callers of getRpcKeyFuture() and getRpcKey() need at least two threads to
+// retrieve the key, one to asynchronously handle binder callbacks and one to
+// wait on the future.
std::optional<std::future<std::optional<RemotelyProvisionedKey>>>
getRpcKeyFuture(const sp<IRemotelyProvisionedComponent>& rpc, int32_t keyId);
-} // namespace identity
-} // namespace security
-} // namespace android
+std::optional<RemotelyProvisionedKey> getRpcKey(const sp<IRemotelyProvisionedComponent>& rpc,
+ int32_t keyId, int32_t timeout_sec = 10);
+
+} // namespace android::security::rkp::support
diff --git a/identity/RemotelyProvisionedKey.cpp b/provisioner/support/rkpd_client.cpp
similarity index 88%
rename from identity/RemotelyProvisionedKey.cpp
rename to provisioner/support/rkpd_client.cpp
index 784a680..0643457 100644
--- a/identity/RemotelyProvisionedKey.cpp
+++ b/provisioner/support/rkpd_client.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_TAG "credstore"
+#define LOG_TAG "rkpd_client"
#include <atomic>
@@ -25,13 +25,10 @@
#include <android/security/rkp/IRemoteProvisioning.h>
#include <binder/IServiceManager.h>
#include <binder/Status.h>
+#include <rkp/support/rkpd_client.h>
#include <vintf/VintfObject.h>
-#include "RemotelyProvisionedKey.h"
-
-namespace android {
-namespace security {
-namespace identity {
+namespace android::security::rkp::support {
namespace {
using ::android::binder::Status;
@@ -46,6 +43,23 @@
constexpr const char* kRemoteProvisioningServiceName = "remote_provisioning";
+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. "
+ << "This is a bug in the vendor implementation.";
+ return std::nullopt;
+ }
+
+ return *rpcHwInfo.uniqueId;
+}
+
std::optional<String16> findRpcNameById(std::string_view targetRpcId) {
auto deviceManifest = vintf::VintfObject::GetDeviceHalManifest();
auto instances = deviceManifest->getAidlInstances("android.hardware.security.keymint",
@@ -157,24 +171,6 @@
} // 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;
@@ -203,6 +199,21 @@
return keyFuture;
}
-} // namespace identity
-} // namespace security
-} // namespace android
+std::optional<RemotelyProvisionedKey> getRpcKey(const sp<IRemotelyProvisionedComponent>& rpc,
+ int32_t keyId, int32_t timeout_sec) {
+ auto rpcKeyFuture = getRpcKeyFuture(rpc, keyId);
+ if (!rpcKeyFuture) {
+ LOG(ERROR) << "Failed getRpcKeyFuture()";
+ return std::nullopt;
+ }
+
+ auto timeout = std::chrono::seconds(timeout_sec);
+ if (rpcKeyFuture->wait_for(timeout) != std::future_status::ready) {
+ LOG(ERROR) << "Waiting for remotely provisioned attestation key timed out";
+ return std::nullopt;
+ }
+
+ return rpcKeyFuture->get();
+}
+
+} // namespace android::security::rkp::support
diff --git a/provisioner/support/test.cpp b/provisioner/support/test.cpp
new file mode 100644
index 0000000..418eab9
--- /dev/null
+++ b/provisioner/support/test.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2023 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 <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <gtest/gtest.h>
+#include <rkp/support/rkpd_client.h>
+
+using ::android::getAidlHalInstanceNames;
+using ::android::sp;
+using ::android::String16;
+using ::android::hardware::security::keymint::IRemotelyProvisionedComponent;
+using ::android::security::rkp::RemotelyProvisionedKey;
+using ::android::security::rkp::support::getRpcKey;
+
+// TODO(b/272600606): Add tests for error cases
+class RkpdClientTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ auto rpcName = String16(GetParam().c_str());
+ rpc_ = android::waitForService<IRemotelyProvisionedComponent>(rpcName);
+ ASSERT_NE(rpc_, nullptr);
+ }
+
+ sp<IRemotelyProvisionedComponent> rpc_;
+};
+
+TEST_P(RkpdClientTest, getRpcKey) {
+ std::optional<RemotelyProvisionedKey> key = getRpcKey(rpc_, /*keyId=*/0);
+
+ ASSERT_TRUE(key.has_value()) << "Failed to get remotely provisioned attestation key";
+ ASSERT_FALSE(key->keyBlob.empty()) << "Key blob is empty";
+ ASSERT_FALSE(key->encodedCertChain.empty()) << "Certificate is empty";
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, RkpdClientTest,
+ testing::ValuesIn(getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor)),
+ ::android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ testing::InitGoogleTest(&argc, argv);
+
+ // We need one thread to issue requests to RKPD and one to handle
+ // asynchronous responses from RKPD.
+ android::ProcessState::self()->setThreadPoolMaxThreadCount(2);
+ android::ProcessState::self()->startThreadPool();
+ return RUN_ALL_TESTS();
+}