attestation_policy_observer.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/attestation/attestation_policy_observer.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string> 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/callback.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/location.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/attestation/attestation_ca_client.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/attestation/attestation_key_payload.pb.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/settings/cros_settings.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/policy/cloud/cloud_policy_client.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/policy/cloud/cloud_policy_manager.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/attestation/attestation_flow.h" 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/cryptohome/async_method_caller.h" 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/cryptohome_client.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/dbus_method_call_status.h" 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h" 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/notification_details.h" 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.h" 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kEnterpriseMachineKey[] = "attest-ent-machine"; 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The number of days before a certificate expires during which it is 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// considered 'expiring soon' and replacement is initiated. The Chrome OS CA 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// issues certificates with an expiry of at least two years. This value has 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// been set large enough so that the majority of users will have gone through 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// a full sign-in during the period. 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kExpiryThresholdInDays = 30; 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kRetryDelay = 5; // Seconds. 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kRetryLimit = 100; 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A dbus callback which handles a boolean result. 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Parameters 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// on_true - Called when status=success and value=true. 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// on_false - Called when status=success and value=false. 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// status - The dbus operation status. 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// value - The value returned by the dbus operation. 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DBusBoolRedirectCallback(const base::Closure& on_true, 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::Closure& on_false, 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::Closure& on_failure, 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const tracked_objects::Location& from_here, 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chromeos::DBusMethodCallStatus status, 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool value) { 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (status != chromeos::DBUS_METHOD_CALL_SUCCESS) { 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Cryptohome DBus method failed: " << from_here.ToString() 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) << " - " << status; 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!on_failure.is_null()) 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch on_failure.Run(); 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::Closure& task = value ? on_true : on_false; 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!task.is_null()) 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) task.Run(); 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A dbus callback which handles a string result. 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Parameters 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// on_success - Called when status=success and result=true. 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// status - The dbus operation status. 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// result - The result returned by the dbus operation. 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// data - The data returned by the dbus operation. 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DBusStringCallback( 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::Callback<void(const std::string&)> on_success, 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::Closure& on_failure, 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const tracked_objects::Location& from_here, 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chromeos::DBusMethodCallStatus status, 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool result, 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& data) { 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) { 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Cryptohome DBus method failed: " << from_here.ToString() 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) << " - " << status << " - " << result; 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!on_failure.is_null()) 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch on_failure.Run(); 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) on_success.Run(data); 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace chromeos { 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace attestation { 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AttestationPolicyObserver::AttestationPolicyObserver( 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) policy::CloudPolicyClient* policy_client) 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : cros_settings_(CrosSettings::Get()), 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) policy_client_(policy_client), 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome_client_(NULL), 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) attestation_flow_(NULL), 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch num_retries_(0), 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch retry_delay_(kRetryDelay), 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_(this) { 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) attestation_subscription_ = cros_settings_->AddSettingsObserver( 10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) kDeviceAttestationEnabled, 10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(&AttestationPolicyObserver::AttestationSettingChanged, 10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Unretained(this))); 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Start(); 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AttestationPolicyObserver::AttestationPolicyObserver( 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) policy::CloudPolicyClient* policy_client, 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CryptohomeClient* cryptohome_client, 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AttestationFlow* attestation_flow) 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : cros_settings_(CrosSettings::Get()), 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) policy_client_(policy_client), 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome_client_(cryptohome_client), 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) attestation_flow_(attestation_flow), 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch num_retries_(0), 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch retry_delay_(kRetryDelay), 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_(this) { 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) attestation_subscription_ = cros_settings_->AddSettingsObserver( 12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) kDeviceAttestationEnabled, 12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(&AttestationPolicyObserver::AttestationSettingChanged, 12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Unretained(this))); 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Start(); 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AttestationPolicyObserver::~AttestationPolicyObserver() { 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void AttestationPolicyObserver::AttestationSettingChanged() { 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch num_retries_ = 0; 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Start(); 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AttestationPolicyObserver::Start() { 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If attestation is not enabled, there is nothing to do. 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool enabled = false; 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!cros_settings_->GetBoolean(kDeviceAttestationEnabled, &enabled) || 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !enabled) 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We expect a registered CloudPolicyClient. 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!policy_client_->is_registered()) { 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "AttestationPolicyObserver: Invalid CloudPolicyClient."; 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!cryptohome_client_) 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome_client_ = DBusThreadManager::Get()->GetCryptohomeClient(); 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!attestation_flow_) { 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<ServerProxy> attestation_ca_client(new AttestationCAClient()); 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) default_attestation_flow_.reset(new AttestationFlow( 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome::AsyncMethodCaller::GetInstance(), 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome_client_, 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) attestation_ca_client.Pass())); 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) attestation_flow_ = default_attestation_flow_.get(); 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Start a dbus call to check if an Enterprise Machine Key already exists. 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Closure on_does_exist = 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&AttestationPolicyObserver::GetExistingCertificate, 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_.GetWeakPtr()); 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Closure on_does_not_exist = 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&AttestationPolicyObserver::GetNewCertificate, 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_.GetWeakPtr()); 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome_client_->TpmAttestationDoesKeyExist( 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) KEY_DEVICE, 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kEnterpriseMachineKey, 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(DBusBoolRedirectCallback, 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) on_does_exist, 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) on_does_not_exist, 179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&AttestationPolicyObserver::Reschedule, 180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch weak_factory_.GetWeakPtr()), 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE)); 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AttestationPolicyObserver::GetNewCertificate() { 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We can reuse the dbus callback handler logic. 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) attestation_flow_->GetCertificate( 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PROFILE_ENTERPRISE_MACHINE_CERTIFICATE, 1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string(), // Not used. 1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string(), // Not used. 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) true, // Force a new key to be generated. 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(DBusStringCallback, 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&AttestationPolicyObserver::UploadCertificate, 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_.GetWeakPtr()), 194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&AttestationPolicyObserver::Reschedule, 195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch weak_factory_.GetWeakPtr()), 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DBUS_METHOD_CALL_SUCCESS)); 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AttestationPolicyObserver::GetExistingCertificate() { 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome_client_->TpmAttestationGetCertificate( 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) KEY_DEVICE, 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kEnterpriseMachineKey, 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(DBusStringCallback, 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&AttestationPolicyObserver::CheckCertificateExpiry, 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_.GetWeakPtr()), 207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&AttestationPolicyObserver::Reschedule, 208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch weak_factory_.GetWeakPtr()), 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE)); 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AttestationPolicyObserver::CheckCertificateExpiry( 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& certificate) { 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<net::X509Certificate> x509( 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) net::X509Certificate::CreateFromBytes(certificate.data(), 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) certificate.length())); 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!x509.get() || x509->valid_expiry().is_null()) { 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(WARNING) << "Failed to parse certificate, cannot check expiry."; 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::TimeDelta threshold = 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::TimeDelta::FromDays(kExpiryThresholdInDays); 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if ((base::Time::Now() + threshold) > x509->valid_expiry()) { 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The certificate has expired or will soon, replace it. 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetNewCertificate(); 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Get the payload and check if the certificate has already been uploaded. 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetKeyPayload(base::Bind(&AttestationPolicyObserver::CheckIfUploaded, 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_.GetWeakPtr(), 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) certificate)); 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AttestationPolicyObserver::UploadCertificate( 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& certificate) { 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) policy_client_->UploadCertificate( 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) certificate, 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&AttestationPolicyObserver::OnUploadComplete, 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_.GetWeakPtr())); 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AttestationPolicyObserver::CheckIfUploaded( 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& certificate, 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& key_payload) { 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AttestationKeyPayload payload_pb; 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!key_payload.empty() && 248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) payload_pb.ParseFromString(key_payload) && 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) payload_pb.is_certificate_uploaded()) { 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Already uploaded... nothing more to do. 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UploadCertificate(certificate); 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AttestationPolicyObserver::GetKeyPayload( 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Callback<void(const std::string&)> callback) { 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome_client_->TpmAttestationGetKeyPayload( 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) KEY_DEVICE, 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kEnterpriseMachineKey, 261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(DBusStringCallback, 262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch callback, 263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&AttestationPolicyObserver::Reschedule, 264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch weak_factory_.GetWeakPtr()), 265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FROM_HERE)); 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AttestationPolicyObserver::OnUploadComplete(bool status) { 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!status) 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(INFO) << "Enterprise Machine Certificate uploaded to DMServer."; 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetKeyPayload(base::Bind(&AttestationPolicyObserver::MarkAsUploaded, 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_.GetWeakPtr())); 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AttestationPolicyObserver::MarkAsUploaded(const std::string& key_payload) { 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AttestationKeyPayload payload_pb; 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!key_payload.empty()) 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) payload_pb.ParseFromString(key_payload); 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) payload_pb.set_is_certificate_uploaded(true); 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string new_payload; 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!payload_pb.SerializeToString(&new_payload)) { 283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(WARNING) << "Failed to serialize key payload."; 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome_client_->TpmAttestationSetKeyPayload( 287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) KEY_DEVICE, 288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kEnterpriseMachineKey, 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new_payload, 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(DBusBoolRedirectCallback, 291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Closure(), 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Closure(), 293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Closure(), 294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE)); 295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid AttestationPolicyObserver::Reschedule() { 298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (++num_retries_ < kRetryLimit) { 299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::BrowserThread::PostDelayedTask( 300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::BrowserThread::UI, FROM_HERE, 301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&AttestationPolicyObserver::Start, 302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch weak_factory_.GetWeakPtr()), 303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::TimeDelta::FromSeconds(retry_delay_)); 304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(WARNING) << "AttestationPolicyObserver: Retry limit exceeded."; 306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace attestation 310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace chromeos 311