Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / chromeos / options / cert_library.cc
blob8c9ac18a9561b38ad70d9c12b469ea89ed4090f0
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/options/cert_library.h"
7 #include <algorithm>
9 #include "base/command_line.h"
10 #include "base/i18n/string_compare.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/observer_list_threadsafe.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "chrome/browser/browser_process.h" // g_browser_process
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/common/net/x509_certificate_model.h"
19 #include "chromeos/dbus/cryptohome_client.h"
20 #include "chromeos/dbus/dbus_thread_manager.h"
21 #include "chromeos/login/login_state.h"
22 #include "chromeos/network/onc/onc_utils.h"
23 #include "content/public/browser/browser_thread.h"
24 #include "crypto/nss_util.h"
25 #include "grit/generated_resources.h"
26 #include "net/cert/cert_database.h"
27 #include "net/cert/nss_cert_database.h"
28 #include "third_party/icu/source/i18n/unicode/coll.h" // icu::Collator
29 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/base/l10n/l10n_util_collator.h"
32 namespace chromeos {
34 namespace {
36 // Root CA certificates that are built into Chrome use this token name.
37 const char kRootCertificateTokenName[] = "Builtin Object Token";
39 base::string16 GetDisplayString(net::X509Certificate* cert, bool hardware_backed) {
40 std::string org;
41 if (!cert->subject().organization_names.empty())
42 org = cert->subject().organization_names[0];
43 if (org.empty())
44 org = cert->subject().GetDisplayName();
45 base::string16 issued_by = base::UTF8ToUTF16(
46 x509_certificate_model::GetIssuerCommonName(cert->os_cert_handle(),
47 org)); // alternative text
48 base::string16 issued_to = base::UTF8ToUTF16(
49 x509_certificate_model::GetCertNameOrNickname(cert->os_cert_handle()));
51 if (hardware_backed) {
52 return l10n_util::GetStringFUTF16(
53 IDS_CERT_MANAGER_HARDWARE_BACKED_KEY_FORMAT_LONG,
54 issued_by,
55 issued_to,
56 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_HARDWARE_BACKED));
57 } else {
58 return l10n_util::GetStringFUTF16(
59 IDS_CERT_MANAGER_KEY_FORMAT_LONG,
60 issued_by,
61 issued_to);
65 std::string CertToPEM(const net::X509Certificate& cert) {
66 std::string pem_encoded_cert;
67 if (!net::X509Certificate::GetPEMEncoded(cert.os_cert_handle(),
68 &pem_encoded_cert)) {
69 LOG(ERROR) << "Couldn't PEM-encode certificate";
70 return std::string();
72 return pem_encoded_cert;
75 } // namespace
77 class CertNameComparator {
78 public:
79 explicit CertNameComparator(icu::Collator* collator)
80 : collator_(collator) {
83 bool operator()(const scoped_refptr<net::X509Certificate>& lhs,
84 const scoped_refptr<net::X509Certificate>& rhs) const {
85 base::string16 lhs_name = GetDisplayString(lhs.get(), false);
86 base::string16 rhs_name = GetDisplayString(rhs.get(), false);
87 if (collator_ == NULL)
88 return lhs_name < rhs_name;
89 return base::i18n::CompareString16WithCollator(
90 collator_, lhs_name, rhs_name) == UCOL_LESS;
93 private:
94 icu::Collator* collator_;
97 static CertLibrary* g_cert_library = NULL;
99 // static
100 void CertLibrary::Initialize() {
101 CHECK(!g_cert_library);
102 g_cert_library = new CertLibrary();
105 // static
106 void CertLibrary::Shutdown() {
107 CHECK(g_cert_library);
108 delete g_cert_library;
109 g_cert_library = NULL;
112 // static
113 CertLibrary* CertLibrary::Get() {
114 CHECK(g_cert_library) << "CertLibrary::Get() called before Initialize()";
115 return g_cert_library;
118 // static
119 bool CertLibrary::IsInitialized() {
120 return g_cert_library;
123 CertLibrary::CertLibrary() {
124 CertLoader::Get()->AddObserver(this);
127 CertLibrary::~CertLibrary() {
128 CertLoader::Get()->RemoveObserver(this);
131 void CertLibrary::AddObserver(CertLibrary::Observer* observer) {
132 observer_list_.AddObserver(observer);
135 void CertLibrary::RemoveObserver(CertLibrary::Observer* observer) {
136 observer_list_.RemoveObserver(observer);
139 bool CertLibrary::CertificatesLoading() const {
140 return CertLoader::Get()->CertificatesLoading();
143 bool CertLibrary::CertificatesLoaded() const {
144 return CertLoader::Get()->certificates_loaded();
147 bool CertLibrary::IsHardwareBacked() const {
148 return CertLoader::Get()->IsHardwareBacked();
151 int CertLibrary::NumCertificates(CertType type) const {
152 const net::CertificateList& cert_list = GetCertificateListForType(type);
153 return static_cast<int>(cert_list.size());
156 base::string16 CertLibrary::GetCertDisplayStringAt(CertType type,
157 int index) const {
158 net::X509Certificate* cert = GetCertificateAt(type, index);
159 bool hardware_backed = IsCertHardwareBackedAt(type, index);
160 return GetDisplayString(cert, hardware_backed);
163 std::string CertLibrary::GetCertPEMAt(CertType type, int index) const {
164 return CertToPEM(*GetCertificateAt(type, index));
167 std::string CertLibrary::GetCertPkcs11IdAt(CertType type, int index) const {
168 net::X509Certificate* cert = GetCertificateAt(type, index);
169 return x509_certificate_model::GetPkcs11Id(cert->os_cert_handle());
172 bool CertLibrary::IsCertHardwareBackedAt(CertType type, int index) const {
173 if (!CertLoader::Get()->IsHardwareBacked())
174 return false;
175 net::X509Certificate* cert = GetCertificateAt(type, index);
176 std::string cert_token_name =
177 x509_certificate_model::GetTokenName(cert->os_cert_handle());
178 return cert_token_name ==
179 CertLoader::Get()->tpm_token_name();
182 int CertLibrary::GetCertIndexByPEM(CertType type,
183 const std::string& pem_encoded) const {
184 int num_certs = NumCertificates(type);
185 for (int index = 0; index < num_certs; ++index) {
186 net::X509Certificate* cert = GetCertificateAt(type, index);
187 if (CertToPEM(*cert) != pem_encoded)
188 continue;
189 return index;
191 return -1;
194 int CertLibrary::GetCertIndexByPkcs11Id(CertType type,
195 const std::string& pkcs11_id) const {
196 int num_certs = NumCertificates(type);
197 for (int index = 0; index < num_certs; ++index) {
198 net::X509Certificate* cert = GetCertificateAt(type, index);
199 net::X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle();
200 std::string id = x509_certificate_model::GetPkcs11Id(cert_handle);
201 if (id == pkcs11_id)
202 return index;
204 return -1; // Not found.
207 void CertLibrary::OnCertificatesLoaded(const net::CertificateList& cert_list,
208 bool initial_load) {
209 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
210 VLOG(1) << "CertLibrary::OnCertificatesLoaded: " << cert_list.size();
211 certs_.clear();
212 user_certs_.clear();
213 server_certs_.clear();
214 server_ca_certs_.clear();
216 // Add certificates to the appropriate list.
217 for (net::CertificateList::const_iterator iter = cert_list.begin();
218 iter != cert_list.end(); ++iter) {
219 certs_.push_back(iter->get());
220 net::X509Certificate::OSCertHandle cert_handle =
221 iter->get()->os_cert_handle();
222 net::CertType type = x509_certificate_model::GetType(cert_handle);
223 switch (type) {
224 case net::USER_CERT:
225 user_certs_.push_back(iter->get());
226 break;
227 case net::SERVER_CERT:
228 server_certs_.push_back(iter->get());
229 break;
230 case net::CA_CERT: {
231 // Exclude root CA certificates that are built into Chrome.
232 std::string token_name =
233 x509_certificate_model::GetTokenName(cert_handle);
234 if (token_name != kRootCertificateTokenName)
235 server_ca_certs_.push_back(iter->get());
236 break;
238 default:
239 break;
243 // Perform locale-sensitive sorting by certificate name.
244 UErrorCode error = U_ZERO_ERROR;
245 scoped_ptr<icu::Collator> collator(icu::Collator::createInstance(
246 icu::Locale(g_browser_process->GetApplicationLocale().c_str()), error));
247 if (U_FAILURE(error))
248 collator.reset();
249 CertNameComparator cert_name_comparator(collator.get());
250 std::sort(certs_.begin(), certs_.end(), cert_name_comparator);
251 std::sort(user_certs_.begin(), user_certs_.end(), cert_name_comparator);
252 std::sort(server_certs_.begin(), server_certs_.end(), cert_name_comparator);
253 std::sort(server_ca_certs_.begin(), server_ca_certs_.end(),
254 cert_name_comparator);
256 VLOG(1) << "certs_: " << certs_.size();
257 VLOG(1) << "user_certs_: " << user_certs_.size();
258 VLOG(1) << "server_certs_: " << server_certs_.size();
259 VLOG(1) << "server_ca_certs_: " << server_ca_certs_.size();
261 FOR_EACH_OBSERVER(CertLibrary::Observer, observer_list_,
262 OnCertificatesLoaded(initial_load));
265 net::X509Certificate* CertLibrary::GetCertificateAt(CertType type,
266 int index) const {
267 const net::CertificateList& cert_list = GetCertificateListForType(type);
268 DCHECK_GE(index, 0);
269 DCHECK_LT(index, static_cast<int>(cert_list.size()));
270 return cert_list[index].get();
273 const net::CertificateList& CertLibrary::GetCertificateListForType(
274 CertType type) const {
275 if (type == CERT_TYPE_USER)
276 return user_certs_;
277 if (type == CERT_TYPE_SERVER)
278 return server_certs_;
279 if (type == CERT_TYPE_SERVER_CA)
280 return server_ca_certs_;
281 DCHECK(type == CERT_TYPE_DEFAULT);
282 return certs_;
285 } // namespace chromeos