blob: 91a6558c71a5ab202b68da9c9264acdce76b0999 [file] [log] [blame]
/* 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;
}