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 "chromeos/attestation/attestation_flow.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/cryptohome/async_method_caller.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/cryptohome_client.h" 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/dbus_method_call_status.h" 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h" 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/cloud_policy_client.h" 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/cloud_policy_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)// The number of days before a certificate expires during which it is 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// considered 'expiring soon' and replacement is initiated. The Chrome OS CA 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// issues certificates with an expiry of at least two years. This value has 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// been set large enough so that the majority of users will have gone through 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// a full sign-in during the period. 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kExpiryThresholdInDays = 30; 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kRetryDelay = 5; // Seconds. 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kRetryLimit = 100; 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A dbus callback which handles a boolean result. 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Parameters 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// on_true - Called when status=success and value=true. 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// on_false - Called when status=success and value=false. 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// status - The dbus operation status. 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// value - The value returned by the dbus operation. 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DBusBoolRedirectCallback(const base::Closure& on_true, 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::Closure& on_false, 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::Closure& on_failure, 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const tracked_objects::Location& from_here, 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chromeos::DBusMethodCallStatus status, 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool value) { 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (status != chromeos::DBUS_METHOD_CALL_SUCCESS) { 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Cryptohome DBus method failed: " << from_here.ToString() 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) << " - " << status; 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!on_failure.is_null()) 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch on_failure.Run(); 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::Closure& task = value ? on_true : on_false; 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!task.is_null()) 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) task.Run(); 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A dbus callback which handles a string result. 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Parameters 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// on_success - Called when status=success and result=true. 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// status - The dbus operation status. 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// result - The result returned by the dbus operation. 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// data - The data returned by the dbus operation. 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DBusStringCallback( 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::Callback<void(const std::string&)> on_success, 73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::Closure& on_failure, 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const tracked_objects::Location& from_here, 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) chromeos::DBusMethodCallStatus status, 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool result, 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& data) { 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) { 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Cryptohome DBus method failed: " << from_here.ToString() 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) << " - " << status << " - " << result; 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!on_failure.is_null()) 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch on_failure.Run(); 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) on_success.Run(data); 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace chromeos { 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace attestation { 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AttestationPolicyObserver::AttestationPolicyObserver( 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) policy::CloudPolicyClient* policy_client) 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : cros_settings_(CrosSettings::Get()), 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) policy_client_(policy_client), 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome_client_(NULL), 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) attestation_flow_(NULL), 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch num_retries_(0), 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch retry_delay_(kRetryDelay), 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_(this) { 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) attestation_subscription_ = cros_settings_->AddSettingsObserver( 10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) kDeviceAttestationEnabled, 10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(&AttestationPolicyObserver::AttestationSettingChanged, 10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Unretained(this))); 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Start(); 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AttestationPolicyObserver::AttestationPolicyObserver( 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) policy::CloudPolicyClient* policy_client, 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CryptohomeClient* cryptohome_client, 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AttestationFlow* attestation_flow) 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : cros_settings_(CrosSettings::Get()), 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) policy_client_(policy_client), 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome_client_(cryptohome_client), 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) attestation_flow_(attestation_flow), 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch num_retries_(0), 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch retry_delay_(kRetryDelay), 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_(this) { 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) attestation_subscription_ = cros_settings_->AddSettingsObserver( 12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) kDeviceAttestationEnabled, 12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(&AttestationPolicyObserver::AttestationSettingChanged, 12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Unretained(this))); 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Start(); 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AttestationPolicyObserver::~AttestationPolicyObserver() { 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void AttestationPolicyObserver::AttestationSettingChanged() { 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch num_retries_ = 0; 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Start(); 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AttestationPolicyObserver::Start() { 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If attestation is not enabled, there is nothing to do. 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool enabled = false; 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!cros_settings_->GetBoolean(kDeviceAttestationEnabled, &enabled) || 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !enabled) 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We expect a registered CloudPolicyClient. 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!policy_client_->is_registered()) { 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "AttestationPolicyObserver: Invalid CloudPolicyClient."; 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!cryptohome_client_) 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome_client_ = DBusThreadManager::Get()->GetCryptohomeClient(); 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!attestation_flow_) { 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<ServerProxy> attestation_ca_client(new AttestationCAClient()); 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) default_attestation_flow_.reset(new AttestationFlow( 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome::AsyncMethodCaller::GetInstance(), 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome_client_, 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) attestation_ca_client.Pass())); 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) attestation_flow_ = default_attestation_flow_.get(); 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Start a dbus call to check if an Enterprise Machine Key already exists. 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Closure on_does_exist = 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&AttestationPolicyObserver::GetExistingCertificate, 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_.GetWeakPtr()); 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Closure on_does_not_exist = 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&AttestationPolicyObserver::GetNewCertificate, 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_.GetWeakPtr()); 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome_client_->TpmAttestationDoesKeyExist( 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) KEY_DEVICE, 1738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::string(), // Not used. 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kEnterpriseMachineKey, 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(DBusBoolRedirectCallback, 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) on_does_exist, 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) on_does_not_exist, 178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&AttestationPolicyObserver::Reschedule, 179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch weak_factory_.GetWeakPtr()), 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE)); 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AttestationPolicyObserver::GetNewCertificate() { 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We can reuse the dbus callback handler logic. 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) attestation_flow_->GetCertificate( 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PROFILE_ENTERPRISE_MACHINE_CERTIFICATE, 1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string(), // Not used. 1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string(), // Not used. 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) true, // Force a new key to be generated. 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(DBusStringCallback, 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&AttestationPolicyObserver::UploadCertificate, 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_.GetWeakPtr()), 193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&AttestationPolicyObserver::Reschedule, 194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch weak_factory_.GetWeakPtr()), 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DBUS_METHOD_CALL_SUCCESS)); 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AttestationPolicyObserver::GetExistingCertificate() { 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome_client_->TpmAttestationGetCertificate( 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) KEY_DEVICE, 2028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::string(), // Not used. 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, 2608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::string(), // Not used. 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kEnterpriseMachineKey, 262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(DBusStringCallback, 263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch callback, 264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&AttestationPolicyObserver::Reschedule, 265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch weak_factory_.GetWeakPtr()), 266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FROM_HERE)); 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AttestationPolicyObserver::OnUploadComplete(bool status) { 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!status) 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VLOG(1) << "Enterprise Machine Certificate uploaded to DMServer."; 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetKeyPayload(base::Bind(&AttestationPolicyObserver::MarkAsUploaded, 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_.GetWeakPtr())); 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AttestationPolicyObserver::MarkAsUploaded(const std::string& key_payload) { 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AttestationKeyPayload payload_pb; 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!key_payload.empty()) 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) payload_pb.ParseFromString(key_payload); 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) payload_pb.set_is_certificate_uploaded(true); 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string new_payload; 283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!payload_pb.SerializeToString(&new_payload)) { 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(WARNING) << "Failed to serialize key payload."; 285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cryptohome_client_->TpmAttestationSetKeyPayload( 288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) KEY_DEVICE, 2898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::string(), // Not used. 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kEnterpriseMachineKey, 291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new_payload, 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(DBusBoolRedirectCallback, 293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Closure(), 294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Closure(), 295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Closure(), 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE)); 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid AttestationPolicyObserver::Reschedule() { 300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (++num_retries_ < kRetryLimit) { 301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::BrowserThread::PostDelayedTask( 302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::BrowserThread::UI, FROM_HERE, 303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&AttestationPolicyObserver::Start, 304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch weak_factory_.GetWeakPtr()), 305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::TimeDelta::FromSeconds(retry_delay_)); 306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(WARNING) << "AttestationPolicyObserver: Retry limit exceeded."; 308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace attestation 312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace chromeos 313