Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / enterprise_platform_keys / enterprise_platform_keys_api.cc
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/enterprise_platform_keys_api.h"
6
7 #include "base/bind.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"
16
17 namespace extensions {
18
19 namespace {
20
21 namespace api_epk = api::enterprise_platform_keys;
22 namespace api_epki = api::enterprise_platform_keys_internal;
23
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.";
27
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";
34
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;
41     return true;
42   }
43   if (token_id == kTokenIdSystem) {
44     *platform_keys_token_id = chromeos::platform_keys::kTokenIdSystem;
45     return true;
46   }
47   return false;
48 }
49
50 std::string PlatformKeysTokenIdToApiId(
51     const std::string& platform_keys_token_id) {
52   if (platform_keys_token_id == chromeos::platform_keys::kTokenIdUser)
53     return kTokenIdUser;
54   if (platform_keys_token_id == chromeos::platform_keys::kTokenIdSystem)
55     return kTokenIdSystem;
56
57   return std::string();
58 }
59
60 }  // namespace
61
62 EnterprisePlatformKeysInternalGenerateKeyFunction::
63     ~EnterprisePlatformKeysInternalGenerateKeyFunction() {
64 }
65
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));
75
76   chromeos::PlatformKeysService* service =
77       chromeos::PlatformKeysServiceFactory::GetForBrowserContext(
78           browser_context());
79   DCHECK(service);
80
81   service->GenerateRSAKey(
82       platform_keys_token_id,
83       params->modulus_length,
84       extension_id(),
85       base::Bind(
86           &EnterprisePlatformKeysInternalGenerateKeyFunction::OnGeneratedKey,
87           this));
88   return RespondLater();
89 }
90
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()) {
96     Respond(
97         ArgumentList(api_epki::GenerateKey::Results::Create(public_key_der)));
98   } else {
99     Respond(Error(error_message));
100   }
101 }
102
103 EnterprisePlatformKeysInternalSignFunction::
104     ~EnterprisePlatformKeysInternalSignFunction() {
105 }
106
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));
115
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;
125   else
126     return RespondNow(Error(kErrorAlgorithmNotSupported));
127
128   chromeos::PlatformKeysService* service =
129       chromeos::PlatformKeysServiceFactory::GetForBrowserContext(
130           browser_context());
131   DCHECK(service);
132
133   service->Sign(
134       platform_keys_token_id,
135       params->public_key,
136       hash_algorithm,
137       params->data,
138       extension_id(),
139       base::Bind(&EnterprisePlatformKeysInternalSignFunction::OnSigned, this));
140   return RespondLater();
141 }
142
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)));
149   else
150     Respond(Error(error_message));
151 }
152
153 EnterprisePlatformKeysGetCertificatesFunction::
154     ~EnterprisePlatformKeysGetCertificatesFunction() {
155 }
156
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));
165
166   chromeos::platform_keys::GetCertificates(
167       platform_keys_token_id,
168       base::Bind(
169           &EnterprisePlatformKeysGetCertificatesFunction::OnGotCertificates,
170           this),
171       browser_context());
172   return RespondLater();
173 }
174
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));
181     return;
182   }
183
184   scoped_ptr<base::ListValue> client_certs(new base::ListValue());
185   for (net::CertificateList::const_iterator it = certs->begin();
186        it != certs->end();
187        ++it) {
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()));
192   }
193
194   scoped_ptr<base::ListValue> results(new base::ListValue());
195   results->Append(client_certs.release());
196   Respond(ArgumentList(results.Pass()));
197 }
198
199 EnterprisePlatformKeysImportCertificateFunction::
200     ~EnterprisePlatformKeysImportCertificateFunction() {
201 }
202
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));
211
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));
217
218   chromeos::platform_keys::ImportCertificate(
219       platform_keys_token_id,
220       cert_x509,
221       base::Bind(&EnterprisePlatformKeysImportCertificateFunction::
222                      OnImportedCertificate,
223                  this),
224       browser_context());
225   return RespondLater();
226 }
227
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());
233   else
234     Respond(Error(error_message));
235 }
236
237 EnterprisePlatformKeysRemoveCertificateFunction::
238     ~EnterprisePlatformKeysRemoveCertificateFunction() {
239 }
240
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));
249
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));
255
256   chromeos::platform_keys::RemoveCertificate(
257       platform_keys_token_id,
258       cert_x509,
259       base::Bind(&EnterprisePlatformKeysRemoveCertificateFunction::
260                      OnRemovedCertificate,
261                  this),
262       browser_context());
263   return RespondLater();
264 }
265
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());
271   else
272     Respond(Error(error_message));
273 }
274
275 EnterprisePlatformKeysInternalGetTokensFunction::
276     ~EnterprisePlatformKeysInternalGetTokensFunction() {
277 }
278
279 ExtensionFunction::ResponseAction
280 EnterprisePlatformKeysInternalGetTokensFunction::Run() {
281   EXTENSION_FUNCTION_VALIDATE(args_->empty());
282
283   chromeos::platform_keys::GetTokens(
284       base::Bind(&EnterprisePlatformKeysInternalGetTokensFunction::OnGotTokens,
285                  this),
286       browser_context());
287   return RespondLater();
288 }
289
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));
296     return;
297   }
298
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();
303        ++it) {
304     std::string token_id = PlatformKeysTokenIdToApiId(*it);
305     if (token_id.empty()) {
306       Respond(Error(kErrorInternal));
307       return;
308     }
309     token_ids.push_back(token_id);
310   }
311
312   Respond(ArgumentList(api_epki::GetTokens::Results::Create(token_ids)));
313 }
314
315 }  // namespace extensions