blob: fb5b1c7c39b5d50c75cbddf9f6490779eaddb019 [file] [log] [blame] [edit]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <libarc-attestation/lib/version_attester.h>
#include <string>
#include <vector>
#include <brillo/secure_blob.h>
#include <libarc_attestation/proto_bindings/arc_attestation_blob.pb.h>
#include <libhwsec/factory/factory_impl.h>
#include <libhwsec/frontend/attestation/frontend.h>
using brillo::BlobFromString;
using brillo::BlobToString;
namespace arc_attestation {
VersionAttester::VersionAttester(Provisioner* provisioner)
: provisioner_(provisioner),
default_hwsec_factory_(nullptr),
hwsec_factory_(nullptr),
hwsec_frontend_(nullptr) {}
AndroidStatus VersionAttester::QuoteCrOSBlob(const brillo::Blob& challenge,
brillo::Blob& output) {
if (!InitHwsec()) {
return AndroidStatus::from_keymint_code(
AndroidStatus::KeymintSpecificErrorCode::
SECURE_HW_COMMUNICATION_FAILED);
}
if (!provisioner_->is_provisioned()) {
LOG(ERROR) << "Unable to quote OS version without provisioning keys";
return AndroidStatus::from_keymint_code(
AndroidStatus::KeymintSpecificErrorCode::
SECURE_HW_COMMUNICATION_FAILED);
}
std::optional<std::string> key_blob = provisioner_->GetTpmCertifyingKeyBlob();
if (!key_blob.has_value()) {
LOG(ERROR) << "No key blob for TpmCertifying key when quoting CrOSBlob";
return AndroidStatus::from_keymint_code(
AndroidStatus::KeymintSpecificErrorCode::
SECURE_HW_COMMUNICATION_FAILED);
}
std::optional<std::string> cert = provisioner_->GetTpmCertifyingKeyCert();
if (!cert.has_value()) {
LOG(ERROR) << "No cert for TpmCertifying key when quoting CrOSBlob";
return AndroidStatus::from_keymint_code(
AndroidStatus::KeymintSpecificErrorCode::
SECURE_HW_COMMUNICATION_FAILED);
}
auto result = hwsec_frontend_->AttestVersion(BlobFromString(*key_blob), *cert,
challenge);
if (!result.ok()) {
LOG(ERROR) << "Failed to attest OS version: " << result.status();
return AndroidStatus::from_keymint_code(
AndroidStatus::KeymintSpecificErrorCode::
SECURE_HW_COMMUNICATION_FAILED);
}
CrOSSpecificBlob result_blob;
*result_blob.mutable_version_attestation() = result.value();
std::vector<std::vector<uint8_t>> dk_certs;
AndroidStatus ret = provisioner_->GetDkCertChain(dk_certs);
if (!ret.is_ok()) {
return ret;
}
for (const std::vector<uint8_t>& cert : dk_certs) {
result_blob.add_device_key_certs(BlobToString(cert));
}
std::string output_str;
if (!result_blob.SerializeToString(&output_str)) {
LOG(ERROR) << "Failure to serialize blob in VersionAttester::QuoteCrOSBlob";
return AndroidStatus::from_keymint_code(
AndroidStatus::KeymintSpecificErrorCode::
SECURE_HW_COMMUNICATION_FAILED);
}
output = brillo::BlobFromString(output_str);
return AndroidStatus::ok();
}
bool VersionAttester::InitHwsec() {
if (!hwsec_factory_) {
if (!default_hwsec_factory_) {
default_hwsec_factory_ = std::make_unique<hwsec::FactoryImpl>(
hwsec::ThreadingMode::kCurrentThread);
}
hwsec_factory_ = default_hwsec_factory_.get();
}
if (!hwsec_frontend_) {
hwsec_frontend_ = hwsec_factory_->GetArcAttestationFrontend();
}
return true;
}
} // namespace arc_attestation