blob: bf1bd647c7539d2f6c429b732453a63af9bb09a4 [file] [log] [blame]
// Copyright 2018 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/bootlockbox/boot_lockbox_client.h"
#include <utility>
#include <vector>
#include <base/timer/elapsed_timer.h>
#include <brillo/glib/object.h>
#include <dbus/cryptohome/dbus-constants.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus.h>
#include <cryptohome/proto_bindings/rpc.pb.h>
#include "bootlockbox/dbus-proxies.h"
namespace cryptohome {
std::unique_ptr<BootLockboxClient>
BootLockboxClient::CreateBootLockboxClient() {
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
if (!bus->Connect()) {
LOG(ERROR) << "D-Bus system bus is not ready";
return nullptr;
}
auto bootlockbox_proxy =
std::make_unique<org::chromium::BootLockboxInterfaceProxy>(bus);
return std::unique_ptr<BootLockboxClient>(
new BootLockboxClient(std::move(bootlockbox_proxy), bus));
}
BootLockboxClient::BootLockboxClient(
std::unique_ptr<org::chromium::BootLockboxInterfaceProxy> bootlockbox,
scoped_refptr<dbus::Bus> bus)
: bootlockbox_(std::move(bootlockbox)), bus_(bus) {}
BootLockboxClient::~BootLockboxClient() {
bus_->ShutdownAndBlock();
}
bool BootLockboxClient::Sign(const std::string& digest,
std::string* signature_out) {
base::ElapsedTimer timer;
cryptohome::SignBootLockboxRequest request;
request.set_data(digest);
std::vector<uint8_t> request_array(request.ByteSize());
CHECK(request.SerializeToArray(request_array.data(), request_array.size()));
std::vector<uint8_t> reply_array;
brillo::ErrorPtr error;
if (!bootlockbox_->SignBootLockbox(request_array, &reply_array, &error)) {
LOG(ERROR) << "Failed to call SignBootLockbox, error: "
<< error->GetMessage();
return false;
}
cryptohome::BaseReply base_reply;
if (!base_reply.ParseFromArray(reply_array.data(), reply_array.size())) {
LOG(ERROR) << "Failed to parse SignBootLockboxReply";
return false;
}
if (base_reply.has_error()) {
LOG(ERROR) << "Failed to call Sign, error code: " << base_reply.error();
return false;
}
if (!base_reply.HasExtension(cryptohome::SignBootLockboxReply::reply)) {
LOG(ERROR) << "Missing reply in SignBootLockboxReply";
return false;
}
cryptohome::SignBootLockboxReply signature_reply =
base_reply.GetExtension(cryptohome::SignBootLockboxReply::reply);
if (!signature_reply.has_signature()) {
LOG(ERROR) << "Missing signature in SignBootLockboxReply";
return false;
}
*signature_out = signature_reply.signature();
LOG(INFO) << "BootLockboxClient::Sign took "
<< timer.Elapsed().InMillisecondsRoundedUp() << "ms";
return true;
}
bool BootLockboxClient::Verify(const std::string& digest,
const std::string& signature) {
base::ElapsedTimer timer;
cryptohome::VerifyBootLockboxRequest request;
request.set_data(digest);
request.set_signature(signature);
std::vector<uint8_t> request_array(request.ByteSize());
CHECK(request.SerializeToArray(request_array.data(), request_array.size()));
std::vector<uint8_t> reply_array;
brillo::ErrorPtr error;
if (!bootlockbox_->VerifyBootLockbox(request_array, &reply_array, &error)) {
LOG(ERROR) << "Failed to call VerifyBootLockbox, " << error->GetMessage();
return false;
}
cryptohome::BaseReply base_reply;
if (!base_reply.ParseFromArray(reply_array.data(), reply_array.size())) {
LOG(ERROR) << "Failed to parse VerifyBootLockbox reply message";
return false;
}
if (base_reply.has_error()) {
LOG(ERROR) << "Error calling VerifyBootLockbox, error code:"
<< base_reply.error();
return false;
}
LOG(INFO) << "BootLockboxClient::Verify took " <<
timer.Elapsed().InMillisecondsRoundedUp() << "ms";
return true;
}
bool BootLockboxClient::Finalize() {
base::ElapsedTimer timer;
cryptohome::FinalizeBootLockboxRequest request;
std::vector<uint8_t> request_array(request.ByteSize());
CHECK(request.SerializeToArray(request_array.data(), request_array.size()));
std::vector<uint8_t> reply_array;
brillo::ErrorPtr error;
if (!bootlockbox_->FinalizeBootLockbox(request_array, &reply_array, &error)) {
LOG(ERROR) << "Failed to call FinalizeBootLockbox";
return false;
}
cryptohome::BaseReply base_reply;
if (!base_reply.ParseFromArray(reply_array.data(), reply_array.size())) {
LOG(ERROR) << "Failed to parse FinalizeBootLockbox reply";
return false;
}
if (base_reply.has_error()) {
LOG(ERROR) << "Error calling FinalizeBootLockbox, error code: "
<< base_reply.error();
return false;
}
LOG(INFO) << "Finalize took " << timer.Elapsed().InMillisecondsRoundedUp()
<< "ms";
return true;
}
} // namespace cryptohome