| // 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 |