Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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/observer_list_threadsafe.h" | 9 #include "base/observer_list_threadsafe.h" |
| 10 #include "base/string_number_conversions.h" | |
| 11 #include "base/string_util.h" | |
| 10 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
| 11 #include "chrome/browser/browser_process.h" // g_browser_process | 13 #include "chrome/browser/browser_process.h" // g_browser_process |
| 14 #include "chrome/browser/chromeos/cros/cros_library.h" | |
| 15 #include "chrome/browser/chromeos/cros/cryptohome_library.h" | |
| 12 #include "chrome/browser/chromeos/login/user_manager.h" | 16 #include "chrome/browser/chromeos/login/user_manager.h" |
| 13 #include "chrome/common/net/x509_certificate_model.h" | 17 #include "chrome/common/net/x509_certificate_model.h" |
| 14 #include "content/public/browser/browser_thread.h" | 18 #include "content/public/browser/browser_thread.h" |
| 19 #include "crypto/encryptor.h" | |
| 15 #include "crypto/nss_util.h" | 20 #include "crypto/nss_util.h" |
| 21 #include "crypto/sha2.h" | |
| 22 #include "crypto/symmetric_key.h" | |
| 16 #include "grit/generated_resources.h" | 23 #include "grit/generated_resources.h" |
| 17 #include "net/base/cert_database.h" | 24 #include "net/base/cert_database.h" |
| 18 #include "ui/base/l10n/l10n_util.h" | 25 #include "ui/base/l10n/l10n_util.h" |
| 19 #include "ui/base/l10n/l10n_util_collator.h" | 26 #include "ui/base/l10n/l10n_util_collator.h" |
| 20 #include "unicode/coll.h" // icu::Collator | 27 #include "unicode/coll.h" // icu::Collator |
| 21 | 28 |
| 22 using content::BrowserThread; | 29 using content::BrowserThread; |
| 23 | 30 |
| 24 ////////////////////////////////////////////////////////////////////////////// | 31 ////////////////////////////////////////////////////////////////////////////// |
| 25 | 32 |
| 26 namespace { | 33 namespace { |
| 27 | 34 |
| 28 // Root CA certificates that are built into Chrome use this token name. | 35 // Root CA certificates that are built into Chrome use this token name. |
| 29 const char kRootCertificateTokenName[] = "Builtin Object Token"; | 36 const char kRootCertificateTokenName[] = "Builtin Object Token"; |
| 30 | 37 |
| 31 // Delay between certificate requests while waiting for TPM/PKCS#11 init. | 38 // Delay between certificate requests while waiting for TPM/PKCS#11 init. |
| 32 const int kRequestDelayMs = 500; | 39 const int kRequestDelayMs = 500; |
| 33 | 40 |
| 41 const size_t kKeySize = 16; | |
| 42 | |
| 43 // Decrypts (AES) hex encoded encrypted token given |key| and |salt|. | |
| 44 std::string DecryptTokenWithKey( | |
| 45 crypto::SymmetricKey* key, | |
| 46 const std::string& salt, | |
| 47 const std::string& encrypted_token_hex) { | |
| 48 std::vector<uint8> encrypted_token_bytes; | |
| 49 if (!base::HexStringToBytes(encrypted_token_hex, &encrypted_token_bytes)) | |
| 50 return std::string(); | |
| 51 | |
| 52 std::string encrypted_token( | |
| 53 reinterpret_cast<char*>(encrypted_token_bytes.data()), | |
| 54 encrypted_token_bytes.size()); | |
| 55 crypto::Encryptor encryptor; | |
| 56 if (!encryptor.Init(key, crypto::Encryptor::CTR, std::string())) | |
| 57 return std::string(); | |
| 58 | |
| 59 std::string nonce = salt.substr(0, kKeySize); | |
| 60 std::string token; | |
| 61 CHECK(encryptor.SetCounter(nonce)); | |
| 62 if (!encryptor.Decrypt(encrypted_token, &token)) | |
| 63 return std::string(); | |
| 64 return token; | |
| 65 } | |
| 66 | |
| 34 string16 GetDisplayString(net::X509Certificate* cert, bool hardware_backed) { | 67 string16 GetDisplayString(net::X509Certificate* cert, bool hardware_backed) { |
| 35 std::string org; | 68 std::string org; |
| 36 if (!cert->subject().organization_names.empty()) | 69 if (!cert->subject().organization_names.empty()) |
| 37 org = cert->subject().organization_names[0]; | 70 org = cert->subject().organization_names[0]; |
| 38 if (org.empty()) | 71 if (org.empty()) |
| 39 org = cert->subject().GetDisplayName(); | 72 org = cert->subject().GetDisplayName(); |
| 40 string16 issued_by = UTF8ToUTF16( | 73 string16 issued_by = UTF8ToUTF16( |
| 41 x509_certificate_model::GetIssuerCommonName(cert->os_cert_handle(), | 74 x509_certificate_model::GetIssuerCommonName(cert->os_cert_handle(), |
| 42 org)); // alternative text | 75 org)); // alternative text |
| 43 string16 issued_to = UTF8ToUTF16( | 76 string16 issued_to = UTF8ToUTF16( |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 | 126 |
| 94 // CertLibrary implementation. | 127 // CertLibrary implementation. |
| 95 virtual void RequestCertificates() OVERRIDE { | 128 virtual void RequestCertificates() OVERRIDE { |
| 96 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 97 | 130 |
| 98 if (!UserManager::Get()->user_is_logged_in()) { | 131 if (!UserManager::Get()->user_is_logged_in()) { |
| 99 // If we are not logged in, we cannot load any certificates. | 132 // If we are not logged in, we cannot load any certificates. |
| 100 // Set 'loaded' to true for the UI, since we are not waiting on loading. | 133 // Set 'loaded' to true for the UI, since we are not waiting on loading. |
| 101 LOG(WARNING) << "Requesting certificates before login."; | 134 LOG(WARNING) << "Requesting certificates before login."; |
| 102 certificates_loaded_ = true; | 135 certificates_loaded_ = true; |
| 103 return; | 136 return; |
|
Nikita (slow)
2011/12/01 14:34:13
Perhaps add supplemental_user_key_.reset(NULL); he
zel
2011/12/02 02:35:23
Done.
| |
| 104 } | 137 } |
| 105 | 138 |
| 106 if (!user_logged_in_) { | 139 if (!user_logged_in_) { |
| 107 user_logged_in_ = true; | 140 user_logged_in_ = true; |
| 108 certificates_loaded_ = false; | 141 certificates_loaded_ = false; |
| 142 supplemental_user_key_.reset(NULL); | |
| 109 } | 143 } |
| 110 | 144 |
| 111 VLOG(1) << "Requesting Certificates."; | 145 VLOG(1) << "Requesting Certificates."; |
| 112 | 146 |
| 113 // Need TPM token name to filter user certificates. | 147 // Need TPM token name to filter user certificates. |
| 114 // TODO(stevenjb): crypto::EnsureTPMTokenReady() may block if init has | 148 // TODO(stevenjb): crypto::EnsureTPMTokenReady() may block if init has |
| 115 // not succeeded. It is not clear whether or not TPM / PKCS#11 init can | 149 // not succeeded. It is not clear whether or not TPM / PKCS#11 init can |
| 116 // be done safely on a non blocking thread. Blocking time is low. | 150 // be done safely on a non blocking thread. Blocking time is low. |
| 117 if (crypto::EnsureTPMTokenReady()) { | 151 if (crypto::EnsureTPMTokenReady()) { |
| 118 std::string unused_pin; | 152 std::string unused_pin; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 172 virtual const CertList& GetServerCertificates() const OVERRIDE { | 206 virtual const CertList& GetServerCertificates() const OVERRIDE { |
| 173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 174 return server_certs_; | 208 return server_certs_; |
| 175 } | 209 } |
| 176 | 210 |
| 177 virtual const CertList& GetCACertificates() const OVERRIDE { | 211 virtual const CertList& GetCACertificates() const OVERRIDE { |
| 178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 179 return server_ca_certs_; | 213 return server_ca_certs_; |
| 180 } | 214 } |
| 181 | 215 |
| 182 virtual crypto::SymmetricKey* GetSupplementalUserKey() const { | 216 virtual std::string EncryptToken(const std::string& token) OVERRIDE { |
| 183 return crypto::GetSupplementalUserKey(); | 217 if (!LoadSupplementalUserKey()) |
| 218 return std::string(); | |
| 219 crypto::Encryptor encryptor; | |
| 220 if (!encryptor.Init(supplemental_user_key_.get(), crypto::Encryptor::CTR, | |
| 221 std::string())) | |
| 222 return std::string(); | |
| 223 std::string salt = | |
| 224 CrosLibrary::Get()->GetCryptohomeLibrary()->GetSystemSalt(); | |
| 225 std::string nonce = salt.substr(0, kKeySize); | |
| 226 std::string encoded_token; | |
| 227 CHECK(encryptor.SetCounter(nonce)); | |
| 228 if (!encryptor.Encrypt(token, &encoded_token)) | |
| 229 return std::string(); | |
| 230 | |
| 231 return StringToLowerASCII(base::HexEncode( | |
| 232 reinterpret_cast<const void*>(encoded_token.data()), | |
| 233 encoded_token.size())); | |
| 234 } | |
| 235 | |
| 236 virtual std::string DecryptToken( | |
| 237 const std::string& encrypted_token_hex) OVERRIDE { | |
| 238 if (!LoadSupplementalUserKey()) | |
| 239 return std::string(); | |
| 240 return DecryptTokenWithKey(supplemental_user_key_.get(), | |
| 241 CrosLibrary::Get()->GetCryptohomeLibrary()->GetSystemSalt(), | |
| 242 encrypted_token_hex); | |
| 184 } | 243 } |
| 185 | 244 |
| 186 // net::CertDatabase::Observer implementation. Observer added on UI thread. | 245 // net::CertDatabase::Observer implementation. Observer added on UI thread. |
| 187 virtual void OnCertTrustChanged(const net::X509Certificate* cert) OVERRIDE { | 246 virtual void OnCertTrustChanged(const net::X509Certificate* cert) OVERRIDE { |
| 188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 247 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 189 } | 248 } |
| 190 | 249 |
| 191 virtual void OnUserCertAdded(const net::X509Certificate* cert) OVERRIDE { | 250 virtual void OnUserCertAdded(const net::X509Certificate* cert) OVERRIDE { |
| 192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 193 VLOG(1) << "Certificate Added."; | 252 VLOG(1) << "Certificate Added."; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 312 | 371 |
| 313 // Set loaded state and notify observers. | 372 // Set loaded state and notify observers. |
| 314 if (!certificates_loaded_) { | 373 if (!certificates_loaded_) { |
| 315 certificates_loaded_ = true; | 374 certificates_loaded_ = true; |
| 316 NotifyCertificatesLoaded(true); | 375 NotifyCertificatesLoaded(true); |
| 317 } else { | 376 } else { |
| 318 NotifyCertificatesLoaded(false); | 377 NotifyCertificatesLoaded(false); |
| 319 } | 378 } |
| 320 } | 379 } |
| 321 | 380 |
| 381 bool LoadSupplementalUserKey() { | |
| 382 if (!user_logged_in_) { | |
| 383 // If we are not logged in, we cannot load any certificates. | |
| 384 // Set 'loaded' to true for the UI, since we are not waiting on loading. | |
| 385 LOG(WARNING) << "Requesting supplemental use key before login."; | |
| 386 return false; | |
| 387 } | |
| 388 if (!supplemental_user_key_.get()) { | |
| 389 supplemental_user_key_.reset(crypto::GetSupplementalUserKey()); | |
| 390 } | |
| 391 return supplemental_user_key_.get() != NULL; | |
| 392 } | |
| 393 | |
| 322 // Observers. | 394 // Observers. |
| 323 const scoped_refptr<CertLibraryObserverList> observer_list_; | 395 const scoped_refptr<CertLibraryObserverList> observer_list_; |
| 324 | 396 |
| 325 // Active request task for re-requests while waiting for TPM init. | 397 // Active request task for re-requests while waiting for TPM init. |
| 326 base::Closure request_task_; | 398 base::Closure request_task_; |
| 327 | 399 |
| 328 // Cached TPM token name. | 400 // Cached TPM token name. |
| 329 std::string tpm_token_name_; | 401 std::string tpm_token_name_; |
| 330 | 402 |
| 403 // Supplemental user key. | |
| 404 scoped_ptr<crypto::SymmetricKey> supplemental_user_key_; | |
| 405 | |
| 331 // Local state. | 406 // Local state. |
| 332 bool user_logged_in_; | 407 bool user_logged_in_; |
| 333 bool certificates_loaded_; | 408 bool certificates_loaded_; |
| 334 | 409 |
| 335 // Certificates. | 410 // Certificates. |
| 336 CertList certs_; | 411 CertList certs_; |
| 337 CertList user_certs_; | 412 CertList user_certs_; |
| 338 CertList server_certs_; | 413 CertList server_certs_; |
| 339 CertList server_ca_certs_; | 414 CertList server_ca_certs_; |
| 340 | 415 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 net::X509Certificate* cert = GetCertificateAt(index); | 478 net::X509Certificate* cert = GetCertificateAt(index); |
| 404 net::X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle(); | 479 net::X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle(); |
| 405 std::string id = x509_certificate_model::GetPkcs11Id(cert_handle); | 480 std::string id = x509_certificate_model::GetPkcs11Id(cert_handle); |
| 406 if (id == pkcs11_id) | 481 if (id == pkcs11_id) |
| 407 return index; | 482 return index; |
| 408 } | 483 } |
| 409 return -1; // Not found. | 484 return -1; // Not found. |
| 410 } | 485 } |
| 411 | 486 |
| 412 } // chromeos | 487 } // chromeos |
| OLD | NEW |