Coverage Report

Created: 2026-01-22 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nss/lib/pk11wrap/pk11pars.c
Line
Count
Source
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
32
{
26
32
    SECMODModule *newMod;
27
32
    PLArenaPool *arena;
28
29
    /* create an arena in which dllName and commonName can be
30
     * allocated.
31
     */
32
32
    arena = PORT_NewArena(512);
33
32
    if (arena == NULL) {
34
0
        return NULL;
35
0
    }
36
37
32
    newMod = (SECMODModule *)PORT_ArenaAlloc(arena, sizeof(SECMODModule));
38
32
    if (newMod == NULL) {
39
0
        PORT_FreeArena(arena, PR_FALSE);
40
0
        return NULL;
41
0
    }
42
43
    /*
44
     * initialize of the fields of the module
45
     */
46
32
    newMod->arena = arena;
47
32
    newMod->internal = PR_FALSE;
48
32
    newMod->loaded = PR_FALSE;
49
32
    newMod->isFIPS = PR_FALSE;
50
32
    newMod->dllName = NULL;
51
32
    newMod->commonName = NULL;
52
32
    newMod->library = NULL;
53
32
    newMod->functionList = NULL;
54
32
    newMod->slotCount = 0;
55
32
    newMod->slots = NULL;
56
32
    newMod->slotInfo = NULL;
57
32
    newMod->slotInfoCount = 0;
58
32
    newMod->refCount = 1;
59
32
    newMod->ssl[0] = 0;
60
32
    newMod->ssl[1] = 0;
61
32
    newMod->libraryParams = NULL;
62
32
    newMod->moduleDBFunc = NULL;
63
32
    newMod->parent = NULL;
64
32
    newMod->isCritical = PR_FALSE;
65
32
    newMod->isModuleDB = PR_FALSE;
66
32
    newMod->moduleDBOnly = PR_FALSE;
67
32
    newMod->trustOrder = 0;
68
32
    newMod->cipherOrder = 0;
69
32
    newMod->evControlMask = 0;
70
32
    newMod->refLock = PZ_NewLock(nssILockRefLock);
71
32
    if (newMod->refLock == NULL) {
72
0
        PORT_FreeArena(arena, PR_FALSE);
73
0
        return NULL;
74
0
    }
75
32
    return newMod;
76
32
}
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
16
#define SECMOD_FLAG_MODULE_DB_IS_MODULE_DB 0x01 /* must be set if any of the \
109
                                                 *other flags are set */
110
16
#define SECMOD_FLAG_MODULE_DB_SKIP_FIRST 0x02
111
16
#define SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB 0x04
112
32
#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
32
#define SECMOD_FLAG_INTERNAL_IS_INTERNAL 0x01 /* must be set if any of \
127
                                               *the other flags are set */
128
64
#define SECMOD_FLAG_INTERNAL_KEY_SLOT 0x02
129
130
/* private flags for policy check. */
131
0
#define SECMOD_FLAG_POLICY_CHECK_IDENTIFIER 0x01
132
0
#define SECMOD_FLAG_POLICY_CHECK_VALUE 0x02
133
134
/*
135
 * for 3.4 we continue to use the old SECMODModule structure
136
 */
137
SECMODModule *
138
SECMOD_CreateModule(const char *library, const char *moduleName,
139
                    const char *parameters, const char *nss)
140
0
{
141
0
    return SECMOD_CreateModuleEx(library, moduleName, parameters, nss, NULL);
142
0
}
143
144
/*
145
 * NSS config options format:
146
 *
147
 * The specified ciphers will be allowed by policy, but an application
148
 * may allow more by policy explicitly:
149
 * config="allow=curve1:curve2:hash1:hash2:rsa-1024..."
150
 *
151
 * Only the specified hashes and curves will be allowed:
152
 * config="disallow=all allow=sha1:sha256:secp256r1:secp384r1"
153
 *
154
 * Only the specified hashes and curves will be allowed, and
155
 *  RSA keys of 2048 or more will be accepted, and DH key exchange
156
 *  with 1024-bit primes or more:
157
 * config="disallow=all allow=sha1:sha256:secp256r1:secp384r1:min-rsa=2048:min-dh=1024"
158
 *
159
 * A policy that enables the AES ciphersuites and the SECP256/384 curves:
160
 * config="allow=aes128-cbc:aes128-gcm:TLS1.0:TLS1.2:TLS1.1:HMAC-SHA1:SHA1:SHA256:SHA384:RSA:ECDHE-RSA:SECP256R1:SECP384R1"
161
 *
162
 * Disallow values are parsed first, then allow values, independent of the
163
 * order they appear.
164
 *
165
 * flags: turn on the following flags:
166
 *    policy-lock: turn off the ability for applications to change policy with
167
 *                 the call NSS_SetAlgorithmPolicy or the other system policy
168
 *                 calls (SSL_SetPolicy, etc.)
169
 *    ssl-lock:    turn off the ability to change the ssl defaults.
170
 *
171
 * The following only apply to ssl cipher suites (future smime)
172
 *
173
 * enable: turn on ciphersuites by default.
174
 * disable: turn off ciphersuites by default without disallowing them by policy.
175
 *
176
 *
177
 */
178
179
typedef struct {
180
    const char *name;
181
    unsigned name_size;
182
    SECOidTag oid;
183
    PRUint32 val;
184
} oidValDef;
185
186
typedef struct {
187
    const char *name;
188
    unsigned name_size;
189
    PRInt32 option;
190
} optionFreeDef;
191
192
typedef struct {
193
    const char *name;
194
    unsigned name_size;
195
    PRUint32 flag;
196
} policyFlagDef;
197
198
/*
199
 *  This table should be merged with the SECOID table.
200
 */
