OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/cros/cert_library.h" | 5 #include "chrome/browser/chromeos/cros/cert_library.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/chromeos/chromeos_version.h" | 9 #include "base/chromeos/chromeos_version.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 29 matching lines...) Expand all Loading... |
40 namespace { | 40 namespace { |
41 | 41 |
42 // Root CA certificates that are built into Chrome use this token name. | 42 // Root CA certificates that are built into Chrome use this token name. |
43 const char kRootCertificateTokenName[] = "Builtin Object Token"; | 43 const char kRootCertificateTokenName[] = "Builtin Object Token"; |
44 | 44 |
45 // Delay between certificate requests while waiting for TPM/PKCS#11 init. | 45 // Delay between certificate requests while waiting for TPM/PKCS#11 init. |
46 const int kRequestDelayMs = 500; | 46 const int kRequestDelayMs = 500; |
47 | 47 |
48 const size_t kKeySize = 16; | 48 const size_t kKeySize = 16; |
49 | 49 |
50 // Decrypts (AES) hex encoded encrypted token given |key| and |salt|. | |
51 std::string DecryptTokenWithKey( | |
52 crypto::SymmetricKey* key, | |
53 const std::string& salt, | |
54 const std::string& encrypted_token_hex) { | |
55 std::vector<uint8> encrypted_token_bytes; | |
56 if (!base::HexStringToBytes(encrypted_token_hex, &encrypted_token_bytes)) { | |
57 LOG(WARNING) << "Corrupt encrypted token found."; | |
58 return std::string(); | |
59 } | |
60 | |
61 std::string encrypted_token( | |
62 reinterpret_cast<char*>(encrypted_token_bytes.data()), | |
63 encrypted_token_bytes.size()); | |
64 crypto::Encryptor encryptor; | |
65 if (!encryptor.Init(key, crypto::Encryptor::CTR, std::string())) { | |
66 LOG(WARNING) << "Failed to initialize Encryptor."; | |
67 return std::string(); | |
68 } | |
69 | |
70 std::string nonce = salt.substr(0, kKeySize); | |
71 std::string token; | |
72 CHECK(encryptor.SetCounter(nonce)); | |
73 if (!encryptor.Decrypt(encrypted_token, &token)) { | |
74 LOG(WARNING) << "Failed to decrypt token."; | |
75 return std::string(); | |
76 } | |
77 return token; | |
78 } | |
79 | |
80 string16 GetDisplayString(net::X509Certificate* cert, bool hardware_backed) { | 50 string16 GetDisplayString(net::X509Certificate* cert, bool hardware_backed) { |
81 std::string org; | 51 std::string org; |
82 if (!cert->subject().organization_names.empty()) | 52 if (!cert->subject().organization_names.empty()) |
83 org = cert->subject().organization_names[0]; | 53 org = cert->subject().organization_names[0]; |
84 if (org.empty()) | 54 if (org.empty()) |
85 org = cert->subject().GetDisplayName(); | 55 org = cert->subject().GetDisplayName(); |
86 string16 issued_by = UTF8ToUTF16( | 56 string16 issued_by = UTF8ToUTF16( |
87 x509_certificate_model::GetIssuerCommonName(cert->os_cert_handle(), | 57 x509_certificate_model::GetIssuerCommonName(cert->os_cert_handle(), |
88 org)); // alternative text | 58 org)); // alternative text |
89 string16 issued_to = UTF8ToUTF16( | 59 string16 issued_to = UTF8ToUTF16( |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 virtual const CertList& GetServerCertificates() const OVERRIDE { | 159 virtual const CertList& GetServerCertificates() const OVERRIDE { |
190 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 160 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
191 return server_certs_; | 161 return server_certs_; |
192 } | 162 } |
193 | 163 |
194 virtual const CertList& GetCACertificates() const OVERRIDE { | 164 virtual const CertList& GetCACertificates() const OVERRIDE { |
195 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 165 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
196 return server_ca_certs_; | 166 return server_ca_certs_; |
197 } | 167 } |
198 | 168 |
199 virtual std::string EncryptToken(const std::string& token) OVERRIDE { | 169 virtual crypto::SymmetricKey* PassphraseToKey(const std::string& passprhase, |
| 170 const std::string& salt) { |
| 171 return crypto::SymmetricKey::DeriveKeyFromPassword( |
| 172 crypto::SymmetricKey::AES, passprhase, salt, 1000, 256); |
| 173 } |
| 174 |
| 175 virtual std::string EncryptWithSystemSalt(const std::string& token) OVERRIDE { |
200 // Don't care about token encryption while debugging. | 176 // Don't care about token encryption while debugging. |
201 if (!base::chromeos::IsRunningOnChromeOS()) | 177 if (!base::chromeos::IsRunningOnChromeOS()) |
202 return token; | 178 return token; |
| 179 |
| 180 if (!LoadSystemSaltKey()) { |
| 181 LOG(WARNING) << "System salt key is not available for encrypt."; |
| 182 return std::string(); |
| 183 } |
| 184 return EncryptTokenWithKey( |
| 185 system_salt_key_.get(), |
| 186 CrosLibrary::Get()->GetCryptohomeLibrary()->GetSystemSalt(), |
| 187 token); |
| 188 } |
| 189 |
| 190 virtual std::string EncryptWithUserKey(const std::string& token) OVERRIDE { |
| 191 // Don't care about token encryption while debugging. |
| 192 if (!base::chromeos::IsRunningOnChromeOS()) |
| 193 return token; |
203 | 194 |
204 if (!LoadSupplementalUserKey()) { | 195 if (!LoadSupplementalUserKey()) { |
205 LOG(WARNING) << "Supplemental user key is not available for encrypt."; | 196 LOG(WARNING) << "Supplemental user key is not available for encrypt."; |
206 return std::string(); | 197 return std::string(); |
207 } | 198 } |
| 199 return EncryptTokenWithKey( |
| 200 supplemental_user_key_.get(), |
| 201 CrosLibrary::Get()->GetCryptohomeLibrary()->GetSystemSalt(), |
| 202 token); |
| 203 } |
| 204 |
| 205 // Encrypts (AES) the token given |key| and |salt|. |
| 206 virtual std::string EncryptTokenWithKey(crypto::SymmetricKey* key, |
| 207 const std::string& salt, |
| 208 const std::string& token) { |
208 crypto::Encryptor encryptor; | 209 crypto::Encryptor encryptor; |
209 if (!encryptor.Init(supplemental_user_key_.get(), crypto::Encryptor::CTR, | 210 if (!encryptor.Init(key, crypto::Encryptor::CTR, std::string())) { |
210 std::string())) { | |
211 LOG(WARNING) << "Failed to initialize Encryptor."; | 211 LOG(WARNING) << "Failed to initialize Encryptor."; |
212 return std::string(); | 212 return std::string(); |
213 } | 213 } |
214 std::string salt = | |
215 CrosLibrary::Get()->GetCryptohomeLibrary()->GetSystemSalt(); | |
216 std::string nonce = salt.substr(0, kKeySize); | 214 std::string nonce = salt.substr(0, kKeySize); |
217 std::string encoded_token; | 215 std::string encoded_token; |
218 CHECK(encryptor.SetCounter(nonce)); | 216 CHECK(encryptor.SetCounter(nonce)); |
219 if (!encryptor.Encrypt(token, &encoded_token)) { | 217 if (!encryptor.Encrypt(token, &encoded_token)) { |
220 LOG(WARNING) << "Failed to encrypt token."; | 218 LOG(WARNING) << "Failed to encrypt token."; |
221 return std::string(); | 219 return std::string(); |
222 } | 220 } |
223 | 221 |
224 return StringToLowerASCII(base::HexEncode( | 222 return StringToLowerASCII(base::HexEncode( |
225 reinterpret_cast<const void*>(encoded_token.data()), | 223 reinterpret_cast<const void*>(encoded_token.data()), |
226 encoded_token.size())); | 224 encoded_token.size())); |
227 } | 225 } |
228 | 226 |
229 virtual std::string DecryptToken( | 227 virtual std::string DecryptWithSystemSalt( |
230 const std::string& encrypted_token_hex) OVERRIDE { | 228 const std::string& encrypted_token_hex) OVERRIDE { |
231 // Don't care about token encryption while debugging. | 229 // Don't care about token encryption while debugging. |
232 if (!base::chromeos::IsRunningOnChromeOS()) | 230 if (!base::chromeos::IsRunningOnChromeOS()) |
| 231 return encrypted_token_hex; |
| 232 |
| 233 if (!LoadSystemSaltKey()) { |
| 234 LOG(WARNING) << "System salt key is not available for decrypt."; |
| 235 return std::string(); |
| 236 } |
| 237 return DecryptTokenWithKey( |
| 238 system_salt_key_.get(), |
| 239 CrosLibrary::Get()->GetCryptohomeLibrary()->GetSystemSalt(), |
| 240 encrypted_token_hex); |
| 241 } |
| 242 |
| 243 virtual std::string DecryptWithUserKey( |
| 244 const std::string& encrypted_token_hex) OVERRIDE { |
| 245 // Don't care about token encryption while debugging. |
| 246 if (!base::chromeos::IsRunningOnChromeOS()) |
233 return encrypted_token_hex; | 247 return encrypted_token_hex; |
234 | 248 |
235 if (!LoadSupplementalUserKey()) { | 249 if (!LoadSupplementalUserKey()) { |
236 LOG(WARNING) << "Supplemental user key is not available for decrypt."; | 250 LOG(WARNING) << "Supplemental user key is not available for decrypt."; |
237 return std::string(); | 251 return std::string(); |
238 } | 252 } |
239 return DecryptTokenWithKey(supplemental_user_key_.get(), | 253 return DecryptTokenWithKey( |
| 254 supplemental_user_key_.get(), |
240 CrosLibrary::Get()->GetCryptohomeLibrary()->GetSystemSalt(), | 255 CrosLibrary::Get()->GetCryptohomeLibrary()->GetSystemSalt(), |
241 encrypted_token_hex); | 256 encrypted_token_hex); |
242 } | 257 } |
243 | 258 |
| 259 // Decrypts (AES) hex encoded encrypted token given |key| and |salt|. |
| 260 virtual std::string DecryptTokenWithKey( |
| 261 crypto::SymmetricKey* key, |
| 262 const std::string& salt, |
| 263 const std::string& encrypted_token_hex) { |
| 264 std::vector<uint8> encrypted_token_bytes; |
| 265 if (!base::HexStringToBytes(encrypted_token_hex, &encrypted_token_bytes)) { |
| 266 LOG(WARNING) << "Corrupt encrypted token found."; |
| 267 return std::string(); |
| 268 } |
| 269 |
| 270 std::string encrypted_token( |
| 271 reinterpret_cast<char*>(encrypted_token_bytes.data()), |
| 272 encrypted_token_bytes.size()); |
| 273 crypto::Encryptor encryptor; |
| 274 if (!encryptor.Init(key, crypto::Encryptor::CTR, std::string())) { |
| 275 LOG(WARNING) << "Failed to initialize Encryptor."; |
| 276 return std::string(); |
| 277 } |
| 278 |
| 279 std::string nonce = salt.substr(0, kKeySize); |
| 280 std::string token; |
| 281 CHECK(encryptor.SetCounter(nonce)); |
| 282 if (!encryptor.Decrypt(encrypted_token, &token)) { |
| 283 LOG(WARNING) << "Failed to decrypt token."; |
| 284 return std::string(); |
| 285 } |
| 286 return token; |
| 287 } |
| 288 |
244 // net::CertDatabase::Observer implementation. Observer added on UI thread. | 289 // net::CertDatabase::Observer implementation. Observer added on UI thread. |
245 virtual void OnCertTrustChanged(const net::X509Certificate* cert) OVERRIDE { | 290 virtual void OnCertTrustChanged(const net::X509Certificate* cert) OVERRIDE { |
246 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 291 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
247 } | 292 } |
248 | 293 |
249 virtual void OnCertAdded(const net::X509Certificate* cert) OVERRIDE { | 294 virtual void OnCertAdded(const net::X509Certificate* cert) OVERRIDE { |
250 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 295 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
251 // Only load certificates if we have completed an initial request. | 296 // Only load certificates if we have completed an initial request. |
252 if (certificates_loaded_) { | 297 if (certificates_loaded_) { |
253 BrowserThread::PostTask( | 298 BrowserThread::PostTask( |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 // Set 'loaded' to true for the UI, since we are not waiting on loading. | 428 // Set 'loaded' to true for the UI, since we are not waiting on loading. |
384 LOG(WARNING) << "Requesting supplemental use key before login."; | 429 LOG(WARNING) << "Requesting supplemental use key before login."; |
385 return false; | 430 return false; |
386 } | 431 } |
387 if (!supplemental_user_key_.get()) { | 432 if (!supplemental_user_key_.get()) { |
388 supplemental_user_key_.reset(crypto::GetSupplementalUserKey()); | 433 supplemental_user_key_.reset(crypto::GetSupplementalUserKey()); |
389 } | 434 } |
390 return supplemental_user_key_.get() != NULL; | 435 return supplemental_user_key_.get() != NULL; |
391 } | 436 } |
392 | 437 |
| 438 // TODO: should this use the system salt for both the password and the salt |
| 439 // value, or should this use a separate salt value? |
| 440 bool LoadSystemSaltKey() { |
| 441 if (!system_salt_key_.get()) { |
| 442 system_salt_key_.reset(PassphraseToKey( |
| 443 CrosLibrary::Get()->GetCryptohomeLibrary()->GetSystemSalt(), |
| 444 CrosLibrary::Get()->GetCryptohomeLibrary()->GetSystemSalt())); |
| 445 } |
| 446 return system_salt_key_.get() != NULL; |
| 447 } |
| 448 |
393 // Call this to start the certificate list initialization process. | 449 // Call this to start the certificate list initialization process. |
394 // Must be called from the UI thread. | 450 // Must be called from the UI thread. |
395 void RequestCertificates() { | 451 void RequestCertificates() { |
396 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 452 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
397 | 453 |
398 certificates_requested_ = true; | 454 certificates_requested_ = true; |
399 | 455 |
400 if (!UserManager::Get()->IsUserLoggedIn()) { | 456 if (!UserManager::Get()->IsUserLoggedIn()) { |
401 // If we are not logged in, we cannot load any certificates. | 457 // If we are not logged in, we cannot load any certificates. |
402 // Set 'loaded' to true for the UI, since we are not waiting on loading. | 458 // Set 'loaded' to true for the UI, since we are not waiting on loading. |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 | 566 |
511 // Cached TPM token name. | 567 // Cached TPM token name. |
512 std::string tpm_token_name_; | 568 std::string tpm_token_name_; |
513 | 569 |
514 // Cached TPM user pin. | 570 // Cached TPM user pin. |
515 std::string tpm_user_pin_; | 571 std::string tpm_user_pin_; |
516 | 572 |
517 // Supplemental user key. | 573 // Supplemental user key. |
518 scoped_ptr<crypto::SymmetricKey> supplemental_user_key_; | 574 scoped_ptr<crypto::SymmetricKey> supplemental_user_key_; |
519 | 575 |
| 576 // A key based on the system salt. Useful for encrypting device-level |
| 577 // data for which we have no additional credentials. |
| 578 scoped_ptr<crypto::SymmetricKey> system_salt_key_; |
| 579 |
520 // Local state. | 580 // Local state. |
521 bool user_logged_in_; | 581 bool user_logged_in_; |
522 bool certificates_requested_; | 582 bool certificates_requested_; |
523 bool certificates_loaded_; | 583 bool certificates_loaded_; |
524 // The key store for the current user has been loaded. This flag is needed to | 584 // The key store for the current user has been loaded. This flag is needed to |
525 // ensure that the key store will not be loaded twice in the policy recovery | 585 // ensure that the key store will not be loaded twice in the policy recovery |
526 // "safe-mode". | 586 // "safe-mode". |
527 bool key_store_loaded_; | 587 bool key_store_loaded_; |
528 | 588 |
529 // Certificates. | 589 // Certificates. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
607 net::X509Certificate* cert = GetCertificateAt(index); | 667 net::X509Certificate* cert = GetCertificateAt(index); |
608 net::X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle(); | 668 net::X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle(); |
609 std::string id = x509_certificate_model::GetPkcs11Id(cert_handle); | 669 std::string id = x509_certificate_model::GetPkcs11Id(cert_handle); |
610 if (id == pkcs11_id) | 670 if (id == pkcs11_id) |
611 return index; | 671 return index; |
612 } | 672 } |
613 return -1; // Not found. | 673 return -1; // Not found. |
614 } | 674 } |
615 | 675 |
616 } // chromeos | 676 } // chromeos |
OLD | NEW |