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

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: json -> idl, use ChromeUIThreadExtFun, split key.js, ... 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 const char kErrorAlgorithmNotSupported[] = "Algorithm not supported.";
28 }
29
30 namespace extensions {
31
32 namespace enterprise_platform_keys {
33
34 namespace nss {
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(scoped_refptr<TokenMethodExtensionFunction> func,
42 crypto::ScopedPK11Slot slot,
43 net::NSSCertDatabase* cert_db)> GetCertDBCallback;
44
45 void DidGetCertDB(scoped_refptr<TokenMethodExtensionFunction> func,
46 const GetCertDBCallback& callback,
47 net::NSSCertDatabase* cert_db) {
48 if (!cert_db) {
49 LOG(ERROR) << "Couldn't get NSSCertDatabase.";
50 func->RespondWithError(kErrorInternal);
51 return;
52 }
53
54 crypto::ScopedPK11Slot slot = cert_db->GetPrivateSlot();
55 if (!slot) {
56 LOG(ERROR) << "No private slot";
57 func->RespondWithError(kErrorInternal);
58 return;
59 }
60 callback.Run(func, slot.Pass(), cert_db);
61 }
62
63 void GetCertDatabase(scoped_refptr<TokenMethodExtensionFunction> func,
64 const std::string& token_id,
65 const GetCertDBCallback& callback) {
66 GetNSSCertDatabaseForProfile(func->GetProfile(),
67 base::Bind(&DidGetCertDB, func, callback));
68 }
69
70 void GenerateWithDB(scoped_ptr<api_epki::GenerateKey::Params> params,
71 scoped_refptr<TokenMethodExtensionFunction> func,
72 crypto::ScopedPK11Slot slot,
73 net::NSSCertDatabase* cert_db) {
74 const int modulus_length = params->modulus_length;
75 if (modulus_length > 2048) {
76 func->RespondWithError(kErrorAlgorithmNotSupported);
77 return;
78 }
79 scoped_ptr<crypto::RSAPrivateKey> rsa_key(
80 crypto::RSAPrivateKey::CreateSensitive(slot.get(), modulus_length));
81 if (!rsa_key) {
82 LOG(ERROR) << "Couldn't create key.";
83 func->RespondWithError(kErrorInternal);
84 return;
85 }
86
87 std::vector<uint8> public_key_der;
88 if (!rsa_key->ExportPublicKey(&public_key_der)) {
89 // TODO(pneubeck): Remove rsa_key from storage.
90 LOG(ERROR) << "Couldn't export public key.";
91 func->RespondWithError(kErrorInternal);
92 return;
93 }
94 std::string public_key_der_str(public_key_der.begin(), public_key_der.end());
95
96 func->RespondWithResults(
97 api_epki::GenerateKey::Results::Create(public_key_der_str));
98 }
99
100 void SignWithDB(scoped_ptr<api_epki::Sign::Params> params,
101 scoped_refptr<TokenMethodExtensionFunction> func,
102 crypto::ScopedPK11Slot slot,
103 net::NSSCertDatabase* cert_db) {
104 const std::string& public_key = params->public_key;
105 const uint8* public_key_uint8 =
106 reinterpret_cast<const uint8*>(public_key.data());
107 std::vector<uint8> public_key_vector(public_key_uint8,
108 public_key_uint8 + public_key.size());
109
110 // TODO(pneubeck): This searches all slots. Change to look only at |slot_|.
111 scoped_ptr<crypto::RSAPrivateKey> rsa_key(
112 crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key_vector));
113 if (!rsa_key) {
114 func->RespondWithError(kErrorKeyNotFound);
115 return;
116 }
117
118 const std::string& data = params->data;
119 SECItem sign_result = {siBuffer, NULL, 0};
120 if (SEC_SignData(&sign_result,
121 reinterpret_cast<const unsigned char*>(data.data()),
122 data.size(),
123 rsa_key->key(),
124 SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION) != SECSuccess) {
125 LOG(ERROR) << "Couldn't sign.";
126 func->RespondWithError(kErrorInternal);
127 return;
128 }
129
130 std::string signature(reinterpret_cast<const char*>(sign_result.data),
131 sign_result.len);
132 func->RespondWithResults(api_epki::Sign::Results::Create(signature));
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->RespondWithResults(results.Pass());
162 // results_ = api_eci::GetClientCertificates::Results::Create(client_certs);
163 }
164
165 void GetCertsWithDB(scoped_ptr<api_epk::GetCertificates::Params> params,
166 scoped_refptr<TokenMethodExtensionFunction> func,
167 crypto::ScopedPK11Slot slot,
168 net::NSSCertDatabase* cert_db) {
169 PK11SlotInfo* slot_ptr = slot.get();
170 cert_db->ListCertsInSlot(base::Bind(&DidGetCerts, func, base::Passed(&slot)),
171 slot_ptr);
172 }
173
174 void ImportWithDB(scoped_ptr<api_epk::ImportCertificate::Params> params,
175 scoped_refptr<TokenMethodExtensionFunction> func,
176 crypto::ScopedPK11Slot slot,
177 net::NSSCertDatabase* cert_db) {
178 const std::string& certificate = params->certificate;
179 scoped_refptr<net::X509Certificate> cert_x509 =
180 net::X509Certificate::CreateFromBytes(certificate.data(),
181 certificate.size());
182 if (!cert_x509) {
183 func->RespondWithError(kErrorInvalidX509Cert);
184 return;
185 }
186
187 net::CertDatabase* db = net::CertDatabase::GetInstance();
188
189 const net::Error cert_status = db->CheckUserCert(cert_x509);
190 if (cert_status == net::ERR_NO_PRIVATE_KEY_FOR_CERT) {
191 func->RespondWithError(kErrorKeyNotFound);
192 return;
193 } else if (cert_status != net::OK) {
194 func->RespondWithError(net::ErrorToString(cert_status));
195 return;
196 }
197
198 const net::Error import_status = db->AddUserCert(cert_x509.get());
199 if (import_status != net::OK) {
200 LOG(ERROR) << "Could not import certificate.";
201 func->RespondWithError(net::ErrorToString(import_status));
202 return;
203 }
204
205 func->RespondWithoutResult();
206 }
207
208 void RemoveWithDB(scoped_ptr<api_epk::RemoveCertificate::Params> params,
209 scoped_refptr<TokenMethodExtensionFunction> func,
210 crypto::ScopedPK11Slot slot,
211 net::NSSCertDatabase* cert_db) {
212 const std::string& certificate = params->certificate;
213 scoped_refptr<net::X509Certificate> cert_x509 =
214 net::X509Certificate::CreateFromBytes(certificate.data(),
215 certificate.size());
216 if (!cert_x509) {
217 func->RespondWithError(kErrorInvalidX509Cert);
218 return;
219 }
220
221 bool certificate_found = cert_x509->os_cert_handle()->isperm;
222 bool success = cert_db->DeleteCertAndKey(cert_x509);
223
224 // CertificateNotFound error has precedence over an internal error.
225 if (!certificate_found) {
226 func->RespondWithError(kErrorCertificateNotFound);
227 return;
228 }
229 if (!success) {
230 func->RespondWithError(kErrorInternal);
231 return;
232 }
233
234 func->RespondWithoutResult();
235 }
236
237 } // namespace
238
239 void Generate(scoped_refptr<TokenMethodExtensionFunction> func,
240 scoped_ptr<api_epki::GenerateKey::Params> params) {
241 GetCertDatabase(func,
242 params->token_id,
243 base::Bind(GenerateWithDB, base::Passed(&params)));
244 }
245
246 void Sign(scoped_refptr<TokenMethodExtensionFunction> func,
247 scoped_ptr<api_epki::Sign::Params> params) {
248 GetCertDatabase(
249 func, params->token_id, base::Bind(SignWithDB, base::Passed(&params)));
250 }
251
252 void GetCerts(scoped_refptr<TokenMethodExtensionFunction> func,
253 scoped_ptr<api_epk::GetCertificates::Params> params) {
254 GetCertDatabase(func,
255 params->token_id,
256 base::Bind(GetCertsWithDB, base::Passed(&params)));
257 }
258
259 void Import(scoped_refptr<TokenMethodExtensionFunction> func,
260 scoped_ptr<api_epk::ImportCertificate::Params> params) {
261 GetCertDatabase(
262 func, params->token_id, base::Bind(ImportWithDB, base::Passed(&params)));
263 }
264
265 void Remove(scoped_refptr<TokenMethodExtensionFunction> func,
266 scoped_ptr<api_epk::RemoveCertificate::Params> params) {
267 GetCertDatabase(
268 func, params->token_id, base::Bind(RemoveWithDB, base::Passed(&params)));
269 }
270
271 } // namespace nss
272
273 } // namespace enterprise_platform_keys
274
275 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698