device_active_use_case.cc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright 2022 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/components/device_activity/device_active_use_case.h"
  5. #include "base/strings/string_number_conversions.h"
  6. #include "base/strings/string_util.h"
  7. #include "chromeos/system/statistics_provider.h"
  8. #include "components/prefs/pref_service.h"
  9. #include "components/version_info/version_info.h"
  10. #include "crypto/hmac.h"
  11. #include "third_party/private_membership/src/private_membership_rlwe_client.h"
  12. namespace ash {
  13. namespace device_activity {
  14. namespace psm_rlwe = private_membership::rlwe;
  15. namespace {
  16. // Default value for devices that are missing the hardware class.
  17. const char kHardwareClassKeyNotFound[] = "HARDWARE_CLASS_KEY_NOT_FOUND";
  18. } // namespace
  19. DeviceActiveUseCase::DeviceActiveUseCase(
  20. const std::string& psm_device_active_secret,
  21. const ChromeDeviceMetadataParameters& chrome_passed_device_params,
  22. const std::string& use_case_pref_key,
  23. psm_rlwe::RlweUseCase psm_use_case,
  24. PrefService* local_state)
  25. : psm_device_active_secret_(psm_device_active_secret),
  26. chrome_passed_device_params_(chrome_passed_device_params),
  27. use_case_pref_key_(use_case_pref_key),
  28. psm_use_case_(psm_use_case),
  29. local_state_(local_state),
  30. statistics_provider_(
  31. chromeos::system::StatisticsProvider::GetInstance()) {}
  32. DeviceActiveUseCase::~DeviceActiveUseCase() = default;
  33. PrefService* DeviceActiveUseCase::GetLocalState() const {
  34. return local_state_;
  35. }
  36. base::Time DeviceActiveUseCase::GetLastKnownPingTimestamp() const {
  37. return GetLocalState()->GetTime(use_case_pref_key_);
  38. }
  39. void DeviceActiveUseCase::SetLastKnownPingTimestamp(base::Time new_ts) {
  40. GetLocalState()->SetTime(use_case_pref_key_, new_ts);
  41. }
  42. bool DeviceActiveUseCase::IsLastKnownPingTimestampSet() const {
  43. return GetLastKnownPingTimestamp() != base::Time::UnixEpoch();
  44. }
  45. psm_rlwe::RlweUseCase DeviceActiveUseCase::GetPsmUseCase() const {
  46. return psm_use_case_;
  47. }
  48. absl::optional<std::string> DeviceActiveUseCase::GetWindowIdentifier() const {
  49. return window_id_;
  50. }
  51. void DeviceActiveUseCase::SetWindowIdentifier(
  52. absl::optional<std::string> window_id) {
  53. window_id_ = window_id;
  54. // nullopt the psm_id_ if a new window_id gets assigned.
  55. psm_id_ = absl::nullopt;
  56. // Reset |psm_rlwe_client_| since it also depends on psm_id value.
  57. psm_rlwe_client_.reset();
  58. }
  59. std::string DeviceActiveUseCase::GetDigestString(
  60. const std::string& key,
  61. const std::string& message) const {
  62. crypto::HMAC hmac(crypto::HMAC::SHA256);
  63. std::vector<uint8_t> digest(hmac.DigestLength());
  64. if (!hmac.Init(key) || !hmac.Sign(message, &digest[0], digest.size())) {
  65. return std::string();
  66. }
  67. return base::HexEncode(&digest[0], digest.size());
  68. }
  69. absl::optional<psm_rlwe::RlwePlaintextId>
  70. DeviceActiveUseCase::GetPsmIdentifier() {
  71. if (!psm_id_.has_value()) {
  72. psm_id_ = GeneratePsmIdentifier();
  73. }
  74. return psm_id_;
  75. }
  76. void DeviceActiveUseCase::SetPsmIdentifier(
  77. absl::optional<psm_rlwe::RlwePlaintextId> psm_id) {
  78. psm_id_ = psm_id;
  79. }
  80. psm_rlwe::PrivateMembershipRlweClient* DeviceActiveUseCase::GetPsmRlweClient() {
  81. return psm_rlwe_client_.get();
  82. }
  83. void DeviceActiveUseCase::SetPsmRlweClient(
  84. std::unique_ptr<psm_rlwe::PrivateMembershipRlweClient> psm_rlwe_client) {
  85. DCHECK(psm_rlwe_client);
  86. // Re-assigning the unique_ptr will reset the old unique_ptr.
  87. psm_rlwe_client_ = std::move(psm_rlwe_client);
  88. }
  89. bool DeviceActiveUseCase::IsDevicePingRequired(base::Time new_ping_ts) const {
  90. // Check the last recorded ping timestamp in local state prefs.
  91. // This variable has the default Unix Epoch value if the device is
  92. // new, powerwashed, recovered, or a RMA device.
  93. base::Time prev_ping_ts = GetLastKnownPingTimestamp();
  94. std::string prev_ping_window_id = GenerateUTCWindowIdentifier(prev_ping_ts);
  95. std::string new_ping_window_id = GenerateUTCWindowIdentifier(new_ping_ts);
  96. // Safety check to avoid against clock drift, or unexpected timestamps.
  97. // Check should make sure that we are not reporting window id's for
  98. // day's previous to one that we reported already.
  99. return prev_ping_ts < new_ping_ts &&
  100. prev_ping_window_id != new_ping_window_id;
  101. }
  102. std::string DeviceActiveUseCase::GetFullHardwareClass() const {
  103. // Retrieve full hardware class from machine statistics object.
  104. // Default |full_hardware_class| to kHardwareClassKeyNotFound if retrieval
  105. // from machine statistics fails.
  106. std::string full_hardware_class = kHardwareClassKeyNotFound;
  107. statistics_provider_->GetMachineStatistic(chromeos::system::kHardwareClassKey,
  108. &full_hardware_class);
  109. return full_hardware_class;
  110. }
  111. std::string DeviceActiveUseCase::GetChromeOSVersion() const {
  112. return version_info::GetMajorVersionNumber();
  113. }
  114. Channel DeviceActiveUseCase::GetChromeOSChannel() const {
  115. switch (chrome_passed_device_params_.chromeos_channel) {
  116. case version_info::Channel::CANARY:
  117. return Channel::CHANNEL_CANARY;
  118. case version_info::Channel::DEV:
  119. return Channel::CHANNEL_DEV;
  120. case version_info::Channel::BETA:
  121. return Channel::CHANNEL_BETA;
  122. case version_info::Channel::STABLE:
  123. return Channel::CHANNEL_STABLE;
  124. case version_info::Channel::UNKNOWN:
  125. default:
  126. return Channel::CHANNEL_UNKNOWN;
  127. }
  128. }
  129. MarketSegment DeviceActiveUseCase::GetMarketSegment() const {
  130. return chrome_passed_device_params_.market_segment;
  131. }
  132. absl::optional<psm_rlwe::RlwePlaintextId>
  133. DeviceActiveUseCase::GeneratePsmIdentifier() const {
  134. const std::string psm_use_case = psm_rlwe::RlweUseCase_Name(GetPsmUseCase());
  135. absl::optional<std::string> window_id = GetWindowIdentifier();
  136. if (psm_device_active_secret_.empty() || psm_use_case.empty() ||
  137. !window_id.has_value()) {
  138. VLOG(1) << "Can not generate PSM id without the psm device secret, use "
  139. "case, and window id being defined.";
  140. return absl::nullopt;
  141. }
  142. std::string unhashed_psm_id =
  143. base::JoinString({psm_use_case, window_id.value()}, "|");
  144. // Convert bytes to hex to avoid encoding/decoding proto issues across
  145. // client/server.
  146. std::string psm_id_hex =
  147. GetDigestString(psm_device_active_secret_, unhashed_psm_id);
  148. if (!psm_id_hex.empty()) {
  149. psm_rlwe::RlwePlaintextId psm_rlwe_id;
  150. psm_rlwe_id.set_sensitive_id(psm_id_hex);
  151. return psm_rlwe_id;
  152. }
  153. // Failed HMAC-SHA256 hash on PSM id.
  154. VLOG(1) << "Failed to calculate HMAC-256 has on PSM id.";
  155. return absl::nullopt;
  156. }
  157. } // namespace device_activity
  158. } // namespace ash