blob: c050c58d13f87a945c024fdc6457870d4bca41e6 [file] [log] [blame]
//
// 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 <thread>
#include <android-base/logging.h>
#include <gflags/gflags.h>
#include <keymaster/android_keymaster.h>
#include <keymaster/soft_keymaster_logger.h>
#include <keymaster/contexts/pure_soft_keymaster_context.h>
#include <tss2/tss2_esys.h>
#include <tss2/tss2_rc.h>
#include "common/libs/fs/shared_fd.h"
#include "common/libs/security/gatekeeper_channel.h"
#include "common/libs/security/keymaster_channel.h"
#include "host/commands/secure_env/device_tpm.h"
#include "host/commands/secure_env/fragile_tpm_storage.h"
#include "host/commands/secure_env/gatekeeper_responder.h"
#include "host/commands/secure_env/insecure_fallback_storage.h"
#include "host/commands/secure_env/in_process_tpm.h"
#include "host/commands/secure_env/keymaster_responder.h"
#include "host/commands/secure_env/soft_gatekeeper.h"
#include "host/commands/secure_env/tpm_gatekeeper.h"
#include "host/commands/secure_env/tpm_keymaster_context.h"
#include "host/commands/secure_env/tpm_keymaster_enforcement.h"
#include "host/commands/secure_env/tpm_resource_manager.h"
#include "host/libs/config/logging.h"
// Copied from AndroidKeymaster4Device
constexpr size_t kOperationTableSize = 16;
DEFINE_int32(keymaster_fd_in, -1, "A pipe for keymaster communication");
DEFINE_int32(keymaster_fd_out, -1, "A pipe for keymaster communication");
DEFINE_int32(gatekeeper_fd_in, -1, "A pipe for gatekeeper communication");
DEFINE_int32(gatekeeper_fd_out, -1, "A pipe for gatekeeper communication");
DEFINE_string(tpm_impl,
"in_memory",
"The TPM implementation. \"in_memory\" or \"host_device\"");
DEFINE_string(keymint_impl, "tpm",
"The keymaster implementation. \"tpm\" or \"software\"");
DEFINE_string(gatekeeper_impl, "tpm",
"The gatekeeper implementation. \"tpm\" or \"software\"");
int main(int argc, char** argv) {
cuttlefish::DefaultSubprocessLogging(argv);
gflags::ParseCommandLineFlags(&argc, &argv, true);
keymaster::SoftKeymasterLogger km_logger;
std::unique_ptr<Tpm> tpm;
if (FLAGS_tpm_impl == "in_memory") {
tpm.reset(new InProcessTpm());
} else if (FLAGS_tpm_impl == "host_device") {
tpm.reset(new DeviceTpm("/dev/tpm0"));
} else {
LOG(FATAL) << "Unknown TPM implementation: " << FLAGS_tpm_impl;
}
if (tpm->TctiContext() == nullptr) {
LOG(FATAL) << "Unable to connect to TPM implementation.";
}
std::unique_ptr<TpmResourceManager> resource_manager;
std::unique_ptr<ESYS_CONTEXT, void(*)(ESYS_CONTEXT*)> esys(
nullptr, [](ESYS_CONTEXT* esys) { Esys_Finalize(&esys); });
if (FLAGS_keymint_impl == "tpm" || FLAGS_gatekeeper_impl == "tpm") {
ESYS_CONTEXT* esys_ptr = nullptr;
auto rc = Esys_Initialize(&esys_ptr, tpm->TctiContext(), nullptr);
if (rc != TPM2_RC_SUCCESS) {
LOG(FATAL) << "Could not initialize esys: " << Tss2_RC_Decode(rc)
<< " (" << rc << ")";
}
esys.reset(esys_ptr);
resource_manager.reset(new TpmResourceManager(esys.get()));
}
std::unique_ptr<GatekeeperStorage> secure_storage;
std::unique_ptr<GatekeeperStorage> insecure_storage;
std::unique_ptr<gatekeeper::GateKeeper> gatekeeper;
std::unique_ptr<keymaster::KeymasterEnforcement> keymaster_enforcement;
if (FLAGS_gatekeeper_impl == "software") {
gatekeeper.reset(new gatekeeper::SoftGateKeeper);
keymaster_enforcement.reset(
new keymaster::SoftKeymasterEnforcement(64, 64));
} else if (FLAGS_gatekeeper_impl == "tpm") {
secure_storage.reset(
new FragileTpmStorage(*resource_manager, "gatekeeper_secure"));
insecure_storage.reset(
new InsecureFallbackStorage(*resource_manager, "gatekeeper_insecure"));
TpmGatekeeper* tpm_gatekeeper =
new TpmGatekeeper(*resource_manager, *secure_storage, *insecure_storage);
gatekeeper.reset(tpm_gatekeeper);
keymaster_enforcement.reset(
new TpmKeymasterEnforcement(*resource_manager, *tpm_gatekeeper));
}
// keymaster::AndroidKeymaster puts the given pointer into a UniquePtr,
// taking ownership.
keymaster::KeymasterContext* keymaster_context;
if (FLAGS_keymint_impl == "software") {
// TODO: See if this is the right KM version.
keymaster_context =
new keymaster::PureSoftKeymasterContext(keymaster::KmVersion::KEYMASTER_4,
KM_SECURITY_LEVEL_SOFTWARE);
} else if (FLAGS_keymint_impl == "tpm") {
keymaster_context =
new TpmKeymasterContext(*resource_manager, *keymaster_enforcement);
} else {
LOG(FATAL) << "Unknown keymaster implementation " << FLAGS_keymint_impl;
return -1;
}
keymaster::AndroidKeymaster keymaster{
keymaster_context, kOperationTableSize,
keymaster::MessageVersion(keymaster::KmVersion::KEYMINT_1,
0 /* km_date */)};
CHECK(FLAGS_keymaster_fd_in != -1);
auto keymaster_in = cuttlefish::SharedFD::Dup(FLAGS_keymaster_fd_in);
CHECK(keymaster_in->IsOpen()) << "Could not dup input fd: "
<< keymaster_in->StrError();
close(FLAGS_keymaster_fd_in);
CHECK(FLAGS_keymaster_fd_out != -1);
auto keymaster_out = cuttlefish::SharedFD::Dup(FLAGS_keymaster_fd_out);
CHECK(keymaster_out->IsOpen()) << "Could not dup output fd: "
<< keymaster_out->StrError();
close(FLAGS_keymaster_fd_out);
CHECK(FLAGS_gatekeeper_fd_in != -1);
auto gatekeeper_in = cuttlefish::SharedFD::Dup(FLAGS_gatekeeper_fd_in);
CHECK(gatekeeper_in->IsOpen()) << "Could not dup input fd: "
<< gatekeeper_in->StrError();
close(FLAGS_gatekeeper_fd_in);
CHECK(FLAGS_gatekeeper_fd_out != -1);
auto gatekeeper_out = cuttlefish::SharedFD::Dup(FLAGS_gatekeeper_fd_out);
CHECK(gatekeeper_out->IsOpen()) << "Could not dup output fd: "
<< keymaster_out->StrError();
close(FLAGS_gatekeeper_fd_out);
std::thread keymaster_thread([keymaster_in, keymaster_out, &keymaster]() {
while (true) {
cuttlefish::KeymasterChannel keymaster_channel(
keymaster_in, keymaster_out);
KeymasterResponder keymaster_responder(keymaster_channel, keymaster);
while (keymaster_responder.ProcessMessage()) {
}
}
});
std::thread gatekeeper_thread([gatekeeper_in, gatekeeper_out, &gatekeeper]() {
while (true) {
cuttlefish::GatekeeperChannel gatekeeper_channel(
gatekeeper_in, gatekeeper_out);
GatekeeperResponder gatekeeper_responder(gatekeeper_channel, *gatekeeper);
while (gatekeeper_responder.ProcessMessage()) {
}
}
});
keymaster_thread.join();
gatekeeper_thread.join();
}