nss_cert_database_chromeos.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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.
  4. #include "net/cert/nss_cert_database_chromeos.h"
  5. #include <cert.h>
  6. #include <pk11pub.h>
  7. #include <algorithm>
  8. #include <memory>
  9. #include <utility>
  10. #include "base/bind.h"
  11. #include "base/callback.h"
  12. #include "base/containers/cxx20_erase.h"
  13. #include "base/location.h"
  14. #include "base/task/thread_pool.h"
  15. #include "base/threading/scoped_blocking_call.h"
  16. #include "net/cert/nss_cert_database.h"
  17. namespace net {
  18. NSSCertDatabaseChromeOS::NSSCertDatabaseChromeOS(
  19. crypto::ScopedPK11Slot public_slot,
  20. crypto::ScopedPK11Slot private_slot)
  21. : NSSCertDatabase(std::move(public_slot), std::move(private_slot)) {
  22. // By default, don't use a system slot. Only if explicitly set by
  23. // SetSystemSlot, the system slot will be used.
  24. profile_filter_.Init(GetPublicSlot(),
  25. GetPrivateSlot(),
  26. crypto::ScopedPK11Slot() /* no system slot */);
  27. }
  28. NSSCertDatabaseChromeOS::~NSSCertDatabaseChromeOS() = default;
  29. void NSSCertDatabaseChromeOS::SetSystemSlot(
  30. crypto::ScopedPK11Slot system_slot) {
  31. system_slot_ = std::move(system_slot);
  32. profile_filter_.Init(GetPublicSlot(), GetPrivateSlot(), GetSystemSlot());
  33. }
  34. void NSSCertDatabaseChromeOS::ListCerts(
  35. NSSCertDatabase::ListCertsCallback callback) {
  36. base::ThreadPool::PostTaskAndReplyWithResult(
  37. FROM_HERE,
  38. {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
  39. base::BindOnce(&NSSCertDatabaseChromeOS::ListCertsImpl, profile_filter_),
  40. std::move(callback));
  41. }
  42. void NSSCertDatabaseChromeOS::ListCertsInfo(ListCertsInfoCallback callback) {
  43. base::ThreadPool::PostTaskAndReplyWithResult(
  44. FROM_HERE,
  45. {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
  46. base::BindOnce(&NSSCertDatabaseChromeOS::ListCertsInfoImpl,
  47. profile_filter_, /*slot=*/GetSystemSlot(),
  48. /*add_certs_info=*/true),
  49. std::move(callback));
  50. }
  51. crypto::ScopedPK11Slot NSSCertDatabaseChromeOS::GetSystemSlot() const {
  52. if (system_slot_)
  53. return crypto::ScopedPK11Slot(PK11_ReferenceSlot(system_slot_.get()));
  54. return crypto::ScopedPK11Slot();
  55. }
  56. void NSSCertDatabaseChromeOS::ListModules(
  57. std::vector<crypto::ScopedPK11Slot>* modules,
  58. bool need_rw) const {
  59. NSSCertDatabase::ListModules(modules, need_rw);
  60. const NSSProfileFilterChromeOS& profile_filter = profile_filter_;
  61. base::EraseIf(*modules, [&profile_filter](crypto::ScopedPK11Slot& module) {
  62. return !profile_filter.IsModuleAllowed(module.get());
  63. });
  64. }
  65. bool NSSCertDatabaseChromeOS::SetCertTrust(CERTCertificate* cert,
  66. CertType type,
  67. TrustBits trust_bits) {
  68. crypto::ScopedPK11Slot public_slot = GetPublicSlot();
  69. // Ensure that the certificate exists on the public slot so NSS puts the trust
  70. // settings there (https://crbug.com/1132030).
  71. if (public_slot == GetSystemSlot()) {
  72. // Never attempt to store trust setting on the system slot.
  73. return false;
  74. }
  75. if (!IsCertificateOnSlot(cert, public_slot.get())) {
  76. // Copy the certificate to the public slot.
  77. SECStatus srv =
  78. PK11_ImportCert(public_slot.get(), cert, CK_INVALID_HANDLE,
  79. cert->nickname, PR_FALSE /* includeTrust (unused) */);
  80. if (srv != SECSuccess) {
  81. LOG(ERROR) << "Failed to import certificate onto public slot.";
  82. return false;
  83. }
  84. }
  85. return NSSCertDatabase::SetCertTrust(cert, type, trust_bits);
  86. }
  87. // static
  88. ScopedCERTCertificateList NSSCertDatabaseChromeOS::ListCertsImpl(
  89. const NSSProfileFilterChromeOS& profile_filter) {
  90. CertInfoList certs_info = ListCertsInfoImpl(
  91. profile_filter, crypto::ScopedPK11Slot(), /*add_certs_info=*/false);
  92. return ExtractCertificates(std::move(certs_info));
  93. }
  94. // static
  95. NSSCertDatabase::CertInfoList NSSCertDatabaseChromeOS::ListCertsInfoImpl(
  96. const NSSProfileFilterChromeOS& profile_filter,
  97. crypto::ScopedPK11Slot system_slot,
  98. bool add_certs_info) {
  99. // This method may acquire the NSS lock or reenter this code via extension
  100. // hooks (such as smart card UI). To ensure threads are not starved or
  101. // deadlocked, the base::ScopedBlockingCall below increments the thread pool
  102. // capacity if this method takes too much time to run.
  103. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  104. base::BlockingType::MAY_BLOCK);
  105. CertInfoList certs_info(NSSCertDatabase::ListCertsInfoImpl(
  106. crypto::ScopedPK11Slot(), add_certs_info));
  107. // Filter certificate information according to user profile.
  108. base::EraseIf(certs_info, [&profile_filter](CertInfo& cert_info) {
  109. return !profile_filter.IsCertAllowed(cert_info.cert.get());
  110. });
  111. if (add_certs_info) {
  112. // Add Chrome OS specific information.
  113. for (auto& cert_info : certs_info) {
  114. cert_info.device_wide =
  115. IsCertificateOnSlot(cert_info.cert.get(), system_slot.get());
  116. cert_info.hardware_backed = IsHardwareBacked(cert_info.cert.get());
  117. }
  118. }
  119. return certs_info;
  120. }
  121. } // namespace net