• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 kErrorAlgorithmNotSupported[] = "Algorithm not supported.";
29 const char kErrorInvalidX509Cert[] =
30     "Certificate is not a valid X.509 certificate.";
31 const char kTokenIdUser[] = "user";
32 
33 // Returns whether |token_id| references a known Token.
ValidateToken(const std::string & token_id)34 bool ValidateToken(const std::string& token_id) {
35   // For now, the user token is the only valid one.
36   return token_id == kTokenIdUser;
37 }
38 
39 }  // namespace
40 
41 EnterprisePlatformKeysInternalGenerateKeyFunction::
~EnterprisePlatformKeysInternalGenerateKeyFunction()42     ~EnterprisePlatformKeysInternalGenerateKeyFunction() {
43 }
44 
45 ExtensionFunction::ResponseAction
Run()46 EnterprisePlatformKeysInternalGenerateKeyFunction::Run() {
47   scoped_ptr<api_epki::GenerateKey::Params> params(
48       api_epki::GenerateKey::Params::Create(*args_));
49   // TODO(pneubeck): Add support for unsigned integers to IDL.
50   EXTENSION_FUNCTION_VALIDATE(params && params->modulus_length >= 0);
51   if (!ValidateToken(params->token_id))
52     return RespondNow(Error(kErrorInvalidToken));
53 
54   chromeos::PlatformKeysService* service =
55       chromeos::PlatformKeysServiceFactory::GetForBrowserContext(
56           browser_context());
57   DCHECK(service);
58 
59   service->GenerateRSAKey(
60       params->token_id,
61       params->modulus_length,
62       extension_id(),
63       base::Bind(
64           &EnterprisePlatformKeysInternalGenerateKeyFunction::OnGeneratedKey,
65           this));
66   return RespondLater();
67 }
68 
OnGeneratedKey(const std::string & public_key_der,const std::string & error_message)69 void EnterprisePlatformKeysInternalGenerateKeyFunction::OnGeneratedKey(
70     const std::string& public_key_der,
71     const std::string& error_message) {
72   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
73   if (error_message.empty()) {
74     Respond(
75         ArgumentList(api_epki::GenerateKey::Results::Create(public_key_der)));
76   } else {
77     Respond(Error(error_message));
78   }
79 }
80 
81 EnterprisePlatformKeysInternalSignFunction::
~EnterprisePlatformKeysInternalSignFunction()82     ~EnterprisePlatformKeysInternalSignFunction() {
83 }
84 
85 ExtensionFunction::ResponseAction
Run()86 EnterprisePlatformKeysInternalSignFunction::Run() {
87   scoped_ptr<api_epki::Sign::Params> params(
88       api_epki::Sign::Params::Create(*args_));
89   EXTENSION_FUNCTION_VALIDATE(params);
90   if (!ValidateToken(params->token_id))
91     return RespondNow(Error(kErrorInvalidToken));
92 
93   chromeos::platform_keys::HashAlgorithm hash_algorithm;
94   if (params->hash_algorithm_name == "SHA-1")
95     hash_algorithm = chromeos::platform_keys::HASH_ALGORITHM_SHA1;
96   else if (params->hash_algorithm_name == "SHA-256")
97     hash_algorithm = chromeos::platform_keys::HASH_ALGORITHM_SHA256;
98   else if (params->hash_algorithm_name == "SHA-384")
99     hash_algorithm = chromeos::platform_keys::HASH_ALGORITHM_SHA384;
100   else if (params->hash_algorithm_name == "SHA-512")
101     hash_algorithm = chromeos::platform_keys::HASH_ALGORITHM_SHA512;
102   else
103     return RespondNow(Error(kErrorAlgorithmNotSupported));
104 
105   chromeos::PlatformKeysService* service =
106       chromeos::PlatformKeysServiceFactory::GetForBrowserContext(
107           browser_context());
108   DCHECK(service);
109 
110   service->Sign(
111       params->token_id,
112       params->public_key,
113       hash_algorithm,
114       params->data,
115       extension_id(),
116       base::Bind(&EnterprisePlatformKeysInternalSignFunction::OnSigned, this));
117   return RespondLater();
118 }
119 
OnSigned(const std::string & signature,const std::string & error_message)120 void EnterprisePlatformKeysInternalSignFunction::OnSigned(
121     const std::string& signature,
122     const std::string& error_message) {
123   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
124   if (error_message.empty())
125     Respond(ArgumentList(api_epki::Sign::Results::Create(signature)));
126   else
127     Respond(Error(error_message));
128 }
129 
130 EnterprisePlatformKeysGetCertificatesFunction::
~EnterprisePlatformKeysGetCertificatesFunction()131     ~EnterprisePlatformKeysGetCertificatesFunction() {
132 }
133 
134 ExtensionFunction::ResponseAction
Run()135 EnterprisePlatformKeysGetCertificatesFunction::Run() {
136   scoped_ptr<api_epk::GetCertificates::Params> params(
137       api_epk::GetCertificates::Params::Create(*args_));
138   EXTENSION_FUNCTION_VALIDATE(params);
139   if (!ValidateToken(params->token_id))
140     return RespondNow(Error(kErrorInvalidToken));
141 
142   chromeos::platform_keys::GetCertificates(
143       params->token_id,
144       base::Bind(
145           &EnterprisePlatformKeysGetCertificatesFunction::OnGotCertificates,
146           this),
147       browser_context());
148   return RespondLater();
149 }
150 
OnGotCertificates(scoped_ptr<net::CertificateList> certs,const std::string & error_message)151 void EnterprisePlatformKeysGetCertificatesFunction::OnGotCertificates(
152     scoped_ptr<net::CertificateList> certs,
153     const std::string& error_message) {
154   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
155   if (!error_message.empty()) {
156     Respond(Error(error_message));
157     return;
158   }
159 
160   scoped_ptr<base::ListValue> client_certs(new base::ListValue());
161   for (net::CertificateList::const_iterator it = certs->begin();
162        it != certs->end();
163        ++it) {
164     std::string der_encoding;
165     net::X509Certificate::GetDEREncoded((*it)->os_cert_handle(), &der_encoding);
166     client_certs->Append(base::BinaryValue::CreateWithCopiedBuffer(
167         der_encoding.data(), der_encoding.size()));
168   }
169 
170   scoped_ptr<base::ListValue> results(new base::ListValue());
171   results->Append(client_certs.release());
172   Respond(ArgumentList(results.Pass()));
173 }
174 
175 EnterprisePlatformKeysImportCertificateFunction::
~EnterprisePlatformKeysImportCertificateFunction()176     ~EnterprisePlatformKeysImportCertificateFunction() {
177 }
178 
179 ExtensionFunction::ResponseAction
Run()180 EnterprisePlatformKeysImportCertificateFunction::Run() {
181   scoped_ptr<api_epk::ImportCertificate::Params> params(
182       api_epk::ImportCertificate::Params::Create(*args_));
183   EXTENSION_FUNCTION_VALIDATE(params);
184   if (!ValidateToken(params->token_id))
185     return RespondNow(Error(kErrorInvalidToken));
186 
187   const std::string& cert_der = params->certificate;
188   scoped_refptr<net::X509Certificate> cert_x509 =
189       net::X509Certificate::CreateFromBytes(cert_der.data(), cert_der.size());
190   if (!cert_x509)
191     return RespondNow(Error(kErrorInvalidX509Cert));
192 
193   chromeos::platform_keys::ImportCertificate(
194       params->token_id,
195       cert_x509,
196       base::Bind(&EnterprisePlatformKeysImportCertificateFunction::
197                      OnImportedCertificate,
198                  this),
199       browser_context());
200   return RespondLater();
201 }
202 
OnImportedCertificate(const std::string & error_message)203 void EnterprisePlatformKeysImportCertificateFunction::OnImportedCertificate(
204     const std::string& error_message) {
205   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
206   if (error_message.empty())
207     Respond(NoArguments());
208   else
209     Respond(Error(error_message));
210 }
211 
212 EnterprisePlatformKeysRemoveCertificateFunction::
~EnterprisePlatformKeysRemoveCertificateFunction()213     ~EnterprisePlatformKeysRemoveCertificateFunction() {
214 }
215 
216 ExtensionFunction::ResponseAction
Run()217 EnterprisePlatformKeysRemoveCertificateFunction::Run() {
218   scoped_ptr<api_epk::RemoveCertificate::Params> params(
219       api_epk::RemoveCertificate::Params::Create(*args_));
220   EXTENSION_FUNCTION_VALIDATE(params);
221   if (!ValidateToken(params->token_id))
222     return RespondNow(Error(kErrorInvalidToken));
223 
224   const std::string& cert_der = params->certificate;
225   scoped_refptr<net::X509Certificate> cert_x509 =
226       net::X509Certificate::CreateFromBytes(cert_der.data(), cert_der.size());
227   if (!cert_x509)
228     return RespondNow(Error(kErrorInvalidX509Cert));
229 
230   chromeos::platform_keys::RemoveCertificate(
231       params->token_id,
232       cert_x509,
233       base::Bind(&EnterprisePlatformKeysRemoveCertificateFunction::
234                      OnRemovedCertificate,
235                  this),
236       browser_context());
237   return RespondLater();
238 }
239 
OnRemovedCertificate(const std::string & error_message)240 void EnterprisePlatformKeysRemoveCertificateFunction::OnRemovedCertificate(
241     const std::string& error_message) {
242   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
243   if (error_message.empty())
244     Respond(NoArguments());
245   else
246     Respond(Error(error_message));
247 }
248 
249 EnterprisePlatformKeysInternalGetTokensFunction::
~EnterprisePlatformKeysInternalGetTokensFunction()250     ~EnterprisePlatformKeysInternalGetTokensFunction() {
251 }
252 
253 ExtensionFunction::ResponseAction
Run()254 EnterprisePlatformKeysInternalGetTokensFunction::Run() {
255   EXTENSION_FUNCTION_VALIDATE(args_->empty());
256 
257   std::vector<std::string> token_ids;
258   token_ids.push_back(kTokenIdUser);
259   return RespondNow(
260       ArgumentList(api_epki::GetTokens::Results::Create(token_ids)));
261 }
262 
263 }  // namespace extensions
264