| // 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 "device_management/device_management_service.h" |
| #include "device_management/install_attributes/platform.h" |
| #include "device_management/proto_bindings/device_management_interface.pb.h" |
| #include "fwmp/firmware_management_parameters.h" |
| |
| #include <memory> |
| #include <unordered_map> |
| #include <vector> |
| |
| #include <base/logging.h> |
| #include <libhwsec/factory/factory_impl.h> |
| #include <libhwsec/structures/threading_mode.h> |
| |
| namespace device_management { |
| |
| DeviceManagementService::DeviceManagementService() |
| : firmware_management_parameters_(nullptr), |
| install_attrs_(nullptr), |
| enterprise_owned_(false) {} |
| DeviceManagementService::~DeviceManagementService() {} |
| |
| void DeviceManagementService::Initialize( |
| const hwsec::CryptohomeFrontend& hwsec_, Platform& platform_) { |
| firmware_management_parameters_ = |
| fwmp::FirmwareManagementParameters::CreateInstance(&hwsec_); |
| install_attrs_ = std::make_unique<InstallAttributes>(&platform_, &hwsec_); |
| // Initialize the install-time locked attributes since we can't do it prior |
| // to ownership. |
| InitializeInstallAttributes(); |
| } |
| |
| device_management::DeviceManagementErrorCode |
| DeviceManagementService::GetFirmwareManagementParameters( |
| device_management::FirmwareManagementParameters* fwmp) { |
| if (!firmware_management_parameters_->Load()) { |
| return device_management:: |
| DEVICE_MANAGEMENT_ERROR_FIRMWARE_MANAGEMENT_PARAMETERS_INVALID; |
| } |
| |
| uint32_t flags; |
| if (firmware_management_parameters_->GetFlags(&flags)) { |
| fwmp->set_flags(flags); |
| } else { |
| LOG(WARNING) |
| << "Failed to GetFlags() for GetFirmwareManagementParameters()."; |
| return device_management:: |
| DEVICE_MANAGEMENT_ERROR_FIRMWARE_MANAGEMENT_PARAMETERS_INVALID; |
| } |
| |
| std::vector<uint8_t> hash; |
| if (firmware_management_parameters_->GetDeveloperKeyHash(&hash)) { |
| *fwmp->mutable_developer_key_hash() = {hash.begin(), hash.end()}; |
| } else { |
| LOG(WARNING) << "Failed to GetDeveloperKeyHash() for " |
| "GetFirmwareManagementParameters()."; |
| return device_management:: |
| DEVICE_MANAGEMENT_ERROR_FIRMWARE_MANAGEMENT_PARAMETERS_INVALID; |
| } |
| |
| return device_management::DEVICE_MANAGEMENT_ERROR_NOT_SET; |
| } |
| |
| device_management::DeviceManagementErrorCode |
| DeviceManagementService::SetFirmwareManagementParameters( |
| const device_management::FirmwareManagementParameters& fwmp) { |
| if (!firmware_management_parameters_->Create()) { |
| return device_management:: |
| DEVICE_MANAGEMENT_ERROR_FIRMWARE_MANAGEMENT_PARAMETERS_CANNOT_STORE; |
| } |
| |
| uint32_t flags = fwmp.flags(); |
| std::unique_ptr<std::vector<uint8_t>> hash; |
| |
| if (!fwmp.developer_key_hash().empty()) { |
| hash.reset(new std::vector<uint8_t>(fwmp.developer_key_hash().begin(), |
| fwmp.developer_key_hash().end())); |
| } |
| |
| if (!firmware_management_parameters_->Store(flags, hash.get())) { |
| return device_management:: |
| DEVICE_MANAGEMENT_ERROR_FIRMWARE_MANAGEMENT_PARAMETERS_CANNOT_STORE; |
| } |
| |
| return device_management::DEVICE_MANAGEMENT_ERROR_NOT_SET; |
| } |
| |
| bool DeviceManagementService::RemoveFirmwareManagementParameters() { |
| return firmware_management_parameters_->Destroy(); |
| } |
| |
| bool DeviceManagementService::InstallAttributesGet( |
| const std::string& name, std::vector<uint8_t>* data_out) { |
| return install_attrs_->Get(name, data_out); |
| } |
| bool DeviceManagementService::InstallAttributesSet( |
| const std::string& name, const std::vector<uint8_t>& data) { |
| return install_attrs_->Set(name, data); |
| } |
| |
| bool DeviceManagementService::InstallAttributesFinalize() { |
| bool result = install_attrs_->Finalize(); |
| DetectEnterpriseOwnership(); |
| return result; |
| } |
| |
| int DeviceManagementService::InstallAttributesCount() { |
| return install_attrs_->Count(); |
| } |
| |
| bool DeviceManagementService::InstallAttributesIsSecure() { |
| return install_attrs_->IsSecure(); |
| } |
| |
| InstallAttributes::Status |
| DeviceManagementService::InstallAttributesGetStatus() { |
| return install_attrs_->status(); |
| } |
| |
| // static |
| device_management::InstallAttributesState |
| DeviceManagementService::InstallAttributesStatusToProtoEnum( |
| InstallAttributes::Status status) { |
| static const std::unordered_map<InstallAttributes::Status, |
| device_management::InstallAttributesState> |
| state_map = {{InstallAttributes::Status::kUnknown, |
| device_management::InstallAttributesState::UNKNOWN}, |
| {InstallAttributes::Status::kTpmNotOwned, |
| device_management::InstallAttributesState::TPM_NOT_OWNED}, |
| {InstallAttributes::Status::kFirstInstall, |
| device_management::InstallAttributesState::FIRST_INSTALL}, |
| {InstallAttributes::Status::kValid, |
| device_management::InstallAttributesState::VALID}, |
| {InstallAttributes::Status::kInvalid, |
| device_management::InstallAttributesState::INVALID}}; |
| if (state_map.count(status) != 0) { |
| return state_map.at(status); |
| } |
| |
| NOTREACHED(); |
| // Return is added so compiler doesn't complain. |
| return device_management::InstallAttributesState::INVALID; |
| } |
| |
| // NOTE: cryptohome will now query device_management service to know the status |
| // of `enterprise_owned_` variable. Earlier, we maintained another copy of |
| // this instance in homedirs_ (see below) and updated it from this function. |
| void DeviceManagementService::SetEnterpriseOwned(bool enterprise_owned) { |
| enterprise_owned_ = enterprise_owned; |
| // homedirs_->set_enterprise_owned(enterprise_owned); |
| } |
| |
| void DeviceManagementService::DetectEnterpriseOwnership() { |
| static const std::string true_str = "true"; |
| brillo::Blob true_value(true_str.begin(), true_str.end()); |
| true_value.push_back(0); |
| |
| brillo::Blob value; |
| if (install_attrs_->Get("enterprise.owned", &value) && value == true_value) { |
| // Update any active mounts with the state, have to be done on mount thread. |
| SetEnterpriseOwned(true); |
| } |
| // Note: Right now there's no way to convert an enterprise owned machine to a |
| // non-enterprise owned machine without clearing the TPM, so we don't try |
| // calling SetEnterpriseOwned() with false. |
| } |
| |
| void DeviceManagementService::InitializeInstallAttributes() { |
| // Don't reinitialize when install attributes are valid or first install. |
| if (install_attrs_->status() == InstallAttributes::Status::kValid || |
| install_attrs_->status() == InstallAttributes::Status::kFirstInstall) { |
| return; |
| } |
| |
| // The TPM owning instance may have changed since initialization. |
| // InstallAttributes can handle a NULL or !IsEnabled Tpm object. |
| std::ignore = install_attrs_->Init(); |
| |
| // Check if the machine is enterprise owned and report to mount_ then. |
| DetectEnterpriseOwnership(); |
| } |
| |
| } // namespace device_management |