Home | History | Annotate | Download | only in enterprise_platform_keys
      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.
     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::
     42     ~EnterprisePlatformKeysInternalGenerateKeyFunction() {
     43 }
     44 
     45 ExtensionFunction::ResponseAction
     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 
     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::
     82     ~EnterprisePlatformKeysInternalSignFunction() {
     83 }
     84 
     85 ExtensionFunction::ResponseAction
     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 
    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::
    131     ~EnterprisePlatformKeysGetCertificatesFunction() {
    132 }
    133 
    134 ExtensionFunction::ResponseAction
    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 
    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::
    176     ~EnterprisePlatformKeysImportCertificateFunction() {
    177 }
    178 
    179 ExtensionFunction::ResponseAction
    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 
    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::
    213     ~EnterprisePlatformKeysRemoveCertificateFunction() {
    214 }
    215 
    216 ExtensionFunction::ResponseAction
    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 
    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::
    250     ~EnterprisePlatformKeysInternalGetTokensFunction() {
    251 }
    252 
    253 ExtensionFunction::ResponseAction
    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