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()) {
+  }
 }