Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/nss/lib/pk11wrap/pk11pars.c
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
/*
5
 * The following handles the loading, unloading and management of
6
 * various PCKS #11 modules
7
 */
8
9
#include <ctype.h>
10
#include <assert.h>
11
#include "pkcs11.h"
12
#include "seccomon.h"
13
#include "secmod.h"
14
#include "secmodi.h"
15
#include "secmodti.h"
16
#include "pki3hack.h"
17
#include "secerr.h"
18
#include "nss.h"
19
#include "utilpars.h"
20
#include "pk11pub.h"
21
22
/* create a new module */
23
static SECMODModule *
24
secmod_NewModule(void)
25
0
{
26
0
    SECMODModule *newMod;
27
0
    PLArenaPool *arena;
28
0
29
0
    /* create an arena in which dllName and commonName can be
30
0
     * allocated.
31
0
     */
32
0
    arena = PORT_NewArena(512);
33
0
    if (arena == NULL) {
34
0
        return NULL;
35
0
    }
36
0
37
0
    newMod = (SECMODModule *)PORT_ArenaAlloc(arena, sizeof(SECMODModule));
38
0
    if (newMod == NULL) {
39
0
        PORT_FreeArena(arena, PR_FALSE);
40
0
        return NULL;
41
0
    }
42
0
43
0
    /*
44
0
     * initialize of the fields of the module
45
0
     */
46
0
    newMod->arena = arena;
47
0
    newMod->internal = PR_FALSE;
48
0
    newMod->loaded = PR_FALSE;
49
0
    newMod->isFIPS = PR_FALSE;
50
0
    newMod->dllName = NULL;
51
0
    newMod->commonName = NULL;
52
0
    newMod->library = NULL;
53
0
    newMod->functionList = NULL;
54
0
    newMod->slotCount = 0;
55
0
    newMod->slots = NULL;
56
0
    newMod->slotInfo = NULL;
57
0
    newMod->slotInfoCount = 0;
58
0
    newMod->refCount = 1;
59
0
    newMod->ssl[0] = 0;
60
0
    newMod->ssl[1] = 0;
61
0
    newMod->libraryParams = NULL;
62
0
    newMod->moduleDBFunc = NULL;
63
0
    newMod->parent = NULL;
64
0
    newMod->isCritical = PR_FALSE;
65
0
    newMod->isModuleDB = PR_FALSE;
66
0
    newMod->moduleDBOnly = PR_FALSE;
67
0
    newMod->trustOrder = 0;
68
0
    newMod->cipherOrder = 0;
69
0
    newMod->evControlMask = 0;
70
0
    newMod->refLock = PZ_NewLock(nssILockRefLock);
71
0
    if (newMod->refLock == NULL) {
72
0
        PORT_FreeArena(arena, PR_FALSE);
73
0
        return NULL;
74
0
    }
75
0
    return newMod;
76
0
}
77
78
/* private flags for isModuleDB (field in SECMODModule). */
79
/* The meaing of these flags is as follows:
80
 *
81
 * SECMOD_FLAG_MODULE_DB_IS_MODULE_DB - This is a module that accesses the
82
 *   database of other modules to load. Module DBs are loadable modules that
83
 *   tells NSS which PKCS #11 modules to load and when. These module DBs are
84
 *   chainable. That is, one module DB can load another one. NSS system init
85
 *   design takes advantage of this feature. In system NSS, a fixed system
86
 *   module DB loads the system defined libraries, then chains out to the
87
 *   traditional module DBs to load any system or user configured modules
88
 *   (like smart cards). This bit is the same as the already existing meaning
89
 *   of  isModuleDB = PR_TRUE. None of the other module db flags should be set
90
 *   if this flag isn't on.
91
 *
92
 * SECMOD_FLAG_MODULE_DB_SKIP_FIRST - This flag tells NSS to skip the first
93
 *   PKCS #11 module presented by a module DB. This allows the OS to load a
94
 *   softoken from the system module, then ask the existing module DB code to
95
 *   load the other PKCS #11 modules in that module DB (skipping it's request
96
 *   to load softoken). This gives the system init finer control over the
97
 *   configuration of that softoken module.
98
 *
99
 * SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB - This flag allows system init to mark a
100
 *   different module DB as the 'default' module DB (the one in which
101
 *   'Add module' changes will go). Without this flag NSS takes the first
102
 *   module as the default Module DB, but in system NSS, that first module
103
 *   is the system module, which is likely read only (at least to the user).
104
 *   This  allows system NSS to delegate those changes to the user's module DB,
105
 *   preserving the user's ability to load new PKCS #11 modules (which only
106
 *   affect him), from existing applications like Firefox.
107
 */
108
0
#define SECMOD_FLAG_MODULE_DB_IS_MODULE_DB 0x01 /* must be set if any of the \
109
                                                 *other flags are set */
110
0
#define SECMOD_FLAG_MODULE_DB_SKIP_FIRST 0x02
111
0
#define SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB 0x04
112
0
#define SECMOD_FLAG_MODULE_DB_POLICY_ONLY 0x08
113
114
/* private flags for internal (field in SECMODModule). */
115
/* The meaing of these flags is as follows:
116
 *
117
 * SECMOD_FLAG_INTERNAL_IS_INTERNAL - This is a marks the the module is
118
 *   the internal module (that is, softoken). This bit is the same as the
119
 *   already existing meaning of internal = PR_TRUE. None of the other
120
 *   internal flags should be set if this flag isn't on.
121
 *
122
 * SECMOD_FLAG_MODULE_INTERNAL_KEY_SLOT - This flag allows system init to mark
123
 *   a  different slot returned byt PK11_GetInternalKeySlot(). The 'primary'
124
 *   slot defined by this module will be the new internal key slot.
125
 */
126
0
#define SECMOD_FLAG_INTERNAL_IS_INTERNAL 0x01 /* must be set if any of \
127
                                               *the other flags are set */
128
0
#define SECMOD_FLAG_INTERNAL_KEY_SLOT 0x02
129
130
/*
131
 * for 3.4 we continue to use the old SECMODModule structure
132
 */
133
SECMODModule *
134
SECMOD_CreateModule(const char *library, const char *moduleName,
135
                    const char *parameters, const char *nss)
136
0
{
137
0
    return SECMOD_CreateModuleEx(library, moduleName, parameters, nss, NULL);
138
0
}
139
140
/*
141
 * NSS config options format:
142
 *
143
 * The specified ciphers will be allowed by policy, but an application
144
 * may allow more by policy explicitly:
145
 * config="allow=curve1:curve2:hash1:hash2:rsa-1024..."
146
 *
147
 * Only the specified hashes and curves will be allowed:
148
 * config="disallow=all allow=sha1:sha256:secp256r1:secp384r1"
149
 *
150
 * Only the specified hashes and curves will be allowed, and
151
 *  RSA keys of 2048 or more will be accepted, and DH key exchange
152
 *  with 1024-bit primes or more:
153
 * config="disallow=all allow=sha1:sha256:secp256r1:secp384r1:min-rsa=2048:min-dh=1024"
154
 *
155
 * A policy that enables the AES ciphersuites and the SECP256/384 curves:
156
 * config="allow=aes128-cbc:aes128-gcm:TLS1.0:TLS1.2:TLS1.1:HMAC-SHA1:SHA1:SHA256:SHA384:RSA:ECDHE-RSA:SECP256R1:SECP384R1"
157
 *
158
 * Disallow values are parsed first, then allow values, independent of the
159
 * order they appear.
160
 *
161
 * Future key words (not yet implemented):
162
 * enable: turn on ciphersuites by default.
163
 * disable: turn off ciphersuites by default without disallowing them by policy.
164
 * flags: turn on the following flags:
165
 *     ssl-lock: turn off the ability for applications to change policy with
166
 *               the SSL_SetCipherPolicy (or SSL_SetPolicy).
167
 *     policy-lock: turn off the ability for applications to change policy with
168
 *               the call NSS_SetAlgorithmPolicy.
169
 *     ssl-default-lock: turn off the ability for applications to change cipher
170
 *               suite states with SSL_EnableCipher, SSL_DisableCipher.
171
 *
172
 */
173
174
typedef struct {
175
    const char *name;
176
    unsigned name_size;
177
    SECOidTag oid;
178
    PRUint32 val;
179
} oidValDef;
180
181
typedef struct {
182
    const char *name;
183
    unsigned name_size;
184
    PRInt32 option;
185
} optionFreeDef;
186
187
typedef struct {
188
    const char *name;
189
    unsigned name_size;
190
    PRUint32 flag;
191
} policyFlagDef;
192
193
/*
194
 *  This table should be merged with the SECOID table.
195
 */
