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