• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <functional>
17 #include <mutex>
18 #include <optional>
19 #include <thread>
20 
21 #include <android-base/logging.h>
22 #include <android-base/strings.h>
23 #include <fruit/fruit.h>
24 #include <gflags/gflags.h>
25 #include <keymaster/android_keymaster.h>
26 #include <keymaster/contexts/pure_soft_keymaster_context.h>
27 #include <keymaster/soft_keymaster_logger.h>
28 #include <tss2/tss2_esys.h>
29 #include <tss2/tss2_rc.h>
30 
31 #include "common/libs/fs/shared_fd.h"
32 #include "common/libs/security/confui_sign.h"
33 #include "common/libs/security/gatekeeper_channel_sharedfd.h"
34 #include "common/libs/security/keymaster_channel_sharedfd.h"
35 #include "common/libs/transport/channel_sharedfd.h"
36 #include "host/commands/kernel_log_monitor/kernel_log_server.h"
37 #include "host/commands/kernel_log_monitor/utils.h"
38 #include "host/commands/secure_env/confui_sign_server.h"
39 #include "host/commands/secure_env/device_tpm.h"
40 #include "host/commands/secure_env/gatekeeper_responder.h"
41 #include "host/commands/secure_env/in_process_tpm.h"
42 #include "host/commands/secure_env/keymaster_responder.h"
43 #include "host/commands/secure_env/oemlock/oemlock.h"
44 #include "host/commands/secure_env/oemlock/oemlock_responder.h"
45 #include "host/commands/secure_env/proxy_keymaster_context.h"
46 #include "host/commands/secure_env/rust/kmr_ta.h"
47 #include "host/commands/secure_env/soft_gatekeeper.h"
48 #include "host/commands/secure_env/storage/insecure_json_storage.h"
49 #include "host/commands/secure_env/storage/storage.h"
50 #include "host/commands/secure_env/storage/tpm_storage.h"
51 #include "host/commands/secure_env/suspend_resume_handler.h"
52 #include "host/commands/secure_env/tpm_gatekeeper.h"
53 #include "host/commands/secure_env/tpm_keymaster_context.h"
54 #include "host/commands/secure_env/tpm_keymaster_enforcement.h"
55 #include "host/commands/secure_env/tpm_resource_manager.h"
56 #include "host/commands/secure_env/worker_thread_loop_body.h"
57 #include "host/libs/config/known_paths.h"
58 #include "host/libs/config/logging.h"
59 
60 DEFINE_int32(confui_server_fd, -1, "A named socket to serve confirmation UI");
61 DEFINE_int32(snapshot_control_fd, -1,
62              "A socket connected to run_cvd for snapshot operations and"
63              "responses");
64 DEFINE_int32(keymaster_fd_in, -1, "A pipe for keymaster communication");
65 DEFINE_int32(keymaster_fd_out, -1, "A pipe for keymaster communication");
66 DEFINE_int32(keymint_fd_in, -1, "A pipe for keymint communication");
67 DEFINE_int32(keymint_fd_out, -1, "A pipe for keymint communication");
68 DEFINE_int32(gatekeeper_fd_in, -1, "A pipe for gatekeeper communication");
69 DEFINE_int32(gatekeeper_fd_out, -1, "A pipe for gatekeeper communication");
70 DEFINE_int32(oemlock_fd_in, -1, "A pipe for oemlock communication");
71 DEFINE_int32(oemlock_fd_out, -1, "A pipe for oemlock communication");
72 DEFINE_int32(kernel_events_fd, -1,
73              "A pipe for monitoring events based on "
74              "messages written to the kernel log. This "
75              "is used by secure_env to monitor for "
76              "device reboots.");
77 
78 DEFINE_string(tpm_impl, "in_memory",
79               "The TPM implementation. \"in_memory\" or \"host_device\"");
80 
81 DEFINE_string(keymint_impl, "tpm",
82               "The KeyMint implementation. \"tpm\" or \"software\"");
83 
84 DEFINE_string(gatekeeper_impl, "tpm",
85               "The gatekeeper implementation. \"tpm\" or \"software\"");
86 
87 DEFINE_string(oemlock_impl, "tpm",
88               "The oemlock implementation. \"tpm\" or \"software\"");
89 
90 namespace cuttlefish {
91 namespace {
92 
93 // Copied from AndroidKeymaster4Device
94 constexpr size_t kOperationTableSize = 16;
95 constexpr std::chrono::seconds kRestartLockTimeout(2);
96 
97 // Dup a command line file descriptor into a SharedFD.
DupFdFlag(gflags::int32 fd)98 SharedFD DupFdFlag(gflags::int32 fd) {
99   CHECK(fd != -1);
100   SharedFD duped = SharedFD::Dup(fd);
101   CHECK(duped->IsOpen()) << "Could not dup output fd: " << duped->StrError();
102   // The original FD is intentionally kept open so that we can re-exec this
103   // process without having to do a bunch of argv book-keeping.
104   return duped;
105 }
106 
107 // Re-launch this process with all the same flags it was originallys started
108 // with.
ReExecSelf()109 [[noreturn]] void ReExecSelf() {
110   // Allocate +1 entry for terminating nullptr.
111   std::vector<char*> argv(gflags::GetArgvs().size() + 1, nullptr);
112   for (size_t i = 0; i < gflags::GetArgvs().size(); ++i) {
113     argv[i] = strdup(gflags::GetArgvs()[i].c_str());
114     CHECK(argv[i] != nullptr) << "OOM";
115   }
116   execv(SecureEnvBinary().c_str(), argv.data());
117   char buf[128];
118   LOG(FATAL) << "Exec failed, secure_env is out of sync with the guest: "
119              << errno << "(" << strerror_r(errno, buf, sizeof(buf)) << ")";
120   abort();  // LOG(FATAL) isn't marked as noreturn
121 }
122 
123 // Spin up a thread that monitors for a kernel loaded event, then re-execs
124 // this process. This way, secure_env's boot tracking matches up with the guest.
StartKernelEventMonitor(SharedFD kernel_events_fd,std::timed_mutex & oemlock_lock)125 std::thread StartKernelEventMonitor(SharedFD kernel_events_fd,
126                                     std::timed_mutex& oemlock_lock) {
127   return std::thread([kernel_events_fd, &oemlock_lock]() {
128     while (kernel_events_fd->IsOpen()) {
129       auto read_result = monitor::ReadEvent(kernel_events_fd);
130       CHECK(read_result.ok()) << read_result.error().FormatForEnv();
131       CHECK(read_result->has_value()) << "EOF in kernel log monitor";
132       if ((*read_result)->event == monitor::Event::BootloaderLoaded) {
133         LOG(DEBUG) << "secure_env detected guest reboot, restarting.";
134 
135         // secure_env app potentially may become stuck at IO during holding the
136         // lock, so limit the waiting time to make sure self-restart is executed
137         // as expected
138         const bool locked = oemlock_lock.try_lock_for(kRestartLockTimeout);
139         if (!locked) {
140           LOG(WARNING) << "Couldn't acquire oemlock lock within timeout. "
141                           "Executing self-restart anyway";
142         }
143 
144         ReExecSelf();
145 
146         if (locked) {
147           oemlock_lock.unlock();
148         }
149       }
150     }
151   });
152 }
153 
154 fruit::Component<fruit::Required<gatekeeper::SoftGateKeeper, TpmGatekeeper,
155                                  TpmResourceManager>,
156                  gatekeeper::GateKeeper, keymaster::KeymasterEnforcement>
ChooseGatekeeperComponent()157 ChooseGatekeeperComponent() {
158   if (FLAGS_gatekeeper_impl == "software") {
159     return fruit::createComponent()
160         .bind<gatekeeper::GateKeeper, gatekeeper::SoftGateKeeper>()
161         .registerProvider([]() -> keymaster::KeymasterEnforcement* {
162           return new keymaster::SoftKeymasterEnforcement(64, 64);
163         });
164   } else if (FLAGS_gatekeeper_impl == "tpm") {
165     return fruit::createComponent()
166         .bind<gatekeeper::GateKeeper, TpmGatekeeper>()
167         .registerProvider(
168             [](TpmResourceManager& resource_manager,
169                TpmGatekeeper& gatekeeper) -> keymaster::KeymasterEnforcement* {
170               return new TpmKeymasterEnforcement(resource_manager, gatekeeper);
171             });
172   } else {
173     LOG(FATAL) << "Invalid gatekeeper implementation: "
174                << FLAGS_gatekeeper_impl;
175     abort();
176   }
177 }
178 
179 fruit::Component<fruit::Required<TpmResourceManager>, oemlock::OemLock>
ChooseOemlockComponent()180 ChooseOemlockComponent() {
181   return fruit::createComponent()
182       .registerProvider(
183           [](TpmResourceManager& resource_manager) -> secure_env::Storage* {
184             if (FLAGS_oemlock_impl == "software") {
185               return new secure_env::InsecureJsonStorage("oemlock_insecure");
186             } else if (FLAGS_oemlock_impl == "tpm") {
187               return new secure_env::TpmStorage(resource_manager,
188                                                 "oemlock_secure");
189             } else {
190               LOG(FATAL) << "Invalid oemlock implementation: "
191                          << FLAGS_oemlock_impl;
192               abort();
193             }
194           })
195       .registerProvider([](secure_env::Storage& storage) -> oemlock::OemLock* {
196         return new oemlock::OemLock(storage);
197       });
198   ;
199 }
200 
201 fruit::Component<TpmResourceManager, gatekeeper::GateKeeper, oemlock::OemLock,
202                  keymaster::KeymasterEnforcement>
SecureEnvComponent()203 SecureEnvComponent() {
204   return fruit::createComponent()
205       .registerProvider([]() -> Tpm* {  // fruit will take ownership
206         if (FLAGS_tpm_impl == "in_memory") {
207           return new InProcessTpm();
208         } else if (FLAGS_tpm_impl == "host_device") {
209           return new DeviceTpm("/dev/tpm0");
210         } else {
211           LOG(FATAL) << "Unknown TPM implementation: " << FLAGS_tpm_impl;
212           abort();
213         }
214       })
215       .registerProvider([](Tpm* tpm) {
216         if (tpm->TctiContext() == nullptr) {
217           LOG(FATAL) << "Unable to connect to TPM implementation.";
218         }
219         ESYS_CONTEXT* esys_ptr = nullptr;
220         std::unique_ptr<ESYS_CONTEXT, void (*)(ESYS_CONTEXT*)> esys(
221             nullptr, [](ESYS_CONTEXT* esys) { Esys_Finalize(&esys); });
222         auto rc = Esys_Initialize(&esys_ptr, tpm->TctiContext(), nullptr);
223         if (rc != TPM2_RC_SUCCESS) {
224           LOG(FATAL) << "Could not initialize esys: " << Tss2_RC_Decode(rc)
225                      << " (" << rc << ")";
226         }
227         esys.reset(esys_ptr);
228         return esys;
229       })
230       .registerProvider(
231           [](std::unique_ptr<ESYS_CONTEXT, void (*)(ESYS_CONTEXT*)>& esys) {
232             return new TpmResourceManager(
233                 esys.get());  // fruit will take ownership
234           })
235       .registerProvider([](TpmResourceManager& resource_manager) {
236         return new secure_env::TpmStorage(resource_manager,
237                                           "gatekeeper_secure");
238       })
239       .registerProvider([]() {
240         return new secure_env::InsecureJsonStorage("gatekeeper_insecure");
241       })
242       .registerProvider([](TpmResourceManager& resource_manager,
243                            secure_env::TpmStorage& secure_storage,
244                            secure_env::InsecureJsonStorage& insecure_storage) {
245         return new TpmGatekeeper(resource_manager, secure_storage,
246                                  insecure_storage);
247       })
248       .registerProvider([]() { return new gatekeeper::SoftGateKeeper(); })
249       .install(ChooseGatekeeperComponent)
250       .install(ChooseOemlockComponent);
251 }
252 
253 }  // namespace
254 
SecureEnvMain(int argc,char ** argv)255 Result<void> SecureEnvMain(int argc, char** argv) {
256   DefaultSubprocessLogging(argv);
257   gflags::ParseCommandLineFlags(&argc, &argv, true);
258   keymaster::SoftKeymasterLogger km_logger;
259 
260   fruit::Injector<TpmResourceManager, gatekeeper::GateKeeper, oemlock::OemLock,
261                   keymaster::KeymasterEnforcement>
262       injector(SecureEnvComponent);
263   TpmResourceManager* resource_manager = injector.get<TpmResourceManager*>();
264   gatekeeper::GateKeeper* gatekeeper = injector.get<gatekeeper::GateKeeper*>();
265   oemlock::OemLock* oemlock = injector.get<oemlock::OemLock*>();
266   keymaster::KeymasterEnforcement* keymaster_enforcement =
267       injector.get<keymaster::KeymasterEnforcement*>();
268   std::unique_ptr<keymaster::KeymasterContext> keymaster_context;
269   std::unique_ptr<keymaster::AndroidKeymaster> keymaster;
270   std::timed_mutex oemlock_lock;
271   std::vector<std::thread> threads;
272 
273   int security_level;
274   if (FLAGS_keymint_impl == "software") {
275     security_level = KM_SECURITY_LEVEL_SOFTWARE;
276   } else if (FLAGS_keymint_impl == "tpm") {
277     security_level = KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
278   } else {
279     return CF_ERR("Unknown Keymint Implementation: " + FLAGS_keymint_impl);
280   }
281 
282   // go/cf-secure-env-snapshot
283   auto [rust_snapshot_socket1, rust_snapshot_socket2] =
284       CF_EXPECT(SharedFD::SocketPair(AF_UNIX, SOCK_STREAM, 0));
285   auto [keymaster_snapshot_socket1, keymaster_snapshot_socket2] =
286       CF_EXPECT(SharedFD::SocketPair(AF_UNIX, SOCK_STREAM, 0));
287   auto [gatekeeper_snapshot_socket1, gatekeeper_snapshot_socket2] =
288       CF_EXPECT(SharedFD::SocketPair(AF_UNIX, SOCK_STREAM, 0));
289   auto [oemlock_snapshot_socket1, oemlock_snapshot_socket2] =
290       CF_EXPECT(SharedFD::SocketPair(AF_UNIX, SOCK_STREAM, 0));
291   SharedFD channel_to_run_cvd = DupFdFlag(FLAGS_snapshot_control_fd);
292 
293   SnapshotCommandHandler suspend_resume_handler(
294       channel_to_run_cvd,
295       SnapshotCommandHandler::SnapshotSockets{
296           .rust = std::move(rust_snapshot_socket1),
297           .keymaster = std::move(keymaster_snapshot_socket1),
298           .gatekeeper = std::move(gatekeeper_snapshot_socket1),
299           .oemlock = std::move(oemlock_snapshot_socket1),
300       });
301 
302   // The guest image may have either the C++ implementation of
303   // KeyMint/Keymaster, xor the Rust implementation of KeyMint.  Those different
304   // implementations each need to have a matching TA implementation in
305   // secure_env, but they use distincts ports (/dev/hvc3 for C++, /dev/hvc11 for
306   // Rust) so start threads for *both* TA implementations -- only one of them
307   // will receive any traffic from the guest.
308 
309   // Start the Rust reference implementation of KeyMint.
310 #ifdef __linux__
311   LOG(INFO) << "starting Rust KeyMint TA implementation in a thread";
312 
313   int keymint_in = FLAGS_keymint_fd_in;
314   int keymint_out = FLAGS_keymint_fd_out;
315   TpmResourceManager* rm = resource_manager;
316   threads.emplace_back([rm, keymint_in, keymint_out, security_level,
317                         rust_snapshot_socket2 =
318                             std::move(rust_snapshot_socket2)]() {
319     int snapshot_socket_fd = std::move(rust_snapshot_socket2)->UNMANAGED_Dup();
320     kmr_ta_main(keymint_in, keymint_out, security_level, rm,
321                 snapshot_socket_fd);
322   });
323 #endif
324 
325   // Start the C++ reference implementation of KeyMint.
326   LOG(INFO) << "starting C++ KeyMint implementation in a thread with FDs in="
327             << FLAGS_keymaster_fd_in << ", out=" << FLAGS_keymaster_fd_out;
328   CF_EXPECTF(security_level == KM_SECURITY_LEVEL_SOFTWARE ||
329                  security_level == KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT,
330              "Unknown keymaster security_level \"{}\" for \"{}\"",
331              security_level, FLAGS_keymint_impl);
332   if (security_level == KM_SECURITY_LEVEL_SOFTWARE) {
333     keymaster_context.reset(new keymaster::PureSoftKeymasterContext(
334         keymaster::KmVersion::KEYMINT_3, KM_SECURITY_LEVEL_SOFTWARE));
335   } else /* KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT */ {
336     keymaster_context.reset(
337         new TpmKeymasterContext(*resource_manager, *keymaster_enforcement));
338   }
339 
340   // keymaster::AndroidKeymaster puts the context pointer into a UniquePtr,
341   // taking ownership.
342   keymaster.reset(new keymaster::AndroidKeymaster(
343       new ProxyKeymasterContext(*keymaster_context), kOperationTableSize,
344       keymaster::MessageVersion(keymaster::KmVersion::KEYMINT_3,
345                                 0 /* km_date */)));
346 
347   auto keymaster_in = DupFdFlag(FLAGS_keymaster_fd_in);
348   auto keymaster_out = DupFdFlag(FLAGS_keymaster_fd_out);
349   keymaster::AndroidKeymaster* borrowed_km = keymaster.get();
350   threads.emplace_back([keymaster_in, keymaster_out, borrowed_km,
351                         keymaster_snapshot_socket2 =
352                             std::move(keymaster_snapshot_socket2)]() {
353     while (true) {
354       SharedFdKeymasterChannel keymaster_channel(keymaster_in, keymaster_out);
355 
356       KeymasterResponder keymaster_responder(keymaster_channel, *borrowed_km);
357 
358       std::function<bool()> keymaster_process_cb = [&keymaster_responder]() {
359         return keymaster_responder.ProcessMessage();
360       };
361 
362       // infinite loop that returns if resetting responder is needed
363       auto result = secure_env_impl::WorkerInnerLoop(
364           keymaster_process_cb, keymaster_in, keymaster_snapshot_socket2);
365       if (!result.ok()) {
366         LOG(FATAL) << "keymaster worker failed: " << result.error().Trace();
367       }
368     }
369   });
370 
371   auto gatekeeper_in = DupFdFlag(FLAGS_gatekeeper_fd_in);
372   auto gatekeeper_out = DupFdFlag(FLAGS_gatekeeper_fd_out);
373   threads.emplace_back([gatekeeper_in, gatekeeper_out, &gatekeeper,
374                         gatekeeper_snapshot_socket2 =
375                             std::move(gatekeeper_snapshot_socket2)]() {
376     while (true) {
377       SharedFdGatekeeperChannel gatekeeper_channel(gatekeeper_in,
378                                                    gatekeeper_out);
379 
380       GatekeeperResponder gatekeeper_responder(gatekeeper_channel, *gatekeeper);
381 
382       std::function<bool()> gatekeeper_process_cb = [&gatekeeper_responder]() {
383         return gatekeeper_responder.ProcessMessage();
384       };
385 
386       // infinite loop that returns if resetting responder is needed
387       auto result = secure_env_impl::WorkerInnerLoop(
388           gatekeeper_process_cb, gatekeeper_in, gatekeeper_snapshot_socket2);
389       if (!result.ok()) {
390         LOG(FATAL) << "gatekeeper worker failed: " << result.error().Trace();
391       }
392     }
393   });
394 
395   auto oemlock_in = DupFdFlag(FLAGS_oemlock_fd_in);
396   auto oemlock_out = DupFdFlag(FLAGS_oemlock_fd_out);
397   threads.emplace_back(
398       [oemlock_in, oemlock_out, &oemlock, &oemlock_lock,
399        oemlock_snapshot_socket2 = std::move(oemlock_snapshot_socket2)]() {
400         while (true) {
401           transport::SharedFdChannel channel(oemlock_in, oemlock_out);
402           oemlock::OemLockResponder responder(channel, *oemlock, oemlock_lock);
403 
404           std::function<bool()> oemlock_process_cb = [&responder]() -> bool {
405             return (responder.ProcessMessage().ok());
406           };
407 
408           // infinite loop that returns if resetting responder is needed
409           auto result = secure_env_impl::WorkerInnerLoop(
410               oemlock_process_cb, oemlock_in, oemlock_snapshot_socket2);
411           if (!result.ok()) {
412             LOG(FATAL) << "oemlock worker failed: " << result.error().Trace();
413           }
414         }
415       });
416 
417   auto confui_server_fd = DupFdFlag(FLAGS_confui_server_fd);
418   threads.emplace_back([confui_server_fd, resource_manager]() {
419     ConfUiSignServer confui_sign_server(*resource_manager, confui_server_fd);
420     // no return, infinite loop
421     confui_sign_server.MainLoop();
422   });
423 
424   auto kernel_events_fd = DupFdFlag(FLAGS_kernel_events_fd);
425   threads.emplace_back(StartKernelEventMonitor(kernel_events_fd, oemlock_lock));
426 
427   for (auto& t : threads) {
428     t.join();
429   }
430   return {};
431 }
432 
433 }  // namespace cuttlefish
434 
main(int argc,char ** argv)435 int main(int argc, char** argv) {
436   auto result = cuttlefish::SecureEnvMain(argc, argv);
437   if (result.ok()) {
438     return 0;
439   }
440   LOG(FATAL) << result.error().Trace();
441   return -1;
442 }
443