blob: d3bb14ba93e2fb382d47e883a4f5f3c4a0f790fb [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 "vtpm/commands/get_capability_command.h"
#include <algorithm>
#include <string>
#include <utility>
#include <vector>
#include <base/callback.h>
#include <base/logging.h>
#include <trunks/command_parser.h>
#include <trunks/response_serializer.h>
#include "vtpm/backends/tpm_handle_manager.h"
namespace vtpm {
GetCapabilityCommand::GetCapabilityCommand(
trunks::CommandParser* command_parser,
trunks::ResponseSerializer* response_serializer,
TpmHandleManager* tpm_handle_manager)
: command_parser_(command_parser),
response_serializer_(response_serializer),
tpm_handle_manager_(tpm_handle_manager) {
CHECK(command_parser_);
CHECK(response_serializer_);
CHECK(tpm_handle_manager_);
}
void GetCapabilityCommand::Run(const std::string& command,
CommandResponseCallback callback) {
trunks::TPM_CAP cap;
trunks::UINT32 property;
trunks::UINT32 property_count;
std::string buffer = command;
trunks::TPM_RC rc = command_parser_->ParseCommandGetCapability(
&buffer, &cap, &property, &property_count);
if (rc) {
ReturnWithError(rc, std::move(callback));
return;
}
// Only "handles" capability is supported. Also, the supported handle types
// are judged by `tpm_handle_manager_`.
if (cap != trunks::TPM_CAP_HANDLES) {
rc = trunks::TPM_RC_VALUE;
} else if (!tpm_handle_manager_->IsHandleTypeSuppoerted(property)) {
rc = trunks::TPM_RC_HANDLE;
}
if (rc) {
ReturnWithError(rc, std::move(callback));
return;
}
trunks::TPMS_CAPABILITY_DATA cap_data = {.capability =
trunks::TPM_CAP_HANDLES};
std::vector<trunks::TPM_HANDLE> found_handles;
rc = tpm_handle_manager_->GetHandleList(property, &found_handles);
if (rc) {
ReturnWithError(rc, std::move(callback));
return;
}
if (property_count > MAX_CAP_HANDLES)
property_count = MAX_CAP_HANDLES;
const trunks::TPMI_YES_NO has_more =
(found_handles.size() > property_count ? YES : NO);
cap_data.data.handles.count =
has_more ? property_count : found_handles.size();
std::copy(found_handles.begin(),
found_handles.begin() + cap_data.data.handles.count,
cap_data.data.handles.handle);
std::string response;
response_serializer_->SerializeResponseGetCapability(has_more, cap_data,
&response);
std::move(callback).Run(response);
return;
}
void GetCapabilityCommand::ReturnWithError(trunks::TPM_RC rc,
CommandResponseCallback callback) {
DCHECK_NE(rc, trunks::TPM_RC_SUCCESS);
std::string response;
response_serializer_->SerializeHeaderOnlyResponse(rc, &response);
std::move(callback).Run(response);
}
} // namespace vtpm