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/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/base64.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/callback.h"
119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/prefs/pref_service.h"
135e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/values.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/browser_process.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/attestation/attestation_ca_client.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/settings/cros_settings.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/signin_manager_factory.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/extensions/api/enterprise_platform_keys_private.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/pref_names.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/attestation/attestation_constants.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/attestation/attestation_flow.h"
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/cryptohome/async_method_caller.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/cryptohome_client.h"
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/dbus_method_call_status.h"
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/settings/cros_settings_names.h"
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h"
32e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "components/signin/core/browser/signin_manager.h"
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "google_apis/gaia/gaia_auth_util.h"
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace extensions {
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace api_epkp = api::enterprise_platform_keys_private;
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Base class
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
42b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char EPKPChallengeKeyBase::kChallengeBadBase64Error[] =
43b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    "Challenge is not base64 encoded.";
44b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char EPKPChallengeKeyBase::kDevicePolicyDisabledError[] =
45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    "Remote attestation is not enabled for your device.";
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char EPKPChallengeKeyBase::kExtensionNotWhitelistedError[] =
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    "The extension does not have permission to call this function.";
48b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char EPKPChallengeKeyBase::kResponseBadBase64Error[] =
49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    "Response cannot be encoded in base64.";
50b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char EPKPChallengeKeyBase::kSignChallengeFailedError[] =
51b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    "Failed to sign the challenge.";
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char EPKPChallengeKeyBase::kUserNotManaged[] =
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    "The user account is not enterprise managed.";
54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)EPKPChallengeKeyBase::PrepareKeyContext::PrepareKeyContext(
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    chromeos::attestation::AttestationKeyType key_type,
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& user_id,
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& key_name,
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    chromeos::attestation::AttestationCertificateProfile certificate_profile,
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool require_user_consent,
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const base::Callback<void(PrepareKeyResult)>& callback)
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : key_type(key_type),
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      user_id(user_id),
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      key_name(key_name),
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      certificate_profile(certificate_profile),
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      require_user_consent(require_user_consent),
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      callback(callback) {
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)EPKPChallengeKeyBase::PrepareKeyContext::~PrepareKeyContext() {
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EPKPChallengeKeyBase::EPKPChallengeKeyBase()
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : cryptohome_client_(
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          chromeos::DBusThreadManager::Get()->GetCryptohomeClient()),
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      async_caller_(cryptohome::AsyncMethodCaller::GetInstance()),
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      install_attributes_(g_browser_process->platform_part()
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              ->browser_policy_connector_chromeos()
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              ->GetInstallAttributes()) {
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<chromeos::attestation::ServerProxy> ca_client(
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new chromeos::attestation::AttestationCAClient());
82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  default_attestation_flow_.reset(
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new chromeos::attestation::AttestationFlow(
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          async_caller_, cryptohome_client_, ca_client.Pass()));
85b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  attestation_flow_ = default_attestation_flow_.get();
86b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
87b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)EPKPChallengeKeyBase::EPKPChallengeKeyBase(
89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    chromeos::CryptohomeClient* cryptohome_client,
90b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    cryptohome::AsyncMethodCaller* async_caller,
91b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    chromeos::attestation::AttestationFlow* attestation_flow,
92b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    policy::EnterpriseInstallAttributes* install_attributes) :
93b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    cryptohome_client_(cryptohome_client),
94b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    async_caller_(async_caller),
95b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    attestation_flow_(attestation_flow),
96b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    install_attributes_(install_attributes) {
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EPKPChallengeKeyBase::~EPKPChallengeKeyBase() {
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeKeyBase::GetDeviceAttestationEnabled(
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Callback<void(bool)>& callback) const {
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  chromeos::CrosSettings* settings = chromeos::CrosSettings::Get();
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  chromeos::CrosSettingsProvider::TrustedStatus status =
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      settings->PrepareTrustedValues(
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::Bind(&EPKPChallengeKeyBase::GetDeviceAttestationEnabled, this,
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     callback));
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool value = false;
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (status) {
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case chromeos::CrosSettingsProvider::TRUSTED:
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!settings->GetBoolean(chromeos::kDeviceAttestationEnabled, &value))
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        value = false;
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case chromeos::CrosSettingsProvider::TEMPORARILY_UNTRUSTED:
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Do nothing. This function will be called again when the values are
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // ready.
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case chromeos::CrosSettingsProvider::PERMANENTLY_UNTRUSTED:
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // If the value cannot be trusted, we assume that the device attestation
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // is false to be on the safe side.
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(value);
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool EPKPChallengeKeyBase::IsEnterpriseDevice() const {
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return install_attributes_->IsEnterpriseDevice();
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool EPKPChallengeKeyBase::IsExtensionWhitelisted() const {
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const base::ListValue* list =
1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      GetProfile()->GetPrefs()->GetList(prefs::kAttestationExtensionWhitelist);
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::StringValue value(extension_->id());
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return list->Find(value) != list->end();
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool EPKPChallengeKeyBase::IsUserManaged() const {
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string email = GetUserEmail();
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(davidyu): Use BrowserPolicyConnector::GetUserAffiliation() and fix
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // the test.
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return email.empty() ? false :
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      gaia::ExtractDomainName(email) == GetEnterpriseDomain();
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string EPKPChallengeKeyBase::GetEnterpriseDomain() const {
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return install_attributes_->GetDomain();
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string EPKPChallengeKeyBase::GetUserEmail() const {
154a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  SigninManagerBase* signin_manager =
1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      SigninManagerFactory::GetForProfile(GetProfile());
156a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (!signin_manager)
157a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return std::string();
158a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return gaia::CanonicalizeEmail(signin_manager->GetAuthenticatedUsername());
160a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
161a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string EPKPChallengeKeyBase::GetDeviceId() const {
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return install_attributes_->GetDeviceId();
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeKeyBase::PrepareKey(
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    chromeos::attestation::AttestationKeyType key_type,
1688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const std::string& user_id,
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& key_name,
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    chromeos::attestation::AttestationCertificateProfile certificate_profile,
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool require_user_consent,
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Callback<void(PrepareKeyResult)>& callback) {
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const PrepareKeyContext context = PrepareKeyContext(key_type,
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                      user_id,
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                      key_name,
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                      certificate_profile,
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                      require_user_consent,
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                      callback);
1790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  cryptohome_client_->TpmAttestationIsPrepared(base::Bind(
1800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      &EPKPChallengeKeyBase::IsAttestationPreparedCallback, this, context));
1810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
1820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void EPKPChallengeKeyBase::IsAttestationPreparedCallback(
1840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const PrepareKeyContext& context,
1850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    chromeos::DBusMethodCallStatus status,
1860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    bool result) {
1870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (status == chromeos::DBUS_METHOD_CALL_FAILURE) {
1880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    context.callback.Run(PREPARE_KEY_DBUS_ERROR);
1890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    return;
1900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
1910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (!result) {
1920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    context.callback.Run(PREPARE_KEY_RESET_REQUIRED);
1930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    return;
1940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
1950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // Attestation is available, see if the key we need already exists.
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  cryptohome_client_->TpmAttestationDoesKeyExist(
1970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      context.key_type, context.user_id, context.key_name, base::Bind(
1980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)          &EPKPChallengeKeyBase::DoesKeyExistCallback, this, context));
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeKeyBase::DoesKeyExistCallback(
2020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const PrepareKeyContext& context,
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    chromeos::DBusMethodCallStatus status,
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool result) {
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status == chromeos::DBUS_METHOD_CALL_FAILURE) {
2060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    context.callback.Run(PREPARE_KEY_DBUS_ERROR);
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (result) {
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // The key exists. Do nothing more.
2120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    context.callback.Run(PREPARE_KEY_OK);
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // The key does not exist. Create a new key and have it signed by PCA.
2150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    if (context.require_user_consent) {
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // We should ask the user explicitly before sending any private
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // information to PCA.
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      AskForUserConsent(
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::Bind(&EPKPChallengeKeyBase::AskForUserConsentCallback, this,
2200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                     context));
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } else {
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // User consent is not required. Skip to the next step.
2230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      AskForUserConsentCallback(context, true);
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeKeyBase::AskForUserConsent(
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Callback<void(bool)>& callback) const {
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(davidyu): right now we just simply reject the request before we have
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // a way to ask for user consent.
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(false);
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeKeyBase::AskForUserConsentCallback(
2360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const PrepareKeyContext& context,
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool result) {
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!result) {
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // The user rejects the request.
2400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    context.callback.Run(PREPARE_KEY_USER_REJECTED);
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Generate a new key and have it signed by PCA.
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  attestation_flow_->GetCertificate(
2460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      context.certificate_profile,
2470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      context.user_id,
2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      std::string(),  // Not used.
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      true,  // Force a new key to be generated.
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&EPKPChallengeKeyBase::GetCertificateCallback, this,
2510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                 context.callback));
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeKeyBase::GetCertificateCallback(
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Callback<void(PrepareKeyResult)>& callback,
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool success,
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& pem_certificate_chain) {
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!success) {
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.Run(PREPARE_KEY_GET_CERTIFICATE_FAILED);
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(PREPARE_KEY_OK);
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Implementation of ChallengeMachineKey()
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
268b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char EPKPChallengeMachineKey::kGetCertificateFailedError[] =
269b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    "Failed to get Enterprise machine certificate. Error code = %d";
270b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char EPKPChallengeMachineKey::kNonEnterpriseDeviceError[] =
271b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    "The device is not enterprise enrolled.";
272b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char EPKPChallengeMachineKey::kKeyName[] = "attest-ent-machine";
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
275b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)EPKPChallengeMachineKey::EPKPChallengeMachineKey() : EPKPChallengeKeyBase() {
276b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
277b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
278b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)EPKPChallengeMachineKey::EPKPChallengeMachineKey(
279b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    chromeos::CryptohomeClient* cryptohome_client,
280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    cryptohome::AsyncMethodCaller* async_caller,
281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    chromeos::attestation::AttestationFlow* attestation_flow,
282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    policy::EnterpriseInstallAttributes* install_attributes) :
283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EPKPChallengeKeyBase(cryptohome_client,
284b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                         async_caller,
285b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                         attestation_flow,
286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                         install_attributes) {
287b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EPKPChallengeMachineKey::~EPKPChallengeMachineKey() {
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
292010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool EPKPChallengeMachineKey::RunAsync() {
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<api_epkp::ChallengeMachineKey::Params>
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      params(api_epkp::ChallengeMachineKey::Params::Create(*args_));
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string challenge;
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!base::Base64Decode(params->challenge, &challenge)) {
299b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    SetError(kChallengeBadBase64Error);
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check if the device is enterprise enrolled.
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!IsEnterpriseDevice()) {
305b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    SetError(kNonEnterpriseDeviceError);
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Check if the extension is whitelisted in the user policy.
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!IsExtensionWhitelisted()) {
31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SetError(kExtensionNotWhitelistedError);
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Check if the user domain is the same as the enrolled enterprise domain.
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!IsUserManaged()) {
31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SetError(kUserNotManaged);
318a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
319a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
320a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check if RA is enabled in the device policy.
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GetDeviceAttestationEnabled(
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&EPKPChallengeMachineKey::GetDeviceAttestationEnabledCallback,
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 this, challenge));
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeMachineKey::GetDeviceAttestationEnabledCallback(
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& challenge, bool enabled) {
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!enabled) {
332b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    SetError(kDevicePolicyDisabledError);
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PrepareKey(chromeos::attestation::KEY_DEVICE,
3388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)             std::string(),  // Not used.
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             kKeyName,
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             chromeos::attestation::PROFILE_ENTERPRISE_MACHINE_CERTIFICATE,
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             false,  // user consent is not required.
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             base::Bind(&EPKPChallengeMachineKey::PrepareKeyCallback, this,
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        challenge));
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeMachineKey::PrepareKeyCallback(
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& challenge, PrepareKeyResult result) {
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (result != PREPARE_KEY_OK) {
349b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    SetError(base::StringPrintf(kGetCertificateFailedError, result));
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Everything is checked. Sign the challenge.
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_caller_->TpmAttestationSignEnterpriseChallenge(
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      chromeos::attestation::KEY_DEVICE,
3578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      std::string(),  // Not used.
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kKeyName,
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetEnterpriseDomain(),
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetDeviceId(),
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      chromeos::attestation::CHALLENGE_OPTION_NONE,
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      challenge,
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&EPKPChallengeMachineKey::SignChallengeCallback, this));
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeMachineKey::SignChallengeCallback(
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool success, const std::string& response) {
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!success) {
369b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    SetError(kSignChallengeFailedError);
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string encoded_response;
375a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::Base64Encode(response, &encoded_response);
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  results_ = api_epkp::ChallengeMachineKey::Results::Create(encoded_response);
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SendResponse(true);
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Implementation of ChallengeUserKey()
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
383b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char EPKPChallengeUserKey::kGetCertificateFailedError[] =
384b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    "Failed to get Enterprise user certificate. Error code = %d";
385b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char EPKPChallengeUserKey::kKeyRegistrationFailedError[] =
386b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    "Key registration failed.";
387b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char EPKPChallengeUserKey::kUserPolicyDisabledError[] =
388b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    "Remote attestation is not enabled for your account.";
389b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char EPKPChallengeUserKey::kKeyName[] = "attest-ent-user";
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
392b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)EPKPChallengeUserKey::EPKPChallengeUserKey() : EPKPChallengeKeyBase() {
393b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
394b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
395b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)EPKPChallengeUserKey::EPKPChallengeUserKey(
396b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    chromeos::CryptohomeClient* cryptohome_client,
397b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    cryptohome::AsyncMethodCaller* async_caller,
398b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    chromeos::attestation::AttestationFlow* attestation_flow,
399b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    policy::EnterpriseInstallAttributes* install_attributes) :
400b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EPKPChallengeKeyBase(cryptohome_client,
401b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                         async_caller,
402b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                         attestation_flow,
403b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                         install_attributes) {
404b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
405b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EPKPChallengeUserKey::~EPKPChallengeUserKey() {
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid EPKPChallengeUserKey::RegisterProfilePrefs(
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    user_prefs::PrefRegistrySyncable* registry) {
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterBooleanPref(
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      prefs::kAttestationEnabled,
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      false,
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterListPref(prefs::kAttestationExtensionWhitelist,
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
419010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool EPKPChallengeUserKey::RunAsync() {
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<api_epkp::ChallengeUserKey::Params> params(
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      api_epkp::ChallengeUserKey::Params::Create(*args_));
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string challenge;
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!base::Base64Decode(params->challenge, &challenge)) {
426b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    SetError(kChallengeBadBase64Error);
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check if RA is enabled in the user policy.
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!IsRemoteAttestationEnabledForUser()) {
432b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    SetError(kUserPolicyDisabledError);
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check if the extension is whitelisted in the user policy.
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!IsExtensionWhitelisted()) {
438b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    SetError(kExtensionNotWhitelistedError);
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (IsEnterpriseDevice()) {
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Check if the user domain is the same as the enrolled enterprise domain.
44490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!IsUserManaged()) {
44590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      SetError(kUserNotManaged);
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false;
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Check if RA is enabled in the device policy.
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GetDeviceAttestationEnabled(
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&EPKPChallengeUserKey::GetDeviceAttestationEnabledCallback,
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   this,
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   challenge,
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   params->register_key,
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   false));  // user consent is not required.
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // For personal devices, we don't need to check if RA is enabled in the
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // device, but we need to ask for user consent if the key does not exist.
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GetDeviceAttestationEnabledCallback(
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        challenge,
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        params->register_key,
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        true,  // user consent is required.
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        true);  // attestation is enabled.
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeUserKey::GetDeviceAttestationEnabledCallback(
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& challenge,
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool register_key,
472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool require_user_consent,
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool enabled) {
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!enabled) {
475b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    SetError(kDevicePolicyDisabledError);
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PrepareKey(chromeos::attestation::KEY_USER,
4818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)             GetUserEmail(),
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             kKeyName,
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             chromeos::attestation::PROFILE_ENTERPRISE_USER_CERTIFICATE,
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             require_user_consent,
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             base::Bind(&EPKPChallengeUserKey::PrepareKeyCallback, this,
48690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                        challenge, register_key));
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeUserKey::PrepareKeyCallback(const std::string& challenge,
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              bool register_key,
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              PrepareKeyResult result) {
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (result != PREPARE_KEY_OK) {
493b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    SetError(base::StringPrintf(kGetCertificateFailedError, result));
494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Everything is checked. Sign the challenge.
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_caller_->TpmAttestationSignEnterpriseChallenge(
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      chromeos::attestation::KEY_USER,
5018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      GetUserEmail(),
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kKeyName,
50390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      GetUserEmail(),
504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetDeviceId(),
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      register_key ?
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          chromeos::attestation::CHALLENGE_INCLUDE_SIGNED_PUBLIC_KEY :
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          chromeos::attestation::CHALLENGE_OPTION_NONE,
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      challenge,
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&EPKPChallengeUserKey::SignChallengeCallback, this,
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 register_key));
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeUserKey::SignChallengeCallback(bool register_key,
514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                 bool success,
515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                 const std::string& response) {
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!success) {
517b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    SetError(kSignChallengeFailedError);
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (register_key) {
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    async_caller_->TpmAttestationRegisterKey(
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        chromeos::attestation::KEY_USER,
5258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        GetUserEmail(),
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        kKeyName,
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&EPKPChallengeUserKey::RegisterKeyCallback, this, response));
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RegisterKeyCallback(response, true, cryptohome::MOUNT_ERROR_NONE);
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeUserKey::RegisterKeyCallback(
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& response,
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool success,
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cryptohome::MountError return_code) {
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!success || return_code != cryptohome::MOUNT_ERROR_NONE) {
538b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    SetError(kKeyRegistrationFailedError);
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string encoded_response;
544a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::Base64Encode(response, &encoded_response);
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  results_ = api_epkp::ChallengeUserKey::Results::Create(encoded_response);
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SendResponse(true);
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool EPKPChallengeUserKey::IsRemoteAttestationEnabledForUser() const {
5511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return GetProfile()->GetPrefs()->GetBoolean(prefs::kAttestationEnabled);
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace extensions
555