1 //
2 // Copyright (C) 2020 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15
16 #include <thread>
17
18 #include <android-base/logging.h>
19 #include <gflags/gflags.h>
20 #include <keymaster/android_keymaster.h>
21 #include <keymaster/contexts/pure_soft_keymaster_context.h>
22 #include <tss2/tss2_esys.h>
23 #include <tss2/tss2_rc.h>
24
25 #include "common/libs/fs/shared_fd.h"
26 #include "common/libs/security/gatekeeper_channel.h"
27 #include "common/libs/security/keymaster_channel.h"
28 #include "host/commands/secure_env/gatekeeper_responder.h"
29 #include "host/commands/secure_env/in_process_tpm.h"
30 #include "host/commands/secure_env/keymaster_responder.h"
31 #include "host/commands/secure_env/soft_gatekeeper.h"
32 #include "host/commands/secure_env/tpm_keymaster_context.h"
33 #include "host/commands/secure_env/tpm_resource_manager.h"
34 #include "host/libs/config/logging.h"
35
36 // Copied from AndroidKeymaster4Device
37 constexpr size_t kOperationTableSize = 16;
38
39 DEFINE_int32(keymaster_fd, -1, "A file descriptor for keymaster communication");
40 DEFINE_int32(gatekeeper_fd, -1, "A file descriptor for gatekeeper communication");
41
42 DEFINE_string(keymaster_impl,
43 "in_process_tpm",
44 "The keymaster implementation. "
45 "\"in_process_tpm\" or \"software\"");
46
main(int argc,char ** argv)47 int main(int argc, char** argv) {
48 cuttlefish::DefaultSubprocessLogging(argv);
49 gflags::ParseCommandLineFlags(&argc, &argv, true);
50 // keymaster::AndroidKeymaster puts the given pointer into a UniquePtr,
51 // taking ownership.
52 keymaster::KeymasterContext* keymaster_context;
53
54 gatekeeper::SoftGateKeeper gatekeeper;
55
56 std::unique_ptr<InProcessTpm> in_process_tpm;
57 std::unique_ptr<ESYS_CONTEXT, void(*)(ESYS_CONTEXT*)> esys(
58 nullptr, [](ESYS_CONTEXT* esys) { Esys_Finalize(&esys); });
59 std::unique_ptr<TpmResourceManager> resource_manager;
60
61 if (FLAGS_keymaster_impl == "software") {
62 keymaster_context =
63 new keymaster::PureSoftKeymasterContext(KM_SECURITY_LEVEL_SOFTWARE);
64 } else if (FLAGS_keymaster_impl == "in_process_tpm") {
65 in_process_tpm.reset(new InProcessTpm());
66 ESYS_CONTEXT* esys_ptr = nullptr;
67 auto rc =
68 Esys_Initialize(&esys_ptr, in_process_tpm->TctiContext(), nullptr);
69 if (rc != TPM2_RC_SUCCESS) {
70 LOG(FATAL) << "Could not initialize esys: " << Tss2_RC_Decode(rc)
71 << " (" << rc << ")";
72 }
73 esys.reset(esys_ptr);
74 rc = Esys_Startup(esys.get(), TPM2_SU_CLEAR);
75 if (rc != TPM2_RC_SUCCESS) {
76 LOG(FATAL) << "TPM2_Startup failed: " << Tss2_RC_Decode(rc)
77 << " (" << rc << ")";
78 }
79 // TODO(schuffelen): Call this only on first boot.
80 rc = Esys_Clear(
81 esys.get(),
82 ESYS_TR_RH_PLATFORM,
83 ESYS_TR_PASSWORD,
84 ESYS_TR_NONE,
85 ESYS_TR_NONE);
86 if (rc != TPM2_RC_SUCCESS) {
87 LOG(FATAL) << "TPM2_Clear failed: " << Tss2_RC_Decode(rc)
88 << " (" << rc << ")";
89 }
90 resource_manager.reset(new TpmResourceManager(esys.get()));
91 keymaster_context = new TpmKeymasterContext(resource_manager.get());
92 } else {
93 LOG(FATAL) << "Unknown keymaster implementation " << FLAGS_keymaster_impl;
94 return -1;
95 }
96 keymaster::AndroidKeymaster keymaster{
97 keymaster_context, kOperationTableSize};
98
99 CHECK(FLAGS_keymaster_fd != -1)
100 << "TODO(schuffelen): Add keymaster_fd alternative";
101 auto keymaster_server = cuttlefish::SharedFD::Dup(FLAGS_keymaster_fd);
102 CHECK(keymaster_server->IsOpen()) << "Could not dup server fd: "
103 << keymaster_server->StrError();
104 close(FLAGS_keymaster_fd);
105
106 CHECK(FLAGS_gatekeeper_fd != -1)
107 << "TODO(schuffelen): Add gatekeeper_fd alternative";
108 auto gatekeeper_server = cuttlefish::SharedFD::Dup(FLAGS_gatekeeper_fd);
109 CHECK(gatekeeper_server->IsOpen()) << "Could not dup server fd: "
110 << gatekeeper_server->StrError();
111 close(FLAGS_gatekeeper_fd);
112
113
114 std::thread keymaster_thread([&keymaster_server, &keymaster]() {
115 while (true) {
116 auto keymaster_conn = cuttlefish::SharedFD::Accept(*keymaster_server);
117 CHECK(keymaster_conn->IsOpen()) << "Unable to open connection: "
118 << keymaster_conn->StrError();
119 cuttlefish::KeymasterChannel keymaster_channel(keymaster_conn);
120
121 KeymasterResponder keymaster_responder(&keymaster_channel, &keymaster);
122
123 while (keymaster_responder.ProcessMessage()) {
124 }
125 }
126 });
127
128 std::thread gatekeeper_thread([&gatekeeper_server, &gatekeeper]() {
129 while (true) {
130 auto gatekeeper_conn = cuttlefish::SharedFD::Accept(*gatekeeper_server);
131 CHECK(gatekeeper_conn->IsOpen()) << "Unable to open connection: "
132 << gatekeeper_conn->StrError();
133 cuttlefish::GatekeeperChannel gatekeeper_channel(gatekeeper_conn);
134
135 GatekeeperResponder gatekeeper_responder(&gatekeeper_channel, &gatekeeper);
136
137 while (gatekeeper_responder.ProcessMessage()) {
138 }
139 }
140 });
141
142 keymaster_thread.join();
143 gatekeeper_thread.join();
144 }
145