blob: 11d326643a9cf0427eb50eb6bb99a9ade867eab5 [file] [log] [blame]
// Copyright 2022 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 "u2fd/u2fhid_service_impl.h"
#include <functional>
#include <memory>
#include <optional>
#include <utility>
#include <attestation-client/attestation/dbus-constants.h>
#include <attestation/proto_bindings/interface.pb.h>
#include <base/logging.h>
#include <metrics/metrics_library.h>
#include <trunks/cr50_headers/virtual_nvmem.h>
#include "u2fd/user_state.h"
namespace u2f {
namespace {
constexpr char kDeviceName[] = "Integrated U2F";
constexpr char kKeyLabelEmk[] = "attest-ent-machine";
} // namespace
U2fHidServiceImpl::U2fHidServiceImpl(bool legacy_kh_fallback,
uint32_t vendor_id,
uint32_t product_id)
: legacy_kh_fallback_(legacy_kh_fallback),
vendor_id_(vendor_id),
product_id_(product_id) {}
bool U2fHidServiceImpl::InitializeDBusProxies(dbus::Bus* bus) {
if (!tpm_proxy_.Init()) {
LOG(ERROR) << "Failed to initialize trunksd DBus proxy";
return false;
}
attestation_proxy_ = bus->GetObjectProxy(
attestation::kAttestationServiceName,
dbus::ObjectPath(attestation::kAttestationServicePath));
if (!attestation_proxy_) {
LOG(ERROR) << "Failed to initialize attestationd DBus proxy";
return false;
}
return true;
}
bool U2fHidServiceImpl::CreateU2fHid(
bool allow_g2f_attestation,
bool include_g2f_allowlisting_data,
std::function<void()> request_user_presence,
UserState* user_state,
MetricsLibraryInterface* metrics) {
std::unique_ptr<u2f::AllowlistingUtil> allowlisting_util;
if (include_g2f_allowlisting_data) {
allowlisting_util = std::make_unique<u2f::AllowlistingUtil>(
[this](int cert_size) { return GetCertifiedG2fCert(cert_size); });
}
u2f_msg_handler_ = std::make_unique<u2f::U2fMessageHandler>(
std::move(allowlisting_util), request_user_presence, user_state,
&tpm_proxy_, metrics, legacy_kh_fallback_, allow_g2f_attestation);
u2fhid_ = std::make_unique<u2f::U2fHid>(
std::make_unique<u2f::UHidDevice>(vendor_id_, product_id_, kDeviceName,
"u2fd-tpm-cr50"),
u2f_msg_handler_.get());
return u2fhid_->Init();
}
std::optional<attestation::GetCertifiedNvIndexReply>
U2fHidServiceImpl::GetCertifiedG2fCert(int g2f_cert_size) {
if (g2f_cert_size < 1 || g2f_cert_size > VIRTUAL_NV_INDEX_G2F_CERT_SIZE) {
LOG(ERROR)
<< "Invalid G2F cert size specified for whitelisting data request";
return std::nullopt;
}
attestation::GetCertifiedNvIndexRequest request;
request.set_nv_index(VIRTUAL_NV_INDEX_G2F_CERT);
request.set_nv_size(g2f_cert_size);
request.set_key_label(kKeyLabelEmk);
brillo::ErrorPtr error;
std::unique_ptr<dbus::Response> dbus_response =
brillo::dbus_utils::CallMethodAndBlock(
attestation_proxy_, attestation::kAttestationInterface,
attestation::kGetCertifiedNvIndex, &error, request);
if (!dbus_response) {
LOG(ERROR) << "Failed to retrieve certified G2F cert from attestationd";
return std::nullopt;
}
attestation::GetCertifiedNvIndexReply reply;
dbus::MessageReader reader(dbus_response.get());
if (!reader.PopArrayOfBytesAsProto(&reply)) {
LOG(ERROR) << "Failed to parse GetCertifiedNvIndexReply";
return std::nullopt;
}
if (reply.status() != attestation::AttestationStatus::STATUS_SUCCESS) {
LOG(ERROR) << "Call get GetCertifiedNvIndex failed, status: "
<< reply.status();
return std::nullopt;
}
return reply;
}
} // namespace u2f