OLD | NEW |
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_manager.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 // static | 23 // static |
24 const char OwnerManager::kOwnerKeyFile[] = "/var/lib/whitelist/owner.key"; | 24 OwnerKeyUtils::Factory* OwnerKeyUtils::factory_ = NULL; |
| 25 |
| 26 class OwnerKeyUtilsImpl : public OwnerKeyUtils { |
| 27 public: |
| 28 OwnerKeyUtilsImpl(); |
| 29 virtual ~OwnerKeyUtilsImpl(); |
| 30 |
| 31 bool GenerateKeyPair(SECKEYPrivateKey** private_key_out, |
| 32 SECKEYPublicKey** public_key_out); |
| 33 |
| 34 bool ExportPublicKey(SECKEYPublicKey* key, const FilePath& key_file); |
| 35 |
| 36 SECKEYPublicKey* ImportPublicKey(const FilePath& key_file); |
| 37 |
| 38 private: |
| 39 // 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 |
| 41 // struct for |key_der|. |key_der->data| should be initialized to NULL |
| 42 // and |key_der->len| should be set to 0. |
| 43 // |
| 44 // Upon success, data is stored in key_der->data, and the caller takes |
| 45 // ownership. Returns false on error. |
| 46 // |
| 47 // To free the data, call |
| 48 // SECITEM_FreeItem(key_der, PR_FALSE); |
| 49 static bool ReadDERFromFile(const FilePath& key_file, SECItem* key_der); |
| 50 |
| 51 // The place outside the owner's encrypted home directory where her |
| 52 // key will live. |
| 53 static const char kOwnerKeyFile[]; |
| 54 |
| 55 // Key generation parameters. |
| 56 static const uint32 kKeyGenMechanism; // used by PK11_GenerateKeyPair() |
| 57 static const unsigned long kExponent; |
| 58 static const int kKeySizeInBits; |
| 59 |
| 60 DISALLOW_COPY_AND_ASSIGN(OwnerKeyUtilsImpl); |
| 61 }; |
| 62 |
| 63 OwnerKeyUtils::OwnerKeyUtils() {} |
| 64 |
| 65 OwnerKeyUtils::~OwnerKeyUtils() {} |
| 66 |
| 67 OwnerKeyUtils* OwnerKeyUtils::Create() { |
| 68 if (!factory_) |
| 69 return new OwnerKeyUtilsImpl(); |
| 70 else |
| 71 return factory_->CreateOwnerKeyUtils(); |
| 72 } |
| 73 |
| 74 // static |
| 75 const char OwnerKeyUtilsImpl::kOwnerKeyFile[] = "/var/lib/whitelist/owner.key"; |
25 | 76 |
26 // We're generating and using 2048-bit RSA keys. | 77 // We're generating and using 2048-bit RSA keys. |
27 // static | 78 // static |
28 const uint32 OwnerManager::kKeyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; | 79 const uint32 OwnerKeyUtilsImpl::kKeyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; |
29 // static | 80 // static |
30 const unsigned long OwnerManager::kExponent = 65537UL; | 81 const unsigned long OwnerKeyUtilsImpl::kExponent = 65537UL; |
31 // static | 82 // static |
32 const int OwnerManager::kKeySizeInBits = 2048; | 83 const int OwnerKeyUtilsImpl::kKeySizeInBits = 2048; |
33 | 84 |
34 // static | 85 OwnerKeyUtilsImpl::OwnerKeyUtilsImpl(){} |
35 bool OwnerManager::GenerateKeyPair(SECKEYPrivateKey** private_key_out, | 86 |
36 SECKEYPublicKey** public_key_out) { | 87 OwnerKeyUtilsImpl::~OwnerKeyUtilsImpl() {} |
| 88 |
| 89 bool OwnerKeyUtilsImpl::GenerateKeyPair(SECKEYPrivateKey** private_key_out, |
| 90 SECKEYPublicKey** public_key_out) { |
37 DCHECK(private_key_out); | 91 DCHECK(private_key_out); |
38 DCHECK(public_key_out); | 92 DCHECK(public_key_out); |
39 | 93 |
40 *private_key_out = NULL; | 94 *private_key_out = NULL; |
41 *public_key_out = NULL; | 95 *public_key_out = NULL; |
42 | 96 |
43 // Temporary structures used for generating the result | 97 // Temporary structures used for generating the result |
44 // in the right format. | 98 // in the right format. |
45 PK11SlotInfo* slot = NULL; | 99 PK11SlotInfo* slot = NULL; |
46 PK11RSAGenParams rsa_key_gen_params; | 100 PK11RSAGenParams rsa_key_gen_params; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 } else { | 162 } else { |
109 LOG(INFO) << "Owner key generation succeeded!"; | 163 LOG(INFO) << "Owner key generation succeeded!"; |
110 } | 164 } |
111 if (slot != NULL) { | 165 if (slot != NULL) { |
112 PK11_FreeSlot(slot); | 166 PK11_FreeSlot(slot); |
113 } | 167 } |
114 | 168 |
115 return is_success; | 169 return is_success; |
116 } | 170 } |
117 | 171 |
118 // static | 172 bool OwnerKeyUtilsImpl::ExportPublicKey(SECKEYPublicKey* key, |
119 bool OwnerManager::ExportPublicKey(SECKEYPublicKey* key, | 173 const FilePath& key_file) { |
120 const FilePath& key_file) { | |
121 DCHECK(key); | 174 DCHECK(key); |
122 SECItem* der; | 175 SECItem* der; |
123 bool ok = false; | 176 bool ok = false; |
124 int safe_file_size = 0; | 177 int safe_file_size = 0; |
125 | 178 |
126 // Instead of exporting/importing the key directly, I'm actually | 179 // Instead of exporting/importing the key directly, I'm actually |
127 // going to use a SubjectPublicKeyInfo. The reason is because NSS | 180 // going to use a SubjectPublicKeyInfo. The reason is because NSS |
128 // exports functions that encode/decode these kinds of structures, while | 181 // exports functions that encode/decode these kinds of structures, while |
129 // it does not export the ones that deal directly with public keys. | 182 // it does not export the ones that deal directly with public keys. |
130 der = SECKEY_EncodeDERSubjectPublicKeyInfo(key); | 183 der = SECKEY_EncodeDERSubjectPublicKeyInfo(key); |
131 if (!der) { | 184 if (!der) { |
132 LOG(ERROR) << "Could not encode public key for export!"; | 185 LOG(ERROR) << "Could not encode public key for export!"; |
133 return false; | 186 return false; |
134 } | 187 } |
135 | 188 |
136 if (der->len > static_cast<uint>(INT_MAX)) { | 189 if (der->len > static_cast<uint>(INT_MAX)) { |
137 LOG(ERROR) << "key is too big! " << der->len; | 190 LOG(ERROR) << "key is too big! " << der->len; |
138 } else { | 191 } else { |
139 safe_file_size = static_cast<int>(der->len); | 192 safe_file_size = static_cast<int>(der->len); |
140 | 193 |
141 ok = (safe_file_size == | 194 ok = (safe_file_size == |
142 file_util::WriteFile(key_file, | 195 file_util::WriteFile(key_file, |
143 reinterpret_cast<char*>(der->data), | 196 reinterpret_cast<char*>(der->data), |
144 der->len)); | 197 der->len)); |
145 } | 198 } |
146 SECITEM_FreeItem(der, PR_TRUE); | 199 SECITEM_FreeItem(der, PR_TRUE); |
147 return ok; | 200 return ok; |
148 } | 201 } |
149 | 202 |
150 // static | 203 SECKEYPublicKey* OwnerKeyUtilsImpl::ImportPublicKey(const FilePath& key_file) { |
151 SECKEYPublicKey* OwnerManager::ImportPublicKey(const FilePath& key_file) { | |
152 SECItem key_der; | 204 SECItem key_der; |
153 | 205 |
154 if (!ReadDERFromFile(key_file, &key_der)) { | 206 if (!ReadDERFromFile(key_file, &key_der)) { |
155 PLOG(ERROR) << "Could not read in key from " << key_file.value() << ":"; | 207 PLOG(ERROR) << "Could not read in key from " << key_file.value() << ":"; |
156 return NULL; | 208 return NULL; |
157 } | 209 } |
158 | 210 |
159 // See the comment in ExportPublicKey() for why I wrote a | 211 // See the comment in ExportPublicKey() for why I wrote a |
160 // SubjectPublicKeyInfo to disk instead of a key. | 212 // SubjectPublicKeyInfo to disk instead of a key. |
161 CERTSubjectPublicKeyInfo* spki = | 213 CERTSubjectPublicKeyInfo* spki = |
162 SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der); | 214 SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der); |
163 if (!spki) { | 215 if (!spki) { |
164 LOG(ERROR) << "Could not decode key info: " << PR_GetError(); | 216 LOG(ERROR) << "Could not decode key info: " << PR_GetError(); |
| 217 SECITEM_FreeItem(&key_der, PR_FALSE); |
165 return NULL; | 218 return NULL; |
166 } | 219 } |
167 | 220 |
168 SECKEYPublicKey *public_key = SECKEY_ExtractPublicKey(spki); | 221 SECKEYPublicKey *public_key = SECKEY_ExtractPublicKey(spki); |
169 SECKEY_DestroySubjectPublicKeyInfo(spki); | 222 SECKEY_DestroySubjectPublicKeyInfo(spki); |
| 223 SECITEM_FreeItem(&key_der, PR_FALSE); |
170 return public_key; | 224 return public_key; |
171 } | 225 } |
172 | 226 |
173 // static | 227 // static |
174 bool OwnerManager::ReadDERFromFile(const FilePath& key_file, | 228 bool OwnerKeyUtilsImpl::ReadDERFromFile(const FilePath& key_file, |
175 SECItem* key_der) { | 229 SECItem* key_der) { |
176 // I'd use NSS' SECU_ReadDERFromFile() here, but the SECU_* functions are | 230 // I'd use NSS' SECU_ReadDERFromFile() here, but the SECU_* functions are |
177 // considered internal to the NSS command line utils. | 231 // considered internal to the NSS command line utils. |
178 // This code is lifted, in spirit, from the implementation of that function. | 232 // This code is lifted, in spirit, from the implementation of that function. |
179 DCHECK(key_der) << "Don't pass NULL for |key_der|"; | 233 DCHECK(key_der) << "Don't pass NULL for |key_der|"; |
180 | 234 |
181 // Get the file size (must fit in a 32 bit int for NSS). | 235 // Get the file size (must fit in a 32 bit int for NSS). |
182 int64 file_size; | 236 int64 file_size; |
183 if (!file_util::GetFileSize(key_file, &file_size)) { | 237 if (!file_util::GetFileSize(key_file, &file_size)) { |
184 LOG(ERROR) << "Could not get size of " << key_file.value(); | 238 LOG(ERROR) << "Could not get size of " << key_file.value(); |
185 return false; | 239 return false; |
(...skipping 18 matching lines...) Expand all Loading... |
204 safe_file_size); | 258 safe_file_size); |
205 | 259 |
206 if (data_read != safe_file_size) { | 260 if (data_read != safe_file_size) { |
207 LOG(ERROR) << "Read the wrong amount of data from the DER encoded key! " | 261 LOG(ERROR) << "Read the wrong amount of data from the DER encoded key! " |
208 << data_read; | 262 << data_read; |
209 SECITEM_FreeItem(key_der, PR_FALSE); | 263 SECITEM_FreeItem(key_der, PR_FALSE); |
210 return false; | 264 return false; |
211 } | 265 } |
212 return true; | 266 return true; |
213 } | 267 } |
OLD | NEW |