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