196
#define CIPHER_NAME(x) x, (sizeof(x) - 1)
197
static const oidValDef curveOptList[] = {
198
    /* Curves */
199
    { CIPHER_NAME("PRIME192V1"), SEC_OID_ANSIX962_EC_PRIME192V1,
200
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
201
    { CIPHER_NAME("PRIME192V2"), SEC_OID_ANSIX962_EC_PRIME192V2,
202
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
203
    { CIPHER_NAME("PRIME192V3"), SEC_OID_ANSIX962_EC_PRIME192V3,
204
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
205
    { CIPHER_NAME("PRIME239V1"), SEC_OID_ANSIX962_EC_PRIME239V1,
206
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
207
    { CIPHER_NAME("PRIME239V2"), SEC_OID_ANSIX962_EC_PRIME239V2,
208
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
209
    { CIPHER_NAME("PRIME239V3"), SEC_OID_ANSIX962_EC_PRIME239V3,
210
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
211
    { CIPHER_NAME("PRIME256V1"), SEC_OID_ANSIX962_EC_PRIME256V1,
212
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
213
    { CIPHER_NAME("SECP112R1"), SEC_OID_SECG_EC_SECP112R1,
214
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
215
    { CIPHER_NAME("SECP112R2"), SEC_OID_SECG_EC_SECP112R2,
216
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
217
    { CIPHER_NAME("SECP128R1"), SEC_OID_SECG_EC_SECP128R1,
218
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
219
    { CIPHER_NAME("SECP128R2"), SEC_OID_SECG_EC_SECP128R2,
220
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
221
    { CIPHER_NAME("SECP160K1"), SEC_OID_SECG_EC_SECP160K1,
222
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
223
    { CIPHER_NAME("SECP160R1"), SEC_OID_SECG_EC_SECP160R1,
224
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
225
    { CIPHER_NAME("SECP160R2"), SEC_OID_SECG_EC_SECP160R2,
226
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
227
    { CIPHER_NAME("SECP192K1"), SEC_OID_SECG_EC_SECP192K1,
228
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
229
    { CIPHER_NAME("SECP192R1"), SEC_OID_ANSIX962_EC_PRIME192V1,
230
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
231
    { CIPHER_NAME("SECP224K1"), SEC_OID_SECG_EC_SECP224K1,
232
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
233
    { CIPHER_NAME("SECP256K1"), SEC_OID_SECG_EC_SECP256K1,
234
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
235
    { CIPHER_NAME("SECP256R1"), SEC_OID_ANSIX962_EC_PRIME256V1,
236
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
237
    { CIPHER_NAME("SECP384R1"), SEC_OID_SECG_EC_SECP384R1,
238
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
239
    { CIPHER_NAME("SECP521R1"), SEC_OID_SECG_EC_SECP521R1,
240
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
241
    /* ANSI X9.62 named elliptic curves (characteristic two field) */
242
    { CIPHER_NAME("C2PNB163V1"), SEC_OID_ANSIX962_EC_C2PNB163V1,
243
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
244
    { CIPHER_NAME("C2PNB163V2"), SEC_OID_ANSIX962_EC_C2PNB163V2,
245
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
246
    { CIPHER_NAME("C2PNB163V3"), SEC_OID_ANSIX962_EC_C2PNB163V3,
247
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
248
    { CIPHER_NAME("C2PNB176V1"), SEC_OID_ANSIX962_EC_C2PNB176V1,
249
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
250
    { CIPHER_NAME("C2TNB191V1"), SEC_OID_ANSIX962_EC_C2TNB191V1,
251
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
252
    { CIPHER_NAME("C2TNB191V2"), SEC_OID_ANSIX962_EC_C2TNB191V2,
253
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
254
    { CIPHER_NAME("C2TNB191V3"), SEC_OID_ANSIX962_EC_C2TNB191V3,
255
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
256
    { CIPHER_NAME("C2ONB191V4"), SEC_OID_ANSIX962_EC_C2ONB191V4,
257
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
258
    { CIPHER_NAME("C2ONB191V5"), SEC_OID_ANSIX962_EC_C2ONB191V5,
259
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
260
    { CIPHER_NAME("C2PNB208W1"), SEC_OID_ANSIX962_EC_C2PNB208W1,
261
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
262
    { CIPHER_NAME("C2TNB239V1"), SEC_OID_ANSIX962_EC_C2TNB239V1,
263
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
264
    { CIPHER_NAME("C2TNB239V2"), SEC_OID_ANSIX962_EC_C2TNB239V2,
265
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
266
    { CIPHER_NAME("C2TNB239V3"), SEC_OID_ANSIX962_EC_C2TNB239V3,
267
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
268
    { CIPHER_NAME("C2ONB239V4"), SEC_OID_ANSIX962_EC_C2ONB239V4,
269
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
270
    { CIPHER_NAME("C2ONB239V5"), SEC_OID_ANSIX962_EC_C2ONB239V5,
271
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
272
    { CIPHER_NAME("C2PNB272W1"), SEC_OID_ANSIX962_EC_C2PNB272W1,
273
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
274
    { CIPHER_NAME("C2PNB304W1"), SEC_OID_ANSIX962_EC_C2PNB304W1,
275
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
276
    { CIPHER_NAME("C2TNB359V1"), SEC_OID_ANSIX962_EC_C2TNB359V1,
277
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
278
    { CIPHER_NAME("C2PNB368W1"), SEC_OID_ANSIX962_EC_C2PNB368W1,
279
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
280
    { CIPHER_NAME("C2TNB431R1"), SEC_OID_ANSIX962_EC_C2TNB431R1,
281
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
282
    /* SECG named elliptic curves (characteristic two field) */
283
    { CIPHER_NAME("SECT113R1"), SEC_OID_SECG_EC_SECT113R1,
284
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
285
    { CIPHER_NAME("SECT131R1"), SEC_OID_SECG_EC_SECT113R2,
286
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
287
    { CIPHER_NAME("SECT131R1"), SEC_OID_SECG_EC_SECT131R1,
288
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
289
    { CIPHER_NAME("SECT131R2"), SEC_OID_SECG_EC_SECT131R2,
290
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
291
    { CIPHER_NAME("SECT163K1"), SEC_OID_SECG_EC_SECT163K1,
292
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
293
    { CIPHER_NAME("SECT163R1"), SEC_OID_SECG_EC_SECT163R1,
294
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
295
    { CIPHER_NAME("SECT163R2"), SEC_OID_SECG_EC_SECT163R2,
296
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
297
    { CIPHER_NAME("SECT193R1"), SEC_OID_SECG_EC_SECT193R1,
298
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
299
    { CIPHER_NAME("SECT193R2"), SEC_OID_SECG_EC_SECT193R2,
300
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
301
    { CIPHER_NAME("SECT233K1"), SEC_OID_SECG_EC_SECT233K1,
302
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
303
    { CIPHER_NAME("SECT233R1"), SEC_OID_SECG_EC_SECT233R1,
304
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
305
    { CIPHER_NAME("SECT239K1"), SEC_OID_SECG_EC_SECT239K1,
306
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
307
    { CIPHER_NAME("SECT283K1"), SEC_OID_SECG_EC_SECT283K1,
308
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
309
    { CIPHER_NAME("SECT283R1"), SEC_OID_SECG_EC_SECT283R1,
310
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
311
    { CIPHER_NAME("SECT409K1"), SEC_OID_SECG_EC_SECT409K1,
312
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
313
    { CIPHER_NAME("SECT409R1"), SEC_OID_SECG_EC_SECT409R1,
314
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
315
    { CIPHER_NAME("SECT571K1"), SEC_OID_SECG_EC_SECT571K1,
316
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
317
    { CIPHER_NAME("SECT571R1"), SEC_OID_SECG_EC_SECT571R1,
318
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
319
};
320
321
static const oidValDef hashOptList[] = {
322
    /* Hashes */
323
    { CIPHER_NAME("MD2"), SEC_OID_MD2,
324
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
325
    { CIPHER_NAME("MD4"), SEC_OID_MD4,
326
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
327
    { CIPHER_NAME("MD5"), SEC_OID_MD5,
328
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
329
    { CIPHER_NAME("SHA1"), SEC_OID_SHA1,
330
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
331
    { CIPHER_NAME("SHA224"), SEC_OID_SHA224,
332
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
333
    { CIPHER_NAME("SHA256"), SEC_OID_SHA256,
334
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
335
    { CIPHER_NAME("SHA384"), SEC_OID_SHA384,
336
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
337
    { CIPHER_NAME("SHA512"), SEC_OID_SHA512,
338
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
339
};
340
341
static const oidValDef macOptList[] = {
342
    /* MACs */
343
    { CIPHER_NAME("HMAC-SHA1"), SEC_OID_HMAC_SHA1, NSS_USE_ALG_IN_SSL },
344
    { CIPHER_NAME("HMAC-SHA224"), SEC_OID_HMAC_SHA224, NSS_USE_ALG_IN_SSL },
345
    { CIPHER_NAME("HMAC-SHA256"), SEC_OID_HMAC_SHA256, NSS_USE_ALG_IN_SSL },
346
    { CIPHER_NAME("HMAC-SHA384"), SEC_OID_HMAC_SHA384, NSS_USE_ALG_IN_SSL },
347
    { CIPHER_NAME("HMAC-SHA512"), SEC_OID_HMAC_SHA512, NSS_USE_ALG_IN_SSL },
348
    { CIPHER_NAME("HMAC-MD5"), SEC_OID_HMAC_MD5, NSS_USE_ALG_IN_SSL },
349
};
350
351
static const oidValDef cipherOptList[] = {
352
    /* Ciphers */
353
    { CIPHER_NAME("AES128-CBC"), SEC_OID_AES_128_CBC, NSS_USE_ALG_IN_SSL },
354
    { CIPHER_NAME("AES192-CBC"), SEC_OID_AES_192_CBC, NSS_USE_ALG_IN_SSL },
355
    { CIPHER_NAME("AES256-CBC"), SEC_OID_AES_256_CBC, NSS_USE_ALG_IN_SSL },
356
    { CIPHER_NAME("AES128-GCM"), SEC_OID_AES_128_GCM, NSS_USE_ALG_IN_SSL },
357
    { CIPHER_NAME("AES192-GCM"), SEC_OID_AES_192_GCM, NSS_USE_ALG_IN_SSL },
358
    { CIPHER_NAME("AES256-GCM"), SEC_OID_AES_256_GCM, NSS_USE_ALG_IN_SSL },
359
    { CIPHER_NAME("CAMELLIA128-CBC"), SEC_OID_CAMELLIA_128_CBC, NSS_USE_ALG_IN_SSL },
360
    { CIPHER_NAME("CAMELLIA192-CBC"), SEC_OID_CAMELLIA_192_CBC, NSS_USE_ALG_IN_SSL },
361
    { CIPHER_NAME("CAMELLIA256-CBC"), SEC_OID_CAMELLIA_256_CBC, NSS_USE_ALG_IN_SSL },
362
    { CIPHER_NAME("CHACHA20-POLY1305"), SEC_OID_CHACHA20_POLY1305, NSS_USE_ALG_IN_SSL },
363
    { CIPHER_NAME("SEED-CBC"), SEC_OID_SEED_CBC, NSS_USE_ALG_IN_SSL },
364
    { CIPHER_NAME("DES-EDE3-CBC"), SEC_OID_DES_EDE3_CBC, NSS_USE_ALG_IN_SSL },
365
    { CIPHER_NAME("DES-40-CBC"), SEC_OID_DES_40_CBC, NSS_USE_ALG_IN_SSL },
366
    { CIPHER_NAME("DES-CBC"), SEC_OID_DES_CBC, NSS_USE_ALG_IN_SSL },
367
    { CIPHER_NAME("NULL-CIPHER"), SEC_OID_NULL_CIPHER, NSS_USE_ALG_IN_SSL },
368
    { CIPHER_NAME("RC2"), SEC_OID_RC2_CBC, NSS_USE_ALG_IN_SSL },
369
    { CIPHER_NAME("RC4"), SEC_OID_RC4, NSS_USE_ALG_IN_SSL },
370
    { CIPHER_NAME("IDEA"), SEC_OID_IDEA_CBC, NSS_USE_ALG_IN_SSL },
371
};
372
373
static const oidValDef kxOptList[] = {
374
    /* Key exchange */
375
    { CIPHER_NAME("RSA"), SEC_OID_TLS_RSA, NSS_USE_ALG_IN_SSL_KX },
376
    { CIPHER_NAME("RSA-EXPORT"), SEC_OID_TLS_RSA_EXPORT, NSS_USE_ALG_IN_SSL_KX },
377
    { CIPHER_NAME("DHE-RSA"), SEC_OID_TLS_DHE_RSA, NSS_USE_ALG_IN_SSL_KX },
378
    { CIPHER_NAME("DHE-DSS"), SEC_OID_TLS_DHE_DSS, NSS_USE_ALG_IN_SSL_KX },
379
    { CIPHER_NAME("DH-RSA"), SEC_OID_TLS_DH_RSA, NSS_USE_ALG_IN_SSL_KX },
380
    { CIPHER_NAME("DH-DSS"), SEC_OID_TLS_DH_DSS, NSS_USE_ALG_IN_SSL_KX },
381
    { CIPHER_NAME("ECDHE-ECDSA"), SEC_OID_TLS_ECDHE_ECDSA, NSS_USE_ALG_IN_SSL_KX },
382
    { CIPHER_NAME("ECDHE-RSA"), SEC_OID_TLS_ECDHE_RSA, NSS_USE_ALG_IN_SSL_KX },
383
    { CIPHER_NAME("ECDH-ECDSA"), SEC_OID_TLS_ECDH_ECDSA, NSS_USE_ALG_IN_SSL_KX },
384
    { CIPHER_NAME("ECDH-RSA"), SEC_OID_TLS_ECDH_RSA, NSS_USE_ALG_IN_SSL_KX },
385
};
386
387
typedef struct {
388
    const oidValDef *list;
389
    PRUint32 entries;
390
    const char *description;
391
} algListsDef;
392
393
static const algListsDef algOptLists[] = {
394
    { curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC" },
395
    { hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH" },
396
    { macOptList, PR_ARRAY_SIZE(macOptList), "MAC" },
397
    { cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER" },
398
    { kxOptList, PR_ARRAY_SIZE(kxOptList), "OTHER-KX" },
399
};
400
401
static const optionFreeDef sslOptList[] = {
402
    /* Versions */
403
    { CIPHER_NAME("SSL2.0"), 0x002 },
404
    { CIPHER_NAME("SSL3.0"), 0x300 },
405
    { CIPHER_NAME("SSL3.1"), 0x301 },
406
    { CIPHER_NAME("TLS1.0"), 0x301 },
407
    { CIPHER_NAME("TLS1.1"), 0x302 },
408
    { CIPHER_NAME("TLS1.2"), 0x303 },
409
    { CIPHER_NAME("TLS1.3"), 0x304 },
410
    { CIPHER_NAME("DTLS1.0"), 0x302 },
411
    { CIPHER_NAME("DTLS1.1"), 0x302 },
412
    { CIPHER_NAME("DTLS1.2"), 0x303 },
413
    { CIPHER_NAME("DTLS1.3"), 0x304 },
414
};
415
416
static const optionFreeDef freeOptList[] = {
417
418
    /* Restrictions for asymetric keys */
419
    { CIPHER_NAME("RSA-MIN"), NSS_RSA_MIN_KEY_SIZE },
420
    { CIPHER_NAME("DH-MIN"), NSS_DH_MIN_KEY_SIZE },
421
    { CIPHER_NAME("DSA-MIN"), NSS_DSA_MIN_KEY_SIZE },
422
    /* constraints on SSL Protocols */
423
    { CIPHER_NAME("TLS-VERSION-MIN"), NSS_TLS_VERSION_MIN_POLICY },
424
    { CIPHER_NAME("TLS-VERSION-MAX"), NSS_TLS_VERSION_MAX_POLICY },
425
    /* constraints on DTLS Protocols */
426
    { CIPHER_NAME("DTLS-VERSION-MIN"), NSS_DTLS_VERSION_MIN_POLICY },
427
    { CIPHER_NAME("DTLS-VERSION-MAX"), NSS_DTLS_VERSION_MAX_POLICY }
428
};
429
430
static const policyFlagDef policyFlagList[] = {
431
    { CIPHER_NAME("SSL"), NSS_USE_ALG_IN_SSL },
432
    { CIPHER_NAME("SSL-KEY-EXCHANGE"), NSS_USE_ALG_IN_SSL_KX },
433
    /* add other key exhanges in the future */
434
    { CIPHER_NAME("KEY-EXCHANGE"), NSS_USE_ALG_IN_SSL_KX },
435
    { CIPHER_NAME("CERT-SIGNATURE"), NSS_USE_ALG_IN_CERT_SIGNATURE },
436
    /* add other signatures in the future */
437
    { CIPHER_NAME("SIGNATURE"), NSS_USE_ALG_IN_CERT_SIGNATURE },
438
    /* enable everything */
439
    { CIPHER_NAME("ALL"), NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
440
    { CIPHER_NAME("NONE"), 0 }
441
};
442
443
/*
444
 *  Get the next cipher on the list. point to the next one in 'next'.
445
 *  return the length;
446
 */
447
static const char *
448
secmod_ArgGetSubValue(const char *cipher, char sep1, char sep2,
449
                      int *len, const char **next)
450
0
{
451
0
    const char *start = cipher;
452
0
453
0
    if (start == NULL) {
454
0
        *len = 0;
455
0
        *next = NULL;
456
0
        return start;
457
0
    }
458
0
459
0
    for (; *cipher && *cipher != sep2; cipher++) {
460
0
        if (*cipher == sep1) {
461
0
            *next = cipher + 1;
462
0
            *len = cipher - start;
463
0
            return start;
464
0
        }
465
0
    }
466
0
    *next = NULL;
467
0
    *len = cipher - start;
468
0
    return start;
469
0
}
470
471
static PRUint32
472
secmod_parsePolicyValue(const char *policyFlags, int policyLength,
473
                        PRBool printPolicyFeedback)
474
0
{
475
0
    const char *flag, *currentString;
476
0
    PRUint32 flags = 0;
477
0
    int i;
478
0
479
0
    for (currentString = policyFlags; currentString &&
480
0
                                      currentString < policyFlags + policyLength;) {
481
0
        int length;
482
0
        PRBool unknown = PR_TRUE;
483
0
        flag = secmod_ArgGetSubValue(currentString, ',', ':', &length,
484
0
                                     &currentString);
485
0
        if (length == 0) {
486
0
            continue;
487
0
        }
488
0
        for (i = 0; i < PR_ARRAY_SIZE(policyFlagList); i++) {
489
0
            const policyFlagDef *policy = &policyFlagList[i];
490
0
            unsigned name_size = policy->name_size;
491
0
            if ((policy->name_size == length) &&
492
0
                PORT_Strncasecmp(policy->name, flag, name_size) == 0) {
493
0
                flags |= policy->flag;
494
0
                unknown = PR_FALSE;
495
0
                break;
496
0
            }
497
0
        }
498
0
        if (unknown && printPolicyFeedback) {
499
0
            PR_SetEnv("NSS_POLICY_FAIL=1");
500
0
            fprintf(stderr, "NSS-POLICY-FAIL %.*s: unknown value: %.*s\n",
501
0
                    policyLength, policyFlags, length, flag);
502
0
        }
503
0
    }
504
0
    return flags;
505
0
}
506
507
/* allow symbolic names for values. The only ones currently defines or
508
 * SSL protocol versions. */
509
static SECStatus
510
secmod_getPolicyOptValue(const char *policyValue, int policyValueLength,
511
                         PRInt32 *result)
512
0
{
513
0
    PRInt32 val = atoi(policyValue);
514
0
    int i;
515
0
516
0
    if ((val != 0) || (*policyValue == '0')) {
517
0
        *result = val;
518
0
        return SECSuccess;
519
0
    }
520
0
    for (i = 0; i < PR_ARRAY_SIZE(sslOptList); i++) {
521
0
        if (policyValueLength == sslOptList[i].name_size &&
522
0
            PORT_Strncasecmp(sslOptList[i].name, policyValue,
523
0
                             sslOptList[i].name_size) == 0) {
524
0
            *result = sslOptList[i].option;
525
0
            return SECSuccess;
526
0
        }
527
0
    }
528
0
    return SECFailure;
529
0
}
530
531
static SECStatus
532
secmod_applyCryptoPolicy(const char *policyString, PRBool allow,
533
                         PRBool printPolicyFeedback)
534
0
{
535
0
    const char *cipher, *currentString;
536
0
    unsigned i, j;
537
0
    SECStatus rv = SECSuccess;
538
0
    PRBool unknown;
539
0
540
0
    if (policyString == NULL || policyString[0] == 0) {
541
0
        return SECSuccess; /* do nothing */
542
0
    }
543
0
544
0
    /* if we change any of these, make sure it gets applied in ssl as well */
545
0
    NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL, 0);
546
0
547
0
    for (currentString = policyString; currentString;) {
548
0
        int length;
549
0
        PRBool newValue = PR_FALSE;
550
0
551
0
        cipher = secmod_ArgGetSubValue(currentString, ':', 0, &length,
552
0
                                       &currentString);
553
0
        unknown = PR_TRUE;
554
0
        if (length >= 3 && cipher[3] == '/') {
555
0
            newValue = PR_TRUE;
556
0
        }
557
0
        if ((newValue || (length == 3)) && PORT_Strncasecmp(cipher, "all", 3) == 0) {
558
0
            /* disable or enable all options by default */
559
0
            PRUint32 value = 0;
560
0
            if (newValue) {
561
0
                value = secmod_parsePolicyValue(&cipher[3] + 1, length - 3 - 1, printPolicyFeedback);
562
0
            }
563
0
            for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) {
564
0
                const algListsDef *algOptList = &algOptLists[i];
565
0
                for (j = 0; j < algOptList->entries; j++) {
566
0
                    PRUint32 enable, disable;
567
0
                    if (!newValue) {
568
0
                        value = algOptList->list[j].val;
569
0
                    }
570
0
                    if (allow) {
571
0
                        enable = value;
572
0
                        disable = 0;
573
0
                    } else {
574
0
                        enable = 0;
575
0
                        disable = value;
576
0
                    }
577
0
                    NSS_SetAlgorithmPolicy(algOptList->list[j].oid, enable, disable);
578
0
                }
579
0
            }
580
0
            continue;
581
0
        }
582
0
583
0
        for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) {
584
0
            const algListsDef *algOptList = &algOptLists[i];
585
0
            for (j = 0; j < algOptList->entries; j++) {
586
0
                const oidValDef *algOpt = &algOptList->list[j];
587
0
                unsigned name_size = algOpt->name_size;
588
0
                PRBool newOption = PR_FALSE;
589
0
590
0
                if ((length >= name_size) && (cipher[name_size] == '/')) {
591
0
                    newOption = PR_TRUE;
592
0
                }
593
0
                if ((newOption || algOpt->name_size == length) &&
594
0
                    PORT_Strncasecmp(algOpt->name, cipher, name_size) == 0) {
595
0
                    PRUint32 value = algOpt->val;
596
0
                    PRUint32 enable, disable;
597
0
                    if (newOption) {
598
0
                        value = secmod_parsePolicyValue(&cipher[name_size] + 1,
599
0
                                                        length - name_size - 1,
600
0
                                                        printPolicyFeedback);
601
0
                    }
602
0
                    if (allow) {
603
0
                        enable = value;
604
0
                        disable = 0;
605
0
                    } else {
606
0
                        enable = 0;
607
0
                        disable = value;
608
0
                    }
609
0
                    rv = NSS_SetAlgorithmPolicy(algOpt->oid, enable, disable);
610
0
                    if (rv != SECSuccess) {
611
0
                        /* could not enable option */
612
0
                        /* NSS_SetAlgorithPolicy should have set the error code */
613
0
                        return SECFailure;
614
0
                    }
615
0
                    unknown = PR_FALSE;
616
0
                    break;
617
0
                }
618
0
            }
619
0
        }
620
0
        if (!unknown) {
621
0
            continue;
622
0
        }
623
0
624
0
        for (i = 0; i < PR_ARRAY_SIZE(freeOptList); i++) {
625
0
            const optionFreeDef *freeOpt = &freeOptList[i];
626
0
            unsigned name_size = freeOpt->name_size;
627
0
628
0
            if ((length > name_size) && cipher[name_size] == '=' &&
629
0
                PORT_Strncasecmp(freeOpt->name, cipher, name_size) == 0) {
630
0
                PRInt32 val;
631
0
                const char *policyValue = &cipher[name_size + 1];
632
0
                int policyValueLength = length - name_size - 1;
633
0
                rv = secmod_getPolicyOptValue(policyValue, policyValueLength,
634
0
                                              &val);
635
0
                if (rv != SECSuccess) {
636
0
                    if (printPolicyFeedback) {
637
0
                        PR_SetEnv("NSS_POLICY_FAIL=1");
638
0
                        fprintf(stderr, "NSS-POLICY-FAIL %.*s: unknown value: %.*s\n",
639
0
                                length, cipher, policyValueLength, policyValue);
640
0
                    }
641
0
                    return SECFailure;
642
0
                }
643
0
                rv = NSS_OptionSet(freeOpt->option, val);
644
0
                if (rv != SECSuccess) {
645
0
                    /* could not enable option */
646
0
                    /* NSS_OptionSet should have set the error code */
647
0
                    return SECFailure;
648
0
                }
649
0
                /* to allow the policy to expand in the future. ignore ciphers
650
0
                 * we don't understand */
651
0
                unknown = PR_FALSE;
652
0
                break;
653
0
            }
654
0
        }
655
0
656
0
        if (unknown && printPolicyFeedback) {
657
0
            PR_SetEnv("NSS_POLICY_FAIL=1");
658
0
            fprintf(stderr, "NSS-POLICY-FAIL %s: unknown identifier: %.*s\n",
659
0
                    allow ? "allow" : "disallow", length, cipher);
660
0
        }
661
0
    }
662
0
    return rv;
663
0
}
664
665
static void
666
secmod_sanityCheckCryptoPolicy(void)
667
0
{
668
0
    unsigned i, j;
669
0
    SECStatus rv = SECSuccess;
670
0
    unsigned num_kx_enabled = 0;
671
0
    unsigned num_ssl_enabled = 0;
672
0
    unsigned num_sig_enabled = 0;
673
0
    unsigned enabledCount[PR_ARRAY_SIZE(algOptLists)];
674
0
    const char *sWarn = "WARN";
675
0
    const char *sInfo = "INFO";
676
0
    PRBool haveWarning = PR_FALSE;
677
0
678
0
    for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) {
679
0
        const algListsDef *algOptList = &algOptLists[i];
680
0
        enabledCount[i] = 0;
681
0
        for (j = 0; j < algOptList->entries; j++) {
682
0
            const oidValDef *algOpt = &algOptList->list[j];
683
0
            PRUint32 value;
684
0
            PRBool anyEnabled = PR_FALSE;
685
0
            rv = NSS_GetAlgorithmPolicy(algOpt->oid, &value);
686
0
            if (rv != SECSuccess) {
687
0
                PR_SetEnv("NSS_POLICY_FAIL=1");
688
0
                fprintf(stderr, "NSS-POLICY-FAIL: internal failure with NSS_GetAlgorithmPolicy at %u\n", i);
689
0
                return;
690
0
            }
691
0
692
0
            if ((algOpt->val & NSS_USE_ALG_IN_SSL_KX) && (value & NSS_USE_ALG_IN_SSL_KX)) {
693
0
                ++num_kx_enabled;
694
0
                anyEnabled = PR_TRUE;
695
0
                fprintf(stderr, "NSS-POLICY-INFO: %s is enabled for KX\n", algOpt->name);
696
0
            }
697
0
            if ((algOpt->val & NSS_USE_ALG_IN_SSL) && (value & NSS_USE_ALG_IN_SSL)) {
698
0
                ++num_ssl_enabled;
699
0
                anyEnabled = PR_TRUE;
700
0
                fprintf(stderr, "NSS-POLICY-INFO: %s is enabled for SSL\n", algOpt->name);
701
0
            }
702
0
            if ((algOpt->val & NSS_USE_ALG_IN_CERT_SIGNATURE) && (value & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
703
0
                ++num_sig_enabled;
704
0
                anyEnabled = PR_TRUE;
705
0
                fprintf(stderr, "NSS-POLICY-INFO: %s is enabled for CERT-SIGNATURE\n", algOpt->name);
706
0
            }
707
0
            if (anyEnabled) {
708
0
                ++enabledCount[i];
709
0
            }
710
0
        }
711
0
    }
712
0
    fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-SSL-ALG-KX: %u\n", num_kx_enabled ? sInfo : sWarn, num_kx_enabled);
713
0
    fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-SSL-ALG: %u\n", num_ssl_enabled ? sInfo : sWarn, num_ssl_enabled);
714
0
    fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-CERT-SIG: %u\n", num_sig_enabled ? sInfo : sWarn, num_sig_enabled);
715
0
    if (!num_kx_enabled || !num_ssl_enabled || !num_sig_enabled) {
716
0
        haveWarning = PR_TRUE;
717
0
    }
718
0
    for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) {
719
0
        const algListsDef *algOptList = &algOptLists[i];
720
0
        fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-%s: %u\n", enabledCount[i] ? sInfo : sWarn, algOptList->description, enabledCount[i]);
721
0
        if (!enabledCount[i]) {
722
0
            haveWarning = PR_TRUE;
723
0
        }
724
0
    }
725
0
    if (haveWarning) {
726
0
        PR_SetEnv("NSS_POLICY_WARN=1");
727
0
    }
728
0
}
729
730
static SECStatus
731
secmod_parseCryptoPolicy(const char *policyConfig, PRBool printPolicyFeedback)
732
0
{
733
0
    char *disallow, *allow;
734
0
    SECStatus rv;
735
0
736
0
    if (policyConfig == NULL) {
737
0
        return SECSuccess; /* no policy given */
738
0
    }
739
0
    /* make sure we initialize the oid table and set all the default policy
740
0
     * values first so we can override them here */
741
0
    rv = SECOID_Init();
742
0
    if (rv != SECSuccess) {
743
0
        return rv;
744
0
    }
745
0
    disallow = NSSUTIL_ArgGetParamValue("disallow", policyConfig);
746
0
    rv = secmod_applyCryptoPolicy(disallow, PR_FALSE, printPolicyFeedback);
747
0
    if (disallow)
748
0
        PORT_Free(disallow);
749
0
    if (rv != SECSuccess) {
750
0
        return rv;
751
0
    }
752
0
    allow = NSSUTIL_ArgGetParamValue("allow", policyConfig);
753
0
    rv = secmod_applyCryptoPolicy(allow, PR_TRUE, printPolicyFeedback);
754
0
    if (allow)
755
0
        PORT_Free(allow);
756
0
    if (rv != SECSuccess) {
757
0
        return rv;
758
0
    }
759
0
    if (printPolicyFeedback) {
760
0
        /* This helps to distinguish configurations that don't contain any
761
0
         * policy config= statement. */
762
0
        PR_SetEnv("NSS_POLICY_LOADED=1");
763
0
        fprintf(stderr, "NSS-POLICY-INFO: LOADED-SUCCESSFULLY\n");
764
0
        secmod_sanityCheckCryptoPolicy();
765
0
    }
766
0
    return rv;
767
0
}
768
769
/*
770
 * for 3.4 we continue to use the old SECMODModule structure
771
 */
772
SECMODModule *
773
SECMOD_CreateModuleEx(const char *library, const char *moduleName,
774
                      const char *parameters, const char *nss,
775
                      const char *config)
776
0
{
777
0
    SECMODModule *mod;
778
0
    SECStatus rv;
779
0
    char *slotParams, *ciphers;
780
0
    /* pk11pars.h still does not have const char * interfaces */
781
0
    char *nssc = (char *)nss;
782
0
    PRBool printPolicyFeedback = NSSUTIL_ArgHasFlag("flags", "printPolicyFeedback", nssc);
783
0
784
0
    rv = secmod_parseCryptoPolicy(config, printPolicyFeedback);
785
0
786
0
    /* do not load the module if policy parsing fails */
787
0
    if (rv != SECSuccess) {
788
0
        if (printPolicyFeedback) {
789
0
            PR_SetEnv("NSS_POLICY_FAIL=1");
790
0
            fprintf(stderr, "NSS-POLICY-FAIL: policy config parsing failed, not loading module %s\n", moduleName);
791
0
        }
792
0
        return NULL;
793
0
    }
794
0
795
0
    mod = secmod_NewModule();
796
0
    if (mod == NULL)
797
0
        return NULL;
798
0
799
0
    mod->commonName = PORT_ArenaStrdup(mod->arena, moduleName ? moduleName : "");
800
0
    if (library) {
801
0
        mod->dllName = PORT_ArenaStrdup(mod->arena, library);
802
0
    }
803
0
    /* new field */
804
0
    if (parameters) {
805
0
        mod->libraryParams = PORT_ArenaStrdup(mod->arena, parameters);
806
0
    }
807
0
808
0
    mod->internal = NSSUTIL_ArgHasFlag("flags", "internal", nssc);
809
0
    mod->isFIPS = NSSUTIL_ArgHasFlag("flags", "FIPS", nssc);
810
0
    mod->isCritical = NSSUTIL_ArgHasFlag("flags", "critical", nssc);
811
0
    slotParams = NSSUTIL_ArgGetParamValue("slotParams", nssc);
812
0
    mod->slotInfo = NSSUTIL_ArgParseSlotInfo(mod->arena, slotParams,
813
0
                                             &mod->slotInfoCount);
814
0
    if (slotParams)
815
0
        PORT_Free(slotParams);
816
0
    /* new field */
817
0
    mod->trustOrder = NSSUTIL_ArgReadLong("trustOrder", nssc,
818
0
                                          NSSUTIL_DEFAULT_TRUST_ORDER, NULL);
819
0
    /* new field */
820
0
    mod->cipherOrder = NSSUTIL_ArgReadLong("cipherOrder", nssc,
821
0
                                           NSSUTIL_DEFAULT_CIPHER_ORDER, NULL);
822
0
    /* new field */
823
0
    mod->isModuleDB = NSSUTIL_ArgHasFlag("flags", "moduleDB", nssc);
824
0
    mod->moduleDBOnly = NSSUTIL_ArgHasFlag("flags", "moduleDBOnly", nssc);
825
0
    if (mod->moduleDBOnly)
826
0
        mod->isModuleDB = PR_TRUE;
827
0
828
0
    /* we need more bits, but we also want to preserve binary compatibility
829
0
     * so we overload the isModuleDB PRBool with additional flags.
830
0
     * These flags are only valid if mod->isModuleDB is already set.
831
0
     * NOTE: this depends on the fact that PRBool is at least a char on
832
0
     * all platforms. These flags are only valid if moduleDB is set, so
833
0
     * code checking if (mod->isModuleDB) will continue to work correctly. */
834
0
    if (mod->isModuleDB) {
835
0
        char flags = SECMOD_FLAG_MODULE_DB_IS_MODULE_DB;
836
0
        if (NSSUTIL_ArgHasFlag("flags", "skipFirst", nssc)) {
837
0
            flags |= SECMOD_FLAG_MODULE_DB_SKIP_FIRST;
838
0
        }
839
0
        if (NSSUTIL_ArgHasFlag("flags", "defaultModDB", nssc)) {
840
0
            flags |= SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB;
841
0
        }
842
0
        if (NSSUTIL_ArgHasFlag("flags", "policyOnly", nssc)) {
843
0
            flags |= SECMOD_FLAG_MODULE_DB_POLICY_ONLY;
844
0
        }
845
0
        /* additional moduleDB flags could be added here in the future */
846
0
        mod->isModuleDB = (PRBool)flags;
847
0
    }
848
0
849
0
    if (mod->internal) {
850
0
        char flags = SECMOD_FLAG_INTERNAL_IS_INTERNAL;
851
0
852
0
        if (NSSUTIL_ArgHasFlag("flags", "internalKeySlot", nssc)) {
853
0
            flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT;
854
0
        }
855
0
        mod->internal = (PRBool)flags;
856
0
    }
857
0
858
0
    ciphers = NSSUTIL_ArgGetParamValue("ciphers", nssc);
859
0
    NSSUTIL_ArgParseCipherFlags(&mod->ssl[0], ciphers);
860
0
    if (ciphers)
861
0
        PORT_Free(ciphers);
862
0
863
0
    secmod_PrivateModuleCount++;
864
0
865
0
    return mod;
866
0
}
867
868
PRBool
869
SECMOD_GetSkipFirstFlag(SECMODModule *mod)
870
0
{
871
0
    char flags = (char)mod->isModuleDB;
872
0
873
0
    return (flags & SECMOD_FLAG_MODULE_DB_SKIP_FIRST) ? PR_TRUE : PR_FALSE;
874
0
}
875
876
PRBool
877
SECMOD_GetDefaultModDBFlag(SECMODModule *mod)
878
0
{
879
0
    char flags = (char)mod->isModuleDB;
880
0
881
0
    return (flags & SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB) ? PR_TRUE : PR_FALSE;
882
0
}
883
884
PRBool
885
secmod_PolicyOnly(SECMODModule *mod)
886
0
{
887
0
    char flags = (char)mod->isModuleDB;
888
0
889
0
    return (flags & SECMOD_FLAG_MODULE_DB_POLICY_ONLY) ? PR_TRUE : PR_FALSE;
890
0
}
891
892
PRBool
893
secmod_IsInternalKeySlot(SECMODModule *mod)
894
0
{
895
0
    char flags = (char)mod->internal;
896
0
897
0
    return (flags & SECMOD_FLAG_INTERNAL_KEY_SLOT) ? PR_TRUE : PR_FALSE;
898
0
}
899
900
void
901
secmod_SetInternalKeySlotFlag(SECMODModule *mod, PRBool val)
902
0
{
903
0
    char flags = (char)mod->internal;
904
0
905
0
    if (val) {
906
0
        flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT;
907
0
    } else {
908
0
        flags &= ~SECMOD_FLAG_INTERNAL_KEY_SLOT;
909
0
    }
910
0
    mod->internal = flags;
911
0
}
912
913
/*
914
 * copy desc and value into target. Target is known to be big enough to
915
 * hold desc +2 +value, which is good because the result of this will be
916
 * *desc"*value". We may, however, have to add some escapes for special
917
 * characters imbedded into value (rare). This string potentially comes from
918
 * a user, so we don't want the user overflowing the target buffer by using
919
 * excessive escapes. To prevent this we count the escapes we need to add and
920
 * try to expand the buffer with Realloc.
921
 */
922
static char *
923
secmod_doDescCopy(char *target, int *targetLen, const char *desc,
924
                  int descLen, char *value)
925
0
{
926
0
    int diff, esc_len;
927
0
928
0
    esc_len = NSSUTIL_EscapeSize(value, '\"') - 1;
929
0
    diff = esc_len - strlen(value);
930
0
    if (diff > 0) {
931
0
        /* we need to escape... expand newSpecPtr as well to make sure
932
0
         * we don't overflow it */
933
0
        char *newPtr = PORT_Realloc(target, *targetLen * diff);
934
0
        if (!newPtr) {
935
0
            return target; /* not enough space, just drop the whole copy */
936
0
        }
937
0
        *targetLen += diff;
938
0
        target = newPtr;
939
0
        value = NSSUTIL_Escape(value, '\"');
940
0
        if (value == NULL) {
941
0
            return target; /* couldn't escape value, just drop the copy */
942
0
        }
943
0
    }
944
0
    PORT_Memcpy(target, desc, descLen);
945
0
    target += descLen;
946
0
    *target++ = '\"';
947
0
    PORT_Memcpy(target, value, esc_len);
948
0
    target += esc_len;
949
0
    *target++ = '\"';
950
0
    if (diff > 0) {
951
0
        PORT_Free(value);
952
0
    }
953
0
    return target;
954
0
}
955
956
#define SECMOD_SPEC_COPY(new, start, end) \
957
0
    if (end > start) {                    \
958
0
        int _cnt = end - start;           \
959
0
        PORT_Memcpy(new, start, _cnt);    \
960
0
        new += _cnt;                      \
961
0
    }
962
#define SECMOD_TOKEN_DESCRIPTION "tokenDescription="
963
#define SECMOD_SLOT_DESCRIPTION "slotDescription="
964
965
/*
966
 * Find any tokens= values in the module spec.
967
 * Always return a new spec which does not have any tokens= arguments.
968
 * If tokens= arguments are found, Split the the various tokens defined into
969
 * an array of child specs to return.
970
 *
971
 * Caller is responsible for freeing the child spec and the new token
972
 * spec.
973
 */
974
char *
975
secmod_ParseModuleSpecForTokens(PRBool convert, PRBool isFIPS,
976
                                const char *moduleSpec, char ***children,
977
                                CK_SLOT_ID **ids)
978
0
{
979
0
    int newSpecLen = PORT_Strlen(moduleSpec) + 2;
980
0
    char *newSpec = PORT_Alloc(newSpecLen);
981
0
    char *newSpecPtr = newSpec;
982
0
    const char *modulePrev = moduleSpec;
983
0
    char *target = NULL;
984
0
    char *tmp = NULL;
985
0
    char **childArray = NULL;
986
0
    const char *tokenIndex;
987
0
    CK_SLOT_ID *idArray = NULL;
988
0
    int tokenCount = 0;
989
0
    int i;
990
0
991
0
    if (newSpec == NULL) {
992
0
        return NULL;
993
0
    }
994
0
995
0
    *children = NULL;
996
0
    if (ids) {
997
0
        *ids = NULL;
998
0
    }
999
0
    moduleSpec = NSSUTIL_ArgStrip(moduleSpec);
1000
0
    SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec);
1001
0
1002
0
    /* Notes on 'convert' and 'isFIPS' flags: The base parameters for opening
1003
0
     * a new softoken module takes the following parameters to name the
1004
0
     * various tokens:
1005
0
     *
1006
0
     *  cryptoTokenDescription: name of the non-fips crypto token.
1007
0
     *  cryptoSlotDescription: name of the non-fips crypto slot.
1008
0
     *  dbTokenDescription: name of the non-fips db token.
1009
0
     *  dbSlotDescription: name of the non-fips db slot.
1010
0
     *  FIPSTokenDescription: name of the fips db/crypto token.
1011
0
     *  FIPSSlotDescription: name of the fips db/crypto slot.
1012
0
     *
1013
0
     * if we are opening a new slot, we need to have the following
1014
0
     * parameters:
1015
0
     *  tokenDescription: name of the token.
1016
0
     *  slotDescription: name of the slot.
1017
0
     *
1018
0
     *
1019
0
     * The convert flag tells us to drop the unnecessary *TokenDescription
1020
0
     * and *SlotDescription arguments and convert the appropriate pair
1021
0
     * (either db or FIPS based on the isFIPS flag) to tokenDescription and
1022
0
     * slotDescription).
1023
0
     */
1024
0
    /*
1025
0
     * walk down the list. if we find a tokens= argument, save it,
1026
0
     * otherise copy the argument.
1027
0
     */
1028
0
    while (*moduleSpec) {
1029
0
        int next;
1030
0
        modulePrev = moduleSpec;
1031
0
        NSSUTIL_HANDLE_STRING_ARG(moduleSpec, target, "tokens=",
1032
0
                                  modulePrev = moduleSpec;
1033
0
                                  /* skip copying */)
1034
0
        NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "cryptoTokenDescription=",
1035
0
                                  if (convert) { modulePrev = moduleSpec; });
1036
0
        NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "cryptoSlotDescription=",
1037
0
                                  if (convert) { modulePrev = moduleSpec; });
1038
0
        NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "dbTokenDescription=",
1039
0
                                  if (convert) {
1040
0
                                      modulePrev = moduleSpec;
1041
0
                                      if (!isFIPS) {
1042
0
                                          newSpecPtr = secmod_doDescCopy(newSpecPtr,
1043
0
                                                                         &newSpecLen,
1044
0
                                                                         SECMOD_TOKEN_DESCRIPTION,
1045
0
                                                                         sizeof(SECMOD_TOKEN_DESCRIPTION) - 1,
1046
0
                                                                         tmp);
1047
0
                                      }
1048
0
                                  });
1049
0
        NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "dbSlotDescription=",
1050
0
                                  if (convert) {
1051
0
                                      modulePrev = moduleSpec; /* skip copying */
1052
0
                                      if (!isFIPS) {
1053
0
                                          newSpecPtr = secmod_doDescCopy(newSpecPtr,
1054
0
                                                                         &newSpecLen,
1055
0
                                                                         SECMOD_SLOT_DESCRIPTION,
1056
0
                                                                         sizeof(SECMOD_SLOT_DESCRIPTION) - 1,
1057
0
                                                                         tmp);
1058
0
                                      }
1059
0
                                  });
1060
0
        NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "FIPSTokenDescription=",
1061
0
                                  if (convert) {
1062
0
                                      modulePrev = moduleSpec; /* skip copying */
1063
0
                                      if (isFIPS) {
1064
0
                                          newSpecPtr = secmod_doDescCopy(newSpecPtr,
1065
0
                                                                         &newSpecLen,
1066
0
                                                                         SECMOD_TOKEN_DESCRIPTION,
1067
0
                                                                         sizeof(SECMOD_TOKEN_DESCRIPTION) - 1,
1068
0
                                                                         tmp);
1069
0
                                      }
1070
0
                                  });
1071
0
        NSSUTIL_HANDLE_STRING_ARG(moduleSpec, tmp, "FIPSSlotDescription=",
1072
0
                                  if (convert) {
1073
0
                                      modulePrev = moduleSpec; /* skip copying */
1074
0
                                      if (isFIPS) {
1075
0
                                          newSpecPtr = secmod_doDescCopy(newSpecPtr,
1076
0
                                                                         &newSpecLen,
1077
0
                                                                         SECMOD_SLOT_DESCRIPTION,
1078
0
                                                                         sizeof(SECMOD_SLOT_DESCRIPTION) - 1,
1079
0
                                                                         tmp);
1080
0
                                      }
1081
0
                                  });
1082
0
        NSSUTIL_HANDLE_FINAL_ARG(moduleSpec)
1083
0
        SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec);
1084
0
    }
1085
0
    if (tmp) {
1086
0
        PORT_Free(tmp);
1087
0
        tmp = NULL;
1088
0
    }
1089
0
    *newSpecPtr = 0;
1090
0
1091
0
    /* no target found, return the newSpec */
1092
0
    if (target == NULL) {
1093
0
        return newSpec;
1094
0
    }
1095
0
1096
0
    /* now build the child array from target */
1097
0
    /*first count them */
1098
0
    for (tokenIndex = NSSUTIL_ArgStrip(target); *tokenIndex;
1099
0
         tokenIndex = NSSUTIL_ArgStrip(NSSUTIL_ArgSkipParameter(tokenIndex))) {
1100
0
        tokenCount++;
1101
0
    }
1102
0
1103
0
    childArray = PORT_NewArray(char *, tokenCount + 1);
1104
0
    if (childArray == NULL) {
1105
0
        /* just return the spec as is then */
1106
0
        PORT_Free(target);
1107
0
        return newSpec;
1108
0
    }
1109
0
    if (ids) {
1110
0
        idArray = PORT_NewArray(CK_SLOT_ID, tokenCount + 1);
1111
0
        if (idArray == NULL) {
1112
0
            PORT_Free(childArray);
1113
0
            PORT_Free(target);
1114
0
            return newSpec;
1115
0
        }
1116
0
    }
1117
0
1118
0
    /* now fill them in */
1119
0
    for (tokenIndex = NSSUTIL_ArgStrip(target), i = 0;
1120
0
         *tokenIndex && (i < tokenCount);
1121
0
         tokenIndex = NSSUTIL_ArgStrip(tokenIndex)) {
1122
0
        int next;
1123
0
        char *name = NSSUTIL_ArgGetLabel(tokenIndex, &next);
1124
0
        tokenIndex += next;
1125
0
1126
0
        if (idArray) {
1127
0
            idArray[i] = NSSUTIL_ArgDecodeNumber(name);
1128
0
        }
1129
0
1130
0
        PORT_Free(name); /* drop the explicit number */
1131
0
1132
0
        /* if anything is left, copy the args to the child array */
1133
0
        if (!NSSUTIL_ArgIsBlank(*tokenIndex)) {
1134
0
            childArray[i++] = NSSUTIL_ArgFetchValue(tokenIndex, &next);
1135
0
            tokenIndex += next;
1136
0
        }
1137
0
    }
1138
0
1139
0
    PORT_Free(target);
1140
0
    childArray[i] = 0;
1141
0
    if (idArray) {
1142
0
        idArray[i] = 0;
1143
0
    }
1144
0
1145
0
    /* return it */
1146
0
    *children = childArray;
1147
0
    if (ids) {
1148
0
        *ids = idArray;
1149
0
    }
1150
0
    return newSpec;
1151
0
}
1152
1153
/* get the database and flags from the spec */
1154
static char *
1155
secmod_getConfigDir(const char *spec, char **certPrefix, char **keyPrefix,
1156
                    PRBool *readOnly)
1157
0
{
1158
0
    char *config = NULL;
1159
0
1160
0
    *certPrefix = NULL;
1161
0
    *keyPrefix = NULL;
1162
0
    *readOnly = NSSUTIL_ArgHasFlag("flags", "readOnly", spec);
1163
0
    if (NSSUTIL_ArgHasFlag("flags", "nocertdb", spec) ||
1164
0
        NSSUTIL_ArgHasFlag("flags", "nokeydb", spec)) {
1165
0
        return NULL;
1166
0
    }
1167
0
1168
0
    spec = NSSUTIL_ArgStrip(spec);
1169
0
    while (*spec) {
1170
0
        int next;
1171
0
        NSSUTIL_HANDLE_STRING_ARG(spec, config, "configdir=", ;)
1172
0
        NSSUTIL_HANDLE_STRING_ARG(spec, *certPrefix, "certPrefix=", ;)
1173
0
        NSSUTIL_HANDLE_STRING_ARG(spec, *keyPrefix, "keyPrefix=", ;)
1174
0
        NSSUTIL_HANDLE_FINAL_ARG(spec)
1175
0
    }
1176
0
    return config;
1177
0
}
1178
1179
struct SECMODConfigListStr {
1180
    char *config;
1181
    char *certPrefix;
1182
    char *keyPrefix;
1183
    PRBool isReadOnly;
1184
};
1185
1186
/*
1187
 * return an array of already openned databases from a spec list.
1188
 */
1189
SECMODConfigList *
1190
secmod_GetConfigList(PRBool isFIPS, char *spec, int *count)
1191
0
{
1192
0
    char **children;
1193
0
    CK_SLOT_ID *ids;
1194
0
    char *strippedSpec;
1195
0
    int childCount;
1196
0
    SECMODConfigList *conflist = NULL;
1197
0
    int i;
1198
0
1199
0
    strippedSpec = secmod_ParseModuleSpecForTokens(PR_TRUE, isFIPS,
1200
0
                                                   spec, &children, &ids);
1201
0
    if (strippedSpec == NULL) {
1202
0
        return NULL;
1203
0
    }
1204
0
1205
0
    for (childCount = 0; children && children[childCount]; childCount++)
1206
0
        ;
1207
0
    *count = childCount + 1; /* include strippedSpec */
1208
0
    conflist = PORT_NewArray(SECMODConfigList, *count);
1209
0
    if (conflist == NULL) {
1210
0
        *count = 0;
1211
0
        goto loser;
1212
0
    }
1213
0
1214
0
    conflist[0].config = secmod_getConfigDir(strippedSpec,
1215
0
                                             &conflist[0].certPrefix,
1216
0
                                             &conflist[0].keyPrefix,
1217
0
                                             &conflist[0].isReadOnly);
1218
0
    for (i = 0; i < childCount; i++) {
1219
0
        conflist[i + 1].config = secmod_getConfigDir(children[i],
1220
0
                                                     &conflist[i + 1].certPrefix,
1221
0
                                                     &conflist[i + 1].keyPrefix,
1222
0
                                                     &conflist[i + 1].isReadOnly);
1223
0
    }
1224
0
1225
0
loser:
1226
0
    secmod_FreeChildren(children, ids);
1227
0
    PORT_Free(strippedSpec);
1228
0
    return conflist;
1229
0
}
1230
1231
/*
1232
 * determine if we are trying to open an old dbm database. For this test
1233
 * RDB databases should return PR_FALSE.
1234
 */
1235
static PRBool
1236
secmod_configIsDBM(char *configDir)
1237
{
1238
    char *env;
1239
1240
    /* explicit dbm open */
1241
    if (strncmp(configDir, "dbm:", 4) == 0) {
1242
        return PR_TRUE;
1243
    }
1244
    /* explicit open of a non-dbm database */
1245
    if ((strncmp(configDir, "sql:", 4) == 0) ||
1246
        (strncmp(configDir, "rdb:", 4) == 0) ||
1247
        (strncmp(configDir, "extern:", 7) == 0)) {
1248
        return PR_FALSE;
1249
    }
1250
    env = PR_GetEnvSecure("NSS_DEFAULT_DB_TYPE");
1251
    /* implicit dbm open */
1252
    if ((env == NULL) || (strcmp(env, "dbm") == 0)) {
1253
        return PR_TRUE;
1254
    }
1255
    /* implicit non-dbm open */
1256
    return PR_FALSE;
1257
}
1258
1259
/*
1260
 * match two prefixes. prefix may be NULL. NULL patches '\0'
1261
 */
1262
static PRBool
1263
secmod_matchPrefix(char *prefix1, char *prefix2)
1264
0
{
1265
0
    if ((prefix1 == NULL) || (*prefix1 == 0)) {
1266
0
        if ((prefix2 == NULL) || (*prefix2 == 0)) {
1267
0
            return PR_TRUE;
1268
0
        }
1269
0
        return PR_FALSE;
1270
0
    }
1271
0
    if (strcmp(prefix1, prefix2) == 0) {
1272
0
        return PR_TRUE;
1273
0
    }
1274
0
    return PR_FALSE;
1275
0
}
1276
1277
/* do two config paramters match? Not all callers are compariing
1278
 * SECMODConfigLists directly, so this function breaks them out to their
1279
 * components. */
1280
static PRBool
1281
secmod_matchConfig(char *configDir1, char *configDir2,
1282
                   char *certPrefix1, char *certPrefix2,
1283
                   char *keyPrefix1, char *keyPrefix2,
1284
                   PRBool isReadOnly1, PRBool isReadOnly2)
1285
0
{
1286
0
    /* TODO: Document the answer to the question:
1287
0
     *       "Why not allow them to match if they are both NULL?"
1288
0
     * See: https://bugzilla.mozilla.org/show_bug.cgi?id=1318633#c1
1289
0
     */
1290
0
    if ((configDir1 == NULL) || (configDir2 == NULL)) {
1291
0
        return PR_FALSE;
1292
0
    }
1293
0
    if (strcmp(configDir1, configDir2) != 0) {
1294
0
        return PR_FALSE;
1295
0
    }
1296
0
    if (!secmod_matchPrefix(certPrefix1, certPrefix2)) {
1297
0
        return PR_FALSE;
1298
0
    }
1299
0
    if (!secmod_matchPrefix(keyPrefix1, keyPrefix2)) {
1300
0
        return PR_FALSE;
1301
0
    }
1302
0
    /* these last test -- if we just need the DB open read only,
1303
0
     * than any open will suffice, but if we requested it read/write
1304
0
     * and it's only open read only, we need to open it again */
1305
0
    if (isReadOnly1) {
1306
0
        return PR_TRUE;
1307
0
    }
1308
0
    if (isReadOnly2) { /* isReadonly1 == PR_FALSE */
1309
0
        return PR_FALSE;
1310
0
    }
1311
0
    return PR_TRUE;
1312
0
}
1313
1314
/*
1315
 * return true if we are requesting a database that is already openned.
1316
 */
1317
PRBool
1318
secmod_MatchConfigList(const char *spec, SECMODConfigList *conflist, int count)
1319
0
{
1320
0
    char *config;
1321
0
    char *certPrefix;
1322
0
    char *keyPrefix;
1323
0
    PRBool isReadOnly;
1324
0
    PRBool ret = PR_FALSE;
1325
0
    int i;
1326
0
1327
0
    config = secmod_getConfigDir(spec, &certPrefix, &keyPrefix, &isReadOnly);
1328
0
    if (!config) {
1329
0
        goto done;
1330
0
    }
1331
0
1332
0
    /* NOTE: we dbm isn't multiple open safe. If we open the same database
1333
0
     * twice from two different locations, then we can corrupt our database
1334
0
     * (the cache will be inconsistent). Protect against this by claiming
1335
0
     * for comparison only that we are always openning dbm databases read only.
1336
0
     */
1337
0
    if (secmod_configIsDBM(config)) {
1338
0
        isReadOnly = 1;
1339
0
    }
1340
0
    for (i = 0; i < count; i++) {
1341
0
        if (secmod_matchConfig(config, conflist[i].config, certPrefix,
1342
0
                               conflist[i].certPrefix, keyPrefix,
1343
0
                               conflist[i].keyPrefix, isReadOnly,
1344
0
                               conflist[i].isReadOnly)) {
1345
0
            ret = PR_TRUE;
1346
0
            goto done;
1347
0
        }
1348
0
    }
1349
0
1350
0
    ret = PR_FALSE;
1351
0
done:
1352
0
    PORT_Free(config);
1353
0
    PORT_Free(certPrefix);
1354
0
    PORT_Free(keyPrefix);
1355
0
    return ret;
1356
0
}
1357
1358
/*
1359
 * Find the slot id from the module spec. If the slot is the database slot, we
1360
 * can get the slot id from the default database slot.
1361
 */
1362
CK_SLOT_ID
1363
secmod_GetSlotIDFromModuleSpec(const char *moduleSpec, SECMODModule *module)
1364
0
{
1365
0
    char *tmp_spec = NULL;
1366
0
    char **children, **thisChild;
1367
0
    CK_SLOT_ID *ids, *thisID, slotID = -1;
1368
0
    char *inConfig = NULL, *thisConfig = NULL;
1369
0
    char *inCertPrefix = NULL, *thisCertPrefix = NULL;
1370
0
    char *inKeyPrefix = NULL, *thisKeyPrefix = NULL;
1371
0
    PRBool inReadOnly, thisReadOnly;
1372
0
1373
0
    inConfig = secmod_getConfigDir(moduleSpec, &inCertPrefix, &inKeyPrefix,
1374
0
                                   &inReadOnly);
1375
0
    if (!inConfig) {
1376
0
        goto done;
1377
0
    }
1378
0
1379
0
    if (secmod_configIsDBM(inConfig)) {
1380
0
        inReadOnly = 1;
1381
0
    }
1382
0
1383
0
    tmp_spec = secmod_ParseModuleSpecForTokens(PR_TRUE, module->isFIPS,
1384
0
                                               module->libraryParams, &children, &ids);
1385
0
    if (tmp_spec == NULL) {
1386
0
        goto done;
1387
0
    }
1388
0
1389
0
    /* first check to see if the parent is the database */
1390
0
    thisConfig = secmod_getConfigDir(tmp_spec, &thisCertPrefix, &thisKeyPrefix,
1391
0
                                     &thisReadOnly);
1392
0
    if (!thisConfig) {
1393
0
        goto done;
1394
0
    }
1395
0
    if (secmod_matchConfig(inConfig, thisConfig, inCertPrefix, thisCertPrefix,
1396
0
                           inKeyPrefix, thisKeyPrefix, inReadOnly, thisReadOnly)) {
1397
0
        /* yup it's the default key slot, get the id for it */
1398
0
        PK11SlotInfo *slot = PK11_GetInternalKeySlot();
1399
0
        if (slot) {
1400
0
            slotID = slot->slotID;
1401
0
            PK11_FreeSlot(slot);
1402
0
        }
1403
0
        goto done;
1404
0
    }
1405
0
1406
0
    /* find id of the token */
1407
0
    for (thisChild = children, thisID = ids; thisChild && *thisChild; thisChild++, thisID++) {
1408
0
        PORT_Free(thisConfig);
1409
0
        PORT_Free(thisCertPrefix);
1410
0
        PORT_Free(thisKeyPrefix);
1411
0
        thisConfig = secmod_getConfigDir(*thisChild, &thisCertPrefix,
1412
0
                                         &thisKeyPrefix, &thisReadOnly);
1413
0
        if (thisConfig == NULL) {
1414
0
            continue;
1415
0
        }
1416
0
        if (secmod_matchConfig(inConfig, thisConfig, inCertPrefix, thisCertPrefix,
1417
0
                               inKeyPrefix, thisKeyPrefix, inReadOnly, thisReadOnly)) {
1418
0
            slotID = *thisID;
1419
0
            break;
1420
0
        }
1421
0
    }
1422
0
1423
0
done:
1424
0
    PORT_Free(inConfig);
1425
0
    PORT_Free(inCertPrefix);
1426
0
    PORT_Free(inKeyPrefix);
1427
0
    PORT_Free(thisConfig);
1428
0
    PORT_Free(thisCertPrefix);
1429
0
    PORT_Free(thisKeyPrefix);
1430
0
    if (tmp_spec) {
1431
0
        secmod_FreeChildren(children, ids);
1432
0
        PORT_Free(tmp_spec);
1433
0
    }
1434
0
    return slotID;
1435
0
}
1436
1437
void
1438
secmod_FreeConfigList(SECMODConfigList *conflist, int count)
1439
0
{
1440
0
    int i;
1441
0
    for (i = 0; i < count; i++) {
1442
0
        PORT_Free(conflist[i].config);
1443
0
        PORT_Free(conflist[i].certPrefix);
1444
0
        PORT_Free(conflist[i].keyPrefix);
1445
0
    }
1446
0
    PORT_Free(conflist);
1447
0
}
1448
1449
void
1450
secmod_FreeChildren(char **children, CK_SLOT_ID *ids)
1451
0
{
1452
0
    char **thisChild;
1453
0
1454
0
    if (!children) {
1455
0
        return;
1456
0
    }
1457
0
1458
0
    for (thisChild = children; thisChild && *thisChild; thisChild++) {
1459
0
        PORT_Free(*thisChild);
1460
0
    }
1461
0
    PORT_Free(children);
1462
0
    if (ids) {
1463
0
        PORT_Free(ids);
1464
0
    }
1465
0
    return;
1466
0
}
1467
1468
/*
1469
 * caclulate the length of each child record:
1470
 * " 0x{id}=<{escaped_child}>"
1471
 */
1472
static int
1473
secmod_getChildLength(char *child, CK_SLOT_ID id)
1474
0
{
1475
0
    int length = NSSUTIL_DoubleEscapeSize(child, '>', ']');
1476
0
    if (id == 0) {
1477
0
        length++;
1478
0
    }
1479
0
    while (id) {
1480
0
        length++;
1481
0
        id = id >> 4;
1482
0
    }
1483
0
    length += 6; /* {sp}0x[id]=<{child}> */
1484
0
    return length;
1485
0
}
1486
1487
/*
1488
 * Build a child record:
1489
 * " 0x{id}=<{escaped_child}>"
1490
 */
1491
static SECStatus
1492
secmod_mkTokenChild(char **next, int *length, char *child, CK_SLOT_ID id)
1493
0
{
1494
0
    int len;
1495
0
    char *escSpec;
1496
0
1497
0
    len = PR_snprintf(*next, *length, " 0x%x=<", id);
1498
0
    if (len < 0) {
1499
0
        return SECFailure;
1500
0
    }
1501
0
    *next += len;
1502
0
    *length -= len;
1503
0
    escSpec = NSSUTIL_DoubleEscape(child, '>', ']');
1504
0
    if (escSpec == NULL) {
1505
0
        return SECFailure;
1506
0
    }
1507
0
    if (*child && (*escSpec == 0)) {
1508
0
        PORT_Free(escSpec);
1509
0
        return SECFailure;
1510
0
    }
1511
0
    len = strlen(escSpec);
1512
0
    if (len + 1 > *length) {
1513
0
        PORT_Free(escSpec);
1514
0
        return SECFailure;
1515
0
    }
1516
0
    PORT_Memcpy(*next, escSpec, len);
1517
0
    *next += len;
1518
0
    *length -= len;
1519
0
    PORT_Free(escSpec);
1520
0
    **next = '>';
1521
0
    (*next)++;
1522
0
    (*length)--;
1523
0
    return SECSuccess;
1524
0
}
1525
1526
0
#define TOKEN_STRING " tokens=["
1527
1528
char *
1529
secmod_MkAppendTokensList(PLArenaPool *arena, char *oldParam, char *newToken,
1530
                          CK_SLOT_ID newID, char **children, CK_SLOT_ID *ids)
1531
0
{
1532
0
    char *rawParam = NULL;  /* oldParam with tokens stripped off */
1533
0
    char *newParam = NULL;  /* space for the return parameter */
1534
0
    char *nextParam = NULL; /* current end of the new parameter */
1535
0
    char **oldChildren = NULL;
1536
0
    CK_SLOT_ID *oldIds = NULL;
1537
0
    void *mark = NULL; /* mark the arena pool in case we need
1538
0
                        * to release it */
1539
0
    int length, i, tmpLen;
1540
0
    SECStatus rv;
1541
0
1542
0
    /* first strip out and save the old tokenlist */
1543
0
    rawParam = secmod_ParseModuleSpecForTokens(PR_FALSE, PR_FALSE,
1544
0
                                               oldParam, &oldChildren, &oldIds);
1545
0
    if (!rawParam) {
1546
0
        goto loser;
1547
0
    }
1548
0
1549
0
    /* now calculate the total length of the new buffer */
1550
0
    /* First the 'fixed stuff', length of rawparam (does not include a NULL),
1551
0
     * length of the token string (does include the NULL), closing bracket */
1552
0
    length = strlen(rawParam) + sizeof(TOKEN_STRING) + 1;
1553
0
    /* now add then length of all the old children */
1554
0
    for (i = 0; oldChildren && oldChildren[i]; i++) {
1555
0
        length += secmod_getChildLength(oldChildren[i], oldIds[i]);
1556
0
    }
1557
0
1558
0
    /* add the new token */
1559
0
    length += secmod_getChildLength(newToken, newID);
1560
0
1561
0
    /* and it's new children */
1562
0
    for (i = 0; children && children[i]; i++) {
1563
0
        if (ids[i] == -1) {
1564
0
            continue;
1565
0
        }
1566
0
        length += secmod_getChildLength(children[i], ids[i]);
1567
0
    }
1568
0
1569
0
    /* now allocate and build the string */
1570
0
    mark = PORT_ArenaMark(arena);
1571
0
    if (!mark) {
1572
0
        goto loser;
1573
0
    }
1574
0
    newParam = PORT_ArenaAlloc(arena, length);
1575
0
    if (!newParam) {
1576
0
        goto loser;
1577
0
    }
1578
0
1579
0
    PORT_Strcpy(newParam, oldParam);
1580
0
    tmpLen = strlen(oldParam);
1581
0
    nextParam = newParam + tmpLen;
1582
0
    length -= tmpLen;
1583
0
    PORT_Memcpy(nextParam, TOKEN_STRING, sizeof(TOKEN_STRING) - 1);
1584
0
    nextParam += sizeof(TOKEN_STRING) - 1;
1585
0
    length -= sizeof(TOKEN_STRING) - 1;
1586
0
1587
0
    for (i = 0; oldChildren && oldChildren[i]; i++) {
1588
0
        rv = secmod_mkTokenChild(&nextParam, &length, oldChildren[i], oldIds[i]);
1589
0
        if (rv != SECSuccess) {
1590
0
            goto loser;
1591
0
        }
1592
0
    }
1593
0
1594
0
    rv = secmod_mkTokenChild(&nextParam, &length, newToken, newID);
1595
0
    if (rv != SECSuccess) {
1596
0
        goto loser;
1597
0
    }
1598
0
1599
0
    for (i = 0; children && children[i]; i++) {
1600
0
        if (ids[i] == -1) {
1601
0
            continue;
1602
0
        }
1603
0
        rv = secmod_mkTokenChild(&nextParam, &length, children[i], ids[i]);
1604
0
        if (rv != SECSuccess) {
1605
0
            goto loser;
1606
0
        }
1607
0
    }
1608
0
1609
0
    if (length < 2) {
1610
0
        goto loser;
1611
0
    }
1612
0
1613
0
    *nextParam++ = ']';
1614
0
    *nextParam++ = 0;
1615
0
1616
0
    /* we are going to return newParam now, don't release the mark */
1617
0
    PORT_ArenaUnmark(arena, mark);
1618
0
    mark = NULL;
1619
0
1620
0
loser:
1621
0
    if (mark) {
1622
0
        PORT_ArenaRelease(arena, mark);
1623
0
        newParam = NULL; /* if the mark is still active,
1624
0
                          * don't return the param */
1625
0
    }
1626
0
    if (rawParam) {
1627
0
        PORT_Free(rawParam);
1628
0
    }
1629
0
    if (oldChildren) {
1630
0
        secmod_FreeChildren(oldChildren, oldIds);
1631
0
    }
1632
0
    return newParam;
1633
0
}
1634
1635
static char *
1636
secmod_mkModuleSpec(SECMODModule *module)
1637
0
{
1638
0
    char *nss = NULL, *modSpec = NULL, **slotStrings = NULL;
1639
0
    int slotCount, i, si;
1640
0
    SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
1641
0
1642
0
    /* allocate target slot info strings */
1643
0
    slotCount = 0;
1644
0
1645
0
    SECMOD_GetReadLock(moduleLock);
1646
0
    if (module->slotCount) {
1647
0
        for (i = 0; i < module->slotCount; i++) {
1648
0
            if (module->slots[i]->defaultFlags != 0) {
1649
0
                slotCount++;
1650
0
            }
1651
0
        }
1652
0
    } else {
1653
0
        slotCount = module->slotInfoCount;
1654
0
    }
1655
0
1656
0
    slotStrings = (char **)PORT_ZAlloc(slotCount * sizeof(char *));
1657
0
    if (slotStrings == NULL) {
1658
0
        SECMOD_ReleaseReadLock(moduleLock);
1659
0
        goto loser;
1660
0
    }
1661
0
1662
0
    /* build the slot info strings */
1663
0
    if (module->slotCount) {
1664
0
        for (i = 0, si = 0; i < module->slotCount; i++) {
1665
0
            if (module->slots[i]->defaultFlags) {
1666
0
                PORT_Assert(si < slotCount);
1667
0
                if (si >= slotCount)
1668
0
                    break;
1669
0
                slotStrings[si] = NSSUTIL_MkSlotString(module->slots[i]->slotID,
1670
0
                                                       module->slots[i]->defaultFlags,
1671
0
                                                       module->slots[i]->timeout,
1672
0
                                                       module->slots[i]->askpw,
1673
0
                                                       module->slots[i]->hasRootCerts,
1674
0
                                                       module->slots[i]->hasRootTrust);
1675
0
                si++;
1676
0
            }
1677
0
        }
1678
0
    } else {
1679
0
        for (i = 0; i < slotCount; i++) {
1680
0
            slotStrings[i] = NSSUTIL_MkSlotString(
1681
0
                module->slotInfo[i].slotID,
1682
0
                module->slotInfo[i].defaultFlags,
1683
0
                module->slotInfo[i].timeout,
1684
0
                module->slotInfo[i].askpw,
1685
0
                module->slotInfo[i].hasRootCerts,
1686
0
                module->slotInfo[i].hasRootTrust);
1687
0
        }
1688
0
    }
1689
0
1690
0
    SECMOD_ReleaseReadLock(moduleLock);
1691
0
    nss = NSSUTIL_MkNSSString(slotStrings, slotCount, module->internal,
1692
0
                              module->isFIPS, module->isModuleDB,
1693
0
                              module->moduleDBOnly, module->isCritical,
1694
0
                              module->trustOrder, module->cipherOrder,
1695
0
                              module->ssl[0], module->ssl[1]);
1696
0
    modSpec = NSSUTIL_MkModuleSpec(module->dllName, module->commonName,
1697
0
                                   module->libraryParams, nss);
1698
0
    PORT_Free(slotStrings);
1699
0
    PR_smprintf_free(nss);
1700
0
loser:
1701
0
    return (modSpec);
1702
0
}
1703
1704
char **
1705
SECMOD_GetModuleSpecList(SECMODModule *module)
1706
0
{
1707
0
    SECMODModuleDBFunc func = (SECMODModuleDBFunc)module->moduleDBFunc;
1708
0
    if (func) {
1709
0
        return (*func)(SECMOD_MODULE_DB_FUNCTION_FIND,
1710
0
                       module->libraryParams, NULL);
1711
0
    }
1712
0
    return NULL;
1713
0
}
1714
1715
SECStatus
1716
SECMOD_AddPermDB(SECMODModule *module)
1717
0
{
1718
0
    SECMODModuleDBFunc func;
1719
0
    char *moduleSpec;
1720
0
    char **retString;
1721
0
1722
0
    if (module->parent == NULL)
1723
0
        return SECFailure;
1724
0
1725
0
    func = (SECMODModuleDBFunc)module->parent->moduleDBFunc;
1726
0
    if (func) {
1727
0
        moduleSpec = secmod_mkModuleSpec(module);
1728
0
        retString = (*func)(SECMOD_MODULE_DB_FUNCTION_ADD,
1729
0
                            module->parent->libraryParams, moduleSpec);
1730
0
        PORT_Free(moduleSpec);
1731
0
        if (retString != NULL)
1732
0
            return SECSuccess;
1733
0
    }
1734
0
    return SECFailure;
1735
0
}
1736
1737
SECStatus
1738
SECMOD_DeletePermDB(SECMODModule *module)
1739
0
{
1740
0
    SECMODModuleDBFunc func;
1741
0
    char *moduleSpec;
1742
0
    char **retString;
1743
0
1744
0
    if (module->parent == NULL)
1745
0
        return SECFailure;
1746
0
1747
0
    func = (SECMODModuleDBFunc)module->parent->moduleDBFunc;
1748
0
    if (func) {
1749
0
        moduleSpec = secmod_mkModuleSpec(module);
1750
0
        retString = (*func)(SECMOD_MODULE_DB_FUNCTION_DEL,
1751
0
                            module->parent->libraryParams, moduleSpec);
1752
0
        PORT_Free(moduleSpec);
1753
0
        if (retString != NULL)
1754
0
            return SECSuccess;
1755
0
    }
1756
0
    return SECFailure;
1757
0
}
1758
1759
SECStatus
1760
SECMOD_FreeModuleSpecList(SECMODModule *module, char **moduleSpecList)
1761
0
{
1762
0
    SECMODModuleDBFunc func = (SECMODModuleDBFunc)module->moduleDBFunc;
1763
0
    char **retString;
1764
0
    if (func) {
1765
0
        retString = (*func)(SECMOD_MODULE_DB_FUNCTION_RELEASE,
1766
0
                            module->libraryParams, moduleSpecList);
1767
0
        if (retString != NULL)
1768
0
            return SECSuccess;
1769
0
    }
1770
0
    return SECFailure;
1771
0
}
1772
1773
/*
1774
 * load a PKCS#11 module but do not add it to the default NSS trust domain
1775
 */
1776
SECMODModule *
1777
SECMOD_LoadModule(char *modulespec, SECMODModule *parent, PRBool recurse)
1778
0
{
1779
0
    char *library = NULL, *moduleName = NULL, *parameters = NULL, *nss = NULL;
1780
0
    char *config = NULL;
1781
0
    SECStatus status;
1782
0
    SECMODModule *module = NULL;
1783
0
    SECMODModule *oldModule = NULL;
1784
0
    SECStatus rv;
1785
0
    PRBool forwardPolicyFeedback = PR_FALSE;
1786
0
1787
0
    /* initialize the underlying module structures */
1788
0
    SECMOD_Init();
1789
0
1790
0
    status = NSSUTIL_ArgParseModuleSpecEx(modulespec, &library, &moduleName,
1791
0
                                          &parameters, &nss,
1792
0
                                          &config);
1793
0
    if (status != SECSuccess) {
1794
0
        goto loser;
1795
0
    }
1796
0
1797
0
    module = SECMOD_CreateModuleEx(library, moduleName, parameters, nss, config);
1798
0
    forwardPolicyFeedback = NSSUTIL_ArgHasFlag("flags", "printPolicyFeedback", nss);
1799
0
    if (library)
1800
0
        PORT_Free(library);
1801
0
    if (moduleName)
1802
0
        PORT_Free(moduleName);
1803
0
    if (parameters)
1804
0
        PORT_Free(parameters);
1805
0
    if (nss)
1806
0
        PORT_Free(nss);
1807
0
    if (config)
1808
0
        PORT_Free(config);
1809
0
    if (!module) {
1810
0
        goto loser;
1811
0
    }
1812
0
1813
0
    /* a policy only stanza doesn't actually get 'loaded'. policy has already
1814
0
     * been parsed as a side effect of the CreateModuleEx call */
1815
0
    if (secmod_PolicyOnly(module)) {
1816
0
        return module;
1817
0
    }
1818
0
    if (parent) {
1819
0
        module->parent = SECMOD_ReferenceModule(parent);
1820
0
        if (module->internal && secmod_IsInternalKeySlot(parent)) {
1821
0
            module->internal = parent->internal;
1822
0
        }
1823
0
    }
1824
0
1825
0
    /* load it */
1826
0
    rv = secmod_LoadPKCS11Module(module, &oldModule);
1827
0
    if (rv != SECSuccess) {
1828
0
        goto loser;
1829
0
    }
1830
0
1831
0
    /* if we just reload an old module, no need to add it to any lists.
1832
0
     * we simple release all our references */
1833
0
    if (oldModule) {
1834
0
        /* This module already exists, don't link it anywhere. This
1835
0
         * will probably destroy this module */
1836
0
        SECMOD_DestroyModule(module);
1837
0
        return oldModule;
1838
0
    }
1839
0
1840
0
    if (recurse && module->isModuleDB) {
1841
0
        char **moduleSpecList;
1842
0
        PORT_SetError(0);
1843
0
1844
0
        moduleSpecList = SECMOD_GetModuleSpecList(module);
1845
0
        if (moduleSpecList) {
1846
0
            char **index;
1847
0
1848
0
            index = moduleSpecList;
1849
0
            if (*index && SECMOD_GetSkipFirstFlag(module)) {
1850
0
                index++;
1851
0
            }
1852
0
1853
0
            for (; *index; index++) {
1854
0
                SECMODModule *child;
1855
0
                if (0 == PORT_Strcmp(*index, modulespec)) {
1856
0
                    /* avoid trivial infinite recursion */
1857
0
                    PORT_SetError(SEC_ERROR_NO_MODULE);
1858
0
                    rv = SECFailure;
1859
0
                    break;
1860
0
                }
1861
0
                if (!forwardPolicyFeedback) {
1862
0
                    child = SECMOD_LoadModule(*index, module, PR_TRUE);
1863
0
                } else {
1864
0
                    /* Add printPolicyFeedback to the nss flags */
1865
0
                    char *specWithForwards =
1866
0
                        NSSUTIL_AddNSSFlagToModuleSpec(*index, "printPolicyFeedback");
1867
0
                    child = SECMOD_LoadModule(specWithForwards, module, PR_TRUE);
1868
0
                    PORT_Free(specWithForwards);
1869
0
                }
1870
0
                if (!child)
1871
0
                    break;
1872
0
                if (child->isCritical && !child->loaded) {
1873
0
                    int err = PORT_GetError();
1874
0
                    if (!err)
1875
0
                        err = SEC_ERROR_NO_MODULE;
1876
0
                    SECMOD_DestroyModule(child);
1877
0
                    PORT_SetError(err);
1878
0
                    rv = SECFailure;
1879
0
                    break;
1880
0
                }
1881
0
                SECMOD_DestroyModule(child);
1882
0
            }
1883
0
            SECMOD_FreeModuleSpecList(module, moduleSpecList);
1884
0
        } else {
1885
0
            if (!PORT_GetError())
1886
0
                PORT_SetError(SEC_ERROR_NO_MODULE);
1887
0
            rv = SECFailure;
1888
0
        }
1889
0
    }
1890
0
1891
0
    if (rv != SECSuccess) {
1892
0
        goto loser;
1893
0
    }
1894
0
1895
0
    /* inherit the reference */
1896
0
    if (!module->moduleDBOnly) {
1897
0
        SECMOD_AddModuleToList(module);
1898
0
    } else {
1899
0
        SECMOD_AddModuleToDBOnlyList(module);
1900
0
    }
1901
0
1902
0
    /* handle any additional work here */
1903
0
    return module;
1904
0
1905
0
loser:
1906
0
    if (module) {
1907
0
        if (module->loaded) {
1908
0
            SECMOD_UnloadModule(module);
1909
0
        }
1910
0
        SECMOD_AddModuleToUnloadList(module);
1911
0
    }
1912
0
    return module;
1913
0
}
1914
1915
/*
1916
 * load a PKCS#11 module and add it to the default NSS trust domain
1917
 */
1918
SECMODModule *
1919
SECMOD_LoadUserModule(char *modulespec, SECMODModule *parent, PRBool recurse)
1920
0
{
1921
0
    SECStatus rv = SECSuccess;
1922
0
    SECMODModule *newmod = SECMOD_LoadModule(modulespec, parent, recurse);
1923
0
    SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
1924
0
1925
0
    if (newmod) {
1926
0
        SECMOD_GetReadLock(moduleLock);
1927
0
        rv = STAN_AddModuleToDefaultTrustDomain(newmod);
1928
0
        SECMOD_ReleaseReadLock(moduleLock);
1929
0
        if (SECSuccess != rv) {
1930
0
            SECMOD_DestroyModule(newmod);
1931
0
            return NULL;
1932
0
        }
1933
0
    }
1934
0
    return newmod;
1935
0
}
1936
1937
/*
1938
 * remove the PKCS#11 module from the default NSS trust domain, call
1939
 * C_Finalize, and destroy the module structure
1940
 */
1941
SECStatus
1942
SECMOD_UnloadUserModule(SECMODModule *mod)
1943
0
{
1944
0
    SECStatus rv = SECSuccess;
1945
0
    int atype = 0;
1946
0
    SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
1947
0
    if (!mod) {
1948
0
        return SECFailure;
1949
0
    }
1950
0
1951
0
    SECMOD_GetReadLock(moduleLock);
1952
0
    rv = STAN_RemoveModuleFromDefaultTrustDomain(mod);
1953
0
    SECMOD_ReleaseReadLock(moduleLock);
1954
0
    if (SECSuccess != rv) {
1955
0
        return SECFailure;
1956
0
    }
1957
0
    return SECMOD_DeleteModuleEx(NULL, mod, &atype, PR_FALSE);
1958
0
}