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

Side by Side Diff: chrome/browser/chromeos/attestation/platform_verification_flow.cc

Issue 50093002: Added a timeout for platform verification key generation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "platform_verification_flow.h" 5 #include "platform_verification_flow.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
9 #include "base/prefs/pref_service.h" 10 #include "base/prefs/pref_service.h"
11 #include "base/time/time.h"
10 #include "chrome/browser/chromeos/attestation/attestation_ca_client.h" 12 #include "chrome/browser/chromeos/attestation/attestation_ca_client.h"
11 #include "chrome/browser/chromeos/attestation/attestation_signed_data.pb.h" 13 #include "chrome/browser/chromeos/attestation/attestation_signed_data.pb.h"
12 #include "chrome/browser/chromeos/attestation/platform_verification_dialog.h" 14 #include "chrome/browser/chromeos/attestation/platform_verification_dialog.h"
13 #include "chrome/browser/chromeos/login/user.h" 15 #include "chrome/browser/chromeos/login/user.h"
14 #include "chrome/browser/chromeos/login/user_manager.h" 16 #include "chrome/browser/chromeos/login/user_manager.h"
15 #include "chrome/browser/chromeos/settings/cros_settings.h" 17 #include "chrome/browser/chromeos/settings/cros_settings.h"
16 #include "chrome/browser/prefs/scoped_user_pref_update.h" 18 #include "chrome/browser/prefs/scoped_user_pref_update.h"
17 #include "chrome/browser/profiles/profile.h" 19 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/common/pref_names.h" 20 #include "chrome/common/pref_names.h"
19 #include "chromeos/attestation/attestation_flow.h" 21 #include "chromeos/attestation/attestation_flow.h"
20 #include "chromeos/cryptohome/async_method_caller.h" 22 #include "chromeos/cryptohome/async_method_caller.h"
21 #include "chromeos/dbus/cryptohome_client.h" 23 #include "chromeos/dbus/cryptohome_client.h"
22 #include "chromeos/dbus/dbus_thread_manager.h" 24 #include "chromeos/dbus/dbus_thread_manager.h"
23 #include "components/user_prefs/pref_registry_syncable.h" 25 #include "components/user_prefs/pref_registry_syncable.h"
24 #include "components/user_prefs/user_prefs.h" 26 #include "components/user_prefs/user_prefs.h"
25 #include "content/public/browser/browser_context.h" 27 #include "content/public/browser/browser_context.h"
26 #include "content/public/browser/browser_thread.h" 28 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/user_metrics.h" 29 #include "content/public/browser/user_metrics.h"
28 #include "content/public/browser/web_contents.h" 30 #include "content/public/browser/web_contents.h"
29 31
30 namespace { 32 namespace {
31 33
34 const int kTimeoutInSeconds = 8;
35
32 // A callback method to handle DBus errors. 36 // A callback method to handle DBus errors.
33 void DBusCallback(const base::Callback<void(bool)>& on_success, 37 void DBusCallback(const base::Callback<void(bool)>& on_success,
34 const base::Closure& on_failure, 38 const base::Closure& on_failure,
35 chromeos::DBusMethodCallStatus call_status, 39 chromeos::DBusMethodCallStatus call_status,
36 bool result) { 40 bool result) {
37 if (call_status == chromeos::DBUS_METHOD_CALL_SUCCESS) { 41 if (call_status == chromeos::DBUS_METHOD_CALL_SUCCESS) {
38 on_success.Run(result); 42 on_success.Run(result);
39 } else { 43 } else {
40 LOG(ERROR) << "PlatformVerificationFlow: DBus call failed!"; 44 LOG(ERROR) << "PlatformVerificationFlow: DBus call failed!";
41 on_failure.Run(); 45 on_failure.Run();
(...skipping 30 matching lines...) Expand all
72 DISALLOW_COPY_AND_ASSIGN(DefaultDelegate); 76 DISALLOW_COPY_AND_ASSIGN(DefaultDelegate);
73 }; 77 };
74 78
75 PlatformVerificationFlow::PlatformVerificationFlow() 79 PlatformVerificationFlow::PlatformVerificationFlow()
76 : attestation_flow_(NULL), 80 : attestation_flow_(NULL),
77 async_caller_(cryptohome::AsyncMethodCaller::GetInstance()), 81 async_caller_(cryptohome::AsyncMethodCaller::GetInstance()),
78 cryptohome_client_(DBusThreadManager::Get()->GetCryptohomeClient()), 82 cryptohome_client_(DBusThreadManager::Get()->GetCryptohomeClient()),
79 user_manager_(UserManager::Get()), 83 user_manager_(UserManager::Get()),
80 delegate_(NULL), 84 delegate_(NULL),
81 testing_prefs_(NULL), 85 testing_prefs_(NULL),
82 weak_factory_(this) { 86 timeout_delay_(kTimeoutInSeconds) {
83 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 87 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
84 scoped_ptr<ServerProxy> attestation_ca_client(new AttestationCAClient()); 88 scoped_ptr<ServerProxy> attestation_ca_client(new AttestationCAClient());
85 default_attestation_flow_.reset(new AttestationFlow( 89 default_attestation_flow_.reset(new AttestationFlow(
86 async_caller_, 90 async_caller_,
87 cryptohome_client_, 91 cryptohome_client_,
88 attestation_ca_client.Pass())); 92 attestation_ca_client.Pass()));
89 attestation_flow_ = default_attestation_flow_.get(); 93 attestation_flow_ = default_attestation_flow_.get();
90 default_delegate_.reset(new DefaultDelegate()); 94 default_delegate_.reset(new DefaultDelegate());
91 delegate_ = default_delegate_.get(); 95 delegate_ = default_delegate_.get();
92 } 96 }
93 97
94 PlatformVerificationFlow::PlatformVerificationFlow( 98 PlatformVerificationFlow::PlatformVerificationFlow(
95 AttestationFlow* attestation_flow, 99 AttestationFlow* attestation_flow,
96 cryptohome::AsyncMethodCaller* async_caller, 100 cryptohome::AsyncMethodCaller* async_caller,
97 CryptohomeClient* cryptohome_client, 101 CryptohomeClient* cryptohome_client,
98 UserManager* user_manager, 102 UserManager* user_manager,
99 Delegate* delegate) 103 Delegate* delegate)
100 : attestation_flow_(attestation_flow), 104 : attestation_flow_(attestation_flow),
101 async_caller_(async_caller), 105 async_caller_(async_caller),
102 cryptohome_client_(cryptohome_client), 106 cryptohome_client_(cryptohome_client),
103 user_manager_(user_manager), 107 user_manager_(user_manager),
104 delegate_(delegate), 108 delegate_(delegate),
105 testing_prefs_(NULL), 109 testing_prefs_(NULL),
106 weak_factory_(this) { 110 timeout_delay_(kTimeoutInSeconds) {
107 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 111 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
108 } 112 }
109 113
110 PlatformVerificationFlow::~PlatformVerificationFlow() { 114 PlatformVerificationFlow::~PlatformVerificationFlow() {
111 } 115 }
112 116
113 void PlatformVerificationFlow::ChallengePlatformKey( 117 void PlatformVerificationFlow::ChallengePlatformKey(
114 content::WebContents* web_contents, 118 content::WebContents* web_contents,
115 const std::string& service_id, 119 const std::string& service_id,
116 const std::string& challenge, 120 const std::string& challenge,
117 const ChallengeCallback& callback) { 121 const ChallengeCallback& callback) {
118 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 122 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
119 if (!IsAttestationEnabled(web_contents)) { 123 if (!IsAttestationEnabled(web_contents)) {
120 LOG(INFO) << "PlatformVerificationFlow: Feature disabled."; 124 LOG(INFO) << "PlatformVerificationFlow: Feature disabled.";
121 ReportError(callback, POLICY_REJECTED); 125 ReportError(callback, POLICY_REJECTED);
122 return; 126 return;
123 } 127 }
128 ChallengeContext context = {web_contents, service_id, challenge, callback};
124 BoolDBusMethodCallback dbus_callback = base::Bind( 129 BoolDBusMethodCallback dbus_callback = base::Bind(
125 &DBusCallback, 130 &DBusCallback,
126 base::Bind(&PlatformVerificationFlow::CheckConsent, 131 base::Bind(&PlatformVerificationFlow::CheckConsent, this, context),
127 weak_factory_.GetWeakPtr(),
128 web_contents,
129 service_id,
130 challenge,
131 callback),
132 base::Bind(&ReportError, callback, INTERNAL_ERROR)); 132 base::Bind(&ReportError, callback, INTERNAL_ERROR));
133 cryptohome_client_->TpmAttestationIsEnrolled(dbus_callback); 133 cryptohome_client_->TpmAttestationIsEnrolled(dbus_callback);
134 } 134 }
135 135
136 void PlatformVerificationFlow::CheckConsent(content::WebContents* web_contents, 136 void PlatformVerificationFlow::CheckConsent(const ChallengeContext& context,
137 const std::string& service_id,
138 const std::string& challenge,
139 const ChallengeCallback& callback,
140 bool attestation_enrolled) { 137 bool attestation_enrolled) {
141 ConsentType consent_type = CONSENT_TYPE_NONE; 138 ConsentType consent_type = CONSENT_TYPE_NONE;
142 if (!attestation_enrolled || IsFirstUse(web_contents)) { 139 if (!attestation_enrolled || IsFirstUse(context.web_contents)) {
143 consent_type = CONSENT_TYPE_ATTESTATION; 140 consent_type = CONSENT_TYPE_ATTESTATION;
144 } else if (IsAlwaysAskRequired(web_contents)) { 141 } else if (IsAlwaysAskRequired(context.web_contents)) {
145 consent_type = CONSENT_TYPE_ALWAYS; 142 consent_type = CONSENT_TYPE_ALWAYS;
146 } 143 }
147 Delegate::ConsentCallback consent_callback = base::Bind( 144 Delegate::ConsentCallback consent_callback = base::Bind(
148 &PlatformVerificationFlow::OnConsentResponse, 145 &PlatformVerificationFlow::OnConsentResponse,
149 weak_factory_.GetWeakPtr(), 146 this,
150 web_contents, 147 context,
151 service_id,
152 challenge,
153 callback,
154 consent_type); 148 consent_type);
155 if (consent_type == CONSENT_TYPE_NONE) { 149 if (consent_type == CONSENT_TYPE_NONE) {
156 consent_callback.Run(CONSENT_RESPONSE_NONE); 150 consent_callback.Run(CONSENT_RESPONSE_NONE);
157 } else { 151 } else {
158 delegate_->ShowConsentPrompt(consent_type, 152 delegate_->ShowConsentPrompt(consent_type,
159 web_contents, 153 context.web_contents,
160 consent_callback); 154 consent_callback);
161 } 155 }
162 } 156 }
163 157
164 void PlatformVerificationFlow::RegisterProfilePrefs( 158 void PlatformVerificationFlow::RegisterProfilePrefs(
165 user_prefs::PrefRegistrySyncable* prefs) { 159 user_prefs::PrefRegistrySyncable* prefs) {
166 prefs->RegisterBooleanPref(prefs::kRAConsentFirstTime, 160 prefs->RegisterBooleanPref(prefs::kRAConsentFirstTime,
167 false, 161 false,
168 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 162 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
169 prefs->RegisterDictionaryPref( 163 prefs->RegisterDictionaryPref(
170 prefs::kRAConsentDomains, 164 prefs::kRAConsentDomains,
171 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 165 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
172 prefs->RegisterBooleanPref(prefs::kRAConsentAlways, 166 prefs->RegisterBooleanPref(prefs::kRAConsentAlways,
173 false, 167 false,
174 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 168 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
175 } 169 }
176 170
177 void PlatformVerificationFlow::OnConsentResponse( 171 void PlatformVerificationFlow::OnConsentResponse(
178 content::WebContents* web_contents, 172 const ChallengeContext& context,
179 const std::string& service_id,
180 const std::string& challenge,
181 const ChallengeCallback& callback,
182 ConsentType consent_type, 173 ConsentType consent_type,
183 ConsentResponse consent_response) { 174 ConsentResponse consent_response) {
184 if (consent_type != CONSENT_TYPE_NONE) { 175 if (consent_type != CONSENT_TYPE_NONE) {
185 if (consent_response == CONSENT_RESPONSE_NONE) { 176 if (consent_response == CONSENT_RESPONSE_NONE) {
186 // No user response - do not proceed and do not modify any settings. 177 // No user response - do not proceed and do not modify any settings.
187 LOG(WARNING) << "PlatformVerificationFlow: No response from user."; 178 LOG(WARNING) << "PlatformVerificationFlow: No response from user.";
188 ReportError(callback, USER_REJECTED); 179 ReportError(context.callback, USER_REJECTED);
189 return; 180 return;
190 } 181 }
191 if (!UpdateSettings(web_contents, consent_type, consent_response)) { 182 if (!UpdateSettings(context.web_contents, consent_type, consent_response)) {
192 ReportError(callback, INTERNAL_ERROR); 183 ReportError(context.callback, INTERNAL_ERROR);
193 return; 184 return;
194 } 185 }
195 if (consent_response == CONSENT_RESPONSE_DENY) { 186 if (consent_response == CONSENT_RESPONSE_DENY) {
196 LOG(INFO) << "PlatformVerificationFlow: User rejected request."; 187 LOG(INFO) << "PlatformVerificationFlow: User rejected request.";
197 content::RecordAction( 188 content::RecordAction(
198 content::UserMetricsAction("PlatformVerificationRejected")); 189 content::UserMetricsAction("PlatformVerificationRejected"));
199 ReportError(callback, USER_REJECTED); 190 ReportError(context.callback, USER_REJECTED);
200 return; 191 return;
201 } else if (consent_response == CONSENT_RESPONSE_ALLOW) { 192 } else if (consent_response == CONSENT_RESPONSE_ALLOW) {
202 content::RecordAction( 193 content::RecordAction(
203 content::UserMetricsAction("PlatformVerificationAccepted")); 194 content::UserMetricsAction("PlatformVerificationAccepted"));
204 } 195 }
205 } 196 }
206 197
207 // At this point all user interaction is complete and we can proceed with the 198 // At this point all user interaction is complete and we can proceed with the
208 // certificate request. 199 // certificate request.
209 chromeos::User* user = GetUser(web_contents); 200 chromeos::User* user = GetUser(context.web_contents);
210 if (!user) { 201 if (!user) {
211 ReportError(callback, INTERNAL_ERROR); 202 ReportError(context.callback, INTERNAL_ERROR);
212 LOG(ERROR) << "Profile does not map to a valid user."; 203 LOG(ERROR) << "Profile does not map to a valid user.";
213 return; 204 return;
214 } 205 }
206 scoped_refptr<TimeoutStatus> timeout_status(new TimeoutStatus);
DaleCurtis 2013/10/30 20:11:52 TimeoutStatus()
207 base::MessageLoop::current()->PostDelayedTask(
208 FROM_HERE,
209 base::Bind(&PlatformVerificationFlow::OnCertificateTimeout, this,
210 context, timeout_status),
211 base::TimeDelta::FromSeconds(timeout_delay_));
215 AttestationFlow::CertificateCallback certificate_callback = base::Bind( 212 AttestationFlow::CertificateCallback certificate_callback = base::Bind(
216 &PlatformVerificationFlow::OnCertificateReady, 213 &PlatformVerificationFlow::OnCertificateReady,
217 weak_factory_.GetWeakPtr(), 214 this,
215 context,
218 user->email(), 216 user->email(),
219 service_id, 217 timeout_status);
220 challenge,
221 callback);
222 attestation_flow_->GetCertificate( 218 attestation_flow_->GetCertificate(
223 PROFILE_CONTENT_PROTECTION_CERTIFICATE, 219 PROFILE_CONTENT_PROTECTION_CERTIFICATE,
224 user->email(), 220 user->email(),
225 service_id, 221 context.service_id,
226 false, // Don't force a new key. 222 false, // Don't force a new key.
227 certificate_callback); 223 certificate_callback);
228 } 224 }
229 225
230 void PlatformVerificationFlow::OnCertificateReady( 226 void PlatformVerificationFlow::OnCertificateReady(
227 const ChallengeContext& context,
231 const std::string& user_id, 228 const std::string& user_id,
232 const std::string& service_id, 229 TimeoutStatus* timeout_status,
DaleCurtis 2013/10/30 20:11:52 Usage of raw pointers with scoped_refptr seems que
Darren Krahn 2013/10/30 22:24:53 Now using scoped_ptr but this can be done with sco
233 const std::string& challenge,
234 const ChallengeCallback& callback,
235 bool operation_success, 230 bool operation_success,
236 const std::string& certificate) { 231 const std::string& certificate) {
237 if (!operation_success) { 232 if (!operation_success) {
238 LOG(WARNING) << "PlatformVerificationFlow: Failed to certify platform."; 233 LOG(WARNING) << "PlatformVerificationFlow: Failed to certify platform.";
239 ReportError(callback, PLATFORM_NOT_VERIFIED); 234 }
235 if (timeout_status->timed_out) {
236 LOG(WARNING) << "PlatformVerificationFlow: Certificate ready but call has "
237 << "already timed out.";
238 return;
239 }
240 timeout_status->finished = true;
241 if (!operation_success) {
242 ReportError(context.callback, PLATFORM_NOT_VERIFIED);
240 return; 243 return;
241 } 244 }
242 cryptohome::AsyncMethodCaller::DataCallback cryptohome_callback = base::Bind( 245 cryptohome::AsyncMethodCaller::DataCallback cryptohome_callback = base::Bind(
243 &PlatformVerificationFlow::OnChallengeReady, 246 &PlatformVerificationFlow::OnChallengeReady,
244 weak_factory_.GetWeakPtr(), 247 this,
245 certificate, 248 context,
246 challenge, 249 certificate);
247 callback);
248 std::string key_name = kContentProtectionKeyPrefix; 250 std::string key_name = kContentProtectionKeyPrefix;
249 key_name += service_id; 251 key_name += context.service_id;
250 async_caller_->TpmAttestationSignSimpleChallenge(KEY_USER, 252 async_caller_->TpmAttestationSignSimpleChallenge(KEY_USER,
251 user_id, 253 user_id,
252 key_name, 254 key_name,
253 challenge, 255 context.challenge,
254 cryptohome_callback); 256 cryptohome_callback);
255 } 257 }
256 258
259 void PlatformVerificationFlow::OnCertificateTimeout(
260 const ChallengeContext& context,
261 TimeoutStatus* timeout_status) {
262 if (!timeout_status->finished) {
263 LOG(WARNING) << "PlatformVerificationFlow: Timing out.";
264 timeout_status->timed_out = true;
265 ReportError(context.callback, TIMEOUT);
266 }
267 }
268
257 void PlatformVerificationFlow::OnChallengeReady( 269 void PlatformVerificationFlow::OnChallengeReady(
270 const ChallengeContext& context,
258 const std::string& certificate, 271 const std::string& certificate,
259 const std::string& challenge,
260 const ChallengeCallback& callback,
261 bool operation_success, 272 bool operation_success,
262 const std::string& response_data) { 273 const std::string& response_data) {
263 if (!operation_success) { 274 if (!operation_success) {
264 LOG(ERROR) << "PlatformVerificationFlow: Failed to sign challenge."; 275 LOG(ERROR) << "PlatformVerificationFlow: Failed to sign challenge.";
265 ReportError(callback, INTERNAL_ERROR); 276 ReportError(context.callback, INTERNAL_ERROR);
266 return; 277 return;
267 } 278 }
268 SignedData signed_data_pb; 279 SignedData signed_data_pb;
269 if (response_data.empty() || !signed_data_pb.ParseFromString(response_data)) { 280 if (response_data.empty() || !signed_data_pb.ParseFromString(response_data)) {
270 LOG(ERROR) << "PlatformVerificationFlow: Failed to parse response data."; 281 LOG(ERROR) << "PlatformVerificationFlow: Failed to parse response data.";
271 ReportError(callback, INTERNAL_ERROR); 282 ReportError(context.callback, INTERNAL_ERROR);
272 return; 283 return;
273 } 284 }
274 callback.Run(SUCCESS, 285 context.callback.Run(SUCCESS,
275 signed_data_pb.data(), 286 signed_data_pb.data(),
276 signed_data_pb.signature(), 287 signed_data_pb.signature(),
277 certificate); 288 certificate);
278 LOG(INFO) << "PlatformVerificationFlow: Platform successfully verified."; 289 LOG(INFO) << "PlatformVerificationFlow: Platform successfully verified.";
279 } 290 }
280 291
281 PrefService* PlatformVerificationFlow::GetPrefs( 292 PrefService* PlatformVerificationFlow::GetPrefs(
282 content::WebContents* web_contents) { 293 content::WebContents* web_contents) {
283 if (testing_prefs_) 294 if (testing_prefs_)
284 return testing_prefs_; 295 return testing_prefs_;
285 return user_prefs::UserPrefs::Get(web_contents->GetBrowserContext()); 296 return user_prefs::UserPrefs::Get(web_contents->GetBrowserContext());
286 } 297 }
287 298
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 bool allow_domain) { 416 bool allow_domain) {
406 PrefService* pref_service = GetPrefs(web_contents); 417 PrefService* pref_service = GetPrefs(web_contents);
407 CHECK(pref_service); 418 CHECK(pref_service);
408 DictionaryPrefUpdate updater(pref_service, prefs::kRAConsentDomains); 419 DictionaryPrefUpdate updater(pref_service, prefs::kRAConsentDomains);
409 const GURL& url = GetURL(web_contents); 420 const GURL& url = GetURL(web_contents);
410 updater->SetBoolean(url.host(), allow_domain); 421 updater->SetBoolean(url.host(), allow_domain);
411 } 422 }
412 423
413 } // namespace attestation 424 } // namespace attestation
414 } // namespace chromeos 425 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698