blob: 92d21f9591c455a68fec9e386af1fb1898dc6548 [file] [log] [blame]
// Copyright 2014 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cryptohome/boot_attributes.h"
#include <base/files/file_path.h>
#include <base/logging.h>
#include <brillo/secure_blob.h>
#include "cryptohome/boot_lockbox.h"
#include "cryptohome/platform.h"
#include "install_attributes.pb.h" // NOLINT(build/include)
using base::FilePath;
namespace cryptohome {
const int BootAttributes::kAttributeFileVersion = 1;
const FilePath::CharType BootAttributes::kAttributeFile[] =
FILE_PATH_LITERAL("/var/lib/boot-lockbox/boot_attributes.pb");
const FilePath::CharType BootAttributes::kSignatureFile[] =
FILE_PATH_LITERAL("/var/lib/boot-lockbox/boot_attributes.sig");
BootAttributes::BootAttributes(BootLockbox* boot_lockbox, Platform* platform)
: boot_lockbox_(boot_lockbox),
platform_(platform) {
}
BootAttributes::~BootAttributes() {
}
bool BootAttributes::Load() {
brillo::SecureBlob data, signature;
if (!platform_->ReadFile(FilePath(kAttributeFile), &data) ||
!platform_->ReadFile(FilePath(kSignatureFile), &signature)) {
LOG(INFO) << "Cannot read boot lockbox files.";
return false;
}
if (!boot_lockbox_->Verify(data, signature)) {
LOG(ERROR) << "Cannot verify the signature of the boot lockbox.";
return false;
}
SerializedInstallAttributes message;
if (!message.ParseFromArray(data.data(), data.size())) {
LOG(ERROR) << "Cannot parse the content of the boot lockbox.";
return false;
}
AttributeMap tmp;
for (int i = 0; i < message.attributes_size(); ++i) {
const std::string& name = message.attributes(i).name();
const std::string& value = message.attributes(i).value();
tmp[name] = value;
}
attributes_.swap(tmp);
write_buffer_ = attributes_;
return true;
}
bool BootAttributes::Get(const std::string& name, std::string* value) const {
AttributeMap::const_iterator it = attributes_.find(name);
if (it == attributes_.end()) {
return false;
}
*value = it->second;
return true;
}
void BootAttributes::Set(const std::string& name, const std::string& value) {
write_buffer_[name] = value;
}
bool BootAttributes::FlushAndSign() {
SerializedInstallAttributes message;
message.set_version(kAttributeFileVersion);
AttributeMap::const_iterator it;
for (it = write_buffer_.begin(); it != write_buffer_.end(); ++it) {
SerializedInstallAttributes::Attribute* attr = message.add_attributes();
attr->set_name(it->first);
attr->set_value(it->second);
}
brillo::SecureBlob content;
content.resize(message.ByteSize());
message.SerializeWithCachedSizesToArray(content.data());
brillo::SecureBlob signature;
if (!boot_lockbox_->Sign(content, &signature)) {
return false;
}
// Write the attributes and the signature to the files.
if (!platform_->WriteFile(FilePath(kAttributeFile), content)) {
LOG(ERROR) << "Failed to write to the boot attribute file.";
return false;
}
if (!platform_->WriteFile(FilePath(kSignatureFile), signature)) {
LOG(ERROR) << "Failed to write to the boot attribute signature file.";
return false;
}
// Since two files are written, atomicity cannot be achieved easily.
// Therefore this only aims for durability.
platform_->DataSyncFile(FilePath(kAttributeFile));
platform_->DataSyncFile(FilePath(kSignatureFile));
attributes_ = write_buffer_;
return true;
}
} // namespace cryptohome