Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1274)

Side by Side Diff: components/proximity_auth/cryptauth/cryptauth_enrollment_manager.cc

Issue 2502343003: Moved //components/proximity_auth/cryptauth to //components/cryptauth. (Closed)
Patch Set: Fixed proto #includes. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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
5 #include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h"
6
7 #include <utility>
8
9 #include "base/base64url.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/time/clock.h"
12 #include "base/time/time.h"
13 #include "components/prefs/pref_registry_simple.h"
14 #include "components/prefs/pref_service.h"
15 #include "components/proximity_auth/cryptauth/cryptauth_enroller.h"
16 #include "components/proximity_auth/cryptauth/pref_names.h"
17 #include "components/proximity_auth/cryptauth/secure_message_delegate.h"
18 #include "components/proximity_auth/cryptauth/sync_scheduler_impl.h"
19 #include "components/proximity_auth/logging/logging.h"
20
21 namespace proximity_auth {
22
23 namespace {
24
25 // The number of days that an enrollment is valid. Note that we try to refresh
26 // the enrollment well before this time elapses.
27 const int kValidEnrollmentPeriodDays = 45;
28
29 // The normal period between successful enrollments in days.
30 const int kEnrollmentRefreshPeriodDays = 30;
31
32 // A more aggressive period between enrollments to recover when the last
33 // enrollment fails, in minutes. This is a base time that increases for each
34 // subsequent failure.
35 const int kEnrollmentBaseRecoveryPeriodMinutes = 10;
36
37 // The bound on the amount to jitter the period between enrollments.
38 const double kEnrollmentMaxJitterRatio = 0.2;
39
40 // The value of the device_software_package field in the device info uploaded
41 // during enrollment. This value must be the same as the app id used for GCM
42 // registration.
43 const char kDeviceSoftwarePackage[] = "com.google.chrome.cryptauth";
44
45 } // namespace
46
47 CryptAuthEnrollmentManager::CryptAuthEnrollmentManager(
48 std::unique_ptr<base::Clock> clock,
49 std::unique_ptr<CryptAuthEnrollerFactory> enroller_factory,
50 std::unique_ptr<SecureMessageDelegate> secure_message_delegate,
51 const cryptauth::GcmDeviceInfo& device_info,
52 CryptAuthGCMManager* gcm_manager,
53 PrefService* pref_service)
54 : clock_(std::move(clock)),
55 enroller_factory_(std::move(enroller_factory)),
56 secure_message_delegate_(std::move(secure_message_delegate)),
57 device_info_(device_info),
58 gcm_manager_(gcm_manager),
59 pref_service_(pref_service),
60 weak_ptr_factory_(this) {}
61
62 CryptAuthEnrollmentManager::~CryptAuthEnrollmentManager() {
63 gcm_manager_->RemoveObserver(this);
64 }
65
66 // static
67 void CryptAuthEnrollmentManager::RegisterPrefs(PrefRegistrySimple* registry) {
68 registry->RegisterBooleanPref(
69 prefs::kCryptAuthEnrollmentIsRecoveringFromFailure, false);
70 registry->RegisterDoublePref(
71 prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds, 0.0);
72 registry->RegisterIntegerPref(prefs::kCryptAuthEnrollmentReason,
73 cryptauth::INVOCATION_REASON_UNKNOWN);
74 registry->RegisterStringPref(prefs::kCryptAuthEnrollmentUserPublicKey,
75 std::string());
76 registry->RegisterStringPref(prefs::kCryptAuthEnrollmentUserPrivateKey,
77 std::string());
78 }
79
80 void CryptAuthEnrollmentManager::Start() {
81 gcm_manager_->AddObserver(this);
82
83 bool is_recovering_from_failure =
84 pref_service_->GetBoolean(
85 prefs::kCryptAuthEnrollmentIsRecoveringFromFailure) ||
86 !IsEnrollmentValid();
87
88 base::Time last_successful_enrollment = GetLastEnrollmentTime();
89 base::TimeDelta elapsed_time_since_last_sync =
90 clock_->Now() - last_successful_enrollment;
91
92 scheduler_ = CreateSyncScheduler();
93 scheduler_->Start(elapsed_time_since_last_sync,
94 is_recovering_from_failure
95 ? SyncScheduler::Strategy::AGGRESSIVE_RECOVERY
96 : SyncScheduler::Strategy::PERIODIC_REFRESH);
97 }
98
99 void CryptAuthEnrollmentManager::AddObserver(Observer* observer) {
100 observers_.AddObserver(observer);
101 }
102
103 void CryptAuthEnrollmentManager::RemoveObserver(Observer* observer) {
104 observers_.RemoveObserver(observer);
105 }
106
107 void CryptAuthEnrollmentManager::ForceEnrollmentNow(
108 cryptauth::InvocationReason invocation_reason) {
109 // We store the invocation reason in a preference so that it can persist
110 // across browser restarts. If the sync fails, the next retry should still use
111 // this original reason instead of INVOCATION_REASON_FAILURE_RECOVERY.
112 pref_service_->SetInteger(prefs::kCryptAuthEnrollmentReason,
113 invocation_reason);
114 scheduler_->ForceSync();
115 }
116
117 bool CryptAuthEnrollmentManager::IsEnrollmentValid() const {
118 base::Time last_enrollment_time = GetLastEnrollmentTime();
119 return !last_enrollment_time.is_null() &&
120 (clock_->Now() - last_enrollment_time) <
121 base::TimeDelta::FromDays(kValidEnrollmentPeriodDays);
122 }
123
124 base::Time CryptAuthEnrollmentManager::GetLastEnrollmentTime() const {
125 return base::Time::FromDoubleT(pref_service_->GetDouble(
126 prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds));
127 }
128
129 base::TimeDelta CryptAuthEnrollmentManager::GetTimeToNextAttempt() const {
130 return scheduler_->GetTimeToNextSync();
131 }
132
133 bool CryptAuthEnrollmentManager::IsEnrollmentInProgress() const {
134 return scheduler_->GetSyncState() ==
135 SyncScheduler::SyncState::SYNC_IN_PROGRESS;
136 }
137
138 bool CryptAuthEnrollmentManager::IsRecoveringFromFailure() const {
139 return scheduler_->GetStrategy() ==
140 SyncScheduler::Strategy::AGGRESSIVE_RECOVERY;
141 }
142
143 void CryptAuthEnrollmentManager::OnEnrollmentFinished(bool success) {
144 if (success) {
145 pref_service_->SetDouble(
146 prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds,
147 clock_->Now().ToDoubleT());
148 pref_service_->SetInteger(prefs::kCryptAuthEnrollmentReason,
149 cryptauth::INVOCATION_REASON_UNKNOWN);
150 }
151
152 pref_service_->SetBoolean(prefs::kCryptAuthEnrollmentIsRecoveringFromFailure,
153 !success);
154
155 sync_request_->OnDidComplete(success);
156 cryptauth_enroller_.reset();
157 sync_request_.reset();
158 for (auto& observer : observers_)
159 observer.OnEnrollmentFinished(success);
160 }
161
162 std::unique_ptr<SyncScheduler>
163 CryptAuthEnrollmentManager::CreateSyncScheduler() {
164 return base::MakeUnique<SyncSchedulerImpl>(
165 this, base::TimeDelta::FromDays(kEnrollmentRefreshPeriodDays),
166 base::TimeDelta::FromMinutes(kEnrollmentBaseRecoveryPeriodMinutes),
167 kEnrollmentMaxJitterRatio, "CryptAuth Enrollment");
168 }
169
170 std::string CryptAuthEnrollmentManager::GetUserPublicKey() {
171 std::string public_key;
172 if (!base::Base64UrlDecode(
173 pref_service_->GetString(prefs::kCryptAuthEnrollmentUserPublicKey),
174 base::Base64UrlDecodePolicy::REQUIRE_PADDING, &public_key)) {
175 PA_LOG(ERROR) << "Invalid public key stored in user prefs.";
176 return std::string();
177 }
178 return public_key;
179 }
180
181 std::string CryptAuthEnrollmentManager::GetUserPrivateKey() {
182 std::string private_key;
183 if (!base::Base64UrlDecode(
184 pref_service_->GetString(prefs::kCryptAuthEnrollmentUserPrivateKey),
185 base::Base64UrlDecodePolicy::REQUIRE_PADDING, &private_key)) {
186 PA_LOG(ERROR) << "Invalid private key stored in user prefs.";
187 return std::string();
188 }
189 return private_key;
190 }
191
192 void CryptAuthEnrollmentManager::OnGCMRegistrationResult(bool success) {
193 if (!sync_request_)
194 return;
195
196 PA_LOG(INFO) << "GCM registration for CryptAuth Enrollment completed: "
197 << success;
198 if (success)
199 DoCryptAuthEnrollment();
200 else
201 OnEnrollmentFinished(false);
202 }
203
204 void CryptAuthEnrollmentManager::OnKeyPairGenerated(
205 const std::string& public_key,
206 const std::string& private_key) {
207 if (!public_key.empty() && !private_key.empty()) {
208 PA_LOG(INFO) << "Key pair generated for CryptAuth enrollment";
209 // Store the keypair in Base64 format because pref values require readable
210 // string values.
211 std::string public_key_b64, private_key_b64;
212 base::Base64UrlEncode(public_key,
213 base::Base64UrlEncodePolicy::INCLUDE_PADDING,
214 &public_key_b64);
215 base::Base64UrlEncode(private_key,
216 base::Base64UrlEncodePolicy::INCLUDE_PADDING,
217 &private_key_b64);
218 pref_service_->SetString(prefs::kCryptAuthEnrollmentUserPublicKey,
219 public_key_b64);
220 pref_service_->SetString(prefs::kCryptAuthEnrollmentUserPrivateKey,
221 private_key_b64);
222 DoCryptAuthEnrollment();
223 } else {
224 OnEnrollmentFinished(false);
225 }
226 }
227
228 void CryptAuthEnrollmentManager::OnReenrollMessage() {
229 ForceEnrollmentNow(cryptauth::INVOCATION_REASON_SERVER_INITIATED);
230 }
231
232 void CryptAuthEnrollmentManager::OnSyncRequested(
233 std::unique_ptr<SyncScheduler::SyncRequest> sync_request) {
234 for (auto& observer : observers_)
235 observer.OnEnrollmentStarted();
236
237 sync_request_ = std::move(sync_request);
238 if (gcm_manager_->GetRegistrationId().empty() ||
239 pref_service_->GetInteger(prefs::kCryptAuthEnrollmentReason) ==
240 cryptauth::INVOCATION_REASON_MANUAL) {
241 gcm_manager_->RegisterWithGCM();
242 } else {
243 DoCryptAuthEnrollment();
244 }
245 }
246
247 void CryptAuthEnrollmentManager::DoCryptAuthEnrollment() {
248 if (GetUserPublicKey().empty() || GetUserPrivateKey().empty()) {
249 secure_message_delegate_->GenerateKeyPair(
250 base::Bind(&CryptAuthEnrollmentManager::OnKeyPairGenerated,
251 weak_ptr_factory_.GetWeakPtr()));
252 } else {
253 DoCryptAuthEnrollmentWithKeys();
254 }
255 }
256
257 void CryptAuthEnrollmentManager::DoCryptAuthEnrollmentWithKeys() {
258 DCHECK(sync_request_);
259 cryptauth::InvocationReason invocation_reason =
260 cryptauth::INVOCATION_REASON_UNKNOWN;
261
262 int reason_stored_in_prefs =
263 pref_service_->GetInteger(prefs::kCryptAuthEnrollmentReason);
264
265 if (cryptauth::InvocationReason_IsValid(reason_stored_in_prefs) &&
266 reason_stored_in_prefs != cryptauth::INVOCATION_REASON_UNKNOWN) {
267 invocation_reason =
268 static_cast<cryptauth::InvocationReason>(reason_stored_in_prefs);
269 } else if (GetLastEnrollmentTime().is_null()) {
270 invocation_reason = cryptauth::INVOCATION_REASON_INITIALIZATION;
271 } else if (!IsEnrollmentValid()) {
272 invocation_reason = cryptauth::INVOCATION_REASON_EXPIRATION;
273 } else if (scheduler_->GetStrategy() ==
274 SyncScheduler::Strategy::PERIODIC_REFRESH) {
275 invocation_reason = cryptauth::INVOCATION_REASON_PERIODIC;
276 } else if (scheduler_->GetStrategy() ==
277 SyncScheduler::Strategy::AGGRESSIVE_RECOVERY) {
278 invocation_reason = cryptauth::INVOCATION_REASON_FAILURE_RECOVERY;
279 }
280
281 // Fill in the current GCM registration id before enrolling, and explicitly
282 // make sure that the software package is the same as the GCM app id.
283 cryptauth::GcmDeviceInfo device_info(device_info_);
284 device_info.set_gcm_registration_id(gcm_manager_->GetRegistrationId());
285 device_info.set_device_software_package(kDeviceSoftwarePackage);
286
287 std::string public_key_b64;
288 base::Base64UrlEncode(GetUserPublicKey(),
289 base::Base64UrlEncodePolicy::INCLUDE_PADDING,
290 &public_key_b64);
291 PA_LOG(INFO) << "Making enrollment:\n"
292 << " public_key: " << public_key_b64 << "\n"
293 << " invocation_reason: " << invocation_reason << "\n"
294 << " gcm_registration_id: "
295 << device_info.gcm_registration_id();
296
297 cryptauth_enroller_ = enroller_factory_->CreateInstance();
298 cryptauth_enroller_->Enroll(
299 GetUserPublicKey(), GetUserPrivateKey(), device_info, invocation_reason,
300 base::Bind(&CryptAuthEnrollmentManager::OnEnrollmentFinished,
301 weak_ptr_factory_.GetWeakPtr()));
302 }
303
304 } // namespace proximity_auth
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698