201
#define CIPHER_NAME(x) x, (sizeof(x) - 1)
202
static const oidValDef curveOptList[] = {
203
    /* Curves */
204
    { CIPHER_NAME("PRIME192V1"), SEC_OID_ANSIX962_EC_PRIME192V1,
205
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
206
    { CIPHER_NAME("PRIME192V2"), SEC_OID_ANSIX962_EC_PRIME192V2,
207
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
208
    { CIPHER_NAME("PRIME192V3"), SEC_OID_ANSIX962_EC_PRIME192V3,
209
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
210
    { CIPHER_NAME("PRIME239V1"), SEC_OID_ANSIX962_EC_PRIME239V1,
211
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
212
    { CIPHER_NAME("PRIME239V2"), SEC_OID_ANSIX962_EC_PRIME239V2,
213
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
214
    { CIPHER_NAME("PRIME239V3"), SEC_OID_ANSIX962_EC_PRIME239V3,
215
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
216
    { CIPHER_NAME("PRIME256V1"), SEC_OID_ANSIX962_EC_PRIME256V1,
217
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
218
    { CIPHER_NAME("SECP112R1"), SEC_OID_SECG_EC_SECP112R1,
219
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
220
    { CIPHER_NAME("SECP112R2"), SEC_OID_SECG_EC_SECP112R2,
221
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
222
    { CIPHER_NAME("SECP128R1"), SEC_OID_SECG_EC_SECP128R1,
223
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
224
    { CIPHER_NAME("SECP128R2"), SEC_OID_SECG_EC_SECP128R2,
225
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
226
    { CIPHER_NAME("SECP160K1"), SEC_OID_SECG_EC_SECP160K1,
227
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
228
    { CIPHER_NAME("SECP160R1"), SEC_OID_SECG_EC_SECP160R1,
229
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
230
    { CIPHER_NAME("SECP160R2"), SEC_OID_SECG_EC_SECP160R2,
231
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
232
    { CIPHER_NAME("SECP192K1"), SEC_OID_SECG_EC_SECP192K1,
233
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
234
    { CIPHER_NAME("SECP192R1"), SEC_OID_ANSIX962_EC_PRIME192V1,
235
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
236
    { CIPHER_NAME("SECP224K1"), SEC_OID_SECG_EC_SECP224K1,
237
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
238
    { CIPHER_NAME("SECP256K1"), SEC_OID_SECG_EC_SECP256K1,
239
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
240
    { CIPHER_NAME("SECP256R1"), SEC_OID_ANSIX962_EC_PRIME256V1,
241
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
242
    { CIPHER_NAME("SECP384R1"), SEC_OID_SECG_EC_SECP384R1,
243
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
244
    { CIPHER_NAME("SECP521R1"), SEC_OID_SECG_EC_SECP521R1,
245
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
246
    { CIPHER_NAME("CURVE25519"), SEC_OID_CURVE25519,
247
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
248
    /* NOTE, don't use '0' to indicate default off. Setting '0'
249
     * makes this entry unmanagable by the policy code (including
250
     * turning the entry off. If you want an entry off by default
251
     * simply explictly flip the bits in SECOID_Init()
252
     * (util/secoid.c) */
253
    { CIPHER_NAME("XYBER768D00"), SEC_OID_XYBER768D00,
254
      NSS_USE_ALG_IN_SSL_KX },
255
    { CIPHER_NAME("X25519MLKEM768"), SEC_OID_MLKEM768X25519,
256
      NSS_USE_ALG_IN_SSL_KX },
257
    { CIPHER_NAME("SECP256R1MLKEM768"), SEC_OID_SECP256R1MLKEM768,
258
      NSS_USE_ALG_IN_SSL_KX },
259
    { CIPHER_NAME("SECP384R1MLKEM1024"), SEC_OID_SECP384R1MLKEM1024,
260
      NSS_USE_ALG_IN_SSL_KX },
261
    { CIPHER_NAME("MLKEM768X25519"), SEC_OID_MLKEM768X25519,
262
      NSS_USE_ALG_IN_SSL_KX },
263
    /* ANSI X9.62 named elliptic curves (characteristic two field) */
264
    { CIPHER_NAME("C2PNB163V1"), SEC_OID_ANSIX962_EC_C2PNB163V1,
265
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
266
    { CIPHER_NAME("C2PNB163V2"), SEC_OID_ANSIX962_EC_C2PNB163V2,
267
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
268
    { CIPHER_NAME("C2PNB163V3"), SEC_OID_ANSIX962_EC_C2PNB163V3,
269
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
270
    { CIPHER_NAME("C2PNB176V1"), SEC_OID_ANSIX962_EC_C2PNB176V1,
271
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
272
    { CIPHER_NAME("C2TNB191V1"), SEC_OID_ANSIX962_EC_C2TNB191V1,
273
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
274
    { CIPHER_NAME("C2TNB191V2"), SEC_OID_ANSIX962_EC_C2TNB191V2,
275
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
276
    { CIPHER_NAME("C2TNB191V3"), SEC_OID_ANSIX962_EC_C2TNB191V3,
277
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
278
    { CIPHER_NAME("C2ONB191V4"), SEC_OID_ANSIX962_EC_C2ONB191V4,
279
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
280
    { CIPHER_NAME("C2ONB191V5"), SEC_OID_ANSIX962_EC_C2ONB191V5,
281
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
282
    { CIPHER_NAME("C2PNB208W1"), SEC_OID_ANSIX962_EC_C2PNB208W1,
283
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
284
    { CIPHER_NAME("C2TNB239V1"), SEC_OID_ANSIX962_EC_C2TNB239V1,
285
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
286
    { CIPHER_NAME("C2TNB239V2"), SEC_OID_ANSIX962_EC_C2TNB239V2,
287
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
288
    { CIPHER_NAME("C2TNB239V3"), SEC_OID_ANSIX962_EC_C2TNB239V3,
289
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
290
    { CIPHER_NAME("C2ONB239V4"), SEC_OID_ANSIX962_EC_C2ONB239V4,
291
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
292
    { CIPHER_NAME("C2ONB239V5"), SEC_OID_ANSIX962_EC_C2ONB239V5,
293
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
294
    { CIPHER_NAME("C2PNB272W1"), SEC_OID_ANSIX962_EC_C2PNB272W1,
295
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
296
    { CIPHER_NAME("C2PNB304W1"), SEC_OID_ANSIX962_EC_C2PNB304W1,
297
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
298
    { CIPHER_NAME("C2TNB359V1"), SEC_OID_ANSIX962_EC_C2TNB359V1,
299
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
300
    { CIPHER_NAME("C2PNB368W1"), SEC_OID_ANSIX962_EC_C2PNB368W1,
301
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
302
    { CIPHER_NAME("C2TNB431R1"), SEC_OID_ANSIX962_EC_C2TNB431R1,
303
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
304
    /* SECG named elliptic curves (characteristic two field) */
305
    { CIPHER_NAME("SECT113R1"), SEC_OID_SECG_EC_SECT113R1,
306
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
307
    { CIPHER_NAME("SECT131R1"), SEC_OID_SECG_EC_SECT113R2,
308
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
309
    { CIPHER_NAME("SECT131R1"), SEC_OID_SECG_EC_SECT131R1,
310
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
311
    { CIPHER_NAME("SECT131R2"), SEC_OID_SECG_EC_SECT131R2,
312
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
313
    { CIPHER_NAME("SECT163K1"), SEC_OID_SECG_EC_SECT163K1,
314
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
315
    { CIPHER_NAME("SECT163R1"), SEC_OID_SECG_EC_SECT163R1,
316
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
317
    { CIPHER_NAME("SECT163R2"), SEC_OID_SECG_EC_SECT163R2,
318
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
319
    { CIPHER_NAME("SECT193R1"), SEC_OID_SECG_EC_SECT193R1,
320
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
321
    { CIPHER_NAME("SECT193R2"), SEC_OID_SECG_EC_SECT193R2,
322
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
323
    { CIPHER_NAME("SECT233K1"), SEC_OID_SECG_EC_SECT233K1,
324
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
325
    { CIPHER_NAME("SECT233R1"), SEC_OID_SECG_EC_SECT233R1,
326
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
327
    { CIPHER_NAME("SECT239K1"), SEC_OID_SECG_EC_SECT239K1,
328
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
329
    { CIPHER_NAME("SECT283K1"), SEC_OID_SECG_EC_SECT283K1,
330
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
331
    { CIPHER_NAME("SECT283R1"), SEC_OID_SECG_EC_SECT283R1,
332
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
333
    { CIPHER_NAME("SECT409K1"), SEC_OID_SECG_EC_SECT409K1,
334
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
335
    { CIPHER_NAME("SECT409R1"), SEC_OID_SECG_EC_SECT409R1,
336
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
337
    { CIPHER_NAME("SECT571K1"), SEC_OID_SECG_EC_SECT571K1,
338
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
339
    { CIPHER_NAME("SECT571R1"), SEC_OID_SECG_EC_SECT571R1,
340
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
341
};
342
343
static const oidValDef hashOptList[] = {
344
    /* Hashes */
345
    { CIPHER_NAME("MD2"), SEC_OID_MD2,
346
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
347
          NSS_USE_ALG_IN_PKCS12 },
348
    { CIPHER_NAME("MD4"), SEC_OID_MD4,
349
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
350
          NSS_USE_ALG_IN_PKCS12 },
351
    { CIPHER_NAME("MD5"), SEC_OID_MD5,
352
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
353
          NSS_USE_ALG_IN_PKCS12 },
354
    { CIPHER_NAME("SHA1"), SEC_OID_SHA1,
355
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
356
          NSS_USE_ALG_IN_PKCS12 },
357
    { CIPHER_NAME("SHA224"), SEC_OID_SHA224,
358
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
359
          NSS_USE_ALG_IN_PKCS12 },
360
    { CIPHER_NAME("SHA256"), SEC_OID_SHA256,
361
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
362
          NSS_USE_ALG_IN_PKCS12 },
363
    { CIPHER_NAME("SHA384"), SEC_OID_SHA384,
364
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
365
          NSS_USE_ALG_IN_PKCS12 },
366
    { CIPHER_NAME("SHA512"), SEC_OID_SHA512,
367
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
368
          NSS_USE_ALG_IN_PKCS12 },
369
    { CIPHER_NAME("SHA3-224"), SEC_OID_SHA3_224,
370
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
371
          NSS_USE_ALG_IN_PKCS12 },
372
    { CIPHER_NAME("SHA3-256"), SEC_OID_SHA3_256,
373
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
374
          NSS_USE_ALG_IN_PKCS12 },
375
    { CIPHER_NAME("SHA3-384"), SEC_OID_SHA3_384,
376
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
377
          NSS_USE_ALG_IN_PKCS12 },
378
    { CIPHER_NAME("SHA3-512"), SEC_OID_SHA3_512,
379
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME |
380
          NSS_USE_ALG_IN_PKCS12 }
381
};
382
383
static const oidValDef macOptList[] = {
384
    /* MACs */
385
    { CIPHER_NAME("HMAC-MD5"), SEC_OID_HMAC_MD5,
386
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
387
    { CIPHER_NAME("HMAC-SHA1"), SEC_OID_HMAC_SHA1,
388
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
389
    { CIPHER_NAME("HMAC-SHA224"), SEC_OID_HMAC_SHA224,
390
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
391
    { CIPHER_NAME("HMAC-SHA256"), SEC_OID_HMAC_SHA256,
392
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
393
    { CIPHER_NAME("HMAC-SHA384"), SEC_OID_HMAC_SHA384,
394
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
395
    { CIPHER_NAME("HMAC-SHA512"), SEC_OID_HMAC_SHA512,
396
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
397
    { CIPHER_NAME("HMAC-SHA3-224"), SEC_OID_HMAC_SHA3_224,
398
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
399
    { CIPHER_NAME("HMAC-SHA3-256"), SEC_OID_HMAC_SHA3_256,
400
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
401
    { CIPHER_NAME("HMAC-SHA3-384"), SEC_OID_HMAC_SHA3_384,
402
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
403
    { CIPHER_NAME("HMAC-SHA3-512"), SEC_OID_HMAC_SHA3_512,
404
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
405
};
406
407
static const oidValDef cipherOptList[] = {
408
    /* Ciphers */
409
    { CIPHER_NAME("AES128-CBC"), SEC_OID_AES_128_CBC,
410
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
411
    { CIPHER_NAME("AES192-CBC"), SEC_OID_AES_192_CBC,
412
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
413
    { CIPHER_NAME("AES256-CBC"), SEC_OID_AES_256_CBC,
414
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
415
    { CIPHER_NAME("AES128-GCM"), SEC_OID_AES_128_GCM, NSS_USE_ALG_IN_SSL },
416
    { CIPHER_NAME("AES192-GCM"), SEC_OID_AES_192_GCM, NSS_USE_ALG_IN_SSL },
417
    { CIPHER_NAME("AES256-GCM"), SEC_OID_AES_256_GCM, NSS_USE_ALG_IN_SSL },
418
    { CIPHER_NAME("CAMELLIA128-CBC"), SEC_OID_CAMELLIA_128_CBC,
419
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
420
    { CIPHER_NAME("CAMELLIA192-CBC"), SEC_OID_CAMELLIA_192_CBC,
421
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
422
    { CIPHER_NAME("CAMELLIA256-CBC"), SEC_OID_CAMELLIA_256_CBC,
423
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
424
    { CIPHER_NAME("CHACHA20-POLY1305"), SEC_OID_CHACHA20_POLY1305, NSS_USE_ALG_IN_SSL },
425
    { CIPHER_NAME("SEED-CBC"), SEC_OID_SEED_CBC,
426
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
427
    { CIPHER_NAME("DES-EDE3-CBC"), SEC_OID_DES_EDE3_CBC,
428
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
429
    { CIPHER_NAME("DES-40-CBC"), SEC_OID_DES_40_CBC,
430
      NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SMIME | NSS_USE_ALG_IN_PKCS12 },
431
    { CIPHER_NAME("DES-CBC"), SEC_OID_DES_CBC, NSS_USE_ALG_IN_SSL },
432
    { CIPHER_NAME("NULL-CIPHER"), SEC_OID_NULL_CIPHER, NSS_USE_ALG_IN_SSL },
433
    { CIPHER_NAME("RC2"), SEC_OID_RC2_CBC, NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
434
    { CIPHER_NAME("RC2-40-CBC"), SEC_OID_RC2_40_CBC, NSS_USE_ALG_IN_SMIME },
435
    { CIPHER_NAME("RC2-64-CBC"), SEC_OID_RC2_64_CBC, NSS_USE_ALG_IN_SMIME },
436
    { CIPHER_NAME("RC2-128-CBC"), SEC_OID_RC2_128_CBC, NSS_USE_ALG_IN_SMIME },
437
    { CIPHER_NAME("RC4"), SEC_OID_RC4, NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_PKCS12 },
438
    { CIPHER_NAME("IDEA"), SEC_OID_IDEA_CBC, NSS_USE_ALG_IN_SSL },
439
};
440
441
static const oidValDef kxOptList[] = {
442
    /* Key exchange */
443
    { CIPHER_NAME("RSA"), SEC_OID_TLS_RSA, NSS_USE_ALG_IN_SSL_KX },
444
    { CIPHER_NAME("RSA-EXPORT"), SEC_OID_TLS_RSA_EXPORT, NSS_USE_ALG_IN_SSL_KX },
445
    { CIPHER_NAME("DHE-RSA"), SEC_OID_TLS_DHE_RSA, NSS_USE_ALG_IN_SSL_KX },
446
    { CIPHER_NAME("DHE-DSS"), SEC_OID_TLS_DHE_DSS, NSS_USE_ALG_IN_SSL_KX },
447
    { CIPHER_NAME("DH-RSA"), SEC_OID_TLS_DH_RSA, NSS_USE_ALG_IN_SSL_KX },
448
    { CIPHER_NAME("DH-DSS"), SEC_OID_TLS_DH_DSS, NSS_USE_ALG_IN_SSL_KX },
449
    { CIPHER_NAME("ECDHE-ECDSA"), SEC_OID_TLS_ECDHE_ECDSA, NSS_USE_ALG_IN_SSL_KX },
450
    { CIPHER_NAME("ECDHE-RSA"), SEC_OID_TLS_ECDHE_RSA, NSS_USE_ALG_IN_SSL_KX },
451
    { CIPHER_NAME("ECDH-ECDSA"), SEC_OID_TLS_ECDH_ECDSA, NSS_USE_ALG_IN_SSL_KX },
452
    { CIPHER_NAME("ECDH-RSA"), SEC_OID_TLS_ECDH_RSA, NSS_USE_ALG_IN_SSL_KX },
453
    { CIPHER_NAME("TLS-REQUIRE-EMS"), SEC_OID_TLS_REQUIRE_EMS, NSS_USE_ALG_IN_SSL_KX },
454
455
};
456
457
static const oidValDef smimeKxOptList[] = {
458
    /* Key exchange */
459
    { CIPHER_NAME("RSA-PKCS"), SEC_OID_PKCS1_RSA_ENCRYPTION, NSS_USE_ALG_IN_SMIME_KX },
460
    { CIPHER_NAME("RSA-OAEP"), SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION, NSS_USE_ALG_IN_SMIME_KX },
461
    { CIPHER_NAME("ECDH"), SEC_OID_ECDH_KEA, NSS_USE_ALG_IN_SMIME_KX },
462
    { CIPHER_NAME("DH"), SEC_OID_X942_DIFFIE_HELMAN_KEY, NSS_USE_ALG_IN_SMIME_KX },
463
};
464
465
static const oidValDef signOptList[] = {
466
    /* Signatures */
467
    { CIPHER_NAME("DSA"), SEC_OID_ANSIX9_DSA_SIGNATURE,
468
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },
469
    { CIPHER_NAME("RSA-PKCS"), SEC_OID_PKCS1_RSA_ENCRYPTION,
470
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },
471
    { CIPHER_NAME("RSA-PSS"), SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
472
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },
473
    { CIPHER_NAME("ECDSA"), SEC_OID_ANSIX962_EC_PUBLIC_KEY,
474
      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },
475
    { CIPHER_NAME("ED25519"), SEC_OID_ED25519_PUBLIC_KEY,
476
      NSS_USE_ALG_IN_SIGNATURE },
477
    { CIPHER_NAME("ML-DSA-44"), SEC_OID_ML_DSA_44,
478
      NSS_USE_ALG_IN_SIGNATURE },
479
    { CIPHER_NAME("ML-DSA-65"), SEC_OID_ML_DSA_65,
480
      NSS_USE_ALG_IN_SIGNATURE },
481
    { CIPHER_NAME("ML-DSA-87"), SEC_OID_ML_DSA_87,
482
      NSS_USE_ALG_IN_SIGNATURE },
483
};
484
485
typedef struct {
486
    const oidValDef *list;
487
    PRUint32 entries;
488
    const char *description;
489
    PRBool allowEmpty;
490
} algListsDef;
491
492
static const algListsDef algOptLists[] = {
493
    { curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC", PR_FALSE },
494
    { hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH", PR_FALSE },
495
    { macOptList, PR_ARRAY_SIZE(macOptList), "MAC", PR_FALSE },
496
    { cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER", PR_FALSE },
497
    { kxOptList, PR_ARRAY_SIZE(kxOptList), "SSL-KX", PR_FALSE },
498
    { smimeKxOptList, PR_ARRAY_SIZE(smimeKxOptList), "SMIME-KX", PR_TRUE },
499
    { signOptList, PR_ARRAY_SIZE(signOptList), "OTHER-SIGN", PR_FALSE },
500
};
501
502
static const optionFreeDef sslOptList[] = {
503
    /* Versions */
504
    { CIPHER_NAME("SSL2.0"), 0x002 },
505
    { CIPHER_NAME("SSL3.0"), 0x300 },
506
    { CIPHER_NAME("SSL3.1"), 0x301 },
507
    { CIPHER_NAME("TLS1.0"), 0x301 },
508
    { CIPHER_NAME("TLS1.1"), 0x302 },
509
    { CIPHER_NAME("TLS1.2"), 0x303 },
510
    { CIPHER_NAME("TLS1.3"), 0x304 },
511
    { CIPHER_NAME("DTLS1.0"), 0x302 },
512
    { CIPHER_NAME("DTLS1.1"), 0x302 },
513
    { CIPHER_NAME("DTLS1.2"), 0x303 },
514
    { CIPHER_NAME("DTLS1.3"), 0x304 },
515
};
516
517
static const optionFreeDef keySizeFlagsList[] = {
518
    { CIPHER_NAME("KEY-SIZE-SSL"), NSS_KEY_SIZE_POLICY_SSL_FLAG },
519
    { CIPHER_NAME("KEY-SIZE-SIGN"), NSS_KEY_SIZE_POLICY_SIGN_FLAG },
520
    { CIPHER_NAME("KEY-SIZE-VERIFY"), NSS_KEY_SIZE_POLICY_VERIFY_FLAG },
521
    { CIPHER_NAME("KEY-SIZE-SMIME"), NSS_KEY_SIZE_POLICY_SMIME_FLAG },
522
    { CIPHER_NAME("KEY-SIZE-ALL"), NSS_KEY_SIZE_POLICY_ALL_FLAGS },
523
};
524
525
static const optionFreeDef freeOptList[] = {
526
527
    /* Restrictions for asymetric keys */
528
    { CIPHER_NAME("RSA-MIN"), NSS_RSA_MIN_KEY_SIZE },
529
    { CIPHER_NAME("DH-MIN"), NSS_DH_MIN_KEY_SIZE },
530
    { CIPHER_NAME("DSA-MIN"), NSS_DSA_MIN_KEY_SIZE },
531
    { CIPHER_NAME("ECC-MIN"), NSS_ECC_MIN_KEY_SIZE },
532
    /* what operations doe the key size apply to */
533
    { CIPHER_NAME("KEY-SIZE-FLAGS"), NSS_KEY_SIZE_POLICY_FLAGS },
534
    /* constraints on SSL Protocols */
535
    { CIPHER_NAME("TLS-VERSION-MIN"), NSS_TLS_VERSION_MIN_POLICY },
536
    { CIPHER_NAME("TLS-VERSION-MAX"), NSS_TLS_VERSION_MAX_POLICY },
537
    /* constraints on DTLS Protocols */
538
    { CIPHER_NAME("DTLS-VERSION-MIN"), NSS_DTLS_VERSION_MIN_POLICY },
539
    { CIPHER_NAME("DTLS-VERSION-MAX"), NSS_DTLS_VERSION_MAX_POLICY }
540
};
541
542
static const policyFlagDef policyFlagList[] = {
543
    { CIPHER_NAME("SSL"), NSS_USE_ALG_IN_SSL },
544
    { CIPHER_NAME("SSL-KEY-EXCHANGE"), NSS_USE_ALG_IN_SSL_KX },
545
    /* add other key exhanges in the future */
546
    { CIPHER_NAME("KEY-EXCHANGE"), NSS_USE_ALG_IN_KEY_EXCHANGE },
547
    { CIPHER_NAME("CERT-SIGNATURE"), NSS_USE_ALG_IN_CERT_SIGNATURE },
548
    { CIPHER_NAME("CMS-SIGNATURE"), NSS_USE_ALG_IN_SMIME_SIGNATURE },
549
    { CIPHER_NAME("SMIME-SIGNATURE"), NSS_USE_ALG_IN_SMIME_SIGNATURE },
550
    { CIPHER_NAME("ALL-SIGNATURE"), NSS_USE_ALG_IN_SIGNATURE },
551
    { CIPHER_NAME("PKCS12"), NSS_USE_ALG_IN_PKCS12 },
552
    /* only use in allow */
553
    { CIPHER_NAME("PKCS12-LEGACY"), NSS_USE_ALG_IN_PKCS12_DECRYPT },
554
    /* only use in disallow */
555
    { CIPHER_NAME("PKCS12-ENCRYPT"), NSS_USE_ALG_IN_PKCS12_ENCRYPT },
556
    { CIPHER_NAME("SMIME"), NSS_USE_ALG_IN_SMIME },
557
    /* only use in allow, enable */
558
    { CIPHER_NAME("SMIME-LEGACY"), NSS_USE_ALG_IN_SMIME_LEGACY },
559
    /* only use in disallow, disable */
560
    { CIPHER_NAME("SMIME-ENCRYPT"), NSS_USE_ALG_IN_SMIME_ENCRYPT },
561
    { CIPHER_NAME("SMIME-KEY-EXCHANGE"), NSS_USE_ALG_IN_SMIME_KX },
562
    /* only use in allow */
563
    { CIPHER_NAME("SMIME-KEY-EXCHANGE-LEGACY"), NSS_USE_ALG_IN_SMIME_KX_LEGACY },
564
    /* only use in disallow */
565
    { CIPHER_NAME("SMIME-KEY-EXCHANGE-ENCRYPT"), NSS_USE_ALG_IN_SMIME_KX_ENCRYPT },
566
    /* sign turns off all signatures, but doesn't change the
567
     * allowance for specific signatures... for example:
568
     *     disallow=sha256/all allow=sha256/signature
569
     * doesn't allow cert-signatures or sime-signatures, where
570
     *     disallow=sha256/all allow=sha256/all-signature
571
     * does. however,
572
     *     disallow=sha256/signature
573
     * and
574
     *     disallow=sha256/all-signature
575
     * are equivalent in effect */
576
    { CIPHER_NAME("SIGNATURE"), NSS_USE_ALG_IN_ANY_SIGNATURE },
577
    /* enable/allow algorithms for legacy (read/verify)operations */
578
    { CIPHER_NAME("LEGACY"), NSS_USE_ALG_IN_PKCS12_DECRYPT |
579
                                 NSS_USE_ALG_IN_SMIME_LEGACY |
580
                                 NSS_USE_ALG_IN_SMIME_KX_LEGACY },
581
    /* enable/disable everything */
582
    { CIPHER_NAME("ALL"), NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SSL_KX |
583
                              NSS_USE_ALG_IN_PKCS12 | NSS_USE_ALG_IN_SMIME |
584
                              NSS_USE_ALG_IN_SIGNATURE |
585
                              NSS_USE_ALG_IN_SMIME_KX },
586
    { CIPHER_NAME("NONE"), 0 }
587
};
588
589
/*
590
 *  Get the next cipher on the list. point to the next one in 'next'.
591
 *  return the length;
592
 */
593
static const char *
594
secmod_ArgGetSubValue(const char *cipher, char sep1, char sep2,
595
                      int *len, const char **next)
596
0
{
597
0
    const char *start = cipher;
598
599
0
    if (start == NULL) {
600
0
        *len = 0;
601
0
        *next = NULL;
602
0
        return start;
603
0
    }
604
605
0
    for (; *cipher && *cipher != sep2; cipher++) {
606
0
        if (*cipher == sep1) {
607
0
            *next = cipher + 1;
608
0
            *len = cipher - start;
609
0
            return start;
610
0
        }
611
0
    }
612
0
    *next = NULL;
613
0
    *len = cipher - start;
614
0
    return start;
615
0
}
616
617
static PRUint32
618
secmod_parsePolicyValue(const char *policyFlags, int policyLength,
619
                        PRBool printPolicyFeedback, PRUint32 policyCheckFlags)
620
0
{
621
0
    const char *flag, *currentString;
622
0
    PRUint32 flags = 0;
623
0
    int i;
624
625
0
    for (currentString = policyFlags; currentString &&
626
0
                                      currentString < policyFlags + policyLength;) {
627
0
        int length;
628
0
        PRBool unknown = PR_TRUE;
629
0
        flag = secmod_ArgGetSubValue(currentString, ',', ':', &length,
630
0
                                     &currentString);
631
0
        if (length == 0) {
632
0
            continue;
633
0
        }
634
0
        for (i = 0; i < PR_ARRAY_SIZE(policyFlagList); i++) {
635
0
            const policyFlagDef *policy = &policyFlagList[i];
636
0
            unsigned name_size = policy->name_size;
637
0
            if ((policy->name_size == length) &&
638
0
                PORT_Strncasecmp(policy->name, flag, name_size) == 0) {
639
0
                flags |= policy->flag;
640
0
                unknown = PR_FALSE;
641
0
                break;
642
0
            }
643
0
        }
644
0
        if (unknown && printPolicyFeedback &&
645
0
            (policyCheckFlags & SECMOD_FLAG_POLICY_CHECK_VALUE)) {
646
0
            PR_SetEnv("NSS_POLICY_FAIL=1");
647
0
            fprintf(stderr, "NSS-POLICY-FAIL %.*s: unknown value: %.*s\n",
648
0
                    policyLength, policyFlags, length, flag);
649
0
        }
650
0
    }
651
0
    return flags;
652
0
}
653
654
/* allow symbolic names for values. The only ones currently defines or
655
 * SSL protocol versions. */
656
static SECStatus
657
secmod_getPolicyOptValue(const char *policyValue, int policyValueLength,
658
                         PRInt32 *result)
659
0
{
660
0
    PRInt32 val = atoi(policyValue);
661
0
    int i;
662
663
0
    if ((val != 0) || (*policyValue == '0')) {
664
0
        *result = val;
665
0
        return SECSuccess;
666
0
    }
667
0
    if (policyValueLength == 0) {
668
0
        return SECFailure;
669
0
    }
670
    /* handle any ssl strings */
671
0
    for (i = 0; i < PR_ARRAY_SIZE(sslOptList); i++) {
672
0
        if (policyValueLength == sslOptList[i].name_size &&
673
0
            PORT_Strncasecmp(sslOptList[i].name, policyValue,
674
0
                             sslOptList[i].name_size) == 0) {
675
0
            *result = sslOptList[i].option;
676
0
            return SECSuccess;
677
0
        }
678
0
    }
679
    /* handle key_size flags. Each flag represents a bit, which
680
     * gets or'd together. They can be separated by , | or + */
681
0
    val = 0;
682
0
    while (policyValueLength > 0) {
683
0
        PRBool found = PR_FALSE;
684
0
        for (i = 0; i < PR_ARRAY_SIZE(keySizeFlagsList); i++) {
685
0
            if (PORT_Strncasecmp(keySizeFlagsList[i].name, policyValue,
686
0
                                 keySizeFlagsList[i].name_size) == 0) {
687
0
                val |= keySizeFlagsList[i].option;
688
0
                found = PR_TRUE;
689
0
                policyValue += keySizeFlagsList[i].name_size;
690
0
                policyValueLength -= keySizeFlagsList[i].name_size;
691
0
                break;
692
0
            }
693
0
        }
694
0
        if (!found) {
695
0
            return SECFailure;
696
0
        }
697
0
        if (*policyValue == ',' || *policyValue == '|' || *policyValue == '+') {
698
0
            policyValue++;
699
0
            policyValueLength--;
700
0
        }
701
0
    }
702
0
    *result = val;
703
0
    return SECSuccess;
704
0
}
705
706
/* Policy operations:
707
 *     Disallow: operation is disallowed by policy. Implies disabled.
708
 *     Allow: operation is allowed by policy (but could be disabled).
709
 *     Disable: operation is turned off by default (but could be allowed).
710
 *     Enable: operation is enabled by default. Implies allowed.
711
 */
712
typedef enum {
713
    NSS_DISALLOW,
714
    NSS_ALLOW,
715
    NSS_DISABLE,
716
    NSS_ENABLE
717
} NSSPolicyOperation;
718
719
/* Enable/Disable only apply to SSL cipher suites and S/MIME symetric algorithms.
720
 * Enable/Disable is implemented by clearing the DEFAULT_NOT_VALID
721
 * flag, then setting the NSS_USE_DEFAULT_SSL_ENABLE and
722
 * NSS_USE_DEFAULT_SMIME_ENABLE flags to the correct value. The ssl
723
 * policy code will then sort out what to set based on ciphers and
724
 * cipher suite values and the smime policy code will sort
725
 * out which ciphers to include in capabilities based on these values */
726
static SECStatus
727
secmod_setDefault(SECOidTag oid, NSSPolicyOperation operation,
728
                  PRUint32 value)
729
0
{
730
0
    SECStatus rv = SECSuccess;
731
0
    PRUint32 policy;
732
0
    PRUint32 useDefault = 0;
733
0
    PRUint32 set = 0;
734
    /* we always clear the default not valid flag as this operation will
735
     * make the defaults valid */
736
0
    PRUint32 clear = NSS_USE_DEFAULT_NOT_VALID;
737
738
    /* what values are we trying to change */
739
    /* if either SSL or SSL_KX is set, enable SSL */
740
0
    if (value & (NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SSL_KX)) {
741
0
        useDefault |= NSS_USE_DEFAULT_SSL_ENABLE;
742
0
    }
743
    /* only bulk ciphers are configured as enable in S/MIME, only
744
     * enable them if both SMIME bits are set */
745
0
    if ((value & NSS_USE_ALG_IN_SMIME) == NSS_USE_ALG_IN_SMIME) {
746
0
        useDefault |= NSS_USE_DEFAULT_SMIME_ENABLE;
747
0
    }
748
749
    /* on disable we clear, on enable we set */
750
0
    if (operation == NSS_DISABLE) {
751
0
        clear |= useDefault;
752
0
    } else {
753
        /* we also turn the cipher on by policy if we enable it,
754
         * so include the policy bits */
755
0
        set |= value | useDefault;
756
0
    }
757
758
    /* if we haven't set the not valid flag yet, then we need to
759
     * clear any of the other bits we aren't actually setting as well.
760
     */
761
0
    rv = NSS_GetAlgorithmPolicy(oid, &policy);
762
0
    if (rv != SECSuccess) {
763
0
        return rv;
764
0
    }
765
0
    if (policy & NSS_USE_DEFAULT_NOT_VALID) {
766
0
        clear |= ((NSS_USE_DEFAULT_SSL_ENABLE | NSS_USE_DEFAULT_SMIME_ENABLE) &
767
0
                  ~set);
768
0
    }
769
0
    return NSS_SetAlgorithmPolicy(oid, set, clear);
770
0
}
771
772
/* apply the operator specific policy */
773
SECStatus
774
secmod_setPolicyOperation(SECOidTag oid, NSSPolicyOperation operation,
775
                          PRUint32 value)
776
0
{
777
0
    SECStatus rv = SECSuccess;
778
0
    switch (operation) {
779
0
        case NSS_DISALLOW:
780
            /* clear the requested policy bits */
781
0
            rv = NSS_SetAlgorithmPolicy(oid, 0, value);
782
0
            break;
783
0
        case NSS_ALLOW:
784
            /* set the requested policy bits */
785
0
            rv = NSS_SetAlgorithmPolicy(oid, value, 0);
786
0
            break;
787
0
        case NSS_DISABLE:
788
0
        case NSS_ENABLE:
789
0
            rv = secmod_setDefault(oid, operation, value);
790
0
            break;
791
0
        default:
792
0
            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
793
0
            rv = SECFailure;
794
0
            break;
795
0
    }
796
0
    return rv;
797
0
}
798
799
const char *
800
secmod_getOperationString(NSSPolicyOperation operation)
801
0
{
802
0
    switch (operation) {
803
0
        case NSS_DISALLOW:
804
0
            return "disallow";
805
0
        case NSS_ALLOW:
806
0
            return "allow";
807
0
        case NSS_DISABLE:
808
0
            return "disable";
809
0
        case NSS_ENABLE:
810
0
            return "enable";
811
0
        default:
812
0
            break;
813
0
    }
814
0
    return "invalid";
815
0
}
816
817
/* Allow external applications fetch the policy oid based on the internal
818
 * string mapping used by the configuration system. The search can be
819
 * narrowed by supplying the name of the table (list) that the policy
820
 * is on. The value 'Any' allows the policy to be searched on all lists */
821
SECOidTag
822
SECMOD_PolicyStringToOid(const char *policy, const char *list)
823
0
{
824
0
    PRBool any = (PORT_Strcasecmp(list, "Any") == 0) ? PR_TRUE : PR_FALSE;
825
0
    int len = PORT_Strlen(policy);
826
0
    int i, j;
827
828
0
    for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) {
829
0
        const algListsDef *algOptList = &algOptLists[i];
830
0
        if (any || (PORT_Strcasecmp(algOptList->description, list) == 0)) {
831
0
            for (j = 0; j < algOptList->entries; j++) {
832
0
                const oidValDef *algOpt = &algOptList->list[j];
833
0
                unsigned name_size = algOpt->name_size;
834
0
                if (len == name_size &&
835
0
                    PORT_Strcasecmp(algOpt->name, policy) == 0) {
836
0
                    return algOpt->oid;
837
0
                }
838
0
            }
839
0
        }
840
0
    }
841
0
    return SEC_OID_UNKNOWN;
842
0
}
843
844
/* Allow external applications fetch the NSS option based on the internal
845
 * string mapping used by the configuration system. */
846
PRUint32
847
SECMOD_PolicyStringToOpt(const char *policy)
848
0
{
849
0
    int len = PORT_Strlen(policy);
850
0
    int i;
851
852
0
    for (i = 0; i < PR_ARRAY_SIZE(freeOptList); i++) {
853
0
        const optionFreeDef *freeOpt = &freeOptList[i];
854
0
        unsigned name_size = freeOpt->name_size;
855
0
        if (len == name_size &&
856
0
            PORT_Strcasecmp(freeOpt->name, policy) == 0) {
857
0
            return freeOpt->option;
858
0
        }
859
0
    }
860
0
    return 0;
861
0
}
862
863
/* Allow external applications map policy flags to their string equivalance.
864
 * Some strings represent more than one flag. If more than one flag is included
865
 * the returned string is the string that contains any of the
866
 * supplied flags unless exact is specified. If exact is specified, then the
867
 * returned value matches all the included flags and only those flags. For
868
 * Example: 'ALL-SIGNATURE' has the bits NSS_USE_ALG_IN_CERTSIGNATURE|
869
 * NSS_USE_ALG_IN_SMIME_SIGNATURE|NSS_USE_ALG_IN_ANY_SIGNATURE. If you ask for
870
 * NSS_USE_ALG_IN_CERT_SIGNATURE|NSS_USE_ALG_IN_SMIME_SIGNATURE and don't set
871
 * exact, this function will return 'ALL-SIGNATURE' if you do set exact, you must
872
 * include all three bits in value to get 'All-SIGNATURE'*/
873
const char *
874
SECMOD_FlagsToPolicyString(PRUint32 val, PRBool exact)
875
0
{
876
0
    int i;
877
878
0
    for (i = 0; i < PR_ARRAY_SIZE(policyFlagList); i++) {
879
0
        const policyFlagDef *policy = &policyFlagList[i];
880
0
        if (exact && (policy->flag == val)) {
881
0
            return policy->name;
882
0
        }
883
0
        if (!exact && ((policy->flag & val) == policy->flag)) {
884
0
            return policy->name;
885
0
        }
886
0
    }
887
0
    return NULL;
888
0
}
889
890
static SECStatus
891
secmod_applyCryptoPolicy(const char *policyString, NSSPolicyOperation operation,
892
                         PRBool printPolicyFeedback, PRUint32 policyCheckFlags)
893
0
{
894
0
    const char *cipher, *currentString;
895
0
    unsigned i, j;
896
0
    SECStatus rv = SECSuccess;
897
0
    PRBool unknown;
898
899
0
    if (policyString == NULL || policyString[0] == 0) {
900
0
        return SECSuccess; /* do nothing */
901
0
    }
902
903
    /* if we change any of these, make sure it gets applied in ssl as well */
904
0
    NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL, 0);
905
906
0
    for (currentString = policyString; currentString;) {
907
0
        int length;
908
0
        PRBool newValue = PR_FALSE;
909
910
0
        cipher = secmod_ArgGetSubValue(currentString, ':', 0, &length,
911
0
                                       &currentString);
912
0
        unknown = PR_TRUE;
913
0
        if (length >= 3 && cipher[3] == '/') {
914
0
            newValue = PR_TRUE;
915
0
        }
916
0
        if ((newValue || (length == 3)) && PORT_Strncasecmp(cipher, "all", 3) == 0) {
917
            /* disable or enable all options by default */
918
0
            PRUint32 value = 0;
919
0
            if (newValue) {
920
0
                value = secmod_parsePolicyValue(&cipher[3] + 1, length - 3 - 1, printPolicyFeedback, policyCheckFlags);
921
0
            }
922
0
            for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) {
923
0
                const algListsDef *algOptList = &algOptLists[i];
924
0
                for (j = 0; j < algOptList->entries; j++) {
925
0
                    if (!newValue) {
926
0
                        value = algOptList->list[j].val;
927
0
                    }
928
0
                    secmod_setPolicyOperation(algOptList->list[j].oid, operation, value);
929
0
                }
930
0
            }
931
0
            continue;
932
0
        }
933
934
0
        for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) {
935
0
            const algListsDef *algOptList = &algOptLists[i];
936
0
            for (j = 0; j < algOptList->entries; j++) {
937
0
                const oidValDef *algOpt = &algOptList->list[j];
938
0
                unsigned name_size = algOpt->name_size;
939
0
                PRBool newOption = PR_FALSE;
940
941
0
                if ((length >= name_size) && (cipher[name_size] == '/')) {
942
0
                    newOption = PR_TRUE;
943
0
                }
944
0
                if ((newOption || algOpt->name_size == length) &&
945
0
                    PORT_Strncasecmp(algOpt->name, cipher, name_size) == 0) {
946
0
                    PRUint32 value = algOpt->val;
947
0
                    if (newOption) {
948
0
                        value = secmod_parsePolicyValue(&cipher[name_size] + 1,
949
0
                                                        length - name_size - 1,
950
0
                                                        printPolicyFeedback,
951
0
                                                        policyCheckFlags);
952
0
                    }
953
0
                    rv = secmod_setPolicyOperation(algOptList->list[j].oid, operation, value);
954
0
                    if (rv != SECSuccess) {
955
                        /* could not enable option */
956
                        /* NSS_SetAlgorithPolicy should have set the error code */
957
0
                        return SECFailure;
958
0
                    }
959
0
                    unknown = PR_FALSE;
960
0
                    break;
961
0
                }
962
0
            }
963
0
        }
964
0
        if (!unknown) {
965
0
            continue;
966
0
        }
967
968
0
        for (i = 0; i < PR_ARRAY_SIZE(freeOptList); i++) {
969
0
            const optionFreeDef *freeOpt = &freeOptList[i];
970
0
            unsigned name_size = freeOpt->name_size;
971
972
0
            if ((length > name_size) && cipher[name_size] == '=' &&
973
0
                PORT_Strncasecmp(freeOpt->name, cipher, name_size) == 0) {
974
0
                PRInt32 val;
975
0
                const char *policyValue = &cipher[name_size + 1];
976
0
                int policyValueLength = length - name_size - 1;
977
0
                rv = secmod_getPolicyOptValue(policyValue, policyValueLength,
978
0
                                              &val);
979
0
                if (rv != SECSuccess) {
980
0
                    if (printPolicyFeedback &&
981
0
                        (policyCheckFlags & SECMOD_FLAG_POLICY_CHECK_VALUE)) {
982
0
                        PR_SetEnv("NSS_POLICY_FAIL=1");
983
0
                        fprintf(stderr, "NSS-POLICY-FAIL %.*s: unknown value: %.*s\n",
984
0
                                length, cipher, policyValueLength, policyValue);
985
0
                    }
986
0
                    return SECFailure;
987
0
                }
988
0
                rv = NSS_OptionSet(freeOpt->option, val);
989
0
                if (rv != SECSuccess) {
990
                    /* could not enable option */
991
                    /* NSS_OptionSet should have set the error code */
992
0
                    return SECFailure;
993
0
                }
994
                /* to allow the policy to expand in the future. ignore ciphers
995
                 * we don't understand */
996
0
                unknown = PR_FALSE;
997
0
                break;
998
0
            }
999
0
        }
1000
1001
0
        if (unknown && printPolicyFeedback &&
1002
0
            (policyCheckFlags & SECMOD_FLAG_POLICY_CHECK_IDENTIFIER)) {
1003
0
            PR_SetEnv("NSS_POLICY_FAIL=1");
1004
0
            fprintf(stderr, "NSS-POLICY-FAIL %s: unknown identifier: %.*s\n",
1005
0
                    secmod_getOperationString(operation), length, cipher);
1006
0
        }
1007
0
    }
1008
0
    return rv;
1009
0
}
1010
1011
static void
1012
secmod_sanityCheckCryptoPolicy(void)
1013
0
{
1014
0
    unsigned i, j;
1015
0
    SECStatus rv = SECSuccess;
1016
0
    unsigned num_kx_enabled = 0;
1017
0
    unsigned num_ssl_enabled = 0;
1018
0
    unsigned num_sig_enabled = 0;
1019
0
    unsigned enabledCount[PR_ARRAY_SIZE(algOptLists)];
1020
0
    const char *sWarn = "WARN";
1021
0
    const char *sInfo = "INFO";
1022
0
    PRBool haveWarning = PR_FALSE;
1023
1024
0
    for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) {
1025
0
        const algListsDef *algOptList = &algOptLists[i];
1026
0
        enabledCount[i] = 0;
1027
0
        for (j = 0; j < algOptList->entries; j++) {
1028
0
            const oidValDef *algOpt = &algOptList->list[j];
1029
0
            PRUint32 value;
1030
0
            PRBool anyEnabled = PR_FALSE;
1031
0
            rv = NSS_GetAlgorithmPolicy(algOpt->oid, &value);
1032
0
            if (rv != SECSuccess) {
1033
0
                PR_SetEnv("NSS_POLICY_FAIL=1");
1034
0
                fprintf(stderr, "NSS-POLICY-FAIL: internal failure with NSS_GetAlgorithmPolicy at %u\n", i);
1035
0
                return;
1036
0
            }
1037
1038
0
            if ((algOpt->val & NSS_USE_ALG_IN_SSL_KX) && (value & NSS_USE_ALG_IN_SSL_KX)) {
1039
0
                ++num_kx_enabled;
1040
0
                anyEnabled = PR_TRUE;
1041
0
                fprintf(stderr, "NSS-POLICY-INFO: %s is enabled for SSL-KX\n", algOpt->name);
1042
0
            }
1043
0
            if ((algOpt->val & NSS_USE_ALG_IN_SSL) && (value & NSS_USE_ALG_IN_SSL)) {
1044
0
                ++num_ssl_enabled;
1045
0
                anyEnabled = PR_TRUE;
1046
0
                fprintf(stderr, "NSS-POLICY-INFO: %s is enabled for SSL\n", algOpt->name);
1047
0
            }
1048
0
            if ((algOpt->val & NSS_USE_ALG_IN_CERT_SIGNATURE) &&
1049
0
                ((value & NSS_USE_CERT_SIGNATURE_OK) == NSS_USE_CERT_SIGNATURE_OK)) {
1050
0
                ++num_sig_enabled;
1051
0
                anyEnabled = PR_TRUE;
1052
0
                fprintf(stderr, "NSS-POLICY-INFO: %s is enabled for CERT-SIGNATURE\n", algOpt->name);
1053
0
            }
1054
0
            if (anyEnabled) {
1055
0
                ++enabledCount[i];
1056
0
            }
1057
0
        }
1058
0
    }
1059
0
    fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-SSL-ALG-KX: %u\n", num_kx_enabled ? sInfo : sWarn, num_kx_enabled);
1060
0
    fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-SSL-ALG: %u\n", num_ssl_enabled ? sInfo : sWarn, num_ssl_enabled);
1061
0
    fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-CERT-SIG: %u\n", num_sig_enabled ? sInfo : sWarn, num_sig_enabled);
1062
0
    if (!num_kx_enabled || !num_ssl_enabled || !num_sig_enabled) {
1063
0
        haveWarning = PR_TRUE;
1064
0
    }
1065
0
    for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) {
1066
0
        const algListsDef *algOptList = &algOptLists[i];
1067
0
        fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-%s: %u\n", enabledCount[i] ? sInfo : sWarn, algOptList->description, enabledCount[i]);
1068
0
        if (!enabledCount[i] && !algOptList->allowEmpty) {
1069
0
            haveWarning = PR_TRUE;
1070
0
        }
1071
0
    }
1072
0
    if (haveWarning) {
1073
0
        PR_SetEnv("NSS_POLICY_WARN=1");
1074
0
    }
1075
0
}
1076
1077
static SECStatus
1078
secmod_parseCryptoPolicy(const char *policyConfig, PRBool printPolicyFeedback,
1079
                         PRUint32 policyCheckFlags)
1080
32
{
1081
32
    char *args;
1082
32
    SECStatus rv;
1083
1084
32
    if (policyConfig == NULL) {
1085
32
        return SECSuccess; /* no policy given */
1086
32
    }
1087
    /* make sure we initialize the oid table and set all the default policy
1088
     * values first so we can override them here */
1089
0
    rv = SECOID_Init();
1090
0
    if (rv != SECSuccess) {
1091
0
        return rv;
1092
0
    }
1093
0
    args = NSSUTIL_ArgGetParamValue("disallow", policyConfig);
1094
0
    rv = secmod_applyCryptoPolicy(args, NSS_DISALLOW, printPolicyFeedback,
1095
0
                                  policyCheckFlags);
1096
0
    if (args)
1097
0
        PORT_Free(args);
1098
0
    if (rv != SECSuccess) {
1099
0
        return rv;
1100
0
    }
1101
0
    args = NSSUTIL_ArgGetParamValue("allow", policyConfig);
1102
0
    rv = secmod_applyCryptoPolicy(args, NSS_ALLOW, printPolicyFeedback,
1103
0
                                  policyCheckFlags);
1104
0
    if (args)
1105
0
        PORT_Free(args);
1106
0
    if (rv != SECSuccess) {
1107
0
        return rv;
1108
0
    }
1109
0
    args = NSSUTIL_ArgGetParamValue("disable", policyConfig);
1110
0
    rv = secmod_applyCryptoPolicy(args, NSS_DISABLE, printPolicyFeedback,
1111
0
                                  policyCheckFlags);
1112
0
    if (args)
1113
0
        PORT_Free(args);
1114
0
    if (rv != SECSuccess) {
1115
0
        return rv;
1116
0
    }
1117
0
    args = NSSUTIL_ArgGetParamValue("enable", policyConfig);
1118
0
    rv = secmod_applyCryptoPolicy(args, NSS_ENABLE, printPolicyFeedback,
1119
0
                                  policyCheckFlags);
1120
0
    if (args)
1121
0
        PORT_Free(args);
1122
0
    if (rv != SECSuccess) {
1123
0
        return rv;
1124
0
    }
1125
    /* this has to be last. Everything after this will be a noop */
1126
0
    if (NSSUTIL_ArgHasFlag("flags", "ssl-lock", policyConfig)) {
1127
0
        PRInt32 locks;
1128
        /* don't overwrite other (future) lock flags */
1129
0
        rv = NSS_OptionGet(NSS_DEFAULT_LOCKS, &locks);
1130
0
        if (rv == SECSuccess) {
1131
0
            rv = NSS_OptionSet(NSS_DEFAULT_LOCKS, locks | NSS_DEFAULT_SSL_LOCK);
1132
0
        }
1133
0
        if (rv != SECSuccess) {
1134
0
            return rv;
1135
0
        }
1136
0
    }
1137
0
    if (NSSUTIL_ArgHasFlag("flags", "policy-lock", policyConfig)) {
1138
0
        NSS_LockPolicy();
1139
0
    }
1140
0
    if (printPolicyFeedback) {
1141
        /* This helps to distinguish configurations that don't contain any
1142
         * policy config= statement. */
1143
0
        PR_SetEnv("NSS_POLICY_LOADED=1");
1144
0
        fprintf(stderr, "NSS-POLICY-INFO: LOADED-SUCCESSFULLY\n");
1145
0
        secmod_sanityCheckCryptoPolicy();
1146
0
    }
1147
0
    return rv;
1148
0
}
1149
1150
static PRUint32
1151
secmod_parsePolicyCheckFlags(const char *nss)
1152
64
{
1153
64
    PRUint32 policyCheckFlags = 0;
1154
1155
64
    if (NSSUTIL_ArgHasFlag("flags", "policyCheckIdentifier", nss)) {
1156
0
        policyCheckFlags |= SECMOD_FLAG_POLICY_CHECK_IDENTIFIER;
1157
0
    }
1158
1159
64
    if (NSSUTIL_ArgHasFlag("flags", "policyCheckValue", nss)) {
1160
0
        policyCheckFlags |= SECMOD_FLAG_POLICY_CHECK_VALUE;
1161
0
    }
1162
1163
64
    return policyCheckFlags;
1164
64
}
1165
1166
/*
1167
 * for 3.4 we continue to use the old SECMODModule structure
1168
 */
1169
SECMODModule *
1170
SECMOD_CreateModuleEx(const char *library, const char *moduleName,
1171
                      const char *parameters, const char *nss,
1172
                      const char *config)
1173
32
{
1174
32
    SECMODModule *mod;
1175
32
    SECStatus rv;
1176
32
    char *slotParams, *ciphers;
1177
32
    PRBool printPolicyFeedback = NSSUTIL_ArgHasFlag("flags", "printPolicyFeedback", nss);
1178
32
    PRUint32 policyCheckFlags = secmod_parsePolicyCheckFlags(nss);
1179
1180
32
    rv = secmod_parseCryptoPolicy(config, printPolicyFeedback, policyCheckFlags);
1181
1182
    /* do not load the module if policy parsing fails */
1183
32
    if (rv != SECSuccess) {
1184
0
        if (printPolicyFeedback) {
1185
0
            PR_SetEnv("NSS_POLICY_FAIL=1");
1186
0
            fprintf(stderr, "NSS-POLICY-FAIL: policy config parsing failed, not loading module %s\n", moduleName);
1187
0
        }
1188
0
        return NULL;
1189
0
    }
1190
1191
32
    mod = secmod_NewModule();
1192
32
    if (mod == NULL)
1193
0
        return NULL;
1194
1195
32
    mod->commonName = PORT_ArenaStrdup(mod->arena, moduleName ? moduleName : "");
1196
32
    if (library) {
1197
0
        mod->dllName = PORT_ArenaStrdup(mod->arena, library);
1198
0
    }
1199
    /* new field */
1200
32
    if (parameters) {
1201
32
        mod->libraryParams = PORT_ArenaStrdup(mod->arena, parameters);
1202
32
    }
1203
1204
32
    mod->internal = NSSUTIL_ArgHasFlag("flags", "internal", nss);
1205
32
    mod->isFIPS = NSSUTIL_ArgHasFlag("flags", "FIPS", nss);
1206
    /* if the system FIPS mode is enabled, force FIPS to be on */
1207
32
    if (SECMOD_GetSystemFIPSEnabled()) {
1208
0
        mod->isFIPS = PR_TRUE;
1209
0
    }
1210
32
    mod->isCritical = NSSUTIL_ArgHasFlag("flags", "critical", nss);
1211
32
    slotParams = NSSUTIL_ArgGetParamValue("slotParams", nss);
1212
32
    mod->slotInfo = NSSUTIL_ArgParseSlotInfo(mod->arena, slotParams,
1213
32
                                             &mod->slotInfoCount);
1214
32
    if (slotParams)
1215
16
        PORT_Free(slotParams);
1216
    /* new field */
1217
32
    mod->trustOrder = NSSUTIL_ArgReadLong("trustOrder", nss,
1218
32
                                          NSSUTIL_DEFAULT_TRUST_ORDER, NULL);
1219
    /* new field */
1220
32
    mod->cipherOrder = NSSUTIL_ArgReadLong("cipherOrder", nss,
1221
32
                                           NSSUTIL_DEFAULT_CIPHER_ORDER, NULL);
1222
    /* new field */
1223
32
    mod->isModuleDB = NSSUTIL_ArgHasFlag("flags", "moduleDB", nss);
1224
32
    mod->moduleDBOnly = NSSUTIL_ArgHasFlag("flags", "moduleDBOnly", nss);
1225
32
    if (mod->moduleDBOnly)
1226
16
        mod->isModuleDB = PR_TRUE;
1227
1228
    /* we need more bits, but we also want to preserve binary compatibility
1229
     * so we overload the isModuleDB PRBool with additional flags.
1230
     * These flags are only valid if mod->isModuleDB is already set.
1231
     * NOTE: this depends on the fact that PRBool is at least a char on
1232
     * all platforms. These flags are only valid if moduleDB is set, so
1233
     * code checking if (mod->isModuleDB) will continue to work correctly. */
1234
32
    if (mod->isModuleDB) {
1235
16
        char flags = SECMOD_FLAG_MODULE_DB_IS_MODULE_DB;
1236
16
        if (NSSUTIL_ArgHasFlag("flags", "skipFirst", nss)) {
1237
0
            flags |= SECMOD_FLAG_MODULE_DB_SKIP_FIRST;
1238
0
        }
1239
16
        if (NSSUTIL_ArgHasFlag("flags", "defaultModDB", nss)) {
1240
16
            flags |= SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB;
1241
16
        }
1242
16
        if (NSSUTIL_ArgHasFlag("flags", "policyOnly", nss)) {
1243
0
            flags |= SECMOD_FLAG_MODULE_DB_POLICY_ONLY;
1244
0
        }
1245
        /* additional moduleDB flags could be added here in the future */
1246
16
        mod->isModuleDB = (PRBool)flags;
1247
16
    }
1248
1249
32
    if (mod->internal) {
1250
32
        char flags = SECMOD_FLAG_INTERNAL_IS_INTERNAL;
1251
1252
32
        if (NSSUTIL_ArgHasFlag("flags", "internalKeySlot", nss)) {
1253
16
            flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT;
1254
16
        }
1255
32
        mod->internal = (PRBool)flags;
1256
32
    }
1257
1258
32
    ciphers = NSSUTIL_ArgGetParamValue("ciphers", nss);
1259
32
    NSSUTIL_ArgParseCipherFlags(&mod->ssl[0], ciphers);
1260
32
    if (ciphers)
1261
0
        PORT_Free(ciphers);
1262
1263
32
    secmod_PrivateModuleCount++;
1264
1265
32
    return mod;
1266
32
}
1267
1268
PRBool
1269
SECMOD_GetSkipFirstFlag(SECMODModule *mod)
1270
16
{
1271
16
    char flags = (char)mod->isModuleDB;
1272
1273
16
    return (flags & SECMOD_FLAG_MODULE_DB_SKIP_FIRST) ? PR_TRUE : PR_FALSE;
1274
16
}
1275
1276
PRBool
1277
SECMOD_GetDefaultModDBFlag(SECMODModule *mod)
1278
0
{
1279
0
    char flags = (char)mod->isModuleDB;
1280
1281
0
    return (flags & SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB) ? PR_TRUE : PR_FALSE;
1282
0
}
1283
1284
PRBool
1285
secmod_PolicyOnly(SECMODModule *mod)
1286
32
{
1287
32
    char flags = (char)mod->isModuleDB;
1288
1289
32
    return (flags & SECMOD_FLAG_MODULE_DB_POLICY_ONLY) ? PR_TRUE : PR_FALSE;
1290
32
}
1291
1292
PRBool
1293
secmod_IsInternalKeySlot(SECMODModule *mod)
1294
48
{
1295
48
    char flags = (char)mod->internal;
1296
1297
48
    return (flags & SECMOD_FLAG_INTERNAL_KEY_SLOT) ? PR_TRUE : PR_FALSE;
1298
48
}
1299
1300
void
1301
secmod_SetInternalKeySlotFlag(SECMODModule *mod, PRBool val)
1302
0
{
1303
0
    char flags = (char)mod->internal;
1304
1305
0
    if (val) {
1306
0
        flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT;
1307
0
    } else {
1308
0
        flags &= ~SECMOD_FLAG_INTERNAL_KEY_SLOT;
1309
0
    }
1310
0
    mod->internal = flags;
1311
0
}
1312
1313
/*
1314
 * copy desc and value into target. Target is known to be big enough to
1315
 * hold desc +2 +value, which is good because the result of this will be
1316
 * *desc"*value". We may, however, have to add some escapes for special
1317
 * characters imbedded into value (rare). This string potentially comes from
1318
 * a user, so we don't want the user overflowing the target buffer by using
1319
 * excessive escapes. To prevent this we count the escapes we need to add and
1320
 * try to expand the buffer with Realloc.
1321
 */
1322
static char *
1323
secmod_doDescCopy(char *target, char **base, int *baseLen,
1324
                  const char *desc, int descLen, char *value)
1325
0
{
1326
0
    int diff, esc_len;
1327
1328
0
    esc_len = NSSUTIL_EscapeSize(value, '\"') - 1;
1329
0
    diff = esc_len - strlen(value);
1330
0
    if (diff > 0) {
1331
        /* we need to escape... expand newSpecPtr as well to make sure
1332
         * we don't overflow it */
1333
0
        int offset = target - *base;
1334
0
        char *newPtr = PORT_Realloc(*base, *baseLen + diff);
1335
0
        if (!newPtr) {
1336
0
            return target; /* not enough space, just drop the whole copy */
1337
0
        }
1338
0
        *baseLen += diff;
1339
0
        target = newPtr + offset;
1340
0
        *base = newPtr;
1341
0
        value = NSSUTIL_Escape(value, '\"');
1342
0
        if (value == NULL) {
1343
0
            return target; /* couldn't escape value, just drop the copy */
1344
0
        }
1345
0
    }
1346
0
    PORT_Memcpy(target, desc, descLen);
1347
0
    target += descLen;
1348
0
    *target++ = '\"';
1349
0
    PORT_Memcpy(target, value, esc_len);
1350
0
    target += esc_len;
1351
0
    *target++ = '\"';
1352
0
    if (diff > 0) {
1353
0
        PORT_Free(value);
1354
0
    }
1355
0
    return target;
1356
0
}
1357
1358
#define SECMOD_SPEC_COPY(new, start, end) \
1359
0
    if (end > start) {                    \
1360
0
        int _cnt = end - start;           \
1361
0
        PORT_Memcpy(new, start, _cnt);    \
1362
0
        new += _cnt;                      \
1363
0
    }
1364
#define SECMOD_TOKEN_DESCRIPTION "tokenDescription="
1365
#define SECMOD_SLOT_DESCRIPTION "slotDescription="
1366
1367
/*
1368
 * Find any tokens= values in the module spec.
1369
 * Always return a new spec which does not have any tokens= arguments.
1370
 * If tokens= arguments are found, Split the the various tokens defined into
1371
 * an array of child specs to return.
1372
 *
1373
 * Caller is responsible for freeing the child spec and the new token
1374
 * spec.
1375
 */
1376
char *
1377
secmod_ParseModuleSpecForTokens(PRBool convert, PRBool isFIPS,
1378
                                const char *moduleSpec, char ***children,
1379
                                CK_SLOT_ID **ids)
1380
0
{
1381
0
    int newSpecLen = PORT_Strlen(moduleSpec) + 2;
1382
0
    char *newSpec = PORT_Alloc(newSpecLen);
1383
0
    char *newSpecPtr = newSpec;
1384
0
    const char *modulePrev = moduleSpec;
1385
0
    char *target = NULL;
1386
0
    char *tmp = NULL;
1387
0
    char **childArray = NULL;
1388
0
    const char *tokenIndex;
1389
0
    CK_SLOT_ID *idArray = NULL;
1390
0
    int tokenCount = 0;
1391
0
    int i;
1392
1393
0
    if (newSpec == NULL) {
1394
0
        return NULL;
1395
0
    }
1396
1397
0
    *children = NULL;
1398
0
    if (ids) {
1399
0
        *ids = NULL;
1400
0
    }
1401
0
    moduleSpec = NSSUTIL_ArgStrip(moduleSpec);
1402
0
    SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec);
1403
1404
    /* Notes on 'convert' and 'isFIPS' flags: The base parameters for opening
1405
     * a new softoken module takes the following parameters to name the
1406
     * various tokens:
1407
     *
1408
     *  cryptoTokenDescription: name of the non-fips crypto token.
1409
     *  cryptoSlotDescription: name of the non-fips crypto slot.
1410
     *  dbTokenDescription: name of the non-fips db token.
1411
     *  dbSlotDescription: name of the non-fips db slot.
1412
     *  FIPSTokenDescription: name of the fips db/crypto token.
1413
     *  FIPSSlotDescription: name of the fips db/crypto slot.
1414
     *
1415
     * if we are opening a new slot, we need to have the following
1416
     * parameters:
1417
     *  tokenDescription: name of the token.
1418
     *  slotDescription: name of the slot.
1419
     *
1420
     *
1421
     * The convert flag tells us to drop the unnecessary *TokenDescription
1422
     * and *SlotDescription arguments and convert the appropriate pair
1423
     * (either db or FIPS based on the isFIPS flag) to tokenDescription and
1424
     * slotDescription).
1425
     */
1426
    /*
1427
     * walk down the list. if we find a tokens= argument, save it,
1428
     * otherise copy the argument.
1429
     */
1430
0
    while (*moduleSpec) {
1431
0
        int next;
1432
0
        modulePrev = moduleSpec;
1433
0
        NSSUTIL_HANDLE_STRING_ARG(moduleSpec, target, "tokens=",
1434
0
                                  modulePrev = moduleSpec;
1435
0
                                  /* skip copying */)
1436
0
        NSSUTIL_HANDLE_STRING_ARG(
1437
0
            moduleSpec, tmp, "cryptoTokenDescription=",
1438
0
            if (convert) { modulePrev = moduleSpec; })
1439
0
        NSSUTIL_HANDLE_STRING_ARG(
1440
0
            moduleSpec, tmp, "cryptoSlotDescription=",
1441
0
            if (convert) { modulePrev = moduleSpec; })
1442
0
        NSSUTIL_HANDLE_STRING_ARG(
1443
0
            moduleSpec, tmp, "dbTokenDescription=",
1444
0
            if (convert) {
1445
0
                modulePrev = moduleSpec;
1446
0
                if (!isFIPS) {
1447
0
                    newSpecPtr = secmod_doDescCopy(newSpecPtr,
1448
0
                                                   &newSpec, &newSpecLen,
1449
0
                                                   SECMOD_TOKEN_DESCRIPTION,
1450
0
                                                   sizeof(SECMOD_TOKEN_DESCRIPTION) - 1,
1451
0
                                                   tmp);
1452
0
                }
1453
0
            })
1454
0
        NSSUTIL_HANDLE_STRING_ARG(
1455
0
            moduleSpec, tmp, "dbSlotDescription=",
1456
0
            if (convert) {
1457
0
                modulePrev = moduleSpec; /* skip copying */
1458
0
                if (!isFIPS) {
1459
0
                    newSpecPtr = secmod_doDescCopy(newSpecPtr,
1460
0
                                                   &newSpec, &newSpecLen,
1461
0
                                                   SECMOD_SLOT_DESCRIPTION,
1462
0
                                                   sizeof(SECMOD_SLOT_DESCRIPTION) - 1,
1463
0
                                                   tmp);
1464
0
                }
1465
0
            })
1466
0
        NSSUTIL_HANDLE_STRING_ARG(
1467
0
            moduleSpec, tmp, "FIPSTokenDescription=",
1468
0
            if (convert) {
1469
0
                modulePrev = moduleSpec; /* skip copying */
1470
0
                if (isFIPS) {
1471
0
                    newSpecPtr = secmod_doDescCopy(newSpecPtr,
1472
0
                                                   &newSpec, &newSpecLen,
1473
0
                                                   SECMOD_TOKEN_DESCRIPTION,
1474
0
                                                   sizeof(SECMOD_TOKEN_DESCRIPTION) - 1,
1475
0
                                                   tmp);
1476
0
                }
1477
0
            })
1478
0
        NSSUTIL_HANDLE_STRING_ARG(
1479
0
            moduleSpec, tmp, "FIPSSlotDescription=",
1480
0
            if (convert) {
1481
0
                modulePrev = moduleSpec; /* skip copying */
1482
0
                if (isFIPS) {
1483
0
                    newSpecPtr = secmod_doDescCopy(newSpecPtr,
1484
0
                                                   &newSpec, &newSpecLen,
1485
0
                                                   SECMOD_SLOT_DESCRIPTION,
1486
0
                                                   sizeof(SECMOD_SLOT_DESCRIPTION) - 1,
1487
0
                                                   tmp);
1488
0
                }
1489
0
            })
1490
0
        NSSUTIL_HANDLE_FINAL_ARG(moduleSpec)
1491
0
        SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec);
1492
0
    }
1493
0
    if (tmp) {
1494
0
        PORT_Free(tmp);
1495
0
        tmp = NULL;
1496
0
    }
1497
0
    *newSpecPtr = 0;
1498
1499
    /* no target found, return the newSpec */
1500
0
    if (target == NULL) {
1501
0
        return newSpec;
1502
0
    }
1503
1504
    /* now build the child array from target */
1505
    /*first count them */
1506
0
    for (tokenIndex = NSSUTIL_ArgStrip(target); *tokenIndex;
1507
0
         tokenIndex = NSSUTIL_ArgStrip(NSSUTIL_ArgSkipParameter(tokenIndex))) {
1508
0
        tokenCount++;
1509
0
    }
1510
1511
0
    childArray = PORT_NewArray(char *, tokenCount + 1);
1512
0
    if (childArray == NULL) {
1513
        /* just return the spec as is then */
1514
0
        PORT_Free(target);
1515
0
        return newSpec;
1516
0
    }
1517
0
    if (ids) {
1518
0
        idArray = PORT_NewArray(CK_SLOT_ID, tokenCount + 1);
1519
0
        if (idArray == NULL) {
1520
0
            PORT_Free(childArray);
1521
0
            PORT_Free(target);
1522
0
            return newSpec;
1523
0
        }
1524
0
    }
1525
1526
    /* now fill them in */
1527
0
    for (tokenIndex = NSSUTIL_ArgStrip(target), i = 0;
1528
0
         *tokenIndex && (i < tokenCount);
1529
0
         tokenIndex = NSSUTIL_ArgStrip(tokenIndex)) {
1530
0
        int next;
1531
0
        char *name = NSSUTIL_ArgGetLabel(tokenIndex, &next);
1532
0
        tokenIndex += next;
1533
1534
0
        if (idArray) {
1535
0
            idArray[i] = NSSUTIL_ArgDecodeNumber(name);
1536
0
        }
1537
1538
0
        PORT_Free(name); /* drop the explicit number */
1539
1540
        /* if anything is left, copy the args to the child array */
1541
0
        if (!NSSUTIL_ArgIsBlank(*tokenIndex)) {
1542
0
            childArray[i++] = NSSUTIL_ArgFetchValue(tokenIndex, &next);
1543
0
            tokenIndex += next;
1544
0
        }
1545
0
    }
1546
1547
0
    PORT_Free(target);
1548
0
    childArray[i] = 0;
1549
0
    if (idArray) {
1550
0
        idArray[i] = 0;
1551
0
    }
1552
1553
    /* return it */
1554
0
    *children = childArray;
1555
0
    if (ids) {
1556
0
        *ids = idArray;
1557
0
    }
1558
0
    return newSpec;
1559
0
}
1560
1561
/* get the database and flags from the spec */
1562
static char *
1563
secmod_getConfigDir(const char *spec, char **certPrefix, char **keyPrefix,
1564
                    PRBool *readOnly)
1565
0
{
1566
0
    char *config = NULL;
1567
1568
0
    *certPrefix = NULL;
1569
0
    *keyPrefix = NULL;
1570
0
    *readOnly = NSSUTIL_ArgHasFlag("flags", "readOnly", spec);
1571
0
    if (NSSUTIL_ArgHasFlag("flags", "nocertdb", spec) ||
1572
0
        NSSUTIL_ArgHasFlag("flags", "nokeydb", spec)) {
1573
0
        return NULL;
1574
0
    }
1575
1576
0
    spec = NSSUTIL_ArgStrip(spec);
1577
0
    while (*spec) {
1578
0
        int next;
1579
0
        NSSUTIL_HANDLE_STRING_ARG(spec, config, "configdir=", ;)
1580
0
        NSSUTIL_HANDLE_STRING_ARG(spec, *certPrefix, "certPrefix=", ;)
1581
0
        NSSUTIL_HANDLE_STRING_ARG(spec, *keyPrefix, "keyPrefix=", ;)
1582
0
        NSSUTIL_HANDLE_FINAL_ARG(spec)
1583
0
    }
1584
0
    return config;
1585
0
}
1586
1587
struct SECMODConfigListStr {
1588
    char *config;
1589
    char *certPrefix;
1590
    char *keyPrefix;
1591
    PRBool isReadOnly;
1592
};
1593
1594
/*
1595
 * return an array of already openned databases from a spec list.
1596
 */
1597
SECMODConfigList *
1598
secmod_GetConfigList(PRBool isFIPS, char *spec, int *count)
1599
0
{
1600
0
    char **children;
1601
0
    CK_SLOT_ID *ids;
1602
0
    char *strippedSpec;
1603
0
    int childCount;
1604
0
    SECMODConfigList *conflist = NULL;
1605
0
    int i;
1606
1607
0
    strippedSpec = secmod_ParseModuleSpecForTokens(PR_TRUE, isFIPS,
1608
0
                                                   spec, &children, &ids);
1609
0
    if (strippedSpec == NULL) {
1610
0
        return NULL;
1611
0
    }
1612
1613
0
    for (childCount = 0; children && children[childCount]; childCount++)
1614
0
        ;
1615
0
    *count = childCount + 1; /* include strippedSpec */
1616
0
    conflist = PORT_NewArray(SECMODConfigList, *count);
1617
0
    if (conflist == NULL) {
1618
0
        *count = 0;
1619
0
        goto loser;
1620
0
    }
1621
1622
0
    conflist[0].config = secmod_getConfigDir(strippedSpec,
1623
0
                                             &conflist[0].certPrefix,
1624
0
                                             &conflist[0].keyPrefix,
1625
0
                                             &conflist[0].isReadOnly);
1626
0
    for (i = 0; i < childCount; i++) {
1627
0
        conflist[i + 1].config = secmod_getConfigDir(children[i],
1628
0
                                                     &conflist[i + 1].certPrefix,
1629
0
                                                     &conflist[i + 1].keyPrefix,
1630
0
                                                     &conflist[i + 1].isReadOnly);
1631
0
    }
1632
1633
0
loser:
1634
0
    secmod_FreeChildren(children, ids);
1635
0
    PORT_Free(strippedSpec);
1636
0
    return conflist;
1637
0
}
1638
1639
/*
1640
 * determine if we are trying to open an old dbm database. For this test
1641
 * RDB databases should return PR_FALSE.
1642
 */
1643
static PRBool
1644
secmod_configIsDBM(char *configDir)
1645
0
{
1646
0
    char *env;
1647
1648
    /* explicit dbm open */
1649
0
    if (strncmp(configDir, "dbm:", 4) == 0) {
1650
0
        return PR_TRUE;
1651
0
    }
1652
    /* explicit open of a non-dbm database */
1653
0
    if ((strncmp(configDir, "sql:", 4) == 0) ||
1654
0
        (strncmp(configDir, "rdb:", 4) == 0) ||
1655
0
        (strncmp(configDir, "extern:", 7) == 0)) {
1656
0
        return PR_FALSE;
1657
0
    }
1658
0
    env = PR_GetEnvSecure("NSS_DEFAULT_DB_TYPE");
1659
    /* implicit dbm open */
1660
0
    if ((env == NULL) || (strcmp(env, "dbm") == 0)) {
1661
0
        return PR_TRUE;
1662
0
    }
1663
    /* implicit non-dbm open */
1664
0
    return PR_FALSE;
1665
0
}
1666
1667
/*
1668
 * match two prefixes. prefix may be NULL. NULL patches '\0'
1669
 */
1670
static PRBool
1671
secmod_matchPrefix(char *prefix1, char *prefix2)
1672
0
{
1673
0
    if ((prefix1 == NULL) || (*prefix1 == 0)) {
1674
0
        if ((prefix2 == NULL) || (*prefix2 == 0)) {
1675
0
            return PR_TRUE;
1676
0
        }
1677
0
        return PR_FALSE;
1678
0
    }
1679
0
    if (strcmp(prefix1, prefix2) == 0) {
1680
0
        return PR_TRUE;
1681
0
    }
1682
0
    return PR_FALSE;
1683
0
}
1684
1685
/* do two config paramters match? Not all callers are compariing
1686
 * SECMODConfigLists directly, so this function breaks them out to their
1687
 * components. */
1688
static PRBool
1689
secmod_matchConfig(char *configDir1, char *configDir2,
1690
                   char *certPrefix1, char *certPrefix2,
1691
                   char *keyPrefix1, char *keyPrefix2,
1692
                   PRBool isReadOnly1, PRBool isReadOnly2)
1693
0
{
1694
    /* TODO: Document the answer to the question:
1695
     *       "Why not allow them to match if they are both NULL?"
1696
     * See: https://bugzilla.mozilla.org/show_bug.cgi?id=1318633#c1
1697
     */
1698
0
    if ((configDir1 == NULL) || (configDir2 == NULL)) {
1699
0
        return PR_FALSE;
1700
0
    }
1701
0
    if (strcmp(configDir1, configDir2) != 0) {
1702
0
        return PR_FALSE;
1703
0
    }
1704
0
    if (!secmod_matchPrefix(certPrefix1, certPrefix2)) {
1705
0
        return PR_FALSE;
1706
0
    }
1707
0
    if (!secmod_matchPrefix(keyPrefix1, keyPrefix2)) {
1708
0
        return PR_FALSE;
1709
0
    }
1710
    /* these last test -- if we just need the DB open read only,
1711
     * than any open will suffice, but if we requested it read/write
1712
     * and it's only open read only, we need to open it again */
1713
0
    if (isReadOnly1) {
1714
0
        return PR_TRUE;
1715
0
    }
1716
0
    if (isReadOnly2) { /* isReadonly1 == PR_FALSE */
1717
0
        return PR_FALSE;
1718
0
    }
1719
0
    return PR_TRUE;
1720
0
}
1721
1722
/*
1723
 * return true if we are requesting a database that is already openned.
1724
 */
1725
PRBool
1726
secmod_MatchConfigList(const char *spec, SECMODConfigList *conflist, int count)
1727
0
{
1728
0
    char *config;
1729
0
    char *certPrefix;
1730
0
    char *keyPrefix;
1731
0
    PRBool isReadOnly;
1732
0
    PRBool ret = PR_FALSE;
1733
0
    int i;
1734
1735
0
    config = secmod_getConfigDir(spec, &certPrefix, &keyPrefix, &isReadOnly);
1736
0
    if (!config) {
1737
0
        goto done;
1738
0
    }
1739
1740
    /* NOTE: we dbm isn't multiple open safe. If we open the same database
1741
     * twice from two different locations, then we can corrupt our database
1742
     * (the cache will be inconsistent). Protect against this by claiming
1743
     * for comparison only that we are always openning dbm databases read only.
1744
     */
1745
0
    if (secmod_configIsDBM(config)) {
1746
0
        isReadOnly = 1;
1747
0
    }
1748
0
    for (i = 0; i < count; i++) {
1749
0
        if (secmod_matchConfig(config, conflist[i].config, certPrefix,
1750
0
                               conflist[i].certPrefix, keyPrefix,
1751
0
                               conflist[i].keyPrefix, isReadOnly,
1752
0
                               conflist[i].isReadOnly)) {
1753
0
            ret = PR_TRUE;
1754
0
            goto done;
1755
0
        }
1756
0
    }
1757
1758
0
    ret = PR_FALSE;
1759
0
done:
1760
0
    PORT_Free(config);
1761
0
    PORT_Free(certPrefix);
1762
0
    PORT_Free(keyPrefix);
1763
0
    return ret;
1764
0
}
1765
1766
/*
1767
 * Find the slot id from the module spec. If the slot is the database slot, we
1768
 * can get the slot id from the default database slot.
1769
 */
1770
CK_SLOT_ID
1771
secmod_GetSlotIDFromModuleSpec(const char *moduleSpec, SECMODModule *module)
1772
0
{
1773
0
    char *tmp_spec = NULL;
1774
0
    char **children, **thisChild;
1775
0
    CK_SLOT_ID *ids, *thisID, slotID = -1;
1776
0
    char *inConfig = NULL, *thisConfig = NULL;
1777
0
    char *inCertPrefix = NULL, *thisCertPrefix = NULL;
1778
0
    char *inKeyPrefix = NULL, *thisKeyPrefix = NULL;
1779
0
    PRBool inReadOnly, thisReadOnly;
1780
1781
0
    inConfig = secmod_getConfigDir(moduleSpec, &inCertPrefix, &inKeyPrefix,
1782
0
                                   &inReadOnly);
1783
0
    if (!inConfig) {
1784
0
        goto done;
1785
0
    }
1786
1787
0
    if (secmod_configIsDBM(inConfig)) {
1788
0
        inReadOnly = 1;
1789
0
    }
1790
1791
0
    tmp_spec = secmod_ParseModuleSpecForTokens(PR_TRUE, module->isFIPS,
1792
0
                                               module->libraryParams, &children, &ids);
1793
0
    if (tmp_spec == NULL) {
1794
0
        goto done;
1795
0
    }
1796
1797
    /* first check to see if the parent is the database */
1798
0
    thisConfig = secmod_getConfigDir(tmp_spec, &thisCertPrefix, &thisKeyPrefix,
1799
0
                                     &thisReadOnly);
1800
0
    if (!thisConfig) {
1801
0
        goto done;
1802
0
    }
1803
0
    if (secmod_matchConfig(inConfig, thisConfig, inCertPrefix, thisCertPrefix,
1804
0
                           inKeyPrefix, thisKeyPrefix, inReadOnly, thisReadOnly)) {
1805
        /* yup it's the default key slot, get the id for it */
1806
0
        PK11SlotInfo *slot = PK11_GetInternalKeySlot();
1807
0
        if (slot) {
1808
0
            slotID = slot->slotID;
1809
0
            PK11_FreeSlot(slot);
1810
0
        }
1811
0
        goto done;
1812
0
    }
1813
1814
    /* find id of the token */
1815
0
    for (thisChild = children, thisID = ids; thisChild && *thisChild; thisChild++, thisID++) {
1816
0
        PORT_Free(thisConfig);
1817
0
        PORT_Free(thisCertPrefix);
1818
0
        PORT_Free(thisKeyPrefix);
1819
0
        thisConfig = secmod_getConfigDir(*thisChild, &thisCertPrefix,
1820
0
                                         &thisKeyPrefix, &thisReadOnly);
1821
0
        if (thisConfig == NULL) {
1822
0
            continue;
1823
0
        }
1824
0
        if (secmod_matchConfig(inConfig, thisConfig, inCertPrefix, thisCertPrefix,
1825
0
                               inKeyPrefix, thisKeyPrefix, inReadOnly, thisReadOnly)) {
1826
0
            slotID = *thisID;
1827
0
            break;
1828
0
        }
1829
0
    }
1830
1831
0
done:
1832
0
    PORT_Free(inConfig);
1833
0
    PORT_Free(inCertPrefix);
1834
0
    PORT_Free(inKeyPrefix);
1835
0
    PORT_Free(thisConfig);
1836
0
    PORT_Free(thisCertPrefix);
1837
0
    PORT_Free(thisKeyPrefix);
1838
0
    if (tmp_spec) {
1839
0
        secmod_FreeChildren(children, ids);
1840
0
        PORT_Free(tmp_spec);
1841
0
    }
1842
0
    return slotID;
1843
0
}
1844
1845
void
1846
secmod_FreeConfigList(SECMODConfigList *conflist, int count)
1847
0
{
1848
0
    int i;
1849
0
    for (i = 0; i < count; i++) {
1850
0
        PORT_Free(conflist[i].config);
1851
0
        PORT_Free(conflist[i].certPrefix);
1852
0
        PORT_Free(conflist[i].keyPrefix);
1853
0
    }
1854
0
    PORT_Free(conflist);
1855
0
}
1856
1857
void
1858
secmod_FreeChildren(char **children, CK_SLOT_ID *ids)
1859
0
{
1860
0
    char **thisChild;
1861
1862
0
    if (!children) {
1863
0
        return;
1864
0
    }
1865
1866
0
    for (thisChild = children; thisChild && *thisChild; thisChild++) {
1867
0
        PORT_Free(*thisChild);
1868
0
    }
1869
0
    PORT_Free(children);
1870
0
    if (ids) {
1871
0
        PORT_Free(ids);
1872
0
    }
1873
0
    return;
1874
0
}
1875
1876
/*
1877
 * caclulate the length of each child record:
1878
 * " 0x{id}=<{escaped_child}>"
1879
 */
1880
static int
1881
secmod_getChildLength(char *child, CK_SLOT_ID id)
1882
0
{
1883
0
    int length = NSSUTIL_DoubleEscapeSize(child, '>', ']');
1884
0
    if (id == 0) {
1885
0
        length++;
1886
0
    }
1887
0
    while (id) {
1888
0
        length++;
1889
0
        id = id >> 4;
1890
0
    }
1891
0
    length += 6; /* {sp}0x[id]=<{child}> */
1892
0
    return length;
1893
0
}
1894
1895
/*
1896
 * Build a child record:
1897
 * " 0x{id}=<{escaped_child}>"
1898
 */
1899
static SECStatus
1900
secmod_mkTokenChild(char **next, int *length, char *child, CK_SLOT_ID id)
1901
0
{
1902
0
    int len;
1903
0
    char *escSpec;
1904
1905
0
    len = PR_snprintf(*next, *length, " 0x%x=<", id);
1906
0
    if (len < 0) {
1907
0
        return SECFailure;
1908
0
    }
1909
0
    *next += len;
1910
0
    *length -= len;
1911
0
    escSpec = NSSUTIL_DoubleEscape(child, '>', ']');
1912
0
    if (escSpec == NULL) {
1913
0
        return SECFailure;
1914
0
    }
1915
0
    if (*child && (*escSpec == 0)) {
1916
0
        PORT_Free(escSpec);
1917
0
        return SECFailure;
1918
0
    }
1919
0
    len = strlen(escSpec);
1920
0
    if (len + 1 > *length) {
1921
0
        PORT_Free(escSpec);
1922
0
        return SECFailure;
1923
0
    }
1924
0
    PORT_Memcpy(*next, escSpec, len);
1925
0
    *next += len;
1926
0
    *length -= len;
1927
0
    PORT_Free(escSpec);
1928
0
    **next = '>';
1929
0
    (*next)++;
1930
0
    (*length)--;
1931
0
    return SECSuccess;
1932
0
}
1933
1934
0
#define TOKEN_STRING " tokens=["
1935
1936
char *
1937
secmod_MkAppendTokensList(PLArenaPool *arena, char *oldParam, char *newToken,
1938
                          CK_SLOT_ID newID, char **children, CK_SLOT_ID *ids)
1939
0
{
1940
0
    char *rawParam = NULL;  /* oldParam with tokens stripped off */
1941
0
    char *newParam = NULL;  /* space for the return parameter */
1942
0
    char *nextParam = NULL; /* current end of the new parameter */
1943
0
    char **oldChildren = NULL;
1944
0
    CK_SLOT_ID *oldIds = NULL;
1945
0
    void *mark = NULL; /* mark the arena pool in case we need
1946
                        * to release it */
1947
0
    int length, i, tmpLen;
1948
0
    SECStatus rv;
1949
1950
    /* first strip out and save the old tokenlist */
1951
0
    rawParam = secmod_ParseModuleSpecForTokens(PR_FALSE, PR_FALSE,
1952
0
                                               oldParam, &oldChildren, &oldIds);
1953
0
    if (!rawParam) {
1954
0
        goto loser;
1955
0
    }
1956
1957
    /* now calculate the total length of the new buffer */
1958
    /* First the 'fixed stuff', length of rawparam (does not include a NULL),
1959
     * length of the token string (does include the NULL), closing bracket */
1960
0
    length = strlen(rawParam) + sizeof(TOKEN_STRING) + 1;
1961
    /* now add then length of all the old children */
1962
0
    for (i = 0; oldChildren && oldChildren[i]; i++) {
1963
0
        length += secmod_getChildLength(oldChildren[i], oldIds[i]);
1964
0
    }
1965
1966
    /* add the new token */
1967
0
    length += secmod_getChildLength(newToken, newID);
1968
1969
    /* and it's new children */
1970
0
    for (i = 0; children && children[i]; i++) {
1971
0
        if (ids[i] == -1) {
1972
0
            continue;
1973
0
        }
1974
0
        length += secmod_getChildLength(children[i], ids[i]);
1975
0
    }
1976
1977
    /* now allocate and build the string */
1978
0
    mark = PORT_ArenaMark(arena);
1979
0
    if (!mark) {
1980
0
        goto loser;
1981
0
    }
1982
0
    newParam = PORT_ArenaAlloc(arena, length);
1983
0
    if (!newParam) {
1984
0
        goto loser;
1985
0
    }
1986
1987
0
    PORT_Strcpy(newParam, oldParam);
1988
0
    tmpLen = strlen(oldParam);
1989
0
    nextParam = newParam + tmpLen;
1990
0
    length -= tmpLen;
1991
0
    PORT_Memcpy(nextParam, TOKEN_STRING, sizeof(TOKEN_STRING) - 1);
1992
0
    nextParam += sizeof(TOKEN_STRING) - 1;
1993
0
    length -= sizeof(TOKEN_STRING) - 1;
1994
1995
0
    for (i = 0; oldChildren && oldChildren[i]; i++) {
1996
0
        rv = secmod_mkTokenChild(&nextParam, &length, oldChildren[i], oldIds[i]);
1997
0
        if (rv != SECSuccess) {
1998
0
            goto loser;
1999
0
        }
2000
0
    }
2001
2002
0
    rv = secmod_mkTokenChild(&nextParam, &length, newToken, newID);
2003
0
    if (rv != SECSuccess) {
2004
0
        goto loser;
2005
0
    }
2006
2007
0
    for (i = 0; children && children[i]; i++) {
2008
0
        if (ids[i] == -1) {
2009
0
            continue;
2010
0
        }
2011
0
        rv = secmod_mkTokenChild(&nextParam, &length, children[i], ids[i]);
2012
0
        if (rv != SECSuccess) {
2013
0
            goto loser;
2014
0
        }
2015
0
    }
2016
2017
0
    if (length < 2) {
2018
0
        goto loser;
2019
0
    }
2020
2021
0
    *nextParam++ = ']';
2022
0
    *nextParam++ = 0;
2023
2024
    /* we are going to return newParam now, don't release the mark */
2025
0
    PORT_ArenaUnmark(arena, mark);
2026
0
    mark = NULL;
2027
2028
0
loser:
2029
0
    if (mark) {
2030
0
        PORT_ArenaRelease(arena, mark);
2031
0
        newParam = NULL; /* if the mark is still active,
2032
                          * don't return the param */
2033
0
    }
2034
0
    if (rawParam) {
2035
0
        PORT_Free(rawParam);
2036
0
    }
2037
0
    if (oldChildren) {
2038
0
        secmod_FreeChildren(oldChildren, oldIds);
2039
0
    }
2040
0
    return newParam;
2041
0
}
2042
2043
static char *
2044
secmod_mkModuleSpec(SECMODModule *module)
2045
0
{
2046
0
    char *nss = NULL, *modSpec = NULL, **slotStrings = NULL;
2047
0
    int slotCount, i, si;
2048
0
    SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
2049
2050
    /* allocate target slot info strings */
2051
0
    slotCount = 0;
2052
2053
0
    SECMOD_GetReadLock(moduleLock);
2054
0
    if (module->slotCount) {
2055
0
        for (i = 0; i < module->slotCount; i++) {
2056
0
            if (module->slots[i]->defaultFlags != 0) {
2057
0
                slotCount++;
2058
0
            }
2059
0
        }
2060
0
    } else {
2061
0
        slotCount = module->slotInfoCount;
2062
0
    }
2063
2064
0
    slotStrings = (char **)PORT_ZAlloc(slotCount * sizeof(char *));
2065
0
    if (slotStrings == NULL) {
2066
0
        SECMOD_ReleaseReadLock(moduleLock);
2067
0
        goto loser;
2068
0
    }
2069
2070
    /* build the slot info strings */
2071
0
    if (module->slotCount) {
2072
0
        for (i = 0, si = 0; i < module->slotCount; i++) {
2073
0
            if (module->slots[i]->defaultFlags) {
2074
0
                PORT_Assert(si < slotCount);
2075
0
                if (si >= slotCount)
2076
0
                    break;
2077
0
                slotStrings[si] = NSSUTIL_MkSlotString(module->slots[i]->slotID,
2078
0
                                                       module->slots[i]->defaultFlags,
2079
0
                                                       module->slots[i]->timeout,
2080
0
                                                       module->slots[i]->askpw,
2081
0
                                                       module->slots[i]->hasRootCerts,
2082
0
                                                       module->slots[i]->hasRootTrust);
2083
0
                si++;
2084
0
            }
2085
0
        }
2086
0
    } else {
2087
0
        for (i = 0; i < slotCount; i++) {
2088
0
            slotStrings[i] = NSSUTIL_MkSlotString(
2089
0
                module->slotInfo[i].slotID,
2090
0
                module->slotInfo[i].defaultFlags,
2091
0
                module->slotInfo[i].timeout,
2092
0
                module->slotInfo[i].askpw,
2093
0
                module->slotInfo[i].hasRootCerts,
2094
0
                module->slotInfo[i].hasRootTrust);
2095
0
        }
2096
0
    }
2097
2098
0
    SECMOD_ReleaseReadLock(moduleLock);
2099
0
    nss = NSSUTIL_MkNSSString(slotStrings, slotCount, module->internal,
2100
0
                              module->isFIPS, module->isModuleDB,
2101
0
                              module->moduleDBOnly, module->isCritical,
2102
0
                              module->trustOrder, module->cipherOrder,
2103
0
                              module->ssl[0], module->ssl[1]);
2104
0
    modSpec = NSSUTIL_MkModuleSpec(module->dllName, module->commonName,
2105
0
                                   module->libraryParams, nss);
2106
0
    PORT_Free(slotStrings);
2107
0
    PR_smprintf_free(nss);
2108
0
loser:
2109
0
    return (modSpec);
2110
0
}
2111
2112
char **
2113
SECMOD_GetModuleSpecList(SECMODModule *module)
2114
16
{
2115
16
    SECMODModuleDBFunc func = (SECMODModuleDBFunc)module->moduleDBFunc;
2116
16
    if (func) {
2117
16
        return (*func)(SECMOD_MODULE_DB_FUNCTION_FIND,
2118
16
                       module->libraryParams, NULL);
2119
16
    }
2120
0
    return NULL;
2121
16
}
2122
2123
SECStatus
2124
SECMOD_AddPermDB(SECMODModule *module)
2125
0
{
2126
0
    SECMODModuleDBFunc func;
2127
0
    char *moduleSpec;
2128
0
    char **retString;
2129
2130
0
    if (module->parent == NULL)
2131
0
        return SECFailure;
2132
2133
0
    func = (SECMODModuleDBFunc)module->parent->moduleDBFunc;
2134
0
    if (func) {
2135
0
        moduleSpec = secmod_mkModuleSpec(module);
2136
0
        retString = (*func)(SECMOD_MODULE_DB_FUNCTION_ADD,
2137
0
                            module->parent->libraryParams, moduleSpec);
2138
0
        PORT_Free(moduleSpec);
2139
0
        if (retString != NULL)
2140
0
            return SECSuccess;
2141
0
    }
2142
0
    return SECFailure;
2143
0
}
2144
2145
SECStatus
2146
SECMOD_DeletePermDB(SECMODModule *module)
2147
0
{
2148
0
    SECMODModuleDBFunc func;
2149
0
    char *moduleSpec;
2150
0
    char **retString;
2151
2152
0
    if (module->parent == NULL)
2153
0
        return SECFailure;
2154
2155
0
    func = (SECMODModuleDBFunc)module->parent->moduleDBFunc;
2156
0
    if (func) {
2157
0
        moduleSpec = secmod_mkModuleSpec(module);
2158
0
        retString = (*func)(SECMOD_MODULE_DB_FUNCTION_DEL,
2159
0
                            module->parent->libraryParams, moduleSpec);
2160
0
        PORT_Free(moduleSpec);
2161
0
        if (retString != NULL)
2162
0
            return SECSuccess;
2163
0
    }
2164
0
    return SECFailure;
2165
0
}
2166
2167
SECStatus
2168
SECMOD_FreeModuleSpecList(SECMODModule *module, char **moduleSpecList)
2169
16
{
2170
16
    SECMODModuleDBFunc func = (SECMODModuleDBFunc)module->moduleDBFunc;
2171
16
    char **retString;
2172
16
    if (func) {
2173
16
        retString = (*func)(SECMOD_MODULE_DB_FUNCTION_RELEASE,
2174
16
                            module->libraryParams, moduleSpecList);
2175
16
        if (retString != NULL)
2176
16
            return SECSuccess;
2177
16
    }
2178
0
    return SECFailure;
2179
16
}
2180
2181
/*
2182
 * load a PKCS#11 module but do not add it to the default NSS trust domain
2183
 */
2184
SECMODModule *
2185
SECMOD_LoadModule(char *modulespec, SECMODModule *parent, PRBool recurse)
2186
32
{
2187
32
    char *library = NULL, *moduleName = NULL, *parameters = NULL, *nss = NULL;
2188
32
    char *config = NULL;
2189
32
    SECStatus status;
2190
32
    SECMODModule *module = NULL;
2191
32
    SECMODModule *oldModule = NULL;
2192
32
    SECStatus rv;
2193
32
    PRBool forwardPolicyFeedback = PR_FALSE;
2194
32
    PRUint32 forwardPolicyCheckFlags;
2195
2196
    /* initialize the underlying module structures */
2197
32
    SECMOD_Init();
2198
2199
32
    status = NSSUTIL_ArgParseModuleSpecEx(modulespec, &library, &moduleName,
2200
32
                                          &parameters, &nss,
2201
32
                                          &config);
2202
32
    if (status != SECSuccess) {
2203
0
        goto loser;
2204
0
    }
2205
2206
32
    module = SECMOD_CreateModuleEx(library, moduleName, parameters, nss, config);
2207
32
    forwardPolicyFeedback = NSSUTIL_ArgHasFlag("flags", "printPolicyFeedback", nss);
2208
32
    forwardPolicyCheckFlags = secmod_parsePolicyCheckFlags(nss);
2209
2210
32
    if (library)
2211
0
        PORT_Free(library);
2212
32
    if (moduleName)
2213
32
        PORT_Free(moduleName);
2214
32
    if (parameters)
2215
32
        PORT_Free(parameters);
2216
32
    if (nss)
2217
32
        PORT_Free(nss);
2218
32
    if (config)
2219
0
        PORT_Free(config);
2220
32
    if (!module) {
2221
0
        goto loser;
2222
0
    }
2223
2224
    /* a policy only stanza doesn't actually get 'loaded'. policy has already
2225
     * been parsed as a side effect of the CreateModuleEx call */
2226
32
    if (secmod_PolicyOnly(module)) {
2227
0
        return module;
2228
0
    }
2229
32
    if (parent) {
2230
16
        module->parent = SECMOD_ReferenceModule(parent);
2231
16
        if (module->internal && secmod_IsInternalKeySlot(parent)) {
2232
16
            module->internal = parent->internal;
2233
16
        }
2234
16
    }
2235
2236
    /* load it */
2237
32
    rv = secmod_LoadPKCS11Module(module, &oldModule);
2238
32
    if (rv != SECSuccess) {
2239
0
        goto loser;
2240
0
    }
2241
2242
    /* if we just reload an old module, no need to add it to any lists.
2243
     * we simple release all our references */
2244
32
    if (oldModule) {
2245
        /* This module already exists, don't link it anywhere. This
2246
         * will probably destroy this module */
2247
0
        SECMOD_DestroyModule(module);
2248
0
        return oldModule;
2249
0
    }
2250
2251
32
    if (recurse && module->isModuleDB) {
2252
16
        char **moduleSpecList;
2253
16
        PORT_SetError(0);
2254
2255
16
        moduleSpecList = SECMOD_GetModuleSpecList(module);
2256
16
        if (moduleSpecList) {
2257
16
            char **index;
2258
2259
16
            index = moduleSpecList;
2260
16
            if (*index && SECMOD_GetSkipFirstFlag(module)) {
2261
0
                index++;
2262
0
            }
2263
2264
32
            for (; *index; index++) {
2265
16
                SECMODModule *child;
2266
16
                if (0 == PORT_Strcmp(*index, modulespec)) {
2267
                    /* avoid trivial infinite recursion */
2268
0
                    PORT_SetError(SEC_ERROR_NO_MODULE);
2269
0
                    rv = SECFailure;
2270
0
                    break;
2271
0
                }
2272
16
                if (!forwardPolicyFeedback) {
2273
16
                    child = SECMOD_LoadModule(*index, module, PR_TRUE);
2274
16
                } else {
2275
                    /* Add printPolicyFeedback to the nss flags */
2276
0
                    char *specWithForwards =
2277
0
                        NSSUTIL_AddNSSFlagToModuleSpec(*index, "printPolicyFeedback");
2278
0
                    char *tmp;
2279
0
                    if (forwardPolicyCheckFlags & SECMOD_FLAG_POLICY_CHECK_IDENTIFIER) {
2280
0
                        tmp = NSSUTIL_AddNSSFlagToModuleSpec(specWithForwards, "policyCheckIdentifier");
2281
0
                        PORT_Free(specWithForwards);
2282
0
                        specWithForwards = tmp;
2283
0
                    }
2284
0
                    if (forwardPolicyCheckFlags & SECMOD_FLAG_POLICY_CHECK_VALUE) {
2285
0
                        tmp = NSSUTIL_AddNSSFlagToModuleSpec(specWithForwards, "policyCheckValue");
2286
0
                        PORT_Free(specWithForwards);
2287
0
                        specWithForwards = tmp;
2288
0
                    }
2289
0
                    child = SECMOD_LoadModule(specWithForwards, module, PR_TRUE);
2290
0
                    PORT_Free(specWithForwards);
2291
0
                }
2292
16
                if (!child)
2293
0
                    break;
2294
16
                if (child->isCritical && !child->loaded) {
2295
0
                    int err = PORT_GetError();
2296
0
                    if (!err)
2297
0
                        err = SEC_ERROR_NO_MODULE;
2298
0
                    SECMOD_DestroyModule(child);
2299
0
                    PORT_SetError(err);
2300
0
                    rv = SECFailure;
2301
0
                    break;
2302
0
                }
2303
16
                SECMOD_DestroyModule(child);
2304
16
            }
2305
16
            SECMOD_FreeModuleSpecList(module, moduleSpecList);
2306
16
        } else {
2307
0
            if (!PORT_GetError())
2308
0
                PORT_SetError(SEC_ERROR_NO_MODULE);
2309
0
            rv = SECFailure;
2310
0
        }
2311
16
    }
2312
2313
32
    if (rv != SECSuccess) {
2314
0
        goto loser;
2315
0
    }
2316
2317
    /* inherit the reference */
2318
32
    if (!module->moduleDBOnly) {
2319
16
        SECMOD_AddModuleToList(module);
2320
16
    } else {
2321
16
        SECMOD_AddModuleToDBOnlyList(module);
2322
16
    }
2323
2324
    /* handle any additional work here */
2325
32
    return module;
2326
2327
0
loser:
2328
0
    if (module) {
2329
0
        if (module->loaded) {
2330
0
            SECMOD_UnloadModule(module);
2331
0
        }
2332
0
        SECMOD_AddModuleToUnloadList(module);
2333
0
    }
2334
0
    return module;
2335
32
}
2336
2337
SECMODModule *
2338
SECMOD_LoadModuleWithFunction(const char *moduleName, CK_C_GetFunctionList fentry)
2339
0
{
2340
0
    SECMODModule *module = NULL;
2341
0
    SECMODModule *oldModule = NULL;
2342
0
    SECStatus rv;
2343
2344
    /* initialize the underlying module structures */
2345
0
    SECMOD_Init();
2346
2347
0
    module = secmod_NewModule();
2348
0
    if (module == NULL) {
2349
0
        goto loser;
2350
0
    }
2351
2352
0
    module->commonName = PORT_ArenaStrdup(module->arena, moduleName ? moduleName : "");
2353
0
    module->internal = PR_FALSE;
2354
0
    module->isFIPS = PR_FALSE;
2355
    /* if the system FIPS mode is enabled, force FIPS to be on */
2356
0
    if (SECMOD_GetSystemFIPSEnabled()) {
2357
0
        module->isFIPS = PR_TRUE;
2358
0
    }
2359
2360
0
    module->isCritical = PR_FALSE;
2361
    /* new field */
2362
0
    module->trustOrder = NSSUTIL_DEFAULT_TRUST_ORDER;
2363
    /* new field */
2364
0
    module->cipherOrder = NSSUTIL_DEFAULT_CIPHER_ORDER;
2365
    /* new field */
2366
0
    module->isModuleDB = PR_FALSE;
2367
0
    module->moduleDBOnly = PR_FALSE;
2368
2369
0
    module->ssl[0] = 0;
2370
0
    module->ssl[1] = 0;
2371
2372
0
    secmod_PrivateModuleCount++;
2373
2374
    /* load it */
2375
0
    rv = secmod_LoadPKCS11ModuleFromFunction(module, &oldModule, fentry);
2376
0
    if (rv != SECSuccess) {
2377
0
        goto loser;
2378
0
    }
2379
2380
    /* if we just reload an old module, no need to add it to any lists.
2381
     * we simple release all our references */
2382
0
    if (oldModule) {
2383
        /* This module already exists, don't link it anywhere. This
2384
         * will probably destroy this module */
2385
0
        SECMOD_DestroyModule(module);
2386
0
        return oldModule;
2387
0
    }
2388
2389
0
    SECMOD_AddModuleToList(module);
2390
    /* handle any additional work here */
2391
0
    return module;
2392
2393
0
loser:
2394
0
    if (module) {
2395
0
        if (module->loaded) {
2396
0
            SECMOD_UnloadModule(module);
2397
0
        }
2398
0
        SECMOD_AddModuleToUnloadList(module);
2399
0
    }
2400
0
    return module;
2401
0
}
2402
2403
/*
2404
 * load a PKCS#11 module and add it to the default NSS trust domain
2405
 */
2406
SECMODModule *
2407
SECMOD_LoadUserModule(char *modulespec, SECMODModule *parent, PRBool recurse)
2408
0
{
2409
0
    SECStatus rv = SECSuccess;
2410
0
    SECMODModule *newmod = SECMOD_LoadModule(modulespec, parent, recurse);
2411
0
    SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
2412
2413
0
    if (newmod) {
2414
0
        SECMOD_GetReadLock(moduleLock);
2415
0
        rv = STAN_AddModuleToDefaultTrustDomain(newmod);
2416
0
        SECMOD_ReleaseReadLock(moduleLock);
2417
0
        if (SECSuccess != rv) {
2418
0
            SECMOD_DestroyModule(newmod);
2419
0
            return NULL;
2420
0
        }
2421
0
    }
2422
0
    return newmod;
2423
0
}
2424
2425
SECMODModule *
2426
SECMOD_LoadUserModuleWithFunction(const char *moduleName, CK_C_GetFunctionList fentry)
2427
0
{
2428
0
    SECStatus rv = SECSuccess;
2429
0
    SECMODModule *newmod = SECMOD_LoadModuleWithFunction(moduleName, fentry);
2430
0
    SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
2431
2432
0
    if (newmod) {
2433
0
        SECMOD_GetReadLock(moduleLock);
2434
0
        rv = STAN_AddModuleToDefaultTrustDomain(newmod);
2435
0
        SECMOD_ReleaseReadLock(moduleLock);
2436
0
        if (SECSuccess != rv) {
2437
0
            SECMOD_DestroyModule(newmod);
2438
0
            return NULL;
2439
0
        }
2440
0
    }
2441
0
    return newmod;
2442
0
}
2443
2444
/*
2445
 * remove the PKCS#11 module from the default NSS trust domain, call
2446
 * C_Finalize, and destroy the module structure
2447
 */
2448
SECStatus
2449
SECMOD_UnloadUserModule(SECMODModule *mod)
2450
0
{
2451
0
    SECStatus rv = SECSuccess;
2452
0
    int atype = 0;
2453
0
    SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
2454
0
    if (!mod) {
2455
0
        return SECFailure;
2456
0
    }
2457
2458
0
    SECMOD_GetReadLock(moduleLock);
2459
0
    rv = STAN_RemoveModuleFromDefaultTrustDomain(mod);
2460
0
    SECMOD_ReleaseReadLock(moduleLock);
2461
0
    if (SECSuccess != rv) {
2462
0
        return SECFailure;
2463
0
    }
2464
0
    return SECMOD_DeleteModuleEx(NULL, mod, &atype, PR_FALSE);
2465
0
}