| Index: chrome/browser/chromeos/platform_keys/platform_keys_service.cc
|
| diff --git a/chrome/browser/chromeos/platform_keys/platform_keys_service.cc b/chrome/browser/chromeos/platform_keys/platform_keys_service.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4137062939ab098e59ad0db828087983272cc376
|
| --- /dev/null
|
| +++ b/chrome/browser/chromeos/platform_keys/platform_keys_service.cc
|
| @@ -0,0 +1,241 @@
|
| +// Copyright 2014 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/chromeos/platform_keys/platform_keys_service.h"
|
| +
|
| +#include "base/base64.h"
|
| +#include "base/callback.h"
|
| +#include "base/values.h"
|
| +#include "chrome/browser/chromeos/platform_keys/platform_keys.h"
|
| +#include "chrome/browser/extensions/state_store.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| +
|
| +using content::BrowserThread;
|
| +
|
| +namespace chromeos {
|
| +
|
| +namespace {
|
| +
|
| +const char kErrorInternal[] = "Internal Error.";
|
| +const char kErrorKeyNotAllowedForSigning[] =
|
| + "This key is not allowed for signing. Either it was used for signing "
|
| + "before or it was not correctly generated.";
|
| +const char kStateStorePlatformKeys[] = "PlatformKeys";
|
| +
|
| +scoped_ptr<base::StringValue> GetPublicKeyValue(
|
| + const std::string& public_key_spki_der) {
|
| + std::string public_key_spki_der_b64;
|
| + base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64);
|
| + return make_scoped_ptr(new base::StringValue(public_key_spki_der_b64));
|
| +}
|
| +
|
| +// Wraps |callback| into a void(bool) callback which forwards
|
| +// |public_key_spki_der| if |true| is passed to it.
|
| +void WrapGenerateKeyCallback(
|
| + const PlatformKeysService::GenerateKeyCallback& callback,
|
| + const std::string& public_key_spki_der,
|
| + bool success) {
|
| + if (success)
|
| + callback.Run(public_key_spki_der, std::string() /* no error */);
|
| + else
|
| + callback.Run(std::string() /* no public key */, kErrorInternal);
|
| +}
|
| +
|
| +// Callback used by |PlatformKeysService::Sign|.
|
| +// Is called with the old validity of |public_key_spki_der| (or false if an
|
| +// error occurred during reading the StateStore). If allowed, starts the actual
|
| +// signing operation which will call back |callback|. If not allowed, calls
|
| +// |callback| with an error.
|
| +void CheckValidityAndSign(const std::string& token_id,
|
| + const std::string& public_key_spki_der,
|
| + const std::string& data,
|
| + const PlatformKeysService::SignCallback& callback,
|
| + Profile* profile,
|
| + bool key_is_valid) {
|
| + if (!key_is_valid) {
|
| + callback.Run(std::string() /* no signature */,
|
| + kErrorKeyNotAllowedForSigning);
|
| + return;
|
| + }
|
| + platform_keys::subtle::Sign(
|
| + token_id, public_key_spki_der, data, callback, profile);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +PlatformKeysService::PlatformKeysService(extensions::StateStore* state_store)
|
| + : state_store_(state_store), weak_factory_(this) {
|
| + DCHECK(state_store);
|
| +}
|
| +
|
| +PlatformKeysService::~PlatformKeysService() {
|
| +}
|
| +
|
| +void PlatformKeysService::GenerateRSAKey(const std::string& token_id,
|
| + unsigned int modulus_length,
|
| + const std::string& extension_id,
|
| + const GenerateKeyCallback& callback,
|
| + Profile* profile) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| +
|
| + platform_keys::subtle::GenerateRSAKey(token_id,
|
| + modulus_length,
|
| + base::Bind(&GenerateRSAKeyCallback,
|
| + extension_id,
|
| + callback,
|
| + weak_factory_.GetWeakPtr()),
|
| + profile);
|
| +}
|
| +
|
| +void PlatformKeysService::Sign(const std::string& token_id,
|
| + const std::string& public_key_spki_der,
|
| + const std::string& data,
|
| + const std::string& extension_id,
|
| + const SignCallback& callback,
|
| + Profile* profile) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + ReadValidityAndInvalidateKey(extension_id,
|
| + public_key_spki_der,
|
| + base::Bind(&CheckValidityAndSign,
|
| + token_id,
|
| + public_key_spki_der,
|
| + data,
|
| + callback,
|
| + profile));
|
| +}
|
| +
|
| +void PlatformKeysService::RegisterPublicKey(
|
| + const std::string& extension_id,
|
| + const std::string& public_key_spki_der,
|
| + const base::Callback<void(bool)>& callback) {
|
| + GetPlatformKeysOfExtension(extension_id,
|
| + base::Bind(&RegisterPublicKeyGotPlatformKeys,
|
| + extension_id,
|
| + public_key_spki_der,
|
| + callback));
|
| +}
|
| +
|
| +void PlatformKeysService::ReadValidityAndInvalidateKey(
|
| + const std::string& extension_id,
|
| + const std::string& public_key_spki_der,
|
| + const base::Callback<void(bool)>& callback) {
|
| + GetPlatformKeysOfExtension(
|
| + extension_id,
|
| + base::Bind(&InvalidateKey, extension_id, public_key_spki_der, callback));
|
| +}
|
| +
|
| +void PlatformKeysService::GetPlatformKeysOfExtension(
|
| + const std::string& extension_id,
|
| + const GetPlatformKeysCallback& callback) {
|
| + state_store_->GetExtensionValue(extension_id,
|
| + kStateStorePlatformKeys,
|
| + base::Bind(&GotPlatformKeysOfExtension,
|
| + extension_id,
|
| + weak_factory_.GetWeakPtr(),
|
| + callback));
|
| +}
|
| +
|
| +// static
|
| +void PlatformKeysService::GenerateRSAKeyCallback(
|
| + const std::string& extension_id,
|
| + const GenerateKeyCallback& callback,
|
| + base::WeakPtr<PlatformKeysService> service,
|
| + const std::string& public_key_spki_der,
|
| + const std::string& error_message) {
|
| + if (!error_message.empty()) {
|
| + callback.Run(std::string() /* no public key */, error_message);
|
| + return;
|
| + }
|
| + base::Callback<void(bool)> wrapped_callback(
|
| + base::Bind(&WrapGenerateKeyCallback, callback, public_key_spki_der));
|
| + if (!service) {
|
| + LOG(ERROR) << "PlatformKeysService is already destructed.";
|
| + wrapped_callback.Run(false);
|
| + return;
|
| + }
|
| + service->RegisterPublicKey(
|
| + extension_id, public_key_spki_der, wrapped_callback);
|
| +}
|
| +
|
| +// static
|
| +void PlatformKeysService::RegisterPublicKeyGotPlatformKeys(
|
| + const std::string& extension_id,
|
| + const std::string& public_key_spki_der,
|
| + const base::Callback<void(bool)>& callback,
|
| + base::WeakPtr<PlatformKeysService> service,
|
| + scoped_ptr<base::ListValue> platform_keys) {
|
| + if (!service) {
|
| + LOG(ERROR) << "PlatformKeysService is already destructed.";
|
| + callback.Run(false);
|
| + return;
|
| + }
|
| +
|
| + if (!platform_keys) {
|
| + LOG(ERROR) << "Error while reading the platform keys.";
|
| + callback.Run(false);
|
| + return;
|
| + }
|
| +
|
| + scoped_ptr<base::StringValue> key_value(
|
| + GetPublicKeyValue(public_key_spki_der));
|
| +
|
| + DCHECK(platform_keys->end() == platform_keys->Find(*key_value))
|
| + << "Keys are assumed to be generated and not to be registered multiple "
|
| + "times.";
|
| + platform_keys->Append(key_value.release());
|
| +
|
| + service->state_store_->SetExtensionValue(extension_id,
|
| + kStateStorePlatformKeys,
|
| + platform_keys.PassAs<base::Value>());
|
| + callback.Run(true);
|
| +}
|
| +
|
| +// static
|
| +void PlatformKeysService::InvalidateKey(
|
| + const std::string& extension_id,
|
| + const std::string& public_key_spki_der,
|
| + const base::Callback<void(bool)>& callback,
|
| + base::WeakPtr<PlatformKeysService> service,
|
| + scoped_ptr<base::ListValue> platform_keys) {
|
| + if (!service) {
|
| + LOG(ERROR) << "PlatformKeysService is already destructed.";
|
| + callback.Run(false);
|
| + return;
|
| + }
|
| +
|
| + scoped_ptr<base::StringValue> key_value(
|
| + GetPublicKeyValue(public_key_spki_der));
|
| +
|
| + size_t index = 0;
|
| + if (!platform_keys->Remove(*key_value, &index)) {
|
| + // The key is not found, so it's not valid to use it for signing.
|
| + callback.Run(false);
|
| + return;
|
| + }
|
| +
|
| + service->state_store_->SetExtensionValue(extension_id,
|
| + kStateStorePlatformKeys,
|
| + platform_keys.PassAs<base::Value>());
|
| + callback.Run(true);
|
| +}
|
| +
|
| +// static
|
| +void PlatformKeysService::GotPlatformKeysOfExtension(
|
| + const std::string& extension_id,
|
| + base::WeakPtr<PlatformKeysService> service,
|
| + const GetPlatformKeysCallback& callback,
|
| + scoped_ptr<base::Value> value) {
|
| + if (!value)
|
| + value.reset(new base::ListValue);
|
| +
|
| + base::ListValue* keys = NULL;
|
| + if (!value->GetAsList(&keys)) {
|
| + LOG(ERROR) << "Found a value of wrong type.";
|
| + value.reset();
|
| + }
|
| + ignore_result(value.release());
|
| + callback.Run(service, make_scoped_ptr(keys));
|
| +}
|
| +
|
| +} // namespace chromeos
|
|
|