Add a remote keymint HAL.
Based on files from here:
https://android.googlesource.com/platform/system/keymaster/+/5592969/ng/
https://android.googlesource.com/platform/hardware/interfaces/+/8bfd260/security/keymint/aidl/default/
https://android.googlesource.com/device/google/cuttlefish/+/8577c21/guest/hals/keymaster/remote/
The keymint code is copied over with s/AndroidKeymaster/RemoteKeymaster/
and the RemoteKeymaster code is copied from the Keymaster 4.1
implementation.
Bug: 182928606
Test: m android.hardware.security.keymint-service.remote
Change-Id: If99b44eac253447637d3682cec3d13d7750d3c5b
diff --git a/guest/hals/keymint/OWNERS b/guest/hals/keymint/OWNERS
new file mode 100644
index 0000000..fb015cb
--- /dev/null
+++ b/guest/hals/keymint/OWNERS
@@ -0,0 +1 @@
+include platform/system/keymaster:/OWNERS
diff --git a/guest/hals/keymint/remote/Android.bp b/guest/hals/keymint/remote/Android.bp
new file mode 100644
index 0000000..59c73a4
--- /dev/null
+++ b/guest/hals/keymint/remote/Android.bp
@@ -0,0 +1,56 @@
+//
+// 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.
+
+cc_binary {
+ name: "android.hardware.security.keymint-service.remote",
+ relative_install_path: "hw",
+ init_rc: ["android.hardware.security.keymint-service.remote.rc"],
+ vintf_fragments: [
+ "android.hardware.security.keymint-service.remote.xml",
+ "android.hardware.security.sharedsecret-service.remote.xml",
+ "android.hardware.security.secureclock-service.remote.xml",
+ ],
+ vendor: true,
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ ],
+ shared_libs: [
+ "android.hardware.security.keymint-V1-ndk_platform",
+ "android.hardware.security.sharedsecret-V1-ndk_platform",
+ "android.hardware.security.secureclock-V1-ndk_platform",
+ "libbase",
+ "libbinder_ndk",
+ "libcppbor_external",
+ "libcrypto",
+ "libcuttlefish_fs",
+ "libcuttlefish_security",
+ "libhardware",
+ "libkeymint",
+ "libkeymaster_messages",
+ "liblog",
+ "libutils",
+ ],
+ srcs: [
+ "remote_keymint_device.cpp",
+ "remote_keymint_operation.cpp",
+ "remote_keymaster.cpp",
+ "remote_secure_clock.cpp",
+ "service.cpp",
+ ],
+ defaults: [
+ "cuttlefish_guest_only",
+ ],
+}
diff --git a/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.rc b/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.rc
new file mode 100644
index 0000000..422fe17
--- /dev/null
+++ b/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.rc
@@ -0,0 +1,3 @@
+service vendor.keymint-remote /vendor/bin/hw/android.hardware.security.keymint-service.remote
+ class early_hal
+ user nobody
diff --git a/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.xml b/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.xml
new file mode 100644
index 0000000..4aa05ef
--- /dev/null
+++ b/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.security.keymint</name>
+ <fqname>IKeyMintDevice/default</fqname>
+ </hal>
+ <hal format="aidl">
+ <name>android.hardware.security.keymint</name>
+ <fqname>IRemotelyProvisionedComponent/default</fqname>
+ </hal>
+</manifest>
diff --git a/guest/hals/keymint/remote/android.hardware.security.secureclock-service.remote.xml b/guest/hals/keymint/remote/android.hardware.security.secureclock-service.remote.xml
new file mode 100644
index 0000000..c0ff775
--- /dev/null
+++ b/guest/hals/keymint/remote/android.hardware.security.secureclock-service.remote.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.security.secureclock</name>
+ <fqname>ISecureClock/default</fqname>
+ </hal>
+</manifest>
diff --git a/guest/hals/keymint/remote/android.hardware.security.sharedsecret-service.remote.xml b/guest/hals/keymint/remote/android.hardware.security.sharedsecret-service.remote.xml
new file mode 100644
index 0000000..d37981f
--- /dev/null
+++ b/guest/hals/keymint/remote/android.hardware.security.sharedsecret-service.remote.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.security.sharedsecret</name>
+ <fqname>ISharedSecret/default</fqname>
+ </hal>
+</manifest>
diff --git a/guest/hals/keymint/remote/remote_keymaster.cpp b/guest/hals/keymint/remote/remote_keymaster.cpp
new file mode 100644
index 0000000..4a37cf0
--- /dev/null
+++ b/guest/hals/keymint/remote/remote_keymaster.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2018 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 "remote_keymaster.h"
+
+#include <android-base/logging.h>
+#include <keymaster/android_keymaster_messages.h>
+#include <keymaster/keymaster_configuration.h>
+
+namespace keymaster {
+
+RemoteKeymaster::RemoteKeymaster(cuttlefish::KeymasterChannel* channel)
+ : channel_(channel) {}
+
+RemoteKeymaster::~RemoteKeymaster() {}
+
+void RemoteKeymaster::ForwardCommand(AndroidKeymasterCommand command,
+ const Serializable& req,
+ KeymasterResponse* rsp) {
+ if (!channel_->SendRequest(command, req)) {
+ LOG(ERROR) << "Failed to send keymaster message: " << command;
+ rsp->error = KM_ERROR_UNKNOWN_ERROR;
+ return;
+ }
+ auto response = channel_->ReceiveMessage();
+ if (!response) {
+ LOG(ERROR) << "Failed to receive keymaster response: " << command;
+ rsp->error = KM_ERROR_UNKNOWN_ERROR;
+ return;
+ }
+ const uint8_t* buffer = response->payload;
+ const uint8_t* buffer_end = response->payload + response->payload_size;
+ if (!rsp->Deserialize(&buffer, buffer_end)) {
+ LOG(ERROR) << "Failed to deserialize keymaster response: " << command;
+ rsp->error = KM_ERROR_UNKNOWN_ERROR;
+ return;
+ }
+}
+
+bool RemoteKeymaster::Initialize() {
+ // We don't need to bother with GetVersion, because CF HAL and remote sides
+ // are always compiled together, so will never disagree about message
+ // versions.
+ ConfigureRequest req(message_version());
+ req.os_version = GetOsVersion();
+ req.os_patchlevel = GetOsPatchlevel();
+
+ ConfigureResponse rsp(message_version());
+ Configure(req, &rsp);
+
+ if (rsp.error != KM_ERROR_OK) {
+ LOG(ERROR) << "Failed to configure keymaster: " << rsp.error;
+ return false;
+ }
+
+ return true;
+}
+
+void RemoteKeymaster::GetVersion(const GetVersionRequest& request,
+ GetVersionResponse* response) {
+ ForwardCommand(GET_VERSION, request, response);
+}
+
+void RemoteKeymaster::SupportedAlgorithms(
+ const SupportedAlgorithmsRequest& request,
+ SupportedAlgorithmsResponse* response) {
+ ForwardCommand(GET_SUPPORTED_ALGORITHMS, request, response);
+}
+
+void RemoteKeymaster::SupportedBlockModes(
+ const SupportedBlockModesRequest& request,
+ SupportedBlockModesResponse* response) {
+ ForwardCommand(GET_SUPPORTED_BLOCK_MODES, request, response);
+}
+
+void RemoteKeymaster::SupportedPaddingModes(
+ const SupportedPaddingModesRequest& request,
+ SupportedPaddingModesResponse* response) {
+ ForwardCommand(GET_SUPPORTED_PADDING_MODES, request, response);
+}
+
+void RemoteKeymaster::SupportedDigests(const SupportedDigestsRequest& request,
+ SupportedDigestsResponse* response) {
+ ForwardCommand(GET_SUPPORTED_DIGESTS, request, response);
+}
+
+void RemoteKeymaster::SupportedImportFormats(
+ const SupportedImportFormatsRequest& request,
+ SupportedImportFormatsResponse* response) {
+ ForwardCommand(GET_SUPPORTED_IMPORT_FORMATS, request, response);
+}
+
+void RemoteKeymaster::SupportedExportFormats(
+ const SupportedExportFormatsRequest& request,
+ SupportedExportFormatsResponse* response) {
+ ForwardCommand(GET_SUPPORTED_EXPORT_FORMATS, request, response);
+}
+
+void RemoteKeymaster::AddRngEntropy(const AddEntropyRequest& request,
+ AddEntropyResponse* response) {
+ ForwardCommand(ADD_RNG_ENTROPY, request, response);
+}
+
+void RemoteKeymaster::Configure(const ConfigureRequest& request,
+ ConfigureResponse* response) {
+ ForwardCommand(CONFIGURE, request, response);
+}
+
+void RemoteKeymaster::GenerateKey(const GenerateKeyRequest& request,
+ GenerateKeyResponse* response) {
+ GenerateKeyRequest datedRequest(request.message_version);
+ datedRequest.key_description = request.key_description;
+
+ if (!request.key_description.Contains(TAG_CREATION_DATETIME)) {
+ datedRequest.key_description.push_back(TAG_CREATION_DATETIME,
+ java_time(time(NULL)));
+ }
+
+ ForwardCommand(GENERATE_KEY, datedRequest, response);
+}
+
+void RemoteKeymaster::GetKeyCharacteristics(
+ const GetKeyCharacteristicsRequest& request,
+ GetKeyCharacteristicsResponse* response) {
+ ForwardCommand(GET_KEY_CHARACTERISTICS, request, response);
+}
+
+void RemoteKeymaster::ImportKey(const ImportKeyRequest& request,
+ ImportKeyResponse* response) {
+ ForwardCommand(IMPORT_KEY, request, response);
+}
+
+void RemoteKeymaster::ImportWrappedKey(const ImportWrappedKeyRequest& request,
+ ImportWrappedKeyResponse* response) {
+ ForwardCommand(IMPORT_WRAPPED_KEY, request, response);
+}
+
+void RemoteKeymaster::ExportKey(const ExportKeyRequest& request,
+ ExportKeyResponse* response) {
+ ForwardCommand(EXPORT_KEY, request, response);
+}
+
+void RemoteKeymaster::AttestKey(const AttestKeyRequest& request,
+ AttestKeyResponse* response) {
+ ForwardCommand(ATTEST_KEY, request, response);
+}
+
+void RemoteKeymaster::UpgradeKey(const UpgradeKeyRequest& request,
+ UpgradeKeyResponse* response) {
+ ForwardCommand(UPGRADE_KEY, request, response);
+}
+
+void RemoteKeymaster::DeleteKey(const DeleteKeyRequest& request,
+ DeleteKeyResponse* response) {
+ ForwardCommand(DELETE_KEY, request, response);
+}
+
+void RemoteKeymaster::DeleteAllKeys(const DeleteAllKeysRequest& request,
+ DeleteAllKeysResponse* response) {
+ ForwardCommand(DELETE_ALL_KEYS, request, response);
+}
+
+void RemoteKeymaster::BeginOperation(const BeginOperationRequest& request,
+ BeginOperationResponse* response) {
+ ForwardCommand(BEGIN_OPERATION, request, response);
+}
+
+void RemoteKeymaster::UpdateOperation(const UpdateOperationRequest& request,
+ UpdateOperationResponse* response) {
+ ForwardCommand(UPDATE_OPERATION, request, response);
+}
+
+void RemoteKeymaster::FinishOperation(const FinishOperationRequest& request,
+ FinishOperationResponse* response) {
+ ForwardCommand(FINISH_OPERATION, request, response);
+}
+
+void RemoteKeymaster::AbortOperation(const AbortOperationRequest& request,
+ AbortOperationResponse* response) {
+ ForwardCommand(ABORT_OPERATION, request, response);
+}
+
+GetHmacSharingParametersResponse RemoteKeymaster::GetHmacSharingParameters() {
+ // Unused empty buffer to allow ForwardCommand to have something to serialize
+ Buffer request;
+ GetHmacSharingParametersResponse response(message_version());
+ ForwardCommand(GET_HMAC_SHARING_PARAMETERS, request, &response);
+ return response;
+}
+
+ComputeSharedHmacResponse RemoteKeymaster::ComputeSharedHmac(
+ const ComputeSharedHmacRequest& request) {
+ ComputeSharedHmacResponse response(message_version());
+ ForwardCommand(COMPUTE_SHARED_HMAC, request, &response);
+ return response;
+}
+
+VerifyAuthorizationResponse RemoteKeymaster::VerifyAuthorization(
+ const VerifyAuthorizationRequest& request) {
+ VerifyAuthorizationResponse response(message_version());
+ ForwardCommand(VERIFY_AUTHORIZATION, request, &response);
+ return response;
+}
+
+DeviceLockedResponse RemoteKeymaster::DeviceLocked(
+ const DeviceLockedRequest& request) {
+ DeviceLockedResponse response(message_version());
+ ForwardCommand(DEVICE_LOCKED, request, &response);
+ return response;
+}
+
+EarlyBootEndedResponse RemoteKeymaster::EarlyBootEnded() {
+ // Unused empty buffer to allow ForwardCommand to have something to serialize
+ Buffer request;
+ EarlyBootEndedResponse response(message_version());
+ ForwardCommand(EARLY_BOOT_ENDED, request, &response);
+ return response;
+}
+
+void RemoteKeymaster::GenerateTimestampToken(GenerateTimestampTokenRequest&,
+ GenerateTimestampTokenResponse*) {
+ // TODO(aosp/1641315): Send a message to the host.
+ // ForwardCommand(GENERATE_TIMESTAMP_TOKEN, request, response);
+}
+
+} // namespace keymaster
diff --git a/guest/hals/keymint/remote/remote_keymaster.h b/guest/hals/keymint/remote/remote_keymaster.h
new file mode 100644
index 0000000..6cc6c7b
--- /dev/null
+++ b/guest/hals/keymint/remote/remote_keymaster.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#ifndef REMOTE_KEYMASTER_H_
+#define REMOTE_KEYMASTER_H_
+
+#include <keymaster/android_keymaster_messages.h>
+
+#include "common/libs/security/keymaster_channel.h"
+
+namespace keymaster {
+
+class RemoteKeymaster {
+ private:
+ cuttlefish::KeymasterChannel* channel_;
+
+ void ForwardCommand(AndroidKeymasterCommand command, const Serializable& req,
+ KeymasterResponse* rsp);
+
+ public:
+ RemoteKeymaster(cuttlefish::KeymasterChannel*);
+ ~RemoteKeymaster();
+ bool Initialize();
+ void GetVersion(const GetVersionRequest& request,
+ GetVersionResponse* response);
+ void SupportedAlgorithms(const SupportedAlgorithmsRequest& request,
+ SupportedAlgorithmsResponse* response);
+ void SupportedBlockModes(const SupportedBlockModesRequest& request,
+ SupportedBlockModesResponse* response);
+ void SupportedPaddingModes(const SupportedPaddingModesRequest& request,
+ SupportedPaddingModesResponse* response);
+ void SupportedDigests(const SupportedDigestsRequest& request,
+ SupportedDigestsResponse* response);
+ void SupportedImportFormats(const SupportedImportFormatsRequest& request,
+ SupportedImportFormatsResponse* response);
+ void SupportedExportFormats(const SupportedExportFormatsRequest& request,
+ SupportedExportFormatsResponse* response);
+ void AddRngEntropy(const AddEntropyRequest& request,
+ AddEntropyResponse* response);
+ void Configure(const ConfigureRequest& request, ConfigureResponse* response);
+ void GenerateKey(const GenerateKeyRequest& request,
+ GenerateKeyResponse* response);
+ void GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
+ GetKeyCharacteristicsResponse* response);
+ void ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response);
+ void ImportWrappedKey(const ImportWrappedKeyRequest& request,
+ ImportWrappedKeyResponse* response);
+ void ExportKey(const ExportKeyRequest& request, ExportKeyResponse* response);
+ void AttestKey(const AttestKeyRequest& request, AttestKeyResponse* response);
+ void UpgradeKey(const UpgradeKeyRequest& request,
+ UpgradeKeyResponse* response);
+ void DeleteKey(const DeleteKeyRequest& request, DeleteKeyResponse* response);
+ void DeleteAllKeys(const DeleteAllKeysRequest& request,
+ DeleteAllKeysResponse* response);
+ void BeginOperation(const BeginOperationRequest& request,
+ BeginOperationResponse* response);
+ void UpdateOperation(const UpdateOperationRequest& request,
+ UpdateOperationResponse* response);
+ void FinishOperation(const FinishOperationRequest& request,
+ FinishOperationResponse* response);
+ void AbortOperation(const AbortOperationRequest& request,
+ AbortOperationResponse* response);
+ GetHmacSharingParametersResponse GetHmacSharingParameters();
+ ComputeSharedHmacResponse ComputeSharedHmac(
+ const ComputeSharedHmacRequest& request);
+ VerifyAuthorizationResponse VerifyAuthorization(
+ const VerifyAuthorizationRequest& request);
+ DeviceLockedResponse DeviceLocked(const DeviceLockedRequest& request);
+ EarlyBootEndedResponse EarlyBootEnded();
+ void GenerateTimestampToken(GenerateTimestampTokenRequest& request,
+ GenerateTimestampTokenResponse* response);
+
+ // CF HAL and remote sides are always compiled together, so will never
+ // disagree about message versions.
+ uint32_t message_version() { return kDefaultMessageVersion; }
+};
+
+} // namespace keymaster
+
+#endif // REMOTE_KEYMASTER_H_
diff --git a/guest/hals/keymint/remote/remote_keymint_device.cpp b/guest/hals/keymint/remote/remote_keymint_device.cpp
new file mode 100644
index 0000000..fbf2568
--- /dev/null
+++ b/guest/hals/keymint/remote/remote_keymint_device.cpp
@@ -0,0 +1,415 @@
+/*
+ * Copyright 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.
+ */
+
+#define LOG_TAG "android.hardware.security.keymint-impl"
+#include <android-base/logging.h>
+
+#include "guest/hals/keymint/remote/remote_keymint_device.h"
+
+#include <aidl/android/hardware/security/keymint/ErrorCode.h>
+
+#include <keymaster/android_keymaster.h>
+#include <keymaster/contexts/pure_soft_keymaster_context.h>
+#include <keymaster/keymaster_configuration.h>
+
+#include "KeyMintUtils.h"
+#include "guest/hals/keymint/remote/remote_keymint_operation.h"
+
+namespace aidl::android::hardware::security::keymint {
+
+using namespace ::keymaster;
+using namespace km_utils;
+using secureclock::TimeStampToken;
+
+namespace {
+
+vector<KeyCharacteristics> convertKeyCharacteristics(
+ SecurityLevel keyMintSecurityLevel, const AuthorizationSet& sw_enforced,
+ const AuthorizationSet& hw_enforced) {
+ KeyCharacteristics keyMintEnforced{keyMintSecurityLevel, {}};
+
+ if (keyMintSecurityLevel != SecurityLevel::SOFTWARE) {
+ // We're pretending to be TRUSTED_ENVIRONMENT or STRONGBOX.
+ keyMintEnforced.authorizations = kmParamSet2Aidl(hw_enforced);
+ // Put all the software authorizations in the keystore list.
+ KeyCharacteristics keystoreEnforced{SecurityLevel::KEYSTORE,
+ kmParamSet2Aidl(sw_enforced)};
+ return {std::move(keyMintEnforced), std::move(keystoreEnforced)};
+ }
+
+ KeyCharacteristics keystoreEnforced{SecurityLevel::KEYSTORE, {}};
+ CHECK(hw_enforced.empty())
+ << "Hardware-enforced list is non-empty for pure SW KeyMint";
+
+ // This is a pure software implementation, so all tags are in sw_enforced.
+ // We need to walk through the SW-enforced list and figure out which tags to
+ // return in the software list and which in the keystore list.
+
+ for (auto& entry : sw_enforced) {
+ switch (entry.tag) {
+ /* Invalid and unused */
+ case KM_TAG_ECIES_SINGLE_HASH_MODE:
+ case KM_TAG_INVALID:
+ case KM_TAG_KDF:
+ case KM_TAG_ROLLBACK_RESISTANCE:
+ CHECK(false) << "We shouldn't see tag " << entry.tag;
+ break;
+
+ /* Unimplemented */
+ case KM_TAG_ALLOW_WHILE_ON_BODY:
+ case KM_TAG_BOOTLOADER_ONLY:
+ case KM_TAG_EARLY_BOOT_ONLY:
+ case KM_TAG_ROLLBACK_RESISTANT:
+ case KM_TAG_STORAGE_KEY:
+ case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED:
+ case KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED:
+ break;
+
+ /* Unenforceable */
+ case KM_TAG_CREATION_DATETIME:
+ break;
+
+ /* Disallowed in KeyCharacteristics */
+ case KM_TAG_APPLICATION_DATA:
+ case KM_TAG_ATTESTATION_APPLICATION_ID:
+ break;
+
+ /* Not key characteristics */
+ case KM_TAG_ASSOCIATED_DATA:
+ case KM_TAG_ATTESTATION_CHALLENGE:
+ case KM_TAG_ATTESTATION_ID_BRAND:
+ case KM_TAG_ATTESTATION_ID_DEVICE:
+ case KM_TAG_ATTESTATION_ID_IMEI:
+ case KM_TAG_ATTESTATION_ID_MANUFACTURER:
+ case KM_TAG_ATTESTATION_ID_MEID:
+ case KM_TAG_ATTESTATION_ID_MODEL:
+ case KM_TAG_ATTESTATION_ID_PRODUCT:
+ case KM_TAG_ATTESTATION_ID_SERIAL:
+ case KM_TAG_AUTH_TOKEN:
+ case KM_TAG_CERTIFICATE_SERIAL:
+ case KM_TAG_CERTIFICATE_SUBJECT:
+ case KM_TAG_CERTIFICATE_NOT_AFTER:
+ case KM_TAG_CERTIFICATE_NOT_BEFORE:
+ case KM_TAG_CONFIRMATION_TOKEN:
+ case KM_TAG_DEVICE_UNIQUE_ATTESTATION:
+ case KM_TAG_IDENTITY_CREDENTIAL_KEY:
+ case KM_TAG_MAC_LENGTH:
+ case KM_TAG_NONCE:
+ case KM_TAG_RESET_SINCE_ID_ROTATION:
+ case KM_TAG_ROOT_OF_TRUST:
+ case KM_TAG_UNIQUE_ID:
+ break;
+
+ /* KeyMint-enforced */
+ case KM_TAG_ALGORITHM:
+ case KM_TAG_APPLICATION_ID:
+ case KM_TAG_AUTH_TIMEOUT:
+ case KM_TAG_BLOB_USAGE_REQUIREMENTS:
+ case KM_TAG_BLOCK_MODE:
+ case KM_TAG_BOOT_PATCHLEVEL:
+ case KM_TAG_CALLER_NONCE:
+ case KM_TAG_DIGEST:
+ case KM_TAG_EC_CURVE:
+ case KM_TAG_EXPORTABLE:
+ case KM_TAG_INCLUDE_UNIQUE_ID:
+ case KM_TAG_KEY_SIZE:
+ case KM_TAG_MAX_USES_PER_BOOT:
+ case KM_TAG_MIN_MAC_LENGTH:
+ case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
+ case KM_TAG_NO_AUTH_REQUIRED:
+ case KM_TAG_ORIGIN:
+ case KM_TAG_OS_PATCHLEVEL:
+ case KM_TAG_OS_VERSION:
+ case KM_TAG_PADDING:
+ case KM_TAG_PURPOSE:
+ case KM_TAG_RSA_OAEP_MGF_DIGEST:
+ case KM_TAG_RSA_PUBLIC_EXPONENT:
+ case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
+ case KM_TAG_USER_AUTH_TYPE:
+ case KM_TAG_USER_SECURE_ID:
+ case KM_TAG_VENDOR_PATCHLEVEL:
+ keyMintEnforced.authorizations.push_back(kmParam2Aidl(entry));
+ break;
+
+ /* Keystore-enforced */
+ case KM_TAG_ACTIVE_DATETIME:
+ case KM_TAG_ALL_APPLICATIONS:
+ case KM_TAG_ALL_USERS:
+ case KM_TAG_MAX_BOOT_LEVEL:
+ case KM_TAG_ORIGINATION_EXPIRE_DATETIME:
+ case KM_TAG_USAGE_EXPIRE_DATETIME:
+ case KM_TAG_USER_ID:
+ case KM_TAG_USAGE_COUNT_LIMIT:
+ keystoreEnforced.authorizations.push_back(kmParam2Aidl(entry));
+ break;
+ }
+ }
+
+ vector<KeyCharacteristics> retval;
+ retval.reserve(2);
+ if (!keyMintEnforced.authorizations.empty())
+ retval.push_back(std::move(keyMintEnforced));
+ if (!keystoreEnforced.authorizations.empty())
+ retval.push_back(std::move(keystoreEnforced));
+
+ return retval;
+}
+
+Certificate convertCertificate(const keymaster_blob_t& cert) {
+ return {std::vector<uint8_t>(cert.data, cert.data + cert.data_length)};
+}
+
+vector<Certificate> convertCertificateChain(const CertificateChain& chain) {
+ vector<Certificate> retval;
+ retval.reserve(chain.entry_count);
+ std::transform(chain.begin(), chain.end(), std::back_inserter(retval),
+ convertCertificate);
+ return retval;
+}
+
+} // namespace
+
+RemoteKeyMintDevice::RemoteKeyMintDevice(::keymaster::RemoteKeymaster& impl,
+ SecurityLevel securityLevel)
+ : impl_(impl), securityLevel_(securityLevel) {}
+
+RemoteKeyMintDevice::~RemoteKeyMintDevice() {}
+
+ScopedAStatus RemoteKeyMintDevice::getHardwareInfo(KeyMintHardwareInfo* info) {
+ info->versionNumber = 1;
+ info->securityLevel = securityLevel_;
+ info->keyMintName = "RemoteKeyMintDevice";
+ info->keyMintAuthorName = "Google";
+ info->timestampTokenRequired = false;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteKeyMintDevice::addRngEntropy(const vector<uint8_t>& data) {
+ if (data.size() == 0) {
+ return ScopedAStatus::ok();
+ }
+
+ AddEntropyRequest request(impl_.message_version());
+ request.random_data.Reinitialize(data.data(), data.size());
+
+ AddEntropyResponse response(impl_.message_version());
+ impl_.AddRngEntropy(request, &response);
+
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus RemoteKeyMintDevice::generateKey(
+ const vector<KeyParameter>& keyParams,
+ const optional<AttestationKey>& attestationKey,
+ KeyCreationResult* creationResult) {
+ GenerateKeyRequest request(impl_.message_version());
+ request.key_description.Reinitialize(KmParamSet(keyParams));
+ if (attestationKey) {
+ request.attestation_signing_key_blob = KeymasterKeyBlob(
+ attestationKey->keyBlob.data(), attestationKey->keyBlob.size());
+ request.attest_key_params.Reinitialize(
+ KmParamSet(attestationKey->attestKeyParams));
+ request.issuer_subject =
+ KeymasterBlob(attestationKey->issuerSubjectName.data(),
+ attestationKey->issuerSubjectName.size());
+ }
+
+ GenerateKeyResponse response(impl_.message_version());
+ impl_.GenerateKey(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ // Note a key difference between this current aidl and previous hal, is
+ // that hal returns void where as aidl returns the error status. If
+ // aidl returns error, then aidl will not return any change you may make
+ // to the out parameters. This is quite different from hal where all
+ // output variable can be modified due to hal returning void.
+ //
+ // So the caller need to be aware not to expect aidl functions to clear
+ // the output variables for you in case of error. If you left some
+ // wrong data set in the out parameters, they will stay there.
+ return kmError2ScopedAStatus(response.error);
+ }
+
+ creationResult->keyBlob = kmBlob2vector(response.key_blob);
+ creationResult->keyCharacteristics = convertKeyCharacteristics(
+ securityLevel_, response.unenforced, response.enforced);
+ creationResult->certificateChain =
+ convertCertificateChain(response.certificate_chain);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteKeyMintDevice::importKey(
+ const vector<KeyParameter>& keyParams, KeyFormat keyFormat,
+ const vector<uint8_t>& keyData,
+ const optional<AttestationKey>& attestationKey,
+ KeyCreationResult* creationResult) {
+ ImportKeyRequest request(impl_.message_version());
+ request.key_description.Reinitialize(KmParamSet(keyParams));
+ request.key_format = legacy_enum_conversion(keyFormat);
+ request.key_data = KeymasterKeyBlob(keyData.data(), keyData.size());
+ if (attestationKey) {
+ request.attestation_signing_key_blob = KeymasterKeyBlob(
+ attestationKey->keyBlob.data(), attestationKey->keyBlob.size());
+ request.attest_key_params.Reinitialize(
+ KmParamSet(attestationKey->attestKeyParams));
+ request.issuer_subject =
+ KeymasterBlob(attestationKey->issuerSubjectName.data(),
+ attestationKey->issuerSubjectName.size());
+ }
+
+ ImportKeyResponse response(impl_.message_version());
+ impl_.ImportKey(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ return kmError2ScopedAStatus(response.error);
+ }
+
+ creationResult->keyBlob = kmBlob2vector(response.key_blob);
+ creationResult->keyCharacteristics = convertKeyCharacteristics(
+ securityLevel_, response.unenforced, response.enforced);
+ creationResult->certificateChain =
+ convertCertificateChain(response.certificate_chain);
+
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteKeyMintDevice::importWrappedKey(
+ const vector<uint8_t>& wrappedKeyData, //
+ const vector<uint8_t>& wrappingKeyBlob, //
+ const vector<uint8_t>& maskingKey, //
+ const vector<KeyParameter>& unwrappingParams, //
+ int64_t passwordSid, int64_t biometricSid, //
+ KeyCreationResult* creationResult) {
+ ImportWrappedKeyRequest request(impl_.message_version());
+ request.SetWrappedMaterial(wrappedKeyData.data(), wrappedKeyData.size());
+ request.SetWrappingMaterial(wrappingKeyBlob.data(), wrappingKeyBlob.size());
+ request.SetMaskingKeyMaterial(maskingKey.data(), maskingKey.size());
+ request.additional_params.Reinitialize(KmParamSet(unwrappingParams));
+ request.password_sid = static_cast<uint64_t>(passwordSid);
+ request.biometric_sid = static_cast<uint64_t>(biometricSid);
+
+ ImportWrappedKeyResponse response(impl_.message_version());
+ impl_.ImportWrappedKey(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ return kmError2ScopedAStatus(response.error);
+ }
+
+ creationResult->keyBlob = kmBlob2vector(response.key_blob);
+ creationResult->keyCharacteristics = convertKeyCharacteristics(
+ securityLevel_, response.unenforced, response.enforced);
+ creationResult->certificateChain =
+ convertCertificateChain(response.certificate_chain);
+
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteKeyMintDevice::upgradeKey(
+ const vector<uint8_t>& keyBlobToUpgrade,
+ const vector<KeyParameter>& upgradeParams, vector<uint8_t>* keyBlob) {
+ UpgradeKeyRequest request(impl_.message_version());
+ request.SetKeyMaterial(keyBlobToUpgrade.data(), keyBlobToUpgrade.size());
+ request.upgrade_params.Reinitialize(KmParamSet(upgradeParams));
+
+ UpgradeKeyResponse response(impl_.message_version());
+ impl_.UpgradeKey(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ return kmError2ScopedAStatus(response.error);
+ }
+
+ *keyBlob = kmBlob2vector(response.upgraded_key);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteKeyMintDevice::deleteKey(const vector<uint8_t>& keyBlob) {
+ DeleteKeyRequest request(impl_.message_version());
+ request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+
+ DeleteKeyResponse response(impl_.message_version());
+ impl_.DeleteKey(request, &response);
+
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus RemoteKeyMintDevice::deleteAllKeys() {
+ // There's nothing to be done to delete software key blobs.
+ DeleteAllKeysRequest request(impl_.message_version());
+ DeleteAllKeysResponse response(impl_.message_version());
+ impl_.DeleteAllKeys(request, &response);
+
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus RemoteKeyMintDevice::destroyAttestationIds() {
+ return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
+}
+
+ScopedAStatus RemoteKeyMintDevice::begin(KeyPurpose purpose,
+ const vector<uint8_t>& keyBlob,
+ const vector<KeyParameter>& params,
+ const HardwareAuthToken& authToken,
+ BeginResult* result) {
+ BeginOperationRequest request(impl_.message_version());
+ request.purpose = legacy_enum_conversion(purpose);
+ request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+ request.additional_params.Reinitialize(KmParamSet(params));
+
+ vector<uint8_t> vector_token = authToken2AidlVec(authToken);
+ request.additional_params.push_back(
+ TAG_AUTH_TOKEN, reinterpret_cast<uint8_t*>(vector_token.data()),
+ vector_token.size());
+
+ BeginOperationResponse response(impl_.message_version());
+ impl_.BeginOperation(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ return kmError2ScopedAStatus(response.error);
+ }
+
+ result->params = kmParamSet2Aidl(response.output_params);
+ result->challenge = response.op_handle;
+ result->operation = ndk::SharedRefBase::make<RemoteKeyMintOperation>(
+ impl_, response.op_handle);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteKeyMintDevice::deviceLocked(
+ bool passwordOnly,
+ const std::optional<secureclock::TimeStampToken>& timestampToken) {
+ DeviceLockedRequest request(impl_.message_version());
+ request.passwordOnly = passwordOnly;
+ if (timestampToken.has_value()) {
+ request.token.challenge = timestampToken->challenge;
+ request.token.mac = {timestampToken->mac.data(),
+ timestampToken->mac.size()};
+ request.token.timestamp = timestampToken->timestamp.milliSeconds;
+ }
+ DeviceLockedResponse response = impl_.DeviceLocked(request);
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus RemoteKeyMintDevice::earlyBootEnded() {
+ EarlyBootEndedResponse response = impl_.EarlyBootEnded();
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus RemoteKeyMintDevice::performOperation(
+ const vector<uint8_t>& /* request */, vector<uint8_t>* /* response */) {
+ return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
+}
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/guest/hals/keymint/remote/remote_keymint_device.h b/guest/hals/keymint/remote/remote_keymint_device.h
new file mode 100644
index 0000000..c4e840e
--- /dev/null
+++ b/guest/hals/keymint/remote/remote_keymint_device.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 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 <aidl/android/hardware/security/keymint/BnKeyMintDevice.h>
+#include <aidl/android/hardware/security/keymint/BnKeyMintOperation.h>
+#include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
+
+#include "guest/hals/keymint/remote/remote_keymaster.h"
+
+namespace aidl::android::hardware::security::keymint {
+using ::ndk::ScopedAStatus;
+using std::optional;
+using std::shared_ptr;
+using std::vector;
+
+using secureclock::TimeStampToken;
+
+class RemoteKeyMintDevice : public BnKeyMintDevice {
+ public:
+ explicit RemoteKeyMintDevice(::keymaster::RemoteKeymaster&, SecurityLevel);
+ virtual ~RemoteKeyMintDevice();
+
+ ScopedAStatus getHardwareInfo(KeyMintHardwareInfo* info) override;
+
+ ScopedAStatus addRngEntropy(const vector<uint8_t>& data) override;
+
+ ScopedAStatus generateKey(const vector<KeyParameter>& keyParams,
+ const optional<AttestationKey>& attestationKey,
+ KeyCreationResult* creationResult) override;
+
+ ScopedAStatus importKey(const vector<KeyParameter>& keyParams,
+ KeyFormat keyFormat, const vector<uint8_t>& keyData,
+ const optional<AttestationKey>& attestationKey,
+ KeyCreationResult* creationResult) override;
+
+ ScopedAStatus importWrappedKey(const vector<uint8_t>& wrappedKeyData,
+ const vector<uint8_t>& wrappingKeyBlob,
+ const vector<uint8_t>& maskingKey,
+ const vector<KeyParameter>& unwrappingParams,
+ int64_t passwordSid, int64_t biometricSid,
+ KeyCreationResult* creationResult) override;
+
+ ScopedAStatus upgradeKey(const vector<uint8_t>& keyBlobToUpgrade,
+ const vector<KeyParameter>& upgradeParams,
+ vector<uint8_t>* keyBlob) override;
+
+ ScopedAStatus deleteKey(const vector<uint8_t>& keyBlob) override;
+ ScopedAStatus deleteAllKeys() override;
+ ScopedAStatus destroyAttestationIds() override;
+
+ ScopedAStatus begin(KeyPurpose purpose, const vector<uint8_t>& keyBlob,
+ const vector<KeyParameter>& params,
+ const HardwareAuthToken& authToken,
+ BeginResult* result) override;
+
+ ScopedAStatus deviceLocked(
+ bool passwordOnly,
+ const optional<TimeStampToken>& timestampToken) override;
+ ScopedAStatus earlyBootEnded() override;
+
+ ScopedAStatus performOperation(const vector<uint8_t>& request,
+ vector<uint8_t>* response) override;
+
+ protected:
+ ::keymaster::RemoteKeymaster& impl_;
+ SecurityLevel securityLevel_;
+};
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/guest/hals/keymint/remote/remote_keymint_operation.cpp b/guest/hals/keymint/remote/remote_keymint_operation.cpp
new file mode 100644
index 0000000..a5fb6aa
--- /dev/null
+++ b/guest/hals/keymint/remote/remote_keymint_operation.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright 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.
+ */
+
+#define LOG_TAG "android.hardware.security.keymint-impl"
+#include <log/log.h>
+
+#include "guest/hals/keymint/remote/remote_keymint_operation.h"
+
+#include <aidl/android/hardware/security/keymint/ErrorCode.h>
+#include <aidl/android/hardware/security/secureclock/ISecureClock.h>
+
+#include <keymaster/android_keymaster.h>
+
+#include "KeyMintUtils.h"
+
+namespace aidl::android::hardware::security::keymint {
+
+using ::keymaster::AbortOperationRequest;
+using ::keymaster::AbortOperationResponse;
+using ::keymaster::Buffer;
+using ::keymaster::FinishOperationRequest;
+using ::keymaster::FinishOperationResponse;
+using ::keymaster::TAG_ASSOCIATED_DATA;
+using ::keymaster::UpdateOperationRequest;
+using ::keymaster::UpdateOperationResponse;
+using secureclock::TimeStampToken;
+using namespace km_utils;
+
+RemoteKeyMintOperation::RemoteKeyMintOperation(
+ ::keymaster::RemoteKeymaster& impl, keymaster_operation_handle_t opHandle)
+ : impl_(impl), opHandle_(opHandle) {}
+
+RemoteKeyMintOperation::~RemoteKeyMintOperation() {
+ if (opHandle_ != 0) {
+ abort();
+ }
+}
+
+ScopedAStatus RemoteKeyMintOperation::updateAad(
+ const vector<uint8_t>& input,
+ const optional<HardwareAuthToken>& /* authToken */,
+ const optional<TimeStampToken>& /* timestampToken */) {
+ UpdateOperationRequest request(impl_.message_version());
+ request.op_handle = opHandle_;
+ request.additional_params.push_back(TAG_ASSOCIATED_DATA, input.data(),
+ input.size());
+
+ UpdateOperationResponse response(impl_.message_version());
+ impl_.UpdateOperation(request, &response);
+
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus RemoteKeyMintOperation::update(
+ const vector<uint8_t>& input,
+ const optional<HardwareAuthToken>& /* authToken */,
+ const optional<TimeStampToken>&
+ /* timestampToken */,
+ vector<uint8_t>* output) {
+ if (!output) return kmError2ScopedAStatus(KM_ERROR_OUTPUT_PARAMETER_NULL);
+
+ UpdateOperationRequest request(impl_.message_version());
+ request.op_handle = opHandle_;
+ request.input.Reinitialize(input.data(), input.size());
+
+ UpdateOperationResponse response(impl_.message_version());
+ impl_.UpdateOperation(request, &response);
+
+ if (response.error != KM_ERROR_OK)
+ return kmError2ScopedAStatus(response.error);
+ if (response.input_consumed != request.input.buffer_size()) {
+ return kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
+ }
+
+ *output = kmBuffer2vector(response.output);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteKeyMintOperation::finish(
+ const optional<vector<uint8_t>>& input, //
+ const optional<vector<uint8_t>>& signature, //
+ const optional<HardwareAuthToken>& /* authToken */,
+ const optional<TimeStampToken>& /* timestampToken */,
+ const optional<vector<uint8_t>>& /* confirmationToken */,
+ vector<uint8_t>* output) {
+ if (!output) {
+ return ScopedAStatus(AStatus_fromServiceSpecificError(
+ static_cast<int32_t>(ErrorCode::OUTPUT_PARAMETER_NULL)));
+ }
+
+ FinishOperationRequest request(impl_.message_version());
+ request.op_handle = opHandle_;
+ if (input) request.input.Reinitialize(input->data(), input->size());
+ if (signature)
+ request.signature.Reinitialize(signature->data(), signature->size());
+
+ FinishOperationResponse response(impl_.message_version());
+ impl_.FinishOperation(request, &response);
+ opHandle_ = 0;
+
+ if (response.error != KM_ERROR_OK)
+ return kmError2ScopedAStatus(response.error);
+
+ *output = kmBuffer2vector(response.output);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteKeyMintOperation::abort() {
+ AbortOperationRequest request(impl_.message_version());
+ request.op_handle = opHandle_;
+
+ AbortOperationResponse response(impl_.message_version());
+ impl_.AbortOperation(request, &response);
+ opHandle_ = 0;
+
+ return kmError2ScopedAStatus(response.error);
+}
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/guest/hals/keymint/remote/remote_keymint_operation.h b/guest/hals/keymint/remote/remote_keymint_operation.h
new file mode 100644
index 0000000..eb3c78b
--- /dev/null
+++ b/guest/hals/keymint/remote/remote_keymint_operation.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 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 <aidl/android/hardware/security/keymint/BnKeyMintOperation.h>
+#include <aidl/android/hardware/security/secureclock/ISecureClock.h>
+
+#include <hardware/keymaster_defs.h>
+
+#include "guest/hals/keymint/remote/remote_keymaster.h"
+
+namespace keymaster {
+class AndroidKeymaster;
+}
+
+namespace aidl::android::hardware::security::keymint {
+
+using ::ndk::ScopedAStatus;
+using secureclock::TimeStampToken;
+using std::optional;
+using std::shared_ptr;
+using std::string;
+using std::vector;
+
+class RemoteKeyMintOperation : public BnKeyMintOperation {
+ public:
+ explicit RemoteKeyMintOperation(::keymaster::RemoteKeymaster& implementation,
+ keymaster_operation_handle_t opHandle);
+ virtual ~RemoteKeyMintOperation();
+
+ ScopedAStatus updateAad(
+ const vector<uint8_t>& input,
+ const optional<HardwareAuthToken>& authToken,
+ const optional<TimeStampToken>& timestampToken) override;
+
+ ScopedAStatus update(const vector<uint8_t>& input,
+ const optional<HardwareAuthToken>& authToken,
+ const optional<TimeStampToken>& timestampToken,
+ vector<uint8_t>* output) override;
+
+ ScopedAStatus finish(const optional<vector<uint8_t>>& input, //
+ const optional<vector<uint8_t>>& signature, //
+ const optional<HardwareAuthToken>& authToken, //
+ const optional<TimeStampToken>& timestampToken,
+ const optional<vector<uint8_t>>& confirmationToken,
+ vector<uint8_t>* output) override;
+
+ ScopedAStatus abort() override;
+
+ protected:
+ ::keymaster::RemoteKeymaster& impl_;
+ keymaster_operation_handle_t opHandle_;
+};
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/guest/hals/keymint/remote/remote_secure_clock.cpp b/guest/hals/keymint/remote/remote_secure_clock.cpp
new file mode 100644
index 0000000..53bab78
--- /dev/null
+++ b/guest/hals/keymint/remote/remote_secure_clock.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright 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.
+ */
+
+#define LOG_TAG "android.hardware.security.secureclock-impl"
+#include <log/log.h>
+
+#include "guest/hals/keymint/remote/remote_secure_clock.h"
+
+#include <aidl/android/hardware/security/keymint/ErrorCode.h>
+
+#include <keymaster/android_keymaster.h>
+#include <keymaster/keymaster_configuration.h>
+#include "KeyMintUtils.h"
+
+namespace aidl::android::hardware::security::secureclock {
+
+using namespace ::keymaster;
+using namespace ::aidl::android::hardware::security::keymint::km_utils;
+
+RemoteSecureClock::RemoteSecureClock(keymaster::RemoteKeymaster& impl)
+ : impl_(impl) {}
+
+RemoteSecureClock::~RemoteSecureClock() {}
+
+ScopedAStatus RemoteSecureClock::generateTimeStamp(int64_t challenge,
+ TimeStampToken* token) {
+ GenerateTimestampTokenRequest request(impl_.message_version());
+ request.challenge = challenge;
+ GenerateTimestampTokenResponse response(request.message_version);
+ impl_.GenerateTimestampToken(request, &response);
+ if (response.error != KM_ERROR_OK) {
+ return kmError2ScopedAStatus(response.error);
+ }
+ token->challenge = response.token.challenge;
+ token->timestamp.milliSeconds =
+ static_cast<int64_t>(response.token.timestamp);
+ token->mac = kmBlob2vector(response.token.mac);
+ return ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::security::secureclock
diff --git a/guest/hals/keymint/remote/remote_secure_clock.h b/guest/hals/keymint/remote/remote_secure_clock.h
new file mode 100644
index 0000000..a0330e2
--- /dev/null
+++ b/guest/hals/keymint/remote/remote_secure_clock.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 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 <aidl/android/hardware/security/secureclock/BnSecureClock.h>
+#include <aidl/android/hardware/security/secureclock/TimeStampToken.h>
+#include <aidl/android/hardware/security/secureclock/Timestamp.h>
+#include "guest/hals/keymint/remote/remote_keymaster.h"
+
+namespace keymaster {
+class AndroidKeymaster;
+}
+
+namespace aidl::android::hardware::security::secureclock {
+using ::ndk::ScopedAStatus;
+using std::shared_ptr;
+using std::vector;
+
+class RemoteSecureClock : public BnSecureClock {
+ public:
+ explicit RemoteSecureClock(::keymaster::RemoteKeymaster& keymint);
+ virtual ~RemoteSecureClock();
+ ScopedAStatus generateTimeStamp(int64_t challenge,
+ TimeStampToken* token) override;
+
+ private:
+ ::keymaster::RemoteKeymaster& impl_;
+};
+} // namespace aidl::android::hardware::security::secureclock
diff --git a/guest/hals/keymint/remote/service.cpp b/guest/hals/keymint/remote/service.cpp
new file mode 100644
index 0000000..0591edf
--- /dev/null
+++ b/guest/hals/keymint/remote/service.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright 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.
+ */
+
+#define LOG_TAG "android.hardware.security.keymint-service"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include <keymaster/soft_keymaster_logger.h>
+#include "guest/hals/keymint/remote/remote_keymint_device.h"
+
+#include <guest/hals/keymint/remote/remote_keymaster.h>
+#include <guest/hals/keymint/remote/remote_keymint_device.h>
+#include <guest/hals/keymint/remote/remote_secure_clock.h>
+#include "common/libs/fs/shared_fd.h"
+#include "common/libs/security/keymaster_channel.h"
+
+static const char device[] = "/dev/hvc3";
+
+using aidl::android::hardware::security::keymint::RemoteKeyMintDevice;
+using aidl::android::hardware::security::keymint::SecurityLevel;
+using aidl::android::hardware::security::secureclock::RemoteSecureClock;
+
+template <typename T, class... Args>
+static std::shared_ptr<T> addService(Args&&... args) {
+ std::shared_ptr<T> ser =
+ ndk::SharedRefBase::make<T>(std::forward<Args>(args)...);
+ auto instanceName = std::string(T::descriptor) + "/remote";
+ LOG(INFO) << "adding keymint service instance: " << instanceName;
+ binder_status_t status =
+ AServiceManager_addService(ser->asBinder().get(), instanceName.c_str());
+ CHECK(status == STATUS_OK);
+ return ser;
+}
+
+int main() {
+ // Zero threads seems like a useless pool, but below we'll join this thread to
+ // it, increasing the pool size to 1.
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+ // Add Keymint Service
+ auto fd = cuttlefish::SharedFD::Open(device, O_RDWR);
+ if (!fd->IsOpen()) {
+ LOG(FATAL) << "Could not connect to keymaster: " << fd->StrError();
+ }
+
+ if (fd->SetTerminalRaw() < 0) {
+ LOG(FATAL) << "Could not make " << device
+ << " a raw terminal: " << fd->StrError();
+ }
+
+ cuttlefish::KeymasterChannel keymasterChannel(fd, fd);
+
+ keymaster::RemoteKeymaster remote_keymaster(&keymasterChannel);
+
+ addService<RemoteKeyMintDevice>(remote_keymaster,
+ SecurityLevel::TRUSTED_ENVIRONMENT);
+ addService<RemoteSecureClock>(remote_keymaster);
+
+ ABinderProcess_joinThreadPool();
+ return EXIT_FAILURE; // should not reach
+}