1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_PLATFORM_KEYS_SERVICE_H_
6 #define CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_PLATFORM_KEYS_SERVICE_H_
12 #include "base/callback_forward.h"
13 #include "base/macros.h"
14 #include "base/memory/linked_ptr.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/memory/weak_ptr.h"
17 #include "chrome/browser/chromeos/platform_keys/platform_keys.h"
18 #include "components/keyed_service/core/keyed_service.h"
30 namespace extensions
{
35 class X509Certificate
;
36 typedef std::vector
<scoped_refptr
<X509Certificate
>> CertificateList
;
41 class PlatformKeysService
: public KeyedService
{
44 using KeyEntries
= std::vector
<KeyEntry
>;
46 // The SelectDelegate is used to select a single certificate from all
47 // certificates matching a request (see SelectClientCertificates). E.g. this
48 // can happen by exposing UI to let the user select.
49 class SelectDelegate
{
51 using CertificateSelectedCallback
= base::Callback
<void(
52 const scoped_refptr
<net::X509Certificate
>& selection
)>;
55 virtual ~SelectDelegate();
57 // Called on an interactive SelectClientCertificates call with the list of
58 // matching certificates, |certs|.
59 // The certificate passed to |callback| will be forwarded to the
60 // calling extension and the extension will get unlimited sign permission
61 // for this cert. By passing null to |callback|, no cert will be selected.
62 // Must eventually call |callback| or be destructed. |callback| must not be
63 // called after this delegate is destructed.
64 // |web_contents| and |context| provide the context in which the
65 // certificates were requested and are not null.
66 virtual void Select(const std::string
& extension_id
,
67 const net::CertificateList
& certs
,
68 const CertificateSelectedCallback
& callback
,
69 content::WebContents
* web_contents
,
70 content::BrowserContext
* context
) = 0;
73 DISALLOW_ASSIGN(SelectDelegate
);
76 // Stores registration information in |state_store|, i.e. for each extension
77 // the list of public keys that are valid to be used for signing. Each key can
78 // be used for signing at most once.
79 // The format written to |state_store| is:
80 // kStateStorePlatformKeys maps to a list of strings.
81 // Each string is the base64 encoding of the DER representation of a public
83 explicit PlatformKeysService(content::BrowserContext
* browser_context
,
84 extensions::StateStore
* state_store
);
85 ~PlatformKeysService() override
;
87 // Sets the delegate which will be used for interactive
88 // SelectClientCertificates calls.
89 void SetSelectDelegate(scoped_ptr
<SelectDelegate
> delegate
);
91 // Grants unlimited sign permission for |cert| to the extension with the ID
93 void GrantUnlimitedSignPermission(const std::string
& extension_id
,
94 scoped_refptr
<net::X509Certificate
> cert
);
96 // If the generation was successful, |public_key_spki_der| will contain the
97 // DER encoding of the SubjectPublicKeyInfo of the generated key and
98 // |error_message| will be empty. If it failed, |public_key_spki_der| will be
99 // empty and |error_message| contain an error message.
100 using GenerateKeyCallback
=
101 base::Callback
<void(const std::string
& public_key_spki_der
,
102 const std::string
& error_message
)>;
104 // Generates an RSA key pair with |modulus_length_bits| and registers the key
105 // to allow a single sign operation by the given extension. |token_id| is
106 // currently ignored, instead the user token associated with |browser_context|
107 // is always used. |callback| will be invoked with the resulting public key or
109 // Will only call back during the lifetime of this object.
110 void GenerateRSAKey(const std::string
& token_id
,
111 unsigned int modulus_length_bits
,
112 const std::string
& extension_id
,
113 const GenerateKeyCallback
& callback
);
115 // If signing was successful, |signature| will be contain the signature and
116 // |error_message| will be empty. If it failed, |signature| will be empty and
117 // |error_message| contain an error message.
118 using SignCallback
= base::Callback
<void(const std::string
& signature
,
119 const std::string
& error_message
)>;
121 // Digests |data|, applies PKCS1 padding and afterwards signs the data with
122 // the private key matching |params.public_key|. If a non empty token id is
123 // provided and the key is not found in that token, the operation aborts.
124 // If the extension does not have permissions for signing with this key, the
125 // operation aborts. In case of a one time permission (granted after
126 // generating the key), this function also removes the permission to prevent
127 // future signing attempts.
128 // |callback| will be invoked with the signature or an error message.
129 // Will only call back during the lifetime of this object.
130 void SignRSAPKCS1Digest(const std::string
& token_id
,
131 const std::string
& data
,
132 const std::string
& public_key
,
133 platform_keys::HashAlgorithm hash_algorithm
,
134 const std::string
& extension_id
,
135 const SignCallback
& callback
);
137 // Applies PKCS1 padding and afterwards signs the data with the private key
138 // matching |params.public_key|. |data| is not digested. If a non empty token
139 // id is provided and the key is not found in that token, the operation
141 // The size of |data| (number of octets) must be smaller than k - 11, where k
142 // is the key size in octets.
143 // If the extension does not have permissions for signing with this key, the
144 // operation aborts. In case of a one time permission (granted after
145 // generating the key), this function also removes the permission to prevent
146 // future signing attempts.
147 // |callback| will be invoked with the signature or an error message.
148 // Will only call back during the lifetime of this object.
149 void SignRSAPKCS1Raw(const std::string
& token_id
,
150 const std::string
& data
,
151 const std::string
& public_key
,
152 const std::string
& extension_id
,
153 const SignCallback
& callback
);
155 // If the certificate request could be processed successfully, |matches| will
156 // contain the list of matching certificates (maybe empty) and |error_message|
157 // will be empty. If an error occurred, |matches| will be null and
158 // |error_message| contain an error message.
159 using SelectCertificatesCallback
=
160 base::Callback
<void(scoped_ptr
<net::CertificateList
> matches
,
161 const std::string
& error_message
)>;
163 // Returns a list of certificates matching |request|.
164 // 1) all certificates that match the request (like being rooted in one of the
165 // give CAs) are determined. 2) if |interactive| is true, the currently set
166 // SelectDelegate is used to select a single certificate from these matches
167 // which will the extension will also be granted access to. 3) only
168 // certificates, that the extension has unlimited sign permission for, will be
170 // |callback| will be invoked with these certificates or an error message.
171 // Will only call back during the lifetime of this object.
172 // |web_contents| must not be null.
173 void SelectClientCertificates(
174 const platform_keys::ClientCertificateRequest
& request
,
176 const std::string
& extension_id
,
177 const SelectCertificatesCallback
& callback
,
178 content::WebContents
* web_contents
);
181 using GetPlatformKeysCallback
=
182 base::Callback
<void(scoped_ptr
<KeyEntries
> platform_keys
)>;
184 enum SignPermission
{ ONCE
, UNLIMITED
};
186 class PermissionUpdateTask
;
191 // Starts |task| eventually. To ensure that at most one |Task| is running at a
192 // time, it queues |task| for later execution if necessary.
193 void StartOrQueueTask(scoped_ptr
<Task
> task
);
195 // Must be called after |task| is done. |task| will be invalid after this
196 // call. This must not be called for any but the task that ran last. If any
197 // other tasks are queued (see StartOrQueueTask()), it will start the next
199 void TaskFinished(Task
* task
);
201 // Reads the list of public keys currently registered for |extension_id| from
202 // StateStore. Calls |callback| with the read list, or a new empty list if
203 // none existed. If an error occurred, calls |callback| with NULL.
204 void GetPlatformKeysOfExtension(const std::string
& extension_id
,
205 const GetPlatformKeysCallback
& callback
);
207 // Writes |platform_keys| to the state store of the extension with id
209 void SetPlatformKeysOfExtension(const std::string
& extension_id
,
210 const KeyEntries
& platform_keys
);
212 // Callback used by |GenerateRSAKey|.
213 // If the key generation was successful, registers the generated public key
214 // for the given extension. If any error occurs during key generation or
215 // registration, calls |callback| with an error. Otherwise, on success, calls
216 // |callback| with the public key.
217 void GeneratedKey(const std::string
& extension_id
,
218 const GenerateKeyCallback
& callback
,
219 const std::string
& public_key_spki_der
,
220 const std::string
& error_message
);
222 // Callback used by |GeneratedKey|.
223 // |public_key_spki_der| will contain the X.509 Subject Public Key Info of
224 // the generated key in DER encoding. |task| points to the finished |Task|
226 void RegisteredGeneratedKey(const GenerateKeyCallback
& callback
,
227 const std::string
& public_key_spki_der
,
230 // Callback used by |GetPlatformKeysOfExtension|.
231 // Is called with |value| set to the PlatformKeys value read from the
232 // StateStore, which it forwards to |callback|. On error, calls |callback|
233 // with NULL; if no value existed, with an empty list.
234 void GotPlatformKeysOfExtension(const std::string
& extension_id
,
235 const GetPlatformKeysCallback
& callback
,
236 scoped_ptr
<base::Value
> value
);
238 content::BrowserContext
* browser_context_
;
239 extensions::StateStore
* state_store_
;
240 scoped_ptr
<SelectDelegate
> select_delegate_
;
241 std::queue
<linked_ptr
<Task
>> tasks_
;
242 base::WeakPtrFactory
<PlatformKeysService
> weak_factory_
;
244 DISALLOW_COPY_AND_ASSIGN(PlatformKeysService
);
247 } // namespace chromeos
249 #endif // CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_PLATFORM_KEYS_SERVICE_H_