Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: chrome/browser/chromeos/platform_keys/platform_keys_nss.cc

Issue 214863002: Extension API enterprise.platformKeys. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Removed 'location: policy' comment. Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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.h"
6
7 #include <cryptohi.h>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback.h"
12 #include "base/compiler_specific.h"
13 #include "base/logging.h"
14 #include "base/memory/weak_ptr.h"
15 #include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_plat form_keys_api.h"
16 #include "chrome/browser/net/nss_context.h"
17 #include "crypto/rsa_private_key.h"
18 #include "net/base/crypto_module.h"
19 #include "net/base/net_errors.h"
20 #include "net/cert/cert_database.h"
21 #include "net/cert/nss_cert_database.h"
22 #include "net/cert/x509_certificate.h"
23
24 namespace {
25 const char kErrorInternal[] = "Internal Error.";
26 const char kErrorKeyNotFound[] = "Key not found.";
27 const char kErrorCertificateNotFound[] = "Certificate could not be found.";
28 const char kErrorAlgorithmNotSupported[] = "Algorithm not supported.";
29 }
30
31 namespace chromeos {
32
33 namespace platform_keys {
34
35 namespace {
36
37 // Base class to store state that is common to all NSS database operations and
38 // to provide convenience methods to callback.
39 class NSSOperationState {
40 public:
41 explicit NSSOperationState(Profile* profile);
42 virtual ~NSSOperationState() {}
43
44 // Called if an error occurred during the execution of the NSS operation
45 // described by this object.
46 virtual void OnError(const std::string& error_message) = 0;
47
48 Profile* profile_;
49 crypto::ScopedPK11Slot slot_;
50 net::NSSCertDatabase* cert_db_;
51
52 private:
53 DISALLOW_COPY_AND_ASSIGN(NSSOperationState);
54 };
55
56 typedef base::Closure GetCertDBCallback;
57
58 // Callback of GetCertDatabase. Called back with the NSSCertDatabase.
59 void DidGetCertDB(const GetCertDBCallback& callback,
60 NSSOperationState* state,
61 net::NSSCertDatabase* cert_db) {
62 if (!cert_db) {
63 LOG(ERROR) << "Couldn't get NSSCertDatabase.";
64 state->OnError(kErrorInternal);
65 return;
66 }
67
68 state->cert_db_ = cert_db;
69 state->slot_ = cert_db->GetPrivateSlot();
70 if (!state->slot_) {
71 LOG(ERROR) << "No private slot";
72 state->OnError(kErrorInternal);
73 return;
74 }
75 callback.Run();
76 }
77
78 // Asynchronously fetches the NSSCertDatabase for |token_id| and passes it to
79 // |callback|.
80 void GetCertDatabase(const std::string& token_id,
81 const GetCertDBCallback& callback,
82 NSSOperationState* state) {
83 GetNSSCertDatabaseForProfile(state->profile_,
84 base::Bind(&DidGetCertDB, callback, state));
85 }
86
87 class GenerateRSAKeyState : public NSSOperationState {
88 public:
89 GenerateRSAKeyState(int modulus_length,
90 const GenerateKeyCallback& callback,
91 Profile* profile);
92 virtual ~GenerateRSAKeyState() {}
93
94 virtual void OnError(const std::string& error_message) OVERRIDE {
95 callback_.Run(std::string() /* no public key */, error_message);
96 }
97
98 int modulus_length_;
99 GenerateKeyCallback callback_;
100 };
101
102 class SignState : public NSSOperationState {
103 public:
104 SignState(const std::string& public_key,
105 const std::string& data,
106 const SignCallback& callback,
107 Profile* profile);
108 virtual ~SignState() {}
109
110 virtual void OnError(const std::string& error_message) OVERRIDE {
111 callback_.Run(std::string() /* no signature */, error_message);
112 }
113
114 std::string public_key_;
115 std::string data_;
116 SignCallback callback_;
117 };
118
119 class GetCertificatesState : public NSSOperationState {
120 public:
121 GetCertificatesState(const GetCertificatesCallback& callback,
122 Profile* profile);
123 virtual ~GetCertificatesState() {}
124
125 virtual void OnError(const std::string& error_message) OVERRIDE {
126 callback_.Run(scoped_ptr<net::CertificateList>() /* no certificates */,
127 error_message);
128 }
129
130 GetCertificatesCallback callback_;
131 };
132
133 class ImportCertificateState : public NSSOperationState {
134 public:
135 ImportCertificateState(scoped_refptr<net::X509Certificate> certificate,
136 const ImportCertificateCallback& callback,
137 Profile* profile);
138 virtual ~ImportCertificateState() {}
139
140 virtual void OnError(const std::string& error_message) OVERRIDE {
141 callback_.Run(error_message);
142 }
143
144 scoped_refptr<net::X509Certificate> certificate_;
145 ImportCertificateCallback callback_;
146 };
147
148 class RemoveCertificateState : public NSSOperationState {
149 public:
150 RemoveCertificateState(scoped_refptr<net::X509Certificate> certificate,
151 const RemoveCertificateCallback& callback,
152 Profile* profile);
153 virtual ~RemoveCertificateState() {}
154
155 virtual void OnError(const std::string& error_message) OVERRIDE {
156 callback_.Run(error_message);
157 }
158
159 scoped_refptr<net::X509Certificate> certificate_;
160 RemoveCertificateCallback callback_;
161 };
162
163 NSSOperationState::NSSOperationState(Profile* profile)
164 : profile_(profile), cert_db_(NULL) {
165 }
166
167 GenerateRSAKeyState::GenerateRSAKeyState(int modulus_length,
168 const GenerateKeyCallback& callback,
169 Profile* profile)
170 : NSSOperationState(profile),
171 modulus_length_(modulus_length),
172 callback_(callback) {
173 }
174
175 SignState::SignState(const std::string& public_key,
176 const std::string& data,
177 const SignCallback& callback,
178 Profile* profile)
179 : NSSOperationState(profile),
180 public_key_(public_key),
181 data_(data),
182 callback_(callback) {
183 }
184
185 GetCertificatesState::GetCertificatesState(
186 const GetCertificatesCallback& callback,
187 Profile* profile)
188 : NSSOperationState(profile), callback_(callback) {
189 }
190
191 ImportCertificateState::ImportCertificateState(
192 scoped_refptr<net::X509Certificate> certificate,
193 const ImportCertificateCallback& callback,
194 Profile* profile)
195 : NSSOperationState(profile),
196 certificate_(certificate),
197 callback_(callback) {
198 }
199
200 RemoveCertificateState::RemoveCertificateState(
201 scoped_refptr<net::X509Certificate> certificate,
202 const RemoveCertificateCallback& callback,
203 Profile* profile)
204 : NSSOperationState(profile),
205 certificate_(certificate),
206 callback_(callback) {
207 }
208
209 // Continues generating a RSA key with the obtained NSSCertDatabase. Used by
210 // GenerateRSAKey().
211 void GenerateRSAKeyWithDB(scoped_ptr<GenerateRSAKeyState> state) {
212 if (state->modulus_length_ > 2048) {
213 state->OnError(kErrorAlgorithmNotSupported);
214 return;
215 }
216 scoped_ptr<crypto::RSAPrivateKey> rsa_key(
217 crypto::RSAPrivateKey::CreateSensitive(state->slot_.get(),
218 state->modulus_length_));
219 if (!rsa_key) {
220 LOG(ERROR) << "Couldn't create key.";
221 state->OnError(kErrorInternal);
222 return;
223 }
224
225 std::vector<uint8> public_key_der;
226 if (!rsa_key->ExportPublicKey(&public_key_der)) {
227 // TODO(pneubeck): Remove rsa_key from storage.
228 LOG(ERROR) << "Couldn't export public key.";
229 state->OnError(kErrorInternal);
230 return;
231 }
232 std::string public_key_der_str(public_key_der.begin(), public_key_der.end());
233 state->callback_.Run(public_key_der_str, std::string() /* no error */);
234 }
235
236 // Continues signing with the obtained NSSCertDatabase. Used by Sign().
237 void RSASignWithDB(scoped_ptr<SignState> state) {
238 const uint8* public_key_uint8 =
239 reinterpret_cast<const uint8*>(state->public_key_.data());
240 std::vector<uint8> public_key_vector(
241 public_key_uint8, public_key_uint8 + state->public_key_.size());
242
243 // TODO(pneubeck): This searches all slots. Change to look only at |slot_|.
244 scoped_ptr<crypto::RSAPrivateKey> rsa_key(
245 crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key_vector));
246 if (!rsa_key) {
247 state->OnError(kErrorKeyNotFound);
248 return;
249 }
250
251 SECItem sign_result = {siBuffer, NULL, 0};
252 if (SEC_SignData(&sign_result,
253 reinterpret_cast<const unsigned char*>(state->data_.data()),
254 state->data_.size(),
255 rsa_key->key(),
256 SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION) != SECSuccess) {
257 LOG(ERROR) << "Couldn't sign.";
258 state->OnError(kErrorInternal);
259 return;
260 }
261
262 std::string signature(reinterpret_cast<const char*>(sign_result.data),
263 sign_result.len);
264 state->callback_.Run(signature, std::string() /* no error */);
265 }
266
267 // Continues getting certificates with the certificates returned by
268 // NSSCertDatabase::ListCertsInSlot. Used by GetCertificatesWithDB().
269 void DidGetCertificates(scoped_ptr<GetCertificatesState> state,
270 scoped_ptr<net::CertificateList> all_certs) {
271 scoped_ptr<net::CertificateList> client_certs(new net::CertificateList);
272 for (net::CertificateList::const_iterator it = all_certs->begin();
273 it != all_certs->end();
274 ++it) {
275 net::X509Certificate::OSCertHandle cert_handle = (*it)->os_cert_handle();
276 crypto::ScopedPK11Slot cert_slot(PK11_KeyForCertExists(cert_handle,
277 NULL, // keyPtr
278 NULL)); // wincx
279
280 // Keep only user certificates, i.e. certs for which the private key is
281 // present and stored in the queried slot.
282 if (cert_slot != state->slot_)
283 continue;
284
285 client_certs->push_back(*it);
286 }
287
288 state->callback_.Run(client_certs.Pass(), std::string() /* no error */);
289 }
290
291 // Continues getting certificates with the obtained NSSCertDatabase. Used by
292 // GetCertificates().
293 void GetCertificatesWithDB(scoped_ptr<GetCertificatesState> state) {
294 // Get the pointer to slot before base::Passed releases |state|.
295 PK11SlotInfo* slot = state->slot_.get();
296 state->cert_db_->ListCertsInSlot(
297 base::Bind(&DidGetCertificates, base::Passed(&state)), slot);
298 }
299
300 // Continues certificate importing with the obtained NSSCertDatabase. Used by
301 // ImportCertificate().
302 void ImportCertificateWithDB(scoped_ptr<ImportCertificateState> state) {
303 net::CertDatabase* db = net::CertDatabase::GetInstance();
304
305 const net::Error cert_status = db->CheckUserCert(state->certificate_);
306 if (cert_status == net::ERR_NO_PRIVATE_KEY_FOR_CERT) {
307 state->OnError(kErrorKeyNotFound);
308 return;
309 } else if (cert_status != net::OK) {
310 state->OnError(net::ErrorToString(cert_status));
311 return;
312 }
313
314 const net::Error import_status = db->AddUserCert(state->certificate_.get());
315 if (import_status != net::OK) {
316 LOG(ERROR) << "Could not import certificate.";
317 state->OnError(net::ErrorToString(import_status));
318 return;
319 }
320
321 state->callback_.Run(std::string() /* no error */);
322 }
323
324 // Continues certificate removal with the obtained NSSCertDatabase. Used by
325 // RemoveCertificate().
326 void RemoveCertificateWithDB(scoped_ptr<RemoveCertificateState> state) {
327 bool certificate_found = state->certificate_->os_cert_handle()->isperm;
328 bool success = state->cert_db_->DeleteCertAndKey(state->certificate_);
329
330 // CertificateNotFound error has precedence over an internal error.
331 if (!certificate_found) {
332 state->OnError(kErrorCertificateNotFound);
333 return;
334 }
335 if (!success) {
336 state->OnError(kErrorInternal);
337 return;
338 }
339
340 state->callback_.Run(std::string() /* no error */);
341 }
342
343 } // namespace
344
345 void GenerateRSAKey(const std::string& token_id,
346 int modulus_length,
347 const GenerateKeyCallback& callback,
348 Profile* profile) {
349 scoped_ptr<GenerateRSAKeyState> state(
350 new GenerateRSAKeyState(modulus_length, callback, profile));
351 // Get the pointer to |state| before base::Passed releases |state|.
352 NSSOperationState* state_ptr = state.get();
353 GetCertDatabase(token_id,
354 base::Bind(&GenerateRSAKeyWithDB, base::Passed(&state)),
355 state_ptr);
356 }
357
358 void Sign(const std::string& token_id,
359 const std::string& public_key,
360 const std::string& data,
361 const SignCallback& callback,
362 Profile* profile) {
363 scoped_ptr<SignState> state(
364 new SignState(public_key, data, callback, profile));
365 // Get the pointer to |state| before base::Passed releases |state|.
366 NSSOperationState* state_ptr = state.get();
367 GetCertDatabase(
368 token_id, base::Bind(&RSASignWithDB, base::Passed(&state)), state_ptr);
369 }
370
371 void GetCertificates(const std::string& token_id,
372 const GetCertificatesCallback& callback,
373 Profile* profile) {
374 scoped_ptr<GetCertificatesState> state(
375 new GetCertificatesState(callback, profile));
376 // Get the pointer to |state| before base::Passed releases |state|.
377 NSSOperationState* state_ptr = state.get();
378 GetCertDatabase(token_id,
379 base::Bind(&GetCertificatesWithDB, base::Passed(&state)),
380 state_ptr);
381 }
382
383 void ImportCertificate(const std::string& token_id,
384 scoped_refptr<net::X509Certificate> certificate,
385 const ImportCertificateCallback& callback,
386 Profile* profile) {
387 scoped_ptr<ImportCertificateState> state(
388 new ImportCertificateState(certificate, callback, profile));
389 // Get the pointer to |state| before base::Passed releases |state|.
390 NSSOperationState* state_ptr = state.get();
391 GetCertDatabase(token_id,
392 base::Bind(&ImportCertificateWithDB, base::Passed(&state)),
393 state_ptr);
394 }
395
396 void RemoveCertificate(const std::string& token_id,
397 scoped_refptr<net::X509Certificate> certificate,
398 const RemoveCertificateCallback& callback,
399 Profile* profile) {
400 scoped_ptr<RemoveCertificateState> state(
401 new RemoveCertificateState(certificate, callback, profile));
402 // Get the pointer to |state| before base::Passed releases |state|.
403 NSSOperationState* state_ptr = state.get();
404 GetCertDatabase(token_id,
405 base::Bind(&RemoveCertificateWithDB, base::Passed(&state)),
406 state_ptr);
407 }
408
409 } // namespace platform_keys
410
411 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698