summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordkrahn <dkrahn@chromium.org>2016-02-26 00:12:29 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-26 08:15:14 +0000
commit3f7776ec96bc700afcb61fc2c9e795f3cbe4e227 (patch)
tree811a1e080b98e3cd023a1149bb976931c68f6839
parent1f40e5362109368bd3c39282088c505ca43914c1 (diff)
downloadchromium_src-3f7776ec96bc700afcb61fc2c9e795f3cbe4e227.zip
chromium_src-3f7776ec96bc700afcb61fc2c9e795f3cbe4e227.tar.gz
chromium_src-3f7776ec96bc700afcb61fc2c9e795f3cbe4e227.tar.bz2
Copy challenge*Key methods to enterprise.platformKeys.
Up to this point the challengeMachineKey and challengeUserKey methods were only available through enterprise.platformKeysPrivate because the web APIs required to meaningfully use these methods had not been published (and now have). The methods will remain in enterprise.platformKeysPrivate until all users have been migrated to use enterprise.platformKeys. The implementation is identical and has been abstracted so it can be invoked from either entry point. BUG=chromium:329341 TEST=unit tests extended to test both entry points Review URL: https://codereview.chromium.org/1685103003 Cr-Commit-Position: refs/heads/master@{#377845}
-rw-r--r--chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc89
-rw-r--r--chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h59
-rw-r--r--chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc563
-rw-r--r--chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc301
-rw-r--r--chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h105
-rw-r--r--chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc28
-rw-r--r--chrome/browser/prefs/browser_prefs.cc3
-rw-r--r--chrome/chrome_tests_unit.gypi1
-rw-r--r--chrome/common/extensions/api/enterprise_platform_keys.idl62
-rw-r--r--extensions/browser/extension_function_histogram_value.h2
-rw-r--r--tools/metrics/histograms/histograms.xml2
11 files changed, 1062 insertions, 153 deletions
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
index 5dcaea9..d21e35e 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
+++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
@@ -31,6 +31,14 @@ const char kErrorInternal[] = "Internal Error.";
const char kErrorInvalidX509Cert[] =
"Certificate is not a valid X.509 certificate.";
+std::vector<char> VectorFromString(const std::string& s) {
+ return std::vector<char>(s.begin(), s.end());
+}
+
+std::string StringFromVector(const std::vector<char>& v) {
+ return std::string(v.begin(), v.end());
+}
+
} // namespace
EnterprisePlatformKeysInternalGenerateKeyFunction::
@@ -236,4 +244,85 @@ void EnterprisePlatformKeysInternalGetTokensFunction::OnGotTokens(
Respond(ArgumentList(api_epki::GetTokens::Results::Create(token_ids)));
}
+EnterprisePlatformKeysChallengeMachineKeyFunction::
+ EnterprisePlatformKeysChallengeMachineKeyFunction()
+ : default_impl_(new EPKPChallengeMachineKey), impl_(default_impl_.get()) {}
+
+EnterprisePlatformKeysChallengeMachineKeyFunction::
+ EnterprisePlatformKeysChallengeMachineKeyFunction(
+ EPKPChallengeMachineKey* impl_for_testing)
+ : impl_(impl_for_testing) {}
+
+EnterprisePlatformKeysChallengeMachineKeyFunction::
+ ~EnterprisePlatformKeysChallengeMachineKeyFunction() = default;
+
+ExtensionFunction::ResponseAction
+EnterprisePlatformKeysChallengeMachineKeyFunction::Run() {
+ scoped_ptr<api_epk::ChallengeMachineKey::Params> params(
+ api_epk::ChallengeMachineKey::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
+ ChallengeKeyCallback callback = base::Bind(
+ &EnterprisePlatformKeysChallengeMachineKeyFunction::OnChallengedKey,
+ this);
+ // base::Unretained is safe on impl_ since its life-cycle matches |this| and
+ // |callback| holds a reference to |this|.
+ base::Closure task = base::Bind(
+ &EPKPChallengeMachineKey::Run, base::Unretained(impl_),
+ scoped_refptr<UIThreadExtensionFunction>(AsUIThreadExtensionFunction()),
+ callback, StringFromVector(params->challenge));
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, task);
+ return RespondLater();
+}
+
+void EnterprisePlatformKeysChallengeMachineKeyFunction::OnChallengedKey(
+ bool success,
+ const std::string& data) {
+ if (success) {
+ Respond(ArgumentList(
+ api_epk::ChallengeMachineKey::Results::Create(VectorFromString(data))));
+ } else {
+ Respond(Error(data));
+ }
+}
+
+EnterprisePlatformKeysChallengeUserKeyFunction::
+ EnterprisePlatformKeysChallengeUserKeyFunction()
+ : default_impl_(new EPKPChallengeUserKey), impl_(default_impl_.get()) {}
+
+EnterprisePlatformKeysChallengeUserKeyFunction::
+ EnterprisePlatformKeysChallengeUserKeyFunction(
+ EPKPChallengeUserKey* impl_for_testing)
+ : impl_(impl_for_testing) {}
+
+EnterprisePlatformKeysChallengeUserKeyFunction::
+ ~EnterprisePlatformKeysChallengeUserKeyFunction() = default;
+
+ExtensionFunction::ResponseAction
+EnterprisePlatformKeysChallengeUserKeyFunction::Run() {
+ scoped_ptr<api_epk::ChallengeUserKey::Params> params(
+ api_epk::ChallengeUserKey::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
+ ChallengeKeyCallback callback = base::Bind(
+ &EnterprisePlatformKeysChallengeUserKeyFunction::OnChallengedKey, this);
+ // base::Unretained is safe on impl_ since its life-cycle matches |this| and
+ // |callback| holds a reference to |this|.
+ base::Closure task = base::Bind(
+ &EPKPChallengeUserKey::Run, base::Unretained(impl_),
+ scoped_refptr<UIThreadExtensionFunction>(AsUIThreadExtensionFunction()),
+ callback, StringFromVector(params->challenge), params->register_key);
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, task);
+ return RespondLater();
+}
+
+void EnterprisePlatformKeysChallengeUserKeyFunction::OnChallengedKey(
+ bool success,
+ const std::string& data) {
+ if (success) {
+ Respond(ArgumentList(
+ api_epk::ChallengeUserKey::Results::Create(VectorFromString(data))));
+ } else {
+ Respond(Error(data));
+ }
+}
+
} // namespace extensions
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h
index dd88919..6af1c1e 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h
+++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h
@@ -10,7 +10,8 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
+#include "chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h"
+#include "extensions/browser/extension_function.h"
namespace net {
class X509Certificate;
@@ -20,7 +21,7 @@ typedef std::vector<scoped_refptr<X509Certificate> > CertificateList;
namespace extensions {
class EnterprisePlatformKeysInternalGenerateKeyFunction
- : public ChromeUIThreadExtensionFunction {
+ : public UIThreadExtensionFunction {
private:
~EnterprisePlatformKeysInternalGenerateKeyFunction() override;
ResponseAction Run() override;
@@ -35,7 +36,7 @@ class EnterprisePlatformKeysInternalGenerateKeyFunction
};
class EnterprisePlatformKeysGetCertificatesFunction
- : public ChromeUIThreadExtensionFunction {
+ : public UIThreadExtensionFunction {
private:
~EnterprisePlatformKeysGetCertificatesFunction() override;
ResponseAction Run() override;
@@ -50,7 +51,7 @@ class EnterprisePlatformKeysGetCertificatesFunction
};
class EnterprisePlatformKeysImportCertificateFunction
- : public ChromeUIThreadExtensionFunction {
+ : public UIThreadExtensionFunction {
private:
~EnterprisePlatformKeysImportCertificateFunction() override;
ResponseAction Run() override;
@@ -64,7 +65,7 @@ class EnterprisePlatformKeysImportCertificateFunction
};
class EnterprisePlatformKeysRemoveCertificateFunction
- : public ChromeUIThreadExtensionFunction {
+ : public UIThreadExtensionFunction {
private:
~EnterprisePlatformKeysRemoveCertificateFunction() override;
ResponseAction Run() override;
@@ -78,7 +79,7 @@ class EnterprisePlatformKeysRemoveCertificateFunction
};
class EnterprisePlatformKeysInternalGetTokensFunction
- : public ChromeUIThreadExtensionFunction {
+ : public UIThreadExtensionFunction {
private:
~EnterprisePlatformKeysInternalGetTokensFunction() override;
ResponseAction Run() override;
@@ -92,6 +93,52 @@ class EnterprisePlatformKeysInternalGetTokensFunction
ENTERPRISE_PLATFORMKEYSINTERNAL_GETTOKENS);
};
+class EnterprisePlatformKeysChallengeMachineKeyFunction
+ : public UIThreadExtensionFunction {
+ public:
+ EnterprisePlatformKeysChallengeMachineKeyFunction();
+ explicit EnterprisePlatformKeysChallengeMachineKeyFunction(
+ EPKPChallengeMachineKey* impl_for_testing);
+
+ private:
+ ~EnterprisePlatformKeysChallengeMachineKeyFunction() override;
+ ResponseAction Run() override;
+
+ // Called when the challenge operation is complete. If the operation succeeded
+ // |success| will be true and |data| will contain the challenge response data.
+ // Otherwise |success| will be false and |data| is an error message.
+ void OnChallengedKey(bool success, const std::string& data);
+
+ scoped_ptr<EPKPChallengeMachineKey> default_impl_;
+ EPKPChallengeMachineKey* impl_;
+
+ DECLARE_EXTENSION_FUNCTION("enterprise.platformKeys.challengeMachineKey",
+ ENTERPRISE_PLATFORMKEYS_CHALLENGEMACHINEKEY);
+};
+
+class EnterprisePlatformKeysChallengeUserKeyFunction
+ : public UIThreadExtensionFunction {
+ public:
+ EnterprisePlatformKeysChallengeUserKeyFunction();
+ explicit EnterprisePlatformKeysChallengeUserKeyFunction(
+ EPKPChallengeUserKey* impl_for_testing);
+
+ private:
+ ~EnterprisePlatformKeysChallengeUserKeyFunction() override;
+ ResponseAction Run() override;
+
+ // Called when the challenge operation is complete. If the operation succeeded
+ // |success| will be true and |data| will contain the challenge response data.
+ // Otherwise |success| will be false and |data| is an error message.
+ void OnChallengedKey(bool success, const std::string& data);
+
+ scoped_ptr<EPKPChallengeUserKey> default_impl_;
+ EPKPChallengeUserKey* impl_;
+
+ DECLARE_EXTENSION_FUNCTION("enterprise.platformKeys.challengeUserKey",
+ ENTERPRISE_PLATFORMKEYS_CHALLENGEUSERKEY);
+};
+
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_PLATFORM_KEYS_ENTERPRISE_PLATFORM_KEYS_API_H_
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
new file mode 100644
index 0000000..f0694a0
--- /dev/null
+++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
@@ -0,0 +1,563 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/strings/stringprintf.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
+#include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
+#include "chrome/browser/chromeos/policy/stub_enterprise_install_attributes.h"
+#include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
+#include "chrome/browser/extensions/extension_function_test_utils.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/browser_with_test_window_test.h"
+#include "chromeos/attestation/attestation_constants.h"
+#include "chromeos/attestation/mock_attestation_flow.h"
+#include "chromeos/cryptohome/async_method_caller.h"
+#include "chromeos/cryptohome/mock_async_method_caller.h"
+#include "chromeos/dbus/dbus_method_call_status.h"
+#include "chromeos/dbus/mock_cryptohome_client.h"
+#include "components/policy/core/common/cloud/cloud_policy_constants.h"
+#include "components/prefs/pref_service.h"
+#include "components/signin/core/account_id/account_id.h"
+#include "components/signin/core/browser/signin_manager.h"
+#include "extensions/common/test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+using testing::_;
+using testing::Invoke;
+using testing::NiceMock;
+using testing::Return;
+using testing::WithArgs;
+
+namespace utils = extension_function_test_utils;
+
+namespace extensions {
+namespace {
+
+// Certificate errors as reported to the calling extension.
+const int kDBusError = 1;
+const int kUserRejected = 2;
+const int kGetCertificateFailed = 3;
+const int kResetRequired = 4;
+
+const char kUserEmail[] = "test@google.com";
+
+// A simple functor to invoke a callback with predefined arguments.
+class FakeBoolDBusMethod {
+ public:
+ FakeBoolDBusMethod(chromeos::DBusMethodCallStatus status, bool value)
+ : status_(status), value_(value) {}
+
+ void operator()(const chromeos::BoolDBusMethodCallback& callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, status_, value_));
+ }
+
+ private:
+ chromeos::DBusMethodCallStatus status_;
+ bool value_;
+};
+
+void RegisterKeyCallbackTrue(
+ chromeos::attestation::AttestationKeyType key_type,
+ const std::string& user_id,
+ const std::string& key_name,
+ const cryptohome::AsyncMethodCaller::Callback& callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, true, cryptohome::MOUNT_ERROR_NONE));
+}
+
+void RegisterKeyCallbackFalse(
+ chromeos::attestation::AttestationKeyType key_type,
+ const std::string& user_id,
+ const std::string& key_name,
+ const cryptohome::AsyncMethodCaller::Callback& callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, false, cryptohome::MOUNT_ERROR_NONE));
+}
+
+void SignChallengeCallbackTrue(
+ chromeos::attestation::AttestationKeyType key_type,
+ const std::string& user_id,
+ const std::string& key_name,
+ const std::string& domain,
+ const std::string& device_id,
+ chromeos::attestation::AttestationChallengeOptions options,
+ const std::string& challenge,
+ const cryptohome::AsyncMethodCaller::DataCallback& callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, true, "response"));
+}
+
+void SignChallengeCallbackFalse(
+ chromeos::attestation::AttestationKeyType key_type,
+ const std::string& user_id,
+ const std::string& key_name,
+ const std::string& domain,
+ const std::string& device_id,
+ chromeos::attestation::AttestationChallengeOptions options,
+ const std::string& challenge,
+ const cryptohome::AsyncMethodCaller::DataCallback& callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, false, ""));
+}
+
+void GetCertificateCallbackTrue(
+ chromeos::attestation::AttestationCertificateProfile certificate_profile,
+ const std::string& user_id,
+ const std::string& request_origin,
+ bool force_new_key,
+ const chromeos::attestation::AttestationFlow::CertificateCallback&
+ callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, true, "certificate"));
+}
+
+void GetCertificateCallbackFalse(
+ chromeos::attestation::AttestationCertificateProfile certificate_profile,
+ const std::string& user_id,
+ const std::string& request_origin,
+ bool force_new_key,
+ const chromeos::attestation::AttestationFlow::CertificateCallback&
+ callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, false, ""));
+}
+
+class EPKChallengeKeyTestBase : public BrowserWithTestWindowTest {
+ protected:
+ EPKChallengeKeyTestBase()
+ : settings_helper_(false),
+ extension_(test_util::CreateEmptyExtension()),
+ fake_user_manager_(new chromeos::FakeChromeUserManager),
+ user_manager_enabler_(fake_user_manager_) {
+ // Set up the default behavior of mocks.
+ ON_CALL(mock_cryptohome_client_, TpmAttestationDoesKeyExist(_, _, _, _))
+ .WillByDefault(WithArgs<3>(Invoke(
+ FakeBoolDBusMethod(chromeos::DBUS_METHOD_CALL_SUCCESS, false))));
+ ON_CALL(mock_cryptohome_client_, TpmAttestationIsPrepared(_))
+ .WillByDefault(Invoke(
+ FakeBoolDBusMethod(chromeos::DBUS_METHOD_CALL_SUCCESS, true)));
+ ON_CALL(mock_async_method_caller_, TpmAttestationRegisterKey(_, _, _, _))
+ .WillByDefault(Invoke(RegisterKeyCallbackTrue));
+ ON_CALL(mock_async_method_caller_,
+ TpmAttestationSignEnterpriseChallenge(_, _, _, _, _, _, _, _))
+ .WillByDefault(Invoke(SignChallengeCallbackTrue));
+ ON_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _))
+ .WillByDefault(Invoke(GetCertificateCallbackTrue));
+
+ // Set the Enterprise install attributes.
+ stub_install_attributes_.SetDomain("google.com");
+ stub_install_attributes_.SetRegistrationUser(kUserEmail);
+ stub_install_attributes_.SetDeviceId("device_id");
+ stub_install_attributes_.SetMode(policy::DEVICE_MODE_ENTERPRISE);
+
+ settings_helper_.ReplaceProvider(chromeos::kDeviceAttestationEnabled);
+ settings_helper_.SetBoolean(chromeos::kDeviceAttestationEnabled, true);
+ }
+
+ void SetUp() override {
+ BrowserWithTestWindowTest::SetUp();
+
+ // Set the user preferences.
+ prefs_ = browser()->profile()->GetPrefs();
+ base::ListValue whitelist;
+ whitelist.AppendString(extension_->id());
+ prefs_->Set(prefs::kAttestationExtensionWhitelist, whitelist);
+
+ SetAuthenticatedUser();
+ fake_user_manager_->AddUserWithAffiliation(
+ AccountId::FromUserEmail(kUserEmail), true);
+ }
+
+ // Derived classes can override this method to set the required authenticated
+ // user in the SigninManager class.
+ virtual void SetAuthenticatedUser() {
+ SigninManagerFactory::GetForProfile(browser()->profile())
+ ->SetAuthenticatedAccountInfo("12345", kUserEmail);
+ }
+
+ // Like extension_function_test_utils::RunFunctionAndReturnError but with an
+ // explicit ListValue.
+ std::string RunFunctionAndReturnError(UIThreadExtensionFunction* function,
+ scoped_ptr<base::ListValue> args,
+ Browser* browser) {
+ scoped_refptr<ExtensionFunction> function_owner(function);
+ // Without a callback the function will not generate a result.
+ function->set_has_callback(true);
+ utils::RunFunction(function, std::move(args), browser, utils::NONE);
+ EXPECT_FALSE(function->GetResultList()) << "Did not expect a result";
+ return function->GetError();
+ }
+
+ // Like extension_function_test_utils::RunFunctionAndReturnSingleResult but
+ // with an explicit ListValue.
+ base::Value* RunFunctionAndReturnSingleResult(
+ UIThreadExtensionFunction* function,
+ scoped_ptr<base::ListValue> args,
+ Browser* browser) {
+ scoped_refptr<ExtensionFunction> function_owner(function);
+ // Without a callback the function will not generate a result.
+ function->set_has_callback(true);
+ utils::RunFunction(function, std::move(args), browser, utils::NONE);
+ EXPECT_TRUE(function->GetError().empty()) << "Unexpected error: "
+ << function->GetError();
+ const base::Value* single_result = NULL;
+ if (function->GetResultList() != NULL &&
+ function->GetResultList()->Get(0, &single_result)) {
+ return single_result->DeepCopy();
+ }
+ return NULL;
+ }
+
+ NiceMock<chromeos::MockCryptohomeClient> mock_cryptohome_client_;
+ NiceMock<cryptohome::MockAsyncMethodCaller> mock_async_method_caller_;
+ NiceMock<chromeos::attestation::MockAttestationFlow> mock_attestation_flow_;
+ chromeos::ScopedCrosSettingsTestHelper settings_helper_;
+ scoped_refptr<extensions::Extension> extension_;
+ policy::StubEnterpriseInstallAttributes stub_install_attributes_;
+ PrefService* prefs_;
+ chromeos::FakeChromeUserManager* fake_user_manager_;
+ chromeos::ScopedUserManagerEnabler user_manager_enabler_;
+};
+
+class EPKChallengeMachineKeyTest : public EPKChallengeKeyTestBase {
+ protected:
+ EPKChallengeMachineKeyTest()
+ : impl_(&mock_cryptohome_client_,
+ &mock_async_method_caller_,
+ &mock_attestation_flow_,
+ &stub_install_attributes_),
+ func_(new EnterprisePlatformKeysChallengeMachineKeyFunction(&impl_)) {
+ func_->set_extension(extension_.get());
+ }
+
+ // Returns an error string for the given code.
+ std::string GetCertificateError(int error_code) {
+ return base::StringPrintf(
+ EPKPChallengeMachineKey::kGetCertificateFailedError, error_code);
+ }
+
+ scoped_ptr<base::ListValue> CreateArgs() {
+ scoped_ptr<base::ListValue> args(new base::ListValue);
+ args->Append(base::BinaryValue::CreateWithCopiedBuffer("challenge", 9));
+ return args;
+ }
+
+ EPKPChallengeMachineKey impl_;
+ scoped_refptr<EnterprisePlatformKeysChallengeMachineKeyFunction> func_;
+ base::ListValue args_;
+};
+
+TEST_F(EPKChallengeMachineKeyTest, NonEnterpriseDevice) {
+ stub_install_attributes_.SetRegistrationUser("");
+
+ EXPECT_EQ(EPKPChallengeMachineKey::kNonEnterpriseDeviceError,
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+TEST_F(EPKChallengeMachineKeyTest, ExtensionNotWhitelisted) {
+ base::ListValue empty_whitelist;
+ prefs_->Set(prefs::kAttestationExtensionWhitelist, empty_whitelist);
+
+ EXPECT_EQ(EPKPChallengeKeyBase::kExtensionNotWhitelistedError,
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+TEST_F(EPKChallengeMachineKeyTest, DevicePolicyDisabled) {
+ settings_helper_.SetBoolean(chromeos::kDeviceAttestationEnabled, false);
+
+ EXPECT_EQ(EPKPChallengeKeyBase::kDevicePolicyDisabledError,
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+TEST_F(EPKChallengeMachineKeyTest, DoesKeyExistDbusFailed) {
+ EXPECT_CALL(mock_cryptohome_client_, TpmAttestationDoesKeyExist(_, _, _, _))
+ .WillRepeatedly(WithArgs<3>(Invoke(
+ FakeBoolDBusMethod(chromeos::DBUS_METHOD_CALL_FAILURE, false))));
+
+ EXPECT_EQ(GetCertificateError(kDBusError),
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+TEST_F(EPKChallengeMachineKeyTest, GetCertificateFailed) {
+ EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _))
+ .WillRepeatedly(Invoke(GetCertificateCallbackFalse));
+
+ EXPECT_EQ(GetCertificateError(kGetCertificateFailed),
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+TEST_F(EPKChallengeMachineKeyTest, SignChallengeFailed) {
+ EXPECT_CALL(mock_async_method_caller_,
+ TpmAttestationSignEnterpriseChallenge(_, _, _, _, _, _, _, _))
+ .WillRepeatedly(Invoke(SignChallengeCallbackFalse));
+
+ EXPECT_EQ(EPKPChallengeKeyBase::kSignChallengeFailedError,
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+TEST_F(EPKChallengeMachineKeyTest, KeyExists) {
+ EXPECT_CALL(mock_cryptohome_client_, TpmAttestationDoesKeyExist(_, _, _, _))
+ .WillRepeatedly(WithArgs<3>(Invoke(
+ FakeBoolDBusMethod(chromeos::DBUS_METHOD_CALL_SUCCESS, true))));
+ // GetCertificate must not be called if the key exists.
+ EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _)).Times(0);
+
+ EXPECT_TRUE(
+ utils::RunFunction(func_.get(), CreateArgs(), browser(), utils::NONE));
+}
+
+TEST_F(EPKChallengeMachineKeyTest, Success) {
+ // GetCertificate must be called exactly once.
+ EXPECT_CALL(mock_attestation_flow_,
+ GetCertificate(
+ chromeos::attestation::PROFILE_ENTERPRISE_MACHINE_CERTIFICATE,
+ _, _, _, _))
+ .Times(1);
+ // SignEnterpriseChallenge must be called exactly once.
+ EXPECT_CALL(mock_async_method_caller_,
+ TpmAttestationSignEnterpriseChallenge(
+ chromeos::attestation::KEY_DEVICE, "", "attest-ent-machine",
+ "google.com", "device_id", _, "challenge", _))
+ .Times(1);
+
+ scoped_ptr<base::Value> value(
+ RunFunctionAndReturnSingleResult(func_.get(), CreateArgs(), browser()));
+
+ const base::BinaryValue* response;
+ ASSERT_TRUE(value->GetAsBinary(&response));
+ EXPECT_EQ("response",
+ std::string(response->GetBuffer(), response->GetSize()));
+}
+
+TEST_F(EPKChallengeMachineKeyTest, AttestationNotPrepared) {
+ EXPECT_CALL(mock_cryptohome_client_, TpmAttestationIsPrepared(_))
+ .WillRepeatedly(Invoke(
+ FakeBoolDBusMethod(chromeos::DBUS_METHOD_CALL_SUCCESS, false)));
+
+ EXPECT_EQ(GetCertificateError(kResetRequired),
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+TEST_F(EPKChallengeMachineKeyTest, AttestationPreparedDbusFailed) {
+ EXPECT_CALL(mock_cryptohome_client_, TpmAttestationIsPrepared(_))
+ .WillRepeatedly(
+ Invoke(FakeBoolDBusMethod(chromeos::DBUS_METHOD_CALL_FAILURE, true)));
+
+ EXPECT_EQ(GetCertificateError(kDBusError),
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+class EPKChallengeUserKeyTest : public EPKChallengeKeyTestBase {
+ protected:
+ EPKChallengeUserKeyTest()
+ : impl_(&mock_cryptohome_client_,
+ &mock_async_method_caller_,
+ &mock_attestation_flow_,
+ &stub_install_attributes_),
+ func_(new EnterprisePlatformKeysChallengeUserKeyFunction(&impl_)) {
+ func_->set_extension(extension_.get());
+ }
+
+ void SetUp() override {
+ EPKChallengeKeyTestBase::SetUp();
+
+ // Set the user preferences.
+ prefs_->SetBoolean(prefs::kAttestationEnabled, true);
+ }
+
+ // Returns an error string for the given code.
+ std::string GetCertificateError(int error_code) {
+ return base::StringPrintf(EPKPChallengeUserKey::kGetCertificateFailedError,
+ error_code);
+ }
+
+ scoped_ptr<base::ListValue> CreateArgs() { return CreateArgsInternal(true); }
+
+ scoped_ptr<base::ListValue> CreateArgsNoRegister() {
+ return CreateArgsInternal(false);
+ }
+
+ scoped_ptr<base::ListValue> CreateArgsInternal(bool register_key) {
+ scoped_ptr<base::ListValue> args(new base::ListValue);
+ args->Append(base::BinaryValue::CreateWithCopiedBuffer("challenge", 9));
+ args->Append(new base::FundamentalValue(register_key));
+ return args;
+ }
+
+ EPKPChallengeUserKey impl_;
+ scoped_refptr<EnterprisePlatformKeysChallengeUserKeyFunction> func_;
+};
+
+TEST_F(EPKChallengeUserKeyTest, UserPolicyDisabled) {
+ prefs_->SetBoolean(prefs::kAttestationEnabled, false);
+
+ EXPECT_EQ(EPKPChallengeUserKey::kUserPolicyDisabledError,
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+TEST_F(EPKChallengeUserKeyTest, ExtensionNotWhitelisted) {
+ base::ListValue empty_whitelist;
+ prefs_->Set(prefs::kAttestationExtensionWhitelist, empty_whitelist);
+
+ EXPECT_EQ(EPKPChallengeKeyBase::kExtensionNotWhitelistedError,
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+TEST_F(EPKChallengeUserKeyTest, DevicePolicyDisabled) {
+ settings_helper_.SetBoolean(chromeos::kDeviceAttestationEnabled, false);
+
+ EXPECT_EQ(EPKPChallengeKeyBase::kDevicePolicyDisabledError,
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+TEST_F(EPKChallengeUserKeyTest, DoesKeyExistDbusFailed) {
+ EXPECT_CALL(mock_cryptohome_client_, TpmAttestationDoesKeyExist(_, _, _, _))
+ .WillRepeatedly(WithArgs<3>(Invoke(
+ FakeBoolDBusMethod(chromeos::DBUS_METHOD_CALL_FAILURE, false))));
+
+ EXPECT_EQ(GetCertificateError(kDBusError),
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+TEST_F(EPKChallengeUserKeyTest, GetCertificateFailed) {
+ EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _))
+ .WillRepeatedly(Invoke(GetCertificateCallbackFalse));
+
+ EXPECT_EQ(GetCertificateError(kGetCertificateFailed),
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+TEST_F(EPKChallengeUserKeyTest, SignChallengeFailed) {
+ EXPECT_CALL(mock_async_method_caller_,
+ TpmAttestationSignEnterpriseChallenge(_, _, _, _, _, _, _, _))
+ .WillRepeatedly(Invoke(SignChallengeCallbackFalse));
+
+ EXPECT_EQ(EPKPChallengeKeyBase::kSignChallengeFailedError,
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+TEST_F(EPKChallengeUserKeyTest, KeyRegistrationFailed) {
+ EXPECT_CALL(mock_async_method_caller_, TpmAttestationRegisterKey(_, _, _, _))
+ .WillRepeatedly(Invoke(RegisterKeyCallbackFalse));
+
+ EXPECT_EQ(EPKPChallengeUserKey::kKeyRegistrationFailedError,
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+TEST_F(EPKChallengeUserKeyTest, KeyExists) {
+ EXPECT_CALL(mock_cryptohome_client_, TpmAttestationDoesKeyExist(_, _, _, _))
+ .WillRepeatedly(WithArgs<3>(Invoke(
+ FakeBoolDBusMethod(chromeos::DBUS_METHOD_CALL_SUCCESS, true))));
+ // GetCertificate must not be called if the key exists.
+ EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _)).Times(0);
+
+ EXPECT_TRUE(
+ utils::RunFunction(func_.get(), CreateArgs(), browser(), utils::NONE));
+}
+
+TEST_F(EPKChallengeUserKeyTest, KeyNotRegistered) {
+ EXPECT_CALL(mock_async_method_caller_, TpmAttestationRegisterKey(_, _, _, _))
+ .Times(0);
+
+ EXPECT_TRUE(utils::RunFunction(func_.get(), CreateArgsNoRegister(), browser(),
+ utils::NONE));
+}
+
+TEST_F(EPKChallengeUserKeyTest, PersonalDevice) {
+ stub_install_attributes_.SetRegistrationUser("");
+
+ // Currently personal devices are not supported.
+ EXPECT_EQ(GetCertificateError(kUserRejected),
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+TEST_F(EPKChallengeUserKeyTest, Success) {
+ // GetCertificate must be called exactly once.
+ EXPECT_CALL(
+ mock_attestation_flow_,
+ GetCertificate(chromeos::attestation::PROFILE_ENTERPRISE_USER_CERTIFICATE,
+ _, _, _, _))
+ .Times(1);
+ // SignEnterpriseChallenge must be called exactly once.
+ EXPECT_CALL(
+ mock_async_method_caller_,
+ TpmAttestationSignEnterpriseChallenge(
+ chromeos::attestation::KEY_USER, kUserEmail, "attest-ent-user",
+ kUserEmail, "device_id", _, "challenge", _))
+ .Times(1);
+ // RegisterKey must be called exactly once.
+ EXPECT_CALL(mock_async_method_caller_,
+ TpmAttestationRegisterKey(chromeos::attestation::KEY_USER,
+ kUserEmail, "attest-ent-user", _))
+ .Times(1);
+
+ scoped_ptr<base::Value> value(
+ RunFunctionAndReturnSingleResult(func_.get(), CreateArgs(), browser()));
+
+ const base::BinaryValue* response;
+ ASSERT_TRUE(value->GetAsBinary(&response));
+ EXPECT_EQ("response",
+ std::string(response->GetBuffer(), response->GetSize()));
+}
+
+TEST_F(EPKChallengeUserKeyTest, AttestationNotPrepared) {
+ EXPECT_CALL(mock_cryptohome_client_, TpmAttestationIsPrepared(_))
+ .WillRepeatedly(Invoke(
+ FakeBoolDBusMethod(chromeos::DBUS_METHOD_CALL_SUCCESS, false)));
+
+ EXPECT_EQ(GetCertificateError(kResetRequired),
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+TEST_F(EPKChallengeUserKeyTest, AttestationPreparedDbusFailed) {
+ EXPECT_CALL(mock_cryptohome_client_, TpmAttestationIsPrepared(_))
+ .WillRepeatedly(
+ Invoke(FakeBoolDBusMethod(chromeos::DBUS_METHOD_CALL_FAILURE, true)));
+
+ EXPECT_EQ(GetCertificateError(kDBusError),
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+class EPKChallengeMachineKeyUnmanagedUserTest
+ : public EPKChallengeMachineKeyTest {
+ protected:
+ void SetAuthenticatedUser() override {
+ SigninManagerFactory::GetForProfile(browser()->profile())
+ ->SetAuthenticatedAccountInfo("12345", "test@chromium.com");
+ }
+};
+
+TEST_F(EPKChallengeMachineKeyUnmanagedUserTest, UserNotManaged) {
+ EXPECT_EQ(EPKPChallengeKeyBase::kUserNotManaged,
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+class EPKChallengeUserKeyUnmanagedUserTest : public EPKChallengeUserKeyTest {
+ protected:
+ void SetAuthenticatedUser() override {
+ SigninManagerFactory::GetForProfile(browser()->profile())
+ ->SetAuthenticatedAccountInfo("12345", "test@chromium.com");
+ }
+};
+
+TEST_F(EPKChallengeUserKeyUnmanagedUserTest, UserNotManaged) {
+ EXPECT_EQ(EPKPChallengeKeyBase::kUserNotManaged,
+ RunFunctionAndReturnError(func_.get(), CreateArgs(), browser()));
+}
+
+} // namespace
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
index 99c6f40..2d95cd0a 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
+++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
@@ -17,6 +17,7 @@
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
+#include "chrome/browser/extensions/chrome_extension_function_details.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/common/extensions/api/enterprise_platform_keys_private.h"
@@ -107,8 +108,8 @@ void EPKPChallengeKeyBase::GetDeviceAttestationEnabled(
chromeos::CrosSettings* settings = chromeos::CrosSettings::Get();
chromeos::CrosSettingsProvider::TrustedStatus status =
settings->PrepareTrustedValues(
- base::Bind(&EPKPChallengeKeyBase::GetDeviceAttestationEnabled, this,
- callback));
+ base::Bind(&EPKPChallengeKeyBase::GetDeviceAttestationEnabled,
+ base::Unretained(this), callback));
bool value = false;
switch (status) {
@@ -135,8 +136,8 @@ bool EPKPChallengeKeyBase::IsEnterpriseDevice() const {
bool EPKPChallengeKeyBase::IsExtensionWhitelisted() const {
const base::ListValue* list =
- GetProfile()->GetPrefs()->GetList(prefs::kAttestationExtensionWhitelist);
- base::StringValue value(extension_->id());
+ profile_->GetPrefs()->GetList(prefs::kAttestationExtensionWhitelist);
+ base::StringValue value(extension_id_);
return list->Find(value) != list->end();
}
@@ -164,7 +165,7 @@ std::string EPKPChallengeKeyBase::GetEnterpriseDomain() const {
std::string EPKPChallengeKeyBase::GetUserEmail() const {
SigninManagerBase* signin_manager =
- SigninManagerFactory::GetForProfile(GetProfile());
+ SigninManagerFactory::GetForProfile(profile_);
if (!signin_manager)
return std::string();
@@ -189,8 +190,9 @@ void EPKPChallengeKeyBase::PrepareKey(
certificate_profile,
require_user_consent,
callback);
- cryptohome_client_->TpmAttestationIsPrepared(base::Bind(
- &EPKPChallengeKeyBase::IsAttestationPreparedCallback, this, context));
+ cryptohome_client_->TpmAttestationIsPrepared(
+ base::Bind(&EPKPChallengeKeyBase::IsAttestationPreparedCallback,
+ base::Unretained(this), context));
}
void EPKPChallengeKeyBase::IsAttestationPreparedCallback(
@@ -207,8 +209,9 @@ void EPKPChallengeKeyBase::IsAttestationPreparedCallback(
}
// Attestation is available, see if the key we need already exists.
cryptohome_client_->TpmAttestationDoesKeyExist(
- context.key_type, context.user_id, context.key_name, base::Bind(
- &EPKPChallengeKeyBase::DoesKeyExistCallback, this, context));
+ context.key_type, context.user_id, context.key_name,
+ base::Bind(&EPKPChallengeKeyBase::DoesKeyExistCallback,
+ base::Unretained(this), context));
}
void EPKPChallengeKeyBase::DoesKeyExistCallback(
@@ -229,8 +232,8 @@ void EPKPChallengeKeyBase::DoesKeyExistCallback(
// We should ask the user explicitly before sending any private
// information to PCA.
AskForUserConsent(
- base::Bind(&EPKPChallengeKeyBase::AskForUserConsentCallback, this,
- context));
+ base::Bind(&EPKPChallengeKeyBase::AskForUserConsentCallback,
+ base::Unretained(this), context));
} else {
// User consent is not required. Skip to the next step.
AskForUserConsentCallback(context, true);
@@ -256,12 +259,11 @@ void EPKPChallengeKeyBase::AskForUserConsentCallback(
// Generate a new key and have it signed by PCA.
attestation_flow_->GetCertificate(
- context.certificate_profile,
- context.user_id,
+ context.certificate_profile, context.user_id,
std::string(), // Not used.
- true, // Force a new key to be generated.
- base::Bind(&EPKPChallengeKeyBase::GetCertificateCallback, this,
- context.callback));
+ true, // Force a new key to be generated.
+ base::Bind(&EPKPChallengeKeyBase::GetCertificateCallback,
+ base::Unretained(this), context.callback));
}
void EPKPChallengeKeyBase::GetCertificateCallback(
@@ -302,48 +304,54 @@ EPKPChallengeMachineKey::EPKPChallengeMachineKey(
EPKPChallengeMachineKey::~EPKPChallengeMachineKey() {
}
-bool EPKPChallengeMachineKey::RunAsync() {
- scoped_ptr<api_epkp::ChallengeMachineKey::Params>
- params(api_epkp::ChallengeMachineKey::Params::Create(*args_));
- EXTENSION_FUNCTION_VALIDATE(params.get());
-
- std::string challenge;
- if (!base::Base64Decode(params->challenge, &challenge)) {
- SetError(kChallengeBadBase64Error);
- return false;
- }
+void EPKPChallengeMachineKey::Run(
+ scoped_refptr<UIThreadExtensionFunction> caller,
+ const ChallengeKeyCallback& callback,
+ const std::string& challenge) {
+ callback_ = callback;
+ profile_ = ChromeExtensionFunctionDetails(caller.get()).GetProfile();
+ extension_id_ = caller->extension_id();
// Check if the device is enterprise enrolled.
if (!IsEnterpriseDevice()) {
- SetError(kNonEnterpriseDeviceError);
- return false;
+ callback_.Run(false, kNonEnterpriseDeviceError);
+ return;
}
// Check if the extension is whitelisted in the user policy.
if (!IsExtensionWhitelisted()) {
- SetError(kExtensionNotWhitelistedError);
- return false;
+ callback_.Run(false, kExtensionNotWhitelistedError);
+ return;
}
// Check if the user domain is the same as the enrolled enterprise domain.
if (!IsUserManaged()) {
- SetError(kUserNotManaged);
- return false;
+ callback_.Run(false, kUserNotManaged);
+ return;
}
// Check if RA is enabled in the device policy.
GetDeviceAttestationEnabled(
base::Bind(&EPKPChallengeMachineKey::GetDeviceAttestationEnabledCallback,
- this, challenge));
+ base::Unretained(this), challenge));
+}
- return true;
+void EPKPChallengeMachineKey::DecodeAndRun(
+ scoped_refptr<UIThreadExtensionFunction> caller,
+ const ChallengeKeyCallback& callback,
+ const std::string& encoded_challenge) {
+ std::string challenge;
+ if (!base::Base64Decode(encoded_challenge, &challenge)) {
+ callback.Run(false, kChallengeBadBase64Error);
+ return;
+ }
+ Run(caller, callback, challenge);
}
void EPKPChallengeMachineKey::GetDeviceAttestationEnabledCallback(
const std::string& challenge, bool enabled) {
if (!enabled) {
- SetError(kDevicePolicyDisabledError);
- SendResponse(false);
+ callback_.Run(false, kDevicePolicyDisabledError);
return;
}
@@ -352,15 +360,15 @@ void EPKPChallengeMachineKey::GetDeviceAttestationEnabledCallback(
kKeyName,
chromeos::attestation::PROFILE_ENTERPRISE_MACHINE_CERTIFICATE,
false, // user consent is not required.
- base::Bind(&EPKPChallengeMachineKey::PrepareKeyCallback, this,
- challenge));
+ base::Bind(&EPKPChallengeMachineKey::PrepareKeyCallback,
+ base::Unretained(this), challenge));
}
void EPKPChallengeMachineKey::PrepareKeyCallback(
const std::string& challenge, PrepareKeyResult result) {
if (result != PREPARE_KEY_OK) {
- SetError(base::StringPrintf(kGetCertificateFailedError, result));
- SendResponse(false);
+ callback_.Run(false,
+ base::StringPrintf(kGetCertificateFailedError, result));
return;
}
@@ -368,27 +376,19 @@ void EPKPChallengeMachineKey::PrepareKeyCallback(
async_caller_->TpmAttestationSignEnterpriseChallenge(
chromeos::attestation::KEY_DEVICE,
std::string(), // Not used.
- kKeyName,
- GetEnterpriseDomain(),
- GetDeviceId(),
- chromeos::attestation::CHALLENGE_OPTION_NONE,
- challenge,
- base::Bind(&EPKPChallengeMachineKey::SignChallengeCallback, this));
+ kKeyName, GetEnterpriseDomain(), GetDeviceId(),
+ chromeos::attestation::CHALLENGE_OPTION_NONE, challenge,
+ base::Bind(&EPKPChallengeMachineKey::SignChallengeCallback,
+ base::Unretained(this)));
}
void EPKPChallengeMachineKey::SignChallengeCallback(
bool success, const std::string& response) {
if (!success) {
- SetError(kSignChallengeFailedError);
- SendResponse(false);
+ callback_.Run(false, kSignChallengeFailedError);
return;
}
-
- std::string encoded_response;
- base::Base64Encode(response, &encoded_response);
-
- results_ = api_epkp::ChallengeMachineKey::Results::Create(encoded_response);
- SendResponse(true);
+ callback_.Run(true, response);
}
// Implementation of ChallengeUserKey()
@@ -425,54 +425,58 @@ void EPKPChallengeUserKey::RegisterProfilePrefs(
registry->RegisterListPref(prefs::kAttestationExtensionWhitelist);
}
-bool EPKPChallengeUserKey::RunAsync() {
- scoped_ptr<api_epkp::ChallengeUserKey::Params> params(
- api_epkp::ChallengeUserKey::Params::Create(*args_));
- EXTENSION_FUNCTION_VALIDATE(params.get());
-
- std::string challenge;
- if (!base::Base64Decode(params->challenge, &challenge)) {
- SetError(kChallengeBadBase64Error);
- return false;
- }
+void EPKPChallengeUserKey::Run(scoped_refptr<UIThreadExtensionFunction> caller,
+ const ChallengeKeyCallback& callback,
+ const std::string& challenge,
+ bool register_key) {
+ callback_ = callback;
+ profile_ = ChromeExtensionFunctionDetails(caller.get()).GetProfile();
+ extension_id_ = caller->extension_id();
// Check if RA is enabled in the user policy.
if (!IsRemoteAttestationEnabledForUser()) {
- SetError(kUserPolicyDisabledError);
- return false;
+ callback_.Run(false, kUserPolicyDisabledError);
+ return;
}
// Check if the extension is whitelisted in the user policy.
if (!IsExtensionWhitelisted()) {
- SetError(kExtensionNotWhitelistedError);
- return false;
+ callback_.Run(false, kExtensionNotWhitelistedError);
+ return;
}
if (IsEnterpriseDevice()) {
// Check if the user domain is the same as the enrolled enterprise domain.
if (!IsUserManaged()) {
- SetError(kUserNotManaged);
- return false;
+ callback_.Run(false, kUserNotManaged);
+ return;
}
// Check if RA is enabled in the device policy.
GetDeviceAttestationEnabled(
base::Bind(&EPKPChallengeUserKey::GetDeviceAttestationEnabledCallback,
- this,
- challenge,
- params->register_key,
+ base::Unretained(this), challenge, register_key,
false)); // user consent is not required.
} else {
// For personal devices, we don't need to check if RA is enabled in the
// device, but we need to ask for user consent if the key does not exist.
- GetDeviceAttestationEnabledCallback(
- challenge,
- params->register_key,
- true, // user consent is required.
- true); // attestation is enabled.
+ GetDeviceAttestationEnabledCallback(challenge, register_key,
+ true, // user consent is required.
+ true); // attestation is enabled.
}
+}
- return true;
+void EPKPChallengeUserKey::DecodeAndRun(
+ scoped_refptr<UIThreadExtensionFunction> caller,
+ const ChallengeKeyCallback& callback,
+ const std::string& encoded_challenge,
+ bool register_key) {
+ std::string challenge;
+ if (!base::Base64Decode(encoded_challenge, &challenge)) {
+ callback.Run(false, kChallengeBadBase64Error);
+ return;
+ }
+ Run(caller, callback, challenge, register_key);
}
void EPKPChallengeUserKey::GetDeviceAttestationEnabledCallback(
@@ -481,59 +485,49 @@ void EPKPChallengeUserKey::GetDeviceAttestationEnabledCallback(
bool require_user_consent,
bool enabled) {
if (!enabled) {
- SetError(kDevicePolicyDisabledError);
- SendResponse(false);
+ callback_.Run(false, kDevicePolicyDisabledError);
return;
}
- PrepareKey(chromeos::attestation::KEY_USER,
- GetUserEmail(),
- kKeyName,
+ PrepareKey(chromeos::attestation::KEY_USER, GetUserEmail(), kKeyName,
chromeos::attestation::PROFILE_ENTERPRISE_USER_CERTIFICATE,
require_user_consent,
- base::Bind(&EPKPChallengeUserKey::PrepareKeyCallback, this,
- challenge, register_key));
+ base::Bind(&EPKPChallengeUserKey::PrepareKeyCallback,
+ base::Unretained(this), challenge, register_key));
}
void EPKPChallengeUserKey::PrepareKeyCallback(const std::string& challenge,
bool register_key,
PrepareKeyResult result) {
if (result != PREPARE_KEY_OK) {
- SetError(base::StringPrintf(kGetCertificateFailedError, result));
- SendResponse(false);
+ callback_.Run(false,
+ base::StringPrintf(kGetCertificateFailedError, result));
return;
}
// Everything is checked. Sign the challenge.
async_caller_->TpmAttestationSignEnterpriseChallenge(
- chromeos::attestation::KEY_USER,
- GetUserEmail(),
- kKeyName,
- GetUserEmail(),
+ chromeos::attestation::KEY_USER, GetUserEmail(), kKeyName, GetUserEmail(),
GetDeviceId(),
- register_key ?
- chromeos::attestation::CHALLENGE_INCLUDE_SIGNED_PUBLIC_KEY :
- chromeos::attestation::CHALLENGE_OPTION_NONE,
- challenge,
- base::Bind(&EPKPChallengeUserKey::SignChallengeCallback, this,
- register_key));
+ register_key ? chromeos::attestation::CHALLENGE_INCLUDE_SIGNED_PUBLIC_KEY
+ : chromeos::attestation::CHALLENGE_OPTION_NONE,
+ challenge, base::Bind(&EPKPChallengeUserKey::SignChallengeCallback,
+ base::Unretained(this), register_key));
}
void EPKPChallengeUserKey::SignChallengeCallback(bool register_key,
bool success,
const std::string& response) {
if (!success) {
- SetError(kSignChallengeFailedError);
- SendResponse(false);
+ callback_.Run(false, kSignChallengeFailedError);
return;
}
if (register_key) {
async_caller_->TpmAttestationRegisterKey(
- chromeos::attestation::KEY_USER,
- GetUserEmail(),
- kKeyName,
- base::Bind(&EPKPChallengeUserKey::RegisterKeyCallback, this, response));
+ chromeos::attestation::KEY_USER, GetUserEmail(), kKeyName,
+ base::Bind(&EPKPChallengeUserKey::RegisterKeyCallback,
+ base::Unretained(this), response));
} else {
RegisterKeyCallback(response, true, cryptohome::MOUNT_ERROR_NONE);
}
@@ -544,20 +538,101 @@ void EPKPChallengeUserKey::RegisterKeyCallback(
bool success,
cryptohome::MountError return_code) {
if (!success || return_code != cryptohome::MOUNT_ERROR_NONE) {
- SetError(kKeyRegistrationFailedError);
- SendResponse(false);
+ callback_.Run(false, kKeyRegistrationFailedError);
return;
}
-
- std::string encoded_response;
- base::Base64Encode(response, &encoded_response);
-
- results_ = api_epkp::ChallengeUserKey::Results::Create(encoded_response);
- SendResponse(true);
+ callback_.Run(true, response);
}
bool EPKPChallengeUserKey::IsRemoteAttestationEnabledForUser() const {
- return GetProfile()->GetPrefs()->GetBoolean(prefs::kAttestationEnabled);
+ return profile_->GetPrefs()->GetBoolean(prefs::kAttestationEnabled);
+}
+
+EnterprisePlatformKeysPrivateChallengeMachineKeyFunction::
+ EnterprisePlatformKeysPrivateChallengeMachineKeyFunction()
+ : default_impl_(new EPKPChallengeMachineKey), impl_(default_impl_.get()) {}
+
+EnterprisePlatformKeysPrivateChallengeMachineKeyFunction::
+ EnterprisePlatformKeysPrivateChallengeMachineKeyFunction(
+ EPKPChallengeMachineKey* impl_for_testing)
+ : impl_(impl_for_testing) {}
+
+EnterprisePlatformKeysPrivateChallengeMachineKeyFunction::
+ ~EnterprisePlatformKeysPrivateChallengeMachineKeyFunction() = default;
+
+ExtensionFunction::ResponseAction
+EnterprisePlatformKeysPrivateChallengeMachineKeyFunction::Run() {
+ scoped_ptr<api_epkp::ChallengeMachineKey::Params> params(
+ api_epkp::ChallengeMachineKey::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
+ ChallengeKeyCallback callback =
+ base::Bind(&EnterprisePlatformKeysPrivateChallengeMachineKeyFunction::
+ OnChallengedKey,
+ this);
+ // base::Unretained is safe on impl_ since its life-cycle matches |this| and
+ // |callback| holds a reference to |this|.
+ base::Closure task = base::Bind(
+ &EPKPChallengeMachineKey::DecodeAndRun, base::Unretained(impl_),
+ scoped_refptr<UIThreadExtensionFunction>(AsUIThreadExtensionFunction()),
+ callback, params->challenge);
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, task);
+ return RespondLater();
+}
+
+void EnterprisePlatformKeysPrivateChallengeMachineKeyFunction::OnChallengedKey(
+ bool success,
+ const std::string& data) {
+ if (success) {
+ std::string encoded_response;
+ base::Base64Encode(data, &encoded_response);
+ Respond(ArgumentList(
+ api_epkp::ChallengeMachineKey::Results::Create(encoded_response)));
+ } else {
+ Respond(Error(data));
+ }
+}
+
+EnterprisePlatformKeysPrivateChallengeUserKeyFunction::
+ EnterprisePlatformKeysPrivateChallengeUserKeyFunction()
+ : default_impl_(new EPKPChallengeUserKey), impl_(default_impl_.get()) {}
+
+EnterprisePlatformKeysPrivateChallengeUserKeyFunction::
+ EnterprisePlatformKeysPrivateChallengeUserKeyFunction(
+ EPKPChallengeUserKey* impl_for_testing)
+ : impl_(impl_for_testing) {}
+
+EnterprisePlatformKeysPrivateChallengeUserKeyFunction::
+ ~EnterprisePlatformKeysPrivateChallengeUserKeyFunction() = default;
+
+ExtensionFunction::ResponseAction
+EnterprisePlatformKeysPrivateChallengeUserKeyFunction::Run() {
+ scoped_ptr<api_epkp::ChallengeUserKey::Params> params(
+ api_epkp::ChallengeUserKey::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params);
+ ChallengeKeyCallback callback = base::Bind(
+ &EnterprisePlatformKeysPrivateChallengeUserKeyFunction::OnChallengedKey,
+ this);
+ // base::Unretained is safe on impl_ since its life-cycle matches |this| and
+ // |callback| holds a reference to |this|.
+ base::Closure task = base::Bind(
+ &EPKPChallengeUserKey::DecodeAndRun, base::Unretained(impl_),
+ scoped_refptr<UIThreadExtensionFunction>(AsUIThreadExtensionFunction()),
+ callback, params->challenge, params->register_key);
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, task);
+ return RespondLater();
+}
+
+void EnterprisePlatformKeysPrivateChallengeUserKeyFunction::OnChallengedKey(
+ bool success,
+ const std::string& data) {
+ if (success) {
+ std::string encoded_response;
+ base::Base64Encode(data, &encoded_response);
+ Respond(ArgumentList(
+ api_epkp::ChallengeUserKey::Results::Create(encoded_response)));
+ } else {
+ Respond(Error(data));
+ }
}
} // namespace extensions
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h
index 49f334f..19f201b 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h
+++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// TODO(dkrahn): Clean up this private API once all clients have been migrated
+// to use the public API. crbug.com/588339.
+
#ifndef CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_PLATFORM_KEYS_PRIVATE_ENTERPRISE_PLATFORM_KEYS_PRIVATE_API_H__
#define CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_PLATFORM_KEYS_PRIVATE_ENTERPRISE_PLATFORM_KEYS_PRIVATE_API_H__
@@ -10,15 +13,16 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/common/extensions/api/enterprise_platform_keys_private.h"
#include "chromeos/attestation/attestation_constants.h"
#include "chromeos/attestation/attestation_flow.h"
#include "chromeos/dbus/cryptohome_client.h"
#include "chromeos/dbus/dbus_method_call_status.h"
+#include "extensions/browser/extension_function.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
class PrefService;
+class Profile;
namespace chromeos {
class CryptohomeClient;
@@ -38,7 +42,13 @@ class PrefRegistrySyncable;
namespace extensions {
-class EPKPChallengeKeyBase : public ChromeAsyncExtensionFunction {
+// A callback for challenge key operations. If the operation succeeded,
+// |success| is true and |data| is the challenge response. Otherwise, |success|
+// is false and |data| is an error message.
+using ChallengeKeyCallback =
+ base::Callback<void(bool success, const std::string& data)>;
+
+class EPKPChallengeKeyBase {
public:
static const char kChallengeBadBase64Error[];
static const char kDevicePolicyDisabledError[];
@@ -62,7 +72,7 @@ class EPKPChallengeKeyBase : public ChromeAsyncExtensionFunction {
cryptohome::AsyncMethodCaller* async_caller,
chromeos::attestation::AttestationFlow* attestation_flow,
policy::EnterpriseInstallAttributes* install_attributes);
- ~EPKPChallengeKeyBase() override;
+ virtual ~EPKPChallengeKeyBase();
// Returns a trusted value from CroSettings indicating if the device
// attestation is enabled.
@@ -103,6 +113,9 @@ class EPKPChallengeKeyBase : public ChromeAsyncExtensionFunction {
cryptohome::AsyncMethodCaller* async_caller_;
chromeos::attestation::AttestationFlow* attestation_flow_;
scoped_ptr<chromeos::attestation::AttestationFlow> default_attestation_flow_;
+ ChallengeKeyCallback callback_;
+ Profile* profile_;
+ std::string extension_id_;
private:
// Holds the context of a PrepareKey() operation.
@@ -156,29 +169,29 @@ class EPKPChallengeMachineKey : public EPKPChallengeKeyBase {
cryptohome::AsyncMethodCaller* async_caller,
chromeos::attestation::AttestationFlow* attestation_flow,
policy::EnterpriseInstallAttributes* install_attributes);
+ ~EPKPChallengeMachineKey() override;
- protected:
- bool RunAsync() override;
+ // Asynchronously run the flow to challenge a machine key in the |caller|
+ // context.
+ void Run(scoped_refptr<UIThreadExtensionFunction> caller,
+ const ChallengeKeyCallback& callback,
+ const std::string& encoded_challenge);
+
+ // Like |Run| but expects a Base64 |encoded_challenge|.
+ void DecodeAndRun(scoped_refptr<UIThreadExtensionFunction> caller,
+ const ChallengeKeyCallback& callback,
+ const std::string& encoded_challenge);
private:
static const char kKeyName[];
- ~EPKPChallengeMachineKey() override;
-
void GetDeviceAttestationEnabledCallback(const std::string& challenge,
bool enabled);
void PrepareKeyCallback(const std::string& challenge,
PrepareKeyResult result);
void SignChallengeCallback(bool success, const std::string& response);
-
- DECLARE_EXTENSION_FUNCTION(
- "enterprise.platformKeysPrivate.challengeMachineKey",
- ENTERPRISE_PLATFORMKEYSPRIVATE_CHALLENGEMACHINEKEY);
};
-typedef EPKPChallengeMachineKey
- EnterprisePlatformKeysPrivateChallengeMachineKeyFunction;
-
class EPKPChallengeUserKey : public EPKPChallengeKeyBase {
public:
static const char kGetCertificateFailedError[];
@@ -191,17 +204,26 @@ class EPKPChallengeUserKey : public EPKPChallengeKeyBase {
cryptohome::AsyncMethodCaller* async_caller,
chromeos::attestation::AttestationFlow* attestation_flow,
policy::EnterpriseInstallAttributes* install_attributes);
+ ~EPKPChallengeUserKey() override;
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
- protected:
- bool RunAsync() override;
+ // Asynchronously run the flow to challenge a user key in the |caller|
+ // context.
+ void Run(scoped_refptr<UIThreadExtensionFunction> caller,
+ const ChallengeKeyCallback& callback,
+ const std::string& challenge,
+ bool register_key);
+
+ // Like |Run| but expects a Base64 |encoded_challenge|.
+ void DecodeAndRun(scoped_refptr<UIThreadExtensionFunction> caller,
+ const ChallengeKeyCallback& callback,
+ const std::string& encoded_challenge,
+ bool register_key);
private:
static const char kKeyName[];
- ~EPKPChallengeUserKey() override;
-
void GetDeviceAttestationEnabledCallback(const std::string& challenge,
bool register_key,
bool require_user_consent,
@@ -217,15 +239,56 @@ class EPKPChallengeUserKey : public EPKPChallengeKeyBase {
cryptohome::MountError return_code);
bool IsRemoteAttestationEnabledForUser() const;
+};
+
+class EnterprisePlatformKeysPrivateChallengeMachineKeyFunction
+ : public UIThreadExtensionFunction {
+ public:
+ EnterprisePlatformKeysPrivateChallengeMachineKeyFunction();
+ explicit EnterprisePlatformKeysPrivateChallengeMachineKeyFunction(
+ EPKPChallengeMachineKey* impl_for_testing);
+
+ private:
+ ~EnterprisePlatformKeysPrivateChallengeMachineKeyFunction() override;
+ ResponseAction Run() override;
+
+ // Called when the challenge operation is complete. If the operation succeeded
+ // |success| will be true and |data| will contain the challenge response data.
+ // Otherwise |success| will be false and |data| is an error message.
+ void OnChallengedKey(bool success, const std::string& data);
+
+ scoped_ptr<EPKPChallengeMachineKey> default_impl_;
+ EPKPChallengeMachineKey* impl_;
+
+ DECLARE_EXTENSION_FUNCTION(
+ "enterprise.platformKeysPrivate.challengeMachineKey",
+ ENTERPRISE_PLATFORMKEYSPRIVATE_CHALLENGEMACHINEKEY);
+};
+
+class EnterprisePlatformKeysPrivateChallengeUserKeyFunction
+ : public UIThreadExtensionFunction {
+ public:
+ EnterprisePlatformKeysPrivateChallengeUserKeyFunction();
+ explicit EnterprisePlatformKeysPrivateChallengeUserKeyFunction(
+ EPKPChallengeUserKey* impl_for_testing);
+
+ private:
+ ~EnterprisePlatformKeysPrivateChallengeUserKeyFunction() override;
+ ResponseAction Run() override;
+
+ // Called when the challenge operation is complete. If the operation succeeded
+ // |success| will be true and |data| will contain the challenge response data.
+ // Otherwise |success| will be false and |data| is an error message.
+ void OnChallengedKey(bool success, const std::string& data);
+
+ scoped_ptr<EPKPChallengeUserKey> default_impl_;
+ EPKPChallengeUserKey* impl_;
DECLARE_EXTENSION_FUNCTION(
"enterprise.platformKeysPrivate.challengeUserKey",
ENTERPRISE_PLATFORMKEYSPRIVATE_CHALLENGEUSERKEY);
};
-typedef EPKPChallengeUserKey
- EnterprisePlatformKeysPrivateChallengeUserKeyFunction;
-
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_PLATFORM_KEYS_PRIVATE_ENTERPRISE_PLATFORM_KEYS_PRIVATE_API_H__
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
index 5219c16..4867a5e 100644
--- a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
@@ -212,10 +212,12 @@ class EPKPChallengeMachineKeyTest : public EPKPChallengeKeyTestBase {
static const char kArgs[];
EPKPChallengeMachineKeyTest()
- : func_(new EPKPChallengeMachineKey(&mock_cryptohome_client_,
- &mock_async_method_caller_,
- &mock_attestation_flow_,
- &stub_install_attributes_)) {
+ : impl_(&mock_cryptohome_client_,
+ &mock_async_method_caller_,
+ &mock_attestation_flow_,
+ &stub_install_attributes_),
+ func_(new EnterprisePlatformKeysPrivateChallengeMachineKeyFunction(
+ &impl_)) {
func_->set_extension(extension_.get());
}
@@ -226,7 +228,8 @@ class EPKPChallengeMachineKeyTest : public EPKPChallengeKeyTestBase {
error_code);
}
- scoped_refptr<EPKPChallengeMachineKey> func_;
+ EPKPChallengeMachineKey impl_;
+ scoped_refptr<EnterprisePlatformKeysPrivateChallengeMachineKeyFunction> func_;
};
// Base 64 encoding of 'challenge'.
@@ -341,11 +344,13 @@ class EPKPChallengeUserKeyTest : public EPKPChallengeKeyTestBase {
protected:
static const char kArgs[];
- EPKPChallengeUserKeyTest() :
- func_(new EPKPChallengeUserKey(&mock_cryptohome_client_,
- &mock_async_method_caller_,
- &mock_attestation_flow_,
- &stub_install_attributes_)) {
+ EPKPChallengeUserKeyTest()
+ : impl_(&mock_cryptohome_client_,
+ &mock_async_method_caller_,
+ &mock_attestation_flow_,
+ &stub_install_attributes_),
+ func_(
+ new EnterprisePlatformKeysPrivateChallengeUserKeyFunction(&impl_)) {
func_->set_extension(extension_.get());
}
@@ -362,7 +367,8 @@ class EPKPChallengeUserKeyTest : public EPKPChallengeKeyTestBase {
error_code);
}
- scoped_refptr<EPKPChallengeUserKey> func_;
+ EPKPChallengeUserKey impl_;
+ scoped_refptr<EnterprisePlatformKeysPrivateChallengeUserKeyFunction> func_;
};
// Base 64 encoding of 'challenge'
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index e06ce4a..1b37e18 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -533,8 +533,7 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
chromeos::SAMLOfflineSigninLimiter::RegisterProfilePrefs(registry);
chromeos::ServicesCustomizationDocument::RegisterProfilePrefs(registry);
chromeos::UserImageSyncObserver::RegisterProfilePrefs(registry);
- extensions::EnterprisePlatformKeysPrivateChallengeUserKeyFunction::
- RegisterProfilePrefs(registry);
+ extensions::EPKPChallengeUserKey::RegisterProfilePrefs(registry);
flags_ui::PrefServiceFlagsStorage::RegisterProfilePrefs(registry);
#endif
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 2630524..df03cd5 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -1109,6 +1109,7 @@
'browser/chromeos/ui/accessibility_focus_ring_controller_unittest.cc',
'browser/chromeos/ui/idle_app_name_notification_view_unittest.cc',
'browser/download/notification/download_item_notification_unittest.cc',
+ 'browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc',
'browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc',
'browser/extensions/api/log_private/syslog_parser_unittest.cc',
'browser/extensions/updater/local_extension_cache_unittest.cc',
diff --git a/chrome/common/extensions/api/enterprise_platform_keys.idl b/chrome/common/extensions/api/enterprise_platform_keys.idl
index 5133bf5..bb5cfb1 100644
--- a/chrome/common/extensions/api/enterprise_platform_keys.idl
+++ b/chrome/common/extensions/api/enterprise_platform_keys.idl
@@ -45,6 +45,11 @@ namespace enterprise.platformKeys {
// operation is finished.
callback DoneCallback = void();
+ // Invoked by <code>challengeMachineKey</code> or
+ // <code>challengeUserKey</code> with the challenge response.
+ // |response|: The challenge response.
+ callback ChallengeCallback = void(ArrayBuffer response);
+
interface Functions {
// Returns the available Tokens. In a regular user's session the list will
// always contain the user's token with <code>id</code> <code>"user"</code>.
@@ -84,5 +89,62 @@ namespace enterprise.platformKeys {
static void removeCertificate(DOMString tokenId,
ArrayBuffer certificate,
optional DoneCallback callback);
+
+ // Challenges a hardware-backed Enterprise Machine Key and emits the
+ // response as part of a remote attestation protocol. Only useful on Chrome
+ // OS and in conjunction with the Verified Access Web API which both issues
+ // challenges and verifies responses. A successful verification by the
+ // Verified Access Web API is a strong signal of all of the following:
+ // * The current device is a legitimate Chrome OS device.
+ // * The current device is managed by the domain specified during
+ // verification.
+ // * The current signed-in user is managed by the domain specified during
+ // verification.
+ // * The current device state complies with enterprise device policy. For
+ // example, a policy may specify that the device must not be in developer
+ // mode.
+ // * Any device identity emitted by the verification is tightly bound to the
+ // hardware of the current device.
+ // This function is highly restricted and will fail if the current device
+ // is not managed, the current user is not managed, or if this operation
+ // has not explicitly been enabled for the caller by enterprise device
+ // policy. The Enterprise Machine Key does not reside in the
+ // <code>"system"</code> token and is not accessible by any other API.
+ // |challenge|: A challenge as emitted by the Verified Access Web API.
+ // |callback|: Called back with the challenge response.
+ static void challengeMachineKey(ArrayBuffer challenge,
+ ChallengeCallback callback);
+
+ // Challenges a hardware-backed Enterprise User Key and emits the response
+ // as part of a remote attestation protocol. Only useful on Chrome OS and in
+ // conjunction with the Verified Access Web API which both issues challenges
+ // and verifies responses. A successful verification by the Verified Access
+ // Web API is a strong signal of all of the following:
+ // * The current device is a legitimate Chrome OS device.
+ // * The current device is managed by the domain specified during
+ // verification.
+ // * The current signed-in user is managed by the domain specified during
+ // verification.
+ // * The current device state complies with enterprise user policy. For
+ // example, a policy may specify that the device must not be in developer
+ // mode.
+ // * The public key emitted by the verification is tightly bound to the
+ // hardware of the current device and to the current signed-in user.
+ // This function is highly restricted and will fail if the current device is
+ // not managed, the current user is not managed, or if this operation has
+ // not explicitly been enabled for the caller by enterprise user policy.
+ // The Enterprise User Key does not reside in the <code>"user"</code> token
+ // and is not accessible by any other API.
+ // |challenge|: A challenge as emitted by the Verified Access Web API.
+ // |registerKey|: If set, the current Enterprise User Key is registered with
+ // the <code>"user"</code> token and relinquishes the
+ // Enterprise User Key role. The key can then be associated
+ // with a certificate and used like any other signing key.
+ // This key is 2048-bit RSA. Subsequent calls to this
+ // function will then generate a new Enterprise User Key.
+ // |callback|: Called back with the challenge response.
+ static void challengeUserKey(ArrayBuffer challenge,
+ boolean registerKey,
+ ChallengeCallback callback);
};
};
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index ab47f53..a312c5a 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -1166,6 +1166,8 @@ enum HistogramValue {
ACCESSIBILITY_PRIVATE_SETKEYBOARDLISTENER,
INPUT_IME_ACTIVATE,
INPUT_IME_DEACTIVATE,
+ ENTERPRISE_PLATFORMKEYS_CHALLENGEMACHINEKEY,
+ ENTERPRISE_PLATFORMKEYS_CHALLENGEUSERKEY,
// Last entry: Add new entries above, then run:
// python tools/metrics/histograms/update_extension_histograms.py
ENUM_BOUNDARY
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index b5facb3..98d00ba 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -65621,6 +65621,8 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
<int value="1105" label="ACCESSIBILITY_PRIVATE_SETKEYBOARDLISTENER"/>
<int value="1106" label="INPUT_IME_ACTIVATE"/>
<int value="1107" label="INPUT_IME_DEACTIVATE"/>
+ <int value="1108" label="ENTERPRISE_PLATFORMKEYS_CHALLENGEMACHINEKEY"/>
+ <int value="1109" label="ENTERPRISE_PLATFORMKEYS_CHALLENGEUSERKEY"/>
</enum>
<enum name="ExtensionInstallCause" type="int">