// 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