Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "PKCS11.h"
8 :
9 : #include "ScopedNSSTypes.h"
10 : #include "mozilla/Telemetry.h"
11 : #include "nsCRTGlue.h"
12 : #include "nsNSSComponent.h"
13 : #include "nsNativeCharsetUtils.h"
14 : #include "nsServiceManagerUtils.h"
15 :
16 : namespace mozilla { namespace psm {
17 :
18 0 : NS_INTERFACE_MAP_BEGIN(PKCS11)
19 0 : NS_INTERFACE_MAP_ENTRY(nsIPKCS11)
20 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
21 0 : NS_INTERFACE_MAP_END
22 :
23 0 : NS_IMPL_ADDREF(PKCS11)
24 0 : NS_IMPL_RELEASE(PKCS11)
25 :
26 0 : PKCS11::PKCS11()
27 : {
28 0 : }
29 :
30 0 : PKCS11::~PKCS11()
31 : {
32 0 : nsNSSShutDownPreventionLock locker;
33 0 : if (isAlreadyShutDown()) {
34 0 : return;
35 : }
36 0 : shutdown(ShutdownCalledFrom::Object);
37 0 : }
38 :
39 : // Delete a PKCS11 module from the user's profile.
40 : NS_IMETHODIMP
41 0 : PKCS11::DeleteModule(const nsAString& aModuleName)
42 : {
43 0 : nsNSSShutDownPreventionLock locker;
44 0 : if (isAlreadyShutDown()) {
45 0 : return NS_ERROR_NOT_AVAILABLE;
46 : }
47 :
48 0 : if (aModuleName.IsEmpty()) {
49 0 : return NS_ERROR_INVALID_ARG;
50 : }
51 :
52 0 : NS_ConvertUTF16toUTF8 moduleName(aModuleName);
53 : // Introduce additional scope for module so all references to it are released
54 : // before we call SECMOD_DeleteModule, below.
55 : #ifndef MOZ_NO_SMART_CARDS
56 : {
57 0 : UniqueSECMODModule module(SECMOD_FindModule(moduleName.get()));
58 0 : if (!module) {
59 0 : return NS_ERROR_FAILURE;
60 : }
61 : nsCOMPtr<nsINSSComponent> nssComponent(
62 0 : do_GetService(PSM_COMPONENT_CONTRACTID));
63 0 : nssComponent->ShutdownSmartCardThread(module.get());
64 : }
65 : #endif
66 :
67 : // modType is an output variable. We ignore it.
68 : int32_t modType;
69 0 : SECStatus srv = SECMOD_DeleteModule(moduleName.get(), &modType);
70 0 : if (srv != SECSuccess) {
71 0 : return NS_ERROR_FAILURE;
72 : }
73 :
74 0 : return NS_OK;
75 : }
76 :
77 : // Given a PKCS#11 module, determines an appropriate name to identify it for the
78 : // purposes of gathering telemetry. For 3rd party PKCS#11 modules, this should
79 : // be the name of the dynamic library that implements the module. For built-in
80 : // NSS modules, it will be the common name of the module.
81 : // Because the result will be used as a telemetry scalar key (which must be less
82 : // than 70 characters), this function will also truncate the result if it
83 : // exceeds this limit. (Note that unfortunately telemetry doesn't expose a way
84 : // to programmatically query the scalar key length limit, so we have to
85 : // hard-code the value here.)
86 : void
87 2 : GetModuleNameForTelemetry(/*in*/ const SECMODModule* module,
88 : /*out*/nsString& result)
89 : {
90 2 : result.Truncate();
91 2 : if (module->dllName) {
92 1 : result.AssignWithConversion(module->dllName);
93 1 : int32_t separatorIndex = result.RFind(FILE_PATH_SEPARATOR);
94 1 : if (separatorIndex != kNotFound) {
95 1 : result = Substring(result, separatorIndex + 1);
96 : }
97 : } else {
98 1 : result.AssignWithConversion(module->commonName);
99 : }
100 2 : if (result.Length() >= 70) {
101 0 : result.Truncate(69);
102 : }
103 2 : }
104 :
105 : // Add a new PKCS11 module to the user's profile.
106 : NS_IMETHODIMP
107 0 : PKCS11::AddModule(const nsAString& aModuleName,
108 : const nsAString& aLibraryFullPath,
109 : int32_t aCryptoMechanismFlags,
110 : int32_t aCipherFlags)
111 : {
112 0 : nsNSSShutDownPreventionLock locker;
113 0 : if (isAlreadyShutDown()) {
114 0 : return NS_ERROR_NOT_AVAILABLE;
115 : }
116 :
117 0 : if (aModuleName.IsEmpty()) {
118 0 : return NS_ERROR_INVALID_ARG;
119 : }
120 :
121 0 : NS_ConvertUTF16toUTF8 moduleName(aModuleName);
122 0 : nsCString fullPath;
123 : // NSS doesn't support Unicode path. Use native charset
124 0 : NS_CopyUnicodeToNative(aLibraryFullPath, fullPath);
125 0 : uint32_t mechFlags = SECMOD_PubMechFlagstoInternal(aCryptoMechanismFlags);
126 0 : uint32_t cipherFlags = SECMOD_PubCipherFlagstoInternal(aCipherFlags);
127 0 : SECStatus srv = SECMOD_AddNewModule(moduleName.get(), fullPath.get(),
128 0 : mechFlags, cipherFlags);
129 0 : if (srv != SECSuccess) {
130 0 : return NS_ERROR_FAILURE;
131 : }
132 :
133 0 : UniqueSECMODModule module(SECMOD_FindModule(moduleName.get()));
134 0 : if (!module) {
135 0 : return NS_ERROR_FAILURE;
136 : }
137 :
138 : #ifndef MOZ_NO_SMART_CARDS
139 : nsCOMPtr<nsINSSComponent> nssComponent(
140 0 : do_GetService(PSM_COMPONENT_CONTRACTID));
141 0 : nssComponent->LaunchSmartCardThread(module.get());
142 : #endif
143 :
144 0 : nsAutoString scalarKey;
145 0 : GetModuleNameForTelemetry(module.get(), scalarKey);
146 : // Scalar keys must be between 0 and 70 characters (exclusive).
147 : // GetModuleNameForTelemetry takes care of keys that are too long.
148 : // If for some reason it couldn't come up with an appropriate name and
149 : // returned an empty result, however, we need to not attempt to record this
150 : // (it wouldn't give us anything useful anyway).
151 0 : if (scalarKey.Length() > 0) {
152 : Telemetry::ScalarSet(Telemetry::ScalarID::SECURITY_PKCS11_MODULES_LOADED,
153 0 : scalarKey, true);
154 : }
155 0 : return NS_OK;
156 : }
157 :
158 : } } // namespace mozilla::psm
|