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