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 #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h"
7 #include "base/base64.h"
8 #include "base/callback.h"
9 #include "base/values.h"
10 #include "chrome/browser/chromeos/platform_keys/platform_keys.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "extensions/browser/state_store.h"
14 using content::BrowserThread
;
20 const char kErrorInternal
[] = "Internal Error.";
21 const char kErrorKeyNotAllowedForSigning
[] =
22 "This key is not allowed for signing. Either it was used for signing "
23 "before or it was not correctly generated.";
24 const char kStateStorePlatformKeys
[] = "PlatformKeys";
26 scoped_ptr
<base::StringValue
> GetPublicKeyValue(
27 const std::string
& public_key_spki_der
) {
28 std::string public_key_spki_der_b64
;
29 base::Base64Encode(public_key_spki_der
, &public_key_spki_der_b64
);
30 return make_scoped_ptr(new base::StringValue(public_key_spki_der_b64
));
33 // Wraps |callback| into a void(bool) callback which forwards
34 // |public_key_spki_der| if |true| is passed to it.
35 void WrapGenerateKeyCallback(
36 const PlatformKeysService::GenerateKeyCallback
& callback
,
37 const std::string
& public_key_spki_der
,
40 callback
.Run(public_key_spki_der
, std::string() /* no error */);
42 callback
.Run(std::string() /* no public key */, kErrorInternal
);
45 // Callback used by |PlatformKeysService::Sign|.
46 // Is called with the old validity of |public_key_spki_der| (or false if an
47 // error occurred during reading the StateStore). If allowed, starts the actual
48 // signing operation which will call back |callback|. If not allowed, calls
49 // |callback| with an error.
50 void CheckValidityAndSign(const std::string
& token_id
,
51 const std::string
& public_key_spki_der
,
52 platform_keys::HashAlgorithm hash_algorithm
,
53 const std::string
& data
,
54 const PlatformKeysService::SignCallback
& callback
,
55 content::BrowserContext
* browser_context
,
58 callback
.Run(std::string() /* no signature */,
59 kErrorKeyNotAllowedForSigning
);
62 platform_keys::subtle::Sign(token_id
,
72 PlatformKeysService::PlatformKeysService(
73 content::BrowserContext
* browser_context
,
74 extensions::StateStore
* state_store
)
75 : browser_context_(browser_context
),
76 state_store_(state_store
),
81 PlatformKeysService::~PlatformKeysService() {
84 void PlatformKeysService::GenerateRSAKey(const std::string
& token_id
,
85 unsigned int modulus_length
,
86 const std::string
& extension_id
,
87 const GenerateKeyCallback
& callback
) {
88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
90 platform_keys::subtle::GenerateRSAKey(
93 base::Bind(&PlatformKeysService::GenerateRSAKeyCallback
,
94 weak_factory_
.GetWeakPtr(),
100 void PlatformKeysService::Sign(const std::string
& token_id
,
101 const std::string
& public_key_spki_der
,
102 platform_keys::HashAlgorithm hash_algorithm
,
103 const std::string
& data
,
104 const std::string
& extension_id
,
105 const SignCallback
& callback
) {
106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
107 ReadValidityAndInvalidateKey(extension_id
,
109 base::Bind(&CheckValidityAndSign
,
118 void PlatformKeysService::RegisterPublicKey(
119 const std::string
& extension_id
,
120 const std::string
& public_key_spki_der
,
121 const base::Callback
<void(bool)>& callback
) {
122 GetPlatformKeysOfExtension(
124 base::Bind(&PlatformKeysService::RegisterPublicKeyGotPlatformKeys
,
125 weak_factory_
.GetWeakPtr(),
131 void PlatformKeysService::ReadValidityAndInvalidateKey(
132 const std::string
& extension_id
,
133 const std::string
& public_key_spki_der
,
134 const base::Callback
<void(bool)>& callback
) {
135 GetPlatformKeysOfExtension(extension_id
,
136 base::Bind(&PlatformKeysService::InvalidateKey
,
137 weak_factory_
.GetWeakPtr(),
143 void PlatformKeysService::GetPlatformKeysOfExtension(
144 const std::string
& extension_id
,
145 const GetPlatformKeysCallback
& callback
) {
146 state_store_
->GetExtensionValue(
148 kStateStorePlatformKeys
,
149 base::Bind(&PlatformKeysService::GotPlatformKeysOfExtension
,
150 weak_factory_
.GetWeakPtr(),
155 void PlatformKeysService::GenerateRSAKeyCallback(
156 const std::string
& extension_id
,
157 const GenerateKeyCallback
& callback
,
158 const std::string
& public_key_spki_der
,
159 const std::string
& error_message
) {
160 if (!error_message
.empty()) {
161 callback
.Run(std::string() /* no public key */, error_message
);
164 base::Callback
<void(bool)> wrapped_callback(
165 base::Bind(&WrapGenerateKeyCallback
, callback
, public_key_spki_der
));
166 RegisterPublicKey(extension_id
, public_key_spki_der
, wrapped_callback
);
169 void PlatformKeysService::RegisterPublicKeyGotPlatformKeys(
170 const std::string
& extension_id
,
171 const std::string
& public_key_spki_der
,
172 const base::Callback
<void(bool)>& callback
,
173 scoped_ptr
<base::ListValue
> platform_keys
) {
174 if (!platform_keys
) {
175 LOG(ERROR
) << "Error while reading the platform keys.";
180 scoped_ptr
<base::StringValue
> key_value(
181 GetPublicKeyValue(public_key_spki_der
));
183 DCHECK(platform_keys
->end() == platform_keys
->Find(*key_value
))
184 << "Keys are assumed to be generated and not to be registered multiple "
186 platform_keys
->Append(key_value
.release());
188 state_store_
->SetExtensionValue(
189 extension_id
, kStateStorePlatformKeys
, platform_keys
.Pass());
193 void PlatformKeysService::InvalidateKey(
194 const std::string
& extension_id
,
195 const std::string
& public_key_spki_der
,
196 const base::Callback
<void(bool)>& callback
,
197 scoped_ptr
<base::ListValue
> platform_keys
) {
198 scoped_ptr
<base::StringValue
> key_value(
199 GetPublicKeyValue(public_key_spki_der
));
202 if (!platform_keys
->Remove(*key_value
, &index
)) {
203 // The key is not found, so it's not valid to use it for signing.
208 state_store_
->SetExtensionValue(
209 extension_id
, kStateStorePlatformKeys
, platform_keys
.Pass());
213 void PlatformKeysService::GotPlatformKeysOfExtension(
214 const std::string
& extension_id
,
215 const GetPlatformKeysCallback
& callback
,
216 scoped_ptr
<base::Value
> value
) {
218 value
.reset(new base::ListValue
);
220 base::ListValue
* keys
= NULL
;
221 if (!value
->GetAsList(&keys
)) {
222 LOG(ERROR
) << "Found a value of wrong type.";
225 ignore_result(value
.release());
226 callback
.Run(make_scoped_ptr(keys
));
229 } // namespace chromeos