summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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">