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.
5 #include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h"
8 #include "base/values.h"
9 #include "chrome/browser/chromeos/platform_keys/platform_keys.h"
10 #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h"
11 #include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h"
12 #include "chrome/common/extensions/api/enterprise_platform_keys.h"
13 #include "chrome/common/extensions/api/enterprise_platform_keys_internal.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "net/cert/x509_certificate.h"
17 namespace extensions {
21 namespace api_epk = api::enterprise_platform_keys;
22 namespace api_epki = api::enterprise_platform_keys_internal;
24 // This error will occur if a token is removed and will be exposed to the
25 // extension. Keep this in sync with the custom binding in Javascript.
26 const char kErrorInvalidToken[] = "The token is not valid.";
28 const char kErrorInternal[] = "Internal Error.";
29 const char kErrorAlgorithmNotSupported[] = "Algorithm not supported.";
30 const char kErrorInvalidX509Cert[] =
31 "Certificate is not a valid X.509 certificate.";
32 const char kTokenIdUser[] = "user";
33 const char kTokenIdSystem[] = "system";
35 // Returns whether |token_id| references a known Token.
36 bool ValidateToken(const std::string& token_id,
37 std::string* platform_keys_token_id) {
38 platform_keys_token_id->clear();
39 if (token_id == kTokenIdUser) {
40 *platform_keys_token_id = chromeos::platform_keys::kTokenIdUser;
43 if (token_id == kTokenIdSystem) {
44 *platform_keys_token_id = chromeos::platform_keys::kTokenIdSystem;
50 std::string PlatformKeysTokenIdToApiId(
51 const std::string& platform_keys_token_id) {
52 if (platform_keys_token_id == chromeos::platform_keys::kTokenIdUser)
54 if (platform_keys_token_id == chromeos::platform_keys::kTokenIdSystem)
55 return kTokenIdSystem;
62 EnterprisePlatformKeysInternalGenerateKeyFunction::
63 ~EnterprisePlatformKeysInternalGenerateKeyFunction() {
66 ExtensionFunction::ResponseAction
67 EnterprisePlatformKeysInternalGenerateKeyFunction::Run() {
68 scoped_ptr<api_epki::GenerateKey::Params> params(
69 api_epki::GenerateKey::Params::Create(*args_));
70 // TODO(pneubeck): Add support for unsigned integers to IDL.
71 EXTENSION_FUNCTION_VALIDATE(params && params->modulus_length >= 0);
72 std::string platform_keys_token_id;
73 if (!ValidateToken(params->token_id, &platform_keys_token_id))
74 return RespondNow(Error(kErrorInvalidToken));
76 chromeos::PlatformKeysService* service =
77 chromeos::PlatformKeysServiceFactory::GetForBrowserContext(
81 service->GenerateRSAKey(
82 platform_keys_token_id,
83 params->modulus_length,
86 &EnterprisePlatformKeysInternalGenerateKeyFunction::OnGeneratedKey,
88 return RespondLater();
91 void EnterprisePlatformKeysInternalGenerateKeyFunction::OnGeneratedKey(
92 const std::string& public_key_der,
93 const std::string& error_message) {
94 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
95 if (error_message.empty()) {
97 ArgumentList(api_epki::GenerateKey::Results::Create(public_key_der)));
99 Respond(Error(error_message));
103 EnterprisePlatformKeysInternalSignFunction::
104 ~EnterprisePlatformKeysInternalSignFunction() {
107 ExtensionFunction::ResponseAction
108 EnterprisePlatformKeysInternalSignFunction::Run() {
109 scoped_ptr<api_epki::Sign::Params> params(
110 api_epki::Sign::Params::Create(*args_));
111 EXTENSION_FUNCTION_VALIDATE(params);
112 std::string platform_keys_token_id;
113 if (!ValidateToken(params->token_id, &platform_keys_token_id))
114 return RespondNow(Error(kErrorInvalidToken));
116 chromeos::platform_keys::HashAlgorithm hash_algorithm;
117 if (params->hash_algorithm_name == "SHA-1")
118 hash_algorithm = chromeos::platform_keys::HASH_ALGORITHM_SHA1;
119 else if (params->hash_algorithm_name == "SHA-256")
120 hash_algorithm = chromeos::platform_keys::HASH_ALGORITHM_SHA256;
121 else if (params->hash_algorithm_name == "SHA-384")
122 hash_algorithm = chromeos::platform_keys::HASH_ALGORITHM_SHA384;
123 else if (params->hash_algorithm_name == "SHA-512")
124 hash_algorithm = chromeos::platform_keys::HASH_ALGORITHM_SHA512;
126 return RespondNow(Error(kErrorAlgorithmNotSupported));
128 chromeos::PlatformKeysService* service =
129 chromeos::PlatformKeysServiceFactory::GetForBrowserContext(
134 platform_keys_token_id,
139 base::Bind(&EnterprisePlatformKeysInternalSignFunction::OnSigned, this));
140 return RespondLater();
143 void EnterprisePlatformKeysInternalSignFunction::OnSigned(
144 const std::string& signature,
145 const std::string& error_message) {
146 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
147 if (error_message.empty())
148 Respond(ArgumentList(api_epki::Sign::Results::Create(signature)));
150 Respond(Error(error_message));
153 EnterprisePlatformKeysGetCertificatesFunction::
154 ~EnterprisePlatformKeysGetCertificatesFunction() {
157 ExtensionFunction::ResponseAction
158 EnterprisePlatformKeysGetCertificatesFunction::Run() {
159 scoped_ptr<api_epk::GetCertificates::Params> params(
160 api_epk::GetCertificates::Params::Create(*args_));
161 EXTENSION_FUNCTION_VALIDATE(params);
162 std::string platform_keys_token_id;
163 if (!ValidateToken(params->token_id, &platform_keys_token_id))
164 return RespondNow(Error(kErrorInvalidToken));
166 chromeos::platform_keys::GetCertificates(
167 platform_keys_token_id,
169 &EnterprisePlatformKeysGetCertificatesFunction::OnGotCertificates,
172 return RespondLater();
175 void EnterprisePlatformKeysGetCertificatesFunction::OnGotCertificates(
176 scoped_ptr<net::CertificateList> certs,
177 const std::string& error_message) {
178 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
179 if (!error_message.empty()) {
180 Respond(Error(error_message));
184 scoped_ptr<base::ListValue> client_certs(new base::ListValue());
185 for (net::CertificateList::const_iterator it = certs->begin();
188 std::string der_encoding;
189 net::X509Certificate::GetDEREncoded((*it)->os_cert_handle(), &der_encoding);
190 client_certs->Append(base::BinaryValue::CreateWithCopiedBuffer(
191 der_encoding.data(), der_encoding.size()));
194 scoped_ptr<base::ListValue> results(new base::ListValue());
195 results->Append(client_certs.release());
196 Respond(ArgumentList(results.Pass()));
199 EnterprisePlatformKeysImportCertificateFunction::
200 ~EnterprisePlatformKeysImportCertificateFunction() {
203 ExtensionFunction::ResponseAction
204 EnterprisePlatformKeysImportCertificateFunction::Run() {
205 scoped_ptr<api_epk::ImportCertificate::Params> params(
206 api_epk::ImportCertificate::Params::Create(*args_));
207 EXTENSION_FUNCTION_VALIDATE(params);
208 std::string platform_keys_token_id;
209 if (!ValidateToken(params->token_id, &platform_keys_token_id))
210 return RespondNow(Error(kErrorInvalidToken));
212 const std::string& cert_der = params->certificate;
213 scoped_refptr<net::X509Certificate> cert_x509 =
214 net::X509Certificate::CreateFromBytes(cert_der.data(), cert_der.size());
215 if (!cert_x509.get())
216 return RespondNow(Error(kErrorInvalidX509Cert));
218 chromeos::platform_keys::ImportCertificate(
219 platform_keys_token_id,
221 base::Bind(&EnterprisePlatformKeysImportCertificateFunction::
222 OnImportedCertificate,
225 return RespondLater();
228 void EnterprisePlatformKeysImportCertificateFunction::OnImportedCertificate(
229 const std::string& error_message) {
230 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
231 if (error_message.empty())
232 Respond(NoArguments());
234 Respond(Error(error_message));
237 EnterprisePlatformKeysRemoveCertificateFunction::
238 ~EnterprisePlatformKeysRemoveCertificateFunction() {
241 ExtensionFunction::ResponseAction
242 EnterprisePlatformKeysRemoveCertificateFunction::Run() {
243 scoped_ptr<api_epk::RemoveCertificate::Params> params(
244 api_epk::RemoveCertificate::Params::Create(*args_));
245 EXTENSION_FUNCTION_VALIDATE(params);
246 std::string platform_keys_token_id;
247 if (!ValidateToken(params->token_id, &platform_keys_token_id))
248 return RespondNow(Error(kErrorInvalidToken));
250 const std::string& cert_der = params->certificate;
251 scoped_refptr<net::X509Certificate> cert_x509 =
252 net::X509Certificate::CreateFromBytes(cert_der.data(), cert_der.size());
253 if (!cert_x509.get())
254 return RespondNow(Error(kErrorInvalidX509Cert));
256 chromeos::platform_keys::RemoveCertificate(
257 platform_keys_token_id,
259 base::Bind(&EnterprisePlatformKeysRemoveCertificateFunction::
260 OnRemovedCertificate,
263 return RespondLater();
266 void EnterprisePlatformKeysRemoveCertificateFunction::OnRemovedCertificate(
267 const std::string& error_message) {
268 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
269 if (error_message.empty())
270 Respond(NoArguments());
272 Respond(Error(error_message));
275 EnterprisePlatformKeysInternalGetTokensFunction::
276 ~EnterprisePlatformKeysInternalGetTokensFunction() {
279 ExtensionFunction::ResponseAction
280 EnterprisePlatformKeysInternalGetTokensFunction::Run() {
281 EXTENSION_FUNCTION_VALIDATE(args_->empty());
283 chromeos::platform_keys::GetTokens(
284 base::Bind(&EnterprisePlatformKeysInternalGetTokensFunction::OnGotTokens,
287 return RespondLater();
290 void EnterprisePlatformKeysInternalGetTokensFunction::OnGotTokens(
291 scoped_ptr<std::vector<std::string> > platform_keys_token_ids,
292 const std::string& error_message) {
293 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
294 if (!error_message.empty()) {
295 Respond(Error(error_message));
299 std::vector<std::string> token_ids;
300 for (std::vector<std::string>::const_iterator it =
301 platform_keys_token_ids->begin();
302 it != platform_keys_token_ids->end();
304 std::string token_id = PlatformKeysTokenIdToApiId(*it);
305 if (token_id.empty()) {
306 Respond(Error(kErrorInternal));
309 token_ids.push_back(token_id);
312 Respond(ArgumentList(api_epki::GetTokens::Results::Create(token_ids)));
315 } // namespace extensions