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
21 using extension_misc::kSignatureAlgorithm;
22
23 namespace chromeos {
24
25 ///////////////////////////////////////////////////////////////////////////
26 // OwnerKeyUtils
27
28 // static
29 OwnerKeyUtils::Factory* OwnerKeyUtils::factory_ = NULL;
30
OwnerKeyUtils()31 OwnerKeyUtils::OwnerKeyUtils() {}
32
~OwnerKeyUtils()33 OwnerKeyUtils::~OwnerKeyUtils() {}
34
35 ///////////////////////////////////////////////////////////////////////////
36 // OwnerKeyUtilsImpl
37
38 class 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.
Create()72 OwnerKeyUtils* OwnerKeyUtils::Create() {
73 if (!factory_)
74 return new OwnerKeyUtilsImpl();
75 else
76 return factory_->CreateOwnerKeyUtils();
77 }
78
79 // static
80 const char OwnerKeyUtilsImpl::kOwnerKeyFile[] = "/var/lib/whitelist/owner.key";
81
OwnerKeyUtilsImpl()82 OwnerKeyUtilsImpl::OwnerKeyUtilsImpl() {}
83
~OwnerKeyUtilsImpl()84 OwnerKeyUtilsImpl::~OwnerKeyUtilsImpl() {}
85
ExportPublicKeyToFile(crypto::RSAPrivateKey * pair,const FilePath & key_file)86 bool 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
ImportPublicKey(const FilePath & key_file,std::vector<uint8> * output)111 bool 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
Verify(const std::string & data,const std::vector<uint8> signature,const std::vector<uint8> public_key)134 bool 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
Sign(const std::string & data,std::vector<uint8> * OUT_signature,crypto::RSAPrivateKey * key)149 bool 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
FindPrivateKey(const std::vector<uint8> & key)161 crypto::RSAPrivateKey* OwnerKeyUtilsImpl::FindPrivateKey(
162 const std::vector<uint8>& key) {
163 return crypto::RSAPrivateKey::FindFromPublicKeyInfo(key);
164 }
165
GetOwnerKeyFilePath()166 FilePath OwnerKeyUtilsImpl::GetOwnerKeyFilePath() {
167 return FilePath(OwnerKeyUtilsImpl::kOwnerKeyFile);
168 }
169
170 } // namespace chromeos
171