enterprise_platform_keys_private_api.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/message_loop.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/prefs/pref_service.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/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"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/settings/cros_settings.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/settings/cros_settings_names.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/policy/browser_policy_connector.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/signin_manager.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/signin_manager_factory.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/extensions/api/enterprise_platform_keys_private.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/pref_names.h"
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/attestation/attestation_constants.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/attestation/attestation_flow.h"
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/cryptohome/async_method_caller.h"
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/cryptohome_client.h"
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/dbus_method_call_status.h"
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "components/user_prefs/pref_registry_syncable.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)
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EPKPChallengeKeyBase::EPKPChallengeKeyBase()
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : cryptohome_client_(
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          chromeos::DBusThreadManager::Get()->GetCryptohomeClient()),
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      async_caller_(cryptohome::AsyncMethodCaller::GetInstance()),
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      install_attributes_(g_browser_process->browser_policy_connector()->
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          GetInstallAttributes()) {
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<chromeos::attestation::ServerProxy> ca_client(
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new chromeos::attestation::AttestationCAClient());
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  attestation_flow_.reset(
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new chromeos::attestation::AttestationFlow(
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          async_caller_, cryptohome_client_, ca_client.Pass()));
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EPKPChallengeKeyBase::~EPKPChallengeKeyBase() {
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeKeyBase::GetDeviceAttestationEnabled(
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Callback<void(bool)>& callback) const {
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  chromeos::CrosSettings* settings = chromeos::CrosSettings::Get();
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  chromeos::CrosSettingsProvider::TrustedStatus status =
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      settings->PrepareTrustedValues(
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::Bind(&EPKPChallengeKeyBase::GetDeviceAttestationEnabled, this,
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     callback));
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool value = false;
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (status) {
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case chromeos::CrosSettingsProvider::TRUSTED:
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!settings->GetBoolean(chromeos::kDeviceAttestationEnabled, &value))
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        value = false;
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case chromeos::CrosSettingsProvider::TEMPORARILY_UNTRUSTED:
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Do nothing. This function will be called again when the values are
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // ready.
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case chromeos::CrosSettingsProvider::PERMANENTLY_UNTRUSTED:
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // If the value cannot be trusted, we assume that the device attestation
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // is false to be on the safe side.
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(value);
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool EPKPChallengeKeyBase::IsEnterpriseDevice() const {
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return install_attributes_->IsEnterpriseDevice();
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string EPKPChallengeKeyBase::GetEnterpriseDomain() const {
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return install_attributes_->GetDomain();
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string EPKPChallengeKeyBase::GetDeviceId() const {
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return install_attributes_->GetDeviceId();
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeKeyBase::PrepareKey(
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    chromeos::attestation::AttestationKeyType key_type,
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& key_name,
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    chromeos::attestation::AttestationCertificateProfile certificate_profile,
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool require_user_consent,
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Callback<void(PrepareKeyResult)>& callback) {
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  cryptohome_client_->TpmAttestationDoesKeyExist(
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      key_type, key_name, base::Bind(
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          &EPKPChallengeKeyBase::DoesKeyExistCallback, this,
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          certificate_profile, require_user_consent, callback));
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeKeyBase::DoesKeyExistCallback(
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    chromeos::attestation::AttestationCertificateProfile certificate_profile,
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool require_user_consent,
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Callback<void(PrepareKeyResult)>& callback,
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    chromeos::DBusMethodCallStatus status,
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool result) {
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status == chromeos::DBUS_METHOD_CALL_FAILURE) {
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.Run(PREPARE_KEY_DBUS_ERROR);
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (result) {
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // The key exists. Do nothing more.
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.Run(PREPARE_KEY_OK);
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // The key does not exist. Create a new key and have it signed by PCA.
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (require_user_consent) {
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // We should ask the user explicitly before sending any private
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // information to PCA.
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      AskForUserConsent(
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::Bind(&EPKPChallengeKeyBase::AskForUserConsentCallback, this,
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     certificate_profile, callback));
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } else {
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // User consent is not required. Skip to the next step.
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      AskForUserConsentCallback(certificate_profile, callback, true);
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeKeyBase::AskForUserConsent(
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Callback<void(bool)>& callback) const {
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(davidyu): right now we just simply reject the request before we have
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // a way to ask for user consent.
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(false);
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeKeyBase::AskForUserConsentCallback(
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    chromeos::attestation::AttestationCertificateProfile certificate_profile,
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Callback<void(PrepareKeyResult)>& callback,
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool result) {
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!result) {
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // The user rejects the request.
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.Run(PREPARE_KEY_USER_REJECTED);
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Generate a new key and have it signed by PCA.
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  attestation_flow_->GetCertificate(
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      certificate_profile,
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      true,  // Force a new key to be generated.
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&EPKPChallengeKeyBase::GetCertificateCallback, this,
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 callback));
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeKeyBase::GetCertificateCallback(
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Callback<void(PrepareKeyResult)>& callback,
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool success,
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& pem_certificate_chain) {
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!success) {
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.Run(PREPARE_KEY_GET_CERTIFICATE_FAILED);
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(PREPARE_KEY_OK);
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Implementation of ChallengeMachineKey()
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char EPKPChallengeMachineKey::kKeyName[] = "attest-ent-machine";
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EPKPChallengeMachineKey::~EPKPChallengeMachineKey() {
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool EPKPChallengeMachineKey::RunImpl() {
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<api_epkp::ChallengeMachineKey::Params>
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      params(api_epkp::ChallengeMachineKey::Params::Create(*args_));
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string challenge;
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!base::Base64Decode(params->challenge, &challenge)) {
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetError("Challenge is not base64 encoded.");
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check if the device is enterprise enrolled.
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!IsEnterpriseDevice()) {
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetError("The device is not enterprise enrolled.");
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check if RA is enabled in the device policy.
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GetDeviceAttestationEnabled(
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&EPKPChallengeMachineKey::GetDeviceAttestationEnabledCallback,
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 this, challenge));
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeMachineKey::GetDeviceAttestationEnabledCallback(
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& challenge, bool enabled) {
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!enabled) {
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetError("Remote attestation is not enabled for your device.");
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PrepareKey(chromeos::attestation::KEY_DEVICE,
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             kKeyName,
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             chromeos::attestation::PROFILE_ENTERPRISE_MACHINE_CERTIFICATE,
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             false,  // user consent is not required.
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             base::Bind(&EPKPChallengeMachineKey::PrepareKeyCallback, this,
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        challenge));
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeMachineKey::PrepareKeyCallback(
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& challenge, PrepareKeyResult result) {
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (result != PREPARE_KEY_OK) {
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetError(base::StringPrintf(
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        "Failed to get Enterprise machince certificate. Error code = %d",
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        result));
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Everything is checked. Sign the challenge.
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_caller_->TpmAttestationSignEnterpriseChallenge(
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      chromeos::attestation::KEY_DEVICE,
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kKeyName,
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetEnterpriseDomain(),
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetDeviceId(),
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      chromeos::attestation::CHALLENGE_OPTION_NONE,
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      challenge,
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&EPKPChallengeMachineKey::SignChallengeCallback, this));
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeMachineKey::SignChallengeCallback(
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool success, const std::string& response) {
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!success) {
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetError("Challenge failed.");
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string encoded_response;
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!base::Base64Encode(response, &encoded_response)) {
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetError("Response cannot be encoded in base64.");
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  results_ = api_epkp::ChallengeMachineKey::Results::Create(encoded_response);
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SendResponse(true);
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Implementation of ChallengeUserKey()
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char EPKPChallengeUserKey::kKeyName[] = "attest-ent-user";
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EPKPChallengeUserKey::~EPKPChallengeUserKey() {
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeUserKey::RegisterUserPrefs(
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    user_prefs::PrefRegistrySyncable* registry) {
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterBooleanPref(
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      prefs::kAttestationEnabled,
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      false,
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registry->RegisterListPref(prefs::kAttestationExtensionWhitelist,
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool EPKPChallengeUserKey::RunImpl() {
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<api_epkp::ChallengeUserKey::Params> params(
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      api_epkp::ChallengeUserKey::Params::Create(*args_));
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string challenge;
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!base::Base64Decode(params->challenge, &challenge)) {
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetError("Challenge is not base64 encoded.");
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check if RA is enabled in the user policy.
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!IsRemoteAttestationEnabledForUser()) {
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetError("Remote attestation is not enabled for your account.");
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check if the extension is whitelisted in the user policy.
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!IsExtensionWhitelisted()) {
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetError("The extension does not have permission to call this function.");
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string user_domain = GetUserDomain();
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (IsEnterpriseDevice()) {
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Check if the user domain is the same as the enrolled enterprise domain.
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string enterprise_domain = GetEnterpriseDomain();
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (user_domain != enterprise_domain) {
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SetError("User domain " + user_domain + " and Enterprise domain " +
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               enterprise_domain + " don't match");
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SendResponse(false);
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false;
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Check if RA is enabled in the device policy.
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GetDeviceAttestationEnabled(
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&EPKPChallengeUserKey::GetDeviceAttestationEnabledCallback,
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   this,
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   challenge,
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   params->register_key,
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   user_domain,
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   false));  // user consent is not required.
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // For personal devices, we don't need to check if RA is enabled in the
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // device, but we need to ask for user consent if the key does not exist.
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GetDeviceAttestationEnabledCallback(
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        challenge,
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        params->register_key,
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        user_domain,
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        true,  // user consent is required.
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        true);  // attestation is enabled.
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeUserKey::GetDeviceAttestationEnabledCallback(
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& challenge,
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool register_key,
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& domain,
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool require_user_consent,
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool enabled) {
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!enabled) {
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetError("Remote attestation is not enabled for your device.");
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PrepareKey(chromeos::attestation::KEY_USER,
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             kKeyName,
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             chromeos::attestation::PROFILE_ENTERPRISE_USER_CERTIFICATE,
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             require_user_consent,
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             base::Bind(&EPKPChallengeUserKey::PrepareKeyCallback, this,
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        challenge, register_key, domain));
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeUserKey::PrepareKeyCallback(const std::string& challenge,
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              bool register_key,
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              const std::string& domain,
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              PrepareKeyResult result) {
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (result != PREPARE_KEY_OK) {
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetError(base::StringPrintf(
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        "Cannot get a key to sign the challenge. Error code = %d", result));
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Everything is checked. Sign the challenge.
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_caller_->TpmAttestationSignEnterpriseChallenge(
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      chromeos::attestation::KEY_USER,
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kKeyName,
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      domain,
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetDeviceId(),
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      register_key ?
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          chromeos::attestation::CHALLENGE_INCLUDE_SIGNED_PUBLIC_KEY :
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          chromeos::attestation::CHALLENGE_OPTION_NONE,
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      challenge,
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&EPKPChallengeUserKey::SignChallengeCallback, this,
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 register_key));
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeUserKey::SignChallengeCallback(bool register_key,
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                 bool success,
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                 const std::string& response) {
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!success) {
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetError("Challenge failed.");
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (register_key) {
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    async_caller_->TpmAttestationRegisterKey(
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        chromeos::attestation::KEY_USER,
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        kKeyName,
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&EPKPChallengeUserKey::RegisterKeyCallback, this, response));
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RegisterKeyCallback(response, true, cryptohome::MOUNT_ERROR_NONE);
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EPKPChallengeUserKey::RegisterKeyCallback(
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& response,
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool success,
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cryptohome::MountError return_code) {
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!success || return_code != cryptohome::MOUNT_ERROR_NONE) {
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetError("Key registration failed.");
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string encoded_response;
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!base::Base64Encode(response, &encoded_response)) {
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetError("Response cannot be encoded in base64.");
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(false);
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  results_ = api_epkp::ChallengeUserKey::Results::Create(encoded_response);
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SendResponse(true);
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool EPKPChallengeUserKey::IsExtensionWhitelisted() const {
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::ListValue* list =
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      profile()->GetPrefs()->GetList(prefs::kAttestationExtensionWhitelist);
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StringValue value(extension_->id());
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return list->Find(value) != list->end();
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool EPKPChallengeUserKey::IsRemoteAttestationEnabledForUser() const {
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return profile()->GetPrefs()->GetBoolean(prefs::kAttestationEnabled);
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string EPKPChallengeUserKey::GetUserDomain() const {
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SigninManagerBase* signin_manager =
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SigninManagerFactory::GetForProfile(profile());
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!signin_manager)
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return std::string();
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return gaia::ExtractDomainName(
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      gaia::CanonicalizeEmail(signin_manager->GetAuthenticatedUsername()));
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace extensions
449