Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / platform_keys / platform_keys_service.cc
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.
4
5 #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h"
6
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"
13
14 using content::BrowserThread;
15
16 namespace chromeos {
17
18 namespace {
19
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";
25
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));
31 }
32
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,
38     bool success) {
39   if (success)
40     callback.Run(public_key_spki_der, std::string() /* no error */);
41   else
42     callback.Run(std::string() /* no public key */, kErrorInternal);
43 }
44
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,
56                           bool key_is_valid) {
57   if (!key_is_valid) {
58     callback.Run(std::string() /* no signature */,
59                  kErrorKeyNotAllowedForSigning);
60     return;
61   }
62   platform_keys::subtle::Sign(token_id,
63                               public_key_spki_der,
64                               hash_algorithm,
65                               data,
66                               callback,
67                               browser_context);
68 }
69
70 }  // namespace
71
72 PlatformKeysService::PlatformKeysService(
73     content::BrowserContext* browser_context,
74     extensions::StateStore* state_store)
75     : browser_context_(browser_context),
76       state_store_(state_store),
77       weak_factory_(this) {
78   DCHECK(state_store);
79 }
80
81 PlatformKeysService::~PlatformKeysService() {
82 }
83
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));
89
90   platform_keys::subtle::GenerateRSAKey(
91       token_id,
92       modulus_length,
93       base::Bind(&PlatformKeysService::GenerateRSAKeyCallback,
94                  weak_factory_.GetWeakPtr(),
95                  extension_id,
96                  callback),
97       browser_context_);
98 }
99
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,
108                                public_key_spki_der,
109                                base::Bind(&CheckValidityAndSign,
110                                           token_id,
111                                           public_key_spki_der,
112                                           hash_algorithm,
113                                           data,
114                                           callback,
115                                           browser_context_));
116 }
117
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(
123       extension_id,
124       base::Bind(&PlatformKeysService::RegisterPublicKeyGotPlatformKeys,
125                  weak_factory_.GetWeakPtr(),
126                  extension_id,
127                  public_key_spki_der,
128                  callback));
129 }
130
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(),
138                                         extension_id,
139                                         public_key_spki_der,
140                                         callback));
141 }
142
143 void PlatformKeysService::GetPlatformKeysOfExtension(
144     const std::string& extension_id,
145     const GetPlatformKeysCallback& callback) {
146   state_store_->GetExtensionValue(
147       extension_id,
148       kStateStorePlatformKeys,
149       base::Bind(&PlatformKeysService::GotPlatformKeysOfExtension,
150                  weak_factory_.GetWeakPtr(),
151                  extension_id,
152                  callback));
153 }
154
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);
162     return;
163   }
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);
167 }
168
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.";
176     callback.Run(false);
177     return;
178   }
179
180   scoped_ptr<base::StringValue> key_value(
181       GetPublicKeyValue(public_key_spki_der));
182
183   DCHECK(platform_keys->end() == platform_keys->Find(*key_value))
184       << "Keys are assumed to be generated and not to be registered multiple "
185          "times.";
186   platform_keys->Append(key_value.release());
187
188   state_store_->SetExtensionValue(extension_id,
189                                   kStateStorePlatformKeys,
190                                   platform_keys.PassAs<base::Value>());
191   callback.Run(true);
192 }
193
194 void PlatformKeysService::InvalidateKey(
195     const std::string& extension_id,
196     const std::string& public_key_spki_der,
197     const base::Callback<void(bool)>& callback,
198     scoped_ptr<base::ListValue> platform_keys) {
199   scoped_ptr<base::StringValue> key_value(
200       GetPublicKeyValue(public_key_spki_der));
201
202   size_t index = 0;
203   if (!platform_keys->Remove(*key_value, &index)) {
204     // The key is not found, so it's not valid to use it for signing.
205     callback.Run(false);
206     return;
207   }
208
209   state_store_->SetExtensionValue(extension_id,
210                                   kStateStorePlatformKeys,
211                                   platform_keys.PassAs<base::Value>());
212   callback.Run(true);
213 }
214
215 void PlatformKeysService::GotPlatformKeysOfExtension(
216     const std::string& extension_id,
217     const GetPlatformKeysCallback& callback,
218     scoped_ptr<base::Value> value) {
219   if (!value)
220     value.reset(new base::ListValue);
221
222   base::ListValue* keys = NULL;
223   if (!value->GetAsList(&keys)) {
224     LOG(ERROR) << "Found a value of wrong type.";
225     value.reset();
226   }
227   ignore_result(value.release());
228   callback.Run(make_scoped_ptr(keys));
229 }
230
231 }  // namespace chromeos