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