| 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 * This file implements PKCS 11 on top of our existing security modules | |
| 6 * | |
| 7 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard. | |
| 8 * This implementation has two slots: | |
| 9 * slot 1 is our generic crypto support. It does not require login. | |
| 10 * It supports Public Key ops, and all they bulk ciphers and hashes. | |
| 11 * It can also support Private Key ops for imported Private keys. It does | |
| 12 * not have any token storage. | |
| 13 * slot 2 is our private key support. It requires a login before use. It | |
| 14 * can store Private Keys and Certs as token objects. Currently only private | |
| 15 * keys and their associated Certificates are saved on the token. | |
| 16 * | |
| 17 * In this implementation, session objects are only visible to the session | |
| 18 * that created or generated them. | |
| 19 */ | |
| 20 #include "seccomon.h" | |
| 21 #include "secitem.h" | |
| 22 #include "pkcs11.h" | |
| 23 #include "pkcs11i.h" | |
| 24 #include "softoken.h" | |
| 25 #include "lowkeyi.h" | |
| 26 #include "blapi.h" | |
| 27 #include "secder.h" | |
| 28 #include "secport.h" | |
| 29 #include "secrng.h" | |
| 30 #include "prtypes.h" | |
| 31 #include "nspr.h" | |
| 32 #include "softkver.h" | |
| 33 #include "secoid.h" | |
| 34 #include "sftkdb.h" | |
| 35 #include "utilpars.h" | |
| 36 #include "ec.h" | |
| 37 #include "secasn1.h" | |
| 38 #include "secerr.h" | |
| 39 #include "lgglue.h" | |
| 40 | |
| 41 PRBool parentForkedAfterC_Initialize; | |
| 42 | |
| 43 #ifndef NO_FORK_CHECK | |
| 44 | |
| 45 PRBool sftkForkCheckDisabled; | |
| 46 | |
| 47 #if defined(CHECK_FORK_PTHREAD) || defined(CHECK_FORK_MIXED) | |
| 48 PRBool forked = PR_FALSE; | |
| 49 #endif | |
| 50 | |
| 51 #if defined(CHECK_FORK_GETPID) || defined(CHECK_FORK_MIXED) | |
| 52 #include <unistd.h> | |
| 53 pid_t myPid; | |
| 54 #endif | |
| 55 | |
| 56 #ifdef CHECK_FORK_MIXED | |
| 57 #include <sys/systeminfo.h> | |
| 58 PRBool usePthread_atfork; | |
| 59 #endif | |
| 60 | |
| 61 #endif | |
| 62 | |
| 63 /* | |
| 64 * ******************** Static data ******************************* | |
| 65 */ | |
| 66 | |
| 67 /* The next three strings must be exactly 32 characters long */ | |
| 68 static char *manufacturerID = "Mozilla Foundation "; | |
| 69 static char manufacturerID_space[33]; | |
| 70 static char *libraryDescription = "NSS Internal Crypto Services "; | |
| 71 static char libraryDescription_space[33]; | |
| 72 | |
| 73 /* | |
| 74 * In FIPS mode, we disallow login attempts for 1 second after a login | |
| 75 * failure so that there are at most 60 login attempts per minute. | |
| 76 */ | |
| 77 static PRIntervalTime loginWaitTime; | |
| 78 static PRUint32 minSessionObjectHandle = 1U; | |
| 79 | |
| 80 #define __PASTE(x,y) x##y | |
| 81 | |
| 82 /* | |
| 83 * we renamed all our internal functions, get the correct | |
| 84 * definitions for them... | |
| 85 */ | |
| 86 #undef CK_PKCS11_FUNCTION_INFO | |
| 87 #undef CK_NEED_ARG_LIST | |
| 88 | |
| 89 #define CK_EXTERN extern | |
| 90 #define CK_PKCS11_FUNCTION_INFO(func) \ | |
| 91 CK_RV __PASTE(NS,func) | |
| 92 #define CK_NEED_ARG_LIST 1 | |
| 93 | |
| 94 #include "pkcs11f.h" | |
| 95 | |
| 96 | |
| 97 | |
| 98 /* build the crypto module table */ | |
| 99 static const CK_FUNCTION_LIST sftk_funcList = { | |
| 100 { 1, 10 }, | |
| 101 | |
| 102 #undef CK_PKCS11_FUNCTION_INFO | |
| 103 #undef CK_NEED_ARG_LIST | |
| 104 | |
| 105 #define CK_PKCS11_FUNCTION_INFO(func) \ | |
| 106 __PASTE(NS,func), | |
| 107 #include "pkcs11f.h" | |
| 108 | |
| 109 }; | |
| 110 | |
| 111 #undef CK_PKCS11_FUNCTION_INFO | |
| 112 #undef CK_NEED_ARG_LIST | |
| 113 | |
| 114 | |
| 115 #undef __PASTE | |
| 116 | |
| 117 /* List of DES Weak Keys */ | |
| 118 typedef unsigned char desKey[8]; | |
| 119 static const desKey sftk_desWeakTable[] = { | |
| 120 #ifdef noParity | |
| 121 /* weak */ | |
| 122 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, | |
| 123 { 0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e }, | |
| 124 { 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0 }, | |
| 125 { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }, | |
| 126 /* semi-weak */ | |
| 127 { 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe }, | |
| 128 { 0xfe, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0xfe }, | |
| 129 | |
| 130 { 0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0 }, | |
| 131 { 0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e }, | |
| 132 | |
| 133 { 0x00, 0xe0, 0x00, 0xe0, 0x00, 0x0f, 0x00, 0x0f }, | |
| 134 { 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00 }, | |
| 135 | |
| 136 { 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe }, | |
| 137 { 0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e }, | |
| 138 | |
| 139 { 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e }, | |
| 140 { 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00 }, | |
| 141 | |
| 142 { 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe }, | |
| 143 { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0 }, | |
| 144 #else | |
| 145 /* weak */ | |
| 146 { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, | |
| 147 { 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e }, | |
| 148 { 0xe0, 0xe0, 0xe0, 0xe0, 0xf1, 0xf1, 0xf1, 0xf1 }, | |
| 149 { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }, | |
| 150 | |
| 151 /* semi-weak */ | |
| 152 { 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe }, | |
| 153 { 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01 }, | |
| 154 | |
| 155 { 0x1f, 0xe0, 0x1f, 0xe0, 0x0e, 0xf1, 0x0e, 0xf1 }, | |
| 156 { 0xe0, 0x1f, 0xe0, 0x1f, 0xf1, 0x0e, 0xf1, 0x0e }, | |
| 157 | |
| 158 { 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1 }, | |
| 159 { 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1, 0x01 }, | |
| 160 | |
| 161 { 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe }, | |
| 162 { 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e }, | |
| 163 | |
| 164 { 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e }, | |
| 165 { 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e, 0x01 }, | |
| 166 | |
| 167 { 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1, 0xfe }, | |
| 168 { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1 } | |
| 169 #endif | |
| 170 }; | |
| 171 | |
| 172 | |
| 173 static const int sftk_desWeakTableSize = sizeof(sftk_desWeakTable)/ | |
| 174 sizeof(sftk_desWeakTable[0]); | |
| 175 | |
| 176 /* DES KEY Parity conversion table. Takes each byte/2 as an index, returns | |
| 177 * that byte with the proper parity bit set */ | |
| 178 static const unsigned char parityTable[256] = { | |
| 179 /* Even...0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e */ | |
| 180 /* E */ 0x01,0x02,0x04,0x07,0x08,0x0b,0x0d,0x0e, | |
| 181 /* Odd....0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e */ | |
| 182 /* O */ 0x10,0x13,0x15,0x16,0x19,0x1a,0x1c,0x1f, | |
| 183 /* Odd....0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e */ | |
| 184 /* O */ 0x20,0x23,0x25,0x26,0x29,0x2a,0x2c,0x2f, | |
| 185 /* Even...0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e */ | |
| 186 /* E */ 0x31,0x32,0x34,0x37,0x38,0x3b,0x3d,0x3e, | |
| 187 /* Odd....0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e */ | |
| 188 /* O */ 0x40,0x43,0x45,0x46,0x49,0x4a,0x4c,0x4f, | |
| 189 /* Even...0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e */ | |
| 190 /* E */ 0x51,0x52,0x54,0x57,0x58,0x5b,0x5d,0x5e, | |
| 191 /* Even...0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e */ | |
| 192 /* E */ 0x61,0x62,0x64,0x67,0x68,0x6b,0x6d,0x6e, | |
| 193 /* Odd....0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e */ | |
| 194 /* O */ 0x70,0x73,0x75,0x76,0x79,0x7a,0x7c,0x7f, | |
| 195 /* Odd....0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e */ | |
| 196 /* O */ 0x80,0x83,0x85,0x86,0x89,0x8a,0x8c,0x8f, | |
| 197 /* Even...0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e */ | |
| 198 /* E */ 0x91,0x92,0x94,0x97,0x98,0x9b,0x9d,0x9e, | |
| 199 /* Even...0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae */ | |
| 200 /* E */ 0xa1,0xa2,0xa4,0xa7,0xa8,0xab,0xad,0xae, | |
| 201 /* Odd....0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe */ | |
| 202 /* O */ 0xb0,0xb3,0xb5,0xb6,0xb9,0xba,0xbc,0xbf, | |
| 203 /* Even...0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce */ | |
| 204 /* E */ 0xc1,0xc2,0xc4,0xc7,0xc8,0xcb,0xcd,0xce, | |
| 205 /* Odd....0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde */ | |
| 206 /* O */ 0xd0,0xd3,0xd5,0xd6,0xd9,0xda,0xdc,0xdf, | |
| 207 /* Odd....0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee */ | |
| 208 /* O */ 0xe0,0xe3,0xe5,0xe6,0xe9,0xea,0xec,0xef, | |
| 209 /* Even...0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe */ | |
| 210 /* E */ 0xf1,0xf2,0xf4,0xf7,0xf8,0xfb,0xfd,0xfe, | |
| 211 }; | |
| 212 | |
| 213 /* Mechanisms */ | |
| 214 struct mechanismList { | |
| 215 CK_MECHANISM_TYPE type; | |
| 216 CK_MECHANISM_INFO info; | |
| 217 PRBool privkey; | |
| 218 }; | |
| 219 | |
| 220 /* | |
| 221 * the following table includes a complete list of mechanism defined by | |
| 222 * PKCS #11 version 2.01. Those Mechanisms not supported by this PKCS #11 | |
| 223 * module are ifdef'ed out. | |
| 224 */ | |
| 225 #define CKF_EN_DE CKF_ENCRYPT | CKF_DECRYPT | |
| 226 #define CKF_WR_UN CKF_WRAP | CKF_UNWRAP | |
| 227 #define CKF_SN_VR CKF_SIGN | CKF_VERIFY | |
| 228 #define CKF_SN_RE CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER | |
| 229 | |
| 230 #define CKF_EN_DE_WR_UN CKF_EN_DE | CKF_WR_UN | |
| 231 #define CKF_SN_VR_RE CKF_SN_VR | CKF_SN_RE | |
| 232 #define CKF_DUZ_IT_ALL CKF_EN_DE_WR_UN | CKF_SN_VR_RE | |
| 233 | |
| 234 #define CKF_EC_PNU CKF_EC_FP | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRES
S | |
| 235 | |
| 236 #define CKF_EC_BPNU CKF_EC_F_2M | CKF_EC_PNU | |
| 237 | |
| 238 #define CK_MAX 0xffffffff | |
| 239 | |
| 240 static const struct mechanismList mechanisms[] = { | |
| 241 | |
| 242 /* | |
| 243 * PKCS #11 Mechanism List. | |
| 244 * | |
| 245 * The first argument is the PKCS #11 Mechanism we support. | |
| 246 * The second argument is Mechanism info structure. It includes: | |
| 247 * The minimum key size, | |
| 248 * in bits for RSA, DSA, DH, EC*, KEA, RC2 and RC4 * algs. | |
| 249 * in bytes for RC5, AES, Camellia, and CAST* | |
| 250 * ignored for DES*, IDEA and FORTEZZA based | |
| 251 * The maximum key size, | |
| 252 * in bits for RSA, DSA, DH, EC*, KEA, RC2 and RC4 * algs. | |
| 253 * in bytes for RC5, AES, Camellia, and CAST* | |
| 254 * ignored for DES*, IDEA and FORTEZZA based | |
| 255 * Flags | |
| 256 * What operations are supported by this mechanism. | |
| 257 * The third argument is a bool which tells if this mechanism is | |
| 258 * supported in the database token. | |
| 259 * | |
| 260 */ | |
| 261 | |
| 262 /* ------------------------- RSA Operations ---------------------------*/ | |
| 263 {CKM_RSA_PKCS_KEY_PAIR_GEN,{RSA_MIN_MODULUS_BITS,CK_MAX, | |
| 264 CKF_GENERATE_KEY_PAIR},PR_TRUE}, | |
| 265 {CKM_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, | |
| 266 CKF_DUZ_IT_ALL}, PR_TRUE}, | |
| 267 {CKM_RSA_PKCS_PSS, {RSA_MIN_MODULUS_BITS,CK_MAX, | |
| 268 CKF_SN_VR}, PR_TRUE}, | |
| 269 {CKM_RSA_PKCS_OAEP, {RSA_MIN_MODULUS_BITS,CK_MAX, | |
| 270 CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 271 #ifdef SFTK_RSA9796_SUPPORTED | |
| 272 {CKM_RSA_9796, {RSA_MIN_MODULUS_BITS,CK_MAX, | |
| 273 CKF_DUZ_IT_ALL}, PR_TRUE}, | |
| 274 #endif | |
| 275 {CKM_RSA_X_509, {RSA_MIN_MODULUS_BITS,CK_MAX, | |
| 276 CKF_DUZ_IT_ALL}, PR_TRUE}, | |
| 277 /* -------------- RSA Multipart Signing Operations -------------------- */ | |
| 278 {CKM_MD2_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, | |
| 279 CKF_SN_VR}, PR_TRUE}, | |
| 280 {CKM_MD5_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, | |
| 281 CKF_SN_VR}, PR_TRUE}, | |
| 282 {CKM_SHA1_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, | |
| 283 CKF_SN_VR}, PR_TRUE}, | |
| 284 {CKM_SHA224_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, | |
| 285 CKF_SN_VR}, PR_TRUE}, | |
| 286 {CKM_SHA256_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, | |
| 287 CKF_SN_VR}, PR_TRUE}, | |
| 288 {CKM_SHA384_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, | |
| 289 CKF_SN_VR}, PR_TRUE}, | |
| 290 {CKM_SHA512_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, | |
| 291 CKF_SN_VR}, PR_TRUE}, | |
| 292 /* ------------------------- DSA Operations --------------------------- */ | |
| 293 {CKM_DSA_KEY_PAIR_GEN, {DSA_MIN_P_BITS, DSA_MAX_P_BITS, | |
| 294 CKF_GENERATE_KEY_PAIR}, PR_TRUE}, | |
| 295 {CKM_DSA, {DSA_MIN_P_BITS, DSA_MAX_P_BITS, | |
| 296 CKF_SN_VR}, PR_TRUE}, | |
| 297 {CKM_DSA_PARAMETER_GEN, {DSA_MIN_P_BITS, DSA_MAX_P_BITS, | |
| 298 CKF_GENERATE}, PR_TRUE}, | |
| 299 {CKM_DSA_SHA1, {DSA_MIN_P_BITS, DSA_MAX_P_BITS, | |
| 300 CKF_SN_VR}, PR_TRUE}, | |
| 301 /* -------------------- Diffie Hellman Operations --------------------- */ | |
| 302 /* no diffie hellman yet */ | |
| 303 {CKM_DH_PKCS_KEY_PAIR_GEN, {DH_MIN_P_BITS, DH_MAX_P_BITS, | |
| 304 CKF_GENERATE_KEY_PAIR}, PR_TRUE}, | |
| 305 {CKM_DH_PKCS_DERIVE, {DH_MIN_P_BITS, DH_MAX_P_BITS, | |
| 306 CKF_DERIVE}, PR_TRUE}, | |
| 307 #ifndef NSS_DISABLE_ECC | |
| 308 /* -------------------- Elliptic Curve Operations --------------------- */ | |
| 309 {CKM_EC_KEY_PAIR_GEN, {EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, | |
| 310 CKF_GENERATE_KEY_PAIR|CKF_EC_BPNU}, PR_TRUE}, | |
| 311 {CKM_ECDH1_DERIVE, {EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, | |
| 312 CKF_DERIVE|CKF_EC_BPNU}, PR_TRUE}, | |
| 313 {CKM_ECDSA, {EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, | |
| 314 CKF_SN_VR|CKF_EC_BPNU}, PR_TRUE}, | |
| 315 {CKM_ECDSA_SHA1, {EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, | |
| 316 CKF_SN_VR|CKF_EC_BPNU}, PR_TRUE}, | |
| 317 #endif /* NSS_DISABLE_ECC */ | |
| 318 /* ------------------------- RC2 Operations --------------------------- */ | |
| 319 {CKM_RC2_KEY_GEN, {1, 128, CKF_GENERATE}, PR_TRUE}, | |
| 320 {CKM_RC2_ECB, {1, 128, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 321 {CKM_RC2_CBC, {1, 128, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 322 {CKM_RC2_MAC, {1, 128, CKF_SN_VR}, PR_TRUE}, | |
| 323 {CKM_RC2_MAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, | |
| 324 {CKM_RC2_CBC_PAD, {1, 128, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 325 /* ------------------------- RC4 Operations --------------------------- */ | |
| 326 {CKM_RC4_KEY_GEN, {1, 256, CKF_GENERATE}, PR_FALSE}, | |
| 327 {CKM_RC4, {1, 256, CKF_EN_DE_WR_UN}, PR_FALSE}, | |
| 328 /* ------------------------- DES Operations --------------------------- */ | |
| 329 {CKM_DES_KEY_GEN, { 8, 8, CKF_GENERATE}, PR_TRUE}, | |
| 330 {CKM_DES_ECB, { 8, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 331 {CKM_DES_CBC, { 8, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 332 {CKM_DES_MAC, { 8, 8, CKF_SN_VR}, PR_TRUE}, | |
| 333 {CKM_DES_MAC_GENERAL, { 8, 8, CKF_SN_VR}, PR_TRUE}, | |
| 334 {CKM_DES_CBC_PAD, { 8, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 335 {CKM_DES2_KEY_GEN, {24, 24, CKF_GENERATE}, PR_TRUE}, | |
| 336 {CKM_DES3_KEY_GEN, {24, 24, CKF_GENERATE}, PR_TRUE }, | |
| 337 {CKM_DES3_ECB, {24, 24, CKF_EN_DE_WR_UN}, PR_TRUE }, | |
| 338 {CKM_DES3_CBC, {24, 24, CKF_EN_DE_WR_UN}, PR_TRUE }, | |
| 339 {CKM_DES3_MAC, {24, 24, CKF_SN_VR}, PR_TRUE }, | |
| 340 {CKM_DES3_MAC_GENERAL, {24, 24, CKF_SN_VR}, PR_TRUE }, | |
| 341 {CKM_DES3_CBC_PAD, {24, 24, CKF_EN_DE_WR_UN}, PR_TRUE }, | |
| 342 /* ------------------------- CDMF Operations --------------------------- */ | |
| 343 {CKM_CDMF_KEY_GEN, {8, 8, CKF_GENERATE}, PR_TRUE}, | |
| 344 {CKM_CDMF_ECB, {8, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 345 {CKM_CDMF_CBC, {8, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 346 {CKM_CDMF_MAC, {8, 8, CKF_SN_VR}, PR_TRUE}, | |
| 347 {CKM_CDMF_MAC_GENERAL, {8, 8, CKF_SN_VR}, PR_TRUE}, | |
| 348 {CKM_CDMF_CBC_PAD, {8, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 349 /* ------------------------- AES Operations --------------------------- */ | |
| 350 {CKM_AES_KEY_GEN, {16, 32, CKF_GENERATE}, PR_TRUE}, | |
| 351 {CKM_AES_ECB, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 352 {CKM_AES_CBC, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 353 {CKM_AES_MAC, {16, 32, CKF_SN_VR}, PR_TRUE}, | |
| 354 {CKM_AES_MAC_GENERAL, {16, 32, CKF_SN_VR}, PR_TRUE}, | |
| 355 {CKM_AES_CBC_PAD, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 356 {CKM_AES_CTS, {16, 32, CKF_EN_DE}, PR_TRUE}, | |
| 357 {CKM_AES_CTR, {16, 32, CKF_EN_DE}, PR_TRUE}, | |
| 358 {CKM_AES_GCM, {16, 32, CKF_EN_DE}, PR_TRUE}, | |
| 359 /* ------------------------- Camellia Operations --------------------- */ | |
| 360 {CKM_CAMELLIA_KEY_GEN, {16, 32, CKF_GENERATE}, PR_TRUE}, | |
| 361 {CKM_CAMELLIA_ECB, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 362 {CKM_CAMELLIA_CBC, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 363 {CKM_CAMELLIA_MAC, {16, 32, CKF_SN_VR}, PR_TRUE}, | |
| 364 {CKM_CAMELLIA_MAC_GENERAL, {16, 32, CKF_SN_VR}, PR_TRUE}, | |
| 365 {CKM_CAMELLIA_CBC_PAD, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 366 /* ------------------------- SEED Operations --------------------------- */ | |
| 367 {CKM_SEED_KEY_GEN, {16, 16, CKF_GENERATE}, PR_TRUE}, | |
| 368 {CKM_SEED_ECB, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 369 {CKM_SEED_CBC, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 370 {CKM_SEED_MAC, {16, 16, CKF_SN_VR}, PR_TRUE}, | |
| 371 {CKM_SEED_MAC_GENERAL, {16, 16, CKF_SN_VR}, PR_TRUE}, | |
| 372 {CKM_SEED_CBC_PAD, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 373 #ifndef NSS_DISABLE_CHACHAPOLY | |
| 374 /* ------------------------- ChaCha20 Operations ---------------------- */ | |
| 375 {CKM_NSS_CHACHA20_KEY_GEN, {32, 32, CKF_GENERATE}, PR_TRUE}, | |
| 376 {CKM_NSS_CHACHA20_POLY1305,{32, 32, CKF_EN_DE}, PR_TRUE}, | |
| 377 #endif /* NSS_DISABLE_CHACHAPOLY */ | |
| 378 /* ------------------------- Hashing Operations ----------------------- */ | |
| 379 {CKM_MD2, {0, 0, CKF_DIGEST}, PR_FALSE}, | |
| 380 {CKM_MD2_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE}, | |
| 381 {CKM_MD2_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, | |
| 382 {CKM_MD5, {0, 0, CKF_DIGEST}, PR_FALSE}, | |
| 383 {CKM_MD5_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE}, | |
| 384 {CKM_MD5_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, | |
| 385 {CKM_SHA_1, {0, 0, CKF_DIGEST}, PR_FALSE}, | |
| 386 {CKM_SHA_1_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE}, | |
| 387 {CKM_SHA_1_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, | |
| 388 {CKM_SHA224, {0, 0, CKF_DIGEST}, PR_FALSE}, | |
| 389 {CKM_SHA224_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE}, | |
| 390 {CKM_SHA224_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, | |
| 391 {CKM_SHA256, {0, 0, CKF_DIGEST}, PR_FALSE}, | |
| 392 {CKM_SHA256_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE}, | |
| 393 {CKM_SHA256_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, | |
| 394 {CKM_SHA384, {0, 0, CKF_DIGEST}, PR_FALSE}, | |
| 395 {CKM_SHA384_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE}, | |
| 396 {CKM_SHA384_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, | |
| 397 {CKM_SHA512, {0, 0, CKF_DIGEST}, PR_FALSE}, | |
| 398 {CKM_SHA512_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE}, | |
| 399 {CKM_SHA512_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, | |
| 400 {CKM_TLS_PRF_GENERAL, {0, 512, CKF_SN_VR}, PR_FALSE}, | |
| 401 {CKM_TLS_MAC, {0, 512, CKF_SN_VR}, PR_FALSE}, | |
| 402 {CKM_NSS_TLS_PRF_GENERAL_SHA256, | |
| 403 {0, 512, CKF_SN_VR}, PR_FALSE}, | |
| 404 /* ------------------------- HKDF Operations -------------------------- */ | |
| 405 {CKM_NSS_HKDF_SHA1, {1, 128, CKF_DERIVE}, PR_TRUE}, | |
| 406 {CKM_NSS_HKDF_SHA256, {1, 128, CKF_DERIVE}, PR_TRUE}, | |
| 407 {CKM_NSS_HKDF_SHA384, {1, 128, CKF_DERIVE}, PR_TRUE}, | |
| 408 {CKM_NSS_HKDF_SHA512, {1, 128, CKF_DERIVE}, PR_TRUE}, | |
| 409 /* ------------------------- CAST Operations --------------------------- */ | |
| 410 #ifdef NSS_SOFTOKEN_DOES_CAST | |
| 411 /* Cast operations are not supported ( yet? ) */ | |
| 412 {CKM_CAST_KEY_GEN, {1, 8, CKF_GENERATE}, PR_TRUE}, | |
| 413 {CKM_CAST_ECB, {1, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 414 {CKM_CAST_CBC, {1, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 415 {CKM_CAST_MAC, {1, 8, CKF_SN_VR}, PR_TRUE}, | |
| 416 {CKM_CAST_MAC_GENERAL, {1, 8, CKF_SN_VR}, PR_TRUE}, | |
| 417 {CKM_CAST_CBC_PAD, {1, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 418 {CKM_CAST3_KEY_GEN, {1, 16, CKF_GENERATE}, PR_TRUE}, | |
| 419 {CKM_CAST3_ECB, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 420 {CKM_CAST3_CBC, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 421 {CKM_CAST3_MAC, {1, 16, CKF_SN_VR}, PR_TRUE}, | |
| 422 {CKM_CAST3_MAC_GENERAL, {1, 16, CKF_SN_VR}, PR_TRUE}, | |
| 423 {CKM_CAST3_CBC_PAD, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 424 {CKM_CAST5_KEY_GEN, {1, 16, CKF_GENERATE}, PR_TRUE}, | |
| 425 {CKM_CAST5_ECB, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 426 {CKM_CAST5_CBC, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 427 {CKM_CAST5_MAC, {1, 16, CKF_SN_VR}, PR_TRUE}, | |
| 428 {CKM_CAST5_MAC_GENERAL, {1, 16, CKF_SN_VR}, PR_TRUE}, | |
| 429 {CKM_CAST5_CBC_PAD, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 430 #endif | |
| 431 #if NSS_SOFTOKEN_DOES_RC5 | |
| 432 /* ------------------------- RC5 Operations --------------------------- */ | |
| 433 {CKM_RC5_KEY_GEN, {1, 32, CKF_GENERATE}, PR_TRUE}, | |
| 434 {CKM_RC5_ECB, {1, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 435 {CKM_RC5_CBC, {1, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 436 {CKM_RC5_MAC, {1, 32, CKF_SN_VR}, PR_TRUE}, | |
| 437 {CKM_RC5_MAC_GENERAL, {1, 32, CKF_SN_VR}, PR_TRUE}, | |
| 438 {CKM_RC5_CBC_PAD, {1, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 439 #endif | |
| 440 #ifdef NSS_SOFTOKEN_DOES_IDEA | |
| 441 /* ------------------------- IDEA Operations -------------------------- */ | |
| 442 {CKM_IDEA_KEY_GEN, {16, 16, CKF_GENERATE}, PR_TRUE}, | |
| 443 {CKM_IDEA_ECB, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 444 {CKM_IDEA_CBC, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 445 {CKM_IDEA_MAC, {16, 16, CKF_SN_VR}, PR_TRUE}, | |
| 446 {CKM_IDEA_MAC_GENERAL, {16, 16, CKF_SN_VR}, PR_TRUE}, | |
| 447 {CKM_IDEA_CBC_PAD, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 448 #endif | |
| 449 /* --------------------- Secret Key Operations ------------------------ */ | |
| 450 {CKM_GENERIC_SECRET_KEY_GEN, {1, 32, CKF_GENERATE}, PR_TRUE}, | |
| 451 {CKM_CONCATENATE_BASE_AND_KEY, {1, 32, CKF_GENERATE}, PR_FALSE}, | |
| 452 {CKM_CONCATENATE_BASE_AND_DATA, {1, 32, CKF_GENERATE}, PR_FALSE}, | |
| 453 {CKM_CONCATENATE_DATA_AND_BASE, {1, 32, CKF_GENERATE}, PR_FALSE}, | |
| 454 {CKM_XOR_BASE_AND_DATA, {1, 32, CKF_GENERATE}, PR_FALSE}, | |
| 455 {CKM_EXTRACT_KEY_FROM_KEY, {1, 32, CKF_DERIVE}, PR_FALSE}, | |
| 456 /* ---------------------- SSL Key Derivations ------------------------- */ | |
| 457 {CKM_SSL3_PRE_MASTER_KEY_GEN, {48, 48, CKF_GENERATE}, PR_FALSE}, | |
| 458 {CKM_SSL3_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, | |
| 459 {CKM_SSL3_MASTER_KEY_DERIVE_DH, {8, 128, CKF_DERIVE}, PR_FALSE}, | |
| 460 {CKM_SSL3_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, | |
| 461 {CKM_SSL3_MD5_MAC, { 0, 16, CKF_DERIVE}, PR_FALSE}, | |
| 462 {CKM_SSL3_SHA1_MAC, { 0, 20, CKF_DERIVE}, PR_FALSE}, | |
| 463 {CKM_MD5_KEY_DERIVATION, { 0, 16, CKF_DERIVE}, PR_FALSE}, | |
| 464 {CKM_MD2_KEY_DERIVATION, { 0, 16, CKF_DERIVE}, PR_FALSE}, | |
| 465 {CKM_SHA1_KEY_DERIVATION, { 0, 20, CKF_DERIVE}, PR_FALSE}, | |
| 466 {CKM_SHA224_KEY_DERIVATION, { 0, 28, CKF_DERIVE}, PR_FALSE}, | |
| 467 {CKM_SHA256_KEY_DERIVATION, { 0, 32, CKF_DERIVE}, PR_FALSE}, | |
| 468 {CKM_SHA384_KEY_DERIVATION, { 0, 48, CKF_DERIVE}, PR_FALSE}, | |
| 469 {CKM_SHA512_KEY_DERIVATION, { 0, 64, CKF_DERIVE}, PR_FALSE}, | |
| 470 {CKM_TLS_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, | |
| 471 {CKM_TLS12_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, | |
| 472 {CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256, | |
| 473 {48, 48, CKF_DERIVE}, PR_FALSE}, | |
| 474 {CKM_TLS_MASTER_KEY_DERIVE_DH, {8, 128, CKF_DERIVE}, PR_FALSE}, | |
| 475 {CKM_TLS12_MASTER_KEY_DERIVE_DH, {8, 128, CKF_DERIVE}, PR_FALSE}, | |
| 476 {CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256, | |
| 477 {8, 128, CKF_DERIVE}, PR_FALSE}, | |
| 478 {CKM_TLS_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, | |
| 479 {CKM_TLS12_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, | |
| 480 {CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256, | |
| 481 {48, 48, CKF_DERIVE}, PR_FALSE}, | |
| 482 {CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE, | |
| 483 {48,128, CKF_DERIVE}, PR_FALSE}, | |
| 484 {CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH, | |
| 485 {48,128, CKF_DERIVE}, PR_FALSE}, | |
| 486 /* ---------------------- PBE Key Derivations ------------------------ */ | |
| 487 {CKM_PBE_MD2_DES_CBC, {8, 8, CKF_DERIVE}, PR_TRUE}, | |
| 488 {CKM_PBE_MD5_DES_CBC, {8, 8, CKF_DERIVE}, PR_TRUE}, | |
| 489 /* ------------------ NETSCAPE PBE Key Derivations ------------------- */ | |
| 490 {CKM_NETSCAPE_PBE_SHA1_DES_CBC, { 8, 8, CKF_GENERATE}, PR_TRUE}, | |
| 491 {CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC, {24,24, CKF_GENERATE}, PR_TRUE}, | |
| 492 {CKM_PBE_SHA1_DES3_EDE_CBC, {24,24, CKF_GENERATE}, PR_TRUE}, | |
| 493 {CKM_PBE_SHA1_DES2_EDE_CBC, {24,24, CKF_GENERATE}, PR_TRUE}, | |
| 494 {CKM_PBE_SHA1_RC2_40_CBC, {40,40, CKF_GENERATE}, PR_TRUE}, | |
| 495 {CKM_PBE_SHA1_RC2_128_CBC, {128,128, CKF_GENERATE}, PR_TRUE}, | |
| 496 {CKM_PBE_SHA1_RC4_40, {40,40, CKF_GENERATE}, PR_TRUE}, | |
| 497 {CKM_PBE_SHA1_RC4_128, {128,128, CKF_GENERATE}, PR_TRUE}, | |
| 498 {CKM_PBA_SHA1_WITH_SHA1_HMAC, {20,20, CKF_GENERATE}, PR_TRUE}, | |
| 499 {CKM_PKCS5_PBKD2, {1,256, CKF_GENERATE}, PR_TRUE}, | |
| 500 {CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN, {20,20, CKF_GENERATE}, PR_TRUE}, | |
| 501 {CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN, {16,16, CKF_GENERATE}, PR_TRUE}, | |
| 502 {CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN, {16,16, CKF_GENERATE}, PR_TRUE}, | |
| 503 /* ------------------ AES Key Wrap (also encrypt) ------------------- */ | |
| 504 {CKM_NETSCAPE_AES_KEY_WRAP, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 505 {CKM_NETSCAPE_AES_KEY_WRAP_PAD, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, | |
| 506 /* --------------------------- J-PAKE -------------------------------- */ | |
| 507 {CKM_NSS_JPAKE_ROUND1_SHA1, {0, 0, CKF_GENERATE}, PR_TRUE}, | |
| 508 {CKM_NSS_JPAKE_ROUND1_SHA256, {0, 0, CKF_GENERATE}, PR_TRUE}, | |
| 509 {CKM_NSS_JPAKE_ROUND1_SHA384, {0, 0, CKF_GENERATE}, PR_TRUE}, | |
| 510 {CKM_NSS_JPAKE_ROUND1_SHA512, {0, 0, CKF_GENERATE}, PR_TRUE}, | |
| 511 {CKM_NSS_JPAKE_ROUND2_SHA1, {0, 0, CKF_DERIVE}, PR_TRUE}, | |
| 512 {CKM_NSS_JPAKE_ROUND2_SHA256, {0, 0, CKF_DERIVE}, PR_TRUE}, | |
| 513 {CKM_NSS_JPAKE_ROUND2_SHA384, {0, 0, CKF_DERIVE}, PR_TRUE}, | |
| 514 {CKM_NSS_JPAKE_ROUND2_SHA512, {0, 0, CKF_DERIVE}, PR_TRUE}, | |
| 515 {CKM_NSS_JPAKE_FINAL_SHA1, {0, 0, CKF_DERIVE}, PR_TRUE}, | |
| 516 {CKM_NSS_JPAKE_FINAL_SHA256, {0, 0, CKF_DERIVE}, PR_TRUE}, | |
| 517 {CKM_NSS_JPAKE_FINAL_SHA384, {0, 0, CKF_DERIVE}, PR_TRUE}, | |
| 518 {CKM_NSS_JPAKE_FINAL_SHA512, {0, 0, CKF_DERIVE}, PR_TRUE}, | |
| 519 /* -------------------- Constant Time TLS MACs ----------------------- */ | |
| 520 {CKM_NSS_HMAC_CONSTANT_TIME, {0, 0, CKF_DIGEST}, PR_TRUE}, | |
| 521 {CKM_NSS_SSL3_MAC_CONSTANT_TIME, {0, 0, CKF_DIGEST}, PR_TRUE} | |
| 522 }; | |
| 523 static const CK_ULONG mechanismCount = sizeof(mechanisms)/sizeof(mechanisms[0]); | |
| 524 | |
| 525 /* sigh global so fipstokn can read it */ | |
| 526 PRBool nsc_init = PR_FALSE; | |
| 527 | |
| 528 #if defined(CHECK_FORK_PTHREAD) || defined(CHECK_FORK_MIXED) | |
| 529 | |
| 530 #include <pthread.h> | |
| 531 | |
| 532 static void ForkedChild(void) | |
| 533 { | |
| 534 if (nsc_init || nsf_init) { | |
| 535 forked = PR_TRUE; | |
| 536 } | |
| 537 } | |
| 538 | |
| 539 #endif | |
| 540 | |
| 541 static char * | |
| 542 sftk_setStringName(const char *inString, char *buffer, int buffer_length,
PRBool nullTerminate) | |
| 543 { | |
| 544 int full_length, string_length; | |
| 545 | |
| 546 full_length = nullTerminate ? buffer_length -1 : buffer_length; | |
| 547 string_length = PORT_Strlen(inString); | |
| 548 /* | |
| 549 * shorten the string, respecting utf8 encoding | |
| 550 * to do so, we work backward from the end | |
| 551 * bytes looking from the end are either: | |
| 552 * - ascii [0x00,0x7f] | |
| 553 * - the [2-n]th byte of a multibyte sequence | |
| 554 * [0x3F,0xBF], i.e, most significant 2 bits are '10' | |
| 555 * - the first byte of a multibyte sequence [0xC0,0xFD], | |
| 556 * i.e, most significant 2 bits are '11' | |
| 557 * | |
| 558 * When the string is too long, we lop off any trailing '10' bytes, | |
| 559 * if any. When these are all eliminated we lop off | |
| 560 * one additional byte. Thus if we lopped any '10' | |
| 561 * we'll be lopping a '11' byte (the first byte of the multibyte sequence), | |
| 562 * otherwise we're lopping off an ascii character. | |
| 563 * | |
| 564 * To test for '10' bytes, we first AND it with | |
| 565 * 11000000 (0xc0) so that we get 10000000 (0x80) if and only if | |
| 566 * the byte starts with 10. We test for equality. | |
| 567 */ | |
| 568 while ( string_length > full_length ) { | |
| 569 /* need to shorten */ | |
| 570 while ( string_length > 0 && | |
| 571 ((inString[string_length-1]&(char)0xc0) == (char)0x80)) { | |
| 572 /* lop off '10' byte */ | |
| 573 string_length--; | |
| 574 } | |
| 575 /* | |
| 576 * test string_length in case bad data is received | |
| 577 * and string consisted of all '10' bytes, | |
| 578 * avoiding any infinite loop | |
| 579 */ | |
| 580 if ( string_length ) { | |
| 581 /* remove either '11' byte or an asci byte */ | |
| 582 string_length--; | |
| 583 } | |
| 584 } | |
| 585 PORT_Memset(buffer,' ',full_length); | |
| 586 if (nullTerminate) { | |
| 587 buffer[full_length] = 0; | |
| 588 } | |
| 589 PORT_Memcpy(buffer,inString,string_length); | |
| 590 return buffer; | |
| 591 } | |
| 592 /* | |
| 593 * Configuration utils | |
| 594 */ | |
| 595 static CK_RV | |
| 596 sftk_configure(const char *man, const char *libdes) | |
| 597 { | |
| 598 | |
| 599 /* make sure the internationalization was done correctly... */ | |
| 600 if (man) { | |
| 601 manufacturerID = sftk_setStringName(man,manufacturerID_space, | |
| 602 sizeof(manufacturerID_space), PR_TRUE); | |
| 603 } | |
| 604 if (libdes) { | |
| 605 libraryDescription = sftk_setStringName(libdes, | |
| 606 libraryDescription_space, sizeof(libraryDescription_space), | |
| 607 PR_TRUE); | |
| 608 } | |
| 609 | |
| 610 return CKR_OK; | |
| 611 } | |
| 612 | |
| 613 /* | |
| 614 * ******************** Password Utilities ******************************* | |
| 615 */ | |
| 616 | |
| 617 /* | |
| 618 * see if the key DB password is enabled | |
| 619 */ | |
| 620 static PRBool | |
| 621 sftk_hasNullPassword(SFTKSlot *slot, SFTKDBHandle *keydb) | |
| 622 { | |
| 623 PRBool pwenabled; | |
| 624 | |
| 625 pwenabled = PR_FALSE; | |
| 626 if (sftkdb_HasPasswordSet(keydb) == SECSuccess) { | |
| 627 PRBool tokenRemoved = PR_FALSE; | |
| 628 SECStatus rv = sftkdb_CheckPassword(keydb, "", &tokenRemoved); | |
| 629 if (tokenRemoved) { | |
| 630 sftk_CloseAllSessions(slot, PR_FALSE); | |
| 631 } | |
| 632 return (rv == SECSuccess); | |
| 633 } | |
| 634 | |
| 635 return pwenabled; | |
| 636 } | |
| 637 | |
| 638 /* | |
| 639 * ******************** Object Creation Utilities *************************** | |
| 640 */ | |
| 641 | |
| 642 | |
| 643 /* Make sure a given attribute exists. If it doesn't, initialize it to | |
| 644 * value and len | |
| 645 */ | |
| 646 CK_RV | |
| 647 sftk_defaultAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type, | |
| 648 const void *value, unsigned int len) | |
| 649 { | |
| 650 if ( !sftk_hasAttribute(object, type)) { | |
| 651 return sftk_AddAttributeType(object,type,value,len); | |
| 652 } | |
| 653 return CKR_OK; | |
| 654 } | |
| 655 | |
| 656 /* | |
| 657 * check the consistancy and initialize a Data Object | |
| 658 */ | |
| 659 static CK_RV | |
| 660 sftk_handleDataObject(SFTKSession *session,SFTKObject *object) | |
| 661 { | |
| 662 CK_RV crv; | |
| 663 | |
| 664 /* first reject private and token data objects */ | |
| 665 if (sftk_isTrue(object,CKA_PRIVATE) || sftk_isTrue(object,CKA_TOKEN)) { | |
| 666 return CKR_ATTRIBUTE_VALUE_INVALID; | |
| 667 } | |
| 668 | |
| 669 /* now just verify the required date fields */ | |
| 670 crv = sftk_defaultAttribute(object,CKA_APPLICATION,NULL,0); | |
| 671 if (crv != CKR_OK) return crv; | |
| 672 crv = sftk_defaultAttribute(object,CKA_VALUE,NULL,0); | |
| 673 if (crv != CKR_OK) return crv; | |
| 674 | |
| 675 return CKR_OK; | |
| 676 } | |
| 677 | |
| 678 /* | |
| 679 * check the consistancy and initialize a Certificate Object | |
| 680 */ | |
| 681 static CK_RV | |
| 682 sftk_handleCertObject(SFTKSession *session,SFTKObject *object) | |
| 683 { | |
| 684 CK_CERTIFICATE_TYPE type; | |
| 685 SFTKAttribute *attribute; | |
| 686 CK_RV crv; | |
| 687 | |
| 688 /* certificates must have a type */ | |
| 689 if ( !sftk_hasAttribute(object,CKA_CERTIFICATE_TYPE) ) { | |
| 690 return CKR_TEMPLATE_INCOMPLETE; | |
| 691 } | |
| 692 | |
| 693 /* we can't store any certs private */ | |
| 694 if (sftk_isTrue(object,CKA_PRIVATE)) { | |
| 695 return CKR_ATTRIBUTE_VALUE_INVALID; | |
| 696 } | |
| 697 | |
| 698 /* We only support X.509 Certs for now */ | |
| 699 attribute = sftk_FindAttribute(object,CKA_CERTIFICATE_TYPE); | |
| 700 if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; | |
| 701 type = *(CK_CERTIFICATE_TYPE *)attribute->attrib.pValue; | |
| 702 sftk_FreeAttribute(attribute); | |
| 703 | |
| 704 if (type != CKC_X_509) { | |
| 705 return CKR_ATTRIBUTE_VALUE_INVALID; | |
| 706 } | |
| 707 | |
| 708 /* X.509 Certificate */ | |
| 709 | |
| 710 /* make sure we have a cert */ | |
| 711 if ( !sftk_hasAttribute(object,CKA_VALUE) ) { | |
| 712 return CKR_TEMPLATE_INCOMPLETE; | |
| 713 } | |
| 714 | |
| 715 /* in PKCS #11, Subject is a required field */ | |
| 716 if ( !sftk_hasAttribute(object,CKA_SUBJECT) ) { | |
| 717 return CKR_TEMPLATE_INCOMPLETE; | |
| 718 } | |
| 719 | |
| 720 /* in PKCS #11, Issuer is a required field */ | |
| 721 if ( !sftk_hasAttribute(object,CKA_ISSUER) ) { | |
| 722 return CKR_TEMPLATE_INCOMPLETE; | |
| 723 } | |
| 724 | |
| 725 /* in PKCS #11, Serial is a required field */ | |
| 726 if ( !sftk_hasAttribute(object,CKA_SERIAL_NUMBER) ) { | |
| 727 return CKR_TEMPLATE_INCOMPLETE; | |
| 728 } | |
| 729 | |
| 730 /* add it to the object */ | |
| 731 object->objectInfo = NULL; | |
| 732 object->infoFree = (SFTKFree) NULL; | |
| 733 | |
| 734 /* now just verify the required date fields */ | |
| 735 crv = sftk_defaultAttribute(object, CKA_ID, NULL, 0); | |
| 736 if (crv != CKR_OK) { return crv; } | |
| 737 | |
| 738 if (sftk_isTrue(object,CKA_TOKEN)) { | |
| 739 SFTKSlot *slot = session->slot; | |
| 740 SFTKDBHandle *certHandle = sftk_getCertDB(slot); | |
| 741 | |
| 742 if (certHandle == NULL) { | |
| 743 return CKR_TOKEN_WRITE_PROTECTED; | |
| 744 } | |
| 745 | |
| 746 crv = sftkdb_write(certHandle, object, &object->handle); | |
| 747 sftk_freeDB(certHandle); | |
| 748 return crv; | |
| 749 } | |
| 750 | |
| 751 return CKR_OK; | |
| 752 } | |
| 753 | |
| 754 /* | |
| 755 * check the consistancy and initialize a Trust Object | |
| 756 */ | |
| 757 static CK_RV | |
| 758 sftk_handleTrustObject(SFTKSession *session,SFTKObject *object) | |
| 759 { | |
| 760 /* we can't store any certs private */ | |
| 761 if (sftk_isTrue(object,CKA_PRIVATE)) { | |
| 762 return CKR_ATTRIBUTE_VALUE_INVALID; | |
| 763 } | |
| 764 | |
| 765 /* certificates must have a type */ | |
| 766 if ( !sftk_hasAttribute(object,CKA_ISSUER) ) { | |
| 767 return CKR_TEMPLATE_INCOMPLETE; | |
| 768 } | |
| 769 if ( !sftk_hasAttribute(object,CKA_SERIAL_NUMBER) ) { | |
| 770 return CKR_TEMPLATE_INCOMPLETE; | |
| 771 } | |
| 772 if ( !sftk_hasAttribute(object,CKA_CERT_SHA1_HASH) ) { | |
| 773 return CKR_TEMPLATE_INCOMPLETE; | |
| 774 } | |
| 775 if ( !sftk_hasAttribute(object,CKA_CERT_MD5_HASH) ) { | |
| 776 return CKR_TEMPLATE_INCOMPLETE; | |
| 777 } | |
| 778 | |
| 779 if (sftk_isTrue(object,CKA_TOKEN)) { | |
| 780 SFTKSlot *slot = session->slot; | |
| 781 SFTKDBHandle *certHandle = sftk_getCertDB(slot); | |
| 782 CK_RV crv; | |
| 783 | |
| 784 if (certHandle == NULL) { | |
| 785 return CKR_TOKEN_WRITE_PROTECTED; | |
| 786 } | |
| 787 | |
| 788 crv = sftkdb_write(certHandle, object, &object->handle); | |
| 789 sftk_freeDB(certHandle); | |
| 790 return crv; | |
| 791 } | |
| 792 | |
| 793 return CKR_OK; | |
| 794 } | |
| 795 | |
| 796 /* | |
| 797 * check the consistancy and initialize a Trust Object | |
| 798 */ | |
| 799 static CK_RV | |
| 800 sftk_handleSMimeObject(SFTKSession *session,SFTKObject *object) | |
| 801 { | |
| 802 | |
| 803 /* we can't store any certs private */ | |
| 804 if (sftk_isTrue(object,CKA_PRIVATE)) { | |
| 805 return CKR_ATTRIBUTE_VALUE_INVALID; | |
| 806 } | |
| 807 | |
| 808 /* certificates must have a type */ | |
| 809 if ( !sftk_hasAttribute(object,CKA_SUBJECT) ) { | |
| 810 return CKR_TEMPLATE_INCOMPLETE; | |
| 811 } | |
| 812 if ( !sftk_hasAttribute(object,CKA_NETSCAPE_EMAIL) ) { | |
| 813 return CKR_TEMPLATE_INCOMPLETE; | |
| 814 } | |
| 815 | |
| 816 if (sftk_isTrue(object,CKA_TOKEN)) { | |
| 817 SFTKSlot *slot = session->slot; | |
| 818 SFTKDBHandle *certHandle; | |
| 819 CK_RV crv; | |
| 820 | |
| 821 PORT_Assert(slot); | |
| 822 if (slot == NULL) { | |
| 823 return CKR_SESSION_HANDLE_INVALID; | |
| 824 } | |
| 825 | |
| 826 certHandle = sftk_getCertDB(slot); | |
| 827 if (certHandle == NULL) { | |
| 828 return CKR_TOKEN_WRITE_PROTECTED; | |
| 829 } | |
| 830 | |
| 831 crv = sftkdb_write(certHandle, object, &object->handle); | |
| 832 sftk_freeDB(certHandle); | |
| 833 return crv; | |
| 834 } | |
| 835 | |
| 836 return CKR_OK; | |
| 837 } | |
| 838 | |
| 839 /* | |
| 840 * check the consistancy and initialize a Trust Object | |
| 841 */ | |
| 842 static CK_RV | |
| 843 sftk_handleCrlObject(SFTKSession *session,SFTKObject *object) | |
| 844 { | |
| 845 | |
| 846 /* we can't store any certs private */ | |
| 847 if (sftk_isTrue(object,CKA_PRIVATE)) { | |
| 848 return CKR_ATTRIBUTE_VALUE_INVALID; | |
| 849 } | |
| 850 | |
| 851 /* certificates must have a type */ | |
| 852 if ( !sftk_hasAttribute(object,CKA_SUBJECT) ) { | |
| 853 return CKR_TEMPLATE_INCOMPLETE; | |
| 854 } | |
| 855 if ( !sftk_hasAttribute(object,CKA_VALUE) ) { | |
| 856 return CKR_TEMPLATE_INCOMPLETE; | |
| 857 } | |
| 858 | |
| 859 if (sftk_isTrue(object,CKA_TOKEN)) { | |
| 860 SFTKSlot *slot = session->slot; | |
| 861 SFTKDBHandle *certHandle = sftk_getCertDB(slot); | |
| 862 CK_RV crv; | |
| 863 | |
| 864 if (certHandle == NULL) { | |
| 865 return CKR_TOKEN_WRITE_PROTECTED; | |
| 866 } | |
| 867 | |
| 868 crv = sftkdb_write(certHandle, object, &object->handle); | |
| 869 sftk_freeDB(certHandle); | |
| 870 return crv; | |
| 871 } | |
| 872 | |
| 873 return CKR_OK; | |
| 874 } | |
| 875 | |
| 876 /* | |
| 877 * check the consistancy and initialize a Public Key Object | |
| 878 */ | |
| 879 static CK_RV | |
| 880 sftk_handlePublicKeyObject(SFTKSession *session, SFTKObject *object, | |
| 881 CK_KEY_TYPE key_type) | |
| 882 { | |
| 883 CK_BBOOL encrypt = CK_TRUE; | |
| 884 CK_BBOOL recover = CK_TRUE; | |
| 885 CK_BBOOL wrap = CK_TRUE; | |
| 886 CK_BBOOL derive = CK_FALSE; | |
| 887 CK_BBOOL verify = CK_TRUE; | |
| 888 CK_RV crv; | |
| 889 | |
| 890 switch (key_type) { | |
| 891 case CKK_RSA: | |
| 892 crv = sftk_ConstrainAttribute(object, CKA_MODULUS, | |
| 893 RSA_MIN_MODULUS_BITS, 0, 0); | |
| 894 if (crv != CKR_OK) { | |
| 895 return crv; | |
| 896 } | |
| 897 crv = sftk_ConstrainAttribute(object, CKA_PUBLIC_EXPONENT, 2, 0, 0); | |
| 898 if (crv != CKR_OK) { | |
| 899 return crv; | |
| 900 } | |
| 901 break; | |
| 902 case CKK_DSA: | |
| 903 crv = sftk_ConstrainAttribute(object, CKA_SUBPRIME, | |
| 904 DSA_MIN_Q_BITS, DSA_MAX_Q_BITS, 0); | |
| 905 if (crv != CKR_OK) { | |
| 906 return crv; | |
| 907 } | |
| 908 crv = sftk_ConstrainAttribute(object, CKA_PRIME, | |
| 909 DSA_MIN_P_BITS, DSA_MAX_P_BITS, 64); | |
| 910 if (crv != CKR_OK) { | |
| 911 return crv; | |
| 912 } | |
| 913 crv = sftk_ConstrainAttribute(object, CKA_BASE, 2, DSA_MAX_P_BITS, 0); | |
| 914 if (crv != CKR_OK) { | |
| 915 return crv; | |
| 916 } | |
| 917 crv = sftk_ConstrainAttribute(object, CKA_VALUE, 2, DSA_MAX_P_BITS, 0); | |
| 918 if (crv != CKR_OK) { | |
| 919 return crv; | |
| 920 } | |
| 921 encrypt = CK_FALSE; | |
| 922 recover = CK_FALSE; | |
| 923 wrap = CK_FALSE; | |
| 924 break; | |
| 925 case CKK_DH: | |
| 926 crv = sftk_ConstrainAttribute(object, CKA_PRIME, | |
| 927 DH_MIN_P_BITS, DH_MAX_P_BITS, 0); | |
| 928 if (crv != CKR_OK) { | |
| 929 return crv; | |
| 930 } | |
| 931 crv = sftk_ConstrainAttribute(object, CKA_BASE, 2, DH_MAX_P_BITS, 0); | |
| 932 if (crv != CKR_OK) { | |
| 933 return crv; | |
| 934 } | |
| 935 crv = sftk_ConstrainAttribute(object, CKA_VALUE, 2, DH_MAX_P_BITS, 0); | |
| 936 if (crv != CKR_OK) { | |
| 937 return crv; | |
| 938 } | |
| 939 verify = CK_FALSE; | |
| 940 derive = CK_TRUE; | |
| 941 encrypt = CK_FALSE; | |
| 942 recover = CK_FALSE; | |
| 943 wrap = CK_FALSE; | |
| 944 break; | |
| 945 #ifndef NSS_DISABLE_ECC | |
| 946 case CKK_EC: | |
| 947 if ( !sftk_hasAttribute(object, CKA_EC_PARAMS)) { | |
| 948 return CKR_TEMPLATE_INCOMPLETE; | |
| 949 } | |
| 950 if ( !sftk_hasAttribute(object, CKA_EC_POINT)) { | |
| 951 return CKR_TEMPLATE_INCOMPLETE; | |
| 952 } | |
| 953 derive = CK_TRUE; /* for ECDH */ | |
| 954 verify = CK_TRUE; /* for ECDSA */ | |
| 955 encrypt = CK_FALSE; | |
| 956 recover = CK_FALSE; | |
| 957 wrap = CK_FALSE; | |
| 958 break; | |
| 959 #endif /* NSS_DISABLE_ECC */ | |
| 960 default: | |
| 961 return CKR_ATTRIBUTE_VALUE_INVALID; | |
| 962 } | |
| 963 | |
| 964 /* make sure the required fields exist */ | |
| 965 crv = sftk_defaultAttribute(object,CKA_SUBJECT,NULL,0); | |
| 966 if (crv != CKR_OK) return crv; | |
| 967 crv = sftk_defaultAttribute(object,CKA_ENCRYPT,&encrypt,sizeof(CK_BBOOL)); | |
| 968 if (crv != CKR_OK) return crv; | |
| 969 crv = sftk_defaultAttribute(object,CKA_VERIFY,&verify,sizeof(CK_BBOOL)); | |
| 970 if (crv != CKR_OK) return crv; | |
| 971 crv = sftk_defaultAttribute(object,CKA_VERIFY_RECOVER, | |
| 972 &recover,sizeof(CK_BBOOL)); | |
| 973 if (crv != CKR_OK) return crv; | |
| 974 crv = sftk_defaultAttribute(object,CKA_WRAP,&wrap,sizeof(CK_BBOOL)); | |
| 975 if (crv != CKR_OK) return crv; | |
| 976 crv = sftk_defaultAttribute(object,CKA_DERIVE,&derive,sizeof(CK_BBOOL)); | |
| 977 if (crv != CKR_OK) return crv; | |
| 978 | |
| 979 object->objectInfo = sftk_GetPubKey(object,key_type, &crv); | |
| 980 if (object->objectInfo == NULL) { | |
| 981 return crv; | |
| 982 } | |
| 983 object->infoFree = (SFTKFree) nsslowkey_DestroyPublicKey; | |
| 984 | |
| 985 /* Check that an imported EC key is valid */ | |
| 986 if (key_type == CKK_EC) { | |
| 987 NSSLOWKEYPublicKey *pubKey = (NSSLOWKEYPublicKey*) object->objectInfo; | |
| 988 SECStatus rv = EC_ValidatePublicKey(&pubKey->u.ec.ecParams, | |
| 989 &pubKey->u.ec.publicValue); | |
| 990 | |
| 991 if (rv != SECSuccess) { | |
| 992 return CKR_TEMPLATE_INCONSISTENT; | |
| 993 } | |
| 994 } | |
| 995 | |
| 996 if (sftk_isTrue(object,CKA_TOKEN)) { | |
| 997 SFTKSlot *slot = session->slot; | |
| 998 SFTKDBHandle *certHandle = sftk_getCertDB(slot); | |
| 999 | |
| 1000 if (certHandle == NULL) { | |
| 1001 return CKR_TOKEN_WRITE_PROTECTED; | |
| 1002 } | |
| 1003 | |
| 1004 crv = sftkdb_write(certHandle, object, &object->handle); | |
| 1005 sftk_freeDB(certHandle); | |
| 1006 return crv; | |
| 1007 } | |
| 1008 | |
| 1009 return CKR_OK; | |
| 1010 } | |
| 1011 | |
| 1012 static NSSLOWKEYPrivateKey * | |
| 1013 sftk_mkPrivKey(SFTKObject *object,CK_KEY_TYPE key, CK_RV *rvp); | |
| 1014 | |
| 1015 static SECStatus | |
| 1016 sftk_verifyRSAPrivateKey(SFTKObject *object, PRBool fillIfNeeded); | |
| 1017 | |
| 1018 /* | |
| 1019 * check the consistancy and initialize a Private Key Object | |
| 1020 */ | |
| 1021 static CK_RV | |
| 1022 sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE
key_type) | |
| 1023 { | |
| 1024 CK_BBOOL cktrue = CK_TRUE; | |
| 1025 CK_BBOOL encrypt = CK_TRUE; | |
| 1026 CK_BBOOL sign = CK_FALSE; | |
| 1027 CK_BBOOL recover = CK_TRUE; | |
| 1028 CK_BBOOL wrap = CK_TRUE; | |
| 1029 CK_BBOOL derive = CK_TRUE; | |
| 1030 CK_BBOOL ckfalse = CK_FALSE; | |
| 1031 PRBool createObjectInfo = PR_TRUE; | |
| 1032 PRBool fillPrivateKey = PR_FALSE; | |
| 1033 int missing_rsa_mod_component = 0; | |
| 1034 int missing_rsa_exp_component = 0; | |
| 1035 int missing_rsa_crt_component = 0; | |
| 1036 | |
| 1037 SECItem mod; | |
| 1038 CK_RV crv; | |
| 1039 SECStatus rv; | |
| 1040 | |
| 1041 switch (key_type) { | |
| 1042 case CKK_RSA: | |
| 1043 if ( !sftk_hasAttribute(object, CKA_MODULUS)) { | |
| 1044 missing_rsa_mod_component++; | |
| 1045 } | |
| 1046 if ( !sftk_hasAttribute(object, CKA_PUBLIC_EXPONENT)) { | |
| 1047 missing_rsa_exp_component++; | |
| 1048 } | |
| 1049 if ( !sftk_hasAttribute(object, CKA_PRIVATE_EXPONENT)) { | |
| 1050 missing_rsa_exp_component++; | |
| 1051 } | |
| 1052 if ( !sftk_hasAttribute(object, CKA_PRIME_1)) { | |
| 1053 missing_rsa_mod_component++; | |
| 1054 } | |
| 1055 if ( !sftk_hasAttribute(object, CKA_PRIME_2)) { | |
| 1056 missing_rsa_mod_component++; | |
| 1057 } | |
| 1058 if ( !sftk_hasAttribute(object, CKA_EXPONENT_1)) { | |
| 1059 missing_rsa_crt_component++; | |
| 1060 } | |
| 1061 if ( !sftk_hasAttribute(object, CKA_EXPONENT_2)) { | |
| 1062 missing_rsa_crt_component++; | |
| 1063 } | |
| 1064 if ( !sftk_hasAttribute(object, CKA_COEFFICIENT)) { | |
| 1065 missing_rsa_crt_component++; | |
| 1066 } | |
| 1067 if (missing_rsa_mod_component || missing_rsa_exp_component || | |
| 1068 missing_rsa_crt_component) { | |
| 1069 /* we are missing a component, see if we have enough to rebuild | |
| 1070 * the rest */ | |
| 1071 int have_exp = 2- missing_rsa_exp_component; | |
| 1072 int have_component = 5- | |
| 1073 (missing_rsa_exp_component+missing_rsa_mod_component); | |
| 1074 | |
| 1075 if ((have_exp == 0) || (have_component < 3)) { | |
| 1076 /* nope, not enough to reconstruct the private key */ | |
| 1077 return CKR_TEMPLATE_INCOMPLETE; | |
| 1078 } | |
| 1079 fillPrivateKey = PR_TRUE; | |
| 1080 } | |
| 1081 /*verify the parameters for consistency*/ | |
| 1082 rv = sftk_verifyRSAPrivateKey(object, fillPrivateKey); | |
| 1083 if (rv != SECSuccess) { | |
| 1084 return CKR_TEMPLATE_INCOMPLETE; | |
| 1085 } | |
| 1086 | |
| 1087 /* make sure Netscape DB attribute is set correctly */ | |
| 1088 crv = sftk_Attribute2SSecItem(NULL, &mod, object, CKA_MODULUS); | |
| 1089 if (crv != CKR_OK) return crv; | |
| 1090 crv = sftk_forceAttribute(object, CKA_NETSCAPE_DB, | |
| 1091 sftk_item_expand(&mod)); | |
| 1092 if (mod.data) PORT_Free(mod.data); | |
| 1093 if (crv != CKR_OK) return crv; | |
| 1094 | |
| 1095 sign = CK_TRUE; | |
| 1096 derive = CK_FALSE; | |
| 1097 break; | |
| 1098 case CKK_DSA: | |
| 1099 if ( !sftk_hasAttribute(object, CKA_SUBPRIME)) { | |
| 1100 return CKR_TEMPLATE_INCOMPLETE; | |
| 1101 } | |
| 1102 sign = CK_TRUE; | |
| 1103 derive = CK_FALSE; | |
| 1104 /* fall through */ | |
| 1105 case CKK_DH: | |
| 1106 if ( !sftk_hasAttribute(object, CKA_PRIME)) { | |
| 1107 return CKR_TEMPLATE_INCOMPLETE; | |
| 1108 } | |
| 1109 if ( !sftk_hasAttribute(object, CKA_BASE)) { | |
| 1110 return CKR_TEMPLATE_INCOMPLETE; | |
| 1111 } | |
| 1112 if ( !sftk_hasAttribute(object, CKA_VALUE)) { | |
| 1113 return CKR_TEMPLATE_INCOMPLETE; | |
| 1114 } | |
| 1115 encrypt = CK_FALSE; | |
| 1116 recover = CK_FALSE; | |
| 1117 wrap = CK_FALSE; | |
| 1118 break; | |
| 1119 #ifndef NSS_DISABLE_ECC | |
| 1120 case CKK_EC: | |
| 1121 if ( !sftk_hasAttribute(object, CKA_EC_PARAMS)) { | |
| 1122 return CKR_TEMPLATE_INCOMPLETE; | |
| 1123 } | |
| 1124 if ( !sftk_hasAttribute(object, CKA_VALUE)) { | |
| 1125 return CKR_TEMPLATE_INCOMPLETE; | |
| 1126 } | |
| 1127 encrypt = CK_FALSE; | |
| 1128 sign = CK_TRUE; | |
| 1129 recover = CK_FALSE; | |
| 1130 wrap = CK_FALSE; | |
| 1131 break; | |
| 1132 #endif /* NSS_DISABLE_ECC */ | |
| 1133 case CKK_NSS_JPAKE_ROUND1: | |
| 1134 if (!sftk_hasAttribute(object, CKA_PRIME) || | |
| 1135 !sftk_hasAttribute(object, CKA_SUBPRIME) || | |
| 1136 !sftk_hasAttribute(object, CKA_BASE)) { | |
| 1137 return CKR_TEMPLATE_INCOMPLETE; | |
| 1138 } | |
| 1139 /* fall through */ | |
| 1140 case CKK_NSS_JPAKE_ROUND2: | |
| 1141 /* CKA_NSS_JPAKE_SIGNERID and CKA_NSS_JPAKE_PEERID are checked in | |
| 1142 the J-PAKE code. */ | |
| 1143 encrypt = sign = recover = wrap = CK_FALSE; | |
| 1144 derive = CK_TRUE; | |
| 1145 createObjectInfo = PR_FALSE; | |
| 1146 break; | |
| 1147 default: | |
| 1148 return CKR_ATTRIBUTE_VALUE_INVALID; | |
| 1149 } | |
| 1150 crv = sftk_defaultAttribute(object,CKA_SUBJECT,NULL,0); | |
| 1151 if (crv != CKR_OK) return crv; | |
| 1152 crv = sftk_defaultAttribute(object,CKA_SENSITIVE,&cktrue,sizeof(CK_BBOOL)); | |
| 1153 if (crv != CKR_OK) return crv; | |
| 1154 crv = sftk_defaultAttribute(object,CKA_EXTRACTABLE,&cktrue,sizeof(CK_BBOOL))
; | |
| 1155 if (crv != CKR_OK) return crv; | |
| 1156 crv = sftk_defaultAttribute(object,CKA_DECRYPT,&encrypt,sizeof(CK_BBOOL)); | |
| 1157 if (crv != CKR_OK) return crv; | |
| 1158 crv = sftk_defaultAttribute(object,CKA_SIGN,&sign,sizeof(CK_BBOOL)); | |
| 1159 if (crv != CKR_OK) return crv; | |
| 1160 crv = sftk_defaultAttribute(object,CKA_SIGN_RECOVER,&recover, | |
| 1161 sizeof(CK_BBOOL)); | |
| 1162 if (crv != CKR_OK) return crv; | |
| 1163 crv = sftk_defaultAttribute(object,CKA_UNWRAP,&wrap,sizeof(CK_BBOOL)); | |
| 1164 if (crv != CKR_OK) return crv; | |
| 1165 crv = sftk_defaultAttribute(object,CKA_DERIVE,&derive,sizeof(CK_BBOOL)); | |
| 1166 if (crv != CKR_OK) return crv; | |
| 1167 /* the next two bits get modified only in the key gen and token cases */ | |
| 1168 crv = sftk_forceAttribute(object,CKA_ALWAYS_SENSITIVE, | |
| 1169 &ckfalse,sizeof(CK_BBOOL)); | |
| 1170 if (crv != CKR_OK) return crv; | |
| 1171 crv = sftk_forceAttribute(object,CKA_NEVER_EXTRACTABLE, | |
| 1172 &ckfalse,sizeof(CK_BBOOL)); | |
| 1173 if (crv != CKR_OK) return crv; | |
| 1174 | |
| 1175 /* should we check the non-token RSA private keys? */ | |
| 1176 | |
| 1177 if (sftk_isTrue(object,CKA_TOKEN)) { | |
| 1178 SFTKSlot *slot = session->slot; | |
| 1179 SFTKDBHandle *keyHandle = sftk_getKeyDB(slot); | |
| 1180 | |
| 1181 if (keyHandle == NULL) { | |
| 1182 return CKR_TOKEN_WRITE_PROTECTED; | |
| 1183 } | |
| 1184 | |
| 1185 crv = sftkdb_write(keyHandle, object, &object->handle); | |
| 1186 sftk_freeDB(keyHandle); | |
| 1187 return crv; | |
| 1188 } else if (createObjectInfo) { | |
| 1189 object->objectInfo = sftk_mkPrivKey(object,key_type,&crv); | |
| 1190 if (object->objectInfo == NULL) return crv; | |
| 1191 object->infoFree = (SFTKFree) nsslowkey_DestroyPrivateKey; | |
| 1192 } | |
| 1193 return CKR_OK; | |
| 1194 } | |
| 1195 | |
| 1196 /* forward declare the DES formating function for handleSecretKey */ | |
| 1197 void sftk_FormatDESKey(unsigned char *key, int length); | |
| 1198 | |
| 1199 /* Validate secret key data, and set defaults */ | |
| 1200 static CK_RV | |
| 1201 validateSecretKey(SFTKSession *session, SFTKObject *object, | |
| 1202 CK_KEY_TYPE key_type, PRBool isFIPS) | |
| 1203 { | |
| 1204 CK_RV crv; | |
| 1205 CK_BBOOL cktrue = CK_TRUE; | |
| 1206 CK_BBOOL ckfalse = CK_FALSE; | |
| 1207 SFTKAttribute *attribute = NULL; | |
| 1208 unsigned long requiredLen; | |
| 1209 | |
| 1210 crv = sftk_defaultAttribute(object,CKA_SENSITIVE, | |
| 1211 isFIPS?&cktrue:&ckfalse,sizeof(CK_BBOOL)); | |
| 1212 if (crv != CKR_OK) return crv; | |
| 1213 crv = sftk_defaultAttribute(object,CKA_EXTRACTABLE, | |
| 1214 &cktrue,sizeof(CK_BBOOL)); | |
| 1215 if (crv != CKR_OK) return crv; | |
| 1216 crv = sftk_defaultAttribute(object,CKA_ENCRYPT,&cktrue,sizeof(CK_BBOOL)); | |
| 1217 if (crv != CKR_OK) return crv; | |
| 1218 crv = sftk_defaultAttribute(object,CKA_DECRYPT,&cktrue,sizeof(CK_BBOOL)); | |
| 1219 if (crv != CKR_OK) return crv; | |
| 1220 crv = sftk_defaultAttribute(object,CKA_SIGN,&ckfalse,sizeof(CK_BBOOL)); | |
| 1221 if (crv != CKR_OK) return crv; | |
| 1222 crv = sftk_defaultAttribute(object,CKA_VERIFY,&ckfalse,sizeof(CK_BBOOL)); | |
| 1223 if (crv != CKR_OK) return crv; | |
| 1224 crv = sftk_defaultAttribute(object,CKA_WRAP,&cktrue,sizeof(CK_BBOOL)); | |
| 1225 if (crv != CKR_OK) return crv; | |
| 1226 crv = sftk_defaultAttribute(object,CKA_UNWRAP,&cktrue,sizeof(CK_BBOOL)); | |
| 1227 if (crv != CKR_OK) return crv; | |
| 1228 | |
| 1229 if ( !sftk_hasAttribute(object, CKA_VALUE)) { | |
| 1230 return CKR_TEMPLATE_INCOMPLETE; | |
| 1231 } | |
| 1232 /* the next two bits get modified only in the key gen and token cases */ | |
| 1233 crv = sftk_forceAttribute(object,CKA_ALWAYS_SENSITIVE, | |
| 1234 &ckfalse,sizeof(CK_BBOOL)); | |
| 1235 if (crv != CKR_OK) return crv; | |
| 1236 crv = sftk_forceAttribute(object,CKA_NEVER_EXTRACTABLE, | |
| 1237 &ckfalse,sizeof(CK_BBOOL)); | |
| 1238 if (crv != CKR_OK) return crv; | |
| 1239 | |
| 1240 /* some types of keys have a value length */ | |
| 1241 crv = CKR_OK; | |
| 1242 switch (key_type) { | |
| 1243 /* force CKA_VALUE_LEN to be set */ | |
| 1244 case CKK_GENERIC_SECRET: | |
| 1245 case CKK_RC2: | |
| 1246 case CKK_RC4: | |
| 1247 #if NSS_SOFTOKEN_DOES_RC5 | |
| 1248 case CKK_RC5: | |
| 1249 #endif | |
| 1250 #ifdef NSS_SOFTOKEN_DOES_CAST | |
| 1251 case CKK_CAST: | |
| 1252 case CKK_CAST3: | |
| 1253 case CKK_CAST5: | |
| 1254 #endif | |
| 1255 #if NSS_SOFTOKEN_DOES_IDEA | |
| 1256 case CKK_IDEA: | |
| 1257 #endif | |
| 1258 attribute = sftk_FindAttribute(object,CKA_VALUE); | |
| 1259 /* shouldn't happen */ | |
| 1260 if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; | |
| 1261 crv = sftk_forceAttribute(object, CKA_VALUE_LEN, | |
| 1262 &attribute->attrib.ulValueLen, sizeof(CK_ULONG)); | |
| 1263 sftk_FreeAttribute(attribute); | |
| 1264 break; | |
| 1265 /* force the value to have the correct parity */ | |
| 1266 case CKK_DES: | |
| 1267 case CKK_DES2: | |
| 1268 case CKK_DES3: | |
| 1269 case CKK_CDMF: | |
| 1270 attribute = sftk_FindAttribute(object,CKA_VALUE); | |
| 1271 /* shouldn't happen */ | |
| 1272 if (attribute == NULL) | |
| 1273 return CKR_TEMPLATE_INCOMPLETE; | |
| 1274 requiredLen = sftk_MapKeySize(key_type); | |
| 1275 if (attribute->attrib.ulValueLen != requiredLen) { | |
| 1276 sftk_FreeAttribute(attribute); | |
| 1277 return CKR_KEY_SIZE_RANGE; | |
| 1278 } | |
| 1279 sftk_FormatDESKey((unsigned char*)attribute->attrib.pValue, | |
| 1280 attribute->attrib.ulValueLen); | |
| 1281 sftk_FreeAttribute(attribute); | |
| 1282 break; | |
| 1283 case CKK_AES: | |
| 1284 attribute = sftk_FindAttribute(object,CKA_VALUE); | |
| 1285 /* shouldn't happen */ | |
| 1286 if (attribute == NULL) | |
| 1287 return CKR_TEMPLATE_INCOMPLETE; | |
| 1288 if (attribute->attrib.ulValueLen != 16 && | |
| 1289 attribute->attrib.ulValueLen != 24 && | |
| 1290 attribute->attrib.ulValueLen != 32) { | |
| 1291 sftk_FreeAttribute(attribute); | |
| 1292 return CKR_KEY_SIZE_RANGE; | |
| 1293 } | |
| 1294 crv = sftk_forceAttribute(object, CKA_VALUE_LEN, | |
| 1295 &attribute->attrib.ulValueLen, sizeof(CK_ULONG)); | |
| 1296 sftk_FreeAttribute(attribute); | |
| 1297 break; | |
| 1298 default: | |
| 1299 break; | |
| 1300 } | |
| 1301 | |
| 1302 return crv; | |
| 1303 } | |
| 1304 | |
| 1305 /* | |
| 1306 * check the consistancy and initialize a Secret Key Object | |
| 1307 */ | |
| 1308 static CK_RV | |
| 1309 sftk_handleSecretKeyObject(SFTKSession *session,SFTKObject *object, | |
| 1310 CK_KEY_TYPE key_type, PRBool isFIPS) | |
| 1311 { | |
| 1312 CK_RV crv; | |
| 1313 | |
| 1314 /* First validate and set defaults */ | |
| 1315 crv = validateSecretKey(session, object, key_type, isFIPS); | |
| 1316 if (crv != CKR_OK) goto loser; | |
| 1317 | |
| 1318 /* If the object is a TOKEN object, store in the database */ | |
| 1319 if (sftk_isTrue(object,CKA_TOKEN)) { | |
| 1320 SFTKSlot *slot = session->slot; | |
| 1321 SFTKDBHandle *keyHandle = sftk_getKeyDB(slot); | |
| 1322 CK_RV crv; | |
| 1323 | |
| 1324 if (keyHandle == NULL) { | |
| 1325 return CKR_TOKEN_WRITE_PROTECTED; | |
| 1326 } | |
| 1327 | |
| 1328 crv = sftkdb_write(keyHandle, object, &object->handle); | |
| 1329 sftk_freeDB(keyHandle); | |
| 1330 return crv; | |
| 1331 } | |
| 1332 | |
| 1333 loser: | |
| 1334 | |
| 1335 return crv; | |
| 1336 } | |
| 1337 | |
| 1338 /* | |
| 1339 * check the consistancy and initialize a Key Object | |
| 1340 */ | |
| 1341 static CK_RV | |
| 1342 sftk_handleKeyObject(SFTKSession *session, SFTKObject *object) | |
| 1343 { | |
| 1344 SFTKAttribute *attribute; | |
| 1345 CK_KEY_TYPE key_type; | |
| 1346 CK_BBOOL ckfalse = CK_FALSE; | |
| 1347 CK_RV crv; | |
| 1348 | |
| 1349 /* verify the required fields */ | |
| 1350 if ( !sftk_hasAttribute(object,CKA_KEY_TYPE) ) { | |
| 1351 return CKR_TEMPLATE_INCOMPLETE; | |
| 1352 } | |
| 1353 | |
| 1354 /* now verify the common fields */ | |
| 1355 crv = sftk_defaultAttribute(object,CKA_ID,NULL,0); | |
| 1356 if (crv != CKR_OK) return crv; | |
| 1357 crv = sftk_defaultAttribute(object,CKA_START_DATE,NULL,0); | |
| 1358 if (crv != CKR_OK) return crv; | |
| 1359 crv = sftk_defaultAttribute(object,CKA_END_DATE,NULL,0); | |
| 1360 if (crv != CKR_OK) return crv; | |
| 1361 /* CKA_DERIVE is common to all keys, but it's default value is | |
| 1362 * key dependent */ | |
| 1363 crv = sftk_defaultAttribute(object,CKA_LOCAL,&ckfalse,sizeof(CK_BBOOL)); | |
| 1364 if (crv != CKR_OK) return crv; | |
| 1365 | |
| 1366 /* get the key type */ | |
| 1367 attribute = sftk_FindAttribute(object,CKA_KEY_TYPE); | |
| 1368 if (!attribute) { | |
| 1369 return CKR_ATTRIBUTE_VALUE_INVALID; | |
| 1370 } | |
| 1371 key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue; | |
| 1372 sftk_FreeAttribute(attribute); | |
| 1373 | |
| 1374 switch (object->objclass) { | |
| 1375 case CKO_PUBLIC_KEY: | |
| 1376 return sftk_handlePublicKeyObject(session,object,key_type); | |
| 1377 case CKO_PRIVATE_KEY: | |
| 1378 return sftk_handlePrivateKeyObject(session,object,key_type); | |
| 1379 case CKO_SECRET_KEY: | |
| 1380 /* make sure the required fields exist */ | |
| 1381 return sftk_handleSecretKeyObject(session,object,key_type, | |
| 1382 (PRBool)(session->slot->slotID == FIPS_SLOT_ID)); | |
| 1383 default: | |
| 1384 break; | |
| 1385 } | |
| 1386 return CKR_ATTRIBUTE_VALUE_INVALID; | |
| 1387 } | |
| 1388 | |
| 1389 /* | |
| 1390 * check the consistancy and Verify a DSA Parameter Object | |
| 1391 */ | |
| 1392 static CK_RV | |
| 1393 sftk_handleDSAParameterObject(SFTKSession *session, SFTKObject *object) | |
| 1394 { | |
| 1395 SFTKAttribute *primeAttr = NULL; | |
| 1396 SFTKAttribute *subPrimeAttr = NULL; | |
| 1397 SFTKAttribute *baseAttr = NULL; | |
| 1398 SFTKAttribute *seedAttr = NULL; | |
| 1399 SFTKAttribute *hAttr = NULL; | |
| 1400 SFTKAttribute *attribute; | |
| 1401 CK_RV crv = CKR_TEMPLATE_INCOMPLETE; | |
| 1402 PQGParams params; | |
| 1403 PQGVerify vfy, *verify = NULL; | |
| 1404 SECStatus result,rv; | |
| 1405 /* This bool keeps track of whether or not we need verify parameters. | |
| 1406 * If a P, Q and G or supplied, we dont' need verify parameters, as we | |
| 1407 * have PQ and G. | |
| 1408 * - If G is not supplied, the presumption is that we want to | |
| 1409 * verify P and Q only. | |
| 1410 * - If counter is supplied, it is presumed we want to verify PQ because | |
| 1411 * the counter is only used in verification. | |
| 1412 * - If H is supplied, is is presumed we want to verify G because H is | |
| 1413 * only used to verify G. | |
| 1414 * - Any verification step must have the SEED (counter or H could be | |
| 1415 * missing depending on exactly what we want to verify). If SEED is supplied
, | |
| 1416 * the code just goes ahead and runs verify (other errors are parameter | |
| 1417 * errors are detected by the PQG_VerifyParams function). If SEED is not | |
| 1418 * supplied, but we determined that we are trying to verify (because needVfy | |
| 1419 * is set, go ahead and return CKR_TEMPLATE_INCOMPLETE. | |
| 1420 */ | |
| 1421 PRBool needVfy = PR_FALSE; | |
| 1422 | |
| 1423 primeAttr = sftk_FindAttribute(object,CKA_PRIME); | |
| 1424 if (primeAttr == NULL) goto loser; | |
| 1425 params.prime.data = primeAttr->attrib.pValue; | |
| 1426 params.prime.len = primeAttr->attrib.ulValueLen; | |
| 1427 | |
| 1428 subPrimeAttr = sftk_FindAttribute(object,CKA_SUBPRIME); | |
| 1429 if (subPrimeAttr == NULL) goto loser; | |
| 1430 params.subPrime.data = subPrimeAttr->attrib.pValue; | |
| 1431 params.subPrime.len = subPrimeAttr->attrib.ulValueLen; | |
| 1432 | |
| 1433 baseAttr = sftk_FindAttribute(object,CKA_BASE); | |
| 1434 if (baseAttr != NULL) { | |
| 1435 params.base.data = baseAttr->attrib.pValue; | |
| 1436 params.base.len = baseAttr->attrib.ulValueLen; | |
| 1437 } else { | |
| 1438 params.base.data = NULL; | |
| 1439 params.base.len = 0; | |
| 1440 needVfy = PR_TRUE; /* presumably only including PQ so we can verify | |
| 1441 * them. */ | |
| 1442 } | |
| 1443 | |
| 1444 attribute = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_COUNTER); | |
| 1445 if (attribute != NULL) { | |
| 1446 vfy.counter = *(CK_ULONG *) attribute->attrib.pValue; | |
| 1447 sftk_FreeAttribute(attribute); | |
| 1448 needVfy = PR_TRUE; /* included a count so we can verify PQ */ | |
| 1449 } else { | |
| 1450 vfy.counter = -1; | |
| 1451 } | |
| 1452 | |
| 1453 hAttr = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_H); | |
| 1454 if (hAttr != NULL) { | |
| 1455 vfy.h.data = hAttr->attrib.pValue; | |
| 1456 vfy.h.len = hAttr->attrib.ulValueLen; | |
| 1457 needVfy = PR_TRUE; /* included H so we can verify G */ | |
| 1458 } else { | |
| 1459 vfy.h.data = NULL; | |
| 1460 vfy.h.len = 0; | |
| 1461 } | |
| 1462 seedAttr = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_SEED); | |
| 1463 if (seedAttr != NULL) { | |
| 1464 vfy.seed.data = seedAttr->attrib.pValue; | |
| 1465 vfy.seed.len = seedAttr->attrib.ulValueLen; | |
| 1466 | |
| 1467 verify = &vfy; | |
| 1468 } else if (needVfy) { | |
| 1469 goto loser; /* Verify always needs seed, if we need verify and not seed | |
| 1470 * then fail */ | |
| 1471 } | |
| 1472 | |
| 1473 crv = CKR_FUNCTION_FAILED; | |
| 1474 rv = PQG_VerifyParams(¶ms,verify,&result); | |
| 1475 if (rv == SECSuccess) { | |
| 1476 crv = (result== SECSuccess) ? CKR_OK : CKR_ATTRIBUTE_VALUE_INVALID; | |
| 1477 } | |
| 1478 | |
| 1479 loser: | |
| 1480 if (hAttr) sftk_FreeAttribute(hAttr); | |
| 1481 if (seedAttr) sftk_FreeAttribute(seedAttr); | |
| 1482 if (baseAttr) sftk_FreeAttribute(baseAttr); | |
| 1483 if (subPrimeAttr) sftk_FreeAttribute(subPrimeAttr); | |
| 1484 if (primeAttr) sftk_FreeAttribute(primeAttr); | |
| 1485 | |
| 1486 return crv; | |
| 1487 } | |
| 1488 | |
| 1489 /* | |
| 1490 * check the consistancy and initialize a Key Parameter Object | |
| 1491 */ | |
| 1492 static CK_RV | |
| 1493 sftk_handleKeyParameterObject(SFTKSession *session, SFTKObject *object) | |
| 1494 { | |
| 1495 SFTKAttribute *attribute; | |
| 1496 CK_KEY_TYPE key_type; | |
| 1497 CK_BBOOL ckfalse = CK_FALSE; | |
| 1498 CK_RV crv; | |
| 1499 | |
| 1500 /* verify the required fields */ | |
| 1501 if ( !sftk_hasAttribute(object,CKA_KEY_TYPE) ) { | |
| 1502 return CKR_TEMPLATE_INCOMPLETE; | |
| 1503 } | |
| 1504 | |
| 1505 /* now verify the common fields */ | |
| 1506 crv = sftk_defaultAttribute(object,CKA_LOCAL,&ckfalse,sizeof(CK_BBOOL)); | |
| 1507 if (crv != CKR_OK) return crv; | |
| 1508 | |
| 1509 /* get the key type */ | |
| 1510 attribute = sftk_FindAttribute(object,CKA_KEY_TYPE); | |
| 1511 if (!attribute) { | |
| 1512 return CKR_ATTRIBUTE_VALUE_INVALID; | |
| 1513 } | |
| 1514 key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue; | |
| 1515 sftk_FreeAttribute(attribute); | |
| 1516 | |
| 1517 switch (key_type) { | |
| 1518 case CKK_DSA: | |
| 1519 return sftk_handleDSAParameterObject(session,object); | |
| 1520 | |
| 1521 default: | |
| 1522 break; | |
| 1523 } | |
| 1524 return CKR_KEY_TYPE_INCONSISTENT; | |
| 1525 } | |
| 1526 | |
| 1527 /* | |
| 1528 * Handle Object does all the object consistancy checks, automatic attribute | |
| 1529 * generation, attribute defaulting, etc. If handleObject succeeds, the object | |
| 1530 * will be assigned an object handle, and the object installed in the session | |
| 1531 * or stored in the DB. | |
| 1532 */ | |
| 1533 CK_RV | |
| 1534 sftk_handleObject(SFTKObject *object, SFTKSession *session) | |
| 1535 { | |
| 1536 SFTKSlot *slot = session->slot; | |
| 1537 SFTKAttribute *attribute; | |
| 1538 SFTKObject *duplicateObject = NULL; | |
| 1539 CK_OBJECT_HANDLE handle; | |
| 1540 CK_BBOOL ckfalse = CK_FALSE; | |
| 1541 CK_BBOOL cktrue = CK_TRUE; | |
| 1542 CK_RV crv; | |
| 1543 | |
| 1544 /* make sure all the base object types are defined. If not set the | |
| 1545 * defaults */ | |
| 1546 crv = sftk_defaultAttribute(object,CKA_TOKEN,&ckfalse,sizeof(CK_BBOOL)); | |
| 1547 if (crv != CKR_OK) return crv; | |
| 1548 crv = sftk_defaultAttribute(object,CKA_PRIVATE,&ckfalse,sizeof(CK_BBOOL)); | |
| 1549 if (crv != CKR_OK) return crv; | |
| 1550 crv = sftk_defaultAttribute(object,CKA_LABEL,NULL,0); | |
| 1551 if (crv != CKR_OK) return crv; | |
| 1552 crv = sftk_defaultAttribute(object,CKA_MODIFIABLE,&cktrue,sizeof(CK_BBOOL)); | |
| 1553 if (crv != CKR_OK) return crv; | |
| 1554 | |
| 1555 /* don't create a private object if we aren't logged in */ | |
| 1556 if ((!slot->isLoggedIn) && (slot->needLogin) && | |
| 1557 (sftk_isTrue(object,CKA_PRIVATE))) { | |
| 1558 return CKR_USER_NOT_LOGGED_IN; | |
| 1559 } | |
| 1560 | |
| 1561 | |
| 1562 if (((session->info.flags & CKF_RW_SESSION) == 0) && | |
| 1563 (sftk_isTrue(object,CKA_TOKEN))) { | |
| 1564 return CKR_SESSION_READ_ONLY; | |
| 1565 } | |
| 1566 | |
| 1567 /* Assign a unique SESSION object handle to every new object, | |
| 1568 * whether it is a session object or a token object. | |
| 1569 * At this point, all new objects are structured as session objects. | |
| 1570 * Objects with the CKA_TOKEN attribute true will be turned into | |
| 1571 * token objects and will have a token object handle assigned to | |
| 1572 * them by a call to sftk_mkHandle in the handler for each object | |
| 1573 * class, invoked below. | |
| 1574 * | |
| 1575 * It may be helpful to note/remember that | |
| 1576 * sftk_narrowToXxxObject uses sftk_isToken, | |
| 1577 * sftk_isToken examines the sign bit of the object's handle, but | |
| 1578 * sftk_isTrue(...,CKA_TOKEN) examines the CKA_TOKEN attribute. | |
| 1579 */ | |
| 1580 do { | |
| 1581 PRUint32 wrappedAround; | |
| 1582 | |
| 1583 duplicateObject = NULL; | |
| 1584 PZ_Lock(slot->objectLock); | |
| 1585 wrappedAround = slot->sessionObjectHandleCount & SFTK_TOKEN_MASK; | |
| 1586 handle = slot->sessionObjectHandleCount & ~SFTK_TOKEN_MASK; | |
| 1587 if (!handle) /* don't allow zero handle */ | |
| 1588 handle = minSessionObjectHandle; | |
| 1589 slot->sessionObjectHandleCount = (handle + 1U) | wrappedAround; | |
| 1590 /* Is there already a session object with this handle? */ | |
| 1591 if (wrappedAround) { | |
| 1592 sftkqueue_find(duplicateObject, handle, slot->sessObjHashTable, \ | |
| 1593 slot->sessObjHashSize); | |
| 1594 } | |
| 1595 PZ_Unlock(slot->objectLock); | |
| 1596 } while (duplicateObject != NULL); | |
| 1597 object->handle = handle; | |
| 1598 | |
| 1599 /* get the object class */ | |
| 1600 attribute = sftk_FindAttribute(object,CKA_CLASS); | |
| 1601 if (attribute == NULL) { | |
| 1602 return CKR_TEMPLATE_INCOMPLETE; | |
| 1603 } | |
| 1604 object->objclass = *(CK_OBJECT_CLASS *)attribute->attrib.pValue; | |
| 1605 sftk_FreeAttribute(attribute); | |
| 1606 | |
| 1607 /* Now handle the specific object class. | |
| 1608 * At this point, all objects are session objects, and the session | |
| 1609 * number must be passed to the object class handlers. | |
| 1610 */ | |
| 1611 switch (object->objclass) { | |
| 1612 case CKO_DATA: | |
| 1613 crv = sftk_handleDataObject(session,object); | |
| 1614 break; | |
| 1615 case CKO_CERTIFICATE: | |
| 1616 crv = sftk_handleCertObject(session,object); | |
| 1617 break; | |
| 1618 case CKO_NETSCAPE_TRUST: | |
| 1619 crv = sftk_handleTrustObject(session,object); | |
| 1620 break; | |
| 1621 case CKO_NETSCAPE_CRL: | |
| 1622 crv = sftk_handleCrlObject(session,object); | |
| 1623 break; | |
| 1624 case CKO_NETSCAPE_SMIME: | |
| 1625 crv = sftk_handleSMimeObject(session,object); | |
| 1626 break; | |
| 1627 case CKO_PRIVATE_KEY: | |
| 1628 case CKO_PUBLIC_KEY: | |
| 1629 case CKO_SECRET_KEY: | |
| 1630 crv = sftk_handleKeyObject(session,object); | |
| 1631 break; | |
| 1632 case CKO_KG_PARAMETERS: | |
| 1633 crv = sftk_handleKeyParameterObject(session,object); | |
| 1634 break; | |
| 1635 default: | |
| 1636 crv = CKR_ATTRIBUTE_VALUE_INVALID; | |
| 1637 break; | |
| 1638 } | |
| 1639 | |
| 1640 /* can't fail from here on out unless the pk_handlXXX functions have | |
| 1641 * failed the request */ | |
| 1642 if (crv != CKR_OK) { | |
| 1643 return crv; | |
| 1644 } | |
| 1645 | |
| 1646 /* Now link the object into the slot and session structures. | |
| 1647 * If the object has a true CKA_TOKEN attribute, the above object | |
| 1648 * class handlers will have set the sign bit in the object handle, | |
| 1649 * causing the following test to be true. | |
| 1650 */ | |
| 1651 if (sftk_isToken(object->handle)) { | |
| 1652 sftk_convertSessionToToken(object); | |
| 1653 } else { | |
| 1654 object->slot = slot; | |
| 1655 sftk_AddObject(session,object); | |
| 1656 } | |
| 1657 | |
| 1658 return CKR_OK; | |
| 1659 } | |
| 1660 | |
| 1661 /* | |
| 1662 * ******************** Public Key Utilities *************************** | |
| 1663 */ | |
| 1664 /* Generate a low public key structure from an object */ | |
| 1665 NSSLOWKEYPublicKey *sftk_GetPubKey(SFTKObject *object,CK_KEY_TYPE key_type, | |
| 1666 CK_RV *crvp) | |
| 1667 { | |
| 1668 NSSLOWKEYPublicKey *pubKey; | |
| 1669 PLArenaPool *arena; | |
| 1670 CK_RV crv; | |
| 1671 | |
| 1672 if (object->objclass != CKO_PUBLIC_KEY) { | |
| 1673 *crvp = CKR_KEY_TYPE_INCONSISTENT; | |
| 1674 return NULL; | |
| 1675 } | |
| 1676 | |
| 1677 if (sftk_isToken(object->handle)) { | |
| 1678 /* ferret out the token object handle */ | |
| 1679 } | |
| 1680 | |
| 1681 /* If we already have a key, use it */ | |
| 1682 if (object->objectInfo) { | |
| 1683 *crvp = CKR_OK; | |
| 1684 return (NSSLOWKEYPublicKey *)object->objectInfo; | |
| 1685 } | |
| 1686 | |
| 1687 /* allocate the structure */ | |
| 1688 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
| 1689 if (arena == NULL) { | |
| 1690 *crvp = CKR_HOST_MEMORY; | |
| 1691 return NULL; | |
| 1692 } | |
| 1693 | |
| 1694 pubKey = (NSSLOWKEYPublicKey *) | |
| 1695 PORT_ArenaAlloc(arena,sizeof(NSSLOWKEYPublicKey)); | |
| 1696 if (pubKey == NULL) { | |
| 1697 PORT_FreeArena(arena,PR_FALSE); | |
| 1698 *crvp = CKR_HOST_MEMORY; | |
| 1699 return NULL; | |
| 1700 } | |
| 1701 | |
| 1702 /* fill in the structure */ | |
| 1703 pubKey->arena = arena; | |
| 1704 switch (key_type) { | |
| 1705 case CKK_RSA: | |
| 1706 pubKey->keyType = NSSLOWKEYRSAKey; | |
| 1707 crv = sftk_Attribute2SSecItem(arena,&pubKey->u.rsa.modulus, | |
| 1708 object,CKA_MODULUS); | |
| 1709 if (crv != CKR_OK) break; | |
| 1710 crv = sftk_Attribute2SSecItem(arena,&pubKey->u.rsa.publicExponent, | |
| 1711 object,CKA_PUBLIC_EXPONENT); | |
| 1712 break; | |
| 1713 case CKK_DSA: | |
| 1714 pubKey->keyType = NSSLOWKEYDSAKey; | |
| 1715 crv = sftk_Attribute2SSecItem(arena,&pubKey->u.dsa.params.prime, | |
| 1716 object,CKA_PRIME); | |
| 1717 if (crv != CKR_OK) break; | |
| 1718 crv = sftk_Attribute2SSecItem(arena,&pubKey->u.dsa.params.subPrime, | |
| 1719 object,CKA_SUBPRIME); | |
| 1720 if (crv != CKR_OK) break; | |
| 1721 crv = sftk_Attribute2SSecItem(arena,&pubKey->u.dsa.params.base, | |
| 1722 object,CKA_BASE); | |
| 1723 if (crv != CKR_OK) break; | |
| 1724 crv = sftk_Attribute2SSecItem(arena,&pubKey->u.dsa.publicValue, | |
| 1725 object,CKA_VALUE); | |
| 1726 break; | |
| 1727 case CKK_DH: | |
| 1728 pubKey->keyType = NSSLOWKEYDHKey; | |
| 1729 crv = sftk_Attribute2SSecItem(arena,&pubKey->u.dh.prime, | |
| 1730 object,CKA_PRIME); | |
| 1731 if (crv != CKR_OK) break; | |
| 1732 crv = sftk_Attribute2SSecItem(arena,&pubKey->u.dh.base, | |
| 1733 object,CKA_BASE); | |
| 1734 if (crv != CKR_OK) break; | |
| 1735 crv = sftk_Attribute2SSecItem(arena,&pubKey->u.dh.publicValue, | |
| 1736 object,CKA_VALUE); | |
| 1737 break; | |
| 1738 #ifndef NSS_DISABLE_ECC | |
| 1739 case CKK_EC: | |
| 1740 pubKey->keyType = NSSLOWKEYECKey; | |
| 1741 crv = sftk_Attribute2SSecItem(arena, | |
| 1742 &pubKey->u.ec.ecParams.DEREncoding, | |
| 1743 object,CKA_EC_PARAMS); | |
| 1744 if (crv != CKR_OK) break; | |
| 1745 | |
| 1746 /* Fill out the rest of the ecParams structure | |
| 1747 * based on the encoded params | |
| 1748 */ | |
| 1749 if (EC_FillParams(arena, &pubKey->u.ec.ecParams.DEREncoding, | |
| 1750 &pubKey->u.ec.ecParams) != SECSuccess) { | |
| 1751 crv = CKR_DOMAIN_PARAMS_INVALID; | |
| 1752 break; | |
| 1753 } | |
| 1754 | |
| 1755 crv = sftk_Attribute2SSecItem(arena,&pubKey->u.ec.publicValue, | |
| 1756 object,CKA_EC_POINT); | |
| 1757 if (crv == CKR_OK) { | |
| 1758 unsigned int keyLen,curveLen; | |
| 1759 | |
| 1760 curveLen = (pubKey->u.ec.ecParams.fieldID.size +7)/8; | |
| 1761 keyLen = (2*curveLen)+1; | |
| 1762 | |
| 1763 /* special note: We can't just use the first byte to determine | |
| 1764 * between these 2 cases because both EC_POINT_FORM_UNCOMPRESSED | |
| 1765 * and SEC_ASN1_OCTET_STRING are 0x04 */ | |
| 1766 | |
| 1767 /* handle the non-DER encoded case (UNCOMPRESSED only) */ | |
| 1768 if (pubKey->u.ec.publicValue.data[0] == EC_POINT_FORM_UNCOMPRESSED | |
| 1769 && pubKey->u.ec.publicValue.len == keyLen) { | |
| 1770 break; /* key was not DER encoded, no need to unwrap */ | |
| 1771 } | |
| 1772 | |
| 1773 /* if we ever support compressed, handle it here */ | |
| 1774 | |
| 1775 /* handle the encoded case */ | |
| 1776 if ((pubKey->u.ec.publicValue.data[0] == SEC_ASN1_OCTET_STRING) | |
| 1777 && pubKey->u.ec.publicValue.len > keyLen) { | |
| 1778 SECItem publicValue; | |
| 1779 SECStatus rv; | |
| 1780 | |
| 1781 rv = SEC_QuickDERDecodeItem(arena, &publicValue, | |
| 1782 SEC_ASN1_GET(SEC_OctetStringTemplate), | |
| 1783 &pubKey->u.ec.publicValue); | |
| 1784 /* nope, didn't decode correctly */ | |
| 1785 if ((rv != SECSuccess) | |
| 1786 || (publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) | |
| 1787 || (publicValue.len != keyLen)) { | |
| 1788 crv = CKR_ATTRIBUTE_VALUE_INVALID; | |
| 1789 break; | |
| 1790 } | |
| 1791 /* replace our previous with the decoded key */ | |
| 1792 pubKey->u.ec.publicValue = publicValue; | |
| 1793 break; | |
| 1794 } | |
| 1795 crv = CKR_ATTRIBUTE_VALUE_INVALID; | |
| 1796 } | |
| 1797 break; | |
| 1798 #endif /* NSS_DISABLE_ECC */ | |
| 1799 default: | |
| 1800 crv = CKR_KEY_TYPE_INCONSISTENT; | |
| 1801 break; | |
| 1802 } | |
| 1803 *crvp = crv; | |
| 1804 if (crv != CKR_OK) { | |
| 1805 PORT_FreeArena(arena,PR_FALSE); | |
| 1806 return NULL; | |
| 1807 } | |
| 1808 | |
| 1809 object->objectInfo = pubKey; | |
| 1810 object->infoFree = (SFTKFree) nsslowkey_DestroyPublicKey; | |
| 1811 return pubKey; | |
| 1812 } | |
| 1813 | |
| 1814 /* make a private key from a verified object */ | |
| 1815 static NSSLOWKEYPrivateKey * | |
| 1816 sftk_mkPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp) | |
| 1817 { | |
| 1818 NSSLOWKEYPrivateKey *privKey; | |
| 1819 SFTKItemTemplate itemTemplate[SFTK_MAX_ITEM_TEMPLATE]; | |
| 1820 int itemTemplateCount = 0; | |
| 1821 PLArenaPool *arena; | |
| 1822 CK_RV crv = CKR_OK; | |
| 1823 SECStatus rv; | |
| 1824 | |
| 1825 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
| 1826 if (arena == NULL) { | |
| 1827 *crvp = CKR_HOST_MEMORY; | |
| 1828 return NULL; | |
| 1829 } | |
| 1830 | |
| 1831 privKey = (NSSLOWKEYPrivateKey *) | |
| 1832 PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey)); | |
| 1833 if (privKey == NULL) { | |
| 1834 PORT_FreeArena(arena,PR_FALSE); | |
| 1835 *crvp = CKR_HOST_MEMORY; | |
| 1836 return NULL; | |
| 1837 } | |
| 1838 | |
| 1839 /* in future this would be a switch on key_type */ | |
| 1840 privKey->arena = arena; | |
| 1841 switch (key_type) { | |
| 1842 case CKK_RSA: | |
| 1843 privKey->keyType = NSSLOWKEYRSAKey; | |
| 1844 | |
| 1845 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, | |
| 1846 &privKey->u.rsa.modulus,CKA_MODULUS); | |
| 1847 itemTemplateCount++; | |
| 1848 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, | |
| 1849 &privKey->u.rsa.publicExponent, CKA_PUBLIC_EXPONENT); | |
| 1850 itemTemplateCount++; | |
| 1851 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, | |
| 1852 &privKey->u.rsa.privateExponent, CKA_PRIVATE_EXPONENT); | |
| 1853 itemTemplateCount++; | |
| 1854 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, | |
| 1855 &privKey->u.rsa.prime1, CKA_PRIME_1); | |
| 1856 itemTemplateCount++; | |
| 1857 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, | |
| 1858 &privKey->u.rsa.prime2, CKA_PRIME_2); | |
| 1859 itemTemplateCount++; | |
| 1860 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, | |
| 1861 &privKey->u.rsa.exponent1, CKA_EXPONENT_1); | |
| 1862 itemTemplateCount++; | |
| 1863 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, | |
| 1864 &privKey->u.rsa.exponent2, CKA_EXPONENT_2); | |
| 1865 itemTemplateCount++; | |
| 1866 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, | |
| 1867 &privKey->u.rsa.coefficient, CKA_COEFFICIENT); | |
| 1868 itemTemplateCount++; | |
| 1869 rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version, | |
| 1870 NSSLOWKEY_PRIVATE_KEY_INFO_VERSION); | |
| 1871 if (rv != SECSuccess) crv = CKR_HOST_MEMORY; | |
| 1872 break; | |
| 1873 | |
| 1874 case CKK_DSA: | |
| 1875 privKey->keyType = NSSLOWKEYDSAKey; | |
| 1876 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, | |
| 1877 &privKey->u.dsa.params.prime, CKA_PRIME); | |
| 1878 itemTemplateCount++; | |
| 1879 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, | |
| 1880 &privKey->u.dsa.params.subPrime, CKA_SUBPRIME); | |
| 1881 itemTemplateCount++; | |
| 1882 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, | |
| 1883 &privKey->u.dsa.params.base, CKA_BASE); | |
| 1884 itemTemplateCount++; | |
| 1885 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, | |
| 1886 &privKey->u.dsa.privateValue, CKA_VALUE); | |
| 1887 itemTemplateCount++; | |
| 1888 /* privKey was zero'd so public value is already set to NULL, 0 | |
| 1889 * if we don't set it explicitly */ | |
| 1890 break; | |
| 1891 | |
| 1892 case CKK_DH: | |
| 1893 privKey->keyType = NSSLOWKEYDHKey; | |
| 1894 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, | |
| 1895 &privKey->u.dh.prime, CKA_PRIME); | |
| 1896 itemTemplateCount++; | |
| 1897 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, | |
| 1898 &privKey->u.dh.base, CKA_BASE); | |
| 1899 itemTemplateCount++; | |
| 1900 SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, | |
| 1901 &privKey->u.dh.privateValue, CKA_VALUE); | |
| 1902 itemTemplateCount++; | |
| 1903 /* privKey was zero'd so public value is already set to NULL, 0 | |
| 1904 * if we don't set it explicitly */ | |
| 1905 break; | |
| 1906 | |
| 1907 #ifndef NSS_DISABLE_ECC | |
| 1908 case CKK_EC: | |
| 1909 privKey->keyType = NSSLOWKEYECKey; | |
| 1910 crv = sftk_Attribute2SSecItem(arena, | |
| 1911 &privKey->u.ec.ecParams.DEREncoding, | |
| 1912 object,CKA_EC_PARAMS); | |
| 1913 if (crv != CKR_OK) break; | |
| 1914 | |
| 1915 /* Fill out the rest of the ecParams structure | |
| 1916 * based on the encoded params | |
| 1917 */ | |
| 1918 if (EC_FillParams(arena, &privKey->u.ec.ecParams.DEREncoding, | |
| 1919 &privKey->u.ec.ecParams) != SECSuccess) { | |
| 1920 crv = CKR_DOMAIN_PARAMS_INVALID; | |
| 1921 break; | |
| 1922 } | |
| 1923 crv = sftk_Attribute2SSecItem(arena,&privKey->u.ec.privateValue, | |
| 1924 object,CKA_VALUE); | |
| 1925 if (crv != CKR_OK) break; | |
| 1926 | |
| 1927 if (sftk_hasAttribute(object, CKA_NETSCAPE_DB)) { | |
| 1928 crv = sftk_Attribute2SSecItem(arena, &privKey->u.ec.publicValue, | |
| 1929 object, CKA_NETSCAPE_DB); | |
| 1930 if (crv != CKR_OK) break; | |
| 1931 /* privKey was zero'd so public value is already set to NULL, 0 | |
| 1932 * if we don't set it explicitly */ | |
| 1933 } | |
| 1934 rv = DER_SetUInteger(privKey->arena, &privKey->u.ec.version, | |
| 1935 NSSLOWKEY_EC_PRIVATE_KEY_VERSION); | |
| 1936 if (rv != SECSuccess) { | |
| 1937 crv = CKR_HOST_MEMORY; | |
| 1938 /* The following ifdef is needed for Linux arm distros and | |
| 1939 * Android as gcc 4.6 has a bug when targeting arm (but not | |
| 1940 * thumb). The bug has been fixed in gcc 4.7. | |
| 1941 * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56561 | |
| 1942 */ | |
| 1943 #if defined (__arm__) && !defined(__thumb__) && defined (__GNUC__) | |
| 1944 *crvp = CKR_HOST_MEMORY; | |
| 1945 break; | |
| 1946 #endif | |
| 1947 } | |
| 1948 break; | |
| 1949 #endif /* NSS_DISABLE_ECC */ | |
| 1950 | |
| 1951 default: | |
| 1952 crv = CKR_KEY_TYPE_INCONSISTENT; | |
| 1953 break; | |
| 1954 } | |
| 1955 if (crv == CKR_OK && itemTemplateCount != 0) { | |
| 1956 PORT_Assert(itemTemplateCount > 0); | |
| 1957 PORT_Assert(itemTemplateCount <= SFTK_MAX_ITEM_TEMPLATE); | |
| 1958 crv = sftk_MultipleAttribute2SecItem(arena, object, itemTemplate, | |
| 1959 itemTemplateCount); | |
| 1960 } | |
| 1961 *crvp = crv; | |
| 1962 if (crv != CKR_OK) { | |
| 1963 PORT_FreeArena(arena,PR_FALSE); | |
| 1964 return NULL; | |
| 1965 } | |
| 1966 return privKey; | |
| 1967 } | |
| 1968 | |
| 1969 /* | |
| 1970 * If a partial RSA private key is present, fill in the rest if necessary, | |
| 1971 * and then verify the parameters are well-formed | |
| 1972 */ | |
| 1973 static SECStatus | |
| 1974 sftk_verifyRSAPrivateKey(SFTKObject *object, PRBool fillIfNeeded) | |
| 1975 { | |
| 1976 RSAPrivateKey tmpKey = { 0 }; | |
| 1977 SFTKAttribute *modulus = NULL; | |
| 1978 SFTKAttribute *prime1 = NULL; | |
| 1979 SFTKAttribute *prime2 = NULL; | |
| 1980 SFTKAttribute *privateExponent = NULL; | |
| 1981 SFTKAttribute *publicExponent = NULL; | |
| 1982 SFTKAttribute *exponent1 = NULL; | |
| 1983 SFTKAttribute *exponent2 = NULL; | |
| 1984 SFTKAttribute *coefficient = NULL; | |
| 1985 SECStatus rv; | |
| 1986 CK_RV crv; | |
| 1987 | |
| 1988 /* first fill in the components that we have. Populate only uses | |
| 1989 * the non-crt components, so only fill those in */ | |
| 1990 tmpKey.arena = NULL; | |
| 1991 modulus = sftk_FindAttribute(object, CKA_MODULUS); | |
| 1992 if (modulus) { | |
| 1993 tmpKey.modulus.data = modulus->attrib.pValue; | |
| 1994 tmpKey.modulus.len = modulus->attrib.ulValueLen; | |
| 1995 } | |
| 1996 prime1 = sftk_FindAttribute(object, CKA_PRIME_1); | |
| 1997 if (prime1) { | |
| 1998 tmpKey.prime1.data = prime1->attrib.pValue; | |
| 1999 tmpKey.prime1.len = prime1->attrib.ulValueLen; | |
| 2000 } | |
| 2001 prime2 = sftk_FindAttribute(object, CKA_PRIME_2); | |
| 2002 if (prime2) { | |
| 2003 tmpKey.prime2.data = prime2->attrib.pValue; | |
| 2004 tmpKey.prime2.len = prime2->attrib.ulValueLen; | |
| 2005 } | |
| 2006 privateExponent = sftk_FindAttribute(object, CKA_PRIVATE_EXPONENT); | |
| 2007 if (privateExponent) { | |
| 2008 tmpKey.privateExponent.data = privateExponent->attrib.pValue; | |
| 2009 tmpKey.privateExponent.len = privateExponent->attrib.ulValueLen; | |
| 2010 } | |
| 2011 publicExponent = sftk_FindAttribute(object, CKA_PUBLIC_EXPONENT); | |
| 2012 if (publicExponent) { | |
| 2013 tmpKey.publicExponent.data = publicExponent->attrib.pValue; | |
| 2014 tmpKey.publicExponent.len = publicExponent->attrib.ulValueLen; | |
| 2015 } | |
| 2016 exponent1 = sftk_FindAttribute(object, CKA_EXPONENT_1); | |
| 2017 if (exponent1) { | |
| 2018 tmpKey.exponent1.data = exponent1->attrib.pValue; | |
| 2019 tmpKey.exponent1.len = exponent1->attrib.ulValueLen; | |
| 2020 } | |
| 2021 exponent2 = sftk_FindAttribute(object, CKA_EXPONENT_2); | |
| 2022 if (exponent2) { | |
| 2023 tmpKey.exponent2.data = exponent2->attrib.pValue; | |
| 2024 tmpKey.exponent2.len = exponent2->attrib.ulValueLen; | |
| 2025 } | |
| 2026 coefficient = sftk_FindAttribute(object, CKA_COEFFICIENT); | |
| 2027 if (coefficient) { | |
| 2028 tmpKey.coefficient.data = coefficient->attrib.pValue; | |
| 2029 tmpKey.coefficient.len = coefficient->attrib.ulValueLen; | |
| 2030 } | |
| 2031 | |
| 2032 if (fillIfNeeded) { | |
| 2033 /* | |
| 2034 * populate requires one exponent plus 2 other components to work. | |
| 2035 * we expected our caller to check that first. If that didn't happen, | |
| 2036 * populate will simply return an error here. | |
| 2037 */ | |
| 2038 rv = RSA_PopulatePrivateKey(&tmpKey); | |
| 2039 if (rv != SECSuccess) { | |
| 2040 goto loser; | |
| 2041 } | |
| 2042 } | |
| 2043 rv = RSA_PrivateKeyCheck(&tmpKey); | |
| 2044 if (rv != SECSuccess) { | |
| 2045 goto loser; | |
| 2046 } | |
| 2047 /* now that we have a fully populated key, set all our attribute values */ | |
| 2048 rv = SECFailure; | |
| 2049 if (!modulus || modulus->attrib.pValue != tmpKey.modulus.data) { | |
| 2050 crv = sftk_forceAttribute(object,CKA_MODULUS, | |
| 2051 sftk_item_expand(&tmpKey.modulus)); | |
| 2052 if (crv != CKR_OK) goto loser; | |
| 2053 } | |
| 2054 if (!publicExponent || | |
| 2055 publicExponent->attrib.pValue != tmpKey.publicExponent.data) { | |
| 2056 crv = sftk_forceAttribute(object, CKA_PUBLIC_EXPONENT, | |
| 2057 sftk_item_expand(&tmpKey.publicExponent)); | |
| 2058 if (crv != CKR_OK) goto loser; | |
| 2059 } | |
| 2060 if (!privateExponent || | |
| 2061 privateExponent->attrib.pValue != tmpKey.privateExponent.data) { | |
| 2062 crv = sftk_forceAttribute(object, CKA_PRIVATE_EXPONENT, | |
| 2063 sftk_item_expand(&tmpKey.privateExponent)); | |
| 2064 if (crv != CKR_OK) goto loser; | |
| 2065 } | |
| 2066 if (!prime1 || prime1->attrib.pValue != tmpKey.prime1.data) { | |
| 2067 crv = sftk_forceAttribute(object, CKA_PRIME_1, | |
| 2068 sftk_item_expand(&tmpKey.prime1)); | |
| 2069 if (crv != CKR_OK) goto loser; | |
| 2070 } | |
| 2071 if (!prime2 || prime2->attrib.pValue != tmpKey.prime2.data) { | |
| 2072 crv = sftk_forceAttribute(object, CKA_PRIME_2, | |
| 2073 sftk_item_expand(&tmpKey.prime2)); | |
| 2074 if (crv != CKR_OK) goto loser; | |
| 2075 } | |
| 2076 if (!exponent1 || exponent1->attrib.pValue != tmpKey.exponent1.data) { | |
| 2077 crv = sftk_forceAttribute(object, CKA_EXPONENT_1, | |
| 2078 sftk_item_expand(&tmpKey.exponent1)); | |
| 2079 if (crv != CKR_OK) goto loser; | |
| 2080 } | |
| 2081 if (!exponent2 || exponent2->attrib.pValue != tmpKey.exponent2.data) { | |
| 2082 crv = sftk_forceAttribute(object, CKA_EXPONENT_2, | |
| 2083 sftk_item_expand(&tmpKey.exponent2)); | |
| 2084 if (crv != CKR_OK) goto loser; | |
| 2085 } | |
| 2086 if (!coefficient || coefficient->attrib.pValue != tmpKey.coefficient.data) { | |
| 2087 crv = sftk_forceAttribute(object, CKA_COEFFICIENT, | |
| 2088 sftk_item_expand(&tmpKey.coefficient)); | |
| 2089 if (crv != CKR_OK) goto loser; | |
| 2090 } | |
| 2091 rv = SECSuccess; | |
| 2092 | |
| 2093 /* we're done (one way or the other), clean up all our stuff */ | |
| 2094 loser: | |
| 2095 if (tmpKey.arena) { | |
| 2096 PORT_FreeArena(tmpKey.arena,PR_TRUE); | |
| 2097 } | |
| 2098 if (modulus) { | |
| 2099 sftk_FreeAttribute(modulus); | |
| 2100 } | |
| 2101 if (prime1) { | |
| 2102 sftk_FreeAttribute(prime1); | |
| 2103 } | |
| 2104 if (prime2) { | |
| 2105 sftk_FreeAttribute(prime2); | |
| 2106 } | |
| 2107 if (privateExponent) { | |
| 2108 sftk_FreeAttribute(privateExponent); | |
| 2109 } | |
| 2110 if (publicExponent) { | |
| 2111 sftk_FreeAttribute(publicExponent); | |
| 2112 } | |
| 2113 if (exponent1) { | |
| 2114 sftk_FreeAttribute(exponent1); | |
| 2115 } | |
| 2116 if (exponent2) { | |
| 2117 sftk_FreeAttribute(exponent2); | |
| 2118 } | |
| 2119 if (coefficient) { | |
| 2120 sftk_FreeAttribute(coefficient); | |
| 2121 } | |
| 2122 return rv; | |
| 2123 } | |
| 2124 | |
| 2125 /* Generate a low private key structure from an object */ | |
| 2126 NSSLOWKEYPrivateKey * | |
| 2127 sftk_GetPrivKey(SFTKObject *object,CK_KEY_TYPE key_type, CK_RV *crvp) | |
| 2128 { | |
| 2129 NSSLOWKEYPrivateKey *priv = NULL; | |
| 2130 | |
| 2131 if (object->objclass != CKO_PRIVATE_KEY) { | |
| 2132 *crvp = CKR_KEY_TYPE_INCONSISTENT; | |
| 2133 return NULL; | |
| 2134 } | |
| 2135 if (object->objectInfo) { | |
| 2136 *crvp = CKR_OK; | |
| 2137 return (NSSLOWKEYPrivateKey *)object->objectInfo; | |
| 2138 } | |
| 2139 | |
| 2140 priv = sftk_mkPrivKey(object, key_type, crvp); | |
| 2141 object->objectInfo = priv; | |
| 2142 object->infoFree = (SFTKFree) nsslowkey_DestroyPrivateKey; | |
| 2143 return priv; | |
| 2144 } | |
| 2145 | |
| 2146 /* | |
| 2147 **************************** Symetric Key utils ************************ | |
| 2148 */ | |
| 2149 /* | |
| 2150 * set the DES key with parity bits correctly | |
| 2151 */ | |
| 2152 void | |
| 2153 sftk_FormatDESKey(unsigned char *key, int length) | |
| 2154 { | |
| 2155 int i; | |
| 2156 | |
| 2157 /* format the des key */ | |
| 2158 for (i=0; i < length; i++) { | |
| 2159 key[i] = parityTable[key[i]>>1]; | |
| 2160 } | |
| 2161 } | |
| 2162 | |
| 2163 /* | |
| 2164 * check a des key (des2 or des3 subkey) for weak keys. | |
| 2165 */ | |
| 2166 PRBool | |
| 2167 sftk_CheckDESKey(unsigned char *key) | |
| 2168 { | |
| 2169 int i; | |
| 2170 | |
| 2171 /* format the des key with parity */ | |
| 2172 sftk_FormatDESKey(key, 8); | |
| 2173 | |
| 2174 for (i=0; i < sftk_desWeakTableSize; i++) { | |
| 2175 if (PORT_Memcmp(key,sftk_desWeakTable[i],8) == 0) { | |
| 2176 return PR_TRUE; | |
| 2177 } | |
| 2178 } | |
| 2179 return PR_FALSE; | |
| 2180 } | |
| 2181 | |
| 2182 /* | |
| 2183 * check if a des or triple des key is weak. | |
| 2184 */ | |
| 2185 PRBool | |
| 2186 sftk_IsWeakKey(unsigned char *key,CK_KEY_TYPE key_type) | |
| 2187 { | |
| 2188 | |
| 2189 switch(key_type) { | |
| 2190 case CKK_DES: | |
| 2191 return sftk_CheckDESKey(key); | |
| 2192 case CKM_DES2_KEY_GEN: | |
| 2193 if (sftk_CheckDESKey(key)) return PR_TRUE; | |
| 2194 return sftk_CheckDESKey(&key[8]); | |
| 2195 case CKM_DES3_KEY_GEN: | |
| 2196 if (sftk_CheckDESKey(key)) return PR_TRUE; | |
| 2197 if (sftk_CheckDESKey(&key[8])) return PR_TRUE; | |
| 2198 return sftk_CheckDESKey(&key[16]); | |
| 2199 default: | |
| 2200 break; | |
| 2201 } | |
| 2202 return PR_FALSE; | |
| 2203 } | |
| 2204 | |
| 2205 | |
| 2206 /********************************************************************** | |
| 2207 * | |
| 2208 * Start of PKCS 11 functions | |
| 2209 * | |
| 2210 **********************************************************************/ | |
| 2211 | |
| 2212 | |
| 2213 /* return the function list */ | |
| 2214 CK_RV NSC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) | |
| 2215 { | |
| 2216 CHECK_FORK(); | |
| 2217 | |
| 2218 *pFunctionList = (CK_FUNCTION_LIST_PTR) &sftk_funcList; | |
| 2219 return CKR_OK; | |
| 2220 } | |
| 2221 | |
| 2222 /* return the function list */ | |
| 2223 CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) | |
| 2224 { | |
| 2225 CHECK_FORK(); | |
| 2226 | |
| 2227 return NSC_GetFunctionList(pFunctionList); | |
| 2228 } | |
| 2229 | |
| 2230 static PLHashNumber | |
| 2231 sftk_HashNumber(const void *key) | |
| 2232 { | |
| 2233 return (PLHashNumber)((char *)key - (char *)NULL); | |
| 2234 } | |
| 2235 | |
| 2236 /* | |
| 2237 * eventually I'd like to expunge all occurances of XXX_SLOT_ID and | |
| 2238 * just go with the info in the slot. This is one place, however, | |
| 2239 * where it might be a little difficult. | |
| 2240 */ | |
| 2241 const char * | |
| 2242 sftk_getDefTokName(CK_SLOT_ID slotID) | |
| 2243 { | |
| 2244 static char buf[33]; | |
| 2245 | |
| 2246 switch (slotID) { | |
| 2247 case NETSCAPE_SLOT_ID: | |
| 2248 return "NSS Generic Crypto Services "; | |
| 2249 case PRIVATE_KEY_SLOT_ID: | |
| 2250 return "NSS Certificate DB "; | |
| 2251 case FIPS_SLOT_ID: | |
| 2252 return "NSS FIPS 140-2 Certificate DB "; | |
| 2253 default: | |
| 2254 break; | |
| 2255 } | |
| 2256 sprintf(buf,"NSS Application Token %08x ",(unsigned int) slotID); | |
| 2257 return buf; | |
| 2258 } | |
| 2259 | |
| 2260 const char * | |
| 2261 sftk_getDefSlotName(CK_SLOT_ID slotID) | |
| 2262 { | |
| 2263 static char buf[65]; | |
| 2264 | |
| 2265 switch (slotID) { | |
| 2266 case NETSCAPE_SLOT_ID: | |
| 2267 return | |
| 2268 "NSS Internal Cryptographic Services "; | |
| 2269 case PRIVATE_KEY_SLOT_ID: | |
| 2270 return | |
| 2271 "NSS User Private Key and Certificate Services "; | |
| 2272 case FIPS_SLOT_ID: | |
| 2273 return | |
| 2274 "NSS FIPS 140-2 User Private Key Services "; | |
| 2275 default: | |
| 2276 break; | |
| 2277 } | |
| 2278 sprintf(buf, | |
| 2279 "NSS Application Slot %08x ", | |
| 2280 (unsigned int) slotID); | |
| 2281 return buf; | |
| 2282 } | |
| 2283 | |
| 2284 static CK_ULONG nscSlotCount[2] = {0 , 0}; | |
| 2285 static CK_SLOT_ID_PTR nscSlotList[2] = {NULL, NULL}; | |
| 2286 static CK_ULONG nscSlotListSize[2] = {0, 0}; | |
| 2287 static PLHashTable *nscSlotHashTable[2] = {NULL, NULL}; | |
| 2288 | |
| 2289 static int | |
| 2290 sftk_GetModuleIndex(CK_SLOT_ID slotID) | |
| 2291 { | |
| 2292 if ((slotID == FIPS_SLOT_ID) || (slotID >= SFTK_MIN_FIPS_USER_SLOT_ID)) { | |
| 2293 return NSC_FIPS_MODULE; | |
| 2294 } | |
| 2295 return NSC_NON_FIPS_MODULE; | |
| 2296 } | |
| 2297 | |
| 2298 /* look up a slot structure from the ID (used to be a macro when we only | |
| 2299 * had two slots) */ | |
| 2300 /* if all is true, return the slot even if it has been 'unloaded' */ | |
| 2301 /* if all is false, only return the slots which are present */ | |
| 2302 SFTKSlot * | |
| 2303 sftk_SlotFromID(CK_SLOT_ID slotID, PRBool all) | |
| 2304 { | |
| 2305 SFTKSlot *slot; | |
| 2306 int index = sftk_GetModuleIndex(slotID); | |
| 2307 | |
| 2308 if (nscSlotHashTable[index] == NULL) return NULL; | |
| 2309 slot = (SFTKSlot *)PL_HashTableLookupConst(nscSlotHashTable[index], | |
| 2310 (void *)slotID); | |
| 2311 /* cleared slots shouldn't 'show up' */ | |
| 2312 if (slot && !all && !slot->present) slot = NULL; | |
| 2313 return slot; | |
| 2314 } | |
| 2315 | |
| 2316 SFTKSlot * | |
| 2317 sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle) | |
| 2318 { | |
| 2319 CK_ULONG slotIDIndex = (handle >> 24) & 0x7f; | |
| 2320 CK_ULONG moduleIndex = (handle >> 31) & 1; | |
| 2321 | |
| 2322 if (slotIDIndex >= nscSlotCount[moduleIndex]) { | |
| 2323 return NULL; | |
| 2324 } | |
| 2325 | |
| 2326 return sftk_SlotFromID(nscSlotList[moduleIndex][slotIDIndex], PR_FALSE); | |
| 2327 } | |
| 2328 | |
| 2329 static CK_RV | |
| 2330 sftk_RegisterSlot(SFTKSlot *slot, int moduleIndex) | |
| 2331 { | |
| 2332 PLHashEntry *entry; | |
| 2333 int index; | |
| 2334 | |
| 2335 index = sftk_GetModuleIndex(slot->slotID); | |
| 2336 | |
| 2337 /* make sure the slotID for this module is valid */ | |
| 2338 if (moduleIndex != index) { | |
| 2339 return CKR_SLOT_ID_INVALID; | |
| 2340 } | |
| 2341 | |
| 2342 if (nscSlotList[index] == NULL) { | |
| 2343 nscSlotListSize[index] = NSC_SLOT_LIST_BLOCK_SIZE; | |
| 2344 nscSlotList[index] = (CK_SLOT_ID *) | |
| 2345 PORT_ZAlloc(nscSlotListSize[index]*sizeof(CK_SLOT_ID)); | |
| 2346 if (nscSlotList[index] == NULL) { | |
| 2347 return CKR_HOST_MEMORY; | |
| 2348 } | |
| 2349 } | |
| 2350 if (nscSlotCount[index] >= nscSlotListSize[index]) { | |
| 2351 CK_SLOT_ID* oldNscSlotList = nscSlotList[index]; | |
| 2352 CK_ULONG oldNscSlotListSize = nscSlotListSize[index]; | |
| 2353 nscSlotListSize[index] += NSC_SLOT_LIST_BLOCK_SIZE; | |
| 2354 nscSlotList[index] = (CK_SLOT_ID *) PORT_Realloc(oldNscSlotList, | |
| 2355 nscSlotListSize[index]*sizeof(CK_SLOT_ID)); | |
| 2356 if (nscSlotList[index] == NULL) { | |
| 2357 nscSlotList[index] = oldNscSlotList; | |
| 2358 nscSlotListSize[index] = oldNscSlotListSize; | |
| 2359 return CKR_HOST_MEMORY; | |
| 2360 } | |
| 2361 } | |
| 2362 | |
| 2363 if (nscSlotHashTable[index] == NULL) { | |
| 2364 nscSlotHashTable[index] = PL_NewHashTable(64,sftk_HashNumber, | |
| 2365 PL_CompareValues, PL_CompareValues, NULL, 0); | |
| 2366 if (nscSlotHashTable[index] == NULL) { | |
| 2367 return CKR_HOST_MEMORY; | |
| 2368 } | |
| 2369 } | |
| 2370 | |
| 2371 entry = PL_HashTableAdd(nscSlotHashTable[index],(void *)slot->slotID,slot); | |
| 2372 if (entry == NULL) { | |
| 2373 return CKR_HOST_MEMORY; | |
| 2374 } | |
| 2375 slot->index = (nscSlotCount[index] & 0x7f) | ((index << 7) & 0x80); | |
| 2376 nscSlotList[index][nscSlotCount[index]++] = slot->slotID; | |
| 2377 | |
| 2378 return CKR_OK; | |
| 2379 } | |
| 2380 | |
| 2381 | |
| 2382 /* | |
| 2383 * ths function has all the common initialization that happens whenever we | |
| 2384 * create a new slot or repurpose an old slot (only valid for slotID's 4 | |
| 2385 * and greater). | |
| 2386 * | |
| 2387 * things that are not reinitialized are: | |
| 2388 * slotID (can't change) | |
| 2389 * slotDescription (can't change once defined) | |
| 2390 * the locks and hash tables (difficult to change in running code, and | |
| 2391 * unnecessary. hash tables and list are cleared on shutdown, but they | |
| 2392 * are cleared in a 'friendly' way). | |
| 2393 * session and object ID counters -- so any old sessions and objects in the | |
| 2394 * application will get properly notified that the world has changed. | |
| 2395 * | |
| 2396 * things that are reinitialized: | |
| 2397 * database (otherwise what would the point be;). | |
| 2398 * state variables related to databases. | |
| 2399 * session count stat info. | |
| 2400 * tokenDescription. | |
| 2401 * | |
| 2402 * NOTE: slotID's 4 and greater show up as removable devices. | |
| 2403 * | |
| 2404 */ | |
| 2405 CK_RV | |
| 2406 SFTK_SlotReInit(SFTKSlot *slot, char *configdir, char *updatedir, | |
| 2407 char *updateID, sftk_token_parameters *params, int moduleIndex) | |
| 2408 { | |
| 2409 PRBool needLogin = !params->noKeyDB; | |
| 2410 CK_RV crv; | |
| 2411 | |
| 2412 slot->hasTokens = PR_FALSE; | |
| 2413 slot->sessionIDConflict = 0; | |
| 2414 slot->sessionCount = 0; | |
| 2415 slot->rwSessionCount = 0; | |
| 2416 slot->needLogin = PR_FALSE; | |
| 2417 slot->isLoggedIn = PR_FALSE; | |
| 2418 slot->ssoLoggedIn = PR_FALSE; | |
| 2419 slot->DB_loaded = PR_FALSE; | |
| 2420 slot->certDB = NULL; | |
| 2421 slot->keyDB = NULL; | |
| 2422 slot->minimumPinLen = 0; | |
| 2423 slot->readOnly = params->readOnly; | |
| 2424 sftk_setStringName(params->tokdes ? params->tokdes : | |
| 2425 sftk_getDefTokName(slot->slotID), slot->tokDescription, | |
| 2426 sizeof(slot->tokDescription),PR_TRUE); | |
| 2427 sftk_setStringName(params->updtokdes ? params->updtokdes : " ", | |
| 2428 slot->updateTokDescription, | |
| 2429 sizeof(slot->updateTokDescription),PR_TRUE); | |
| 2430 | |
| 2431 if ((!params->noCertDB) || (!params->noKeyDB)) { | |
| 2432 SFTKDBHandle * certHandle = NULL; | |
| 2433 SFTKDBHandle *keyHandle = NULL; | |
| 2434 crv = sftk_DBInit(params->configdir ? params->configdir : configdir, | |
| 2435 params->certPrefix, params->keyPrefix, | |
| 2436 params->updatedir ? params->updatedir : updatedir, | |
| 2437 params->updCertPrefix, params->updKeyPrefix, | |
| 2438 params->updateID ? params->updateID : updateID, | |
| 2439 params->readOnly, params->noCertDB, params->noKeyDB, | |
| 2440 params->forceOpen, | |
| 2441 moduleIndex == NSC_FIPS_MODULE, | |
| 2442 &certHandle, &keyHandle); | |
| 2443 if (crv != CKR_OK) { | |
| 2444 goto loser; | |
| 2445 } | |
| 2446 | |
| 2447 slot->certDB = certHandle; | |
| 2448 slot->keyDB = keyHandle; | |
| 2449 } | |
| 2450 if (needLogin) { | |
| 2451 /* if the data base is initialized with a null password,remember that */ | |
| 2452 slot->needLogin = | |
| 2453 (PRBool)!sftk_hasNullPassword(slot, slot->keyDB); | |
| 2454 if ((params->minPW >= 0) && (params->minPW <= SFTK_MAX_PIN)) { | |
| 2455 slot->minimumPinLen = params->minPW; | |
| 2456 } | |
| 2457 if ((slot->minimumPinLen == 0) && (params->pwRequired)) { | |
| 2458 slot->minimumPinLen = 1; | |
| 2459 } | |
| 2460 if ((moduleIndex == NSC_FIPS_MODULE) && | |
| 2461 (slot->minimumPinLen < FIPS_MIN_PIN)) { | |
| 2462 slot->minimumPinLen = FIPS_MIN_PIN; | |
| 2463 } | |
| 2464 } | |
| 2465 | |
| 2466 slot->present = PR_TRUE; | |
| 2467 return CKR_OK; | |
| 2468 | |
| 2469 loser: | |
| 2470 SFTK_ShutdownSlot(slot); | |
| 2471 return crv; | |
| 2472 } | |
| 2473 | |
| 2474 /* | |
| 2475 * initialize one of the slot structures. figure out which by the ID | |
| 2476 */ | |
| 2477 CK_RV | |
| 2478 SFTK_SlotInit(char *configdir, char *updatedir, char *updateID, | |
| 2479 sftk_token_parameters *params, int moduleIndex) | |
| 2480 { | |
| 2481 unsigned int i; | |
| 2482 CK_SLOT_ID slotID = params->slotID; | |
| 2483 SFTKSlot *slot; | |
| 2484 CK_RV crv = CKR_HOST_MEMORY; | |
| 2485 | |
| 2486 /* | |
| 2487 * first we initialize everything that is 'permanent' with this slot. | |
| 2488 * that is everything we aren't going to shutdown if we close this slot | |
| 2489 * and open it up again with different databases */ | |
| 2490 | |
| 2491 slot = PORT_ZNew(SFTKSlot); | |
| 2492 | |
| 2493 if (slot == NULL) { | |
| 2494 return CKR_HOST_MEMORY; | |
| 2495 } | |
| 2496 | |
| 2497 slot->optimizeSpace = params->optimizeSpace; | |
| 2498 if (slot->optimizeSpace) { | |
| 2499 slot->sessObjHashSize = SPACE_SESSION_OBJECT_HASH_SIZE; | |
| 2500 slot->sessHashSize = SPACE_SESSION_HASH_SIZE; | |
| 2501 slot->numSessionLocks = 1; | |
| 2502 } else { | |
| 2503 slot->sessObjHashSize = TIME_SESSION_OBJECT_HASH_SIZE; | |
| 2504 slot->sessHashSize = TIME_SESSION_HASH_SIZE; | |
| 2505 slot->numSessionLocks = slot->sessHashSize/BUCKETS_PER_SESSION_LOCK; | |
| 2506 } | |
| 2507 slot->sessionLockMask = slot->numSessionLocks-1; | |
| 2508 | |
| 2509 slot->slotLock = PZ_NewLock(nssILockSession); | |
| 2510 if (slot->slotLock == NULL) | |
| 2511 goto mem_loser; | |
| 2512 slot->sessionLock = PORT_ZNewArray(PZLock *, slot->numSessionLocks); | |
| 2513 if (slot->sessionLock == NULL) | |
| 2514 goto mem_loser; | |
| 2515 for (i=0; i < slot->numSessionLocks; i++) { | |
| 2516 slot->sessionLock[i] = PZ_NewLock(nssILockSession); | |
| 2517 if (slot->sessionLock[i] == NULL) | |
| 2518 goto mem_loser; | |
| 2519 } | |
| 2520 slot->objectLock = PZ_NewLock(nssILockObject); | |
| 2521 if (slot->objectLock == NULL) | |
| 2522 goto mem_loser; | |
| 2523 slot->pwCheckLock = PR_NewLock(); | |
| 2524 if (slot->pwCheckLock == NULL) | |
| 2525 goto mem_loser; | |
| 2526 slot->head = PORT_ZNewArray(SFTKSession *, slot->sessHashSize); | |
| 2527 if (slot->head == NULL) | |
| 2528 goto mem_loser; | |
| 2529 slot->sessObjHashTable = PORT_ZNewArray(SFTKObject *, slot->sessObjHashSize)
; | |
| 2530 if (slot->sessObjHashTable == NULL) | |
| 2531 goto mem_loser; | |
| 2532 slot->tokObjHashTable = PL_NewHashTable(64,sftk_HashNumber,PL_CompareValues, | |
| 2533 SECITEM_HashCompare, NULL, 0); | |
| 2534 if (slot->tokObjHashTable == NULL) | |
| 2535 goto mem_loser; | |
| 2536 | |
| 2537 slot->sessionIDCount = 0; | |
| 2538 slot->sessionObjectHandleCount = minSessionObjectHandle; | |
| 2539 slot->slotID = slotID; | |
| 2540 sftk_setStringName(params->slotdes ? params->slotdes : | |
| 2541 sftk_getDefSlotName(slotID), slot->slotDescription, | |
| 2542 sizeof(slot->slotDescription), PR_TRUE); | |
| 2543 | |
| 2544 /* call the reinit code to set everything that changes between token | |
| 2545 * init calls */ | |
| 2546 crv = SFTK_SlotReInit(slot, configdir, updatedir, updateID, | |
| 2547 params, moduleIndex); | |
| 2548 if (crv != CKR_OK) { | |
| 2549 goto loser; | |
| 2550 } | |
| 2551 crv = sftk_RegisterSlot(slot, moduleIndex); | |
| 2552 if (crv != CKR_OK) { | |
| 2553 goto loser; | |
| 2554 } | |
| 2555 return CKR_OK; | |
| 2556 | |
| 2557 mem_loser: | |
| 2558 crv = CKR_HOST_MEMORY; | |
| 2559 loser: | |
| 2560 SFTK_DestroySlotData(slot); | |
| 2561 return crv; | |
| 2562 } | |
| 2563 | |
| 2564 | |
| 2565 CK_RV sftk_CloseAllSessions(SFTKSlot *slot, PRBool logout) | |
| 2566 { | |
| 2567 SFTKSession *session; | |
| 2568 unsigned int i; | |
| 2569 SFTKDBHandle *handle; | |
| 2570 | |
| 2571 /* first log out the card */ | |
| 2572 /* special case - if we are in a middle of upgrade, we want to close the | |
| 2573 * sessions to fake a token removal to tell the upper level code we have | |
| 2574 * switched from one database to another, but we don't want to | |
| 2575 * explicity logout in case we can continue the upgrade with the | |
| 2576 * existing password if possible. | |
| 2577 */ | |
| 2578 if (logout) { | |
| 2579 handle = sftk_getKeyDB(slot); | |
| 2580 SKIP_AFTER_FORK(PZ_Lock(slot->slotLock)); | |
| 2581 slot->isLoggedIn = PR_FALSE; | |
| 2582 if (slot->needLogin && handle) { | |
| 2583 sftkdb_ClearPassword(handle); | |
| 2584 } | |
| 2585 SKIP_AFTER_FORK(PZ_Unlock(slot->slotLock)); | |
| 2586 if (handle) { | |
| 2587 sftk_freeDB(handle); | |
| 2588 } | |
| 2589 } | |
| 2590 | |
| 2591 /* now close all the current sessions */ | |
| 2592 /* NOTE: If you try to open new sessions before NSC_CloseAllSessions | |
| 2593 * completes, some of those new sessions may or may not be closed by | |
| 2594 * NSC_CloseAllSessions... but any session running when this code starts | |
| 2595 * will guarrenteed be close, and no session will be partially closed */ | |
| 2596 for (i=0; i < slot->sessHashSize; i++) { | |
| 2597 PZLock *lock = SFTK_SESSION_LOCK(slot,i); | |
| 2598 do { | |
| 2599 SKIP_AFTER_FORK(PZ_Lock(lock)); | |
| 2600 session = slot->head[i]; | |
| 2601 /* hand deque */ | |
| 2602 /* this duplicates function of NSC_close session functions, but | |
| 2603 * because we know that we are freeing all the sessions, we can | |
| 2604 * do more efficient processing */ | |
| 2605 if (session) { | |
| 2606 slot->head[i] = session->next; | |
| 2607 if (session->next) session->next->prev = NULL; | |
| 2608 session->next = session->prev = NULL; | |
| 2609 SKIP_AFTER_FORK(PZ_Unlock(lock)); | |
| 2610 SKIP_AFTER_FORK(PZ_Lock(slot->slotLock)); | |
| 2611 --slot->sessionCount; | |
| 2612 SKIP_AFTER_FORK(PZ_Unlock(slot->slotLock)); | |
| 2613 if (session->info.flags & CKF_RW_SESSION) { | |
| 2614 (void)PR_ATOMIC_DECREMENT(&slot->rwSessionCount); | |
| 2615 } | |
| 2616 } else { | |
| 2617 SKIP_AFTER_FORK(PZ_Unlock(lock)); | |
| 2618 } | |
| 2619 if (session) sftk_FreeSession(session); | |
| 2620 } while (session != NULL); | |
| 2621 } | |
| 2622 return CKR_OK; | |
| 2623 } | |
| 2624 | |
| 2625 /* | |
| 2626 * shut down the databases. | |
| 2627 * we get the slot lock (which also protects slot->certDB and slot->keyDB) | |
| 2628 * and clear the values so the new users will not find the databases. | |
| 2629 * once things are clear, we can release our references to the databases. | |
| 2630 * The databases will close when the last reference is released. | |
| 2631 * | |
| 2632 * We use reference counts so that we don't crash if someone shuts down | |
| 2633 * a token that another thread is actively using. | |
| 2634 */ | |
| 2635 static void | |
| 2636 sftk_DBShutdown(SFTKSlot *slot) | |
| 2637 { | |
| 2638 SFTKDBHandle *certHandle; | |
| 2639 SFTKDBHandle *keyHandle; | |
| 2640 SKIP_AFTER_FORK(PZ_Lock(slot->slotLock)); | |
| 2641 certHandle = slot->certDB; | |
| 2642 slot->certDB = NULL; | |
| 2643 keyHandle = slot->keyDB; | |
| 2644 slot->keyDB = NULL; | |
| 2645 SKIP_AFTER_FORK(PZ_Unlock(slot->slotLock)); | |
| 2646 if (certHandle) { | |
| 2647 sftk_freeDB(certHandle); | |
| 2648 } | |
| 2649 if (keyHandle) { | |
| 2650 sftk_freeDB(keyHandle); | |
| 2651 } | |
| 2652 } | |
| 2653 | |
| 2654 CK_RV | |
| 2655 SFTK_ShutdownSlot(SFTKSlot *slot) | |
| 2656 { | |
| 2657 /* make sure no new PK11 calls work except C_GetSlotInfo */ | |
| 2658 slot->present = PR_FALSE; | |
| 2659 | |
| 2660 /* close all outstanding sessions | |
| 2661 * the sessHashSize variable guarentees we have all the session | |
| 2662 * mechanism set up */ | |
| 2663 if (slot->head) { | |
| 2664 sftk_CloseAllSessions(slot, PR_TRUE); | |
| 2665 } | |
| 2666 | |
| 2667 /* clear all objects.. session objects are cleared as a result of | |
| 2668 * closing all the sessions. We just need to clear the token object | |
| 2669 * cache. slot->tokObjHashTable guarentees we have the token | |
| 2670 * infrastructure set up. */ | |
| 2671 if (slot->tokObjHashTable) { | |
| 2672 SFTK_ClearTokenKeyHashTable(slot); | |
| 2673 } | |
| 2674 | |
| 2675 /* clear the slot description for the next guy */ | |
| 2676 PORT_Memset(slot->tokDescription, 0, sizeof(slot->tokDescription)); | |
| 2677 | |
| 2678 /* now shut down the databases. */ | |
| 2679 sftk_DBShutdown(slot); | |
| 2680 return CKR_OK; | |
| 2681 } | |
| 2682 | |
| 2683 /* | |
| 2684 * initialize one of the slot structures. figure out which by the ID | |
| 2685 */ | |
| 2686 CK_RV | |
| 2687 SFTK_DestroySlotData(SFTKSlot *slot) | |
| 2688 { | |
| 2689 unsigned int i; | |
| 2690 | |
| 2691 SFTK_ShutdownSlot(slot); | |
| 2692 | |
| 2693 if (slot->tokObjHashTable) { | |
| 2694 PL_HashTableDestroy(slot->tokObjHashTable); | |
| 2695 slot->tokObjHashTable = NULL; | |
| 2696 } | |
| 2697 | |
| 2698 if (slot->sessObjHashTable) { | |
| 2699 PORT_Free(slot->sessObjHashTable); | |
| 2700 slot->sessObjHashTable = NULL; | |
| 2701 } | |
| 2702 slot->sessObjHashSize = 0; | |
| 2703 | |
| 2704 if (slot->head) { | |
| 2705 PORT_Free(slot->head); | |
| 2706 slot->head = NULL; | |
| 2707 } | |
| 2708 slot->sessHashSize = 0; | |
| 2709 | |
| 2710 /* OK everything has been disassembled, now we can finally get rid | |
| 2711 * of the locks */ | |
| 2712 SKIP_AFTER_FORK(PZ_DestroyLock(slot->slotLock)); | |
| 2713 slot->slotLock = NULL; | |
| 2714 if (slot->sessionLock) { | |
| 2715 for (i=0; i < slot->numSessionLocks; i++) { | |
| 2716 if (slot->sessionLock[i]) { | |
| 2717 SKIP_AFTER_FORK(PZ_DestroyLock(slot->sessionLock[i])); | |
| 2718 slot->sessionLock[i] = NULL; | |
| 2719 } | |
| 2720 } | |
| 2721 PORT_Free(slot->sessionLock); | |
| 2722 slot->sessionLock = NULL; | |
| 2723 } | |
| 2724 if (slot->objectLock) { | |
| 2725 SKIP_AFTER_FORK(PZ_DestroyLock(slot->objectLock)); | |
| 2726 slot->objectLock = NULL; | |
| 2727 } | |
| 2728 if (slot->pwCheckLock) { | |
| 2729 SKIP_AFTER_FORK(PR_DestroyLock(slot->pwCheckLock)); | |
| 2730 slot->pwCheckLock = NULL; | |
| 2731 } | |
| 2732 PORT_Free(slot); | |
| 2733 return CKR_OK; | |
| 2734 } | |
| 2735 | |
| 2736 /* | |
| 2737 * handle the SECMOD.db | |
| 2738 */ | |
| 2739 char ** | |
| 2740 NSC_ModuleDBFunc(unsigned long function,char *parameters, void *args) | |
| 2741 { | |
| 2742 char *secmod = NULL; | |
| 2743 char *appName = NULL; | |
| 2744 char *filename = NULL; | |
| 2745 NSSDBType dbType = NSS_DB_TYPE_NONE; | |
| 2746 PRBool rw; | |
| 2747 static char *success="Success"; | |
| 2748 char **rvstr = NULL; | |
| 2749 | |
| 2750 rvstr = NSSUTIL_DoModuleDBFunction(function, parameters, args); | |
| 2751 if (rvstr != NULL) { | |
| 2752 return rvstr; | |
| 2753 } | |
| 2754 | |
| 2755 if (PORT_GetError() != SEC_ERROR_LEGACY_DATABASE) { | |
| 2756 return NULL; | |
| 2757 } | |
| 2758 | |
| 2759 /* The legacy database uses the old dbm, which is only linked with the | |
| 2760 * legacy DB handler, which is only callable from softoken */ | |
| 2761 | |
| 2762 secmod = _NSSUTIL_GetSecmodName(parameters, &dbType, &appName, | |
| 2763 &filename, &rw); | |
| 2764 | |
| 2765 switch (function) { | |
| 2766 case SECMOD_MODULE_DB_FUNCTION_FIND: | |
| 2767 if (secmod == NULL) { | |
| 2768 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 2769 goto loser; | |
| 2770 } | |
| 2771 if (rw && (dbType != NSS_DB_TYPE_LEGACY) && | |
| 2772 (dbType != NSS_DB_TYPE_MULTIACCESS)) { | |
| 2773 /* if we get here, we are trying to update the local database */ | |
| 2774 /* force data from the legacy DB */ | |
| 2775 char *oldSecmod = NULL; | |
| 2776 char *oldAppName = NULL; | |
| 2777 char *oldFilename = NULL; | |
| 2778 PRBool oldrw; | |
| 2779 char **strings = NULL; | |
| 2780 int i; | |
| 2781 | |
| 2782 dbType = NSS_DB_TYPE_LEGACY; | |
| 2783 oldSecmod = _NSSUTIL_GetSecmodName(parameters,&dbType, &oldAppName, | |
| 2784 &oldFilename, &oldrw); | |
| 2785 strings = sftkdbCall_ReadSecmodDB(appName, oldFilename, oldSecmod, | |
| 2786 (char *)parameters, oldrw); | |
| 2787 if (strings) { | |
| 2788 /* write out the strings */ | |
| 2789 for (i=0; strings[i]; i++) { | |
| 2790 NSSUTIL_DoModuleDBFunction(SECMOD_MODULE_DB_FUNCTION_ADD, | |
| 2791 parameters, strings[i]); | |
| 2792 } | |
| 2793 sftkdbCall_ReleaseSecmodDBData(oldAppName,oldFilename,oldSecmod, | |
| 2794 (char **)strings,oldrw); | |
| 2795 } else { | |
| 2796 /* write out a dummy record */ | |
| 2797 NSSUTIL_DoModuleDBFunction(SECMOD_MODULE_DB_FUNCTION_ADD, | |
| 2798 parameters, " "); | |
| 2799 } | |
| 2800 if (oldSecmod) { PR_smprintf_free(oldSecmod); } | |
| 2801 if (oldAppName) { PORT_Free(oldAppName); } | |
| 2802 if (oldFilename) { PORT_Free(oldFilename); } | |
| 2803 rvstr = NSSUTIL_DoModuleDBFunction(function, parameters, args); | |
| 2804 break; | |
| 2805 } | |
| 2806 rvstr = sftkdbCall_ReadSecmodDB(appName,filename,secmod, | |
| 2807 (char *)parameters,rw); | |
| 2808 break; | |
| 2809 case SECMOD_MODULE_DB_FUNCTION_ADD: | |
| 2810 if (secmod == NULL) { | |
| 2811 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 2812 goto loser; | |
| 2813 } | |
| 2814 rvstr = (sftkdbCall_AddSecmodDB(appName,filename,secmod, | |
| 2815 (char *)args,rw) == SECSuccess) ? &success: NULL; | |
| 2816 break; | |
| 2817 case SECMOD_MODULE_DB_FUNCTION_DEL: | |
| 2818 if (secmod == NULL) { | |
| 2819 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 2820 goto loser; | |
| 2821 } | |
| 2822 rvstr = (sftkdbCall_DeleteSecmodDB(appName,filename,secmod, | |
| 2823 (char *)args,rw) == SECSuccess) ? &success: NULL; | |
| 2824 break; | |
| 2825 case SECMOD_MODULE_DB_FUNCTION_RELEASE: | |
| 2826 rvstr = (sftkdbCall_ReleaseSecmodDBData(appName,filename,secmod, | |
| 2827 (char **)args,rw) == SECSuccess) ? &success: NULL; | |
| 2828 break; | |
| 2829 } | |
| 2830 | |
| 2831 loser: | |
| 2832 if (secmod) PR_smprintf_free(secmod); | |
| 2833 if (appName) PORT_Free(appName); | |
| 2834 if (filename) PORT_Free(filename); | |
| 2835 return rvstr; | |
| 2836 } | |
| 2837 | |
| 2838 static void nscFreeAllSlots(int moduleIndex) | |
| 2839 { | |
| 2840 /* free all the slots */ | |
| 2841 SFTKSlot *slot = NULL; | |
| 2842 CK_SLOT_ID slotID; | |
| 2843 int i; | |
| 2844 | |
| 2845 if (nscSlotList[moduleIndex]) { | |
| 2846 CK_ULONG tmpSlotCount = nscSlotCount[moduleIndex]; | |
| 2847 CK_SLOT_ID_PTR tmpSlotList = nscSlotList[moduleIndex]; | |
| 2848 PLHashTable *tmpSlotHashTable = nscSlotHashTable[moduleIndex]; | |
| 2849 | |
| 2850 /* first close all the session */ | |
| 2851 for (i=0; i < (int) tmpSlotCount; i++) { | |
| 2852 slotID = tmpSlotList[i]; | |
| 2853 (void) NSC_CloseAllSessions(slotID); | |
| 2854 } | |
| 2855 | |
| 2856 /* now clear out the statics */ | |
| 2857 nscSlotList[moduleIndex] = NULL; | |
| 2858 nscSlotCount[moduleIndex] = 0; | |
| 2859 nscSlotHashTable[moduleIndex] = NULL; | |
| 2860 nscSlotListSize[moduleIndex] = 0; | |
| 2861 | |
| 2862 for (i=0; i < (int) tmpSlotCount; i++) { | |
| 2863 slotID = tmpSlotList[i]; | |
| 2864 slot = (SFTKSlot *) | |
| 2865 PL_HashTableLookup(tmpSlotHashTable, (void *)slotID); | |
| 2866 PORT_Assert(slot); | |
| 2867 if (!slot) continue; | |
| 2868 SFTK_DestroySlotData(slot); | |
| 2869 PL_HashTableRemove(tmpSlotHashTable, (void *)slotID); | |
| 2870 } | |
| 2871 PORT_Free(tmpSlotList); | |
| 2872 PL_HashTableDestroy(tmpSlotHashTable); | |
| 2873 } | |
| 2874 } | |
| 2875 | |
| 2876 static void | |
| 2877 sftk_closePeer(PRBool isFIPS) | |
| 2878 { | |
| 2879 CK_SLOT_ID slotID = isFIPS ? PRIVATE_KEY_SLOT_ID: FIPS_SLOT_ID; | |
| 2880 SFTKSlot *slot; | |
| 2881 int moduleIndex = isFIPS? NSC_NON_FIPS_MODULE : NSC_FIPS_MODULE; | |
| 2882 PLHashTable *tmpSlotHashTable = nscSlotHashTable[moduleIndex]; | |
| 2883 | |
| 2884 slot = (SFTKSlot *) PL_HashTableLookup(tmpSlotHashTable, (void *)slotID); | |
| 2885 if (slot == NULL) { | |
| 2886 return; | |
| 2887 } | |
| 2888 sftk_DBShutdown(slot); | |
| 2889 return; | |
| 2890 } | |
| 2891 | |
| 2892 /* NSC_Initialize initializes the Cryptoki library. */ | |
| 2893 CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) | |
| 2894 { | |
| 2895 CK_RV crv = CKR_OK; | |
| 2896 SECStatus rv; | |
| 2897 CK_C_INITIALIZE_ARGS *init_args = (CK_C_INITIALIZE_ARGS *) pReserved; | |
| 2898 int i; | |
| 2899 int moduleIndex = isFIPS? NSC_FIPS_MODULE : NSC_NON_FIPS_MODULE; | |
| 2900 | |
| 2901 if (isFIPS) { | |
| 2902 loginWaitTime = PR_SecondsToInterval(1); | |
| 2903 } | |
| 2904 | |
| 2905 ENABLE_FORK_CHECK(); | |
| 2906 | |
| 2907 rv = SECOID_Init(); | |
| 2908 if (rv != SECSuccess) { | |
| 2909 crv = CKR_DEVICE_ERROR; | |
| 2910 return crv; | |
| 2911 } | |
| 2912 | |
| 2913 rv = RNG_RNGInit(); /* initialize random number generator */ | |
| 2914 if (rv != SECSuccess) { | |
| 2915 crv = CKR_DEVICE_ERROR; | |
| 2916 return crv; | |
| 2917 } | |
| 2918 rv = BL_Init(); /* initialize freebl engine */ | |
| 2919 if (rv != SECSuccess) { | |
| 2920 crv = CKR_DEVICE_ERROR; | |
| 2921 return crv; | |
| 2922 } | |
| 2923 | |
| 2924 /* NOTE: | |
| 2925 * we should be getting out mutexes from this list, not statically binding | |
| 2926 * them from NSPR. This should happen before we allow the internal to split | |
| 2927 * off from the rest on NSS. | |
| 2928 */ | |
| 2929 | |
| 2930 /* initialize the key and cert db's */ | |
| 2931 if (init_args && (!(init_args->flags & CKF_OS_LOCKING_OK))) { | |
| 2932 if (init_args->CreateMutex && init_args->DestroyMutex && | |
| 2933 init_args->LockMutex && init_args->UnlockMutex) { | |
| 2934 /* softoken always uses NSPR (ie. OS locking), and doesn't know how | |
| 2935 * to use the lock functions provided by the application. | |
| 2936 */ | |
| 2937 crv = CKR_CANT_LOCK; | |
| 2938 return crv; | |
| 2939 } | |
| 2940 if (init_args->CreateMutex || init_args->DestroyMutex || | |
| 2941 init_args->LockMutex || init_args->UnlockMutex) { | |
| 2942 /* only some of the lock functions were provided by the | |
| 2943 * application. This is invalid per PKCS#11 spec. | |
| 2944 */ | |
| 2945 crv = CKR_ARGUMENTS_BAD; | |
| 2946 return crv; | |
| 2947 } | |
| 2948 } | |
| 2949 crv = CKR_ARGUMENTS_BAD; | |
| 2950 if ((init_args && init_args->LibraryParameters)) { | |
| 2951 sftk_parameters paramStrings; | |
| 2952 | |
| 2953 crv = sftk_parseParameters | |
| 2954 ((char *)init_args->LibraryParameters, ¶mStrings, isFIPS); | |
| 2955 if (crv != CKR_OK) { | |
| 2956 return crv; | |
| 2957 } | |
| 2958 crv = sftk_configure(paramStrings.man, paramStrings.libdes); | |
| 2959 if (crv != CKR_OK) { | |
| 2960 goto loser; | |
| 2961 } | |
| 2962 | |
| 2963 /* if we have a peer already open, have him close his DB's so we | |
| 2964 * don't clobber each other. */ | |
| 2965 if ((isFIPS && nsc_init) || (!isFIPS && nsf_init)) { | |
| 2966 sftk_closePeer(isFIPS); | |
| 2967 if (sftk_audit_enabled) { | |
| 2968 if (isFIPS && nsc_init) { | |
| 2969 sftk_LogAuditMessage(NSS_AUDIT_INFO, NSS_AUDIT_FIPS_STATE, | |
| 2970 "enabled FIPS mode"); | |
| 2971 } else { | |
| 2972 sftk_LogAuditMessage(NSS_AUDIT_INFO, NSS_AUDIT_FIPS_STATE, | |
| 2973 "disabled FIPS mode"); | |
| 2974 } | |
| 2975 } | |
| 2976 } | |
| 2977 | |
| 2978 for (i=0; i < paramStrings.token_count; i++) { | |
| 2979 crv = SFTK_SlotInit(paramStrings.configdir, | |
| 2980 paramStrings.updatedir, paramStrings.updateID, | |
| 2981 ¶mStrings.tokens[i], moduleIndex); | |
| 2982 if (crv != CKR_OK) { | |
| 2983 nscFreeAllSlots(moduleIndex); | |
| 2984 break; | |
| 2985 } | |
| 2986 } | |
| 2987 loser: | |
| 2988 sftk_freeParams(¶mStrings); | |
| 2989 } | |
| 2990 if (CKR_OK == crv) { | |
| 2991 sftk_InitFreeLists(); | |
| 2992 } | |
| 2993 | |
| 2994 #ifndef NO_FORK_CHECK | |
| 2995 if (CKR_OK == crv) { | |
| 2996 #if defined(CHECK_FORK_MIXED) | |
| 2997 /* Before Solaris 10, fork handlers are not unregistered at dlclose() | |
| 2998 * time. So, we only use pthread_atfork on Solaris 10 and later. For | |
| 2999 * earlier versions, we use PID checks. | |
| 3000 */ | |
| 3001 char buf[200]; | |
| 3002 int major = 0, minor = 0; | |
| 3003 | |
| 3004 long rv = sysinfo(SI_RELEASE, buf, sizeof(buf)); | |
| 3005 if (rv > 0 && rv < sizeof(buf)) { | |
| 3006 if (2 == sscanf(buf, "%d.%d", &major, &minor)) { | |
| 3007 /* Are we on Solaris 10 or greater ? */ | |
| 3008 if (major >5 || (5 == major && minor >= 10)) { | |
| 3009 /* we are safe to use pthread_atfork */ | |
| 3010 usePthread_atfork = PR_TRUE; | |
| 3011 } | |
| 3012 } | |
| 3013 } | |
| 3014 if (usePthread_atfork) { | |
| 3015 pthread_atfork(NULL, NULL, ForkedChild); | |
| 3016 } else { | |
| 3017 myPid = getpid(); | |
| 3018 } | |
| 3019 | |
| 3020 #elif defined(CHECK_FORK_PTHREAD) | |
| 3021 pthread_atfork(NULL, NULL, ForkedChild); | |
| 3022 #elif defined(CHECK_FORK_GETPID) | |
| 3023 myPid = getpid(); | |
| 3024 #else | |
| 3025 #error Incorrect fork check method. | |
| 3026 #endif | |
| 3027 } | |
| 3028 #endif | |
| 3029 return crv; | |
| 3030 } | |
| 3031 | |
| 3032 CK_RV NSC_Initialize(CK_VOID_PTR pReserved) | |
| 3033 { | |
| 3034 CK_RV crv; | |
| 3035 | |
| 3036 sftk_ForkReset(pReserved, &crv); | |
| 3037 | |
| 3038 if (nsc_init) { | |
| 3039 return CKR_CRYPTOKI_ALREADY_INITIALIZED; | |
| 3040 } | |
| 3041 crv = nsc_CommonInitialize(pReserved,PR_FALSE); | |
| 3042 nsc_init = (PRBool) (crv == CKR_OK); | |
| 3043 return crv; | |
| 3044 } | |
| 3045 | |
| 3046 | |
| 3047 /* NSC_Finalize indicates that an application is done with the | |
| 3048 * Cryptoki library.*/ | |
| 3049 CK_RV nsc_CommonFinalize (CK_VOID_PTR pReserved, PRBool isFIPS) | |
| 3050 { | |
| 3051 /* propagate the fork status to freebl and util */ | |
| 3052 BL_SetForkState(parentForkedAfterC_Initialize); | |
| 3053 UTIL_SetForkState(parentForkedAfterC_Initialize); | |
| 3054 | |
| 3055 nscFreeAllSlots(isFIPS ? NSC_FIPS_MODULE : NSC_NON_FIPS_MODULE); | |
| 3056 | |
| 3057 /* don't muck with the globals if our peer is still initialized */ | |
| 3058 if (isFIPS && nsc_init) { | |
| 3059 return CKR_OK; | |
| 3060 } | |
| 3061 if (!isFIPS && nsf_init) { | |
| 3062 return CKR_OK; | |
| 3063 } | |
| 3064 | |
| 3065 sftk_CleanupFreeLists(); | |
| 3066 sftkdb_Shutdown(); | |
| 3067 | |
| 3068 /* This function does not discard all our previously aquired entropy. */ | |
| 3069 RNG_RNGShutdown(); | |
| 3070 | |
| 3071 /* tell freeBL to clean up after itself */ | |
| 3072 BL_Cleanup(); | |
| 3073 | |
| 3074 /* reset fork status in freebl. We must do this before BL_Unload so that | |
| 3075 * this call doesn't force freebl to be reloaded. */ | |
| 3076 BL_SetForkState(PR_FALSE); | |
| 3077 | |
| 3078 /* unload freeBL shared library from memory. This may only decrement the | |
| 3079 * OS refcount if it's been loaded multiple times, eg. by libssl */ | |
| 3080 BL_Unload(); | |
| 3081 | |
| 3082 /* clean up the default OID table */ | |
| 3083 SECOID_Shutdown(); | |
| 3084 | |
| 3085 /* reset fork status in util */ | |
| 3086 UTIL_SetForkState(PR_FALSE); | |
| 3087 | |
| 3088 nsc_init = PR_FALSE; | |
| 3089 | |
| 3090 #ifdef CHECK_FORK_MIXED | |
| 3091 if (!usePthread_atfork) { | |
| 3092 myPid = 0; /* allow CHECK_FORK in the next softoken initialization to | |
| 3093 * succeed */ | |
| 3094 } else { | |
| 3095 forked = PR_FALSE; /* allow reinitialization */ | |
| 3096 } | |
| 3097 #elif defined(CHECK_FORK_GETPID) | |
| 3098 myPid = 0; /* allow reinitialization */ | |
| 3099 #elif defined (CHECK_FORK_PTHREAD) | |
| 3100 forked = PR_FALSE; /* allow reinitialization */ | |
| 3101 #endif | |
| 3102 return CKR_OK; | |
| 3103 } | |
| 3104 | |
| 3105 /* Hard-reset the entire softoken PKCS#11 module if the parent process forked | |
| 3106 * while it was initialized. */ | |
| 3107 PRBool sftk_ForkReset(CK_VOID_PTR pReserved, CK_RV* crv) | |
| 3108 { | |
| 3109 #ifndef NO_FORK_CHECK | |
| 3110 if (PARENT_FORKED()) { | |
| 3111 parentForkedAfterC_Initialize = PR_TRUE; | |
| 3112 if (nsc_init) { | |
| 3113 /* finalize non-FIPS token */ | |
| 3114 *crv = nsc_CommonFinalize(pReserved, PR_FALSE); | |
| 3115 PORT_Assert(CKR_OK == *crv); | |
| 3116 nsc_init = (PRBool) !(*crv == CKR_OK); | |
| 3117 } | |
| 3118 if (nsf_init) { | |
| 3119 /* finalize FIPS token */ | |
| 3120 *crv = nsc_CommonFinalize(pReserved, PR_TRUE); | |
| 3121 PORT_Assert(CKR_OK == *crv); | |
| 3122 nsf_init = (PRBool) !(*crv == CKR_OK); | |
| 3123 } | |
| 3124 parentForkedAfterC_Initialize = PR_FALSE; | |
| 3125 return PR_TRUE; | |
| 3126 } | |
| 3127 #endif | |
| 3128 return PR_FALSE; | |
| 3129 } | |
| 3130 | |
| 3131 /* NSC_Finalize indicates that an application is done with the | |
| 3132 * Cryptoki library.*/ | |
| 3133 CK_RV NSC_Finalize (CK_VOID_PTR pReserved) | |
| 3134 { | |
| 3135 CK_RV crv; | |
| 3136 | |
| 3137 /* reset entire PKCS#11 module upon fork */ | |
| 3138 if (sftk_ForkReset(pReserved, &crv)) { | |
| 3139 return crv; | |
| 3140 } | |
| 3141 | |
| 3142 if (!nsc_init) { | |
| 3143 return CKR_OK; | |
| 3144 } | |
| 3145 | |
| 3146 crv = nsc_CommonFinalize (pReserved, PR_FALSE); | |
| 3147 | |
| 3148 nsc_init = (PRBool) !(crv == CKR_OK); | |
| 3149 | |
| 3150 return crv; | |
| 3151 } | |
| 3152 | |
| 3153 extern const char __nss_softokn_version[]; | |
| 3154 | |
| 3155 /* NSC_GetInfo returns general information about Cryptoki. */ | |
| 3156 CK_RV NSC_GetInfo(CK_INFO_PTR pInfo) | |
| 3157 { | |
| 3158 #define NSS_VERSION_VARIABLE __nss_softokn_version | |
| 3159 #include "verref.h" | |
| 3160 | |
| 3161 CHECK_FORK(); | |
| 3162 | |
| 3163 pInfo->cryptokiVersion.major = 2; | |
| 3164 pInfo->cryptokiVersion.minor = 20; | |
| 3165 PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); | |
| 3166 pInfo->libraryVersion.major = SOFTOKEN_VMAJOR; | |
| 3167 pInfo->libraryVersion.minor = SOFTOKEN_VMINOR; | |
| 3168 PORT_Memcpy(pInfo->libraryDescription,libraryDescription,32); | |
| 3169 pInfo->flags = 0; | |
| 3170 return CKR_OK; | |
| 3171 } | |
| 3172 | |
| 3173 | |
| 3174 /* NSC_GetSlotList obtains a list of slots in the system. */ | |
| 3175 CK_RV nsc_CommonGetSlotList(CK_BBOOL tokenPresent, | |
| 3176 CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount, int moduleIndex) | |
| 3177 { | |
| 3178 *pulCount = nscSlotCount[moduleIndex]; | |
| 3179 if (pSlotList != NULL) { | |
| 3180 PORT_Memcpy(pSlotList,nscSlotList[moduleIndex], | |
| 3181 nscSlotCount[moduleIndex]*sizeof(CK_SLOT_ID)); | |
| 3182 } | |
| 3183 return CKR_OK; | |
| 3184 } | |
| 3185 | |
| 3186 /* NSC_GetSlotList obtains a list of slots in the system. */ | |
| 3187 CK_RV NSC_GetSlotList(CK_BBOOL tokenPresent, | |
| 3188 CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) | |
| 3189 { | |
| 3190 CHECK_FORK(); | |
| 3191 return nsc_CommonGetSlotList(tokenPresent, pSlotList, pulCount, | |
| 3192 NSC_NON_FIPS_MODULE); | |
| 3193 } | |
| 3194 | |
| 3195 /* NSC_GetSlotInfo obtains information about a particular slot in the system. */ | |
| 3196 CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) | |
| 3197 { | |
| 3198 SFTKSlot *slot = sftk_SlotFromID(slotID, PR_TRUE); | |
| 3199 | |
| 3200 CHECK_FORK(); | |
| 3201 | |
| 3202 if (slot == NULL) return CKR_SLOT_ID_INVALID; | |
| 3203 | |
| 3204 PORT_Memcpy(pInfo->manufacturerID,manufacturerID, | |
| 3205 sizeof(pInfo->manufacturerID)); | |
| 3206 PORT_Memcpy(pInfo->slotDescription,slot->slotDescription, | |
| 3207 sizeof(pInfo->slotDescription)); | |
| 3208 pInfo->flags = (slot->present) ? CKF_TOKEN_PRESENT : 0; | |
| 3209 | |
| 3210 /* all user defined slots are defined as removable */ | |
| 3211 if (slotID >= SFTK_MIN_USER_SLOT_ID) { | |
| 3212 pInfo->flags |= CKF_REMOVABLE_DEVICE; | |
| 3213 } else { | |
| 3214 /* In the case where we are doing a merge update, we need | |
| 3215 * the DB slot to be removable so the token name can change | |
| 3216 * appropriately. */ | |
| 3217 SFTKDBHandle *handle = sftk_getKeyDB(slot); | |
| 3218 if (handle) { | |
| 3219 if (sftkdb_InUpdateMerge(handle)) { | |
| 3220 pInfo->flags |= CKF_REMOVABLE_DEVICE; | |
| 3221 } | |
| 3222 sftk_freeDB(handle); | |
| 3223 } | |
| 3224 } | |
| 3225 | |
| 3226 /* ok we really should read it out of the keydb file. */ | |
| 3227 /* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */ | |
| 3228 pInfo->hardwareVersion.major = SOFTOKEN_VMAJOR; | |
| 3229 pInfo->hardwareVersion.minor = SOFTOKEN_VMINOR; | |
| 3230 pInfo->firmwareVersion.major = SOFTOKEN_VPATCH; | |
| 3231 pInfo->firmwareVersion.minor = SOFTOKEN_VBUILD; | |
| 3232 return CKR_OK; | |
| 3233 } | |
| 3234 | |
| 3235 /* | |
| 3236 * check the current state of the 'needLogin' flag in case the database has | |
| 3237 * been changed underneath us. | |
| 3238 */ | |
| 3239 static PRBool | |
| 3240 sftk_checkNeedLogin(SFTKSlot *slot, SFTKDBHandle *keyHandle) | |
| 3241 { | |
| 3242 if (sftkdb_PWCached(keyHandle) == SECSuccess) { | |
| 3243 return slot->needLogin; | |
| 3244 } | |
| 3245 slot->needLogin = (PRBool)!sftk_hasNullPassword(slot, keyHandle); | |
| 3246 return (slot->needLogin); | |
| 3247 } | |
| 3248 | |
| 3249 static PRBool | |
| 3250 sftk_isBlank(const char *s, int len) | |
| 3251 { | |
| 3252 int i; | |
| 3253 for (i=0; i < len; i++) { | |
| 3254 if (s[i] != ' ') { | |
| 3255 return PR_FALSE; | |
| 3256 } | |
| 3257 } | |
| 3258 return PR_TRUE; | |
| 3259 } | |
| 3260 | |
| 3261 /* NSC_GetTokenInfo obtains information about a particular token in | |
| 3262 * the system. */ | |
| 3263 CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) | |
| 3264 { | |
| 3265 SFTKSlot *slot; | |
| 3266 SFTKDBHandle *handle; | |
| 3267 | |
| 3268 CHECK_FORK(); | |
| 3269 | |
| 3270 if (!nsc_init && !nsf_init) return CKR_CRYPTOKI_NOT_INITIALIZED; | |
| 3271 slot = sftk_SlotFromID(slotID, PR_FALSE); | |
| 3272 if (slot == NULL) return CKR_SLOT_ID_INVALID; | |
| 3273 | |
| 3274 PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); | |
| 3275 PORT_Memcpy(pInfo->model,"NSS 3 ",16); | |
| 3276 PORT_Memcpy(pInfo->serialNumber,"0000000000000000",16); | |
| 3277 PORT_Memcpy(pInfo->utcTime,"0000000000000000",16); | |
| 3278 pInfo->ulMaxSessionCount = 0; /* arbitrarily large */ | |
| 3279 pInfo->ulSessionCount = slot->sessionCount; | |
| 3280 pInfo->ulMaxRwSessionCount = 0; /* arbitarily large */ | |
| 3281 pInfo->ulRwSessionCount = slot->rwSessionCount; | |
| 3282 pInfo->firmwareVersion.major = 0; | |
| 3283 pInfo->firmwareVersion.minor = 0; | |
| 3284 PORT_Memcpy(pInfo->label,slot->tokDescription,sizeof(pInfo->label)); | |
| 3285 handle = sftk_getKeyDB(slot); | |
| 3286 pInfo->flags = CKF_RNG | CKF_DUAL_CRYPTO_OPERATIONS; | |
| 3287 if (handle == NULL) { | |
| 3288 pInfo->flags |= CKF_WRITE_PROTECTED; | |
| 3289 pInfo->ulMaxPinLen = 0; | |
| 3290 pInfo->ulMinPinLen = 0; | |
| 3291 pInfo->ulTotalPublicMemory = 0; | |
| 3292 pInfo->ulFreePublicMemory = 0; | |
| 3293 pInfo->ulTotalPrivateMemory = 0; | |
| 3294 pInfo->ulFreePrivateMemory = 0; | |
| 3295 pInfo->hardwareVersion.major = 4; | |
| 3296 pInfo->hardwareVersion.minor = 0; | |
| 3297 } else { | |
| 3298 /* | |
| 3299 * we have three possible states which we may be in: | |
| 3300 * (1) No DB password has been initialized. This also means we | |
| 3301 * have no keys in the key db. | |
| 3302 * (2) Password initialized to NULL. This means we have keys, but | |
| 3303 * the user has chosen not use a password. | |
| 3304 * (3) Finally we have an initialized password whicn is not NULL, and | |
| 3305 * we will need to prompt for it. | |
| 3306 */ | |
| 3307 if (sftkdb_HasPasswordSet(handle) == SECFailure) { | |
| 3308 pInfo->flags |= CKF_LOGIN_REQUIRED; | |
| 3309 } else if (!sftk_checkNeedLogin(slot,handle)) { | |
| 3310 pInfo->flags |= CKF_USER_PIN_INITIALIZED; | |
| 3311 } else { | |
| 3312 pInfo->flags |= CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED; | |
| 3313 /* | |
| 3314 * if we are doing a merge style update, and we need to get the password | |
| 3315 * of our source database (the database we are updating from), make sure
we | |
| 3316 * return a token name that will match the database we are prompting for
. | |
| 3317 */ | |
| 3318 if (sftkdb_NeedUpdateDBPassword(handle)) { | |
| 3319 /* if we have an update tok description, use it. otherwise | |
| 3320 * use the updateID for this database */ | |
| 3321 if (!sftk_isBlank(slot->updateTokDescription, | |
| 3322 sizeof(pInfo->label))) { | |
| 3323 PORT_Memcpy(pInfo->label,slot->updateTokDescription, | |
| 3324 sizeof(pInfo->label)); | |
| 3325 } else { | |
| 3326 /* build from updateID */ | |
| 3327 const char *updateID = sftkdb_GetUpdateID(handle); | |
| 3328 if (updateID) { | |
| 3329 sftk_setStringName(updateID, (char *)pInfo->label, | |
| 3330 sizeof(pInfo->label), PR_FALSE); | |
| 3331 } | |
| 3332 } | |
| 3333 } | |
| 3334 } | |
| 3335 pInfo->ulMaxPinLen = SFTK_MAX_PIN; | |
| 3336 pInfo->ulMinPinLen = (CK_ULONG)slot->minimumPinLen; | |
| 3337 pInfo->ulTotalPublicMemory = 1; | |
| 3338 pInfo->ulFreePublicMemory = 1; | |
| 3339 pInfo->ulTotalPrivateMemory = 1; | |
| 3340 pInfo->ulFreePrivateMemory = 1; | |
| 3341 #ifdef SHDB_FIXME | |
| 3342 pInfo->hardwareVersion.major = CERT_DB_FILE_VERSION; | |
| 3343 pInfo->hardwareVersion.minor = handle->version; | |
| 3344 #else | |
| 3345 pInfo->hardwareVersion.major = 0; | |
| 3346 pInfo->hardwareVersion.minor = 0; | |
| 3347 #endif | |
| 3348 sftk_freeDB(handle); | |
| 3349 } | |
| 3350 /* | |
| 3351 * CKF_LOGIN_REQUIRED CKF_USER_PIN_INITIALIZED how CKF_TOKEN_INITIALIZED | |
| 3352 * should be set | |
| 3353 * 0 0 1 | |
| 3354 * 1 0 0 | |
| 3355 * 0 1 1 | |
| 3356 * 1 1 1 | |
| 3357 */ | |
| 3358 if (!(pInfo->flags & CKF_LOGIN_REQUIRED) || | |
| 3359 (pInfo->flags & CKF_USER_PIN_INITIALIZED)) { | |
| 3360 pInfo->flags |= CKF_TOKEN_INITIALIZED; | |
| 3361 } | |
| 3362 return CKR_OK; | |
| 3363 } | |
| 3364 | |
| 3365 /* NSC_GetMechanismList obtains a list of mechanism types | |
| 3366 * supported by a token. */ | |
| 3367 CK_RV NSC_GetMechanismList(CK_SLOT_ID slotID, | |
| 3368 CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount) | |
| 3369 { | |
| 3370 CK_ULONG i; | |
| 3371 | |
| 3372 CHECK_FORK(); | |
| 3373 | |
| 3374 switch (slotID) { | |
| 3375 /* default: */ | |
| 3376 case NETSCAPE_SLOT_ID: | |
| 3377 *pulCount = mechanismCount; | |
| 3378 if (pMechanismList != NULL) { | |
| 3379 for (i=0; i < mechanismCount; i++) { | |
| 3380 pMechanismList[i] = mechanisms[i].type; | |
| 3381 } | |
| 3382 } | |
| 3383 break; | |
| 3384 default: | |
| 3385 *pulCount = 0; | |
| 3386 for (i=0; i < mechanismCount; i++) { | |
| 3387 if (mechanisms[i].privkey) { | |
| 3388 (*pulCount)++; | |
| 3389 if (pMechanismList != NULL) { | |
| 3390 *pMechanismList++ = mechanisms[i].type; | |
| 3391 } | |
| 3392 } | |
| 3393 } | |
| 3394 break; | |
| 3395 } | |
| 3396 return CKR_OK; | |
| 3397 } | |
| 3398 | |
| 3399 | |
| 3400 /* NSC_GetMechanismInfo obtains information about a particular mechanism | |
| 3401 * possibly supported by a token. */ | |
| 3402 CK_RV NSC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, | |
| 3403 CK_MECHANISM_INFO_PTR pInfo) | |
| 3404 { | |
| 3405 PRBool isPrivateKey; | |
| 3406 CK_ULONG i; | |
| 3407 | |
| 3408 CHECK_FORK(); | |
| 3409 | |
| 3410 switch (slotID) { | |
| 3411 case NETSCAPE_SLOT_ID: | |
| 3412 isPrivateKey = PR_FALSE; | |
| 3413 break; | |
| 3414 default: | |
| 3415 isPrivateKey = PR_TRUE; | |
| 3416 break; | |
| 3417 } | |
| 3418 for (i=0; i < mechanismCount; i++) { | |
| 3419 if (type == mechanisms[i].type) { | |
| 3420 if (isPrivateKey && !mechanisms[i].privkey) { | |
| 3421 return CKR_MECHANISM_INVALID; | |
| 3422 } | |
| 3423 PORT_Memcpy(pInfo,&mechanisms[i].info, sizeof(CK_MECHANISM_INFO)); | |
| 3424 return CKR_OK; | |
| 3425 } | |
| 3426 } | |
| 3427 return CKR_MECHANISM_INVALID; | |
| 3428 } | |
| 3429 | |
| 3430 CK_RV sftk_MechAllowsOperation(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE op) | |
| 3431 { | |
| 3432 CK_ULONG i; | |
| 3433 CK_FLAGS flags; | |
| 3434 | |
| 3435 switch (op) { | |
| 3436 case CKA_ENCRYPT: flags = CKF_ENCRYPT; break; | |
| 3437 case CKA_DECRYPT: flags = CKF_DECRYPT; break; | |
| 3438 case CKA_WRAP: flags = CKF_WRAP; break; | |
| 3439 case CKA_UNWRAP: flags = CKF_UNWRAP; break; | |
| 3440 case CKA_SIGN: flags = CKF_SIGN; break; | |
| 3441 case CKA_SIGN_RECOVER: flags = CKF_SIGN_RECOVER; break; | |
| 3442 case CKA_VERIFY: flags = CKF_VERIFY; break; | |
| 3443 case CKA_VERIFY_RECOVER: flags = CKF_VERIFY_RECOVER; break; | |
| 3444 case CKA_DERIVE: flags = CKF_DERIVE; break; | |
| 3445 default: | |
| 3446 return CKR_ARGUMENTS_BAD; | |
| 3447 } | |
| 3448 for (i=0; i < mechanismCount; i++) { | |
| 3449 if (type == mechanisms[i].type) { | |
| 3450 return (flags & mechanisms[i].info.flags) ? CKR_OK | |
| 3451 : CKR_MECHANISM_INVALID; | |
| 3452 } | |
| 3453 } | |
| 3454 return CKR_MECHANISM_INVALID; | |
| 3455 } | |
| 3456 | |
| 3457 /* NSC_InitToken initializes a token. */ | |
| 3458 CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin, | |
| 3459 CK_ULONG ulPinLen,CK_CHAR_PTR pLabel) { | |
| 3460 SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE); | |
| 3461 SFTKDBHandle *handle; | |
| 3462 SFTKDBHandle *certHandle; | |
| 3463 SECStatus rv; | |
| 3464 unsigned int i; | |
| 3465 SFTKObject *object; | |
| 3466 | |
| 3467 CHECK_FORK(); | |
| 3468 | |
| 3469 if (slot == NULL) return CKR_SLOT_ID_INVALID; | |
| 3470 | |
| 3471 /* don't initialize the database if we aren't talking to a token | |
| 3472 * that uses the key database. | |
| 3473 */ | |
| 3474 if (slotID == NETSCAPE_SLOT_ID) { | |
| 3475 return CKR_TOKEN_WRITE_PROTECTED; | |
| 3476 } | |
| 3477 | |
| 3478 /* first, delete all our loaded key and cert objects from our | |
| 3479 * internal list. */ | |
| 3480 PZ_Lock(slot->objectLock); | |
| 3481 for (i=0; i < slot->sessObjHashSize; i++) { | |
| 3482 do { | |
| 3483 object = slot->sessObjHashTable[i]; | |
| 3484 /* hand deque */ | |
| 3485 /* this duplicates function of NSC_close session functions, but | |
| 3486 * because we know that we are freeing all the sessions, we can | |
| 3487 * do more efficient processing */ | |
| 3488 if (object) { | |
| 3489 slot->sessObjHashTable[i] = object->next; | |
| 3490 | |
| 3491 if (object->next) object->next->prev = NULL; | |
| 3492 object->next = object->prev = NULL; | |
| 3493 } | |
| 3494 if (object) sftk_FreeObject(object); | |
| 3495 } while (object != NULL); | |
| 3496 } | |
| 3497 slot->DB_loaded = PR_FALSE; | |
| 3498 PZ_Unlock(slot->objectLock); | |
| 3499 | |
| 3500 /* then clear out the key database */ | |
| 3501 handle = sftk_getKeyDB(slot); | |
| 3502 if (handle == NULL) { | |
| 3503 return CKR_TOKEN_WRITE_PROTECTED; | |
| 3504 } | |
| 3505 | |
| 3506 rv = sftkdb_ResetKeyDB(handle); | |
| 3507 sftk_freeDB(handle); | |
| 3508 if (rv != SECSuccess) { | |
| 3509 return CKR_DEVICE_ERROR; | |
| 3510 } | |
| 3511 | |
| 3512 /* finally mark all the user certs as non-user certs */ | |
| 3513 certHandle = sftk_getCertDB(slot); | |
| 3514 if (certHandle == NULL) return CKR_OK; | |
| 3515 | |
| 3516 sftk_freeDB(certHandle); | |
| 3517 | |
| 3518 return CKR_OK; /*is this the right function for not implemented*/ | |
| 3519 } | |
| 3520 | |
| 3521 | |
| 3522 /* NSC_InitPIN initializes the normal user's PIN. */ | |
| 3523 CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession, | |
| 3524 CK_CHAR_PTR pPin, CK_ULONG ulPinLen) | |
| 3525 { | |
| 3526 SFTKSession *sp = NULL; | |
| 3527 SFTKSlot *slot; | |
| 3528 SFTKDBHandle *handle = NULL; | |
| 3529 char newPinStr[SFTK_MAX_PIN+1]; | |
| 3530 SECStatus rv; | |
| 3531 CK_RV crv = CKR_SESSION_HANDLE_INVALID; | |
| 3532 PRBool tokenRemoved = PR_FALSE; | |
| 3533 | |
| 3534 CHECK_FORK(); | |
| 3535 | |
| 3536 sp = sftk_SessionFromHandle(hSession); | |
| 3537 if (sp == NULL) { | |
| 3538 goto loser; | |
| 3539 } | |
| 3540 | |
| 3541 slot = sftk_SlotFromSession(sp); | |
| 3542 if (slot == NULL) { | |
| 3543 goto loser; | |
| 3544 } | |
| 3545 | |
| 3546 handle = sftk_getKeyDB(slot); | |
| 3547 if (handle == NULL) { | |
| 3548 crv = CKR_PIN_LEN_RANGE; | |
| 3549 goto loser; | |
| 3550 } | |
| 3551 | |
| 3552 | |
| 3553 if (sp->info.state != CKS_RW_SO_FUNCTIONS) { | |
| 3554 crv = CKR_USER_NOT_LOGGED_IN; | |
| 3555 goto loser; | |
| 3556 } | |
| 3557 | |
| 3558 sftk_FreeSession(sp); | |
| 3559 sp = NULL; | |
| 3560 | |
| 3561 /* make sure the pins aren't too long */ | |
| 3562 if (ulPinLen > SFTK_MAX_PIN) { | |
| 3563 crv = CKR_PIN_LEN_RANGE; | |
| 3564 goto loser; | |
| 3565 } | |
| 3566 if (ulPinLen < (CK_ULONG)slot->minimumPinLen) { | |
| 3567 crv = CKR_PIN_LEN_RANGE; | |
| 3568 goto loser; | |
| 3569 } | |
| 3570 | |
| 3571 if (sftkdb_HasPasswordSet(handle) != SECFailure) { | |
| 3572 crv = CKR_DEVICE_ERROR; | |
| 3573 goto loser; | |
| 3574 } | |
| 3575 | |
| 3576 /* convert to null terminated string */ | |
| 3577 PORT_Memcpy(newPinStr, pPin, ulPinLen); | |
| 3578 newPinStr[ulPinLen] = 0; | |
| 3579 | |
| 3580 /* build the hashed pins which we pass around */ | |
| 3581 | |
| 3582 /* change the data base */ | |
| 3583 rv = sftkdb_ChangePassword(handle, NULL, newPinStr, &tokenRemoved); | |
| 3584 if (tokenRemoved) { | |
| 3585 sftk_CloseAllSessions(slot, PR_FALSE); | |
| 3586 } | |
| 3587 sftk_freeDB(handle); | |
| 3588 handle = NULL; | |
| 3589 | |
| 3590 /* Now update our local copy of the pin */ | |
| 3591 if (rv == SECSuccess) { | |
| 3592 if (ulPinLen == 0) slot->needLogin = PR_FALSE; | |
| 3593 return CKR_OK; | |
| 3594 } | |
| 3595 crv = CKR_PIN_INCORRECT; | |
| 3596 | |
| 3597 loser: | |
| 3598 if (sp) { | |
| 3599 sftk_FreeSession(sp); | |
| 3600 } | |
| 3601 if (handle) { | |
| 3602 sftk_freeDB(handle); | |
| 3603 } | |
| 3604 return crv; | |
| 3605 } | |
| 3606 | |
| 3607 | |
| 3608 /* NSC_SetPIN modifies the PIN of user that is currently logged in. */ | |
| 3609 /* NOTE: This is only valid for the PRIVATE_KEY_SLOT */ | |
| 3610 CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, | |
| 3611 CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen) | |
| 3612 { | |
| 3613 SFTKSession *sp = NULL; | |
| 3614 SFTKSlot *slot; | |
| 3615 SFTKDBHandle *handle = NULL; | |
| 3616 char newPinStr[SFTK_MAX_PIN+1],oldPinStr[SFTK_MAX_PIN+1]; | |
| 3617 SECStatus rv; | |
| 3618 CK_RV crv = CKR_SESSION_HANDLE_INVALID; | |
| 3619 PRBool tokenRemoved = PR_FALSE; | |
| 3620 | |
| 3621 CHECK_FORK(); | |
| 3622 | |
| 3623 sp = sftk_SessionFromHandle(hSession); | |
| 3624 if (sp == NULL) { | |
| 3625 goto loser; | |
| 3626 } | |
| 3627 | |
| 3628 slot = sftk_SlotFromSession(sp); | |
| 3629 if (!slot) { | |
| 3630 goto loser; | |
| 3631 } | |
| 3632 | |
| 3633 handle = sftk_getKeyDB(slot); | |
| 3634 if (handle == NULL) { | |
| 3635 sftk_FreeSession(sp); | |
| 3636 return CKR_PIN_LEN_RANGE; /* XXX FIXME wrong return value */ | |
| 3637 } | |
| 3638 | |
| 3639 if (slot->needLogin && sp->info.state != CKS_RW_USER_FUNCTIONS) { | |
| 3640 crv = CKR_USER_NOT_LOGGED_IN; | |
| 3641 goto loser; | |
| 3642 } | |
| 3643 | |
| 3644 sftk_FreeSession(sp); | |
| 3645 sp = NULL; | |
| 3646 | |
| 3647 /* make sure the pins aren't too long */ | |
| 3648 if ((ulNewLen > SFTK_MAX_PIN) || (ulOldLen > SFTK_MAX_PIN)) { | |
| 3649 crv = CKR_PIN_LEN_RANGE; | |
| 3650 goto loser; | |
| 3651 } | |
| 3652 if (ulNewLen < (CK_ULONG)slot->minimumPinLen) { | |
| 3653 crv = CKR_PIN_LEN_RANGE; | |
| 3654 goto loser; | |
| 3655 } | |
| 3656 | |
| 3657 | |
| 3658 /* convert to null terminated string */ | |
| 3659 PORT_Memcpy(newPinStr,pNewPin,ulNewLen); | |
| 3660 newPinStr[ulNewLen] = 0; | |
| 3661 PORT_Memcpy(oldPinStr,pOldPin,ulOldLen); | |
| 3662 oldPinStr[ulOldLen] = 0; | |
| 3663 | |
| 3664 /* change the data base password */ | |
| 3665 PR_Lock(slot->pwCheckLock); | |
| 3666 rv = sftkdb_ChangePassword(handle, oldPinStr, newPinStr, &tokenRemoved); | |
| 3667 if (tokenRemoved) { | |
| 3668 sftk_CloseAllSessions(slot, PR_FALSE); | |
| 3669 } | |
| 3670 if ((rv != SECSuccess) && (slot->slotID == FIPS_SLOT_ID)) { | |
| 3671 PR_Sleep(loginWaitTime); | |
| 3672 } | |
| 3673 PR_Unlock(slot->pwCheckLock); | |
| 3674 | |
| 3675 /* Now update our local copy of the pin */ | |
| 3676 if (rv == SECSuccess) { | |
| 3677 slot->needLogin = (PRBool)(ulNewLen != 0); | |
| 3678 /* Reset login flags. */ | |
| 3679 if (ulNewLen == 0) { | |
| 3680 PRBool tokenRemoved = PR_FALSE; | |
| 3681 PZ_Lock(slot->slotLock); | |
| 3682 slot->isLoggedIn = PR_FALSE; | |
| 3683 slot->ssoLoggedIn = PR_FALSE; | |
| 3684 PZ_Unlock(slot->slotLock); | |
| 3685 | |
| 3686 rv = sftkdb_CheckPassword(handle, "", &tokenRemoved); | |
| 3687 if (tokenRemoved) { | |
| 3688 sftk_CloseAllSessions(slot, PR_FALSE); | |
| 3689 } | |
| 3690 } | |
| 3691 sftk_update_all_states(slot); | |
| 3692 sftk_freeDB(handle); | |
| 3693 return CKR_OK; | |
| 3694 } | |
| 3695 crv = CKR_PIN_INCORRECT; | |
| 3696 loser: | |
| 3697 if (sp) { | |
| 3698 sftk_FreeSession(sp); | |
| 3699 } | |
| 3700 if (handle) { | |
| 3701 sftk_freeDB(handle); | |
| 3702 } | |
| 3703 return crv; | |
| 3704 } | |
| 3705 | |
| 3706 /* NSC_OpenSession opens a session between an application and a token. */ | |
| 3707 CK_RV NSC_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, | |
| 3708 CK_VOID_PTR pApplication,CK_NOTIFY Notify,CK_SESSION_HANDLE_PTR phSession) | |
| 3709 { | |
| 3710 SFTKSlot *slot; | |
| 3711 CK_SESSION_HANDLE sessionID; | |
| 3712 SFTKSession *session; | |
| 3713 SFTKSession *sameID; | |
| 3714 | |
| 3715 CHECK_FORK(); | |
| 3716 | |
| 3717 slot = sftk_SlotFromID(slotID, PR_FALSE); | |
| 3718 if (slot == NULL) return CKR_SLOT_ID_INVALID; | |
| 3719 | |
| 3720 /* new session (we only have serial sessions) */ | |
| 3721 session = sftk_NewSession(slotID, Notify, pApplication, | |
| 3722 flags | CKF_SERIAL_SESSION); | |
| 3723 if (session == NULL) return CKR_HOST_MEMORY; | |
| 3724 | |
| 3725 if (slot->readOnly && (flags & CKF_RW_SESSION)) { | |
| 3726 /* NETSCAPE_SLOT_ID is Read ONLY */ | |
| 3727 session->info.flags &= ~CKF_RW_SESSION; | |
| 3728 } | |
| 3729 PZ_Lock(slot->slotLock); | |
| 3730 ++slot->sessionCount; | |
| 3731 PZ_Unlock(slot->slotLock); | |
| 3732 if (session->info.flags & CKF_RW_SESSION) { | |
| 3733 (void)PR_ATOMIC_INCREMENT(&slot->rwSessionCount); | |
| 3734 } | |
| 3735 | |
| 3736 do { | |
| 3737 PZLock *lock; | |
| 3738 do { | |
| 3739 sessionID = (PR_ATOMIC_INCREMENT(&slot->sessionIDCount) & 0xffffff) | |
| 3740 | (slot->index << 24); | |
| 3741 } while (sessionID == CK_INVALID_HANDLE); | |
| 3742 lock = SFTK_SESSION_LOCK(slot,sessionID); | |
| 3743 PZ_Lock(lock); | |
| 3744 sftkqueue_find(sameID, sessionID, slot->head, slot->sessHashSize); | |
| 3745 if (sameID == NULL) { | |
| 3746 session->handle = sessionID; | |
| 3747 sftk_update_state(slot, session); | |
| 3748 sftkqueue_add(session, sessionID, slot->head,slot->sessHashSize); | |
| 3749 } else { | |
| 3750 slot->sessionIDConflict++; /* for debugging */ | |
| 3751 } | |
| 3752 PZ_Unlock(lock); | |
| 3753 } while (sameID != NULL); | |
| 3754 | |
| 3755 *phSession = sessionID; | |
| 3756 return CKR_OK; | |
| 3757 } | |
| 3758 | |
| 3759 | |
| 3760 /* NSC_CloseSession closes a session between an application and a token. */ | |
| 3761 CK_RV NSC_CloseSession(CK_SESSION_HANDLE hSession) | |
| 3762 { | |
| 3763 SFTKSlot *slot; | |
| 3764 SFTKSession *session; | |
| 3765 PRBool sessionFound; | |
| 3766 PZLock *lock; | |
| 3767 | |
| 3768 CHECK_FORK(); | |
| 3769 | |
| 3770 session = sftk_SessionFromHandle(hSession); | |
| 3771 if (session == NULL) return CKR_SESSION_HANDLE_INVALID; | |
| 3772 slot = sftk_SlotFromSession(session); | |
| 3773 sessionFound = PR_FALSE; | |
| 3774 | |
| 3775 /* lock */ | |
| 3776 lock = SFTK_SESSION_LOCK(slot,hSession); | |
| 3777 PZ_Lock(lock); | |
| 3778 if (sftkqueue_is_queued(session,hSession,slot->head,slot->sessHashSize)) { | |
| 3779 sessionFound = PR_TRUE; | |
| 3780 sftkqueue_delete(session,hSession,slot->head,slot->sessHashSize); | |
| 3781 session->refCount--; /* can't go to zero while we hold the reference */ | |
| 3782 PORT_Assert(session->refCount > 0); | |
| 3783 } | |
| 3784 PZ_Unlock(lock); | |
| 3785 | |
| 3786 if (sessionFound) { | |
| 3787 SFTKDBHandle *handle; | |
| 3788 handle = sftk_getKeyDB(slot); | |
| 3789 PZ_Lock(slot->slotLock); | |
| 3790 if (--slot->sessionCount == 0) { | |
| 3791 slot->isLoggedIn = PR_FALSE; | |
| 3792 if (slot->needLogin && handle) { | |
| 3793 sftkdb_ClearPassword(handle); | |
| 3794 } | |
| 3795 } | |
| 3796 PZ_Unlock(slot->slotLock); | |
| 3797 if (handle) { | |
| 3798 sftk_freeDB(handle); | |
| 3799 } | |
| 3800 if (session->info.flags & CKF_RW_SESSION) { | |
| 3801 (void)PR_ATOMIC_DECREMENT(&slot->rwSessionCount); | |
| 3802 } | |
| 3803 } | |
| 3804 | |
| 3805 sftk_FreeSession(session); | |
| 3806 return CKR_OK; | |
| 3807 } | |
| 3808 | |
| 3809 | |
| 3810 /* NSC_CloseAllSessions closes all sessions with a token. */ | |
| 3811 CK_RV NSC_CloseAllSessions (CK_SLOT_ID slotID) | |
| 3812 { | |
| 3813 SFTKSlot *slot; | |
| 3814 | |
| 3815 #ifndef NO_FORK_CHECK | |
| 3816 /* skip fork check if we are being called from C_Initialize or C_Finalize */ | |
| 3817 if (!parentForkedAfterC_Initialize) { | |
| 3818 CHECK_FORK(); | |
| 3819 } | |
| 3820 #endif | |
| 3821 | |
| 3822 slot = sftk_SlotFromID(slotID, PR_FALSE); | |
| 3823 if (slot == NULL) return CKR_SLOT_ID_INVALID; | |
| 3824 | |
| 3825 return sftk_CloseAllSessions(slot, PR_TRUE); | |
| 3826 } | |
| 3827 | |
| 3828 | |
| 3829 | |
| 3830 /* NSC_GetSessionInfo obtains information about the session. */ | |
| 3831 CK_RV NSC_GetSessionInfo(CK_SESSION_HANDLE hSession, | |
| 3832 CK_SESSION_INFO_PTR pInfo) | |
| 3833 { | |
| 3834 SFTKSession *session; | |
| 3835 | |
| 3836 CHECK_FORK(); | |
| 3837 | |
| 3838 session = sftk_SessionFromHandle(hSession); | |
| 3839 if (session == NULL) return CKR_SESSION_HANDLE_INVALID; | |
| 3840 | |
| 3841 PORT_Memcpy(pInfo,&session->info,sizeof(CK_SESSION_INFO)); | |
| 3842 sftk_FreeSession(session); | |
| 3843 return CKR_OK; | |
| 3844 } | |
| 3845 | |
| 3846 /* NSC_Login logs a user into a token. */ | |
| 3847 CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, | |
| 3848 CK_CHAR_PTR pPin, CK_ULONG ulPinLen) | |
| 3849 { | |
| 3850 SFTKSlot *slot; | |
| 3851 SFTKSession *session; | |
| 3852 SFTKDBHandle *handle; | |
| 3853 CK_FLAGS sessionFlags; | |
| 3854 SECStatus rv; | |
| 3855 CK_RV crv; | |
| 3856 char pinStr[SFTK_MAX_PIN+1]; | |
| 3857 PRBool tokenRemoved = PR_FALSE; | |
| 3858 | |
| 3859 CHECK_FORK(); | |
| 3860 | |
| 3861 /* get the slot */ | |
| 3862 slot = sftk_SlotFromSessionHandle(hSession); | |
| 3863 if (slot == NULL) { | |
| 3864 return CKR_SESSION_HANDLE_INVALID; | |
| 3865 } | |
| 3866 | |
| 3867 /* make sure the session is valid */ | |
| 3868 session = sftk_SessionFromHandle(hSession); | |
| 3869 if (session == NULL) { | |
| 3870 return CKR_SESSION_HANDLE_INVALID; | |
| 3871 } | |
| 3872 sessionFlags = session->info.flags; | |
| 3873 sftk_FreeSession(session); | |
| 3874 session = NULL; | |
| 3875 | |
| 3876 /* can't log into the Netscape Slot */ | |
| 3877 if (slot->slotID == NETSCAPE_SLOT_ID) { | |
| 3878 return CKR_USER_TYPE_INVALID; | |
| 3879 } | |
| 3880 | |
| 3881 if (slot->isLoggedIn) return CKR_USER_ALREADY_LOGGED_IN; | |
| 3882 if (!slot->needLogin) { | |
| 3883 return ulPinLen ? CKR_PIN_INCORRECT : CKR_OK; | |
| 3884 } | |
| 3885 slot->ssoLoggedIn = PR_FALSE; | |
| 3886 | |
| 3887 if (ulPinLen > SFTK_MAX_PIN) return CKR_PIN_LEN_RANGE; | |
| 3888 | |
| 3889 /* convert to null terminated string */ | |
| 3890 PORT_Memcpy(pinStr,pPin,ulPinLen); | |
| 3891 pinStr[ulPinLen] = 0; | |
| 3892 | |
| 3893 handle = sftk_getKeyDB(slot); | |
| 3894 if (handle == NULL) { | |
| 3895 return CKR_USER_TYPE_INVALID; | |
| 3896 } | |
| 3897 | |
| 3898 /* | |
| 3899 * Deal with bootstrap. We allow the SSO to login in with a NULL | |
| 3900 * password if and only if we haven't initialized the KEY DB yet. | |
| 3901 * We only allow this on a RW session. | |
| 3902 */ | |
| 3903 rv = sftkdb_HasPasswordSet(handle); | |
| 3904 if (rv == SECFailure) { | |
| 3905 /* allow SSO's to log in only if there is not password on the | |
| 3906 * key database */ | |
| 3907 if (((userType == CKU_SO) && (sessionFlags & CKF_RW_SESSION)) | |
| 3908 /* fips always needs to authenticate, even if there isn't a db */ | |
| 3909 || (slot->slotID == FIPS_SLOT_ID)) { | |
| 3910 /* should this be a fixed password? */ | |
| 3911 if (ulPinLen == 0) { | |
| 3912 sftkdb_ClearPassword(handle); | |
| 3913 PZ_Lock(slot->slotLock); | |
| 3914 slot->isLoggedIn = PR_TRUE; | |
| 3915 slot->ssoLoggedIn = (PRBool)(userType == CKU_SO); | |
| 3916 PZ_Unlock(slot->slotLock); | |
| 3917 sftk_update_all_states(slot); | |
| 3918 crv = CKR_OK; | |
| 3919 goto done; | |
| 3920 } | |
| 3921 crv = CKR_PIN_INCORRECT; | |
| 3922 goto done; | |
| 3923 } | |
| 3924 crv = CKR_USER_TYPE_INVALID; | |
| 3925 goto done; | |
| 3926 } | |
| 3927 | |
| 3928 /* don't allow the SSO to log in if the user is already initialized */ | |
| 3929 if (userType != CKU_USER) { | |
| 3930 crv = CKR_USER_TYPE_INVALID; | |
| 3931 goto done; | |
| 3932 } | |
| 3933 | |
| 3934 | |
| 3935 /* build the hashed pins which we pass around */ | |
| 3936 PR_Lock(slot->pwCheckLock); | |
| 3937 rv = sftkdb_CheckPassword(handle,pinStr, &tokenRemoved); | |
| 3938 if (tokenRemoved) { | |
| 3939 sftk_CloseAllSessions(slot, PR_FALSE); | |
| 3940 } | |
| 3941 if ((rv != SECSuccess) && (slot->slotID == FIPS_SLOT_ID)) { | |
| 3942 PR_Sleep(loginWaitTime); | |
| 3943 } | |
| 3944 PR_Unlock(slot->pwCheckLock); | |
| 3945 if (rv == SECSuccess) { | |
| 3946 PZ_Lock(slot->slotLock); | |
| 3947 /* make sure the login state matches the underlying | |
| 3948 * database state */ | |
| 3949 slot->isLoggedIn = sftkdb_PWCached(handle) == SECSuccess ? | |
| 3950 PR_TRUE : PR_FALSE; | |
| 3951 PZ_Unlock(slot->slotLock); | |
| 3952 | |
| 3953 sftk_freeDB(handle); | |
| 3954 handle = NULL; | |
| 3955 | |
| 3956 /* update all sessions */ | |
| 3957 sftk_update_all_states(slot); | |
| 3958 return CKR_OK; | |
| 3959 } | |
| 3960 | |
| 3961 crv = CKR_PIN_INCORRECT; | |
| 3962 done: | |
| 3963 if (handle) { | |
| 3964 sftk_freeDB(handle); | |
| 3965 } | |
| 3966 return crv; | |
| 3967 } | |
| 3968 | |
| 3969 /* NSC_Logout logs a user out from a token. */ | |
| 3970 CK_RV NSC_Logout(CK_SESSION_HANDLE hSession) | |
| 3971 { | |
| 3972 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); | |
| 3973 SFTKSession *session; | |
| 3974 SFTKDBHandle *handle; | |
| 3975 | |
| 3976 CHECK_FORK(); | |
| 3977 | |
| 3978 if (slot == NULL) { | |
| 3979 return CKR_SESSION_HANDLE_INVALID; | |
| 3980 } | |
| 3981 session = sftk_SessionFromHandle(hSession); | |
| 3982 if (session == NULL) return CKR_SESSION_HANDLE_INVALID; | |
| 3983 sftk_FreeSession(session); | |
| 3984 session = NULL; | |
| 3985 | |
| 3986 if (!slot->isLoggedIn) return CKR_USER_NOT_LOGGED_IN; | |
| 3987 | |
| 3988 handle = sftk_getKeyDB(slot); | |
| 3989 PZ_Lock(slot->slotLock); | |
| 3990 slot->isLoggedIn = PR_FALSE; | |
| 3991 slot->ssoLoggedIn = PR_FALSE; | |
| 3992 if (slot->needLogin && handle) { | |
| 3993 sftkdb_ClearPassword(handle); | |
| 3994 } | |
| 3995 PZ_Unlock(slot->slotLock); | |
| 3996 if (handle) { | |
| 3997 sftk_freeDB(handle); | |
| 3998 } | |
| 3999 | |
| 4000 sftk_update_all_states(slot); | |
| 4001 return CKR_OK; | |
| 4002 } | |
| 4003 | |
| 4004 /* | |
| 4005 * Create or remove a new slot on the fly. | |
| 4006 * When creating a slot, "slot" is the slot that the request came from. The | |
| 4007 * resulting slot will live in the same module as "slot". | |
| 4008 * When removing a slot, "slot" is the slot to be removed. | |
| 4009 * "object" is the creation object that specifies the module spec for the slot | |
| 4010 * to add or remove. | |
| 4011 */ | |
| 4012 static CK_RV sftk_CreateNewSlot(SFTKSlot *slot, CK_OBJECT_CLASS class, | |
| 4013 SFTKObject *object) | |
| 4014 { | |
| 4015 PRBool isValidUserSlot = PR_FALSE; | |
| 4016 PRBool isValidFIPSUserSlot = PR_FALSE; | |
| 4017 PRBool isValidSlot = PR_FALSE; | |
| 4018 PRBool isFIPS = PR_FALSE; | |
| 4019 unsigned long moduleIndex = NSC_NON_FIPS_MODULE; | |
| 4020 SFTKAttribute *attribute; | |
| 4021 sftk_parameters paramStrings; | |
| 4022 char *paramString; | |
| 4023 CK_SLOT_ID slotID = 0; | |
| 4024 SFTKSlot *newSlot = NULL; | |
| 4025 CK_RV crv = CKR_OK; | |
| 4026 | |
| 4027 if (class != CKO_NETSCAPE_DELSLOT && class != CKO_NETSCAPE_NEWSLOT) { | |
| 4028 return CKR_ATTRIBUTE_VALUE_INVALID; | |
| 4029 } | |
| 4030 if (class == CKO_NETSCAPE_NEWSLOT && slot->slotID == FIPS_SLOT_ID) { | |
| 4031 isFIPS = PR_TRUE; | |
| 4032 } | |
| 4033 attribute = sftk_FindAttribute(object, CKA_NETSCAPE_MODULE_SPEC); | |
| 4034 if (attribute == NULL) { | |
| 4035 return CKR_TEMPLATE_INCOMPLETE; | |
| 4036 } | |
| 4037 paramString = (char *)attribute->attrib.pValue; | |
| 4038 crv = sftk_parseParameters(paramString, ¶mStrings, isFIPS); | |
| 4039 if (crv != CKR_OK) { | |
| 4040 goto loser; | |
| 4041 } | |
| 4042 | |
| 4043 /* enforce only one at a time */ | |
| 4044 if (paramStrings.token_count != 1) { | |
| 4045 crv = CKR_ATTRIBUTE_VALUE_INVALID; | |
| 4046 goto loser; | |
| 4047 } | |
| 4048 | |
| 4049 slotID = paramStrings.tokens[0].slotID; | |
| 4050 | |
| 4051 /* stay within the valid ID space */ | |
| 4052 isValidUserSlot = (slotID >= SFTK_MIN_USER_SLOT_ID && | |
| 4053 slotID <= SFTK_MAX_USER_SLOT_ID); | |
| 4054 isValidFIPSUserSlot = (slotID >= SFTK_MIN_FIPS_USER_SLOT_ID && | |
| 4055 slotID <= SFTK_MAX_FIPS_USER_SLOT_ID); | |
| 4056 | |
| 4057 if (class == CKO_NETSCAPE_DELSLOT) { | |
| 4058 if (slot->slotID == slotID) { | |
| 4059 isValidSlot = isValidUserSlot || isValidFIPSUserSlot; | |
| 4060 } | |
| 4061 } else { | |
| 4062 /* only the crypto or FIPS slots can create new slot objects */ | |
| 4063 if (slot->slotID == NETSCAPE_SLOT_ID) { | |
| 4064 isValidSlot = isValidUserSlot; | |
| 4065 moduleIndex = NSC_NON_FIPS_MODULE; | |
| 4066 } else if (slot->slotID == FIPS_SLOT_ID) { | |
| 4067 isValidSlot = isValidFIPSUserSlot; | |
| 4068 moduleIndex = NSC_FIPS_MODULE; | |
| 4069 } | |
| 4070 } | |
| 4071 | |
| 4072 if (!isValidSlot) { | |
| 4073 crv = CKR_ATTRIBUTE_VALUE_INVALID; | |
| 4074 goto loser; | |
| 4075 } | |
| 4076 | |
| 4077 /* unload any existing slot at this id */ | |
| 4078 newSlot = sftk_SlotFromID(slotID, PR_TRUE); | |
| 4079 if (newSlot && newSlot->present) { | |
| 4080 crv = SFTK_ShutdownSlot(newSlot); | |
| 4081 if (crv != CKR_OK) { | |
| 4082 goto loser; | |
| 4083 } | |
| 4084 } | |
| 4085 | |
| 4086 /* if we were just planning on deleting the slot, then do so now */ | |
| 4087 if (class == CKO_NETSCAPE_DELSLOT) { | |
| 4088 /* sort of a unconventional use of this error code, be we are | |
| 4089 * overusing CKR_ATTRIBUTE_VALUE_INVALID, and it does apply */ | |
| 4090 crv = newSlot ? CKR_OK : CKR_SLOT_ID_INVALID; | |
| 4091 goto loser; /* really exit */ | |
| 4092 } | |
| 4093 | |
| 4094 if (newSlot) { | |
| 4095 crv = SFTK_SlotReInit(newSlot, paramStrings.configdir, | |
| 4096 paramStrings.updatedir, paramStrings.updateID, | |
| 4097 ¶mStrings.tokens[0], moduleIndex); | |
| 4098 } else { | |
| 4099 crv = SFTK_SlotInit(paramStrings.configdir, | |
| 4100 paramStrings.updatedir, paramStrings.updateID, | |
| 4101 ¶mStrings.tokens[0], moduleIndex); | |
| 4102 } | |
| 4103 | |
| 4104 loser: | |
| 4105 sftk_freeParams(¶mStrings); | |
| 4106 sftk_FreeAttribute(attribute); | |
| 4107 | |
| 4108 return crv; | |
| 4109 } | |
| 4110 | |
| 4111 | |
| 4112 /* NSC_CreateObject creates a new object. */ | |
| 4113 CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession, | |
| 4114 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, | |
| 4115 CK_OBJECT_HANDLE_PTR phObject) | |
| 4116 { | |
| 4117 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); | |
| 4118 SFTKSession *session; | |
| 4119 SFTKObject *object; | |
| 4120 /* make sure class isn't randomly CKO_NETSCAPE_NEWSLOT or | |
| 4121 * CKO_NETSCPE_DELSLOT. */ | |
| 4122 CK_OBJECT_CLASS class = CKO_VENDOR_DEFINED; | |
| 4123 CK_RV crv; | |
| 4124 int i; | |
| 4125 | |
| 4126 CHECK_FORK(); | |
| 4127 | |
| 4128 *phObject = CK_INVALID_HANDLE; | |
| 4129 | |
| 4130 if (slot == NULL) { | |
| 4131 return CKR_SESSION_HANDLE_INVALID; | |
| 4132 } | |
| 4133 /* | |
| 4134 * now lets create an object to hang the attributes off of | |
| 4135 */ | |
| 4136 object = sftk_NewObject(slot); /* fill in the handle later */ | |
| 4137 if (object == NULL) { | |
| 4138 return CKR_HOST_MEMORY; | |
| 4139 } | |
| 4140 | |
| 4141 /* | |
| 4142 * load the template values into the object | |
| 4143 */ | |
| 4144 for (i=0; i < (int) ulCount; i++) { | |
| 4145 crv = sftk_AddAttributeType(object,sftk_attr_expand(&pTemplate[i])); | |
| 4146 if (crv != CKR_OK) { | |
| 4147 sftk_FreeObject(object); | |
| 4148 return crv; | |
| 4149 } | |
| 4150 if ((pTemplate[i].type == CKA_CLASS) && pTemplate[i].pValue) { | |
| 4151 class = *(CK_OBJECT_CLASS *)pTemplate[i].pValue; | |
| 4152 } | |
| 4153 } | |
| 4154 | |
| 4155 /* get the session */ | |
| 4156 session = sftk_SessionFromHandle(hSession); | |
| 4157 if (session == NULL) { | |
| 4158 sftk_FreeObject(object); | |
| 4159 return CKR_SESSION_HANDLE_INVALID; | |
| 4160 } | |
| 4161 | |
| 4162 /* | |
| 4163 * handle pseudo objects (CKO_NEWSLOT) | |
| 4164 */ | |
| 4165 if ((class == CKO_NETSCAPE_NEWSLOT) || (class == CKO_NETSCAPE_DELSLOT)) { | |
| 4166 crv = sftk_CreateNewSlot(slot, class, object); | |
| 4167 goto done; | |
| 4168 } | |
| 4169 | |
| 4170 /* | |
| 4171 * handle the base object stuff | |
| 4172 */ | |
| 4173 crv = sftk_handleObject(object,session); | |
| 4174 *phObject = object->handle; | |
| 4175 done: | |
| 4176 sftk_FreeSession(session); | |
| 4177 sftk_FreeObject(object); | |
| 4178 | |
| 4179 return crv; | |
| 4180 } | |
| 4181 | |
| 4182 | |
| 4183 | |
| 4184 /* NSC_CopyObject copies an object, creating a new object for the copy. */ | |
| 4185 CK_RV NSC_CopyObject(CK_SESSION_HANDLE hSession, | |
| 4186 CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, | |
| 4187 CK_OBJECT_HANDLE_PTR phNewObject) | |
| 4188 { | |
| 4189 SFTKObject *destObject,*srcObject; | |
| 4190 SFTKSession *session; | |
| 4191 CK_RV crv = CKR_OK; | |
| 4192 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); | |
| 4193 int i; | |
| 4194 | |
| 4195 CHECK_FORK(); | |
| 4196 | |
| 4197 if (slot == NULL) { | |
| 4198 return CKR_SESSION_HANDLE_INVALID; | |
| 4199 } | |
| 4200 /* Get srcObject so we can find the class */ | |
| 4201 session = sftk_SessionFromHandle(hSession); | |
| 4202 if (session == NULL) { | |
| 4203 return CKR_SESSION_HANDLE_INVALID; | |
| 4204 } | |
| 4205 srcObject = sftk_ObjectFromHandle(hObject,session); | |
| 4206 if (srcObject == NULL) { | |
| 4207 sftk_FreeSession(session); | |
| 4208 return CKR_OBJECT_HANDLE_INVALID; | |
| 4209 } | |
| 4210 /* | |
| 4211 * create an object to hang the attributes off of | |
| 4212 */ | |
| 4213 destObject = sftk_NewObject(slot); /* fill in the handle later */ | |
| 4214 if (destObject == NULL) { | |
| 4215 sftk_FreeSession(session); | |
| 4216 sftk_FreeObject(srcObject); | |
| 4217 return CKR_HOST_MEMORY; | |
| 4218 } | |
| 4219 | |
| 4220 /* | |
| 4221 * load the template values into the object | |
| 4222 */ | |
| 4223 for (i=0; i < (int) ulCount; i++) { | |
| 4224 if (sftk_modifyType(pTemplate[i].type,srcObject->objclass) == SFTK_NEVER
) { | |
| 4225 crv = CKR_ATTRIBUTE_READ_ONLY; | |
| 4226 break; | |
| 4227 } | |
| 4228 crv = sftk_AddAttributeType(destObject,sftk_attr_expand(&pTemplate[i])); | |
| 4229 if (crv != CKR_OK) { break; } | |
| 4230 } | |
| 4231 if (crv != CKR_OK) { | |
| 4232 sftk_FreeSession(session); | |
| 4233 sftk_FreeObject(srcObject); | |
| 4234 sftk_FreeObject(destObject); | |
| 4235 return crv; | |
| 4236 } | |
| 4237 | |
| 4238 /* sensitive can only be changed to CK_TRUE */ | |
| 4239 if (sftk_hasAttribute(destObject,CKA_SENSITIVE)) { | |
| 4240 if (!sftk_isTrue(destObject,CKA_SENSITIVE)) { | |
| 4241 sftk_FreeSession(session); | |
| 4242 sftk_FreeObject(srcObject); | |
| 4243 sftk_FreeObject(destObject); | |
| 4244 return CKR_ATTRIBUTE_READ_ONLY; | |
| 4245 } | |
| 4246 } | |
| 4247 | |
| 4248 /* | |
| 4249 * now copy the old attributes from the new attributes | |
| 4250 */ | |
| 4251 /* don't create a token object if we aren't in a rw session */ | |
| 4252 /* we need to hold the lock to copy a consistant version of | |
| 4253 * the object. */ | |
| 4254 crv = sftk_CopyObject(destObject,srcObject); | |
| 4255 | |
| 4256 destObject->objclass = srcObject->objclass; | |
| 4257 sftk_FreeObject(srcObject); | |
| 4258 if (crv != CKR_OK) { | |
| 4259 sftk_FreeObject(destObject); | |
| 4260 sftk_FreeSession(session); | |
| 4261 return crv; | |
| 4262 } | |
| 4263 | |
| 4264 crv = sftk_handleObject(destObject,session); | |
| 4265 *phNewObject = destObject->handle; | |
| 4266 sftk_FreeSession(session); | |
| 4267 sftk_FreeObject(destObject); | |
| 4268 | |
| 4269 return crv; | |
| 4270 } | |
| 4271 | |
| 4272 | |
| 4273 /* NSC_GetObjectSize gets the size of an object in bytes. */ | |
| 4274 CK_RV NSC_GetObjectSize(CK_SESSION_HANDLE hSession, | |
| 4275 CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize) | |
| 4276 { | |
| 4277 CHECK_FORK(); | |
| 4278 | |
| 4279 *pulSize = 0; | |
| 4280 return CKR_OK; | |
| 4281 } | |
| 4282 | |
| 4283 | |
| 4284 /* NSC_GetAttributeValue obtains the value of one or more object attributes. */ | |
| 4285 CK_RV NSC_GetAttributeValue(CK_SESSION_HANDLE hSession, | |
| 4286 CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount) | |
| 4287 { | |
| 4288 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); | |
| 4289 SFTKSession *session; | |
| 4290 SFTKObject *object; | |
| 4291 SFTKAttribute *attribute; | |
| 4292 PRBool sensitive; | |
| 4293 CK_RV crv; | |
| 4294 int i; | |
| 4295 | |
| 4296 CHECK_FORK(); | |
| 4297 | |
| 4298 if (slot == NULL) { | |
| 4299 return CKR_SESSION_HANDLE_INVALID; | |
| 4300 } | |
| 4301 /* | |
| 4302 * make sure we're allowed | |
| 4303 */ | |
| 4304 session = sftk_SessionFromHandle(hSession); | |
| 4305 if (session == NULL) { | |
| 4306 return CKR_SESSION_HANDLE_INVALID; | |
| 4307 } | |
| 4308 | |
| 4309 /* short circuit everything for token objects */ | |
| 4310 if (sftk_isToken(hObject)) { | |
| 4311 SFTKSlot *slot = sftk_SlotFromSession(session); | |
| 4312 SFTKDBHandle *dbHandle = sftk_getDBForTokenObject(slot, hObject); | |
| 4313 SFTKDBHandle *keydb = NULL; | |
| 4314 | |
| 4315 if (dbHandle == NULL) { | |
| 4316 sftk_FreeSession(session); | |
| 4317 return CKR_OBJECT_HANDLE_INVALID; | |
| 4318 } | |
| 4319 | |
| 4320 crv = sftkdb_GetAttributeValue(dbHandle, hObject, pTemplate, ulCount); | |
| 4321 | |
| 4322 /* make sure we don't export any sensitive information */ | |
| 4323 keydb = sftk_getKeyDB(slot); | |
| 4324 if (dbHandle == keydb) { | |
| 4325 for (i=0; i < (int) ulCount; i++) { | |
| 4326 if (sftk_isSensitive(pTemplate[i].type,CKO_PRIVATE_KEY)) { | |
| 4327 crv = CKR_ATTRIBUTE_SENSITIVE; | |
| 4328 if (pTemplate[i].pValue && (pTemplate[i].ulValueLen!= -1)){ | |
| 4329 PORT_Memset(pTemplate[i].pValue, 0, | |
| 4330 pTemplate[i].ulValueLen); | |
| 4331 } | |
| 4332 pTemplate[i].ulValueLen = -1; | |
| 4333 } | |
| 4334 } | |
| 4335 } | |
| 4336 | |
| 4337 sftk_FreeSession(session); | |
| 4338 sftk_freeDB(dbHandle); | |
| 4339 if (keydb) { | |
| 4340 sftk_freeDB(keydb); | |
| 4341 } | |
| 4342 return crv; | |
| 4343 } | |
| 4344 | |
| 4345 /* handle the session object */ | |
| 4346 object = sftk_ObjectFromHandle(hObject,session); | |
| 4347 sftk_FreeSession(session); | |
| 4348 if (object == NULL) { | |
| 4349 return CKR_OBJECT_HANDLE_INVALID; | |
| 4350 } | |
| 4351 | |
| 4352 /* don't read a private object if we aren't logged in */ | |
| 4353 if ((!slot->isLoggedIn) && (slot->needLogin) && | |
| 4354 (sftk_isTrue(object,CKA_PRIVATE))) { | |
| 4355 sftk_FreeObject(object); | |
| 4356 return CKR_USER_NOT_LOGGED_IN; | |
| 4357 } | |
| 4358 | |
| 4359 crv = CKR_OK; | |
| 4360 sensitive = sftk_isTrue(object,CKA_SENSITIVE); | |
| 4361 for (i=0; i < (int) ulCount; i++) { | |
| 4362 /* Make sure that this attribute is retrievable */ | |
| 4363 if (sensitive && sftk_isSensitive(pTemplate[i].type,object->objclass)) { | |
| 4364 crv = CKR_ATTRIBUTE_SENSITIVE; | |
| 4365 pTemplate[i].ulValueLen = -1; | |
| 4366 continue; | |
| 4367 } | |
| 4368 attribute = sftk_FindAttribute(object,pTemplate[i].type); | |
| 4369 if (attribute == NULL) { | |
| 4370 crv = CKR_ATTRIBUTE_TYPE_INVALID; | |
| 4371 pTemplate[i].ulValueLen = -1; | |
| 4372 continue; | |
| 4373 } | |
| 4374 if (pTemplate[i].pValue != NULL) { | |
| 4375 PORT_Memcpy(pTemplate[i].pValue,attribute->attrib.pValue, | |
| 4376 attribute->attrib.ulValueLen); | |
| 4377 } | |
| 4378 pTemplate[i].ulValueLen = attribute->attrib.ulValueLen; | |
| 4379 sftk_FreeAttribute(attribute); | |
| 4380 } | |
| 4381 | |
| 4382 sftk_FreeObject(object); | |
| 4383 return crv; | |
| 4384 } | |
| 4385 | |
| 4386 /* NSC_SetAttributeValue modifies the value of one or more object attributes */ | |
| 4387 CK_RV NSC_SetAttributeValue (CK_SESSION_HANDLE hSession, | |
| 4388 CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount) | |
| 4389 { | |
| 4390 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); | |
| 4391 SFTKSession *session; | |
| 4392 SFTKAttribute *attribute; | |
| 4393 SFTKObject *object; | |
| 4394 PRBool isToken; | |
| 4395 CK_RV crv = CKR_OK; | |
| 4396 CK_BBOOL legal; | |
| 4397 int i; | |
| 4398 | |
| 4399 CHECK_FORK(); | |
| 4400 | |
| 4401 if (slot == NULL) { | |
| 4402 return CKR_SESSION_HANDLE_INVALID; | |
| 4403 } | |
| 4404 /* | |
| 4405 * make sure we're allowed | |
| 4406 */ | |
| 4407 session = sftk_SessionFromHandle(hSession); | |
| 4408 if (session == NULL) { | |
| 4409 return CKR_SESSION_HANDLE_INVALID; | |
| 4410 } | |
| 4411 | |
| 4412 object = sftk_ObjectFromHandle(hObject,session); | |
| 4413 if (object == NULL) { | |
| 4414 sftk_FreeSession(session); | |
| 4415 return CKR_OBJECT_HANDLE_INVALID; | |
| 4416 } | |
| 4417 | |
| 4418 /* don't modify a private object if we aren't logged in */ | |
| 4419 if ((!slot->isLoggedIn) && (slot->needLogin) && | |
| 4420 (sftk_isTrue(object,CKA_PRIVATE))) { | |
| 4421 sftk_FreeSession(session); | |
| 4422 sftk_FreeObject(object); | |
| 4423 return CKR_USER_NOT_LOGGED_IN; | |
| 4424 } | |
| 4425 | |
| 4426 /* don't modify a token object if we aren't in a rw session */ | |
| 4427 isToken = sftk_isTrue(object,CKA_TOKEN); | |
| 4428 if (((session->info.flags & CKF_RW_SESSION) == 0) && isToken) { | |
| 4429 sftk_FreeSession(session); | |
| 4430 sftk_FreeObject(object); | |
| 4431 return CKR_SESSION_READ_ONLY; | |
| 4432 } | |
| 4433 sftk_FreeSession(session); | |
| 4434 | |
| 4435 /* only change modifiable objects */ | |
| 4436 if (!sftk_isTrue(object,CKA_MODIFIABLE)) { | |
| 4437 sftk_FreeObject(object); | |
| 4438 return CKR_ATTRIBUTE_READ_ONLY; | |
| 4439 } | |
| 4440 | |
| 4441 for (i=0; i < (int) ulCount; i++) { | |
| 4442 /* Make sure that this attribute is changeable */ | |
| 4443 switch (sftk_modifyType(pTemplate[i].type,object->objclass)) { | |
| 4444 case SFTK_NEVER: | |
| 4445 case SFTK_ONCOPY: | |
| 4446 default: | |
| 4447 crv = CKR_ATTRIBUTE_READ_ONLY; | |
| 4448 break; | |
| 4449 | |
| 4450 case SFTK_SENSITIVE: | |
| 4451 legal = (pTemplate[i].type == CKA_EXTRACTABLE) ? CK_FALSE : CK_TRUE; | |
| 4452 if ((*(CK_BBOOL *)pTemplate[i].pValue) != legal) { | |
| 4453 crv = CKR_ATTRIBUTE_READ_ONLY; | |
| 4454 } | |
| 4455 break; | |
| 4456 case SFTK_ALWAYS: | |
| 4457 break; | |
| 4458 } | |
| 4459 if (crv != CKR_OK) break; | |
| 4460 | |
| 4461 /* find the old attribute */ | |
| 4462 attribute = sftk_FindAttribute(object,pTemplate[i].type); | |
| 4463 if (attribute == NULL) { | |
| 4464 crv =CKR_ATTRIBUTE_TYPE_INVALID; | |
| 4465 break; | |
| 4466 } | |
| 4467 sftk_FreeAttribute(attribute); | |
| 4468 crv = sftk_forceAttribute(object,sftk_attr_expand(&pTemplate[i])); | |
| 4469 if (crv != CKR_OK) break; | |
| 4470 | |
| 4471 } | |
| 4472 | |
| 4473 sftk_FreeObject(object); | |
| 4474 return crv; | |
| 4475 } | |
| 4476 | |
| 4477 static CK_RV | |
| 4478 sftk_expandSearchList(SFTKSearchResults *search, int count) | |
| 4479 { | |
| 4480 search->array_size += count; | |
| 4481 search->handles = (CK_OBJECT_HANDLE *)PORT_Realloc(search->handles, | |
| 4482 sizeof(CK_OBJECT_HANDLE)*search->array_size); | |
| 4483 return search->handles ? CKR_OK : CKR_HOST_MEMORY; | |
| 4484 } | |
| 4485 | |
| 4486 | |
| 4487 | |
| 4488 static CK_RV | |
| 4489 sftk_searchDatabase(SFTKDBHandle *handle, SFTKSearchResults *search, | |
| 4490 const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) | |
| 4491 { | |
| 4492 CK_RV crv; | |
| 4493 int objectListSize = search->array_size-search->size; | |
| 4494 CK_OBJECT_HANDLE *array = &search->handles[search->size]; | |
| 4495 SDBFind *find; | |
| 4496 CK_ULONG count; | |
| 4497 | |
| 4498 crv = sftkdb_FindObjectsInit(handle, pTemplate, ulCount, &find); | |
| 4499 if (crv != CKR_OK) | |
| 4500 return crv; | |
| 4501 do { | |
| 4502 crv = sftkdb_FindObjects(handle, find, array, objectListSize, &count); | |
| 4503 if ((crv != CKR_OK) || (count == 0)) | |
| 4504 break; | |
| 4505 search->size += count; | |
| 4506 objectListSize -= count; | |
| 4507 if (objectListSize > 0) | |
| 4508 break; | |
| 4509 crv = sftk_expandSearchList(search,NSC_SEARCH_BLOCK_SIZE); | |
| 4510 objectListSize = NSC_SEARCH_BLOCK_SIZE; | |
| 4511 array = &search->handles[search->size]; | |
| 4512 } while (crv == CKR_OK); | |
| 4513 sftkdb_FindObjectsFinal(handle, find); | |
| 4514 | |
| 4515 return crv; | |
| 4516 } | |
| 4517 | |
| 4518 /* softoken used to search the SMimeEntries automatically instead of | |
| 4519 * doing this in pk11wrap. This code should really be up in | |
| 4520 * pk11wrap so that it will work with other tokens other than softoken. | |
| 4521 */ | |
| 4522 CK_RV | |
| 4523 sftk_emailhack(SFTKSlot *slot, SFTKDBHandle *handle, | |
| 4524 SFTKSearchResults *search, CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) | |
| 4525 { | |
| 4526 PRBool isCert = PR_FALSE; | |
| 4527 int emailIndex = -1; | |
| 4528 unsigned int i; | |
| 4529 SFTKSearchResults smime_search; | |
| 4530 CK_ATTRIBUTE smime_template[2]; | |
| 4531 CK_OBJECT_CLASS smime_class = CKO_NETSCAPE_SMIME; | |
| 4532 SFTKAttribute *attribute = NULL; | |
| 4533 SFTKObject *object = NULL; | |
| 4534 CK_RV crv = CKR_OK; | |
| 4535 | |
| 4536 | |
| 4537 smime_search.handles = NULL; /* paranoia, some one is bound to add a goto | |
| 4538 * loser before this gets initialized */ | |
| 4539 | |
| 4540 /* see if we are looking for email certs */ | |
| 4541 for (i=0; i < ulCount; i++) { | |
| 4542 if (pTemplate[i].type == CKA_CLASS) { | |
| 4543 if ((pTemplate[i].ulValueLen != sizeof(CK_OBJECT_CLASS) || | |
| 4544 (*(CK_OBJECT_CLASS *)pTemplate[i].pValue) != CKO_CERTIFICATE)) { | |
| 4545 /* not a cert, skip out */ | |
| 4546 break; | |
| 4547 } | |
| 4548 isCert = PR_TRUE; | |
| 4549 } else if (pTemplate[i].type == CKA_NETSCAPE_EMAIL) { | |
| 4550 emailIndex = i; | |
| 4551 | |
| 4552 } | |
| 4553 if (isCert && (emailIndex != -1)) break; | |
| 4554 } | |
| 4555 | |
| 4556 if (!isCert || (emailIndex == -1)) { | |
| 4557 return CKR_OK; | |
| 4558 } | |
| 4559 | |
| 4560 /* we are doing a cert and email search, find the SMimeEntry */ | |
| 4561 smime_template[0].type = CKA_CLASS; | |
| 4562 smime_template[0].pValue = &smime_class; | |
| 4563 smime_template[0].ulValueLen = sizeof(smime_class); | |
| 4564 smime_template[1] = pTemplate[emailIndex]; | |
| 4565 | |
| 4566 smime_search.handles = (CK_OBJECT_HANDLE *) | |
| 4567 PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * NSC_SEARCH_BLOCK_SIZE); | |
| 4568 if (smime_search.handles == NULL) { | |
| 4569 crv = CKR_HOST_MEMORY; | |
| 4570 goto loser; | |
| 4571 } | |
| 4572 smime_search.index = 0; | |
| 4573 smime_search.size = 0; | |
| 4574 smime_search.array_size = NSC_SEARCH_BLOCK_SIZE; | |
| 4575 | |
| 4576 crv = sftk_searchDatabase(handle, &smime_search, smime_template, 2); | |
| 4577 if (crv != CKR_OK || smime_search.size == 0) { | |
| 4578 goto loser; | |
| 4579 } | |
| 4580 | |
| 4581 /* get the SMime subject */ | |
| 4582 object = sftk_NewTokenObject(slot, NULL, smime_search.handles[0]); | |
| 4583 if (object == NULL) { | |
| 4584 crv = CKR_HOST_MEMORY; /* is there any other reason for this failure? */ | |
| 4585 goto loser; | |
| 4586 } | |
| 4587 attribute = sftk_FindAttribute(object,CKA_SUBJECT); | |
| 4588 if (attribute == NULL) { | |
| 4589 crv = CKR_ATTRIBUTE_TYPE_INVALID; | |
| 4590 goto loser; | |
| 4591 } | |
| 4592 | |
| 4593 /* now find the certs with that subject */ | |
| 4594 pTemplate[emailIndex] = attribute->attrib; | |
| 4595 /* now add the appropriate certs to the search list */ | |
| 4596 crv = sftk_searchDatabase(handle, search, pTemplate, ulCount); | |
| 4597 pTemplate[emailIndex] = smime_template[1]; /* restore the user's template*/ | |
| 4598 | |
| 4599 loser: | |
| 4600 if (attribute) { | |
| 4601 sftk_FreeAttribute(attribute); | |
| 4602 } | |
| 4603 if (object) { | |
| 4604 sftk_FreeObject(object); | |
| 4605 } | |
| 4606 if (smime_search.handles) { | |
| 4607 PORT_Free(smime_search.handles); | |
| 4608 } | |
| 4609 | |
| 4610 return crv; | |
| 4611 } | |
| 4612 | |
| 4613 static void | |
| 4614 sftk_pruneSearch(CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount, | |
| 4615 PRBool *searchCertDB, PRBool *searchKeyDB) { | |
| 4616 CK_ULONG i; | |
| 4617 | |
| 4618 *searchCertDB = PR_TRUE; | |
| 4619 *searchKeyDB = PR_TRUE; | |
| 4620 for (i = 0; i < ulCount; i++) { | |
| 4621 if (pTemplate[i].type == CKA_CLASS && pTemplate[i].pValue != NULL) { | |
| 4622 CK_OBJECT_CLASS class = *((CK_OBJECT_CLASS*)pTemplate[i].pValue); | |
| 4623 if (class == CKO_PRIVATE_KEY || class == CKO_SECRET_KEY) { | |
| 4624 *searchCertDB = PR_FALSE; | |
| 4625 } else { | |
| 4626 *searchKeyDB = PR_FALSE; | |
| 4627 } | |
| 4628 break; | |
| 4629 } | |
| 4630 } | |
| 4631 } | |
| 4632 | |
| 4633 static CK_RV | |
| 4634 sftk_searchTokenList(SFTKSlot *slot, SFTKSearchResults *search, | |
| 4635 CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount, | |
| 4636 PRBool *tokenOnly, PRBool isLoggedIn) | |
| 4637 { | |
| 4638 CK_RV crv = CKR_OK; | |
| 4639 CK_RV crv2; | |
| 4640 PRBool searchCertDB; | |
| 4641 PRBool searchKeyDB; | |
| 4642 | |
| 4643 sftk_pruneSearch(pTemplate, ulCount, &searchCertDB, &searchKeyDB); | |
| 4644 | |
| 4645 if (searchCertDB) { | |
| 4646 SFTKDBHandle *certHandle = sftk_getCertDB(slot); | |
| 4647 crv = sftk_searchDatabase(certHandle, search, pTemplate, ulCount); | |
| 4648 crv2 = sftk_emailhack(slot, certHandle, search, pTemplate, ulCount); | |
| 4649 if (crv == CKR_OK) crv = crv2; | |
| 4650 sftk_freeDB(certHandle); | |
| 4651 } | |
| 4652 | |
| 4653 if (crv == CKR_OK && isLoggedIn && searchKeyDB) { | |
| 4654 SFTKDBHandle *keyHandle = sftk_getKeyDB(slot); | |
| 4655 crv = sftk_searchDatabase(keyHandle, search, pTemplate, ulCount); | |
| 4656 sftk_freeDB(keyHandle); | |
| 4657 } | |
| 4658 return crv; | |
| 4659 } | |
| 4660 | |
| 4661 /* NSC_FindObjectsInit initializes a search for token and session objects | |
| 4662 * that match a template. */ | |
| 4663 CK_RV NSC_FindObjectsInit(CK_SESSION_HANDLE hSession, | |
| 4664 CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount) | |
| 4665 { | |
| 4666 SFTKSearchResults *search = NULL, *freeSearch = NULL; | |
| 4667 SFTKSession *session = NULL; | |
| 4668 SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); | |
| 4669 PRBool tokenOnly = PR_FALSE; | |
| 4670 CK_RV crv = CKR_OK; | |
| 4671 PRBool isLoggedIn; | |
| 4672 | |
| 4673 CHECK_FORK(); | |
| 4674 | |
| 4675 if (slot == NULL) { | |
| 4676 return CKR_SESSION_HANDLE_INVALID; | |
| 4677 } | |
| 4678 session = sftk_SessionFromHandle(hSession); | |
| 4679 if (session == NULL) { | |
| 4680 crv = CKR_SESSION_HANDLE_INVALID; | |
| 4681 goto loser; | |
| 4682 } | |
| 4683 | |
| 4684 search = (SFTKSearchResults *)PORT_Alloc(sizeof(SFTKSearchResults)); | |
| 4685 if (search == NULL) { | |
| 4686 crv = CKR_HOST_MEMORY; | |
| 4687 goto loser; | |
| 4688 } | |
| 4689 search->handles = (CK_OBJECT_HANDLE *) | |
| 4690 PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * NSC_SEARCH_BLOCK_SIZE); | |
| 4691 if (search->handles == NULL) { | |
| 4692 crv = CKR_HOST_MEMORY; | |
| 4693 goto loser; | |
| 4694 } | |
| 4695 search->index = 0; | |
| 4696 search->size = 0; | |
| 4697 search->array_size = NSC_SEARCH_BLOCK_SIZE; | |
| 4698 isLoggedIn = (PRBool)((!slot->needLogin) || slot->isLoggedIn); | |
| 4699 | |
| 4700 crv = sftk_searchTokenList(slot, search, pTemplate, ulCount, &tokenOnly, | |
| 4701 isLoggedIn); | |
| 4702 if (crv != CKR_OK) { | |
| 4703 goto loser; | |
| 4704 } | |
| 4705 | |
| 4706 /* build list of found objects in the session */ | |
| 4707 if (!tokenOnly) { | |
| 4708 crv = sftk_searchObjectList(search, slot->sessObjHashTable, | |
| 4709 slot->sessObjHashSize, slot->objectLock, | |
| 4710 pTemplate, ulCount, isLoggedIn); | |
| 4711 } | |
| 4712 if (crv != CKR_OK) { | |
| 4713 goto loser; | |
| 4714 } | |
| 4715 | |
| 4716 if ((freeSearch = session->search) != NULL) { | |
| 4717 session->search = NULL; | |
| 4718 sftk_FreeSearch(freeSearch); | |
| 4719 } | |
| 4720 session->search = search; | |
| 4721 sftk_FreeSession(session); | |
| 4722 return CKR_OK; | |
| 4723 | |
| 4724 loser: | |
| 4725 if (search) { | |
| 4726 sftk_FreeSearch(search); | |
| 4727 } | |
| 4728 if (session) { | |
| 4729 sftk_FreeSession(session); | |
| 4730 } | |
| 4731 return crv; | |
| 4732 } | |
| 4733 | |
| 4734 | |
| 4735 /* NSC_FindObjects continues a search for token and session objects | |
| 4736 * that match a template, obtaining additional object handles. */ | |
| 4737 CK_RV NSC_FindObjects(CK_SESSION_HANDLE hSession, | |
| 4738 CK_OBJECT_HANDLE_PTR phObject,CK_ULONG ulMaxObjectCount, | |
| 4739 CK_ULONG_PTR pulObjectCount) | |
| 4740 { | |
| 4741 SFTKSession *session; | |
| 4742 SFTKSearchResults *search; | |
| 4743 int transfer; | |
| 4744 int left; | |
| 4745 | |
| 4746 CHECK_FORK(); | |
| 4747 | |
| 4748 *pulObjectCount = 0; | |
| 4749 session = sftk_SessionFromHandle(hSession); | |
| 4750 if (session == NULL) return CKR_SESSION_HANDLE_INVALID; | |
| 4751 if (session->search == NULL) { | |
| 4752 sftk_FreeSession(session); | |
| 4753 return CKR_OK; | |
| 4754 } | |
| 4755 search = session->search; | |
| 4756 left = session->search->size - session->search->index; | |
| 4757 transfer = ((int)ulMaxObjectCount > left) ? left : ulMaxObjectCount; | |
| 4758 if (transfer > 0) { | |
| 4759 PORT_Memcpy(phObject,&search->handles[search->index], | |
| 4760 transfer*sizeof(CK_OBJECT_HANDLE)); | |
| 4761 } else { | |
| 4762 *phObject = CK_INVALID_HANDLE; | |
| 4763 } | |
| 4764 | |
| 4765 search->index += transfer; | |
| 4766 if (search->index == search->size) { | |
| 4767 session->search = NULL; | |
| 4768 sftk_FreeSearch(search); | |
| 4769 } | |
| 4770 *pulObjectCount = transfer; | |
| 4771 sftk_FreeSession(session); | |
| 4772 return CKR_OK; | |
| 4773 } | |
| 4774 | |
| 4775 /* NSC_FindObjectsFinal finishes a search for token and session objects. */ | |
| 4776 CK_RV NSC_FindObjectsFinal(CK_SESSION_HANDLE hSession) | |
| 4777 { | |
| 4778 SFTKSession *session; | |
| 4779 SFTKSearchResults *search; | |
| 4780 | |
| 4781 CHECK_FORK(); | |
| 4782 | |
| 4783 session = sftk_SessionFromHandle(hSession); | |
| 4784 if (session == NULL) return CKR_SESSION_HANDLE_INVALID; | |
| 4785 search = session->search; | |
| 4786 session->search = NULL; | |
| 4787 sftk_FreeSession(session); | |
| 4788 if (search != NULL) { | |
| 4789 sftk_FreeSearch(search); | |
| 4790 } | |
| 4791 return CKR_OK; | |
| 4792 } | |
| 4793 | |
| 4794 | |
| 4795 | |
| 4796 CK_RV NSC_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, | |
| 4797 CK_VOID_PTR pReserved) | |
| 4798 { | |
| 4799 CHECK_FORK(); | |
| 4800 | |
| 4801 return CKR_FUNCTION_NOT_SUPPORTED; | |
| 4802 } | |
| 4803 | |
| OLD | NEW |