1// Copyright (c) 2011 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/chromeos/login/owner_key_utils.h"
6
7#include <limits>
8
9#include "base/file_path.h"
10#include "base/file_util.h"
11#include "base/logging.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/string_util.h"
14#include "crypto/rsa_private_key.h"
15#include "crypto/signature_creator.h"
16#include "crypto/signature_verifier.h"
17#include "chrome/browser/chromeos/cros/cros_library.h"
18#include "chrome/browser/chromeos/cros/login_library.h"
19#include "chrome/common/extensions/extension_constants.h"
20
21using extension_misc::kSignatureAlgorithm;
22
23namespace chromeos {
24
25///////////////////////////////////////////////////////////////////////////
26// OwnerKeyUtils
27
28// static
29OwnerKeyUtils::Factory* OwnerKeyUtils::factory_ = NULL;
30
31OwnerKeyUtils::OwnerKeyUtils() {}
32
33OwnerKeyUtils::~OwnerKeyUtils() {}
34
35///////////////////////////////////////////////////////////////////////////
36// OwnerKeyUtilsImpl
37
38class OwnerKeyUtilsImpl : public OwnerKeyUtils {
39 public:
40  OwnerKeyUtilsImpl();
41
42  bool ImportPublicKey(const FilePath& key_file,
43                       std::vector<uint8>* output);
44
45  bool Verify(const std::string& data,
46              const std::vector<uint8> signature,
47              const std::vector<uint8> public_key);
48
49  bool Sign(const std::string& data,
50            std::vector<uint8>* OUT_signature,
51            crypto::RSAPrivateKey* key);
52
53  crypto::RSAPrivateKey* FindPrivateKey(const std::vector<uint8>& key);
54
55  FilePath GetOwnerKeyFilePath();
56
57 protected:
58  virtual ~OwnerKeyUtilsImpl();
59
60  bool ExportPublicKeyToFile(crypto::RSAPrivateKey* pair,
61                             const FilePath& key_file);
62
63 private:
64  // The file outside the owner's encrypted home directory where her
65  // key will live.
66  static const char kOwnerKeyFile[];
67
68  DISALLOW_COPY_AND_ASSIGN(OwnerKeyUtilsImpl);
69};
70
71// Defined here, instead of up above, because we need OwnerKeyUtilsImpl.
72OwnerKeyUtils* OwnerKeyUtils::Create() {
73  if (!factory_)
74    return new OwnerKeyUtilsImpl();
75  else
76    return factory_->CreateOwnerKeyUtils();
77}
78
79// static
80const char OwnerKeyUtilsImpl::kOwnerKeyFile[] = "/var/lib/whitelist/owner.key";
81
82OwnerKeyUtilsImpl::OwnerKeyUtilsImpl() {}
83
84OwnerKeyUtilsImpl::~OwnerKeyUtilsImpl() {}
85
86bool OwnerKeyUtilsImpl::ExportPublicKeyToFile(crypto::RSAPrivateKey* pair,
87                                              const FilePath& key_file) {
88  DCHECK(pair);
89  bool ok = false;
90  int safe_file_size = 0;
91
92  std::vector<uint8> to_export;
93  if (!pair->ExportPublicKey(&to_export)) {
94    LOG(ERROR) << "Formatting key for export failed!";
95    return false;
96  }
97
98  if (to_export.size() > static_cast<uint>(INT_MAX)) {
99    LOG(ERROR) << "key is too big! " << to_export.size();
100  } else {
101    safe_file_size = static_cast<int>(to_export.size());
102
103    ok = (safe_file_size ==
104          file_util::WriteFile(key_file,
105                               reinterpret_cast<char*>(&to_export.front()),
106                               safe_file_size));
107  }
108  return ok;
109}
110
111bool OwnerKeyUtilsImpl::ImportPublicKey(const FilePath& key_file,
112                                        std::vector<uint8>* output) {
113  // Get the file size (must fit in a 32 bit int for NSS).
114  int64 file_size;
115  if (!file_util::GetFileSize(key_file, &file_size)) {
116    LOG(ERROR) << "Could not get size of " << key_file.value();
117    return false;
118  }
119  if (file_size > static_cast<int64>(std::numeric_limits<int>::max())) {
120    LOG(ERROR) << key_file.value() << "is "
121               << file_size << "bytes!!!  Too big!";
122    return false;
123  }
124  int32 safe_file_size = static_cast<int32>(file_size);
125
126  output->resize(safe_file_size);
127  // Get the key data off of disk
128  int data_read = file_util::ReadFile(key_file,
129                                      reinterpret_cast<char*>(&(output->at(0))),
130                                      safe_file_size);
131  return data_read == safe_file_size;
132}
133
134bool OwnerKeyUtilsImpl::Verify(const std::string& data,
135                               const std::vector<uint8> signature,
136                               const std::vector<uint8> public_key) {
137  crypto::SignatureVerifier verifier;
138  if (!verifier.VerifyInit(kSignatureAlgorithm, sizeof(kSignatureAlgorithm),
139                           &signature[0], signature.size(),
140                           &public_key[0], public_key.size())) {
141    return false;
142  }
143
144  verifier.VerifyUpdate(reinterpret_cast<const uint8*>(data.c_str()),
145                        data.length());
146  return (verifier.VerifyFinal());
147}
148
149bool OwnerKeyUtilsImpl::Sign(const std::string& data,
150                             std::vector<uint8>* OUT_signature,
151                             crypto::RSAPrivateKey* key) {
152  scoped_ptr<crypto::SignatureCreator> signer(
153      crypto::SignatureCreator::Create(key));
154  if (!signer->Update(reinterpret_cast<const uint8*>(data.c_str()),
155                      data.length())) {
156    return false;
157  }
158  return signer->Final(OUT_signature);
159}
160
161crypto::RSAPrivateKey* OwnerKeyUtilsImpl::FindPrivateKey(
162    const std::vector<uint8>& key) {
163  return crypto::RSAPrivateKey::FindFromPublicKeyInfo(key);
164}
165
166FilePath OwnerKeyUtilsImpl::GetOwnerKeyFilePath() {
167  return FilePath(OwnerKeyUtilsImpl::kOwnerKeyFile);
168}
169
170}  // namespace chromeos
171