blob: e8bd9193db7f6836c0069f57f4eaaf32e10d2e2f [file]
// Copyright 2020 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "libstorage/storage_container/fscrypt_container.h"
#include <base/files/file_path.h>
#include <base/logging.h>
#include <libstorage/platform/keyring/keyring.h>
#include <libstorage/platform/platform.h>
#include "libstorage/storage_container/filesystem_key.h"
namespace libstorage {
FscryptContainer::FscryptContainer(const base::FilePath& backing_dir,
const FileSystemKeyReference& key_reference,
bool allow_v2,
Platform* platform,
Keyring* keyring)
: backing_dir_(backing_dir),
key_reference_(key_reference),
allow_v2_(allow_v2),
platform_(platform),
keyring_(keyring) {}
bool FscryptContainer::Purge() {
return platform_->DeletePathRecursively(backing_dir_);
}
bool FscryptContainer::Exists() {
return platform_->DirectoryExists(backing_dir_) &&
platform_->GetDirCryptoKeyState(backing_dir_) ==
dircrypto::KeyState::ENCRYPTED;
}
bool FscryptContainer::Setup(const FileSystemKey& encryption_key) {
if (!platform_->DirectoryExists(backing_dir_)) {
if (!platform_->CreateDirectory(backing_dir_)) {
LOG(ERROR) << "Failed to create directory " << backing_dir_;
return false;
}
}
auto key_type = UseV2() ? Keyring::KeyType::kFscryptV2Key
: Keyring::KeyType::kFscryptV1Key;
if (!keyring_->AddKey(key_type, encryption_key, &key_reference_)) {
LOG(ERROR) << "Failed to add fscrypt key to kernel";
return false;
}
// `SetDirectoryKey` is a set-or-verify function: for directories with the
// encryption policy already set, this function call acts as a verifier.
dircrypto::KeyReference ref = {
.policy_version = UseV2() ? FSCRYPT_POLICY_V2 : FSCRYPT_POLICY_V1,
.reference = key_reference_.fek_sig,
};
if (!platform_->SetDirCryptoKey(backing_dir_, ref)) {
LOG(ERROR) << "Failed to set fscrypt key for backing directory";
return false;
}
return true;
}
bool FscryptContainer::Reset() {
// Reset should never be called for fscrypt containers.
LOG(ERROR) << "Reset not supported on fscrypt containers";
return false;
}
bool FscryptContainer::Teardown() {
auto key_type = UseV2() ? Keyring::KeyType::kFscryptV2Key
: Keyring::KeyType::kFscryptV1Key;
return keyring_->RemoveKey(key_type, key_reference_);
}
base::FilePath FscryptContainer::GetBackingLocation() const {
return backing_dir_;
}
bool FscryptContainer::UseV2() {
auto existing_policy = platform_->GetDirectoryPolicyVersion(backing_dir_);
if (existing_policy == FSCRYPT_POLICY_V1) {
return false;
}
if (existing_policy == FSCRYPT_POLICY_V2) {
return true;
}
return (allow_v2_ && platform_->CheckFscryptKeyIoctlSupport());
}
} // namespace libstorage