Commit d062dc8c authored by Erik Chen's avatar Erik Chen Committed by Commit Bot

lacros: Add plumbing for enterprise.platformKeysInternal.getTokens.

This CL adds a new crosapi method KeystoreService.GetKeyStores. This
provides the necessary and sufficient plumbing to implement
enterprise.platformKeysInternal.getTokens. The difference in
nomenclature and method signature between GetKeyStores and getTokens is
intentional -- the goal is to create a cleaner API surface for
stabilization.

As a necessary side effect, this CL adds
enterprise_platform_keys_internal.idl to Lacros builds.

Bug: 1127505
Change-Id: I1d6678708316d26edd2b4ca043662a0b34ab3c27
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2406668Reviewed-by: default avatarKaran Bhatia <karandeepb@chromium.org>
Reviewed-by: default avatarGreg Kerr <kerrnel@chromium.org>
Reviewed-by: default avatarJames Cook <jamescook@chromium.org>
Reviewed-by: default avatarMaksim Ivanov <emaxx@chromium.org>
Commit-Queue: Erik Chen <erikchen@chromium.org>
Auto-Submit: Erik Chen <erikchen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#812920}
parent 53a16cf1
......@@ -6,23 +6,30 @@
#include <utility>
#include "base/threading/sequenced_task_runner_handle.h"
#include "chrome/browser/chromeos/attestation/tpm_challenge_key.h"
#include "chrome/browser/chromeos/platform_keys/platform_keys_service.h"
#include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "content/public/browser/browser_thread.h"
namespace crosapi {
KeystoreServiceAsh::KeystoreServiceAsh(
mojo::PendingReceiver<mojom::KeystoreService> receiver)
: receiver_(this, std::move(receiver)) {}
: receiver_(this, std::move(receiver)) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
KeystoreServiceAsh::~KeystoreServiceAsh() = default;
KeystoreServiceAsh::~KeystoreServiceAsh() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
void KeystoreServiceAsh::ChallengeAttestationOnlyKeystore(
const std::string& challenge,
mojom::KeystoreType type,
bool migrate,
ChallengeAttestationOnlyKeystoreCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (!crosapi::mojom::IsKnownEnumValue(type)) {
mojom::ChallengeAttestationOnlyKeystoreResultPtr result_ptr =
mojom::ChallengeAttestationOnlyKeystoreResult::New();
......@@ -56,10 +63,53 @@ void KeystoreServiceAsh::ChallengeAttestationOnlyKeystore(
/*register_key=*/false, /*key_name_for_spkac=*/"");
}
void KeystoreServiceAsh::GetKeyStores(GetKeyStoresCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
chromeos::platform_keys::PlatformKeysService* platform_keys_service =
chromeos::platform_keys::PlatformKeysServiceFactory::GetForBrowserContext(
ProfileManager::GetActiveUserProfile());
CHECK(platform_keys_service);
platform_keys_service->GetTokens(
base::BindOnce(&KeystoreServiceAsh::OnGetTokens, std::move(callback)));
}
// static
void KeystoreServiceAsh::OnGetTokens(
GetKeyStoresCallback callback,
std::unique_ptr<std::vector<chromeos::platform_keys::TokenId>>
platform_keys_token_ids,
chromeos::platform_keys::Status status) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
mojom::GetKeyStoresResultPtr result_ptr = mojom::GetKeyStoresResult::New();
if (status == chromeos::platform_keys::Status::kSuccess) {
std::vector<mojom::KeystoreType> key_stores;
for (auto token_id : *platform_keys_token_ids) {
switch (token_id) {
case chromeos::platform_keys::TokenId::kUser:
key_stores.push_back(mojom::KeystoreType::kUser);
break;
case chromeos::platform_keys::TokenId::kSystem:
key_stores.push_back(mojom::KeystoreType::kDevice);
break;
}
}
result_ptr->set_key_stores(std::move(key_stores));
} else {
result_ptr->set_error_message(
chromeos::platform_keys::StatusToString(status));
}
std::move(callback).Run(std::move(result_ptr));
}
void KeystoreServiceAsh::DidChallengeAttestationOnlyKeystore(
ChallengeAttestationOnlyKeystoreCallback callback,
void* challenge_key_ptr,
const chromeos::attestation::TpmChallengeKeyResult& result) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
mojom::ChallengeAttestationOnlyKeystoreResultPtr result_ptr =
mojom::ChallengeAttestationOnlyKeystoreResult::New();
if (result.IsSuccess()) {
......
......@@ -9,6 +9,7 @@
#include <vector>
#include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/platform_keys/platform_keys.h"
#include "chromeos/crosapi/mojom/keystore_service.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
......@@ -24,7 +25,7 @@ namespace crosapi {
// This class is the ash implementation of the KeystoreService crosapi. It
// allows lacros to expose blessed extension APIs which can query or modify the
// system keystores.
// system keystores. This class is affine to the UI thread.
class KeystoreServiceAsh : public mojom::KeystoreService {
public:
explicit KeystoreServiceAsh(
......@@ -40,8 +41,15 @@ class KeystoreServiceAsh : public mojom::KeystoreService {
mojom::KeystoreType type,
bool migrate,
ChallengeAttestationOnlyKeystoreCallback callback) override;
void GetKeyStores(GetKeyStoresCallback callback) override;
private:
static void OnGetTokens(
GetKeyStoresCallback callback,
std::unique_ptr<std::vector<chromeos::platform_keys::TokenId>>
platform_keys_token_ids,
chromeos::platform_keys::Status status);
// |challenge| is used as a opaque identifier to match against the unique_ptr
// in outstanding_challenges_. It should not be dereferenced.
void DidChallengeAttestationOnlyKeystore(
......
......@@ -13,6 +13,7 @@
#include "chrome/browser/extensions/api/platform_keys/platform_keys_api.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/enterprise_platform_keys.h"
#include "chrome/common/extensions/api/enterprise_platform_keys_internal.h"
#include "chromeos/lacros/lacros_chrome_service_impl.h"
namespace extensions {
......@@ -20,6 +21,7 @@ namespace extensions {
namespace {
namespace api_epk = api::enterprise_platform_keys;
namespace api_epki = api::enterprise_platform_keys_internal;
std::vector<uint8_t> VectorFromString(const std::string& s) {
return std::vector<uint8_t>(s.begin(), s.end());
......@@ -38,6 +40,51 @@ ExtensionFunction::ResponseAction LacrosNotImplementedExtensionFunction::Run() {
return RespondNow(Error(kLacrosNotImplementedError));
}
ExtensionFunction::ResponseAction
EnterprisePlatformKeysInternalGetTokensFunction::Run() {
EXTENSION_FUNCTION_VALIDATE(args_->empty());
// This API is used in security-sensitive contexts and attests against a
// particular user. Since the attestation is done by ash, we need to ensure
// that the user for ash is the same as the user for lacros. We do this by
// restricting the API to the default profile, which is guaranteed to be the
// same user.
if (!Profile::FromBrowserContext(browser_context())->IsDefaultProfile())
return RespondNow(Error(kUnsupportedProfile));
auto c = base::BindOnce(
&EnterprisePlatformKeysInternalGetTokensFunction::OnGetKeyStores, this);
chromeos::LacrosChromeServiceImpl::Get()
->keystore_service_remote()
->GetKeyStores(std::move(c));
return RespondLater();
}
void EnterprisePlatformKeysInternalGetTokensFunction::OnGetKeyStores(
ResultPtr result) {
using Result = crosapi::mojom::GetKeyStoresResult;
switch (result->which()) {
case Result::Tag::ERROR_MESSAGE:
Respond(Error(result->get_error_message()));
return;
case Result::Tag::KEY_STORES:
std::vector<std::string> key_stores;
using KeystoreType = crosapi::mojom::KeystoreType;
for (KeystoreType keystore_type : result->get_key_stores()) {
switch (keystore_type) {
case KeystoreType::kUser:
key_stores.push_back("user");
break;
case KeystoreType::kDevice:
key_stores.push_back("system");
break;
}
}
Respond(ArgumentList(api_epki::GetTokens::Results::Create(key_stores)));
return;
}
}
ExtensionFunction::ResponseAction
EnterprisePlatformKeysChallengeMachineKeyFunction::Run() {
std::unique_ptr<api_epk::ChallengeMachineKey::Params> params(
......
......@@ -18,6 +18,14 @@ class LacrosNotImplementedExtensionFunction : public ExtensionFunction {
ResponseAction Run() override;
};
class EnterprisePlatformKeysInternalGenerateKeyFunction
: public LacrosNotImplementedExtensionFunction {
private:
~EnterprisePlatformKeysInternalGenerateKeyFunction() override = default;
DECLARE_EXTENSION_FUNCTION("enterprise.platformKeysInternal.generateKey",
ENTERPRISE_PLATFORMKEYSINTERNAL_GENERATEKEY)
};
class EnterprisePlatformKeysGetCertificatesFunction
: public LacrosNotImplementedExtensionFunction {
private:
......@@ -43,9 +51,13 @@ class EnterprisePlatformKeysRemoveCertificateFunction
};
class EnterprisePlatformKeysInternalGetTokensFunction
: public LacrosNotImplementedExtensionFunction {
: public ExtensionFunction {
private:
~EnterprisePlatformKeysInternalGetTokensFunction() override = default;
ResponseAction Run() override;
using ResultPtr = crosapi::mojom::GetKeyStoresResultPtr;
void OnGetKeyStores(ResultPtr result);
DECLARE_EXTENSION_FUNCTION("enterprise.platformKeysInternal.getTokens",
ENTERPRISE_PLATFORMKEYSINTERNAL_GETTOKENS)
};
......
......@@ -78,7 +78,10 @@ if (is_chromeos || is_mac || is_win) {
}
if (is_chromeos || chromeos_is_browser_only) {
schema_sources_ += [ "enterprise_platform_keys.idl" ]
schema_sources_ += [
"enterprise_platform_keys.idl",
"enterprise_platform_keys_internal.idl",
]
}
if (is_chromeos) {
......@@ -89,7 +92,6 @@ if (is_chromeos) {
"echo_private.json",
"enterprise_device_attributes.idl",
"enterprise_networking_attributes.idl",
"enterprise_platform_keys_internal.idl",
"enterprise_platform_keys_private.json",
"file_browser_handler_internal.json",
"file_manager_private.idl",
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Internal API for platform keys and certificate management.
[ platforms = ("chromeos"),
[ platforms = ("chromeos", "lacros"),
implemented_in = "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h" ]
namespace enterprise.platformKeysInternal {
dictionary Hash {
......
......@@ -34,6 +34,16 @@ union ChallengeAttestationOnlyKeystoreResult {
string challenge_response;
};
// Returned by GetKeyStores().
[Stable]
union GetKeyStoresResult {
// Implies failure.
string error_message;
// Implies success.
array<KeystoreType> key_stores;
};
// This interface is implemented by ash-chrome. It provides lacros-chrome a
// mechanism to modify and query the attestation-only and generate purpose
// keystores.
......@@ -51,5 +61,10 @@ interface KeystoreService {
ChallengeAttestationOnlyKeystore@0(
string challenge, KeystoreType type, bool migrate) =>
(ChallengeAttestationOnlyKeystoreResult result);
// Returns the key stores available to the client. These are used as inputs to
// the other methods on this interface.
[MinVersion=1]
GetKeyStores@1() => (GetKeyStoresResult result);
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment