| 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 |