Commit 27d305cb authored by Leo Lai's avatar Leo Lai Committed by Chromium LUCI CQ

DeviceStatusCollector use (TpmManager|Attestation)Client.

We are deprecating GetTpmStatus by cryptohome.

Also, dropping the status of boot lockbox because it isn't supported by
cryptohome anymore.

BUG=b:172748724
TEST=browser_tests.

Change-Id: Iefe7060ba64aec11f12fce188cb0f1c146124b6b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2569431
Commit-Queue: Leo Lai <cylai@google.com>
Reviewed-by: default avatarMaksim Ivanov <emaxx@chromium.org>
Cr-Commit-Position: refs/heads/master@{#834210}
parent f323251b
......@@ -2395,6 +2395,8 @@ source_set("chromeos") {
"policy/status_collector/status_collector.h",
"policy/status_collector/status_collector_state.cc",
"policy/status_collector/status_collector_state.h",
"policy/status_collector/tpm_status_combiner.cc",
"policy/status_collector/tpm_status_combiner.h",
"policy/status_uploader.cc",
"policy/status_uploader.h",
"policy/system_features_disable_list_policy_handler.cc",
......
......@@ -55,6 +55,7 @@
#include "chrome/browser/chromeos/policy/status_collector/enterprise_activity_storage.h"
#include "chrome/browser/chromeos/policy/status_collector/interval_map.h"
#include "chrome/browser/chromeos/policy/status_collector/status_collector_state.h"
#include "chrome/browser/chromeos/policy/status_collector/tpm_status_combiner.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/crash_upload_list/crash_upload_list.h"
......@@ -64,6 +65,7 @@
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chromeos/audio/cras_audio_handler.h"
#include "chromeos/dbus/attestation/attestation_client.h"
#include "chromeos/dbus/cryptohome/cryptohome_client.h"
#include "chromeos/dbus/cryptohome/rpc.pb.h"
#include "chromeos/dbus/cryptohome/tpm_util.h"
......@@ -435,57 +437,23 @@ bool ReadAndroidStatus(
return true;
}
// Converts the given GetTpmStatusReply to TpmStatusInfo.
policy::TpmStatusInfo GetTpmStatusReplyToTpmStatusInfo(
const base::Optional<cryptohome::BaseReply>& reply) {
policy::TpmStatusInfo tpm_status_info;
if (!reply.has_value()) {
LOG(ERROR) << "GetTpmStatus call failed with empty reply.";
return tpm_status_info;
}
if (reply->has_error() &&
reply->error() != cryptohome::CRYPTOHOME_ERROR_NOT_SET) {
LOG(ERROR) << "GetTpmStatus failed with error: " << reply->error();
return tpm_status_info;
}
if (!reply->HasExtension(cryptohome::GetTpmStatusReply::reply)) {
LOG(ERROR)
<< "GetTpmStatus failed with no GetTpmStatusReply extension in reply.";
return tpm_status_info;
}
auto reply_proto = reply->GetExtension(cryptohome::GetTpmStatusReply::reply);
tpm_status_info.enabled = reply_proto.enabled();
tpm_status_info.owned = reply_proto.owned();
tpm_status_info.initialized = reply_proto.initialized();
tpm_status_info.attestation_prepared = reply_proto.attestation_prepared();
tpm_status_info.attestation_enrolled = reply_proto.attestation_enrolled();
tpm_status_info.dictionary_attack_counter =
reply_proto.dictionary_attack_counter();
tpm_status_info.dictionary_attack_threshold =
reply_proto.dictionary_attack_threshold();
tpm_status_info.dictionary_attack_lockout_in_effect =
reply_proto.dictionary_attack_lockout_in_effect();
tpm_status_info.dictionary_attack_lockout_seconds_remaining =
reply_proto.dictionary_attack_lockout_seconds_remaining();
tpm_status_info.boot_lockbox_finalized = reply_proto.boot_lockbox_finalized();
return tpm_status_info;
}
void ReadTpmStatus(policy::DeviceStatusCollector::TpmStatusReceiver callback) {
// D-Bus calls are allowed only on the UI thread.
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
chromeos::CryptohomeClient::Get()->GetTpmStatus(
cryptohome::GetTpmStatusRequest(),
base::BindOnce(
[](policy::DeviceStatusCollector::TpmStatusReceiver callback,
base::Optional<cryptohome::BaseReply> reply) {
std::move(callback).Run(GetTpmStatusReplyToTpmStatusInfo(reply));
},
std::move(callback)));
auto tpm_status_combiner =
base::MakeRefCounted<::policy::TpmStatusCombiner>(std::move(callback));
chromeos::TpmManagerClient::Get()->GetTpmNonsensitiveStatus(
::tpm_manager::GetTpmNonsensitiveStatusRequest(),
base::BindOnce(&::policy::TpmStatusCombiner::OnGetTpmStatus,
tpm_status_combiner));
chromeos::AttestationClient::Get()->GetStatus(
::attestation::GetStatusRequest(),
base::BindOnce(&::policy::TpmStatusCombiner::OnGetEnrollmentStatus,
tpm_status_combiner));
chromeos::TpmManagerClient::Get()->GetDictionaryAttackInfo(
::tpm_manager::GetDictionaryAttackInfoRequest(),
base::BindOnce(&::policy::TpmStatusCombiner::OnGetDictionaryAttackInfo,
tpm_status_combiner));
}
base::Version GetPlatformVersion() {
......
......@@ -57,6 +57,7 @@
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "chromeos/audio/cras_audio_handler.h"
#include "chromeos/dbus/attestation/attestation_client.h"
#include "chromeos/dbus/cros_disks_client.h"
#include "chromeos/dbus/cros_healthd/cros_healthd_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
......@@ -280,7 +281,6 @@ class TestingDeviceStatusCollectorOptions {
policy::DeviceStatusCollector::CPUStatisticsFetcher cpu_fetcher;
policy::DeviceStatusCollector::CPUTempFetcher cpu_temp_fetcher;
policy::StatusCollector::AndroidStatusFetcher android_status_fetcher;
policy::DeviceStatusCollector::TpmStatusFetcher tpm_status_fetcher;
policy::DeviceStatusCollector::EMMCLifetimeFetcher emmc_lifetime_fetcher;
policy::DeviceStatusCollector::StatefulPartitionInfoFetcher
stateful_partition_info_fetcher;
......@@ -294,24 +294,27 @@ class TestingDeviceStatusCollectorOptions {
class TestingDeviceStatusCollector : public policy::DeviceStatusCollector {
public:
// Note that that TpmStatusFetcher is null so the test exercises the
// production logic with fake tpm manager and attestation clients.
TestingDeviceStatusCollector(
PrefService* pref_service,
chromeos::system::StatisticsProvider* provider,
std::unique_ptr<TestingDeviceStatusCollectorOptions> options,
base::SimpleTestClock* clock)
: policy::DeviceStatusCollector(pref_service,
provider,
options->volume_info_fetcher,
options->cpu_fetcher,
options->cpu_temp_fetcher,
options->android_status_fetcher,
options->tpm_status_fetcher,
options->emmc_lifetime_fetcher,
options->stateful_partition_info_fetcher,
options->cros_healthd_data_fetcher,
options->graphics_status_fetcher,
options->crash_report_info_fetcher,
clock),
: policy::DeviceStatusCollector(
pref_service,
provider,
options->volume_info_fetcher,
options->cpu_fetcher,
options->cpu_temp_fetcher,
options->android_status_fetcher,
policy::DeviceStatusCollector::TpmStatusFetcher(),
options->emmc_lifetime_fetcher,
options->stateful_partition_info_fetcher,
options->cros_healthd_data_fetcher,
options->graphics_status_fetcher,
options->crash_report_info_fetcher,
clock),
test_clock_(*clock) {
// Set the baseline time to a fixed value (1 hour after day start) to
// prevent test flakiness due to a single activity period spanning two days.
......@@ -454,17 +457,6 @@ bool GetFakeAndroidStatus(
return true;
}
void GetEmptyTpmStatus(
policy::DeviceStatusCollector::TpmStatusReceiver receiver) {
std::move(receiver).Run(policy::TpmStatusInfo());
}
void GetFakeTpmStatus(
const policy::TpmStatusInfo& tpm_status_info,
policy::DeviceStatusCollector::TpmStatusReceiver receiver) {
std::move(receiver).Run(tpm_status_info);
}
em::DiskLifetimeEstimation GetEmptyEMMCLifetimeEstimation() {
return em::DiskLifetimeEstimation();
}
......@@ -799,6 +791,7 @@ class DeviceStatusCollectorTest : public testing::Test {
chromeos::CrasAudioHandler::InitializeForTesting();
chromeos::CryptohomeClient::InitializeFake();
chromeos::PowerManagerClient::InitializeFake();
chromeos::AttestationClient::InitializeFake();
chromeos::TpmManagerClient::InitializeFake();
chromeos::LoginState::Initialize();
}
......@@ -806,6 +799,7 @@ class DeviceStatusCollectorTest : public testing::Test {
~DeviceStatusCollectorTest() override {
chromeos::LoginState::Shutdown();
chromeos::TpmManagerClient::Shutdown();
chromeos::AttestationClient::Shutdown();
chromeos::PowerManagerClient::Shutdown();
chromeos::CryptohomeClient::Shutdown();
chromeos::CrasAudioHandler::Shutdown();
......@@ -866,7 +860,7 @@ class DeviceStatusCollectorTest : public testing::Test {
options->cpu_temp_fetcher = base::BindRepeating(&GetEmptyCPUTempInfo);
options->android_status_fetcher =
base::BindRepeating(&GetEmptyAndroidStatus);
options->tpm_status_fetcher = base::BindRepeating(&GetEmptyTpmStatus);
options->emmc_lifetime_fetcher =
base::BindRepeating(&GetEmptyEMMCLifetimeEstimation);
options->stateful_partition_info_fetcher =
......@@ -2229,47 +2223,94 @@ TEST_F(DeviceStatusCollectorTest,
}
TEST_F(DeviceStatusCollectorTest, TpmStatusReporting) {
// Create a fake TPM status info and populate it with some random values.
const policy::TpmStatusInfo kFakeTpmStatus{
true, /* enabled */
false, /* owned */
true, /* initialized */
false, /* attestation_prepared */
true, /* attestation_enrolled */
5, /* dictionary_attack_counter */
10, /* dictionary_attack_threshold */
false, /* dictionary_attack_lockout_in_effect */
0, /* dictionary_attack_lockout_seconds_remaining */
true /* boot_lockbox_finalized */
};
auto options = CreateEmptyDeviceStatusCollectorOptions();
options->tpm_status_fetcher =
base::BindRepeating(&GetFakeTpmStatus, kFakeTpmStatus);
RestartStatusCollector(std::move(options));
auto* tpm_status_reply = chromeos::TpmManagerClient::Get()
->GetTestInterface()
->mutable_nonsensitive_status_reply();
tpm_status_reply->set_is_enabled(true);
tpm_status_reply->set_is_owned(true);
tpm_status_reply->set_is_owner_password_present(false);
auto* enrollment_status_reply = chromeos::AttestationClient::Get()
->GetTestInterface()
->mutable_status_reply();
enrollment_status_reply->set_prepared_for_enrollment(true);
enrollment_status_reply->set_enrolled(false);
auto* da_info_reply = chromeos::TpmManagerClient::Get()
->GetTestInterface()
->mutable_dictionary_attack_info_reply();
da_info_reply->set_dictionary_attack_counter(5);
da_info_reply->set_dictionary_attack_threshold(10);
da_info_reply->set_dictionary_attack_lockout_in_effect(false);
da_info_reply->set_dictionary_attack_lockout_seconds_remaining(0);
GetStatus();
EXPECT_TRUE(device_status_.has_tpm_status_info());
EXPECT_EQ(kFakeTpmStatus.enabled, device_status_.tpm_status_info().enabled());
EXPECT_EQ(kFakeTpmStatus.owned, device_status_.tpm_status_info().owned());
EXPECT_EQ(kFakeTpmStatus.initialized,
EXPECT_EQ(tpm_status_reply->is_enabled(),
device_status_.tpm_status_info().enabled());
EXPECT_EQ(tpm_status_reply->is_owned(),
device_status_.tpm_status_info().owned());
EXPECT_EQ(tpm_status_reply->is_owned() &&
!tpm_status_reply->is_owner_password_present(),
device_status_.tpm_status_info().tpm_initialized());
EXPECT_EQ(kFakeTpmStatus.attestation_prepared,
EXPECT_EQ(enrollment_status_reply->prepared_for_enrollment(),
device_status_.tpm_status_info().attestation_prepared());
EXPECT_EQ(kFakeTpmStatus.attestation_enrolled,
EXPECT_EQ(enrollment_status_reply->enrolled(),
device_status_.tpm_status_info().attestation_enrolled());
EXPECT_EQ(kFakeTpmStatus.dictionary_attack_counter,
EXPECT_EQ(da_info_reply->dictionary_attack_counter(),
device_status_.tpm_status_info().dictionary_attack_counter());
EXPECT_EQ(kFakeTpmStatus.dictionary_attack_threshold,
EXPECT_EQ(da_info_reply->dictionary_attack_threshold(),
device_status_.tpm_status_info().dictionary_attack_threshold());
EXPECT_EQ(
kFakeTpmStatus.dictionary_attack_lockout_in_effect,
da_info_reply->dictionary_attack_lockout_in_effect(),
device_status_.tpm_status_info().dictionary_attack_lockout_in_effect());
EXPECT_EQ(kFakeTpmStatus.dictionary_attack_lockout_seconds_remaining,
EXPECT_EQ(da_info_reply->dictionary_attack_lockout_seconds_remaining(),
device_status_.tpm_status_info()
.dictionary_attack_lockout_seconds_remaining());
EXPECT_EQ(kFakeTpmStatus.boot_lockbox_finalized,
device_status_.tpm_status_info().boot_lockbox_finalized());
EXPECT_EQ(false, device_status_.tpm_status_info().boot_lockbox_finalized());
}
// Checks if tpm status is partially reported even if any error happens
// among the multiple D-Bus calls.
TEST_F(DeviceStatusCollectorTest, TpmStatusReportingAnyDBusError) {
auto* tpm_status_reply = chromeos::TpmManagerClient::Get()
->GetTestInterface()
->mutable_nonsensitive_status_reply();
auto* enrollment_status_reply = chromeos::AttestationClient::Get()
->GetTestInterface()
->mutable_status_reply();
auto* da_info_reply = chromeos::TpmManagerClient::Get()
->GetTestInterface()
->mutable_dictionary_attack_info_reply();
tpm_status_reply->set_status(::tpm_manager::STATUS_DBUS_ERROR);
enrollment_status_reply->set_prepared_for_enrollment(true);
GetStatus();
EXPECT_EQ(enrollment_status_reply->prepared_for_enrollment(),
device_status_.tpm_status_info().attestation_prepared());
// Reset the error status.
tpm_status_reply->set_status(::tpm_manager::STATUS_SUCCESS);
RestartStatusCollector();
enrollment_status_reply->set_status(::attestation::STATUS_DBUS_ERROR);
da_info_reply->set_dictionary_attack_counter(5);
GetStatus();
// Reset the error status.
EXPECT_EQ(da_info_reply->dictionary_attack_counter(),
device_status_.tpm_status_info().dictionary_attack_counter());
// Reset the error status.
enrollment_status_reply->set_status(::attestation::STATUS_SUCCESS);
RestartStatusCollector();
da_info_reply->set_status(::tpm_manager::STATUS_DBUS_ERROR);
tpm_status_reply->set_is_enabled(true);
GetStatus();
EXPECT_TRUE(device_status_.has_tpm_status_info());
EXPECT_EQ(tpm_status_reply->is_enabled(),
device_status_.tpm_status_info().enabled());
// Reset the error status (for symmetry).
da_info_reply->set_status(::tpm_manager::STATUS_SUCCESS);
}
TEST_F(DeviceStatusCollectorTest, NoTimeZoneReporting) {
......
// Copyright 2020 The Chromium 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 "chrome/browser/chromeos/policy/status_collector/tpm_status_combiner.h"
#include <utility>
#include "base/logging.h"
namespace policy {
TpmStatusCombiner::TpmStatusCombiner(
DeviceStatusCollector::TpmStatusReceiver callback)
: callback_(std::move(callback)) {
DCHECK(!callback_.is_null());
}
TpmStatusCombiner::~TpmStatusCombiner() = default;
void TpmStatusCombiner::OnGetTpmStatus(
const ::tpm_manager::GetTpmNonsensitiveStatusReply& reply) {
has_tpm_status_ = true;
if (reply.status() == ::tpm_manager::STATUS_SUCCESS) {
tpm_status_info_.enabled = reply.is_enabled();
tpm_status_info_.owned = reply.is_owned();
// Wiped owner password means the TPm initialization is done and no any
// further operations needed.
tpm_status_info_.initialized =
reply.is_owned() && !reply.is_owner_password_present();
} else {
LOG(WARNING) << "Failed to get tpm status.";
}
RunCallbackIfComplete();
}
void TpmStatusCombiner::OnGetEnrollmentStatus(
const ::attestation::GetStatusReply& reply) {
has_enrollment_status_ = true;
if (reply.status() == ::attestation::STATUS_SUCCESS) {
tpm_status_info_.attestation_prepared = reply.prepared_for_enrollment();
tpm_status_info_.attestation_enrolled = reply.enrolled();
} else {
LOG(WARNING) << "Failed to get enrollment info.";
}
RunCallbackIfComplete();
}
void TpmStatusCombiner::OnGetDictionaryAttackInfo(
const ::tpm_manager::GetDictionaryAttackInfoReply& reply) {
has_dictionary_attack_info_ = true;
if (reply.status() == ::tpm_manager::STATUS_SUCCESS) {
tpm_status_info_.dictionary_attack_counter =
reply.dictionary_attack_counter();
tpm_status_info_.dictionary_attack_threshold =
reply.dictionary_attack_threshold();
tpm_status_info_.dictionary_attack_lockout_in_effect =
reply.dictionary_attack_lockout_in_effect();
tpm_status_info_.dictionary_attack_lockout_seconds_remaining =
reply.dictionary_attack_lockout_seconds_remaining();
} else {
LOG(WARNING) << "Failed to get dictionary attack info.";
}
RunCallbackIfComplete();
}
void TpmStatusCombiner::RunCallbackIfComplete() {
if (!has_tpm_status_ || !has_enrollment_status_ ||
!has_dictionary_attack_info_)
return;
std::move(callback_).Run(tpm_status_info_);
}
} // namespace policy
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_CHROMEOS_POLICY_STATUS_COLLECTOR_TPM_STATUS_COMBINER_H_
#define CHROME_BROWSER_CHROMEOS_POLICY_STATUS_COLLECTOR_TPM_STATUS_COMBINER_H_
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "chrome/browser/chromeos/policy/status_collector/device_status_collector.h"
#include "chromeos/dbus/attestation/interface.pb.h"
#include "chromeos/dbus/tpm_manager/tpm_manager.pb.h"
namespace policy {
// This class is meant to combine multiple statuses around TPM and enrollment.
// Because the result `policy::TpmStatusInfo` comes from different sources of
// D-Bus calls, this class is designed to be used as a shared pointer that
// resides in multiple callbacks. When all the replies of the D-Bus calls, which
// are sent by the user of this class, are finished, this class combines the
// results into a single `policy::TpmStatusInfo` and get destroyed naturally
// when all the callbacks of the D-Bus calls are done.
//
// Note that in order to increase test coverage of `DeviceStatusCollector`, this
// class doesn't have its own unittest; instead, it is tested along with
// `DeviceStatusCollector` end-to-end.
class TpmStatusCombiner : public base::RefCounted<TpmStatusCombiner> {
public:
// The passed `callback` is invoked when all the D-Bus responses of
// interest are received.
explicit TpmStatusCombiner(DeviceStatusCollector::TpmStatusReceiver callback);
// Not copyable or movable.
TpmStatusCombiner(const TpmStatusCombiner&) = delete;
TpmStatusCombiner& operator=(const TpmStatusCombiner&) = delete;
TpmStatusCombiner(TpmStatusCombiner&&) = delete;
TpmStatusCombiner& operator=(TpmStatusCombiner&&) = delete;
// Designed to be the callback of
// `TpmManagerClient::GetTpmNonsensitiveStatus()`.
void OnGetTpmStatus(
const ::tpm_manager::GetTpmNonsensitiveStatusReply& reply);
// Designed to be the callback of `AttestationClient::GetStatus()`.
void OnGetEnrollmentStatus(const ::attestation::GetStatusReply& reply);
// Designed to be the callback of
// `AttestationClient::GetDictionaryAttackInfoReply()`.
void OnGetDictionaryAttackInfo(
const ::tpm_manager::GetDictionaryAttackInfoReply& reply);
private:
// `RefCounted` subclass requires the destructor to be non-public.
friend class base::RefCounted<TpmStatusCombiner>;
~TpmStatusCombiner();
// Called when receiving any D-Bus response. If it's the last D-Bus response
// we expect to handle, runs the callback passed in
void RunCallbackIfComplete();
// Invoked when all D-Bus response are handled.
DeviceStatusCollector::TpmStatusReceiver callback_;
// The combined result passed into `callback_`.
policy::TpmStatusInfo tpm_status_info_;
// Indicates each D-Bus response being received or not.
bool has_tpm_status_ = false;
bool has_enrollment_status_ = false;
bool has_dictionary_attack_info_ = false;
};
} // namespace policy
#endif // CHROME_BROWSER_CHROMEOS_POLICY_STATUS_COLLECTOR_TPM_STATUS_COMBINER_H_
......@@ -56,7 +56,7 @@ void FakeTpmManagerClient::GetVersionInfo(
void FakeTpmManagerClient::GetDictionaryAttackInfo(
const ::tpm_manager::GetDictionaryAttackInfoRequest& request,
GetDictionaryAttackInfoCallback callback) {
NOTIMPLEMENTED();
PostProtoResponse(std::move(callback), dictionary_attack_info_reply_);
}
void FakeTpmManagerClient::TakeOwnership(
......@@ -100,6 +100,11 @@ FakeTpmManagerClient::mutable_version_info_reply() {
return &version_info_reply_;
}
::tpm_manager::GetDictionaryAttackInfoReply*
FakeTpmManagerClient::mutable_dictionary_attack_info_reply() {
return &dictionary_attack_info_reply_;
}
int FakeTpmManagerClient::clear_stored_owner_password_count() const {
return clear_stored_owner_password_count_;
}
......
......@@ -50,6 +50,8 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_TPM_MANAGER) FakeTpmManagerClient
mutable_nonsensitive_status_reply() override;
void set_non_nonsensitive_status_dbus_error_count(int count) override;
::tpm_manager::GetVersionInfoReply* mutable_version_info_reply() override;
::tpm_manager::GetDictionaryAttackInfoReply*
mutable_dictionary_attack_info_reply() override;
int clear_stored_owner_password_count() const override;
void EmitOwnershipTakenSignal() override;
......@@ -57,6 +59,7 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_TPM_MANAGER) FakeTpmManagerClient
::tpm_manager::GetTpmNonsensitiveStatusReply nonsensitive_status_reply_;
int nonsensitive_status_dbus_error_count_ = 0;
::tpm_manager::GetVersionInfoReply version_info_reply_;
::tpm_manager::GetDictionaryAttackInfoReply dictionary_attack_info_reply_;
int clear_stored_owner_password_count_ = 0;
// The observer list of ownership taken signal.
......
......@@ -56,6 +56,10 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_TPM_MANAGER) TpmManagerClient {
// Gets a mutable reply that is returned when `GetVersionInfo()` is called.
virtual ::tpm_manager::GetVersionInfoReply*
mutable_version_info_reply() = 0;
// Gets a mutable reply that is returned when `GetDictionaryAttackInfo()` is
// called.
virtual ::tpm_manager::GetDictionaryAttackInfoReply*
mutable_dictionary_attack_info_reply() = 0;
// Gets the count of `ClearStoredOwnerPassword()` being called.
virtual int clear_stored_owner_password_count() const = 0;
// Emits ownership taken signal.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment