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