OLD | NEW |
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 "chrome/browser/chromeos/attestation/platform_verification_flow.h" | 5 #include "chrome/browser/chromeos/attestation/platform_verification_flow.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/macros.h" | 11 #include "base/macros.h" |
12 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
14 #include "base/time/time.h" | 14 #include "base/time/time.h" |
15 #include "base/timer/timer.h" | 15 #include "base/timer/timer.h" |
16 #include "chrome/browser/chromeos/attestation/attestation_ca_client.h" | 16 #include "chrome/browser/chromeos/attestation/attestation_ca_client.h" |
17 #include "chrome/browser/chromeos/attestation/attestation_signed_data.pb.h" | 17 #include "chrome/browser/chromeos/attestation/attestation_signed_data.pb.h" |
18 #include "chrome/browser/chromeos/profiles/profile_helper.h" | 18 #include "chrome/browser/chromeos/profiles/profile_helper.h" |
19 #include "chrome/browser/chromeos/settings/cros_settings.h" | 19 #include "chrome/browser/chromeos/settings/cros_settings.h" |
20 #include "chrome/browser/media/protected_media_identifier_permission_context.h" | 20 #include "chrome/browser/media/protected_media_identifier_permission_context.h" |
21 #include "chrome/browser/media/protected_media_identifier_permission_context_fac
tory.h" | 21 #include "chrome/browser/media/protected_media_identifier_permission_context_fac
tory.h" |
22 #include "chrome/browser/profiles/profile.h" | 22 #include "chrome/browser/profiles/profile.h" |
23 #include "chromeos/attestation/attestation_flow.h" | 23 #include "chromeos/attestation/attestation_flow.h" |
24 #include "chromeos/chromeos_switches.h" | 24 #include "chromeos/chromeos_switches.h" |
25 #include "chromeos/cryptohome/async_method_caller.h" | 25 #include "chromeos/cryptohome/async_method_caller.h" |
| 26 #include "chromeos/cryptohome/cryptohome_parameters.h" |
26 #include "chromeos/dbus/cryptohome_client.h" | 27 #include "chromeos/dbus/cryptohome_client.h" |
27 #include "chromeos/dbus/dbus_thread_manager.h" | 28 #include "chromeos/dbus/dbus_thread_manager.h" |
28 #include "components/content_settings/core/browser/host_content_settings_map.h" | 29 #include "components/content_settings/core/browser/host_content_settings_map.h" |
29 #include "components/content_settings/core/common/content_settings_pattern.h" | 30 #include "components/content_settings/core/common/content_settings_pattern.h" |
30 #include "components/user_manager/user.h" | 31 #include "components/user_manager/user.h" |
31 #include "content/public/browser/browser_context.h" | 32 #include "content/public/browser/browser_context.h" |
32 #include "content/public/browser/browser_thread.h" | 33 #include "content/public/browser/browser_thread.h" |
33 #include "content/public/browser/render_process_host.h" | 34 #include "content/public/browser/render_process_host.h" |
34 #include "content/public/browser/render_view_host.h" | 35 #include "content/public/browser/render_view_host.h" |
35 #include "content/public/browser/user_metrics.h" | 36 #include "content/public/browser/user_metrics.h" |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 } | 243 } |
243 | 244 |
244 // Permission allowed. Now proceed to get certificate. | 245 // Permission allowed. Now proceed to get certificate. |
245 const user_manager::User* user = delegate_->GetUser(context.web_contents); | 246 const user_manager::User* user = delegate_->GetUser(context.web_contents); |
246 if (!user) { | 247 if (!user) { |
247 ReportError(context.callback, INTERNAL_ERROR); | 248 ReportError(context.callback, INTERNAL_ERROR); |
248 LOG(ERROR) << "Profile does not map to a valid user."; | 249 LOG(ERROR) << "Profile does not map to a valid user."; |
249 return; | 250 return; |
250 } | 251 } |
251 | 252 |
252 GetCertificate(context, user->email(), false /* Don't force a new key */); | 253 GetCertificate(context, user->GetAccountId(), |
| 254 false /* Don't force a new key */); |
253 } | 255 } |
254 | 256 |
255 void PlatformVerificationFlow::GetCertificate(const ChallengeContext& context, | 257 void PlatformVerificationFlow::GetCertificate(const ChallengeContext& context, |
256 const std::string& user_id, | 258 const AccountId& account_id, |
257 bool force_new_key) { | 259 bool force_new_key) { |
258 scoped_ptr<base::Timer> timer(new base::Timer(false, // Don't retain. | 260 scoped_ptr<base::Timer> timer(new base::Timer(false, // Don't retain. |
259 false)); // Don't repeat. | 261 false)); // Don't repeat. |
260 base::Closure timeout_callback = base::Bind( | 262 base::Closure timeout_callback = base::Bind( |
261 &PlatformVerificationFlow::OnCertificateTimeout, | 263 &PlatformVerificationFlow::OnCertificateTimeout, |
262 this, | 264 this, |
263 context); | 265 context); |
264 timer->Start(FROM_HERE, timeout_delay_, timeout_callback); | 266 timer->Start(FROM_HERE, timeout_delay_, timeout_callback); |
265 | 267 |
266 AttestationFlow::CertificateCallback certificate_callback = base::Bind( | 268 AttestationFlow::CertificateCallback certificate_callback = |
267 &PlatformVerificationFlow::OnCertificateReady, | 269 base::Bind(&PlatformVerificationFlow::OnCertificateReady, this, context, |
268 this, | 270 account_id, base::Passed(&timer)); |
269 context, | 271 attestation_flow_->GetCertificate(PROFILE_CONTENT_PROTECTION_CERTIFICATE, |
270 user_id, | 272 account_id, context.service_id, |
271 base::Passed(&timer)); | 273 force_new_key, certificate_callback); |
272 attestation_flow_->GetCertificate( | |
273 PROFILE_CONTENT_PROTECTION_CERTIFICATE, | |
274 user_id, | |
275 context.service_id, | |
276 force_new_key, | |
277 certificate_callback); | |
278 } | 274 } |
279 | 275 |
280 void PlatformVerificationFlow::OnCertificateReady( | 276 void PlatformVerificationFlow::OnCertificateReady( |
281 const ChallengeContext& context, | 277 const ChallengeContext& context, |
282 const std::string& user_id, | 278 const AccountId& account_id, |
283 scoped_ptr<base::Timer> timer, | 279 scoped_ptr<base::Timer> timer, |
284 bool operation_success, | 280 bool operation_success, |
285 const std::string& certificate_chain) { | 281 const std::string& certificate_chain) { |
286 // Log failure before checking the timer so all failures are logged, even if | 282 // Log failure before checking the timer so all failures are logged, even if |
287 // they took too long. | 283 // they took too long. |
288 if (!operation_success) { | 284 if (!operation_success) { |
289 LOG(WARNING) << "PlatformVerificationFlow: Failed to certify platform."; | 285 LOG(WARNING) << "PlatformVerificationFlow: Failed to certify platform."; |
290 } | 286 } |
291 if (!timer->IsRunning()) { | 287 if (!timer->IsRunning()) { |
292 LOG(WARNING) << "PlatformVerificationFlow: Certificate ready but call has " | 288 LOG(WARNING) << "PlatformVerificationFlow: Certificate ready but call has " |
293 << "already timed out."; | 289 << "already timed out."; |
294 return; | 290 return; |
295 } | 291 } |
296 timer->Stop(); | 292 timer->Stop(); |
297 if (!operation_success) { | 293 if (!operation_success) { |
298 ReportError(context.callback, PLATFORM_NOT_VERIFIED); | 294 ReportError(context.callback, PLATFORM_NOT_VERIFIED); |
299 return; | 295 return; |
300 } | 296 } |
301 ExpiryStatus expiry_status = CheckExpiry(certificate_chain); | 297 ExpiryStatus expiry_status = CheckExpiry(certificate_chain); |
302 ReportExpiryStatus(expiry_status); | 298 ReportExpiryStatus(expiry_status); |
303 if (expiry_status == EXPIRY_STATUS_EXPIRED) { | 299 if (expiry_status == EXPIRY_STATUS_EXPIRED) { |
304 GetCertificate(context, user_id, true /* Force a new key */); | 300 GetCertificate(context, account_id, true /* Force a new key */); |
305 return; | 301 return; |
306 } | 302 } |
307 bool is_expiring_soon = (expiry_status == EXPIRY_STATUS_EXPIRING_SOON); | 303 bool is_expiring_soon = (expiry_status == EXPIRY_STATUS_EXPIRING_SOON); |
308 cryptohome::AsyncMethodCaller::DataCallback cryptohome_callback = | 304 cryptohome::AsyncMethodCaller::DataCallback cryptohome_callback = |
309 base::Bind(&PlatformVerificationFlow::OnChallengeReady, this, context, | 305 base::Bind(&PlatformVerificationFlow::OnChallengeReady, this, context, |
310 user_id, certificate_chain, is_expiring_soon); | 306 account_id, certificate_chain, is_expiring_soon); |
311 std::string key_name = kContentProtectionKeyPrefix; | 307 std::string key_name = kContentProtectionKeyPrefix; |
312 key_name += context.service_id; | 308 key_name += context.service_id; |
313 async_caller_->TpmAttestationSignSimpleChallenge(KEY_USER, | 309 async_caller_->TpmAttestationSignSimpleChallenge( |
314 user_id, | 310 KEY_USER, cryptohome::Identification(account_id), key_name, |
315 key_name, | 311 context.challenge, cryptohome_callback); |
316 context.challenge, | |
317 cryptohome_callback); | |
318 } | 312 } |
319 | 313 |
320 void PlatformVerificationFlow::OnCertificateTimeout( | 314 void PlatformVerificationFlow::OnCertificateTimeout( |
321 const ChallengeContext& context) { | 315 const ChallengeContext& context) { |
322 LOG(WARNING) << "PlatformVerificationFlow: Timing out."; | 316 LOG(WARNING) << "PlatformVerificationFlow: Timing out."; |
323 ReportError(context.callback, TIMEOUT); | 317 ReportError(context.callback, TIMEOUT); |
324 } | 318 } |
325 | 319 |
326 void PlatformVerificationFlow::OnChallengeReady( | 320 void PlatformVerificationFlow::OnChallengeReady( |
327 const ChallengeContext& context, | 321 const ChallengeContext& context, |
328 const std::string& user_id, | 322 const AccountId& account_id, |
329 const std::string& certificate_chain, | 323 const std::string& certificate_chain, |
330 bool is_expiring_soon, | 324 bool is_expiring_soon, |
331 bool operation_success, | 325 bool operation_success, |
332 const std::string& response_data) { | 326 const std::string& response_data) { |
333 if (!operation_success) { | 327 if (!operation_success) { |
334 LOG(ERROR) << "PlatformVerificationFlow: Failed to sign challenge."; | 328 LOG(ERROR) << "PlatformVerificationFlow: Failed to sign challenge."; |
335 ReportError(context.callback, INTERNAL_ERROR); | 329 ReportError(context.callback, INTERNAL_ERROR); |
336 return; | 330 return; |
337 } | 331 } |
338 SignedData signed_data_pb; | 332 SignedData signed_data_pb; |
339 if (response_data.empty() || !signed_data_pb.ParseFromString(response_data)) { | 333 if (response_data.empty() || !signed_data_pb.ParseFromString(response_data)) { |
340 LOG(ERROR) << "PlatformVerificationFlow: Failed to parse response data."; | 334 LOG(ERROR) << "PlatformVerificationFlow: Failed to parse response data."; |
341 ReportError(context.callback, INTERNAL_ERROR); | 335 ReportError(context.callback, INTERNAL_ERROR); |
342 return; | 336 return; |
343 } | 337 } |
344 VLOG(1) << "Platform verification successful."; | 338 VLOG(1) << "Platform verification successful."; |
345 UMA_HISTOGRAM_ENUMERATION(kAttestationResultHistogram, SUCCESS, RESULT_MAX); | 339 UMA_HISTOGRAM_ENUMERATION(kAttestationResultHistogram, SUCCESS, RESULT_MAX); |
346 context.callback.Run(SUCCESS, signed_data_pb.data(), | 340 context.callback.Run(SUCCESS, signed_data_pb.data(), |
347 signed_data_pb.signature(), certificate_chain); | 341 signed_data_pb.signature(), certificate_chain); |
348 if (is_expiring_soon && renewals_in_progress_.count(certificate_chain) == 0) { | 342 if (is_expiring_soon && renewals_in_progress_.count(certificate_chain) == 0) { |
349 renewals_in_progress_.insert(certificate_chain); | 343 renewals_in_progress_.insert(certificate_chain); |
350 // Fire off a certificate request so next time we'll have a new one. | 344 // Fire off a certificate request so next time we'll have a new one. |
351 AttestationFlow::CertificateCallback renew_callback = | 345 AttestationFlow::CertificateCallback renew_callback = |
352 base::Bind(&PlatformVerificationFlow::RenewCertificateCallback, this, | 346 base::Bind(&PlatformVerificationFlow::RenewCertificateCallback, this, |
353 certificate_chain); | 347 certificate_chain); |
354 attestation_flow_->GetCertificate(PROFILE_CONTENT_PROTECTION_CERTIFICATE, | 348 attestation_flow_->GetCertificate(PROFILE_CONTENT_PROTECTION_CERTIFICATE, |
355 user_id, context.service_id, | 349 account_id, context.service_id, |
356 true, // force_new_key | 350 true, // force_new_key |
357 renew_callback); | 351 renew_callback); |
358 } | 352 } |
359 } | 353 } |
360 | 354 |
361 bool PlatformVerificationFlow::IsAttestationAllowedByPolicy() { | 355 bool PlatformVerificationFlow::IsAttestationAllowedByPolicy() { |
362 // Check the device policy for the feature. | 356 // Check the device policy for the feature. |
363 bool enabled_for_device = false; | 357 bool enabled_for_device = false; |
364 if (!CrosSettings::Get()->GetBoolean(kAttestationForContentProtectionEnabled, | 358 if (!CrosSettings::Get()->GetBoolean(kAttestationForContentProtectionEnabled, |
365 &enabled_for_device)) { | 359 &enabled_for_device)) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 if (!operation_success) { | 422 if (!operation_success) { |
429 LOG(WARNING) << "PlatformVerificationFlow: Failed to renew platform " | 423 LOG(WARNING) << "PlatformVerificationFlow: Failed to renew platform " |
430 "certificate."; | 424 "certificate."; |
431 return; | 425 return; |
432 } | 426 } |
433 VLOG(1) << "Certificate successfully renewed."; | 427 VLOG(1) << "Certificate successfully renewed."; |
434 } | 428 } |
435 | 429 |
436 } // namespace attestation | 430 } // namespace attestation |
437 } // namespace chromeos | 431 } // namespace chromeos |
OLD | NEW |