blob: 17045fa6f9545fc4b1f1000cd6b77da8c0572247 [file] [log] [blame]
// 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.
#ifndef CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_PLATFORM_KEYS_SERVICE_H_
#define CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_PLATFORM_KEYS_SERVICE_H_
#include <memory>
#include <string>
#include <vector>
#include "base/callback_forward.h"
#include "base/containers/queue.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/platform_keys/key_permissions.h"
#include "chrome/browser/chromeos/platform_keys/platform_keys.h"
#include "components/keyed_service/core/keyed_service.h"
class PrefService;
namespace content {
class BrowserContext;
class WebContents;
}
namespace extensions {
class StateStore;
}
namespace net {
class X509Certificate;
typedef std::vector<scoped_refptr<X509Certificate>> CertificateList;
}
namespace policy {
class PolicyService;
}
namespace chromeos {
class PlatformKeysService : public KeyedService {
public:
// The SelectDelegate is used to select a single certificate from all
// certificates matching a request (see SelectClientCertificates). E.g. this
// can happen by exposing UI to let the user select.
class SelectDelegate {
public:
using CertificateSelectedCallback = base::Callback<void(
const scoped_refptr<net::X509Certificate>& selection)>;
SelectDelegate();
virtual ~SelectDelegate();
// Called on an interactive SelectClientCertificates call with the list of
// matching certificates, |certs|.
// The certificate passed to |callback| will be forwarded to the
// calling extension and the extension will get unlimited sign permission
// for this cert. By passing null to |callback|, no cert will be selected.
// Must eventually call |callback| or be destructed. |callback| must not be
// called after this delegate is destructed.
// |web_contents| and |context| provide the context in which the
// certificates were requested and are not null.
virtual void Select(const std::string& extension_id,
const net::CertificateList& certs,
const CertificateSelectedCallback& callback,
content::WebContents* web_contents,
content::BrowserContext* context) = 0;
private:
DISALLOW_ASSIGN(SelectDelegate);
};
// Stores registration information in |state_store|, i.e. for each extension
// the list of public keys that are valid to be used for signing. See
// |KeyPermissions| for details.
// |browser_context| and |state_store| must not be null and outlive this
// object.
explicit PlatformKeysService(bool profile_is_managed,
PrefService* profile_prefs,
policy::PolicyService* profile_policies,
content::BrowserContext* browser_context,
extensions::StateStore* state_store);
~PlatformKeysService() override;
// Sets the delegate which will be used for interactive
// SelectClientCertificates calls.
void SetSelectDelegate(std::unique_ptr<SelectDelegate> delegate);
// If the generation was successful, |public_key_spki_der| will contain the
// DER encoding of the SubjectPublicKeyInfo of the generated key and
// |error_message| will be empty. If it failed, |public_key_spki_der| will be
// empty and |error_message| contain an error message.
using GenerateKeyCallback =
base::Callback<void(const std::string& public_key_spki_der,
const std::string& error_message)>;
// Generates an RSA key pair with |modulus_length_bits| and registers the key
// to allow a single sign operation by the given extension. |token_id|
// specifies the token to store the keypair on. |callback| will be invoked
// with the resulting public key or an error. Will only call back during the
// lifetime of this object.
void GenerateRSAKey(const std::string& token_id,
unsigned int modulus_length_bits,
const std::string& extension_id,
const GenerateKeyCallback& callback);
// If signing was successful, |signature| will be contain the signature and
// |error_message| will be empty. If it failed, |signature| will be empty and
// |error_message| contain an error message.
using SignCallback = base::Callback<void(const std::string& signature,
const std::string& error_message)>;
// Digests |data|, applies PKCS1 padding and afterwards signs the data with
// the private key matching |public_key_spki_der|. If a non empty token id is
// provided and the key is not found in that token, the operation aborts. If
// the extension does not have permissions for signing with this key, the
// operation aborts. In case of a one time permission (granted after
// generating the key), this function also removes the permission to prevent
// future signing attempts.
// |callback| will be invoked with the signature or an error message.
// Will only call back during the lifetime of this object.
void SignRSAPKCS1Digest(const std::string& token_id,
const std::string& data,
const std::string& public_key_spki_der,
platform_keys::HashAlgorithm hash_algorithm,
const std::string& extension_id,
const SignCallback& callback);
// Applies PKCS1 padding and afterwards signs the data with the private key
// matching |public_key_spki_der|. |data| is not digested. If a non empty
// token id is provided and the key is not found in that token, the operation
// aborts.
// The size of |data| (number of octets) must be smaller than k - 11, where k
// is the key size in octets.
// If the extension does not have permissions for signing with this key, the
// operation aborts. In case of a one time permission (granted after
// generating the key), this function also removes the permission to prevent
// future signing attempts.
// |callback| will be invoked with the signature or an error message.
// Will only call back during the lifetime of this object.
void SignRSAPKCS1Raw(const std::string& token_id,
const std::string& data,
const std::string& public_key_spki_der,
const std::string& extension_id,
const SignCallback& callback);
// If the certificate request could be processed successfully, |matches| will
// contain the list of matching certificates (maybe empty) and |error_message|
// will be empty. If an error occurred, |matches| will be null and
// |error_message| contain an error message.
using SelectCertificatesCallback =
base::Callback<void(std::unique_ptr<net::CertificateList> matches,
const std::string& error_message)>;
// Returns a list of certificates matching |request|.
// 1) all certificates that match the request (like being rooted in one of the
// give CAs) are determined.
// 2) if |client_certificates| is not null, drops all certificates that are
// not elements of |client_certificates|,
// 3) if |interactive| is true, the currently set SelectDelegate is used to
// select a single certificate from these matches
// which will the extension will also be granted access to.
// 4) only certificates, that the extension has unlimited sign permission for,
// will be returned.
// |callback| will be invoked with these certificates or an error message.
// Will only call back during the lifetime of this object. |web_contents| must
// not be null.
void SelectClientCertificates(
const platform_keys::ClientCertificateRequest& request,
std::unique_ptr<net::CertificateList> client_certificates,
bool interactive,
const std::string& extension_id,
const SelectCertificatesCallback& callback,
content::WebContents* web_contents);
private:
class GenerateRSAKeyTask;
class SelectTask;
class SignTask;
class Task;
// Starts |task| eventually. To ensure that at most one |Task| is running at a
// time, it queues |task| for later execution if necessary.
void StartOrQueueTask(std::unique_ptr<Task> task);
// Must be called after |task| is done. |task| will be invalid after this
// call. This must not be called for any but the task that ran last. If any
// other tasks are queued (see StartOrQueueTask()), it will start the next
// one.
void TaskFinished(Task* task);
// Callback used by |GenerateRSAKey|.
// If the key generation was successful, registers the generated public key
// for the given extension. If any error occurs during key generation or
// registration, calls |callback| with an error. Otherwise, on success, calls
// |callback| with the public key.
void GeneratedKey(const std::string& extension_id,
const GenerateKeyCallback& callback,
const std::string& public_key_spki_der,
const std::string& error_message);
content::BrowserContext* browser_context_;
KeyPermissions key_permissions_;
std::unique_ptr<SelectDelegate> select_delegate_;
base::queue<std::unique_ptr<Task>> tasks_;
base::WeakPtrFactory<PlatformKeysService> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PlatformKeysService);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_PLATFORM_KEYS_SERVICE_H_