pk11pars.c (89534B)
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 { 26 SECMODModule *newMod; 27 PLArenaPool *arena; 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 /* 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 #define SECMOD_FLAG_MODULE_DB_IS_MODULE_DB 0x01 /* must be set if any of the \ 109 *other flags are set */ 110 #define SECMOD_FLAG_MODULE_DB_SKIP_FIRST 0x02 111 #define SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB 0x04 112 #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 #define SECMOD_FLAG_INTERNAL_IS_INTERNAL 0x01 /* must be set if any of \ 127 *the other flags are set */ 128 #define SECMOD_FLAG_INTERNAL_KEY_SLOT 0x02 129 130 /* private flags for policy check. */ 131 #define SECMOD_FLAG_POLICY_CHECK_IDENTIFIER 0x01 132 #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 { 141 return SECMOD_CreateModuleEx(library, moduleName, parameters, nss, NULL); 142 } 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 { 597 const char *start = cipher; 598 599 if (start == NULL) { 600 *len = 0; 601 *next = NULL; 602 return start; 603 } 604 605 for (; *cipher && *cipher != sep2; cipher++) { 606 if (*cipher == sep1) { 607 *next = cipher + 1; 608 *len = cipher - start; 609 return start; 610 } 611 } 612 *next = NULL; 613 *len = cipher - start; 614 return start; 615 } 616 617 static PRUint32 618 secmod_parsePolicyValue(const char *policyFlags, int policyLength, 619 PRBool printPolicyFeedback, PRUint32 policyCheckFlags) 620 { 621 const char *flag, *currentString; 622 PRUint32 flags = 0; 623 int i; 624 625 for (currentString = policyFlags; currentString && 626 currentString < policyFlags + policyLength;) { 627 int length; 628 PRBool unknown = PR_TRUE; 629 flag = secmod_ArgGetSubValue(currentString, ',', ':', &length, 630 ¤tString); 631 if (length == 0) { 632 continue; 633 } 634 for (i = 0; i < PR_ARRAY_SIZE(policyFlagList); i++) { 635 const policyFlagDef *policy = &policyFlagList[i]; 636 unsigned name_size = policy->name_size; 637 if ((policy->name_size == length) && 638 PORT_Strncasecmp(policy->name, flag, name_size) == 0) { 639 flags |= policy->flag; 640 unknown = PR_FALSE; 641 break; 642 } 643 } 644 if (unknown && printPolicyFeedback && 645 (policyCheckFlags & SECMOD_FLAG_POLICY_CHECK_VALUE)) { 646 PR_SetEnv("NSS_POLICY_FAIL=1"); 647 fprintf(stderr, "NSS-POLICY-FAIL %.*s: unknown value: %.*s\n", 648 policyLength, policyFlags, length, flag); 649 } 650 } 651 return flags; 652 } 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 { 660 PRInt32 val = atoi(policyValue); 661 int i; 662 663 if ((val != 0) || (*policyValue == '0')) { 664 *result = val; 665 return SECSuccess; 666 } 667 if (policyValueLength == 0) { 668 return SECFailure; 669 } 670 /* handle any ssl strings */ 671 for (i = 0; i < PR_ARRAY_SIZE(sslOptList); i++) { 672 if (policyValueLength == sslOptList[i].name_size && 673 PORT_Strncasecmp(sslOptList[i].name, policyValue, 674 sslOptList[i].name_size) == 0) { 675 *result = sslOptList[i].option; 676 return SECSuccess; 677 } 678 } 679 /* handle key_size flags. Each flag represents a bit, which 680 * gets or'd together. They can be separated by , | or + */ 681 val = 0; 682 while (policyValueLength > 0) { 683 PRBool found = PR_FALSE; 684 for (i = 0; i < PR_ARRAY_SIZE(keySizeFlagsList); i++) { 685 if (PORT_Strncasecmp(keySizeFlagsList[i].name, policyValue, 686 keySizeFlagsList[i].name_size) == 0) { 687 val |= keySizeFlagsList[i].option; 688 found = PR_TRUE; 689 policyValue += keySizeFlagsList[i].name_size; 690 policyValueLength -= keySizeFlagsList[i].name_size; 691 break; 692 } 693 } 694 if (!found) { 695 return SECFailure; 696 } 697 if (*policyValue == ',' || *policyValue == '|' || *policyValue == '+') { 698 policyValue++; 699 policyValueLength--; 700 } 701 } 702 *result = val; 703 return SECSuccess; 704 } 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 { 730 SECStatus rv = SECSuccess; 731 PRUint32 policy; 732 PRUint32 useDefault = 0; 733 PRUint32 set = 0; 734 /* we always clear the default not valid flag as this operation will 735 * make the defaults valid */ 736 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 if (value & (NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SSL_KX)) { 741 useDefault |= NSS_USE_DEFAULT_SSL_ENABLE; 742 } 743 /* only bulk ciphers are configured as enable in S/MIME, only 744 * enable them if both SMIME bits are set */ 745 if ((value & NSS_USE_ALG_IN_SMIME) == NSS_USE_ALG_IN_SMIME) { 746 useDefault |= NSS_USE_DEFAULT_SMIME_ENABLE; 747 } 748 749 /* on disable we clear, on enable we set */ 750 if (operation == NSS_DISABLE) { 751 clear |= useDefault; 752 } else { 753 /* we also turn the cipher on by policy if we enable it, 754 * so include the policy bits */ 755 set |= value | useDefault; 756 } 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 rv = NSS_GetAlgorithmPolicy(oid, &policy); 762 if (rv != SECSuccess) { 763 return rv; 764 } 765 if (policy & NSS_USE_DEFAULT_NOT_VALID) { 766 clear |= ((NSS_USE_DEFAULT_SSL_ENABLE | NSS_USE_DEFAULT_SMIME_ENABLE) & 767 ~set); 768 } 769 return NSS_SetAlgorithmPolicy(oid, set, clear); 770 } 771 772 /* apply the operator specific policy */ 773 SECStatus 774 secmod_setPolicyOperation(SECOidTag oid, NSSPolicyOperation operation, 775 PRUint32 value) 776 { 777 SECStatus rv = SECSuccess; 778 switch (operation) { 779 case NSS_DISALLOW: 780 /* clear the requested policy bits */ 781 rv = NSS_SetAlgorithmPolicy(oid, 0, value); 782 break; 783 case NSS_ALLOW: 784 /* set the requested policy bits */ 785 rv = NSS_SetAlgorithmPolicy(oid, value, 0); 786 break; 787 case NSS_DISABLE: 788 case NSS_ENABLE: 789 rv = secmod_setDefault(oid, operation, value); 790 break; 791 default: 792 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 793 rv = SECFailure; 794 break; 795 } 796 return rv; 797 } 798 799 const char * 800 secmod_getOperationString(NSSPolicyOperation operation) 801 { 802 switch (operation) { 803 case NSS_DISALLOW: 804 return "disallow"; 805 case NSS_ALLOW: 806 return "allow"; 807 case NSS_DISABLE: 808 return "disable"; 809 case NSS_ENABLE: 810 return "enable"; 811 default: 812 break; 813 } 814 return "invalid"; 815 } 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 { 824 PRBool any = (PORT_Strcasecmp(list, "Any") == 0) ? PR_TRUE : PR_FALSE; 825 int len = PORT_Strlen(policy); 826 int i, j; 827 828 for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) { 829 const algListsDef *algOptList = &algOptLists[i]; 830 if (any || (PORT_Strcasecmp(algOptList->description, list) == 0)) { 831 for (j = 0; j < algOptList->entries; j++) { 832 const oidValDef *algOpt = &algOptList->list[j]; 833 unsigned name_size = algOpt->name_size; 834 if (len == name_size && 835 PORT_Strcasecmp(algOpt->name, policy) == 0) { 836 return algOpt->oid; 837 } 838 } 839 } 840 } 841 return SEC_OID_UNKNOWN; 842 } 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 { 849 int len = PORT_Strlen(policy); 850 int i; 851 852 for (i = 0; i < PR_ARRAY_SIZE(freeOptList); i++) { 853 const optionFreeDef *freeOpt = &freeOptList[i]; 854 unsigned name_size = freeOpt->name_size; 855 if (len == name_size && 856 PORT_Strcasecmp(freeOpt->name, policy) == 0) { 857 return freeOpt->option; 858 } 859 } 860 return 0; 861 } 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 { 876 int i; 877 878 for (i = 0; i < PR_ARRAY_SIZE(policyFlagList); i++) { 879 const policyFlagDef *policy = &policyFlagList[i]; 880 if (exact && (policy->flag == val)) { 881 return policy->name; 882 } 883 if (!exact && ((policy->flag & val) == policy->flag)) { 884 return policy->name; 885 } 886 } 887 return NULL; 888 } 889 890 static SECStatus 891 secmod_applyCryptoPolicy(const char *policyString, NSSPolicyOperation operation, 892 PRBool printPolicyFeedback, PRUint32 policyCheckFlags) 893 { 894 const char *cipher, *currentString; 895 unsigned i, j; 896 SECStatus rv = SECSuccess; 897 PRBool unknown; 898 899 if (policyString == NULL || policyString[0] == 0) { 900 return SECSuccess; /* do nothing */ 901 } 902 903 /* if we change any of these, make sure it gets applied in ssl as well */ 904 NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL, 0); 905 906 for (currentString = policyString; currentString;) { 907 int length; 908 PRBool newValue = PR_FALSE; 909 910 cipher = secmod_ArgGetSubValue(currentString, ':', 0, &length, 911 ¤tString); 912 unknown = PR_TRUE; 913 if (length >= 3 && cipher[3] == '/') { 914 newValue = PR_TRUE; 915 } 916 if ((newValue || (length == 3)) && PORT_Strncasecmp(cipher, "all", 3) == 0) { 917 /* disable or enable all options by default */ 918 PRUint32 value = 0; 919 if (newValue) { 920 value = secmod_parsePolicyValue(&cipher[3] + 1, length - 3 - 1, printPolicyFeedback, policyCheckFlags); 921 } 922 for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) { 923 const algListsDef *algOptList = &algOptLists[i]; 924 for (j = 0; j < algOptList->entries; j++) { 925 if (!newValue) { 926 value = algOptList->list[j].val; 927 } 928 secmod_setPolicyOperation(algOptList->list[j].oid, operation, value); 929 } 930 } 931 continue; 932 } 933 934 for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) { 935 const algListsDef *algOptList = &algOptLists[i]; 936 for (j = 0; j < algOptList->entries; j++) { 937 const oidValDef *algOpt = &algOptList->list[j]; 938 unsigned name_size = algOpt->name_size; 939 PRBool newOption = PR_FALSE; 940 941 if ((length >= name_size) && (cipher[name_size] == '/')) { 942 newOption = PR_TRUE; 943 } 944 if ((newOption || algOpt->name_size == length) && 945 PORT_Strncasecmp(algOpt->name, cipher, name_size) == 0) { 946 PRUint32 value = algOpt->val; 947 if (newOption) { 948 value = secmod_parsePolicyValue(&cipher[name_size] + 1, 949 length - name_size - 1, 950 printPolicyFeedback, 951 policyCheckFlags); 952 } 953 rv = secmod_setPolicyOperation(algOptList->list[j].oid, operation, value); 954 if (rv != SECSuccess) { 955 /* could not enable option */ 956 /* NSS_SetAlgorithPolicy should have set the error code */ 957 return SECFailure; 958 } 959 unknown = PR_FALSE; 960 break; 961 } 962 } 963 } 964 if (!unknown) { 965 continue; 966 } 967 968 for (i = 0; i < PR_ARRAY_SIZE(freeOptList); i++) { 969 const optionFreeDef *freeOpt = &freeOptList[i]; 970 unsigned name_size = freeOpt->name_size; 971 972 if ((length > name_size) && cipher[name_size] == '=' && 973 PORT_Strncasecmp(freeOpt->name, cipher, name_size) == 0) { 974 PRInt32 val; 975 const char *policyValue = &cipher[name_size + 1]; 976 int policyValueLength = length - name_size - 1; 977 rv = secmod_getPolicyOptValue(policyValue, policyValueLength, 978 &val); 979 if (rv != SECSuccess) { 980 if (printPolicyFeedback && 981 (policyCheckFlags & SECMOD_FLAG_POLICY_CHECK_VALUE)) { 982 PR_SetEnv("NSS_POLICY_FAIL=1"); 983 fprintf(stderr, "NSS-POLICY-FAIL %.*s: unknown value: %.*s\n", 984 length, cipher, policyValueLength, policyValue); 985 } 986 return SECFailure; 987 } 988 rv = NSS_OptionSet(freeOpt->option, val); 989 if (rv != SECSuccess) { 990 /* could not enable option */ 991 /* NSS_OptionSet should have set the error code */ 992 return SECFailure; 993 } 994 /* to allow the policy to expand in the future. ignore ciphers 995 * we don't understand */ 996 unknown = PR_FALSE; 997 break; 998 } 999 } 1000 1001 if (unknown && printPolicyFeedback && 1002 (policyCheckFlags & SECMOD_FLAG_POLICY_CHECK_IDENTIFIER)) { 1003 PR_SetEnv("NSS_POLICY_FAIL=1"); 1004 fprintf(stderr, "NSS-POLICY-FAIL %s: unknown identifier: %.*s\n", 1005 secmod_getOperationString(operation), length, cipher); 1006 } 1007 } 1008 return rv; 1009 } 1010 1011 static void 1012 secmod_sanityCheckCryptoPolicy(void) 1013 { 1014 unsigned i, j; 1015 SECStatus rv = SECSuccess; 1016 unsigned num_kx_enabled = 0; 1017 unsigned num_ssl_enabled = 0; 1018 unsigned num_sig_enabled = 0; 1019 unsigned enabledCount[PR_ARRAY_SIZE(algOptLists)]; 1020 const char *sWarn = "WARN"; 1021 const char *sInfo = "INFO"; 1022 PRBool haveWarning = PR_FALSE; 1023 1024 for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) { 1025 const algListsDef *algOptList = &algOptLists[i]; 1026 enabledCount[i] = 0; 1027 for (j = 0; j < algOptList->entries; j++) { 1028 const oidValDef *algOpt = &algOptList->list[j]; 1029 PRUint32 value; 1030 PRBool anyEnabled = PR_FALSE; 1031 rv = NSS_GetAlgorithmPolicy(algOpt->oid, &value); 1032 if (rv != SECSuccess) { 1033 PR_SetEnv("NSS_POLICY_FAIL=1"); 1034 fprintf(stderr, "NSS-POLICY-FAIL: internal failure with NSS_GetAlgorithmPolicy at %u\n", i); 1035 return; 1036 } 1037 1038 if ((algOpt->val & NSS_USE_ALG_IN_SSL_KX) && (value & NSS_USE_ALG_IN_SSL_KX)) { 1039 ++num_kx_enabled; 1040 anyEnabled = PR_TRUE; 1041 fprintf(stderr, "NSS-POLICY-INFO: %s is enabled for SSL-KX\n", algOpt->name); 1042 } 1043 if ((algOpt->val & NSS_USE_ALG_IN_SSL) && (value & NSS_USE_ALG_IN_SSL)) { 1044 ++num_ssl_enabled; 1045 anyEnabled = PR_TRUE; 1046 fprintf(stderr, "NSS-POLICY-INFO: %s is enabled for SSL\n", algOpt->name); 1047 } 1048 if ((algOpt->val & NSS_USE_ALG_IN_CERT_SIGNATURE) && 1049 ((value & NSS_USE_CERT_SIGNATURE_OK) == NSS_USE_CERT_SIGNATURE_OK)) { 1050 ++num_sig_enabled; 1051 anyEnabled = PR_TRUE; 1052 fprintf(stderr, "NSS-POLICY-INFO: %s is enabled for CERT-SIGNATURE\n", algOpt->name); 1053 } 1054 if (anyEnabled) { 1055 ++enabledCount[i]; 1056 } 1057 } 1058 } 1059 fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-SSL-ALG-KX: %u\n", num_kx_enabled ? sInfo : sWarn, num_kx_enabled); 1060 fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-SSL-ALG: %u\n", num_ssl_enabled ? sInfo : sWarn, num_ssl_enabled); 1061 fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-CERT-SIG: %u\n", num_sig_enabled ? sInfo : sWarn, num_sig_enabled); 1062 if (!num_kx_enabled || !num_ssl_enabled || !num_sig_enabled) { 1063 haveWarning = PR_TRUE; 1064 } 1065 for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) { 1066 const algListsDef *algOptList = &algOptLists[i]; 1067 fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-%s: %u\n", enabledCount[i] ? sInfo : sWarn, algOptList->description, enabledCount[i]); 1068 if (!enabledCount[i] && !algOptList->allowEmpty) { 1069 haveWarning = PR_TRUE; 1070 } 1071 } 1072 if (haveWarning) { 1073 PR_SetEnv("NSS_POLICY_WARN=1"); 1074 } 1075 } 1076 1077 static SECStatus 1078 secmod_parseCryptoPolicy(const char *policyConfig, PRBool printPolicyFeedback, 1079 PRUint32 policyCheckFlags) 1080 { 1081 char *args; 1082 SECStatus rv; 1083 1084 if (policyConfig == NULL) { 1085 return SECSuccess; /* no policy given */ 1086 } 1087 /* make sure we initialize the oid table and set all the default policy 1088 * values first so we can override them here */ 1089 rv = SECOID_Init(); 1090 if (rv != SECSuccess) { 1091 return rv; 1092 } 1093 args = NSSUTIL_ArgGetParamValue("disallow", policyConfig); 1094 rv = secmod_applyCryptoPolicy(args, NSS_DISALLOW, printPolicyFeedback, 1095 policyCheckFlags); 1096 if (args) 1097 PORT_Free(args); 1098 if (rv != SECSuccess) { 1099 return rv; 1100 } 1101 args = NSSUTIL_ArgGetParamValue("allow", policyConfig); 1102 rv = secmod_applyCryptoPolicy(args, NSS_ALLOW, printPolicyFeedback, 1103 policyCheckFlags); 1104 if (args) 1105 PORT_Free(args); 1106 if (rv != SECSuccess) { 1107 return rv; 1108 } 1109 args = NSSUTIL_ArgGetParamValue("disable", policyConfig); 1110 rv = secmod_applyCryptoPolicy(args, NSS_DISABLE, printPolicyFeedback, 1111 policyCheckFlags); 1112 if (args) 1113 PORT_Free(args); 1114 if (rv != SECSuccess) { 1115 return rv; 1116 } 1117 args = NSSUTIL_ArgGetParamValue("enable", policyConfig); 1118 rv = secmod_applyCryptoPolicy(args, NSS_ENABLE, printPolicyFeedback, 1119 policyCheckFlags); 1120 if (args) 1121 PORT_Free(args); 1122 if (rv != SECSuccess) { 1123 return rv; 1124 } 1125 /* this has to be last. Everything after this will be a noop */ 1126 if (NSSUTIL_ArgHasFlag("flags", "ssl-lock", policyConfig)) { 1127 PRInt32 locks; 1128 /* don't overwrite other (future) lock flags */ 1129 rv = NSS_OptionGet(NSS_DEFAULT_LOCKS, &locks); 1130 if (rv == SECSuccess) { 1131 rv = NSS_OptionSet(NSS_DEFAULT_LOCKS, locks | NSS_DEFAULT_SSL_LOCK); 1132 } 1133 if (rv != SECSuccess) { 1134 return rv; 1135 } 1136 } 1137 if (NSSUTIL_ArgHasFlag("flags", "policy-lock", policyConfig)) { 1138 NSS_LockPolicy(); 1139 } 1140 if (printPolicyFeedback) { 1141 /* This helps to distinguish configurations that don't contain any 1142 * policy config= statement. */ 1143 PR_SetEnv("NSS_POLICY_LOADED=1"); 1144 fprintf(stderr, "NSS-POLICY-INFO: LOADED-SUCCESSFULLY\n"); 1145 secmod_sanityCheckCryptoPolicy(); 1146 } 1147 return rv; 1148 } 1149 1150 static PRUint32 1151 secmod_parsePolicyCheckFlags(const char *nss) 1152 { 1153 PRUint32 policyCheckFlags = 0; 1154 1155 if (NSSUTIL_ArgHasFlag("flags", "policyCheckIdentifier", nss)) { 1156 policyCheckFlags |= SECMOD_FLAG_POLICY_CHECK_IDENTIFIER; 1157 } 1158 1159 if (NSSUTIL_ArgHasFlag("flags", "policyCheckValue", nss)) { 1160 policyCheckFlags |= SECMOD_FLAG_POLICY_CHECK_VALUE; 1161 } 1162 1163 return policyCheckFlags; 1164 } 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 { 1174 SECMODModule *mod; 1175 SECStatus rv; 1176 char *slotParams, *ciphers; 1177 PRBool printPolicyFeedback = NSSUTIL_ArgHasFlag("flags", "printPolicyFeedback", nss); 1178 PRUint32 policyCheckFlags = secmod_parsePolicyCheckFlags(nss); 1179 1180 rv = secmod_parseCryptoPolicy(config, printPolicyFeedback, policyCheckFlags); 1181 1182 /* do not load the module if policy parsing fails */ 1183 if (rv != SECSuccess) { 1184 if (printPolicyFeedback) { 1185 PR_SetEnv("NSS_POLICY_FAIL=1"); 1186 fprintf(stderr, "NSS-POLICY-FAIL: policy config parsing failed, not loading module %s\n", moduleName); 1187 } 1188 return NULL; 1189 } 1190 1191 mod = secmod_NewModule(); 1192 if (mod == NULL) 1193 return NULL; 1194 1195 mod->commonName = PORT_ArenaStrdup(mod->arena, moduleName ? moduleName : ""); 1196 if (library) { 1197 mod->dllName = PORT_ArenaStrdup(mod->arena, library); 1198 } 1199 /* new field */ 1200 if (parameters) { 1201 mod->libraryParams = PORT_ArenaStrdup(mod->arena, parameters); 1202 } 1203 1204 mod->internal = NSSUTIL_ArgHasFlag("flags", "internal", nss); 1205 mod->isFIPS = NSSUTIL_ArgHasFlag("flags", "FIPS", nss); 1206 /* if the system FIPS mode is enabled, force FIPS to be on */ 1207 if (SECMOD_GetSystemFIPSEnabled()) { 1208 mod->isFIPS = PR_TRUE; 1209 } 1210 mod->isCritical = NSSUTIL_ArgHasFlag("flags", "critical", nss); 1211 slotParams = NSSUTIL_ArgGetParamValue("slotParams", nss); 1212 mod->slotInfo = NSSUTIL_ArgParseSlotInfo(mod->arena, slotParams, 1213 &mod->slotInfoCount); 1214 if (slotParams) 1215 PORT_Free(slotParams); 1216 /* new field */ 1217 mod->trustOrder = NSSUTIL_ArgReadLong("trustOrder", nss, 1218 NSSUTIL_DEFAULT_TRUST_ORDER, NULL); 1219 /* new field */ 1220 mod->cipherOrder = NSSUTIL_ArgReadLong("cipherOrder", nss, 1221 NSSUTIL_DEFAULT_CIPHER_ORDER, NULL); 1222 /* new field */ 1223 mod->isModuleDB = NSSUTIL_ArgHasFlag("flags", "moduleDB", nss); 1224 mod->moduleDBOnly = NSSUTIL_ArgHasFlag("flags", "moduleDBOnly", nss); 1225 if (mod->moduleDBOnly) 1226 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 if (mod->isModuleDB) { 1235 char flags = SECMOD_FLAG_MODULE_DB_IS_MODULE_DB; 1236 if (NSSUTIL_ArgHasFlag("flags", "skipFirst", nss)) { 1237 flags |= SECMOD_FLAG_MODULE_DB_SKIP_FIRST; 1238 } 1239 if (NSSUTIL_ArgHasFlag("flags", "defaultModDB", nss)) { 1240 flags |= SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB; 1241 } 1242 if (NSSUTIL_ArgHasFlag("flags", "policyOnly", nss)) { 1243 flags |= SECMOD_FLAG_MODULE_DB_POLICY_ONLY; 1244 } 1245 /* additional moduleDB flags could be added here in the future */ 1246 mod->isModuleDB = (PRBool)flags; 1247 } 1248 1249 if (mod->internal) { 1250 char flags = SECMOD_FLAG_INTERNAL_IS_INTERNAL; 1251 1252 if (NSSUTIL_ArgHasFlag("flags", "internalKeySlot", nss)) { 1253 flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT; 1254 } 1255 mod->internal = (PRBool)flags; 1256 } 1257 1258 ciphers = NSSUTIL_ArgGetParamValue("ciphers", nss); 1259 NSSUTIL_ArgParseCipherFlags(&mod->ssl[0], ciphers); 1260 if (ciphers) 1261 PORT_Free(ciphers); 1262 1263 secmod_PrivateModuleCount++; 1264 1265 return mod; 1266 } 1267 1268 PRBool 1269 SECMOD_GetSkipFirstFlag(SECMODModule *mod) 1270 { 1271 char flags = (char)mod->isModuleDB; 1272 1273 return (flags & SECMOD_FLAG_MODULE_DB_SKIP_FIRST) ? PR_TRUE : PR_FALSE; 1274 } 1275 1276 PRBool 1277 SECMOD_GetDefaultModDBFlag(SECMODModule *mod) 1278 { 1279 char flags = (char)mod->isModuleDB; 1280 1281 return (flags & SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB) ? PR_TRUE : PR_FALSE; 1282 } 1283 1284 PRBool 1285 secmod_PolicyOnly(SECMODModule *mod) 1286 { 1287 char flags = (char)mod->isModuleDB; 1288 1289 return (flags & SECMOD_FLAG_MODULE_DB_POLICY_ONLY) ? PR_TRUE : PR_FALSE; 1290 } 1291 1292 PRBool 1293 secmod_IsInternalKeySlot(SECMODModule *mod) 1294 { 1295 char flags = (char)mod->internal; 1296 1297 return (flags & SECMOD_FLAG_INTERNAL_KEY_SLOT) ? PR_TRUE : PR_FALSE; 1298 } 1299 1300 void 1301 secmod_SetInternalKeySlotFlag(SECMODModule *mod, PRBool val) 1302 { 1303 char flags = (char)mod->internal; 1304 1305 if (val) { 1306 flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT; 1307 } else { 1308 flags &= ~SECMOD_FLAG_INTERNAL_KEY_SLOT; 1309 } 1310 mod->internal = flags; 1311 } 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 { 1326 int diff, esc_len; 1327 1328 esc_len = NSSUTIL_EscapeSize(value, '\"') - 1; 1329 diff = esc_len - strlen(value); 1330 if (diff > 0) { 1331 /* we need to escape... expand newSpecPtr as well to make sure 1332 * we don't overflow it */ 1333 int offset = target - *base; 1334 char *newPtr = PORT_Realloc(*base, *baseLen + diff); 1335 if (!newPtr) { 1336 return target; /* not enough space, just drop the whole copy */ 1337 } 1338 *baseLen += diff; 1339 target = newPtr + offset; 1340 *base = newPtr; 1341 value = NSSUTIL_Escape(value, '\"'); 1342 if (value == NULL) { 1343 return target; /* couldn't escape value, just drop the copy */ 1344 } 1345 } 1346 PORT_Memcpy(target, desc, descLen); 1347 target += descLen; 1348 *target++ = '\"'; 1349 PORT_Memcpy(target, value, esc_len); 1350 target += esc_len; 1351 *target++ = '\"'; 1352 if (diff > 0) { 1353 PORT_Free(value); 1354 } 1355 return target; 1356 } 1357 1358 #define SECMOD_SPEC_COPY(new, start, end) \ 1359 if (end > start) { \ 1360 int _cnt = end - start; \ 1361 PORT_Memcpy(new, start, _cnt); \ 1362 new += _cnt; \ 1363 } 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 { 1381 int newSpecLen = PORT_Strlen(moduleSpec) + 2; 1382 char *newSpec = PORT_Alloc(newSpecLen); 1383 char *newSpecPtr = newSpec; 1384 const char *modulePrev = moduleSpec; 1385 char *target = NULL; 1386 char *tmp = NULL; 1387 char **childArray = NULL; 1388 const char *tokenIndex; 1389 CK_SLOT_ID *idArray = NULL; 1390 int tokenCount = 0; 1391 int i; 1392 1393 if (newSpec == NULL) { 1394 return NULL; 1395 } 1396 1397 *children = NULL; 1398 if (ids) { 1399 *ids = NULL; 1400 } 1401 moduleSpec = NSSUTIL_ArgStrip(moduleSpec); 1402 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 while (*moduleSpec) { 1431 int next; 1432 modulePrev = moduleSpec; 1433 NSSUTIL_HANDLE_STRING_ARG(moduleSpec, target, "tokens=", 1434 modulePrev = moduleSpec; 1435 /* skip copying */) 1436 NSSUTIL_HANDLE_STRING_ARG( 1437 moduleSpec, tmp, "cryptoTokenDescription=", 1438 if (convert) { modulePrev = moduleSpec; }) 1439 NSSUTIL_HANDLE_STRING_ARG( 1440 moduleSpec, tmp, "cryptoSlotDescription=", 1441 if (convert) { modulePrev = moduleSpec; }) 1442 NSSUTIL_HANDLE_STRING_ARG( 1443 moduleSpec, tmp, "dbTokenDescription=", 1444 if (convert) { 1445 modulePrev = moduleSpec; 1446 if (!isFIPS) { 1447 newSpecPtr = secmod_doDescCopy(newSpecPtr, 1448 &newSpec, &newSpecLen, 1449 SECMOD_TOKEN_DESCRIPTION, 1450 sizeof(SECMOD_TOKEN_DESCRIPTION) - 1, 1451 tmp); 1452 } 1453 }) 1454 NSSUTIL_HANDLE_STRING_ARG( 1455 moduleSpec, tmp, "dbSlotDescription=", 1456 if (convert) { 1457 modulePrev = moduleSpec; /* skip copying */ 1458 if (!isFIPS) { 1459 newSpecPtr = secmod_doDescCopy(newSpecPtr, 1460 &newSpec, &newSpecLen, 1461 SECMOD_SLOT_DESCRIPTION, 1462 sizeof(SECMOD_SLOT_DESCRIPTION) - 1, 1463 tmp); 1464 } 1465 }) 1466 NSSUTIL_HANDLE_STRING_ARG( 1467 moduleSpec, tmp, "FIPSTokenDescription=", 1468 if (convert) { 1469 modulePrev = moduleSpec; /* skip copying */ 1470 if (isFIPS) { 1471 newSpecPtr = secmod_doDescCopy(newSpecPtr, 1472 &newSpec, &newSpecLen, 1473 SECMOD_TOKEN_DESCRIPTION, 1474 sizeof(SECMOD_TOKEN_DESCRIPTION) - 1, 1475 tmp); 1476 } 1477 }) 1478 NSSUTIL_HANDLE_STRING_ARG( 1479 moduleSpec, tmp, "FIPSSlotDescription=", 1480 if (convert) { 1481 modulePrev = moduleSpec; /* skip copying */ 1482 if (isFIPS) { 1483 newSpecPtr = secmod_doDescCopy(newSpecPtr, 1484 &newSpec, &newSpecLen, 1485 SECMOD_SLOT_DESCRIPTION, 1486 sizeof(SECMOD_SLOT_DESCRIPTION) - 1, 1487 tmp); 1488 } 1489 }) 1490 NSSUTIL_HANDLE_FINAL_ARG(moduleSpec) 1491 SECMOD_SPEC_COPY(newSpecPtr, modulePrev, moduleSpec); 1492 } 1493 if (tmp) { 1494 PORT_Free(tmp); 1495 tmp = NULL; 1496 } 1497 *newSpecPtr = 0; 1498 1499 /* no target found, return the newSpec */ 1500 if (target == NULL) { 1501 return newSpec; 1502 } 1503 1504 /* now build the child array from target */ 1505 /*first count them */ 1506 for (tokenIndex = NSSUTIL_ArgStrip(target); *tokenIndex; 1507 tokenIndex = NSSUTIL_ArgStrip(NSSUTIL_ArgSkipParameter(tokenIndex))) { 1508 tokenCount++; 1509 } 1510 1511 childArray = PORT_NewArray(char *, tokenCount + 1); 1512 if (childArray == NULL) { 1513 /* just return the spec as is then */ 1514 PORT_Free(target); 1515 return newSpec; 1516 } 1517 if (ids) { 1518 idArray = PORT_NewArray(CK_SLOT_ID, tokenCount + 1); 1519 if (idArray == NULL) { 1520 PORT_Free(childArray); 1521 PORT_Free(target); 1522 return newSpec; 1523 } 1524 } 1525 1526 /* now fill them in */ 1527 for (tokenIndex = NSSUTIL_ArgStrip(target), i = 0; 1528 *tokenIndex && (i < tokenCount); 1529 tokenIndex = NSSUTIL_ArgStrip(tokenIndex)) { 1530 int next; 1531 char *name = NSSUTIL_ArgGetLabel(tokenIndex, &next); 1532 tokenIndex += next; 1533 1534 if (idArray) { 1535 idArray[i] = NSSUTIL_ArgDecodeNumber(name); 1536 } 1537 1538 PORT_Free(name); /* drop the explicit number */ 1539 1540 /* if anything is left, copy the args to the child array */ 1541 if (!NSSUTIL_ArgIsBlank(*tokenIndex)) { 1542 childArray[i++] = NSSUTIL_ArgFetchValue(tokenIndex, &next); 1543 tokenIndex += next; 1544 } 1545 } 1546 1547 PORT_Free(target); 1548 childArray[i] = 0; 1549 if (idArray) { 1550 idArray[i] = 0; 1551 } 1552 1553 /* return it */ 1554 *children = childArray; 1555 if (ids) { 1556 *ids = idArray; 1557 } 1558 return newSpec; 1559 } 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 { 1566 char *config = NULL; 1567 1568 *certPrefix = NULL; 1569 *keyPrefix = NULL; 1570 *readOnly = NSSUTIL_ArgHasFlag("flags", "readOnly", spec); 1571 if (NSSUTIL_ArgHasFlag("flags", "nocertdb", spec) || 1572 NSSUTIL_ArgHasFlag("flags", "nokeydb", spec)) { 1573 return NULL; 1574 } 1575 1576 spec = NSSUTIL_ArgStrip(spec); 1577 while (*spec) { 1578 int next; 1579 NSSUTIL_HANDLE_STRING_ARG(spec, config, "configdir=", ;) 1580 NSSUTIL_HANDLE_STRING_ARG(spec, *certPrefix, "certPrefix=", ;) 1581 NSSUTIL_HANDLE_STRING_ARG(spec, *keyPrefix, "keyPrefix=", ;) 1582 NSSUTIL_HANDLE_FINAL_ARG(spec) 1583 } 1584 return config; 1585 } 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 { 1600 char **children; 1601 CK_SLOT_ID *ids; 1602 char *strippedSpec; 1603 int childCount; 1604 SECMODConfigList *conflist = NULL; 1605 int i; 1606 1607 strippedSpec = secmod_ParseModuleSpecForTokens(PR_TRUE, isFIPS, 1608 spec, &children, &ids); 1609 if (strippedSpec == NULL) { 1610 return NULL; 1611 } 1612 1613 for (childCount = 0; children && children[childCount]; childCount++) 1614 ; 1615 *count = childCount + 1; /* include strippedSpec */ 1616 conflist = PORT_NewArray(SECMODConfigList, *count); 1617 if (conflist == NULL) { 1618 *count = 0; 1619 goto loser; 1620 } 1621 1622 conflist[0].config = secmod_getConfigDir(strippedSpec, 1623 &conflist[0].certPrefix, 1624 &conflist[0].keyPrefix, 1625 &conflist[0].isReadOnly); 1626 for (i = 0; i < childCount; i++) { 1627 conflist[i + 1].config = secmod_getConfigDir(children[i], 1628 &conflist[i + 1].certPrefix, 1629 &conflist[i + 1].keyPrefix, 1630 &conflist[i + 1].isReadOnly); 1631 } 1632 1633 loser: 1634 secmod_FreeChildren(children, ids); 1635 PORT_Free(strippedSpec); 1636 return conflist; 1637 } 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 { 1646 char *env; 1647 1648 /* explicit dbm open */ 1649 if (strncmp(configDir, "dbm:", 4) == 0) { 1650 return PR_TRUE; 1651 } 1652 /* explicit open of a non-dbm database */ 1653 if ((strncmp(configDir, "sql:", 4) == 0) || 1654 (strncmp(configDir, "rdb:", 4) == 0) || 1655 (strncmp(configDir, "extern:", 7) == 0)) { 1656 return PR_FALSE; 1657 } 1658 env = PR_GetEnvSecure("NSS_DEFAULT_DB_TYPE"); 1659 /* implicit dbm open */ 1660 if ((env == NULL) || (strcmp(env, "dbm") == 0)) { 1661 return PR_TRUE; 1662 } 1663 /* implicit non-dbm open */ 1664 return PR_FALSE; 1665 } 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 { 1673 if ((prefix1 == NULL) || (*prefix1 == 0)) { 1674 if ((prefix2 == NULL) || (*prefix2 == 0)) { 1675 return PR_TRUE; 1676 } 1677 return PR_FALSE; 1678 } 1679 if (strcmp(prefix1, prefix2) == 0) { 1680 return PR_TRUE; 1681 } 1682 return PR_FALSE; 1683 } 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 { 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 if ((configDir1 == NULL) || (configDir2 == NULL)) { 1699 return PR_FALSE; 1700 } 1701 if (strcmp(configDir1, configDir2) != 0) { 1702 return PR_FALSE; 1703 } 1704 if (!secmod_matchPrefix(certPrefix1, certPrefix2)) { 1705 return PR_FALSE; 1706 } 1707 if (!secmod_matchPrefix(keyPrefix1, keyPrefix2)) { 1708 return PR_FALSE; 1709 } 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 if (isReadOnly1) { 1714 return PR_TRUE; 1715 } 1716 if (isReadOnly2) { /* isReadonly1 == PR_FALSE */ 1717 return PR_FALSE; 1718 } 1719 return PR_TRUE; 1720 } 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 { 1728 char *config; 1729 char *certPrefix; 1730 char *keyPrefix; 1731 PRBool isReadOnly; 1732 PRBool ret = PR_FALSE; 1733 int i; 1734 1735 config = secmod_getConfigDir(spec, &certPrefix, &keyPrefix, &isReadOnly); 1736 if (!config) { 1737 goto done; 1738 } 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 if (secmod_configIsDBM(config)) { 1746 isReadOnly = 1; 1747 } 1748 for (i = 0; i < count; i++) { 1749 if (secmod_matchConfig(config, conflist[i].config, certPrefix, 1750 conflist[i].certPrefix, keyPrefix, 1751 conflist[i].keyPrefix, isReadOnly, 1752 conflist[i].isReadOnly)) { 1753 ret = PR_TRUE; 1754 goto done; 1755 } 1756 } 1757 1758 ret = PR_FALSE; 1759 done: 1760 PORT_Free(config); 1761 PORT_Free(certPrefix); 1762 PORT_Free(keyPrefix); 1763 return ret; 1764 } 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 { 1773 char *tmp_spec = NULL; 1774 char **children, **thisChild; 1775 CK_SLOT_ID *ids, *thisID, slotID = -1; 1776 char *inConfig = NULL, *thisConfig = NULL; 1777 char *inCertPrefix = NULL, *thisCertPrefix = NULL; 1778 char *inKeyPrefix = NULL, *thisKeyPrefix = NULL; 1779 PRBool inReadOnly, thisReadOnly; 1780 1781 inConfig = secmod_getConfigDir(moduleSpec, &inCertPrefix, &inKeyPrefix, 1782 &inReadOnly); 1783 if (!inConfig) { 1784 goto done; 1785 } 1786 1787 if (secmod_configIsDBM(inConfig)) { 1788 inReadOnly = 1; 1789 } 1790 1791 tmp_spec = secmod_ParseModuleSpecForTokens(PR_TRUE, module->isFIPS, 1792 module->libraryParams, &children, &ids); 1793 if (tmp_spec == NULL) { 1794 goto done; 1795 } 1796 1797 /* first check to see if the parent is the database */ 1798 thisConfig = secmod_getConfigDir(tmp_spec, &thisCertPrefix, &thisKeyPrefix, 1799 &thisReadOnly); 1800 if (!thisConfig) { 1801 goto done; 1802 } 1803 if (secmod_matchConfig(inConfig, thisConfig, inCertPrefix, thisCertPrefix, 1804 inKeyPrefix, thisKeyPrefix, inReadOnly, thisReadOnly)) { 1805 /* yup it's the default key slot, get the id for it */ 1806 PK11SlotInfo *slot = PK11_GetInternalKeySlot(); 1807 if (slot) { 1808 slotID = slot->slotID; 1809 PK11_FreeSlot(slot); 1810 } 1811 goto done; 1812 } 1813 1814 /* find id of the token */ 1815 for (thisChild = children, thisID = ids; thisChild && *thisChild; thisChild++, thisID++) { 1816 PORT_Free(thisConfig); 1817 PORT_Free(thisCertPrefix); 1818 PORT_Free(thisKeyPrefix); 1819 thisConfig = secmod_getConfigDir(*thisChild, &thisCertPrefix, 1820 &thisKeyPrefix, &thisReadOnly); 1821 if (thisConfig == NULL) { 1822 continue; 1823 } 1824 if (secmod_matchConfig(inConfig, thisConfig, inCertPrefix, thisCertPrefix, 1825 inKeyPrefix, thisKeyPrefix, inReadOnly, thisReadOnly)) { 1826 slotID = *thisID; 1827 break; 1828 } 1829 } 1830 1831 done: 1832 PORT_Free(inConfig); 1833 PORT_Free(inCertPrefix); 1834 PORT_Free(inKeyPrefix); 1835 PORT_Free(thisConfig); 1836 PORT_Free(thisCertPrefix); 1837 PORT_Free(thisKeyPrefix); 1838 if (tmp_spec) { 1839 secmod_FreeChildren(children, ids); 1840 PORT_Free(tmp_spec); 1841 } 1842 return slotID; 1843 } 1844 1845 void 1846 secmod_FreeConfigList(SECMODConfigList *conflist, int count) 1847 { 1848 int i; 1849 for (i = 0; i < count; i++) { 1850 PORT_Free(conflist[i].config); 1851 PORT_Free(conflist[i].certPrefix); 1852 PORT_Free(conflist[i].keyPrefix); 1853 } 1854 PORT_Free(conflist); 1855 } 1856 1857 void 1858 secmod_FreeChildren(char **children, CK_SLOT_ID *ids) 1859 { 1860 char **thisChild; 1861 1862 if (!children) { 1863 return; 1864 } 1865 1866 for (thisChild = children; thisChild && *thisChild; thisChild++) { 1867 PORT_Free(*thisChild); 1868 } 1869 PORT_Free(children); 1870 if (ids) { 1871 PORT_Free(ids); 1872 } 1873 return; 1874 } 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 { 1883 int length = NSSUTIL_DoubleEscapeSize(child, '>', ']'); 1884 if (id == 0) { 1885 length++; 1886 } 1887 while (id) { 1888 length++; 1889 id = id >> 4; 1890 } 1891 length += 6; /* {sp}0x[id]=<{child}> */ 1892 return length; 1893 } 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 { 1902 int len; 1903 char *escSpec; 1904 1905 len = PR_snprintf(*next, *length, " 0x%x=<", id); 1906 if (len < 0) { 1907 return SECFailure; 1908 } 1909 *next += len; 1910 *length -= len; 1911 escSpec = NSSUTIL_DoubleEscape(child, '>', ']'); 1912 if (escSpec == NULL) { 1913 return SECFailure; 1914 } 1915 if (*child && (*escSpec == 0)) { 1916 PORT_Free(escSpec); 1917 return SECFailure; 1918 } 1919 len = strlen(escSpec); 1920 if (len + 1 > *length) { 1921 PORT_Free(escSpec); 1922 return SECFailure; 1923 } 1924 PORT_Memcpy(*next, escSpec, len); 1925 *next += len; 1926 *length -= len; 1927 PORT_Free(escSpec); 1928 **next = '>'; 1929 (*next)++; 1930 (*length)--; 1931 return SECSuccess; 1932 } 1933 1934 #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 { 1940 char *rawParam = NULL; /* oldParam with tokens stripped off */ 1941 char *newParam = NULL; /* space for the return parameter */ 1942 char *nextParam = NULL; /* current end of the new parameter */ 1943 char **oldChildren = NULL; 1944 CK_SLOT_ID *oldIds = NULL; 1945 void *mark = NULL; /* mark the arena pool in case we need 1946 * to release it */ 1947 int length, i, tmpLen; 1948 SECStatus rv; 1949 1950 /* first strip out and save the old tokenlist */ 1951 rawParam = secmod_ParseModuleSpecForTokens(PR_FALSE, PR_FALSE, 1952 oldParam, &oldChildren, &oldIds); 1953 if (!rawParam) { 1954 goto loser; 1955 } 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 length = strlen(rawParam) + sizeof(TOKEN_STRING) + 1; 1961 /* now add then length of all the old children */ 1962 for (i = 0; oldChildren && oldChildren[i]; i++) { 1963 length += secmod_getChildLength(oldChildren[i], oldIds[i]); 1964 } 1965 1966 /* add the new token */ 1967 length += secmod_getChildLength(newToken, newID); 1968 1969 /* and it's new children */ 1970 for (i = 0; children && children[i]; i++) { 1971 if (ids[i] == -1) { 1972 continue; 1973 } 1974 length += secmod_getChildLength(children[i], ids[i]); 1975 } 1976 1977 /* now allocate and build the string */ 1978 mark = PORT_ArenaMark(arena); 1979 if (!mark) { 1980 goto loser; 1981 } 1982 newParam = PORT_ArenaAlloc(arena, length); 1983 if (!newParam) { 1984 goto loser; 1985 } 1986 1987 PORT_Strcpy(newParam, oldParam); 1988 tmpLen = strlen(oldParam); 1989 nextParam = newParam + tmpLen; 1990 length -= tmpLen; 1991 PORT_Memcpy(nextParam, TOKEN_STRING, sizeof(TOKEN_STRING) - 1); 1992 nextParam += sizeof(TOKEN_STRING) - 1; 1993 length -= sizeof(TOKEN_STRING) - 1; 1994 1995 for (i = 0; oldChildren && oldChildren[i]; i++) { 1996 rv = secmod_mkTokenChild(&nextParam, &length, oldChildren[i], oldIds[i]); 1997 if (rv != SECSuccess) { 1998 goto loser; 1999 } 2000 } 2001 2002 rv = secmod_mkTokenChild(&nextParam, &length, newToken, newID); 2003 if (rv != SECSuccess) { 2004 goto loser; 2005 } 2006 2007 for (i = 0; children && children[i]; i++) { 2008 if (ids[i] == -1) { 2009 continue; 2010 } 2011 rv = secmod_mkTokenChild(&nextParam, &length, children[i], ids[i]); 2012 if (rv != SECSuccess) { 2013 goto loser; 2014 } 2015 } 2016 2017 if (length < 2) { 2018 goto loser; 2019 } 2020 2021 *nextParam++ = ']'; 2022 *nextParam++ = 0; 2023 2024 /* we are going to return newParam now, don't release the mark */ 2025 PORT_ArenaUnmark(arena, mark); 2026 mark = NULL; 2027 2028 loser: 2029 if (mark) { 2030 PORT_ArenaRelease(arena, mark); 2031 newParam = NULL; /* if the mark is still active, 2032 * don't return the param */ 2033 } 2034 if (rawParam) { 2035 PORT_Free(rawParam); 2036 } 2037 if (oldChildren) { 2038 secmod_FreeChildren(oldChildren, oldIds); 2039 } 2040 return newParam; 2041 } 2042 2043 static char * 2044 secmod_mkModuleSpec(SECMODModule *module) 2045 { 2046 char *nss = NULL, *modSpec = NULL, **slotStrings = NULL; 2047 int slotCount, i, si; 2048 SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); 2049 2050 /* allocate target slot info strings */ 2051 slotCount = 0; 2052 2053 SECMOD_GetReadLock(moduleLock); 2054 if (module->slotCount) { 2055 for (i = 0; i < module->slotCount; i++) { 2056 if (module->slots[i]->defaultFlags != 0) { 2057 slotCount++; 2058 } 2059 } 2060 } else { 2061 slotCount = module->slotInfoCount; 2062 } 2063 2064 slotStrings = (char **)PORT_ZAlloc(slotCount * sizeof(char *)); 2065 if (slotStrings == NULL) { 2066 SECMOD_ReleaseReadLock(moduleLock); 2067 goto loser; 2068 } 2069 2070 /* build the slot info strings */ 2071 if (module->slotCount) { 2072 for (i = 0, si = 0; i < module->slotCount; i++) { 2073 if (module->slots[i]->defaultFlags) { 2074 PORT_Assert(si < slotCount); 2075 if (si >= slotCount) 2076 break; 2077 slotStrings[si] = NSSUTIL_MkSlotString(module->slots[i]->slotID, 2078 module->slots[i]->defaultFlags, 2079 module->slots[i]->timeout, 2080 module->slots[i]->askpw, 2081 module->slots[i]->hasRootCerts, 2082 module->slots[i]->hasRootTrust); 2083 si++; 2084 } 2085 } 2086 } else { 2087 for (i = 0; i < slotCount; i++) { 2088 slotStrings[i] = NSSUTIL_MkSlotString( 2089 module->slotInfo[i].slotID, 2090 module->slotInfo[i].defaultFlags, 2091 module->slotInfo[i].timeout, 2092 module->slotInfo[i].askpw, 2093 module->slotInfo[i].hasRootCerts, 2094 module->slotInfo[i].hasRootTrust); 2095 } 2096 } 2097 2098 SECMOD_ReleaseReadLock(moduleLock); 2099 nss = NSSUTIL_MkNSSString(slotStrings, slotCount, module->internal, 2100 module->isFIPS, module->isModuleDB, 2101 module->moduleDBOnly, module->isCritical, 2102 module->trustOrder, module->cipherOrder, 2103 module->ssl[0], module->ssl[1]); 2104 modSpec = NSSUTIL_MkModuleSpec(module->dllName, module->commonName, 2105 module->libraryParams, nss); 2106 PORT_Free(slotStrings); 2107 PR_smprintf_free(nss); 2108 loser: 2109 return (modSpec); 2110 } 2111 2112 char ** 2113 SECMOD_GetModuleSpecList(SECMODModule *module) 2114 { 2115 SECMODModuleDBFunc func = (SECMODModuleDBFunc)module->moduleDBFunc; 2116 if (func) { 2117 return (*func)(SECMOD_MODULE_DB_FUNCTION_FIND, 2118 module->libraryParams, NULL); 2119 } 2120 return NULL; 2121 } 2122 2123 SECStatus 2124 SECMOD_AddPermDB(SECMODModule *module) 2125 { 2126 SECMODModuleDBFunc func; 2127 char *moduleSpec; 2128 char **retString; 2129 2130 if (module->parent == NULL) 2131 return SECFailure; 2132 2133 func = (SECMODModuleDBFunc)module->parent->moduleDBFunc; 2134 if (func) { 2135 moduleSpec = secmod_mkModuleSpec(module); 2136 retString = (*func)(SECMOD_MODULE_DB_FUNCTION_ADD, 2137 module->parent->libraryParams, moduleSpec); 2138 PORT_Free(moduleSpec); 2139 if (retString != NULL) 2140 return SECSuccess; 2141 } 2142 return SECFailure; 2143 } 2144 2145 SECStatus 2146 SECMOD_DeletePermDB(SECMODModule *module) 2147 { 2148 SECMODModuleDBFunc func; 2149 char *moduleSpec; 2150 char **retString; 2151 2152 if (module->parent == NULL) 2153 return SECFailure; 2154 2155 func = (SECMODModuleDBFunc)module->parent->moduleDBFunc; 2156 if (func) { 2157 moduleSpec = secmod_mkModuleSpec(module); 2158 retString = (*func)(SECMOD_MODULE_DB_FUNCTION_DEL, 2159 module->parent->libraryParams, moduleSpec); 2160 PORT_Free(moduleSpec); 2161 if (retString != NULL) 2162 return SECSuccess; 2163 } 2164 return SECFailure; 2165 } 2166 2167 SECStatus 2168 SECMOD_FreeModuleSpecList(SECMODModule *module, char **moduleSpecList) 2169 { 2170 SECMODModuleDBFunc func = (SECMODModuleDBFunc)module->moduleDBFunc; 2171 char **retString; 2172 if (func) { 2173 retString = (*func)(SECMOD_MODULE_DB_FUNCTION_RELEASE, 2174 module->libraryParams, moduleSpecList); 2175 if (retString != NULL) 2176 return SECSuccess; 2177 } 2178 return SECFailure; 2179 } 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 { 2187 char *library = NULL, *moduleName = NULL, *parameters = NULL, *nss = NULL; 2188 char *config = NULL; 2189 SECStatus status; 2190 SECMODModule *module = NULL; 2191 SECMODModule *oldModule = NULL; 2192 SECStatus rv; 2193 PRBool forwardPolicyFeedback = PR_FALSE; 2194 PRUint32 forwardPolicyCheckFlags; 2195 2196 /* initialize the underlying module structures */ 2197 SECMOD_Init(); 2198 2199 status = NSSUTIL_ArgParseModuleSpecEx(modulespec, &library, &moduleName, 2200 ¶meters, &nss, 2201 &config); 2202 if (status != SECSuccess) { 2203 goto loser; 2204 } 2205 2206 module = SECMOD_CreateModuleEx(library, moduleName, parameters, nss, config); 2207 forwardPolicyFeedback = NSSUTIL_ArgHasFlag("flags", "printPolicyFeedback", nss); 2208 forwardPolicyCheckFlags = secmod_parsePolicyCheckFlags(nss); 2209 2210 if (library) 2211 PORT_Free(library); 2212 if (moduleName) 2213 PORT_Free(moduleName); 2214 if (parameters) 2215 PORT_Free(parameters); 2216 if (nss) 2217 PORT_Free(nss); 2218 if (config) 2219 PORT_Free(config); 2220 if (!module) { 2221 goto loser; 2222 } 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 if (secmod_PolicyOnly(module)) { 2227 return module; 2228 } 2229 if (parent) { 2230 module->parent = SECMOD_ReferenceModule(parent); 2231 if (module->internal && secmod_IsInternalKeySlot(parent)) { 2232 module->internal = parent->internal; 2233 } 2234 } 2235 2236 /* load it */ 2237 rv = secmod_LoadPKCS11Module(module, &oldModule); 2238 if (rv != SECSuccess) { 2239 goto loser; 2240 } 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 if (oldModule) { 2245 /* This module already exists, don't link it anywhere. This 2246 * will probably destroy this module */ 2247 SECMOD_DestroyModule(module); 2248 return oldModule; 2249 } 2250 2251 if (recurse && module->isModuleDB) { 2252 char **moduleSpecList; 2253 PORT_SetError(0); 2254 2255 moduleSpecList = SECMOD_GetModuleSpecList(module); 2256 if (moduleSpecList) { 2257 char **index; 2258 2259 index = moduleSpecList; 2260 if (*index && SECMOD_GetSkipFirstFlag(module)) { 2261 index++; 2262 } 2263 2264 for (; *index; index++) { 2265 SECMODModule *child; 2266 if (0 == PORT_Strcmp(*index, modulespec)) { 2267 /* avoid trivial infinite recursion */ 2268 PORT_SetError(SEC_ERROR_NO_MODULE); 2269 rv = SECFailure; 2270 break; 2271 } 2272 if (!forwardPolicyFeedback) { 2273 child = SECMOD_LoadModule(*index, module, PR_TRUE); 2274 } else { 2275 /* Add printPolicyFeedback to the nss flags */ 2276 char *specWithForwards = 2277 NSSUTIL_AddNSSFlagToModuleSpec(*index, "printPolicyFeedback"); 2278 char *tmp; 2279 if (forwardPolicyCheckFlags & SECMOD_FLAG_POLICY_CHECK_IDENTIFIER) { 2280 tmp = NSSUTIL_AddNSSFlagToModuleSpec(specWithForwards, "policyCheckIdentifier"); 2281 PORT_Free(specWithForwards); 2282 specWithForwards = tmp; 2283 } 2284 if (forwardPolicyCheckFlags & SECMOD_FLAG_POLICY_CHECK_VALUE) { 2285 tmp = NSSUTIL_AddNSSFlagToModuleSpec(specWithForwards, "policyCheckValue"); 2286 PORT_Free(specWithForwards); 2287 specWithForwards = tmp; 2288 } 2289 child = SECMOD_LoadModule(specWithForwards, module, PR_TRUE); 2290 PORT_Free(specWithForwards); 2291 } 2292 if (!child) 2293 break; 2294 if (child->isCritical && !child->loaded) { 2295 int err = PORT_GetError(); 2296 if (!err) 2297 err = SEC_ERROR_NO_MODULE; 2298 SECMOD_DestroyModule(child); 2299 PORT_SetError(err); 2300 rv = SECFailure; 2301 break; 2302 } 2303 SECMOD_DestroyModule(child); 2304 } 2305 SECMOD_FreeModuleSpecList(module, moduleSpecList); 2306 } else { 2307 if (!PORT_GetError()) 2308 PORT_SetError(SEC_ERROR_NO_MODULE); 2309 rv = SECFailure; 2310 } 2311 } 2312 2313 if (rv != SECSuccess) { 2314 goto loser; 2315 } 2316 2317 /* inherit the reference */ 2318 if (!module->moduleDBOnly) { 2319 SECMOD_AddModuleToList(module); 2320 } else { 2321 SECMOD_AddModuleToDBOnlyList(module); 2322 } 2323 2324 /* handle any additional work here */ 2325 return module; 2326 2327 loser: 2328 if (module) { 2329 if (module->loaded) { 2330 SECMOD_UnloadModule(module); 2331 } 2332 SECMOD_AddModuleToUnloadList(module); 2333 } 2334 return module; 2335 } 2336 2337 SECMODModule * 2338 SECMOD_LoadModuleWithFunction(const char *moduleName, CK_C_GetFunctionList fentry) 2339 { 2340 SECMODModule *module = NULL; 2341 SECMODModule *oldModule = NULL; 2342 SECStatus rv; 2343 2344 /* initialize the underlying module structures */ 2345 SECMOD_Init(); 2346 2347 module = secmod_NewModule(); 2348 if (module == NULL) { 2349 goto loser; 2350 } 2351 2352 module->commonName = PORT_ArenaStrdup(module->arena, moduleName ? moduleName : ""); 2353 module->internal = PR_FALSE; 2354 module->isFIPS = PR_FALSE; 2355 /* if the system FIPS mode is enabled, force FIPS to be on */ 2356 if (SECMOD_GetSystemFIPSEnabled()) { 2357 module->isFIPS = PR_TRUE; 2358 } 2359 2360 module->isCritical = PR_FALSE; 2361 /* new field */ 2362 module->trustOrder = NSSUTIL_DEFAULT_TRUST_ORDER; 2363 /* new field */ 2364 module->cipherOrder = NSSUTIL_DEFAULT_CIPHER_ORDER; 2365 /* new field */ 2366 module->isModuleDB = PR_FALSE; 2367 module->moduleDBOnly = PR_FALSE; 2368 2369 module->ssl[0] = 0; 2370 module->ssl[1] = 0; 2371 2372 secmod_PrivateModuleCount++; 2373 2374 /* load it */ 2375 rv = secmod_LoadPKCS11ModuleFromFunction(module, &oldModule, fentry); 2376 if (rv != SECSuccess) { 2377 goto loser; 2378 } 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 if (oldModule) { 2383 /* This module already exists, don't link it anywhere. This 2384 * will probably destroy this module */ 2385 SECMOD_DestroyModule(module); 2386 return oldModule; 2387 } 2388 2389 SECMOD_AddModuleToList(module); 2390 /* handle any additional work here */ 2391 return module; 2392 2393 loser: 2394 if (module) { 2395 if (module->loaded) { 2396 SECMOD_UnloadModule(module); 2397 } 2398 SECMOD_AddModuleToUnloadList(module); 2399 } 2400 return module; 2401 } 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 { 2409 SECStatus rv = SECSuccess; 2410 SECMODModule *newmod = SECMOD_LoadModule(modulespec, parent, recurse); 2411 SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); 2412 2413 if (newmod) { 2414 SECMOD_GetReadLock(moduleLock); 2415 rv = STAN_AddModuleToDefaultTrustDomain(newmod); 2416 SECMOD_ReleaseReadLock(moduleLock); 2417 if (SECSuccess != rv) { 2418 SECMOD_DestroyModule(newmod); 2419 return NULL; 2420 } 2421 } 2422 return newmod; 2423 } 2424 2425 SECMODModule * 2426 SECMOD_LoadUserModuleWithFunction(const char *moduleName, CK_C_GetFunctionList fentry) 2427 { 2428 SECStatus rv = SECSuccess; 2429 SECMODModule *newmod = SECMOD_LoadModuleWithFunction(moduleName, fentry); 2430 SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); 2431 2432 if (newmod) { 2433 SECMOD_GetReadLock(moduleLock); 2434 rv = STAN_AddModuleToDefaultTrustDomain(newmod); 2435 SECMOD_ReleaseReadLock(moduleLock); 2436 if (SECSuccess != rv) { 2437 SECMOD_DestroyModule(newmod); 2438 return NULL; 2439 } 2440 } 2441 return newmod; 2442 } 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 { 2451 SECStatus rv = SECSuccess; 2452 int atype = 0; 2453 SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); 2454 if (!mod) { 2455 return SECFailure; 2456 } 2457 2458 SECMOD_GetReadLock(moduleLock); 2459 rv = STAN_RemoveModuleFromDefaultTrustDomain(mod); 2460 SECMOD_ReleaseReadLock(moduleLock); 2461 if (SECSuccess != rv) { 2462 return SECFailure; 2463 } 2464 return SECMOD_DeleteModuleEx(NULL, mod, &atype, PR_FALSE); 2465 }