| /* Copyright 2012 The ChromiumOS Authors | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| * | |
| * This tool will attempt to mount or create the encrypted stateful partition, | |
| * and the various bind mountable subdirectories. | |
| * | |
| */ | |
| #define _FILE_OFFSET_BITS 64 | |
| #define CHROMEOS_ENVIRONMENT | |
| #include <fcntl.h> | |
| #include <sys/time.h> | |
| #include <memory> | |
| #include <string> | |
| #include <utility> | |
| #include <vector> | |
| #include <base/files/file_util.h> | |
| #include <base/logging.h> | |
| #include <base/strings/string_number_conversions.h> | |
| #include <brillo/files/file_util.h> | |
| #include <brillo/flag_helper.h> | |
| #include <brillo/secure_blob.h> | |
| #include <brillo/syslog_logging.h> | |
| #include <libhwsec-foundation/tlcl_wrapper/tlcl_wrapper_impl.h> | |
| #include <libstorage/platform/platform.h> | |
| #include <libstorage/storage_container/filesystem_key.h> | |
| #include <libstorage/storage_container/storage_container_factory.h> | |
| #include "init/metrics/metrics.h" | |
| #include "init/mount_encrypted/encrypted_fs.h" | |
| #include "init/tpm_encryption/encryption_key.h" | |
| #include "init/tpm_encryption/tpm_setup.h" | |
| #if DEBUG_ENABLED | |
| struct timeval tick = {}; | |
| struct timeval tick_start = {}; | |
| #endif | |
| namespace { | |
| constexpr char kMountEncryptedMetricsPath[] = | |
| "/run/mount_encrypted/metrics.mount-encrypted"; | |
| } // namespace | |
| static void print_usage(const char process_name[]) { | |
| fprintf(stderr, "Usage: %s [info|umount|set|mount]\n", process_name); | |
| } | |
| int main(int argc, const char* argv[]) { | |
| DEFINE_bool(unsafe, false, "mount encrypt partition with well known secret."); | |
| brillo::FlagHelper::Init(argc, argv, "mount-encrypted"); | |
| brillo::InitLog(brillo::kLogToSyslog | brillo::kLogToStderr); | |
| logging::SetLogItems(false, // process ID | |
| false, // thread ID | |
| true, // timestamp | |
| false); // tickcount | |
| auto commandline = base::CommandLine::ForCurrentProcess(); | |
| auto args = commandline->GetArgs(); | |
| char* rootdir_env = getenv("MOUNT_ENCRYPTED_ROOT"); | |
| base::FilePath rootdir = base::FilePath(rootdir_env ? rootdir_env : "/"); | |
| base::FilePath stateful_partition = rootdir.Append("mnt/stateful_partition"); | |
| libstorage::Platform platform; | |
| init_metrics::ScopedInitMetricsSingleton scoped_metrics( | |
| kMountEncryptedMetricsPath); | |
| libstorage::StorageContainerFactory storage_container_factory( | |
| &platform, init_metrics::InitMetrics::GetInternal()); | |
| auto encrypted_fs = mount_encrypted::EncryptedFs::Generate( | |
| rootdir, stateful_partition, &platform, &storage_container_factory); | |
| hwsec_foundation::TlclWrapperImpl tlcl; | |
| auto tpm_system_key = encryption::TpmSystemKey( | |
| &platform, &tlcl, init_metrics::InitMetrics::Get(), rootdir, | |
| stateful_partition); | |
| if (!encrypted_fs) { | |
| LOG(ERROR) << "Failed to create encrypted fs handler."; | |
| return 1; | |
| } | |
| LOG(INFO) << "Starting."; | |
| if (args.size() >= 1) { | |
| if (args[0] == "umount") { | |
| return encrypted_fs->Teardown() ? 0 : 1; | |
| } else if (args[0] == "info") { | |
| // Report info from the encrypted mount. | |
| tpm_system_key.ReportInfo(); | |
| encrypted_fs->ReportInfo(); | |
| return 0; | |
| } else if (args[0] == "set") { | |
| const char* key_material = args.size() >= 2 ? args[1].c_str() : nullptr; | |
| if (!key_material) { | |
| LOG(ERROR) << "Key material file not provided."; | |
| return 1; | |
| } | |
| return tpm_system_key.Set(base::FilePath(key_material)) ? 0 : 1; | |
| } else if (args[0] == "mount") { | |
| goto mount_encrypted_partition; | |
| } else { | |
| print_usage(argv[0]); | |
| return 1; | |
| } | |
| } | |
| mount_encrypted_partition: | |
| // For the mount operation at boot, return false to trigger | |
| // chromeos_startup do the stateful wipe. | |
| if (!encrypted_fs->CheckStates()) | |
| return 1; | |
| // default operation is mount encrypted partition. | |
| const base::FilePath empty; | |
| auto key = tpm_system_key.Load(!FLAGS_unsafe, empty); | |
| if (!key) | |
| return 1; | |
| libstorage::FileSystemKey encryption_key; | |
| encryption_key.fek = key->encryption_key(); | |
| if (!encrypted_fs->Setup(encryption_key, key->is_fresh())) | |
| return 1; | |
| return tpm_system_key.Export() ? 0 : 1; | |
| } |