blob: 5935c09cf28f55f9a91d12be71a6e799ffbf8c3d [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 "libhwsec/frontend/attestation/frontend_impl.h"
#include <string>
#include <utility>
#include <vector>
#include <attestation/proto_bindings/attestation_ca.pb.h>
#include <attestation/proto_bindings/database.pb.h>
#include <brillo/secure_blob.h>
#include <libhwsec-foundation/status/status_chain_macros.h>
#include "libhwsec/backend/backend.h"
#include "libhwsec/middleware/middleware.h"
#include "libhwsec/status.h"
#include "libhwsec/structures/key.h"
#include "libhwsec/structures/operation_policy.h"
#include "libhwsec/structures/space.h"
using hwsec_foundation::status::MakeStatus;
namespace hwsec {
namespace {
StatusOr<KeyAlgoType> ToKeyAlgoType(attestation::KeyType key_type) {
switch (key_type) {
case attestation::KeyType::KEY_TYPE_RSA:
return KeyAlgoType::kRsa;
case attestation::KeyType::KEY_TYPE_ECC:
return KeyAlgoType::kEcc;
}
return MakeStatus<TPMError>("Unsuported attestation key algorithm type",
TPMRetryAction::kNoRetry);
}
StatusOr<RoSpace> ToEndorsementCertSpace(attestation::KeyType key_type) {
switch (key_type) {
case attestation::KeyType::KEY_TYPE_RSA:
return RoSpace::kEndorsementRsaCert;
case attestation::KeyType::KEY_TYPE_ECC:
return RoSpace::kEndorsementEccCert;
}
return MakeStatus<TPMError>("Unsuported attestation key algorithm type",
TPMRetryAction::kNoRetry);
}
attestation::KeyType key_types[] = {attestation::KeyType::KEY_TYPE_RSA,
attestation::KeyType::KEY_TYPE_ECC};
} // namespace
StatusOr<attestation::TpmVersion> AttestationFrontendImpl::GetVersion() const {
return middleware_.CallSync<&Backend::Attestation::GetTpmVersion>();
}
Status AttestationFrontendImpl::WaitUntilReady() const {
return middleware_.CallSync<&Backend::State::WaitUntilReady>();
}
StatusOr<brillo::SecureBlob> AttestationFrontendImpl::Unseal(
const brillo::Blob& sealed_data) const {
return middleware_.CallSync<&Backend::Sealing::Unseal>(
OperationPolicy{
.device_configs =
DeviceConfigs{
DeviceConfig::kBootMode,
},
},
sealed_data, Sealing::UnsealOptions{});
}
StatusOr<brillo::Blob> AttestationFrontendImpl::Seal(
const brillo::SecureBlob& unsealed_data) const {
return middleware_.CallSync<&Backend::Sealing::Seal>(
OperationPolicySetting{
.device_config_settings =
DeviceConfigSettings{
.boot_mode =
DeviceConfigSettings::BootModeSetting{
.mode = std::nullopt,
},
},
},
unsealed_data);
}
StatusOr<attestation::Quote> AttestationFrontendImpl::Quote(
DeviceConfig device_config, const brillo::Blob& key_blob) const {
ASSIGN_OR_RETURN(
ScopedKey key,
middleware_.CallSync<&Backend::KeyManagement::LoadKey>(
OperationPolicy{}, key_blob,
Backend::KeyManagement::LoadKeyOptions{.auto_reload = true}));
return middleware_.CallSync<&Backend::Attestation::Quote>(
DeviceConfigs{device_config}, key.GetKey());
}
StatusOr<bool> AttestationFrontendImpl::IsQuoted(
DeviceConfig device_config, const attestation::Quote& quote) const {
return middleware_.CallSync<&Backend::Attestation::IsQuoted>(
DeviceConfigs{device_config}, quote);
}
StatusOr<DeviceConfigSettings::BootModeSetting::Mode>
AttestationFrontendImpl::GetCurrentBootMode() const {
return middleware_.CallSync<&Backend::Config::GetCurrentBootMode>();
}
StatusOr<attestation::Quote> AttestationFrontendImpl::CertifyNV(
RoSpace space, const brillo::Blob& key_blob) const {
ASSIGN_OR_RETURN(
ScopedKey key,
middleware_.CallSync<&Backend::KeyManagement::LoadKey>(
OperationPolicy{}, key_blob,
Backend::KeyManagement::LoadKeyOptions{.auto_reload = true}));
return middleware_.CallSync<&Backend::RoData::Certify>(space, key.GetKey());
}
StatusOr<attestation::CertifiedKey> AttestationFrontendImpl::CreateCertifiedKey(
const brillo::Blob& identity_key_blob,
attestation::KeyType key_type,
attestation::KeyUsage key_usage,
KeyRestriction restriction,
EndorsementAuth endorsement_auth,
const std::string& external_data) const {
ASSIGN_OR_RETURN(
const ScopedKey& identity_key,
middleware_.CallSync<&Backend::KeyManagement::LoadKey>(
OperationPolicy{}, identity_key_blob,
Backend::KeyManagement::LoadKeyOptions{.auto_reload = true}));
return middleware_.CallSync<&Backend::Attestation::CreateCertifiedKey>(
identity_key.GetKey(), key_type, key_usage, restriction, endorsement_auth,
external_data);
}
StatusOr<Attestation::CreateIdentityResult>
AttestationFrontendImpl::CreateIdentity(attestation::KeyType key_type) const {
return middleware_.CallSync<&Backend::Attestation::CreateIdentity>(key_type);
}
StatusOr<brillo::Blob> AttestationFrontendImpl::GetEndorsementPublicKey(
attestation::KeyType key_type,
KeyManagement::PublicKeyEncoding encoding) const {
ASSIGN_OR_RETURN(KeyAlgoType key_algo, ToKeyAlgoType(key_type));
return middleware_.CallSync<&Backend::KeyManagement::GetEndorsementPublicKey>(
key_algo, encoding);
}
StatusOr<std::vector<attestation::KeyType>>
AttestationFrontendImpl::GetSupportedKeyTypes() const {
ASSIGN_OR_RETURN(
absl::flat_hash_set<KeyAlgoType> key_algoes,
middleware_.CallSync<&Backend::KeyManagement::GetSupportedAlgo>());
std::vector<attestation::KeyType> result;
for (auto key_type : key_types) {
ASSIGN_OR_RETURN(KeyAlgoType key_algo, ToKeyAlgoType(key_type));
if (key_algoes.count(key_algo)) {
result.push_back(key_type);
}
}
return result;
}
StatusOr<brillo::Blob> AttestationFrontendImpl::Sign(
const brillo::Blob& key_blob, const brillo::Blob& data) const {
ASSIGN_OR_RETURN(
const ScopedKey& key,
middleware_.CallSync<&Backend::KeyManagement::LoadKey>(
OperationPolicy{}, key_blob,
Backend::KeyManagement::LoadKeyOptions{.auto_reload = true}));
return middleware_.CallSync<&Backend::Signing::Sign>(
key.GetKey(), data,
SigningOptions{.ecdsa_encoding = SigningOptions::EcdsaEncoding::kDer});
}
StatusOr<brillo::SecureBlob> AttestationFrontendImpl::ActivateIdentity(
attestation::KeyType key_type,
const brillo::Blob& identity_key_blob,
const attestation::EncryptedIdentityCredential& encrypted_certificate)
const {
ASSIGN_OR_RETURN(
const ScopedKey& identity_key,
middleware_.CallSync<&Backend::KeyManagement::LoadKey>(
OperationPolicy{}, identity_key_blob,
Backend::KeyManagement::LoadKeyOptions{.auto_reload = true}));
return middleware_.CallSync<&Backend::Attestation::ActivateIdentity>(
key_type, identity_key.GetKey(), encrypted_certificate);
}
StatusOr<brillo::Blob> AttestationFrontendImpl::GetEndorsementCert(
attestation::KeyType key_type) const {
ASSIGN_OR_RETURN(RoSpace space, ToEndorsementCertSpace(key_type));
return middleware_.CallSync<&Backend::RoData::Read>(space);
}
StatusOr<bool> AttestationFrontendImpl::IsReady() const {
return middleware_.CallSync<&Backend::State::IsReady>();
}
Status AttestationFrontendImpl::FinalizeEnrollmentPreparation() const {
return middleware_
.CallSync<&Backend::Attestation::FinalizeEnrollmentPreparation>();
}
} // namespace hwsec