[go: nahoru, domu]

blob: 4b176ae608dc179118e94ca352a9b37ef71c6647 [file] [log] [blame]
Avi Drissman201a9a832022-09-13 19:39:251// Copyright 2020 The Chromium Authors
Michael Ershov1c50ac952020-12-02 21:01:172// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "crypto/chaps_support.h"
6
7#include <dlfcn.h>
Michael Ershovd9a627e2021-11-03 13:55:278#include <secmod.h>
Michael Ershov1c50ac952020-12-02 21:01:179#include <secmodt.h>
10
11#include "base/logging.h"
12#include "base/threading/scoped_blocking_call.h"
Michael Ershovd9a627e2021-11-03 13:55:2713#include "crypto/scoped_nss_types.h"
Michael Ershov1c50ac952020-12-02 21:01:1714#include "nss_util_internal.h"
15
16namespace crypto {
17
18namespace {
19
20// Constants for loading the Chrome OS TPM-backed PKCS #11 library.
21const char kChapsModuleName[] = "Chaps";
22const char kChapsPath[] = "libchaps.so";
23
24class ScopedChapsLoadFixup {
25 public:
26 ScopedChapsLoadFixup();
27 ~ScopedChapsLoadFixup();
28
29 private:
30#if defined(COMPONENT_BUILD)
31 void* chaps_handle_;
32#endif
33};
34
35#if defined(COMPONENT_BUILD)
36
37ScopedChapsLoadFixup::ScopedChapsLoadFixup() {
38 // HACK: libchaps links the system protobuf and there are symbol conflicts
39 // with the bundled copy. Load chaps with RTLD_DEEPBIND to workaround.
40 chaps_handle_ = dlopen(kChapsPath, RTLD_LOCAL | RTLD_NOW | RTLD_DEEPBIND);
41}
42
43ScopedChapsLoadFixup::~ScopedChapsLoadFixup() {
44 // LoadNSSModule() will have taken a 2nd reference.
45 if (chaps_handle_)
46 dlclose(chaps_handle_);
47}
48
49#else
50
51ScopedChapsLoadFixup::ScopedChapsLoadFixup() = default;
52ScopedChapsLoadFixup::~ScopedChapsLoadFixup() = default;
53
54#endif // defined(COMPONENT_BUILD)
55
56} // namespace
57
58SECMODModule* LoadChaps() {
59 // NSS functions may reenter //net via extension hooks. If the reentered
60 // code needs to synchronously wait for a task to run but the thread pool in
61 // which that task must run doesn't have enough threads to schedule it, a
62 // deadlock occurs. To prevent that, the base::ScopedBlockingCall below
63 // increments the thread pool capacity for the duration of the TPM
64 // initialization.
65 base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
66 base::BlockingType::WILL_BLOCK);
67
68 ScopedChapsLoadFixup chaps_loader;
69
70 DVLOG(3) << "Loading chaps...";
71 return LoadNSSModule(
72 kChapsModuleName, kChapsPath,
73 // For more details on these parameters, see:
74 // https://developer.mozilla.org/en/PKCS11_Module_Specs
75 // slotFlags=[PublicCerts] -- Certificates and public keys can be
76 // read from this slot without requiring a call to C_Login.
77 // askpw=only -- Only authenticate to the token when necessary.
78 "NSS=\"slotParams=(0={slotFlags=[PublicCerts] askpw=only})\"");
79}
80
Michael Ershovd9a627e2021-11-03 13:55:2781ScopedPK11Slot GetChapsSlot(SECMODModule* chaps_module, CK_SLOT_ID slot_id) {
82 DCHECK(chaps_module);
83
84 // NSS functions may reenter //net via extension hooks. If the reentered
85 // code needs to synchronously wait for a task to run but the thread pool in
86 // which that task must run doesn't have enough threads to schedule it, a
87 // deadlock occurs. To prevent that, the base::ScopedBlockingCall below
88 // increments the thread pool capacity for the duration of the TPM
89 // initialization.
90 base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
91 base::BlockingType::WILL_BLOCK);
92
93 DVLOG(3) << "Poking chaps module.";
94 SECStatus rv = SECMOD_UpdateSlotList(chaps_module);
95 if (rv != SECSuccess)
96 LOG(ERROR) << "SECMOD_UpdateSlotList failed: " << PORT_GetError();
97
98 ScopedPK11Slot slot =
99 ScopedPK11Slot(SECMOD_LookupSlot(chaps_module->moduleID, slot_id));
100 if (!slot)
101 LOG(ERROR) << "TPM slot " << slot_id << " not found.";
102 return slot;
103}
104
Michael Ershov1c50ac952020-12-02 21:01:17105bool IsSlotProvidedByChaps(PK11SlotInfo* slot) {
106 if (!slot)
107 return false;
108
109 SECMODModule* pk11_module = PK11_GetModule(slot);
110 return pk11_module && base::StringPiece(pk11_module->commonName) ==
111 base::StringPiece(kChapsModuleName);
112}
113
114} // namespace crypto