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

Side by Side Diff: chrome/browser/extensions/api/enterprise_platform_keys/token_method_nss.cc

Issue 214863002: Extension API enterprise.platformKeys. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Removed some namespaces, changed ownership, more documentation 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/extensions/api/enterprise_platform_keys/token_method.h"
6
7 #include <cryptohi.h>
8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
10 #include "base/callback.h"
11 #include "base/compiler_specific.h"
12 #include "base/logging.h"
13 #include "base/memory/weak_ptr.h"
14 #include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_plat form_keys_api.h"
15 #include "chrome/browser/net/nss_context.h"
16 #include "crypto/rsa_private_key.h"
17 #include "net/base/crypto_module.h"
18 #include "net/base/net_errors.h"
19 #include "net/cert/cert_database.h"
20 #include "net/cert/nss_cert_database.h"
21 #include "net/cert/x509_certificate.h"
22
23 namespace {
24 const char kErrorInternal[] = "Internal Error";
25 const char kErrorKeyNotFound[] = "Key not found.";
26 const char kErrorInvalidX509Cert[] =
27 "Certificate is not a valid X.509 certificate.";
28 const char kErrorCertificateNotFound[] = "Certificate could not be found.";
29 const char kErrorAlgorithmNotSupported[] = "Algorithm not supported.";
30 }
31
32 namespace extensions {
33
34 namespace enterprise_platform_keys_details {
35
36 namespace {
37
38 namespace api_epk = api::enterprise_platform_keys;
39 namespace api_epki = api::enterprise_platform_keys_internal;
40
41 typedef base::Callback<void(crypto::ScopedPK11Slot slot,
42 net::NSSCertDatabase* cert_db)> GetCertDBCallback;
43
44 void DidGetCertDB(const GetCertDBCallback& callback,
45 EnterprisePlatformKeysTokenMethodExtensionFunction* func,
46 net::NSSCertDatabase* cert_db) {
47 if (!cert_db) {
48 LOG(ERROR) << "Couldn't get NSSCertDatabase.";
49 func->RespondWithError(kErrorInternal);
50 return;
51 }
52
53 crypto::ScopedPK11Slot slot = cert_db->GetPrivateSlot();
54 if (!slot) {
55 LOG(ERROR) << "No private slot";
56 func->RespondWithError(kErrorInternal);
57 return;
58 }
59 callback.Run(slot.Pass(), cert_db);
60 }
61
62 void GetCertDatabase(const std::string& token_id,
63 const GetCertDBCallback& callback,
64 EnterprisePlatformKeysTokenMethodExtensionFunction* func) {
65 GetNSSCertDatabaseForProfile(
66 func->GetProfile(),
67 base::Bind(&DidGetCertDB, callback, base::Unretained(func)));
68 }
69
70 class GenerateKey : public TokenMethod {
71 public:
72 GenerateKey(scoped_ptr<api_epki::GenerateKey::Params> params,
73 EnterprisePlatformKeysTokenMethodExtensionFunction* func);
74 virtual ~GenerateKey() {}
75 virtual void Run() OVERRIDE;
76
77 void DidGetDB(crypto::ScopedPK11Slot slot, net::NSSCertDatabase* cert_db);
78
79 private:
80 scoped_ptr<api_epki::GenerateKey::Params> params_;
81 base::WeakPtrFactory<GenerateKey> weak_factory_;
82 };
83
84 class Sign : public TokenMethod {
85 public:
86 Sign(scoped_ptr<api_epki::Sign::Params> params,
87 EnterprisePlatformKeysTokenMethodExtensionFunction* func);
88 virtual ~Sign() {}
89 virtual void Run() OVERRIDE;
90
91 void DidGetDB(crypto::ScopedPK11Slot slot, net::NSSCertDatabase* cert_db);
92
93 private:
94 scoped_ptr<api_epki::Sign::Params> params_;
95 base::WeakPtrFactory<Sign> weak_factory_;
96 };
97
98 class GetCertificates : public TokenMethod {
99 public:
100 GetCertificates(scoped_ptr<api_epk::GetCertificates::Params> params,
101 EnterprisePlatformKeysTokenMethodExtensionFunction* func);
102 virtual ~GetCertificates() {}
103 virtual void Run() OVERRIDE;
104
105 void DidGetDB(crypto::ScopedPK11Slot slot, net::NSSCertDatabase* cert_db);
106 void DidGetCertificates(scoped_ptr<net::CertificateList> certs);
107
108 private:
109 scoped_ptr<api_epk::GetCertificates::Params> params_;
110 crypto::ScopedPK11Slot slot_;
111 base::WeakPtrFactory<GetCertificates> weak_factory_;
112 };
113
114 class ImportCertificate : public TokenMethod {
115 public:
116 ImportCertificate(scoped_ptr<api_epk::ImportCertificate::Params> params,
117 EnterprisePlatformKeysTokenMethodExtensionFunction* func);
118 virtual ~ImportCertificate() {}
119 virtual void Run() OVERRIDE;
120
121 void DidGetDB(crypto::ScopedPK11Slot slot, net::NSSCertDatabase* cert_db);
122
123 private:
124 scoped_ptr<api_epk::ImportCertificate::Params> params_;
125 base::WeakPtrFactory<ImportCertificate> weak_factory_;
126 };
127
128 class RemoveCertificate : public TokenMethod {
129 public:
130 RemoveCertificate(scoped_ptr<api_epk::RemoveCertificate::Params> params,
131 EnterprisePlatformKeysTokenMethodExtensionFunction* func);
132 virtual ~RemoveCertificate() {}
133 virtual void Run() OVERRIDE;
134
135 void DidGetDB(crypto::ScopedPK11Slot slot, net::NSSCertDatabase* cert_db);
136
137 private:
138 scoped_ptr<api_epk::RemoveCertificate::Params> params_;
139 base::WeakPtrFactory<RemoveCertificate> weak_factory_;
140 };
141
142 GenerateKey::GenerateKey(
143 scoped_ptr<api_epki::GenerateKey::Params> params,
144 EnterprisePlatformKeysTokenMethodExtensionFunction* func)
145 : TokenMethod(func), params_(params.Pass()), weak_factory_(this) {
146 }
147
148 void GenerateKey::Run() {
149 GetCertDatabase(
150 params_->token_id,
151 base::Bind(&GenerateKey::DidGetDB, weak_factory_.GetWeakPtr()),
152 func_);
153 }
154
155 void GenerateKey::DidGetDB(crypto::ScopedPK11Slot slot,
156 net::NSSCertDatabase* cert_db) {
157 const int modulus_length = params_->modulus_length;
158 if (modulus_length > 2048) {
159 func_->RespondWithError(kErrorAlgorithmNotSupported);
160 return;
161 }
162 scoped_ptr<crypto::RSAPrivateKey> rsa_key(
163 crypto::RSAPrivateKey::CreateSensitive(slot.get(), modulus_length));
164 if (!rsa_key) {
165 LOG(ERROR) << "Couldn't create key.";
166 func_->RespondWithError(kErrorInternal);
167 return;
168 }
169
170 std::vector<uint8> public_key_der;
171 if (!rsa_key->ExportPublicKey(&public_key_der)) {
172 // TODO(pneubeck): Remove rsa_key from storage.
173 LOG(ERROR) << "Couldn't export public key.";
174 func_->RespondWithError(kErrorInternal);
175 return;
176 }
177 std::string public_key_der_str(public_key_der.begin(), public_key_der.end());
178
179 func_->RespondWithResults(
180 api_epki::GenerateKey::Results::Create(public_key_der_str));
181 }
182
183 Sign::Sign(scoped_ptr<api_epki::Sign::Params> params,
184 EnterprisePlatformKeysTokenMethodExtensionFunction* func)
185 : TokenMethod(func), params_(params.Pass()), weak_factory_(this) {
186 }
187
188 void Sign::Run() {
189 GetCertDatabase(params_->token_id,
190 base::Bind(&Sign::DidGetDB, weak_factory_.GetWeakPtr()),
191 func_);
192 }
193
194 void Sign::DidGetDB(crypto::ScopedPK11Slot slot,
195 net::NSSCertDatabase* cert_db) {
196 const std::string& public_key = params_->public_key;
197 const uint8* public_key_uint8 =
198 reinterpret_cast<const uint8*>(public_key.data());
199 std::vector<uint8> public_key_vector(public_key_uint8,
200 public_key_uint8 + public_key.size());
201
202 // TODO(pneubeck): This searches all slots. Change to look only at |slot_|.
203 scoped_ptr<crypto::RSAPrivateKey> rsa_key(
204 crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key_vector));
205 if (!rsa_key) {
206 func_->RespondWithError(kErrorKeyNotFound);
207 return;
208 }
209
210 const std::string& data = params_->data;
211 SECItem sign_result = {siBuffer, NULL, 0};
212 if (SEC_SignData(&sign_result,
213 reinterpret_cast<const unsigned char*>(data.data()),
214 data.size(),
215 rsa_key->key(),
216 SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION) != SECSuccess) {
217 LOG(ERROR) << "Couldn't sign.";
218 func_->RespondWithError(kErrorInternal);
219 return;
220 }
221
222 std::string signature(reinterpret_cast<const char*>(sign_result.data),
223 sign_result.len);
224 func_->RespondWithResults(api_epki::Sign::Results::Create(signature));
225 }
226
227 GetCertificates::GetCertificates(
228 scoped_ptr<api_epk::GetCertificates::Params> params,
229 EnterprisePlatformKeysTokenMethodExtensionFunction* func)
230 : TokenMethod(func), params_(params.Pass()), weak_factory_(this) {
231 }
232
233 void GetCertificates::Run() {
234 GetCertDatabase(
235 params_->token_id,
236 base::Bind(&GetCertificates::DidGetDB, weak_factory_.GetWeakPtr()),
237 func_);
238 }
239
240 void GetCertificates::DidGetDB(crypto::ScopedPK11Slot slot,
241 net::NSSCertDatabase* cert_db) {
242 slot_ = slot.Pass();
243 cert_db->ListCertsInSlot(base::Bind(&GetCertificates::DidGetCertificates,
244 weak_factory_.GetWeakPtr()),
245 slot_.get());
246 }
247
248 void GetCertificates::DidGetCertificates(
249 scoped_ptr<net::CertificateList> certs) {
250 // std::vector<std::string> client_certs;
251 scoped_ptr<base::ListValue> client_certs(new base::ListValue());
252 for (net::CertificateList::const_iterator it = certs->begin();
253 it != certs->end();
254 ++it) {
255 net::X509Certificate::OSCertHandle cert_handle = (*it)->os_cert_handle();
256 crypto::ScopedPK11Slot cert_slot(PK11_KeyForCertExists(cert_handle,
257 NULL, // keyPtr
258 NULL)); // wincx
259
260 // Keep only user certificate, i.e. certs for which the private key is
261 // present, and certs where the private key is stored in the queried slot.
262 if (cert_slot != slot_)
263 continue;
264
265 std::string der_encoding;
266 net::X509Certificate::GetDEREncoded(cert_handle, &der_encoding);
267 // client_certs.push_back(der_encoding);
268 client_certs->Append(base::BinaryValue::CreateWithCopiedBuffer(
269 der_encoding.data(), der_encoding.size()));
270 }
271 scoped_ptr<base::ListValue> results(new base::ListValue());
272 results->Append(client_certs.release());
273 func_->RespondWithResults(results.Pass());
274 // results_ = api_eci::GetClientCertificates::Results::Create(client_certs);
275 }
276
277 ImportCertificate::ImportCertificate(
278 scoped_ptr<api_epk::ImportCertificate::Params> params,
279 EnterprisePlatformKeysTokenMethodExtensionFunction* func)
280 : TokenMethod(func), params_(params.Pass()), weak_factory_(this) {
281 }
282
283 void ImportCertificate::Run() {
284 GetCertDatabase(
285 params_->token_id,
286 base::Bind(&ImportCertificate::DidGetDB, weak_factory_.GetWeakPtr()),
287 func_);
288 }
289
290 void ImportCertificate::DidGetDB(crypto::ScopedPK11Slot slot,
291 net::NSSCertDatabase* cert_db) {
292 const std::string& certificate = params_->certificate;
293 scoped_refptr<net::X509Certificate> cert_x509 =
294 net::X509Certificate::CreateFromBytes(certificate.data(),
295 certificate.size());
296 if (!cert_x509) {
297 func_->RespondWithError(kErrorInvalidX509Cert);
298 return;
299 }
300
301 net::CertDatabase* db = net::CertDatabase::GetInstance();
302
303 const net::Error cert_status = db->CheckUserCert(cert_x509);
304 if (cert_status == net::ERR_NO_PRIVATE_KEY_FOR_CERT) {
305 func_->RespondWithError(kErrorKeyNotFound);
306 return;
307 } else if (cert_status != net::OK) {
308 func_->RespondWithError(net::ErrorToString(cert_status));
309 return;
310 }
311
312 const net::Error import_status = db->AddUserCert(cert_x509.get());
313 if (import_status != net::OK) {
314 LOG(ERROR) << "Could not import certificate.";
315 func_->RespondWithError(net::ErrorToString(import_status));
316 return;
317 }
318
319 func_->RespondWithoutResult();
320 }
321
322 RemoveCertificate::RemoveCertificate(
323 scoped_ptr<api_epk::RemoveCertificate::Params> params,
324 EnterprisePlatformKeysTokenMethodExtensionFunction* func)
325 : TokenMethod(func), params_(params.Pass()), weak_factory_(this) {
326 }
327
328 void RemoveCertificate::Run() {
329 GetCertDatabase(
330 params_->token_id,
331 base::Bind(&RemoveCertificate::DidGetDB, weak_factory_.GetWeakPtr()),
332 func_);
333 }
334
335 void RemoveCertificate::DidGetDB(crypto::ScopedPK11Slot slot,
336 net::NSSCertDatabase* cert_db) {
337 const std::string& certificate = params_->certificate;
338 scoped_refptr<net::X509Certificate> cert_x509 =
339 net::X509Certificate::CreateFromBytes(certificate.data(),
340 certificate.size());
341 if (!cert_x509) {
342 func_->RespondWithError(kErrorInvalidX509Cert);
343 return;
344 }
345
346 bool certificate_found = cert_x509->os_cert_handle()->isperm;
347 bool success = cert_db->DeleteCertAndKey(cert_x509);
348
349 // CertificateNotFound error has precedence over an internal error.
350 if (!certificate_found) {
351 func_->RespondWithError(kErrorCertificateNotFound);
352 return;
353 }
354 if (!success) {
355 func_->RespondWithError(kErrorInternal);
356 return;
357 }
358
359 func_->RespondWithoutResult();
360 }
361
362 } // namespace
363
364 scoped_ptr<TokenMethod> CreateGenerateKey(
365 scoped_ptr<api_epki::GenerateKey::Params> params,
366 EnterprisePlatformKeysTokenMethodExtensionFunction* func) {
367 return scoped_ptr<TokenMethod>(new GenerateKey(params.Pass(), func));
368 }
369
370 scoped_ptr<TokenMethod> CreateSign(
371 scoped_ptr<api_epki::Sign::Params> params,
372 EnterprisePlatformKeysTokenMethodExtensionFunction* func) {
373 return scoped_ptr<TokenMethod>(new Sign(params.Pass(), func));
374 }
375
376 scoped_ptr<TokenMethod> CreateGetCertificates(
377 scoped_ptr<api_epk::GetCertificates::Params> params,
378 EnterprisePlatformKeysTokenMethodExtensionFunction* func) {
379 return scoped_ptr<TokenMethod>(new GetCertificates(params.Pass(), func));
380 }
381
382 scoped_ptr<TokenMethod> CreateImportCertificate(
383 scoped_ptr<api_epk::ImportCertificate::Params> params,
384 EnterprisePlatformKeysTokenMethodExtensionFunction* func) {
385 return scoped_ptr<TokenMethod>(new ImportCertificate(params.Pass(), func));
386 }
387
388 scoped_ptr<TokenMethod> CreateRemoveCertificate(
389 scoped_ptr<api_epk::RemoveCertificate::Params> params,
390 EnterprisePlatformKeysTokenMethodExtensionFunction* func) {
391 return scoped_ptr<TokenMethod>(new RemoveCertificate(params.Pass(), func));
392 }
393
394 } // namespace enterprise_platform_keys_details
395
396 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698