Integrate PureSoftKeymaster in secure_env.
Bug: 155328335
Test: m secure_env
Change-Id: I45be3620c61c916c790b0f4dc31669af31b334c7
diff --git a/host/commands/secure_env/Android.bp b/host/commands/secure_env/Android.bp
index 018718c..8d8efe7 100644
--- a/host/commands/secure_env/Android.bp
+++ b/host/commands/secure_env/Android.bp
@@ -16,11 +16,13 @@
cc_binary_host {
name: "secure_env",
srcs: [
+ "keymaster_responder.cpp",
"secure_env.cpp",
],
shared_libs: [
"libbase",
"libcuttlefish_fs",
+ "libcuttlefish_security",
"libcuttlefish_utils",
"libkeymaster_portable",
"libkeymaster_messages",
@@ -28,9 +30,13 @@
"liblog",
"libcrypto",
"libcutils",
+ "libpuresoftkeymasterdevice_host",
],
static_libs: [
"libgflags",
],
defaults: ["cuttlefish_host_only"],
+ cflags: [
+ "-fno-rtti", // Required for libkeymaster_portable
+ ],
}
diff --git a/host/commands/secure_env/keymaster_responder.cpp b/host/commands/secure_env/keymaster_responder.cpp
new file mode 100644
index 0000000..2076866
--- /dev/null
+++ b/host/commands/secure_env/keymaster_responder.cpp
@@ -0,0 +1,104 @@
+//
+// Copyright (C) 2020 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 "keymaster_responder.h"
+
+#include <android-base/logging.h>
+#include <keymaster/android_keymaster_messages.h>
+
+KeymasterResponder::KeymasterResponder(
+ cvd::KeymasterChannel* channel, keymaster::AndroidKeymaster* keymaster)
+ : channel_(channel), keymaster_(keymaster) {
+}
+
+bool KeymasterResponder::ProcessMessage() {
+ auto request = channel_->ReceiveMessage();
+ if (!request) {
+ LOG(ERROR) << "Could not receive message";
+ return false;
+ }
+ const uint8_t* buffer = request->payload;
+ const uint8_t* end = request->payload + request->payload_size;
+ switch(request->cmd) {
+ using namespace keymaster;
+#define HANDLE_MESSAGE(ENUM_NAME, METHOD_NAME) \
+ case ENUM_NAME: {\
+ METHOD_NAME##Request request; \
+ if (!request.Deserialize(&buffer, end)) { \
+ LOG(ERROR) << "Failed to deserialize " #METHOD_NAME "Request"; \
+ return false; \
+ } \
+ METHOD_NAME##Response response; \
+ keymaster_->METHOD_NAME(request, &response); \
+ return channel_->SendResponse(ENUM_NAME, response); \
+ }
+ HANDLE_MESSAGE(GENERATE_KEY, GenerateKey)
+ HANDLE_MESSAGE(BEGIN_OPERATION, BeginOperation)
+ HANDLE_MESSAGE(UPDATE_OPERATION, UpdateOperation)
+ HANDLE_MESSAGE(FINISH_OPERATION, FinishOperation)
+ HANDLE_MESSAGE(ABORT_OPERATION, AbortOperation)
+ HANDLE_MESSAGE(IMPORT_KEY, ImportKey)
+ HANDLE_MESSAGE(EXPORT_KEY, ExportKey)
+ HANDLE_MESSAGE(GET_VERSION, GetVersion)
+ HANDLE_MESSAGE(GET_SUPPORTED_ALGORITHMS, SupportedAlgorithms)
+ HANDLE_MESSAGE(GET_SUPPORTED_BLOCK_MODES, SupportedBlockModes)
+ HANDLE_MESSAGE(GET_SUPPORTED_PADDING_MODES, SupportedPaddingModes)
+ HANDLE_MESSAGE(GET_SUPPORTED_DIGESTS, SupportedDigests)
+ HANDLE_MESSAGE(GET_SUPPORTED_IMPORT_FORMATS, SupportedImportFormats)
+ HANDLE_MESSAGE(GET_SUPPORTED_EXPORT_FORMATS, SupportedExportFormats)
+ HANDLE_MESSAGE(GET_KEY_CHARACTERISTICS, GetKeyCharacteristics)
+ HANDLE_MESSAGE(ATTEST_KEY, AttestKey)
+ HANDLE_MESSAGE(UPGRADE_KEY, UpgradeKey)
+ HANDLE_MESSAGE(CONFIGURE, Configure)
+ HANDLE_MESSAGE(DELETE_KEY, DeleteKey)
+ HANDLE_MESSAGE(DELETE_ALL_KEYS, DeleteAllKeys)
+ HANDLE_MESSAGE(IMPORT_WRAPPED_KEY, ImportWrappedKey)
+#undef HANDLE_MESSAGE
+#define HANDLE_MESSAGE(ENUM_NAME, METHOD_NAME) \
+ case ENUM_NAME: {\
+ METHOD_NAME##Request request; \
+ if (!request.Deserialize(&buffer, end)) { \
+ LOG(ERROR) << "Failed to deserialize " #METHOD_NAME "Request"; \
+ return false; \
+ } \
+ auto response = keymaster_->METHOD_NAME(request); \
+ return channel_->SendResponse(ENUM_NAME, response); \
+ }
+ HANDLE_MESSAGE(COMPUTE_SHARED_HMAC, ComputeSharedHmac)
+ HANDLE_MESSAGE(VERIFY_AUTHORIZATION, VerifyAuthorization)
+#undef HANDLE_MESSAGE
+#define HANDLE_MESSAGE(ENUM_NAME, METHOD_NAME) \
+ case ENUM_NAME: {\
+ auto response = keymaster_->METHOD_NAME(); \
+ return channel_->SendResponse(ENUM_NAME, response); \
+ }
+ HANDLE_MESSAGE(GET_HMAC_SHARING_PARAMETERS, GetHmacSharingParameters)
+ HANDLE_MESSAGE(EARLY_BOOT_ENDED, EarlyBootEnded)
+ case ADD_RNG_ENTROPY: {
+ AddEntropyRequest request;
+ if (!request.Deserialize(&buffer, end)) {
+ LOG(ERROR) << "Failed to deserialize AddEntropyRequest";
+ return false;
+ }
+ AddEntropyResponse response;
+ keymaster_->AddRngEntropy(request, &response);
+ return channel_->SendResponse(ADD_RNG_ENTROPY, response);
+ }
+ case DESTROY_ATTESTATION_IDS: // Not defined in AndroidKeymaster?
+ break;
+ }
+ LOG(ERROR) << "Unknown request type: " << request->cmd;
+ return false;
+}
diff --git a/host/commands/secure_env/keymaster_responder.h b/host/commands/secure_env/keymaster_responder.h
new file mode 100644
index 0000000..b30c6a4
--- /dev/null
+++ b/host/commands/secure_env/keymaster_responder.h
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2020 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 <keymaster/android_keymaster.h>
+
+#include "common/libs/security/keymaster_channel.h"
+
+class KeymasterResponder {
+private:
+ cvd::KeymasterChannel* channel_;
+ keymaster::AndroidKeymaster* keymaster_;
+public:
+ KeymasterResponder(cvd::KeymasterChannel* channel,
+ keymaster::AndroidKeymaster* keymaster);
+
+ bool ProcessMessage();
+};
diff --git a/host/commands/secure_env/secure_env.cpp b/host/commands/secure_env/secure_env.cpp
index 60fc23b..c9edc6b 100644
--- a/host/commands/secure_env/secure_env.cpp
+++ b/host/commands/secure_env/secure_env.cpp
@@ -13,5 +13,39 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-int main() {
+#include <android-base/logging.h>
+#include <gflags/gflags.h>
+#include <keymaster/android_keymaster.h>
+#include <keymaster/contexts/pure_soft_keymaster_context.h>
+
+#include "common/libs/fs/shared_fd.h"
+#include "common/libs/security/keymaster_channel.h"
+#include "host/commands/secure_env/keymaster_responder.h"
+
+// Copied from AndroidKeymaster4Device
+constexpr size_t kOperationTableSize = 16;
+
+DEFINE_int32(keymaster_fd, -1, "A file descriptor for keymaster communication");
+
+int main(int argc, char** argv) {
+ ::android::base::InitLogging(argv);
+ gflags::ParseCommandLineFlags(&argc, &argv, true);
+ keymaster::PureSoftKeymasterContext keymaster_context{
+ KM_SECURITY_LEVEL_SOFTWARE};
+ keymaster::AndroidKeymaster keymaster{&keymaster_context, kOperationTableSize};
+
+ CHECK(FLAGS_keymaster_fd != -1)
+ << "TODO(schuffelen): Add keymaster_fd alternative";
+ auto server = cvd::SharedFD::Dup(FLAGS_keymaster_fd);
+ CHECK(server->IsOpen()) << "Could not dup server fd: " << server->StrError();
+ close(FLAGS_keymaster_fd);
+ auto conn = cvd::SharedFD::Accept(*server);
+ CHECK(conn->IsOpen()) << "Unable to open connection: " << conn->StrError();
+ cvd::KeymasterChannel keymaster_channel(conn);
+
+ KeymasterResponder keymaster_responder(&keymaster_channel, &keymaster);
+
+ // TODO(schuffelen): Do this in a thread when adding other HALs
+ while (keymaster_responder.ProcessMessage()) {
+ }
}