OLD | NEW |
---|---|
(Empty) | |
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 "chrome/browser/extensions/state_store.h" | |
12 #include "content/public/browser/browser_thread.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| (or false if an error | |
47 // occurred during reading the StateStore). If allowed, starts the actual | |
48 // signing operation which will call back |callback|. If not allowd, calls | |
eroman
2014/06/12 05:50:45
typo: allowd -> allowed
pneubeck (no reviews)
2014/06/12 09:21:37
Done.
| |
49 // |callback| with an error. | |
50 void CheckValidityAndSign(const std::string& token_id, | |
51 const std::string& public_key, | |
52 const std::string& data, | |
53 const PlatformKeysService::SignCallback& callback, | |
54 Profile* profile, | |
55 bool key_is_valid) { | |
56 if (!key_is_valid) { | |
57 callback.Run(std::string() /* no signature */, | |
58 kErrorKeyNotAllowedForSigning); | |
59 return; | |
60 } | |
61 platform_keys::subtle::Sign(token_id, public_key, data, callback, profile); | |
62 } | |
63 | |
64 } // namespace | |
65 | |
66 PlatformKeysService::PlatformKeysService(extensions::StateStore* state_store) | |
67 : state_store_(state_store), weak_factory_(this) { | |
68 DCHECK(state_store); | |
69 } | |
70 | |
71 PlatformKeysService::~PlatformKeysService() { | |
72 } | |
73 | |
74 void PlatformKeysService::GenerateRSAKey(const std::string& token_id, | |
75 unsigned int modulus_length, | |
76 const std::string& extension_id, | |
77 const GenerateKeyCallback& callback, | |
78 Profile* profile) { | |
79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
80 | |
81 platform_keys::subtle::GenerateRSAKey(token_id, | |
82 modulus_length, | |
83 base::Bind(&GenerateRSAKeyCallback, | |
84 extension_id, | |
85 callback, | |
86 weak_factory_.GetWeakPtr()), | |
87 profile); | |
88 } | |
89 | |
90 void PlatformKeysService::Sign(const std::string& token_id, | |
91 const std::string& public_key, | |
92 const std::string& data, | |
93 const std::string& extension_id, | |
94 const SignCallback& callback, | |
95 Profile* profile) { | |
96 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
97 ReadValidityAndInvalidateKey(extension_id, | |
98 public_key, | |
99 base::Bind(&CheckValidityAndSign, | |
100 token_id, | |
101 public_key, | |
102 data, | |
103 callback, | |
104 profile)); | |
105 } | |
106 | |
107 void PlatformKeysService::RegisterPublicKey( | |
108 const std::string& extension_id, | |
109 const std::string& public_key_spki_der, | |
110 const base::Callback<void(bool)>& callback) { | |
111 GetPlatformKeysOfExtension(extension_id, | |
112 base::Bind(&RegisterPublicKeyGotPlatformKeys, | |
113 extension_id, | |
114 public_key_spki_der, | |
115 callback)); | |
116 } | |
117 | |
118 void PlatformKeysService::ReadValidityAndInvalidateKey( | |
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(&InvalidateKey, extension_id, public_key_spki_der, callback)); | |
125 } | |
126 | |
127 void PlatformKeysService::GetPlatformKeysOfExtension( | |
128 const std::string& extension_id, | |
129 const GetPlatformKeysCallback& callback) { | |
130 state_store_->GetExtensionValue(extension_id, | |
131 kStateStorePlatformKeys, | |
132 base::Bind(&GotPlatformKeysOfExtension, | |
133 extension_id, | |
134 weak_factory_.GetWeakPtr(), | |
135 callback)); | |
136 } | |
137 | |
138 // static | |
139 void PlatformKeysService::GenerateRSAKeyCallback( | |
140 const std::string& extension_id, | |
141 const GenerateKeyCallback& callback, | |
142 base::WeakPtr<PlatformKeysService> service, | |
143 const std::string& public_key_spki_der, | |
144 const std::string& error_message) { | |
145 if (!error_message.empty()) { | |
146 callback.Run(std::string() /* no public key */, error_message); | |
147 return; | |
148 } | |
149 base::Callback<void(bool)> wrapped_callback( | |
150 base::Bind(&WrapGenerateKeyCallback, callback, public_key_spki_der)); | |
151 if (!service) { | |
152 LOG(ERROR) << "PlatformKeysService is already destructed."; | |
153 wrapped_callback.Run(false); | |
154 return; | |
155 } | |
156 service->RegisterPublicKey( | |
157 extension_id, public_key_spki_der, wrapped_callback); | |
158 } | |
159 | |
160 // static | |
161 void PlatformKeysService::RegisterPublicKeyGotPlatformKeys( | |
162 const std::string& extension_id, | |
163 const std::string& public_key_spki_der, | |
164 const base::Callback<void(bool)>& callback, | |
165 base::WeakPtr<PlatformKeysService> service, | |
166 scoped_ptr<base::ListValue> platform_keys) { | |
167 if (!service) { | |
168 LOG(ERROR) << "PlatformKeysService is already destructed."; | |
169 callback.Run(false); | |
170 return; | |
171 } | |
172 | |
173 if (!platform_keys) { | |
174 LOG(ERROR) << "Error while reading the platform keys."; | |
175 callback.Run(false); | |
176 return; | |
177 } | |
178 | |
179 scoped_ptr<base::StringValue> key_value( | |
180 GetPublicKeyValue(public_key_spki_der)); | |
181 | |
182 DCHECK(platform_keys->end() == platform_keys->Find(*key_value)) | |
eroman
2014/06/12 05:50:45
This is a DCHECK() because it is assumed keys are
pneubeck (no reviews)
2014/06/12 09:21:37
Yes, updated the error string for clarification.
| |
183 << "Public key is already registered"; | |
184 platform_keys->Append(key_value.release()); | |
eroman
2014/06/12 05:50:45
What sort of bounds checks are done? Is it possibl
pneubeck (no reviews)
2014/06/12 09:21:36
No bounds checks so far. And yes an extension can
| |
185 | |
186 service->state_store_->SetExtensionValue(extension_id, | |
187 kStateStorePlatformKeys, | |
188 platform_keys.PassAs<base::Value>()); | |
189 callback.Run(true); | |
190 } | |
191 | |
192 // static | |
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 base::WeakPtr<PlatformKeysService> service, | |
198 scoped_ptr<base::ListValue> platform_keys) { | |
199 if (!service) { | |
200 LOG(ERROR) << "PlatformKeysService is already destructed."; | |
201 callback.Run(false); | |
202 return; | |
203 } | |
204 | |
205 scoped_ptr<base::StringValue> key_value( | |
206 GetPublicKeyValue(public_key_spki_der)); | |
207 | |
208 size_t index = 0; | |
209 if (!platform_keys->Remove(*key_value, &index)) { | |
210 // The key is not found, so it's not valid to use it for signing. | |
211 callback.Run(false); | |
212 return; | |
213 } | |
214 | |
215 service->state_store_->SetExtensionValue(extension_id, | |
216 kStateStorePlatformKeys, | |
217 platform_keys.PassAs<base::Value>()); | |
218 callback.Run(true); | |
219 } | |
220 | |
221 // static | |
222 void PlatformKeysService::GotPlatformKeysOfExtension( | |
223 const std::string& extension_id, | |
224 base::WeakPtr<PlatformKeysService> service, | |
225 const GetPlatformKeysCallback& callback, | |
226 scoped_ptr<base::Value> value) { | |
227 base::ListValue* keys = NULL; | |
228 if (value) { | |
229 if (!value->GetAsList(&keys)) { | |
230 LOG(ERROR) << "Found a value of wrong type."; | |
231 value.reset(); | |
232 } | |
233 } else { | |
234 keys = new base::ListValue; | |
235 value.reset(keys); | |
eroman
2014/06/12 05:50:45
why bother with this line, when the next one relea
pneubeck (no reviews)
2014/06/12 09:21:37
the intention was that both branches have the same
| |
236 } | |
237 ignore_result(value.release()); | |
238 callback.Run(service, make_scoped_ptr(keys)); | |
239 } | |
240 | |
241 } // namespace chromeos | |
OLD | NEW |