blob: 5c7e0f9a1a2788e058ce4b6a4e4174c724aa13fe [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/virtualizer.h"
#include <map>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <base/callback.h>
#include <base/files/file_path.h>
#include <trunks/command_parser.h>
#include <trunks/response_serializer.h>
#include <trunks/tpm_generated.h>
#include "vtpm/commands/get_capability_command.h"
#include "vtpm/commands/unsupported_command.h"
namespace vtpm {
namespace {
constexpr trunks::TPM_HANDLE kSrkHandle = trunks::PERSISTENT_FIRST;
// TODO(b/228789530): Virtualizer is not the best one that decides the layout of
// files. We should make sure that the path is managed in a more systematic way,
// and it should be revolved after all the persistent data is ready, and before
// the bug is resolved.
constexpr char kVsrkCachePath[] = "/var/lib/vtpm/vsrk.blob";
} // namespace
std::unique_ptr<Virtualizer> Virtualizer::Create(Virtualizer::Profile profile) {
std::unique_ptr<Virtualizer> v =
std::unique_ptr<Virtualizer>(new Virtualizer());
if (profile == Virtualizer::Profile::kGLinux) {
CHECK(v->trunks_factory_.Initialize())
<< " Failed to initialize trunks factory.";
v->command_parser_ = &v->real_command_parser_;
v->response_serializer_ = &v->real_response_serializer_;
// Set up VSRK.
v->vsrk_cache_ =
std::make_unique<DiskCacheBlob>(base::FilePath(kVsrkCachePath));
v->cacheable_vsrk_ =
std::make_unique<CacheableBlob>(&v->vsrk_, v->vsrk_cache_.get());
v->real_tpm_handle_manager_ = std::make_unique<RealTpmHandleManager>(
std::map<trunks::TPM_HANDLE, Blob*>{
{kSrkHandle, v->cacheable_vsrk_.get()},
});
// add `GetCapabilityCommand`.
v->commands_.emplace_back(std::make_unique<GetCapabilityCommand>(
&v->real_command_parser_, &v->real_response_serializer_,
v->real_tpm_handle_manager_.get()));
v->command_table_.emplace(trunks::TPM_CC_GetCapability,
v->commands_.back().get());
// Use an `UnsupportedCommand` as fallback.
v->commands_.emplace_back(
std::make_unique<UnsupportedCommand>(v->response_serializer_));
v->fallback_command_ = v->commands_.back().get();
// Others are not implemented yet.
}
return v;
}
Virtualizer::Virtualizer(trunks::CommandParser* parser,
trunks::ResponseSerializer* serializer,
std::unordered_map<trunks::TPM_CC, Command*> table,
Command* fallback_command)
: command_parser_(parser),
response_serializer_(serializer),
command_table_(std::move(table)),
fallback_command_(fallback_command) {}
void Virtualizer::Run(const std::string& command,
CommandResponseCallback callback) {
std::string buffer = command;
trunks::TPMI_ST_COMMAND_TAG tag;
trunks::UINT32 size;
trunks::TPM_CC cc;
const trunks::TPM_RC rc =
command_parser_->ParseHeader(&buffer, &tag, &size, &cc);
if (rc) {
std::string response;
response_serializer_->SerializeHeaderOnlyResponse(rc, &response);
std::move(callback).Run(response);
return;
}
if (command_table_.count(cc) == 0) {
fallback_command_->Run(command, std::move(callback));
return;
}
command_table_[cc]->Run(command, std::move(callback));
}
} // namespace vtpm