普通文本  |  171行  |  5.25 KB

// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/login/owner_key_utils.h"

#include <limits>

#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/string_util.h"
#include "crypto/rsa_private_key.h"
#include "crypto/signature_creator.h"
#include "crypto/signature_verifier.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/login_library.h"
#include "chrome/common/extensions/extension_constants.h"

using extension_misc::kSignatureAlgorithm;

namespace chromeos {

///////////////////////////////////////////////////////////////////////////
// OwnerKeyUtils

// static
OwnerKeyUtils::Factory* OwnerKeyUtils::factory_ = NULL;

OwnerKeyUtils::OwnerKeyUtils() {}

OwnerKeyUtils::~OwnerKeyUtils() {}

///////////////////////////////////////////////////////////////////////////
// OwnerKeyUtilsImpl

class OwnerKeyUtilsImpl : public OwnerKeyUtils {
 public:
  OwnerKeyUtilsImpl();

  bool ImportPublicKey(const FilePath& key_file,
                       std::vector<uint8>* output);

  bool Verify(const std::string& data,
              const std::vector<uint8> signature,
              const std::vector<uint8> public_key);

  bool Sign(const std::string& data,
            std::vector<uint8>* OUT_signature,
            crypto::RSAPrivateKey* key);

  crypto::RSAPrivateKey* FindPrivateKey(const std::vector<uint8>& key);

  FilePath GetOwnerKeyFilePath();

 protected:
  virtual ~OwnerKeyUtilsImpl();

  bool ExportPublicKeyToFile(crypto::RSAPrivateKey* pair,
                             const FilePath& key_file);

 private:
  // The file outside the owner's encrypted home directory where her
  // key will live.
  static const char kOwnerKeyFile[];

  DISALLOW_COPY_AND_ASSIGN(OwnerKeyUtilsImpl);
};

// Defined here, instead of up above, because we need OwnerKeyUtilsImpl.
OwnerKeyUtils* OwnerKeyUtils::Create() {
  if (!factory_)
    return new OwnerKeyUtilsImpl();
  else
    return factory_->CreateOwnerKeyUtils();
}

// static
const char OwnerKeyUtilsImpl::kOwnerKeyFile[] = "/var/lib/whitelist/owner.key";

OwnerKeyUtilsImpl::OwnerKeyUtilsImpl() {}

OwnerKeyUtilsImpl::~OwnerKeyUtilsImpl() {}

bool OwnerKeyUtilsImpl::ExportPublicKeyToFile(crypto::RSAPrivateKey* pair,
                                              const FilePath& key_file) {
  DCHECK(pair);
  bool ok = false;
  int safe_file_size = 0;

  std::vector<uint8> to_export;
  if (!pair->ExportPublicKey(&to_export)) {
    LOG(ERROR) << "Formatting key for export failed!";
    return false;
  }

  if (to_export.size() > static_cast<uint>(INT_MAX)) {
    LOG(ERROR) << "key is too big! " << to_export.size();
  } else {
    safe_file_size = static_cast<int>(to_export.size());

    ok = (safe_file_size ==
          file_util::WriteFile(key_file,
                               reinterpret_cast<char*>(&to_export.front()),
                               safe_file_size));
  }
  return ok;
}

bool OwnerKeyUtilsImpl::ImportPublicKey(const FilePath& key_file,
                                        std::vector<uint8>* output) {
  // Get the file size (must fit in a 32 bit int for NSS).
  int64 file_size;
  if (!file_util::GetFileSize(key_file, &file_size)) {
    LOG(ERROR) << "Could not get size of " << key_file.value();
    return false;
  }
  if (file_size > static_cast<int64>(std::numeric_limits<int>::max())) {
    LOG(ERROR) << key_file.value() << "is "
               << file_size << "bytes!!!  Too big!";
    return false;
  }
  int32 safe_file_size = static_cast<int32>(file_size);

  output->resize(safe_file_size);
  // Get the key data off of disk
  int data_read = file_util::ReadFile(key_file,
                                      reinterpret_cast<char*>(&(output->at(0))),
                                      safe_file_size);
  return data_read == safe_file_size;
}

bool OwnerKeyUtilsImpl::Verify(const std::string& data,
                               const std::vector<uint8> signature,
                               const std::vector<uint8> public_key) {
  crypto::SignatureVerifier verifier;
  if (!verifier.VerifyInit(kSignatureAlgorithm, sizeof(kSignatureAlgorithm),
                           &signature[0], signature.size(),
                           &public_key[0], public_key.size())) {
    return false;
  }

  verifier.VerifyUpdate(reinterpret_cast<const uint8*>(data.c_str()),
                        data.length());
  return (verifier.VerifyFinal());
}

bool OwnerKeyUtilsImpl::Sign(const std::string& data,
                             std::vector<uint8>* OUT_signature,
                             crypto::RSAPrivateKey* key) {
  scoped_ptr<crypto::SignatureCreator> signer(
      crypto::SignatureCreator::Create(key));
  if (!signer->Update(reinterpret_cast<const uint8*>(data.c_str()),
                      data.length())) {
    return false;
  }
  return signer->Final(OUT_signature);
}

crypto::RSAPrivateKey* OwnerKeyUtilsImpl::FindPrivateKey(
    const std::vector<uint8>& key) {
  return crypto::RSAPrivateKey::FindFromPublicKeyInfo(key);
}

FilePath OwnerKeyUtilsImpl::GetOwnerKeyFilePath() {
  return FilePath(OwnerKeyUtilsImpl::kOwnerKeyFile);
}

}  // namespace chromeos