Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: chrome/browser/chromeos/login/owner_key_utils.cc

Issue 3078001: Update OwnerKeyUtils API (Closed)
Patch Set: address comments Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/login/owner_key_utils.h" 5 #include "chrome/browser/chromeos/login/owner_key_utils.h"
6 6
7 #include <keyhi.h> // SECKEY_CreateSubjectPublicKeyInfo() 7 #include <keyhi.h> // SECKEY_CreateSubjectPublicKeyInfo()
8 #include <pk11pub.h> 8 #include <pk11pub.h>
9 #include <prerror.h> // PR_GetError() 9 #include <prerror.h> // PR_GetError()
10 #include <secder.h> // DER_Encode() 10 #include <secder.h> // DER_Encode()
11 #include <secmod.h> 11 #include <secmod.h>
12 12
13 #include <limits> 13 #include <limits>
14 14
15 #include "base/file_path.h" 15 #include "base/file_path.h"
16 #include "base/file_util.h" 16 #include "base/file_util.h"
17 #include "base/logging.h" 17 #include "base/logging.h"
18 #include "base/nss_util_internal.h" 18 #include "base/nss_util_internal.h"
19 #include "base/nss_util.h" 19 #include "base/nss_util.h"
20 #include "base/scoped_ptr.h" 20 #include "base/scoped_ptr.h"
21 #include "base/string_util.h" 21 #include "base/string_util.h"
22 22
23 namespace chromeos {
24
25 ///////////////////////////////////////////////////////////////////////////
26 // OwnerKeyUtils
27
23 // static 28 // static
24 OwnerKeyUtils::Factory* OwnerKeyUtils::factory_ = NULL; 29 OwnerKeyUtils::Factory* OwnerKeyUtils::factory_ = NULL;
25 30
31 OwnerKeyUtils::OwnerKeyUtils() {}
32
33 OwnerKeyUtils::~OwnerKeyUtils() {}
34
35 ///////////////////////////////////////////////////////////////////////////
36 // OwnerKeyUtilsImpl
37
26 class OwnerKeyUtilsImpl : public OwnerKeyUtils { 38 class OwnerKeyUtilsImpl : public OwnerKeyUtils {
27 public: 39 public:
28 OwnerKeyUtilsImpl(); 40 OwnerKeyUtilsImpl();
29 virtual ~OwnerKeyUtilsImpl(); 41 virtual ~OwnerKeyUtilsImpl();
30 42
31 bool GenerateKeyPair(SECKEYPrivateKey** private_key_out, 43 bool GenerateKeyPair(SECKEYPrivateKey** private_key_out,
32 SECKEYPublicKey** public_key_out); 44 SECKEYPublicKey** public_key_out);
33 45
34 bool ExportPublicKey(SECKEYPublicKey* key, const FilePath& key_file); 46 bool ExportPublicKeyViaDbus(SECKEYPublicKey* key);
47
48 bool ExportPublicKeyToFile(SECKEYPublicKey* key, const FilePath& key_file);
35 49
36 SECKEYPublicKey* ImportPublicKey(const FilePath& key_file); 50 SECKEYPublicKey* ImportPublicKey(const FilePath& key_file);
37 51
52 SECKEYPrivateKey* FindPrivateKey(SECKEYPublicKey* key);
53
54 void DestroyKeys(SECKEYPrivateKey* private_key, SECKEYPublicKey* public_key);
55
56 FilePath GetOwnerKeyFilePath();
57
38 private: 58 private:
39 // Fills in fields of |key_der| with DER encoded data from a file at 59 // Fills in fields of |key_der| with DER encoded data from a file at
40 // |key_file|. The caller must pass in a pointer to an actual SECItem 60 // |key_file|. The caller must pass in a pointer to an actual SECItem
41 // struct for |key_der|. |key_der->data| should be initialized to NULL 61 // struct for |key_der|. |key_der->data| should be initialized to NULL
42 // and |key_der->len| should be set to 0. 62 // and |key_der->len| should be set to 0.
43 // 63 //
44 // Upon success, data is stored in key_der->data, and the caller takes 64 // Upon success, data is stored in key_der->data, and the caller takes
45 // ownership. Returns false on error. 65 // ownership. Returns false on error.
46 // 66 //
47 // To free the data, call 67 // To free the data, call
48 // SECITEM_FreeItem(key_der, PR_FALSE); 68 // SECITEM_FreeItem(key_der, PR_FALSE);
49 static bool ReadDERFromFile(const FilePath& key_file, SECItem* key_der); 69 static bool ReadDERFromFile(const FilePath& key_file, SECItem* key_der);
50 70
51 // The place outside the owner's encrypted home directory where her 71 static bool EncodePublicKey(SECKEYPublicKey* key, std::string* out);
72
73 // The file outside the owner's encrypted home directory where her
52 // key will live. 74 // key will live.
53 static const char kOwnerKeyFile[]; 75 static const char kOwnerKeyFile[];
54 76
55 // Key generation parameters. 77 // Key generation parameters.
56 static const uint32 kKeyGenMechanism; // used by PK11_GenerateKeyPair() 78 static const uint32 kKeyGenMechanism; // used by PK11_GenerateKeyPair()
57 static const unsigned long kExponent; 79 static const unsigned long kExponent;
58 static const int kKeySizeInBits; 80 static const int kKeySizeInBits;
59 81
60 DISALLOW_COPY_AND_ASSIGN(OwnerKeyUtilsImpl); 82 DISALLOW_COPY_AND_ASSIGN(OwnerKeyUtilsImpl);
61 }; 83 };
62 84
63 OwnerKeyUtils::OwnerKeyUtils() {} 85 // Defined here, instead of up above, because we need OwnerKeyUtilsImpl.
64
65 OwnerKeyUtils::~OwnerKeyUtils() {}
66
67 OwnerKeyUtils* OwnerKeyUtils::Create() { 86 OwnerKeyUtils* OwnerKeyUtils::Create() {
68 if (!factory_) 87 if (!factory_)
69 return new OwnerKeyUtilsImpl(); 88 return new OwnerKeyUtilsImpl();
70 else 89 else
71 return factory_->CreateOwnerKeyUtils(); 90 return factory_->CreateOwnerKeyUtils();
72 } 91 }
73 92
74 // static 93 // static
75 const char OwnerKeyUtilsImpl::kOwnerKeyFile[] = "/var/lib/whitelist/owner.key"; 94 const char OwnerKeyUtilsImpl::kOwnerKeyFile[] = "/var/lib/whitelist/owner.key";
76 95
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 if (!*private_key_out) { 159 if (!*private_key_out) {
141 LOG(INFO) << "Generation of Keypair failed!"; 160 LOG(INFO) << "Generation of Keypair failed!";
142 is_success = false; 161 is_success = false;
143 goto failure; 162 goto failure;
144 } 163 }
145 164
146 failure: 165 failure:
147 if (!is_success) { 166 if (!is_success) {
148 LOG(ERROR) << "Owner key generation failed! (NSS error code " 167 LOG(ERROR) << "Owner key generation failed! (NSS error code "
149 << PR_GetError() << ")"; 168 << PR_GetError() << ")";
150 // Do cleanups 169 DestroyKeys(*private_key_out, *public_key_out);
151 base::AutoNSSWriteLock lock; 170 *private_key_out = NULL;
152 if (*private_key_out) { 171 *public_key_out = NULL;
153 PK11_DestroyTokenObject((*private_key_out)->pkcs11Slot,
154 (*private_key_out)->pkcs11ID);
155 SECKEY_DestroyPrivateKey(*private_key_out);
156 }
157 if (*public_key_out) {
158 PK11_DestroyTokenObject((*public_key_out)->pkcs11Slot,
159 (*public_key_out)->pkcs11ID);
160 SECKEY_DestroyPublicKey(*public_key_out);
161 }
162 } else { 172 } else {
163 LOG(INFO) << "Owner key generation succeeded!"; 173 LOG(INFO) << "Owner key generation succeeded!";
164 } 174 }
165 if (slot != NULL) { 175 if (slot != NULL) {
166 PK11_FreeSlot(slot); 176 PK11_FreeSlot(slot);
167 } 177 }
168 178
169 return is_success; 179 return is_success;
170 } 180 }
171 181
172 bool OwnerKeyUtilsImpl::ExportPublicKey(SECKEYPublicKey* key, 182 bool OwnerKeyUtilsImpl::ExportPublicKeyViaDbus(SECKEYPublicKey* key) {
173 const FilePath& key_file) {
174 DCHECK(key); 183 DCHECK(key);
175 SECItem* der; 184 bool ok = false;
185
186 std::string to_export;
187 if (!EncodePublicKey(key, &to_export)) {
188 LOG(ERROR) << "Formatting key for export failed!";
189 return ok;
190 }
191
192 // TODO(cmasone): send the data over dbus.
193 return ok;
194 }
195
196 bool OwnerKeyUtilsImpl::ExportPublicKeyToFile(SECKEYPublicKey* key,
197 const FilePath& key_file) {
198 DCHECK(key);
176 bool ok = false; 199 bool ok = false;
177 int safe_file_size = 0; 200 int safe_file_size = 0;
178 201
179 // Instead of exporting/importing the key directly, I'm actually 202 std::string to_export;
180 // going to use a SubjectPublicKeyInfo. The reason is because NSS 203 if (!EncodePublicKey(key, &to_export)) {
181 // exports functions that encode/decode these kinds of structures, while 204 LOG(ERROR) << "Formatting key for export failed!";
182 // it does not export the ones that deal directly with public keys. 205 return ok;
183 der = SECKEY_EncodeDERSubjectPublicKeyInfo(key);
184 if (!der) {
185 LOG(ERROR) << "Could not encode public key for export!";
186 return false;
187 } 206 }
188 207
189 if (der->len > static_cast<uint>(INT_MAX)) { 208 if (to_export.length() > static_cast<uint>(INT_MAX)) {
190 LOG(ERROR) << "key is too big! " << der->len; 209 LOG(ERROR) << "key is too big! " << to_export.length();
191 } else { 210 } else {
192 safe_file_size = static_cast<int>(der->len); 211 safe_file_size = static_cast<int>(to_export.length());
193 212
194 ok = (safe_file_size == 213 ok = (safe_file_size == file_util::WriteFile(key_file,
195 file_util::WriteFile(key_file, 214 to_export.c_str(),
196 reinterpret_cast<char*>(der->data), 215 safe_file_size));
197 der->len));
198 } 216 }
199 SECITEM_FreeItem(der, PR_TRUE);
200 return ok; 217 return ok;
201 } 218 }
202 219
203 SECKEYPublicKey* OwnerKeyUtilsImpl::ImportPublicKey(const FilePath& key_file) { 220 SECKEYPublicKey* OwnerKeyUtilsImpl::ImportPublicKey(const FilePath& key_file) {
204 SECItem key_der; 221 SECItem key_der;
222 key_der.data = NULL;
223 key_der.len = 0;
205 224
206 if (!ReadDERFromFile(key_file, &key_der)) { 225 if (!ReadDERFromFile(key_file, &key_der)) {
207 PLOG(ERROR) << "Could not read in key from " << key_file.value() << ":"; 226 PLOG(ERROR) << "Could not read in key from " << key_file.value() << ":";
208 return NULL; 227 return NULL;
209 } 228 }
210 229
211 // See the comment in ExportPublicKey() for why I wrote a 230 // See the comment in ExportPublicKey() for why I wrote a
212 // SubjectPublicKeyInfo to disk instead of a key. 231 // SubjectPublicKeyInfo to disk instead of a key.
213 CERTSubjectPublicKeyInfo* spki = 232 CERTSubjectPublicKeyInfo* spki =
214 SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der); 233 SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der);
215 if (!spki) { 234 if (!spki) {
216 LOG(ERROR) << "Could not decode key info: " << PR_GetError(); 235 LOG(ERROR) << "Could not decode key info: " << PR_GetError();
217 SECITEM_FreeItem(&key_der, PR_FALSE); 236 SECITEM_FreeItem(&key_der, PR_FALSE);
218 return NULL; 237 return NULL;
219 } 238 }
220 239
221 SECKEYPublicKey *public_key = SECKEY_ExtractPublicKey(spki); 240 SECKEYPublicKey *public_key = SECKEY_ExtractPublicKey(spki);
222 SECKEY_DestroySubjectPublicKeyInfo(spki); 241 SECKEY_DestroySubjectPublicKeyInfo(spki);
223 SECITEM_FreeItem(&key_der, PR_FALSE); 242 SECITEM_FreeItem(&key_der, PR_FALSE);
224 return public_key; 243 return public_key;
225 } 244 }
226 245
227 // static 246 // static
228 bool OwnerKeyUtilsImpl::ReadDERFromFile(const FilePath& key_file, 247 bool OwnerKeyUtilsImpl::ReadDERFromFile(const FilePath& key_file,
229 SECItem* key_der) { 248 SECItem* key_der) {
230 // I'd use NSS' SECU_ReadDERFromFile() here, but the SECU_* functions are 249 // I'd use NSS' SECU_ReadDERFromFile() here, but the SECU_* functions are
231 // considered internal to the NSS command line utils. 250 // considered internal to the NSS command line utils.
232 // This code is lifted, in spirit, from the implementation of that function. 251 // This code is lifted, in spirit, from the implementation of that function.
233 DCHECK(key_der) << "Don't pass NULL for |key_der|"; 252 DCHECK(key_der) << "Don't pass NULL for |key_der|";
253 DCHECK(key_der->data == NULL);
254 DCHECK(key_der->len == 0);
234 255
235 // Get the file size (must fit in a 32 bit int for NSS). 256 // Get the file size (must fit in a 32 bit int for NSS).
236 int64 file_size; 257 int64 file_size;
237 if (!file_util::GetFileSize(key_file, &file_size)) { 258 if (!file_util::GetFileSize(key_file, &file_size)) {
238 LOG(ERROR) << "Could not get size of " << key_file.value(); 259 LOG(ERROR) << "Could not get size of " << key_file.value();
239 return false; 260 return false;
240 } 261 }
241 if (file_size > static_cast<int64>(std::numeric_limits<int>::max())) { 262 if (file_size > static_cast<int64>(std::numeric_limits<int>::max())) {
242 LOG(ERROR) << key_file.value() << "is " 263 LOG(ERROR) << key_file.value() << "is "
243 << file_size << "bytes!!! Too big!"; 264 << file_size << "bytes!!! Too big!";
(...skipping 14 matching lines...) Expand all
258 safe_file_size); 279 safe_file_size);
259 280
260 if (data_read != safe_file_size) { 281 if (data_read != safe_file_size) {
261 LOG(ERROR) << "Read the wrong amount of data from the DER encoded key! " 282 LOG(ERROR) << "Read the wrong amount of data from the DER encoded key! "
262 << data_read; 283 << data_read;
263 SECITEM_FreeItem(key_der, PR_FALSE); 284 SECITEM_FreeItem(key_der, PR_FALSE);
264 return false; 285 return false;
265 } 286 }
266 return true; 287 return true;
267 } 288 }
289
290 bool OwnerKeyUtilsImpl::EncodePublicKey(SECKEYPublicKey* key,
291 std::string* out) {
292 SECItem* der;
293
294 // Instead of exporting/importing the key directly, I'm actually
295 // going to use a SubjectPublicKeyInfo. The reason is because NSS
296 // exports functions that encode/decode these kinds of structures, while
297 // it does not export the ones that deal directly with public keys.
298 der = SECKEY_EncodeDERSubjectPublicKeyInfo(key);
299 if (!der) {
300 LOG(ERROR) << "Could not encode public key for export!";
301 return false;
302 }
303
304 out->assign(reinterpret_cast<char*>(der->data), der->len);
305
306 SECITEM_FreeItem(der, PR_TRUE);
307 return true;
308 }
309
310 SECKEYPrivateKey* OwnerKeyUtilsImpl::FindPrivateKey(SECKEYPublicKey* key) {
311 DCHECK(key);
312
313 PK11SlotInfo* slot = NULL;
314 SECItem* ck_id = NULL;
315 SECKEYPrivateKey* found = NULL;
316
317 slot = base::GetDefaultNSSKeySlot();
318 if (!slot)
319 goto cleanup;
320
321 ck_id = PK11_MakeIDFromPubKey(&(key->u.rsa.modulus));
322 if (!ck_id)
323 goto cleanup;
324
325 found = PK11_FindKeyByKeyID(slot, ck_id, NULL);
326
327 cleanup:
328 if (slot)
329 PK11_FreeSlot(slot);
330 if (ck_id)
331 SECITEM_FreeItem(ck_id, PR_TRUE);
332
333 return found;
334 }
335
336 void OwnerKeyUtilsImpl::DestroyKeys(SECKEYPrivateKey* private_key,
337 SECKEYPublicKey* public_key) {
338 base::AutoNSSWriteLock lock;
339 if (private_key) {
340 PK11_DestroyTokenObject(private_key->pkcs11Slot, private_key->pkcs11ID);
341 SECKEY_DestroyPrivateKey(private_key);
342 }
343 if (public_key) {
344 PK11_DestroyTokenObject(public_key->pkcs11Slot, public_key->pkcs11ID);
345 SECKEY_DestroyPublicKey(public_key);
346 }
347 }
348
349 FilePath OwnerKeyUtilsImpl::GetOwnerKeyFilePath() {
350 return FilePath(OwnerKeyUtilsImpl::kOwnerKeyFile);
351 }
352
353 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/login/owner_key_utils.h ('k') | chrome/browser/chromeos/login/owner_key_utils_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698