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

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: Addressed comments. Splitted custom_binding, added comments... 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_ns s.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/logging.h"
12 #include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_plat form_keys_api.h"
13 #include "chrome/browser/net/nss_context.h"
14 #include "crypto/rsa_private_key.h"
15 #include "net/base/crypto_module.h"
16 #include "net/base/net_errors.h"
17 #include "net/cert/cert_database.h"
18 #include "net/cert/nss_cert_database.h"
19 #include "net/cert/x509_certificate.h"
20
21 namespace {
22 const char kErrorInternal[] = "Internal Error";
23 const char kErrorKeyNotFound[] = "Key not found.";
24 const char kErrorInvalidX509Cert[] =
25 "Certificate is not a valid X.509 certificate.";
26 const char kErrorCertificateNotFound[] = "Certificate could not be found.";
27 }
28
29 namespace extensions {
30
31 namespace enterprise_platform_keys {
32
33 namespace nss {
34
35 namespace {
36
37 namespace api_epk = api::enterprise_platform_keys;
38 namespace api_epki = api::enterprise_platform_keys_internal;
39
40 typedef base::Callback<bool(scoped_refptr<TokenMethodExtensionFunction> func,
41 crypto::ScopedPK11Slot slot,
42 net::NSSCertDatabase* cert_db)> GetCertDBCallback;
43
44 void DidGetCertDB(scoped_refptr<TokenMethodExtensionFunction> func,
45 const GetCertDBCallback& callback,
46 net::NSSCertDatabase* cert_db) {
47 if (!cert_db) {
48 LOG(ERROR) << "Couldn't get NSSCertDatabase.";
49 func->SetError(kErrorInternal);
50 func->SendResponse(false);
51 return;
52 }
53
54 crypto::ScopedPK11Slot slot = cert_db->GetPrivateSlot();
55 if (!slot) {
56 LOG(ERROR) << "No private slot";
57 func->SetError(kErrorInternal);
58 func->SendResponse(false);
59 return;
60 }
61 if (!callback.Run(func, slot.Pass(), cert_db))
62 func->SendResponse(false);
63 }
64
65 void GetCertDatabase(scoped_refptr<TokenMethodExtensionFunction> func,
66 const std::string& token_id,
67 const GetCertDBCallback& callback) {
68 GetNSSCertDatabaseForProfile(func->GetProfile(),
69 base::Bind(&DidGetCertDB, func, callback));
70 }
71
72 bool GenerateWithDB(scoped_ptr<api_epki::GenerateKey::Params> params,
73 scoped_refptr<TokenMethodExtensionFunction> func,
74 crypto::ScopedPK11Slot slot,
75 net::NSSCertDatabase* cert_db) {
76 scoped_ptr<crypto::RSAPrivateKey> rsa_key(
77 crypto::RSAPrivateKey::CreateSensitive(slot.get(), 512));
78 if (!rsa_key) {
79 LOG(ERROR) << "Couldn't create key.";
80 func->SetError(kErrorInternal);
81 return false;
82 }
83
84 std::vector<uint8> public_key_der;
85 if (!rsa_key->ExportPublicKey(&public_key_der)) {
86 // TODO(pneubeck): Remove rsa_key from storage.
87 LOG(ERROR) << "Couldn't export public key.";
88 func->SetError(kErrorInternal);
89 return false;
90 }
91 std::string public_key_der_str(public_key_der.begin(), public_key_der.end());
92
93 func->SetResults(api_epki::GenerateKey::Results::Create(public_key_der_str));
94 func->SendResponse(true);
95 return true;
96 }
97
98 bool SignWithDB(scoped_ptr<api_epki::Sign::Params> params,
99 scoped_refptr<TokenMethodExtensionFunction> func,
100 crypto::ScopedPK11Slot slot,
101 net::NSSCertDatabase* cert_db) {
102 const std::string& public_key = params->public_key;
103 const uint8* public_key_uint8 =
104 reinterpret_cast<const uint8*>(public_key.data());
105 std::vector<uint8> public_key_vector(public_key_uint8,
106 public_key_uint8 + public_key.size());
107
108 // TODO(pneubeck): This searches all slots. Change to look only at |slot_|.
109 scoped_ptr<crypto::RSAPrivateKey> rsa_key(
110 crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key_vector));
111 if (!rsa_key) {
112 func->SetError(kErrorKeyNotFound);
113 return false;
114 }
115
116 const std::string& data = params->data;
117 SECItem sign_result = {siBuffer, NULL, 0};
118 if (SEC_SignData(&sign_result,
119 reinterpret_cast<const unsigned char*>(data.data()),
120 data.size(),
121 rsa_key->key(),
122 SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION) != SECSuccess) {
123 LOG(ERROR) << "Couldn't sign.";
124 func->SetError(kErrorInternal);
125 return false;
126 }
127
128 std::string signature(reinterpret_cast<const char*>(sign_result.data),
129 sign_result.len);
130 func->SetResults(api_epki::Sign::Results::Create(signature));
131 func->SendResponse(true);
132 return true;
133 }
134
135 void DidGetCerts(scoped_refptr<TokenMethodExtensionFunction> func,
136 crypto::ScopedPK11Slot slot,
137 scoped_ptr<net::CertificateList> certs) {
138 // std::vector<std::string> client_certs;
139 scoped_ptr<base::ListValue> client_certs(new base::ListValue());
140 for (net::CertificateList::const_iterator it = certs->begin();
141 it != certs->end();
142 ++it) {
143 net::X509Certificate::OSCertHandle cert_handle = (*it)->os_cert_handle();
144 crypto::ScopedPK11Slot cert_slot(PK11_KeyForCertExists(cert_handle,
145 NULL, // keyPtr
146 NULL)); // wincx
147
148 // Keep only user certificate, i.e. certs for which the private key is
149 // present, and certs where the private key is stored in the queried slot.
150 if (cert_slot != slot)
151 continue;
152
153 std::string der_encoding;
154 net::X509Certificate::GetDEREncoded(cert_handle, &der_encoding);
155 // client_certs.push_back(der_encoding);
156 client_certs->Append(base::BinaryValue::CreateWithCopiedBuffer(
157 der_encoding.data(), der_encoding.size()));
158 }
159 scoped_ptr<base::ListValue> results(new base::ListValue());
160 results->Append(client_certs.release());
161 func->SetResults(results.Pass());
162 // results_ = api_eci::GetClientCertificates::Results::Create(client_certs);
163 func->SendResponse(true);
164 }
165
166 bool GetCertsWithDB(scoped_ptr<api_epk::GetCertificates::Params> params,
167 scoped_refptr<TokenMethodExtensionFunction> func,
168 crypto::ScopedPK11Slot slot,
169 net::NSSCertDatabase* cert_db) {
170 PK11SlotInfo* slot_ptr = slot.get();
171 cert_db->ListCertsInSlot(base::Bind(&DidGetCerts, func, base::Passed(&slot)),
172 slot_ptr);
173 return true;
174 }
175
176 bool ImportWithDB(scoped_ptr<api_epk::ImportCertificate::Params> params,
177 scoped_refptr<TokenMethodExtensionFunction> func,
178 crypto::ScopedPK11Slot slot,
179 net::NSSCertDatabase* cert_db) {
180 const std::string& certificate = params->certificate;
181 scoped_refptr<net::X509Certificate> cert_x509 =
182 net::X509Certificate::CreateFromBytes(certificate.data(),
183 certificate.size());
184 if (!cert_x509) {
185 func->SetError(kErrorInvalidX509Cert);
186 return false;
187 }
188
189 net::CertDatabase* db = net::CertDatabase::GetInstance();
190
191 const net::Error cert_status = db->CheckUserCert(cert_x509);
192 if (cert_status == net::ERR_NO_PRIVATE_KEY_FOR_CERT) {
193 func->SetError(kErrorKeyNotFound);
194 return false;
195 } else if (cert_status != net::OK) {
196 func->SetError(net::ErrorToString(cert_status));
197 return false;
198 }
199
200 const net::Error import_status = db->AddUserCert(cert_x509.get());
201 if (import_status != net::OK) {
202 LOG(ERROR) << "Could not import certificate.";
203 func->SetError(net::ErrorToString(import_status));
204 return false;
205 }
206
207 func->SendResponse(true);
208 return true;
209 }
210
211 bool RemoveWithDB(scoped_ptr<api_epk::RemoveCertificate::Params> params,
212 scoped_refptr<TokenMethodExtensionFunction> func,
213 crypto::ScopedPK11Slot slot,
214 net::NSSCertDatabase* cert_db) {
215 const std::string& certificate = params->certificate;
216 scoped_refptr<net::X509Certificate> cert_x509 =
217 net::X509Certificate::CreateFromBytes(certificate.data(),
218 certificate.size());
219 if (!cert_x509) {
220 func->SetError(kErrorInvalidX509Cert);
221 return false;
222 }
223
224 bool certificate_found = cert_x509->os_cert_handle()->isperm;
225 bool success = cert_db->DeleteCertAndKey(cert_x509);
226
227 // CertificateNotFound error has precedence over an internal error.
228 if (!certificate_found) {
229 func->SetError(kErrorCertificateNotFound);
230 return false;
231 }
232 if (!success) {
233 func->SetError(kErrorInternal);
234 return false;
235 }
236
237 func->SendResponse(true);
238 return true;
239 }
240
241 } // namespace
242
243 void Generate(scoped_refptr<TokenMethodExtensionFunction> func,
244 scoped_ptr<api_epki::GenerateKey::Params> params) {
245 GetCertDatabase(func,
246 params->token_id,
247 base::Bind(GenerateWithDB, base::Passed(&params)));
248 }
249
250 void Sign(scoped_refptr<TokenMethodExtensionFunction> func,
251 scoped_ptr<api_epki::Sign::Params> params) {
252 GetCertDatabase(
253 func, params->token_id, base::Bind(SignWithDB, base::Passed(&params)));
254 }
255
256 void GetCerts(scoped_refptr<TokenMethodExtensionFunction> func,
257 scoped_ptr<api_epk::GetCertificates::Params> params) {
258 GetCertDatabase(func,
259 params->token_id,
260 base::Bind(GetCertsWithDB, base::Passed(&params)));
261 }
262
263 void Import(scoped_refptr<TokenMethodExtensionFunction> func,
264 scoped_ptr<api_epk::ImportCertificate::Params> params) {
265 GetCertDatabase(
266 func, params->token_id, base::Bind(ImportWithDB, base::Passed(&params)));
267 }
268
269 void Remove(scoped_refptr<TokenMethodExtensionFunction> func,
270 scoped_ptr<api_epk::RemoveCertificate::Params> params) {
271 GetCertDatabase(
272 func, params->token_id, base::Bind(RemoveWithDB, base::Passed(&params)));
273 }
274
275 } // namespace nss
276
277 } // namespace enterprise_platform_keys
278
279 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698