File: nss_cert_database_chromeos.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (149 lines) | stat: -rw-r--r-- 5,401 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/cert/nss_cert_database_chromeos.h"

#include <cert.h>
#include <pk11pub.h>

#include <algorithm>
#include <memory>
#include <utility>
#include <vector>

#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/location.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "net/cert/nss_cert_database.h"

namespace net {

NSSCertDatabaseChromeOS::NSSCertDatabaseChromeOS(
    crypto::ScopedPK11Slot public_slot,
    crypto::ScopedPK11Slot private_slot)
    : NSSCertDatabase(std::move(public_slot), std::move(private_slot)) {
  // By default, don't use a system slot. Only if explicitly set by
  // SetSystemSlot, the system slot will be used.
  profile_filter_.Init(GetPublicSlot(),
                       GetPrivateSlot(),
                       crypto::ScopedPK11Slot() /* no system slot */);
}

NSSCertDatabaseChromeOS::~NSSCertDatabaseChromeOS() = default;

void NSSCertDatabaseChromeOS::SetSystemSlot(
    crypto::ScopedPK11Slot system_slot) {
  system_slot_ = std::move(system_slot);
  profile_filter_.Init(GetPublicSlot(), GetPrivateSlot(), GetSystemSlot());
}

void NSSCertDatabaseChromeOS::ListCerts(
    NSSCertDatabase::ListCertsCallback callback) {
  base::ThreadPool::PostTaskAndReplyWithResult(
      FROM_HERE,
      {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
      base::BindOnce(&NSSCertDatabaseChromeOS::ListCertsImpl, profile_filter_),
      std::move(callback));
}

void NSSCertDatabaseChromeOS::ListCertsInfo(
    ListCertsInfoCallback callback,
    NSSRootsHandling nss_roots_handling) {
  base::ThreadPool::PostTaskAndReplyWithResult(
      FROM_HERE,
      {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
      base::BindOnce(&NSSCertDatabaseChromeOS::ListCertsInfoImpl,
                     profile_filter_, /*slot=*/GetSystemSlot(),
                     /*add_certs_info=*/true, nss_roots_handling),
      std::move(callback));
}

crypto::ScopedPK11Slot NSSCertDatabaseChromeOS::GetSystemSlot() const {
  if (system_slot_)
    return crypto::ScopedPK11Slot(PK11_ReferenceSlot(system_slot_.get()));
  return crypto::ScopedPK11Slot();
}

void NSSCertDatabaseChromeOS::ListModules(
    std::vector<crypto::ScopedPK11Slot>* modules,
    bool need_rw) const {
  NSSCertDatabase::ListModules(modules, need_rw);

  const NSSProfileFilterChromeOS& profile_filter = profile_filter_;
  std::erase_if(*modules, [&profile_filter](crypto::ScopedPK11Slot& module) {
    return !profile_filter.IsModuleAllowed(module.get());
  });
}

bool NSSCertDatabaseChromeOS::SetCertTrust(CERTCertificate* cert,
                                           CertType type,
                                           TrustBits trust_bits) {
  crypto::ScopedPK11Slot public_slot = GetPublicSlot();

  // Ensure that the certificate exists on the public slot so NSS puts the trust
  // settings there (https://crbug.com/1132030).
  if (public_slot == GetSystemSlot()) {
    // Never attempt to store trust setting on the system slot.
    return false;
  }

  if (!IsCertificateOnSlot(cert, public_slot.get())) {
    // Copy the certificate to the public slot.
    SECStatus srv =
        PK11_ImportCert(public_slot.get(), cert, CK_INVALID_HANDLE,
                        cert->nickname, PR_FALSE /* includeTrust (unused) */);
    if (srv != SECSuccess) {
      LOG(ERROR) << "Failed to import certificate onto public slot.";
      return false;
    }
  }
  return NSSCertDatabase::SetCertTrust(cert, type, trust_bits);
}

// static
ScopedCERTCertificateList NSSCertDatabaseChromeOS::ListCertsImpl(
    const NSSProfileFilterChromeOS& profile_filter) {
  CertInfoList certs_info =
      ListCertsInfoImpl(profile_filter, crypto::ScopedPK11Slot(),
                        /*add_certs_info=*/false, NSSRootsHandling::kInclude);

  return ExtractCertificates(std::move(certs_info));
}

// static
NSSCertDatabase::CertInfoList NSSCertDatabaseChromeOS::ListCertsInfoImpl(
    const NSSProfileFilterChromeOS& profile_filter,
    crypto::ScopedPK11Slot system_slot,
    bool add_certs_info,
    NSSRootsHandling nss_roots_handling) {
  // This method may acquire the NSS lock or reenter this code via extension
  // hooks (such as smart card UI). To ensure threads are not starved or
  // deadlocked, the base::ScopedBlockingCall below increments the thread pool
  // capacity if this method takes too much time to run.
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);

  CertInfoList certs_info(NSSCertDatabase::ListCertsInfoImpl(
      crypto::ScopedPK11Slot(), add_certs_info, nss_roots_handling));

  // Filter certificate information according to user profile.
  std::erase_if(certs_info, [&profile_filter](CertInfo& cert_info) {
    return !profile_filter.IsCertAllowed(cert_info.cert.get());
  });

  if (add_certs_info) {
    // Add Chrome OS specific information.
    for (auto& cert_info : certs_info) {
      cert_info.device_wide =
          IsCertificateOnSlot(cert_info.cert.get(), system_slot.get());
      cert_info.hardware_backed = IsHardwareBacked(cert_info.cert.get());
    }
  }

  return certs_info;
}

}  // namespace net