1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/softoken/pkcs11.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,4789 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +/* 1.8 + * This file implements PKCS 11 on top of our existing security modules 1.9 + * 1.10 + * For more information about PKCS 11 See PKCS 11 Token Inteface Standard. 1.11 + * This implementation has two slots: 1.12 + * slot 1 is our generic crypto support. It does not require login. 1.13 + * It supports Public Key ops, and all they bulk ciphers and hashes. 1.14 + * It can also support Private Key ops for imported Private keys. It does 1.15 + * not have any token storage. 1.16 + * slot 2 is our private key support. It requires a login before use. It 1.17 + * can store Private Keys and Certs as token objects. Currently only private 1.18 + * keys and their associated Certificates are saved on the token. 1.19 + * 1.20 + * In this implementation, session objects are only visible to the session 1.21 + * that created or generated them. 1.22 + */ 1.23 +#include "seccomon.h" 1.24 +#include "secitem.h" 1.25 +#include "pkcs11.h" 1.26 +#include "pkcs11i.h" 1.27 +#include "softoken.h" 1.28 +#include "lowkeyi.h" 1.29 +#include "blapi.h" 1.30 +#include "secder.h" 1.31 +#include "secport.h" 1.32 +#include "secrng.h" 1.33 +#include "prtypes.h" 1.34 +#include "nspr.h" 1.35 +#include "softkver.h" 1.36 +#include "secoid.h" 1.37 +#include "sftkdb.h" 1.38 +#include "utilpars.h" 1.39 +#include "ec.h" 1.40 +#include "secasn1.h" 1.41 +#include "secerr.h" 1.42 +#include "lgglue.h" 1.43 + 1.44 +PRBool parentForkedAfterC_Initialize; 1.45 + 1.46 +#ifndef NO_FORK_CHECK 1.47 + 1.48 +PRBool sftkForkCheckDisabled; 1.49 + 1.50 +#if defined(CHECK_FORK_PTHREAD) || defined(CHECK_FORK_MIXED) 1.51 +PRBool forked = PR_FALSE; 1.52 +#endif 1.53 + 1.54 +#if defined(CHECK_FORK_GETPID) || defined(CHECK_FORK_MIXED) 1.55 +#include <unistd.h> 1.56 +pid_t myPid; 1.57 +#endif 1.58 + 1.59 +#ifdef CHECK_FORK_MIXED 1.60 +#include <sys/systeminfo.h> 1.61 +PRBool usePthread_atfork; 1.62 +#endif 1.63 + 1.64 +#endif 1.65 + 1.66 +/* 1.67 + * ******************** Static data ******************************* 1.68 + */ 1.69 + 1.70 +/* The next three strings must be exactly 32 characters long */ 1.71 +static char *manufacturerID = "Mozilla Foundation "; 1.72 +static char manufacturerID_space[33]; 1.73 +static char *libraryDescription = "NSS Internal Crypto Services "; 1.74 +static char libraryDescription_space[33]; 1.75 + 1.76 +/* 1.77 + * In FIPS mode, we disallow login attempts for 1 second after a login 1.78 + * failure so that there are at most 60 login attempts per minute. 1.79 + */ 1.80 +static PRIntervalTime loginWaitTime; 1.81 +static PRUint32 minSessionObjectHandle = 1U; 1.82 + 1.83 +#define __PASTE(x,y) x##y 1.84 + 1.85 +/* 1.86 + * we renamed all our internal functions, get the correct 1.87 + * definitions for them... 1.88 + */ 1.89 +#undef CK_PKCS11_FUNCTION_INFO 1.90 +#undef CK_NEED_ARG_LIST 1.91 + 1.92 +#define CK_EXTERN extern 1.93 +#define CK_PKCS11_FUNCTION_INFO(func) \ 1.94 + CK_RV __PASTE(NS,func) 1.95 +#define CK_NEED_ARG_LIST 1 1.96 + 1.97 +#include "pkcs11f.h" 1.98 + 1.99 + 1.100 + 1.101 +/* build the crypto module table */ 1.102 +static const CK_FUNCTION_LIST sftk_funcList = { 1.103 + { 1, 10 }, 1.104 + 1.105 +#undef CK_PKCS11_FUNCTION_INFO 1.106 +#undef CK_NEED_ARG_LIST 1.107 + 1.108 +#define CK_PKCS11_FUNCTION_INFO(func) \ 1.109 + __PASTE(NS,func), 1.110 +#include "pkcs11f.h" 1.111 + 1.112 +}; 1.113 + 1.114 +#undef CK_PKCS11_FUNCTION_INFO 1.115 +#undef CK_NEED_ARG_LIST 1.116 + 1.117 + 1.118 +#undef __PASTE 1.119 + 1.120 +/* List of DES Weak Keys */ 1.121 +typedef unsigned char desKey[8]; 1.122 +static const desKey sftk_desWeakTable[] = { 1.123 +#ifdef noParity 1.124 + /* weak */ 1.125 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 1.126 + { 0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e }, 1.127 + { 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0 }, 1.128 + { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }, 1.129 + /* semi-weak */ 1.130 + { 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe }, 1.131 + { 0xfe, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0xfe }, 1.132 + 1.133 + { 0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0 }, 1.134 + { 0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e }, 1.135 + 1.136 + { 0x00, 0xe0, 0x00, 0xe0, 0x00, 0x0f, 0x00, 0x0f }, 1.137 + { 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00 }, 1.138 + 1.139 + { 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe }, 1.140 + { 0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e }, 1.141 + 1.142 + { 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e }, 1.143 + { 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00 }, 1.144 + 1.145 + { 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe }, 1.146 + { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0 }, 1.147 +#else 1.148 + /* weak */ 1.149 + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, 1.150 + { 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e }, 1.151 + { 0xe0, 0xe0, 0xe0, 0xe0, 0xf1, 0xf1, 0xf1, 0xf1 }, 1.152 + { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }, 1.153 + 1.154 + /* semi-weak */ 1.155 + { 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe }, 1.156 + { 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01 }, 1.157 + 1.158 + { 0x1f, 0xe0, 0x1f, 0xe0, 0x0e, 0xf1, 0x0e, 0xf1 }, 1.159 + { 0xe0, 0x1f, 0xe0, 0x1f, 0xf1, 0x0e, 0xf1, 0x0e }, 1.160 + 1.161 + { 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1 }, 1.162 + { 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1, 0x01 }, 1.163 + 1.164 + { 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe }, 1.165 + { 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e }, 1.166 + 1.167 + { 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e }, 1.168 + { 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e, 0x01 }, 1.169 + 1.170 + { 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1, 0xfe }, 1.171 + { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1 } 1.172 +#endif 1.173 +}; 1.174 + 1.175 + 1.176 +static const int sftk_desWeakTableSize = sizeof(sftk_desWeakTable)/ 1.177 + sizeof(sftk_desWeakTable[0]); 1.178 + 1.179 +/* DES KEY Parity conversion table. Takes each byte/2 as an index, returns 1.180 + * that byte with the proper parity bit set */ 1.181 +static const unsigned char parityTable[256] = { 1.182 +/* Even...0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e */ 1.183 +/* E */ 0x01,0x02,0x04,0x07,0x08,0x0b,0x0d,0x0e, 1.184 +/* Odd....0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e */ 1.185 +/* O */ 0x10,0x13,0x15,0x16,0x19,0x1a,0x1c,0x1f, 1.186 +/* Odd....0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e */ 1.187 +/* O */ 0x20,0x23,0x25,0x26,0x29,0x2a,0x2c,0x2f, 1.188 +/* Even...0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e */ 1.189 +/* E */ 0x31,0x32,0x34,0x37,0x38,0x3b,0x3d,0x3e, 1.190 +/* Odd....0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e */ 1.191 +/* O */ 0x40,0x43,0x45,0x46,0x49,0x4a,0x4c,0x4f, 1.192 +/* Even...0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e */ 1.193 +/* E */ 0x51,0x52,0x54,0x57,0x58,0x5b,0x5d,0x5e, 1.194 +/* Even...0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e */ 1.195 +/* E */ 0x61,0x62,0x64,0x67,0x68,0x6b,0x6d,0x6e, 1.196 +/* Odd....0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e */ 1.197 +/* O */ 0x70,0x73,0x75,0x76,0x79,0x7a,0x7c,0x7f, 1.198 +/* Odd....0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e */ 1.199 +/* O */ 0x80,0x83,0x85,0x86,0x89,0x8a,0x8c,0x8f, 1.200 +/* Even...0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e */ 1.201 +/* E */ 0x91,0x92,0x94,0x97,0x98,0x9b,0x9d,0x9e, 1.202 +/* Even...0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae */ 1.203 +/* E */ 0xa1,0xa2,0xa4,0xa7,0xa8,0xab,0xad,0xae, 1.204 +/* Odd....0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe */ 1.205 +/* O */ 0xb0,0xb3,0xb5,0xb6,0xb9,0xba,0xbc,0xbf, 1.206 +/* Even...0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce */ 1.207 +/* E */ 0xc1,0xc2,0xc4,0xc7,0xc8,0xcb,0xcd,0xce, 1.208 +/* Odd....0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde */ 1.209 +/* O */ 0xd0,0xd3,0xd5,0xd6,0xd9,0xda,0xdc,0xdf, 1.210 +/* Odd....0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee */ 1.211 +/* O */ 0xe0,0xe3,0xe5,0xe6,0xe9,0xea,0xec,0xef, 1.212 +/* Even...0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe */ 1.213 +/* E */ 0xf1,0xf2,0xf4,0xf7,0xf8,0xfb,0xfd,0xfe, 1.214 +}; 1.215 + 1.216 +/* Mechanisms */ 1.217 +struct mechanismList { 1.218 + CK_MECHANISM_TYPE type; 1.219 + CK_MECHANISM_INFO info; 1.220 + PRBool privkey; 1.221 +}; 1.222 + 1.223 +/* 1.224 + * the following table includes a complete list of mechanism defined by 1.225 + * PKCS #11 version 2.01. Those Mechanisms not supported by this PKCS #11 1.226 + * module are ifdef'ed out. 1.227 + */ 1.228 +#define CKF_EN_DE CKF_ENCRYPT | CKF_DECRYPT 1.229 +#define CKF_WR_UN CKF_WRAP | CKF_UNWRAP 1.230 +#define CKF_SN_VR CKF_SIGN | CKF_VERIFY 1.231 +#define CKF_SN_RE CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER 1.232 + 1.233 +#define CKF_EN_DE_WR_UN CKF_EN_DE | CKF_WR_UN 1.234 +#define CKF_SN_VR_RE CKF_SN_VR | CKF_SN_RE 1.235 +#define CKF_DUZ_IT_ALL CKF_EN_DE_WR_UN | CKF_SN_VR_RE 1.236 + 1.237 +#define CKF_EC_PNU CKF_EC_FP | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS 1.238 + 1.239 +#define CKF_EC_BPNU CKF_EC_F_2M | CKF_EC_PNU 1.240 + 1.241 +#define CK_MAX 0xffffffff 1.242 + 1.243 +static const struct mechanismList mechanisms[] = { 1.244 + 1.245 + /* 1.246 + * PKCS #11 Mechanism List. 1.247 + * 1.248 + * The first argument is the PKCS #11 Mechanism we support. 1.249 + * The second argument is Mechanism info structure. It includes: 1.250 + * The minimum key size, 1.251 + * in bits for RSA, DSA, DH, EC*, KEA, RC2 and RC4 * algs. 1.252 + * in bytes for RC5, AES, Camellia, and CAST* 1.253 + * ignored for DES*, IDEA and FORTEZZA based 1.254 + * The maximum key size, 1.255 + * in bits for RSA, DSA, DH, EC*, KEA, RC2 and RC4 * algs. 1.256 + * in bytes for RC5, AES, Camellia, and CAST* 1.257 + * ignored for DES*, IDEA and FORTEZZA based 1.258 + * Flags 1.259 + * What operations are supported by this mechanism. 1.260 + * The third argument is a bool which tells if this mechanism is 1.261 + * supported in the database token. 1.262 + * 1.263 + */ 1.264 + 1.265 + /* ------------------------- RSA Operations ---------------------------*/ 1.266 + {CKM_RSA_PKCS_KEY_PAIR_GEN,{RSA_MIN_MODULUS_BITS,CK_MAX, 1.267 + CKF_GENERATE_KEY_PAIR},PR_TRUE}, 1.268 + {CKM_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, 1.269 + CKF_DUZ_IT_ALL}, PR_TRUE}, 1.270 + {CKM_RSA_PKCS_PSS, {RSA_MIN_MODULUS_BITS,CK_MAX, 1.271 + CKF_SN_VR}, PR_TRUE}, 1.272 + {CKM_RSA_PKCS_OAEP, {RSA_MIN_MODULUS_BITS,CK_MAX, 1.273 + CKF_EN_DE_WR_UN}, PR_TRUE}, 1.274 +#ifdef SFTK_RSA9796_SUPPORTED 1.275 + {CKM_RSA_9796, {RSA_MIN_MODULUS_BITS,CK_MAX, 1.276 + CKF_DUZ_IT_ALL}, PR_TRUE}, 1.277 +#endif 1.278 + {CKM_RSA_X_509, {RSA_MIN_MODULUS_BITS,CK_MAX, 1.279 + CKF_DUZ_IT_ALL}, PR_TRUE}, 1.280 + /* -------------- RSA Multipart Signing Operations -------------------- */ 1.281 + {CKM_MD2_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, 1.282 + CKF_SN_VR}, PR_TRUE}, 1.283 + {CKM_MD5_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, 1.284 + CKF_SN_VR}, PR_TRUE}, 1.285 + {CKM_SHA1_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, 1.286 + CKF_SN_VR}, PR_TRUE}, 1.287 + {CKM_SHA224_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, 1.288 + CKF_SN_VR}, PR_TRUE}, 1.289 + {CKM_SHA256_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, 1.290 + CKF_SN_VR}, PR_TRUE}, 1.291 + {CKM_SHA384_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, 1.292 + CKF_SN_VR}, PR_TRUE}, 1.293 + {CKM_SHA512_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, 1.294 + CKF_SN_VR}, PR_TRUE}, 1.295 + /* ------------------------- DSA Operations --------------------------- */ 1.296 + {CKM_DSA_KEY_PAIR_GEN, {DSA_MIN_P_BITS, DSA_MAX_P_BITS, 1.297 + CKF_GENERATE_KEY_PAIR}, PR_TRUE}, 1.298 + {CKM_DSA, {DSA_MIN_P_BITS, DSA_MAX_P_BITS, 1.299 + CKF_SN_VR}, PR_TRUE}, 1.300 + {CKM_DSA_PARAMETER_GEN, {DSA_MIN_P_BITS, DSA_MAX_P_BITS, 1.301 + CKF_GENERATE}, PR_TRUE}, 1.302 + {CKM_DSA_SHA1, {DSA_MIN_P_BITS, DSA_MAX_P_BITS, 1.303 + CKF_SN_VR}, PR_TRUE}, 1.304 + /* -------------------- Diffie Hellman Operations --------------------- */ 1.305 + /* no diffie hellman yet */ 1.306 + {CKM_DH_PKCS_KEY_PAIR_GEN, {DH_MIN_P_BITS, DH_MAX_P_BITS, 1.307 + CKF_GENERATE_KEY_PAIR}, PR_TRUE}, 1.308 + {CKM_DH_PKCS_DERIVE, {DH_MIN_P_BITS, DH_MAX_P_BITS, 1.309 + CKF_DERIVE}, PR_TRUE}, 1.310 +#ifndef NSS_DISABLE_ECC 1.311 + /* -------------------- Elliptic Curve Operations --------------------- */ 1.312 + {CKM_EC_KEY_PAIR_GEN, {EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, 1.313 + CKF_GENERATE_KEY_PAIR|CKF_EC_BPNU}, PR_TRUE}, 1.314 + {CKM_ECDH1_DERIVE, {EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, 1.315 + CKF_DERIVE|CKF_EC_BPNU}, PR_TRUE}, 1.316 + {CKM_ECDSA, {EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, 1.317 + CKF_SN_VR|CKF_EC_BPNU}, PR_TRUE}, 1.318 + {CKM_ECDSA_SHA1, {EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, 1.319 + CKF_SN_VR|CKF_EC_BPNU}, PR_TRUE}, 1.320 +#endif /* NSS_DISABLE_ECC */ 1.321 + /* ------------------------- RC2 Operations --------------------------- */ 1.322 + {CKM_RC2_KEY_GEN, {1, 128, CKF_GENERATE}, PR_TRUE}, 1.323 + {CKM_RC2_ECB, {1, 128, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.324 + {CKM_RC2_CBC, {1, 128, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.325 + {CKM_RC2_MAC, {1, 128, CKF_SN_VR}, PR_TRUE}, 1.326 + {CKM_RC2_MAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, 1.327 + {CKM_RC2_CBC_PAD, {1, 128, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.328 + /* ------------------------- RC4 Operations --------------------------- */ 1.329 + {CKM_RC4_KEY_GEN, {1, 256, CKF_GENERATE}, PR_FALSE}, 1.330 + {CKM_RC4, {1, 256, CKF_EN_DE_WR_UN}, PR_FALSE}, 1.331 + /* ------------------------- DES Operations --------------------------- */ 1.332 + {CKM_DES_KEY_GEN, { 8, 8, CKF_GENERATE}, PR_TRUE}, 1.333 + {CKM_DES_ECB, { 8, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.334 + {CKM_DES_CBC, { 8, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.335 + {CKM_DES_MAC, { 8, 8, CKF_SN_VR}, PR_TRUE}, 1.336 + {CKM_DES_MAC_GENERAL, { 8, 8, CKF_SN_VR}, PR_TRUE}, 1.337 + {CKM_DES_CBC_PAD, { 8, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.338 + {CKM_DES2_KEY_GEN, {24, 24, CKF_GENERATE}, PR_TRUE}, 1.339 + {CKM_DES3_KEY_GEN, {24, 24, CKF_GENERATE}, PR_TRUE }, 1.340 + {CKM_DES3_ECB, {24, 24, CKF_EN_DE_WR_UN}, PR_TRUE }, 1.341 + {CKM_DES3_CBC, {24, 24, CKF_EN_DE_WR_UN}, PR_TRUE }, 1.342 + {CKM_DES3_MAC, {24, 24, CKF_SN_VR}, PR_TRUE }, 1.343 + {CKM_DES3_MAC_GENERAL, {24, 24, CKF_SN_VR}, PR_TRUE }, 1.344 + {CKM_DES3_CBC_PAD, {24, 24, CKF_EN_DE_WR_UN}, PR_TRUE }, 1.345 + /* ------------------------- CDMF Operations --------------------------- */ 1.346 + {CKM_CDMF_KEY_GEN, {8, 8, CKF_GENERATE}, PR_TRUE}, 1.347 + {CKM_CDMF_ECB, {8, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.348 + {CKM_CDMF_CBC, {8, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.349 + {CKM_CDMF_MAC, {8, 8, CKF_SN_VR}, PR_TRUE}, 1.350 + {CKM_CDMF_MAC_GENERAL, {8, 8, CKF_SN_VR}, PR_TRUE}, 1.351 + {CKM_CDMF_CBC_PAD, {8, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.352 + /* ------------------------- AES Operations --------------------------- */ 1.353 + {CKM_AES_KEY_GEN, {16, 32, CKF_GENERATE}, PR_TRUE}, 1.354 + {CKM_AES_ECB, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.355 + {CKM_AES_CBC, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.356 + {CKM_AES_MAC, {16, 32, CKF_SN_VR}, PR_TRUE}, 1.357 + {CKM_AES_MAC_GENERAL, {16, 32, CKF_SN_VR}, PR_TRUE}, 1.358 + {CKM_AES_CBC_PAD, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.359 + {CKM_AES_CTS, {16, 32, CKF_EN_DE}, PR_TRUE}, 1.360 + {CKM_AES_CTR, {16, 32, CKF_EN_DE}, PR_TRUE}, 1.361 + {CKM_AES_GCM, {16, 32, CKF_EN_DE}, PR_TRUE}, 1.362 + /* ------------------------- Camellia Operations --------------------- */ 1.363 + {CKM_CAMELLIA_KEY_GEN, {16, 32, CKF_GENERATE}, PR_TRUE}, 1.364 + {CKM_CAMELLIA_ECB, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.365 + {CKM_CAMELLIA_CBC, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.366 + {CKM_CAMELLIA_MAC, {16, 32, CKF_SN_VR}, PR_TRUE}, 1.367 + {CKM_CAMELLIA_MAC_GENERAL, {16, 32, CKF_SN_VR}, PR_TRUE}, 1.368 + {CKM_CAMELLIA_CBC_PAD, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.369 + /* ------------------------- SEED Operations --------------------------- */ 1.370 + {CKM_SEED_KEY_GEN, {16, 16, CKF_GENERATE}, PR_TRUE}, 1.371 + {CKM_SEED_ECB, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.372 + {CKM_SEED_CBC, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.373 + {CKM_SEED_MAC, {16, 16, CKF_SN_VR}, PR_TRUE}, 1.374 + {CKM_SEED_MAC_GENERAL, {16, 16, CKF_SN_VR}, PR_TRUE}, 1.375 + {CKM_SEED_CBC_PAD, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.376 + /* ------------------------- Hashing Operations ----------------------- */ 1.377 + {CKM_MD2, {0, 0, CKF_DIGEST}, PR_FALSE}, 1.378 + {CKM_MD2_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE}, 1.379 + {CKM_MD2_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, 1.380 + {CKM_MD5, {0, 0, CKF_DIGEST}, PR_FALSE}, 1.381 + {CKM_MD5_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE}, 1.382 + {CKM_MD5_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, 1.383 + {CKM_SHA_1, {0, 0, CKF_DIGEST}, PR_FALSE}, 1.384 + {CKM_SHA_1_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE}, 1.385 + {CKM_SHA_1_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, 1.386 + {CKM_SHA224, {0, 0, CKF_DIGEST}, PR_FALSE}, 1.387 + {CKM_SHA224_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE}, 1.388 + {CKM_SHA224_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, 1.389 + {CKM_SHA256, {0, 0, CKF_DIGEST}, PR_FALSE}, 1.390 + {CKM_SHA256_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE}, 1.391 + {CKM_SHA256_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, 1.392 + {CKM_SHA384, {0, 0, CKF_DIGEST}, PR_FALSE}, 1.393 + {CKM_SHA384_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE}, 1.394 + {CKM_SHA384_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, 1.395 + {CKM_SHA512, {0, 0, CKF_DIGEST}, PR_FALSE}, 1.396 + {CKM_SHA512_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE}, 1.397 + {CKM_SHA512_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, 1.398 + {CKM_TLS_PRF_GENERAL, {0, 512, CKF_SN_VR}, PR_FALSE}, 1.399 + {CKM_NSS_TLS_PRF_GENERAL_SHA256, 1.400 + {0, 512, CKF_SN_VR}, PR_FALSE}, 1.401 + /* ------------------------- HKDF Operations -------------------------- */ 1.402 + {CKM_NSS_HKDF_SHA1, {1, 128, CKF_DERIVE}, PR_TRUE}, 1.403 + {CKM_NSS_HKDF_SHA256, {1, 128, CKF_DERIVE}, PR_TRUE}, 1.404 + {CKM_NSS_HKDF_SHA384, {1, 128, CKF_DERIVE}, PR_TRUE}, 1.405 + {CKM_NSS_HKDF_SHA512, {1, 128, CKF_DERIVE}, PR_TRUE}, 1.406 + /* ------------------------- CAST Operations --------------------------- */ 1.407 +#ifdef NSS_SOFTOKEN_DOES_CAST 1.408 + /* Cast operations are not supported ( yet? ) */ 1.409 + {CKM_CAST_KEY_GEN, {1, 8, CKF_GENERATE}, PR_TRUE}, 1.410 + {CKM_CAST_ECB, {1, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.411 + {CKM_CAST_CBC, {1, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.412 + {CKM_CAST_MAC, {1, 8, CKF_SN_VR}, PR_TRUE}, 1.413 + {CKM_CAST_MAC_GENERAL, {1, 8, CKF_SN_VR}, PR_TRUE}, 1.414 + {CKM_CAST_CBC_PAD, {1, 8, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.415 + {CKM_CAST3_KEY_GEN, {1, 16, CKF_GENERATE}, PR_TRUE}, 1.416 + {CKM_CAST3_ECB, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.417 + {CKM_CAST3_CBC, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.418 + {CKM_CAST3_MAC, {1, 16, CKF_SN_VR}, PR_TRUE}, 1.419 + {CKM_CAST3_MAC_GENERAL, {1, 16, CKF_SN_VR}, PR_TRUE}, 1.420 + {CKM_CAST3_CBC_PAD, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.421 + {CKM_CAST5_KEY_GEN, {1, 16, CKF_GENERATE}, PR_TRUE}, 1.422 + {CKM_CAST5_ECB, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.423 + {CKM_CAST5_CBC, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.424 + {CKM_CAST5_MAC, {1, 16, CKF_SN_VR}, PR_TRUE}, 1.425 + {CKM_CAST5_MAC_GENERAL, {1, 16, CKF_SN_VR}, PR_TRUE}, 1.426 + {CKM_CAST5_CBC_PAD, {1, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.427 +#endif 1.428 +#if NSS_SOFTOKEN_DOES_RC5 1.429 + /* ------------------------- RC5 Operations --------------------------- */ 1.430 + {CKM_RC5_KEY_GEN, {1, 32, CKF_GENERATE}, PR_TRUE}, 1.431 + {CKM_RC5_ECB, {1, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.432 + {CKM_RC5_CBC, {1, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.433 + {CKM_RC5_MAC, {1, 32, CKF_SN_VR}, PR_TRUE}, 1.434 + {CKM_RC5_MAC_GENERAL, {1, 32, CKF_SN_VR}, PR_TRUE}, 1.435 + {CKM_RC5_CBC_PAD, {1, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.436 +#endif 1.437 +#ifdef NSS_SOFTOKEN_DOES_IDEA 1.438 + /* ------------------------- IDEA Operations -------------------------- */ 1.439 + {CKM_IDEA_KEY_GEN, {16, 16, CKF_GENERATE}, PR_TRUE}, 1.440 + {CKM_IDEA_ECB, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.441 + {CKM_IDEA_CBC, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.442 + {CKM_IDEA_MAC, {16, 16, CKF_SN_VR}, PR_TRUE}, 1.443 + {CKM_IDEA_MAC_GENERAL, {16, 16, CKF_SN_VR}, PR_TRUE}, 1.444 + {CKM_IDEA_CBC_PAD, {16, 16, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.445 +#endif 1.446 + /* --------------------- Secret Key Operations ------------------------ */ 1.447 + {CKM_GENERIC_SECRET_KEY_GEN, {1, 32, CKF_GENERATE}, PR_TRUE}, 1.448 + {CKM_CONCATENATE_BASE_AND_KEY, {1, 32, CKF_GENERATE}, PR_FALSE}, 1.449 + {CKM_CONCATENATE_BASE_AND_DATA, {1, 32, CKF_GENERATE}, PR_FALSE}, 1.450 + {CKM_CONCATENATE_DATA_AND_BASE, {1, 32, CKF_GENERATE}, PR_FALSE}, 1.451 + {CKM_XOR_BASE_AND_DATA, {1, 32, CKF_GENERATE}, PR_FALSE}, 1.452 + {CKM_EXTRACT_KEY_FROM_KEY, {1, 32, CKF_DERIVE}, PR_FALSE}, 1.453 + /* ---------------------- SSL Key Derivations ------------------------- */ 1.454 + {CKM_SSL3_PRE_MASTER_KEY_GEN, {48, 48, CKF_GENERATE}, PR_FALSE}, 1.455 + {CKM_SSL3_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, 1.456 + {CKM_SSL3_MASTER_KEY_DERIVE_DH, {8, 128, CKF_DERIVE}, PR_FALSE}, 1.457 + {CKM_SSL3_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, 1.458 + {CKM_SSL3_MD5_MAC, { 0, 16, CKF_DERIVE}, PR_FALSE}, 1.459 + {CKM_SSL3_SHA1_MAC, { 0, 20, CKF_DERIVE}, PR_FALSE}, 1.460 + {CKM_MD5_KEY_DERIVATION, { 0, 16, CKF_DERIVE}, PR_FALSE}, 1.461 + {CKM_MD2_KEY_DERIVATION, { 0, 16, CKF_DERIVE}, PR_FALSE}, 1.462 + {CKM_SHA1_KEY_DERIVATION, { 0, 20, CKF_DERIVE}, PR_FALSE}, 1.463 + {CKM_SHA224_KEY_DERIVATION, { 0, 28, CKF_DERIVE}, PR_FALSE}, 1.464 + {CKM_SHA256_KEY_DERIVATION, { 0, 32, CKF_DERIVE}, PR_FALSE}, 1.465 + {CKM_SHA384_KEY_DERIVATION, { 0, 48, CKF_DERIVE}, PR_FALSE}, 1.466 + {CKM_SHA512_KEY_DERIVATION, { 0, 64, CKF_DERIVE}, PR_FALSE}, 1.467 + {CKM_TLS_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, 1.468 + {CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256, 1.469 + {48, 48, CKF_DERIVE}, PR_FALSE}, 1.470 + {CKM_TLS_MASTER_KEY_DERIVE_DH, {8, 128, CKF_DERIVE}, PR_FALSE}, 1.471 + {CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256, 1.472 + {8, 128, CKF_DERIVE}, PR_FALSE}, 1.473 + {CKM_TLS_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, 1.474 + {CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256, 1.475 + {48, 48, CKF_DERIVE}, PR_FALSE}, 1.476 + /* ---------------------- PBE Key Derivations ------------------------ */ 1.477 + {CKM_PBE_MD2_DES_CBC, {8, 8, CKF_DERIVE}, PR_TRUE}, 1.478 + {CKM_PBE_MD5_DES_CBC, {8, 8, CKF_DERIVE}, PR_TRUE}, 1.479 + /* ------------------ NETSCAPE PBE Key Derivations ------------------- */ 1.480 + {CKM_NETSCAPE_PBE_SHA1_DES_CBC, { 8, 8, CKF_GENERATE}, PR_TRUE}, 1.481 + {CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC, {24,24, CKF_GENERATE}, PR_TRUE}, 1.482 + {CKM_PBE_SHA1_DES3_EDE_CBC, {24,24, CKF_GENERATE}, PR_TRUE}, 1.483 + {CKM_PBE_SHA1_DES2_EDE_CBC, {24,24, CKF_GENERATE}, PR_TRUE}, 1.484 + {CKM_PBE_SHA1_RC2_40_CBC, {40,40, CKF_GENERATE}, PR_TRUE}, 1.485 + {CKM_PBE_SHA1_RC2_128_CBC, {128,128, CKF_GENERATE}, PR_TRUE}, 1.486 + {CKM_PBE_SHA1_RC4_40, {40,40, CKF_GENERATE}, PR_TRUE}, 1.487 + {CKM_PBE_SHA1_RC4_128, {128,128, CKF_GENERATE}, PR_TRUE}, 1.488 + {CKM_PBA_SHA1_WITH_SHA1_HMAC, {20,20, CKF_GENERATE}, PR_TRUE}, 1.489 + {CKM_PKCS5_PBKD2, {1,256, CKF_GENERATE}, PR_TRUE}, 1.490 + {CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN, {20,20, CKF_GENERATE}, PR_TRUE}, 1.491 + {CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN, {16,16, CKF_GENERATE}, PR_TRUE}, 1.492 + {CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN, {16,16, CKF_GENERATE}, PR_TRUE}, 1.493 + /* ------------------ AES Key Wrap (also encrypt) ------------------- */ 1.494 + {CKM_NETSCAPE_AES_KEY_WRAP, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.495 + {CKM_NETSCAPE_AES_KEY_WRAP_PAD, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE}, 1.496 + /* --------------------------- J-PAKE -------------------------------- */ 1.497 + {CKM_NSS_JPAKE_ROUND1_SHA1, {0, 0, CKF_GENERATE}, PR_TRUE}, 1.498 + {CKM_NSS_JPAKE_ROUND1_SHA256, {0, 0, CKF_GENERATE}, PR_TRUE}, 1.499 + {CKM_NSS_JPAKE_ROUND1_SHA384, {0, 0, CKF_GENERATE}, PR_TRUE}, 1.500 + {CKM_NSS_JPAKE_ROUND1_SHA512, {0, 0, CKF_GENERATE}, PR_TRUE}, 1.501 + {CKM_NSS_JPAKE_ROUND2_SHA1, {0, 0, CKF_DERIVE}, PR_TRUE}, 1.502 + {CKM_NSS_JPAKE_ROUND2_SHA256, {0, 0, CKF_DERIVE}, PR_TRUE}, 1.503 + {CKM_NSS_JPAKE_ROUND2_SHA384, {0, 0, CKF_DERIVE}, PR_TRUE}, 1.504 + {CKM_NSS_JPAKE_ROUND2_SHA512, {0, 0, CKF_DERIVE}, PR_TRUE}, 1.505 + {CKM_NSS_JPAKE_FINAL_SHA1, {0, 0, CKF_DERIVE}, PR_TRUE}, 1.506 + {CKM_NSS_JPAKE_FINAL_SHA256, {0, 0, CKF_DERIVE}, PR_TRUE}, 1.507 + {CKM_NSS_JPAKE_FINAL_SHA384, {0, 0, CKF_DERIVE}, PR_TRUE}, 1.508 + {CKM_NSS_JPAKE_FINAL_SHA512, {0, 0, CKF_DERIVE}, PR_TRUE}, 1.509 + /* -------------------- Constant Time TLS MACs ----------------------- */ 1.510 + {CKM_NSS_HMAC_CONSTANT_TIME, {0, 0, CKF_DIGEST}, PR_TRUE}, 1.511 + {CKM_NSS_SSL3_MAC_CONSTANT_TIME, {0, 0, CKF_DIGEST}, PR_TRUE} 1.512 +}; 1.513 +static const CK_ULONG mechanismCount = sizeof(mechanisms)/sizeof(mechanisms[0]); 1.514 + 1.515 +/* sigh global so fipstokn can read it */ 1.516 +PRBool nsc_init = PR_FALSE; 1.517 + 1.518 +#if defined(CHECK_FORK_PTHREAD) || defined(CHECK_FORK_MIXED) 1.519 + 1.520 +#include <pthread.h> 1.521 + 1.522 +static void ForkedChild(void) 1.523 +{ 1.524 + if (nsc_init || nsf_init) { 1.525 + forked = PR_TRUE; 1.526 + } 1.527 +} 1.528 + 1.529 +#endif 1.530 + 1.531 +static char * 1.532 +sftk_setStringName(const char *inString, char *buffer, int buffer_length, PRBool nullTerminate) 1.533 +{ 1.534 + int full_length, string_length; 1.535 + 1.536 + full_length = nullTerminate ? buffer_length -1 : buffer_length; 1.537 + string_length = PORT_Strlen(inString); 1.538 + /* 1.539 + * shorten the string, respecting utf8 encoding 1.540 + * to do so, we work backward from the end 1.541 + * bytes looking from the end are either: 1.542 + * - ascii [0x00,0x7f] 1.543 + * - the [2-n]th byte of a multibyte sequence 1.544 + * [0x3F,0xBF], i.e, most significant 2 bits are '10' 1.545 + * - the first byte of a multibyte sequence [0xC0,0xFD], 1.546 + * i.e, most significant 2 bits are '11' 1.547 + * 1.548 + * When the string is too long, we lop off any trailing '10' bytes, 1.549 + * if any. When these are all eliminated we lop off 1.550 + * one additional byte. Thus if we lopped any '10' 1.551 + * we'll be lopping a '11' byte (the first byte of the multibyte sequence), 1.552 + * otherwise we're lopping off an ascii character. 1.553 + * 1.554 + * To test for '10' bytes, we first AND it with 1.555 + * 11000000 (0xc0) so that we get 10000000 (0x80) if and only if 1.556 + * the byte starts with 10. We test for equality. 1.557 + */ 1.558 + while ( string_length > full_length ) { 1.559 + /* need to shorten */ 1.560 + while ( string_length > 0 && 1.561 + ((inString[string_length-1]&(char)0xc0) == (char)0x80)) { 1.562 + /* lop off '10' byte */ 1.563 + string_length--; 1.564 + } 1.565 + /* 1.566 + * test string_length in case bad data is received 1.567 + * and string consisted of all '10' bytes, 1.568 + * avoiding any infinite loop 1.569 + */ 1.570 + if ( string_length ) { 1.571 + /* remove either '11' byte or an asci byte */ 1.572 + string_length--; 1.573 + } 1.574 + } 1.575 + PORT_Memset(buffer,' ',full_length); 1.576 + if (nullTerminate) { 1.577 + buffer[full_length] = 0; 1.578 + } 1.579 + PORT_Memcpy(buffer,inString,string_length); 1.580 + return buffer; 1.581 +} 1.582 +/* 1.583 + * Configuration utils 1.584 + */ 1.585 +static CK_RV 1.586 +sftk_configure(const char *man, const char *libdes) 1.587 +{ 1.588 + 1.589 + /* make sure the internationalization was done correctly... */ 1.590 + if (man) { 1.591 + manufacturerID = sftk_setStringName(man,manufacturerID_space, 1.592 + sizeof(manufacturerID_space), PR_TRUE); 1.593 + } 1.594 + if (libdes) { 1.595 + libraryDescription = sftk_setStringName(libdes, 1.596 + libraryDescription_space, sizeof(libraryDescription_space), 1.597 + PR_TRUE); 1.598 + } 1.599 + 1.600 + return CKR_OK; 1.601 +} 1.602 + 1.603 +/* 1.604 + * ******************** Password Utilities ******************************* 1.605 + */ 1.606 + 1.607 +/* 1.608 + * see if the key DB password is enabled 1.609 + */ 1.610 +static PRBool 1.611 +sftk_hasNullPassword(SFTKSlot *slot, SFTKDBHandle *keydb) 1.612 +{ 1.613 + PRBool pwenabled; 1.614 + 1.615 + pwenabled = PR_FALSE; 1.616 + if (sftkdb_HasPasswordSet(keydb) == SECSuccess) { 1.617 + PRBool tokenRemoved = PR_FALSE; 1.618 + SECStatus rv = sftkdb_CheckPassword(keydb, "", &tokenRemoved); 1.619 + if (tokenRemoved) { 1.620 + sftk_CloseAllSessions(slot, PR_FALSE); 1.621 + } 1.622 + return (rv == SECSuccess); 1.623 + } 1.624 + 1.625 + return pwenabled; 1.626 +} 1.627 + 1.628 +/* 1.629 + * ******************** Object Creation Utilities *************************** 1.630 + */ 1.631 + 1.632 + 1.633 +/* Make sure a given attribute exists. If it doesn't, initialize it to 1.634 + * value and len 1.635 + */ 1.636 +CK_RV 1.637 +sftk_defaultAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type, 1.638 + const void *value, unsigned int len) 1.639 +{ 1.640 + if ( !sftk_hasAttribute(object, type)) { 1.641 + return sftk_AddAttributeType(object,type,value,len); 1.642 + } 1.643 + return CKR_OK; 1.644 +} 1.645 + 1.646 +/* 1.647 + * check the consistancy and initialize a Data Object 1.648 + */ 1.649 +static CK_RV 1.650 +sftk_handleDataObject(SFTKSession *session,SFTKObject *object) 1.651 +{ 1.652 + CK_RV crv; 1.653 + 1.654 + /* first reject private and token data objects */ 1.655 + if (sftk_isTrue(object,CKA_PRIVATE) || sftk_isTrue(object,CKA_TOKEN)) { 1.656 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.657 + } 1.658 + 1.659 + /* now just verify the required date fields */ 1.660 + crv = sftk_defaultAttribute(object,CKA_APPLICATION,NULL,0); 1.661 + if (crv != CKR_OK) return crv; 1.662 + crv = sftk_defaultAttribute(object,CKA_VALUE,NULL,0); 1.663 + if (crv != CKR_OK) return crv; 1.664 + 1.665 + return CKR_OK; 1.666 +} 1.667 + 1.668 +/* 1.669 + * check the consistancy and initialize a Certificate Object 1.670 + */ 1.671 +static CK_RV 1.672 +sftk_handleCertObject(SFTKSession *session,SFTKObject *object) 1.673 +{ 1.674 + CK_CERTIFICATE_TYPE type; 1.675 + SFTKAttribute *attribute; 1.676 + CK_RV crv; 1.677 + 1.678 + /* certificates must have a type */ 1.679 + if ( !sftk_hasAttribute(object,CKA_CERTIFICATE_TYPE) ) { 1.680 + return CKR_TEMPLATE_INCOMPLETE; 1.681 + } 1.682 + 1.683 + /* we can't store any certs private */ 1.684 + if (sftk_isTrue(object,CKA_PRIVATE)) { 1.685 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.686 + } 1.687 + 1.688 + /* We only support X.509 Certs for now */ 1.689 + attribute = sftk_FindAttribute(object,CKA_CERTIFICATE_TYPE); 1.690 + if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; 1.691 + type = *(CK_CERTIFICATE_TYPE *)attribute->attrib.pValue; 1.692 + sftk_FreeAttribute(attribute); 1.693 + 1.694 + if (type != CKC_X_509) { 1.695 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.696 + } 1.697 + 1.698 + /* X.509 Certificate */ 1.699 + 1.700 + /* make sure we have a cert */ 1.701 + if ( !sftk_hasAttribute(object,CKA_VALUE) ) { 1.702 + return CKR_TEMPLATE_INCOMPLETE; 1.703 + } 1.704 + 1.705 + /* in PKCS #11, Subject is a required field */ 1.706 + if ( !sftk_hasAttribute(object,CKA_SUBJECT) ) { 1.707 + return CKR_TEMPLATE_INCOMPLETE; 1.708 + } 1.709 + 1.710 + /* in PKCS #11, Issuer is a required field */ 1.711 + if ( !sftk_hasAttribute(object,CKA_ISSUER) ) { 1.712 + return CKR_TEMPLATE_INCOMPLETE; 1.713 + } 1.714 + 1.715 + /* in PKCS #11, Serial is a required field */ 1.716 + if ( !sftk_hasAttribute(object,CKA_SERIAL_NUMBER) ) { 1.717 + return CKR_TEMPLATE_INCOMPLETE; 1.718 + } 1.719 + 1.720 + /* add it to the object */ 1.721 + object->objectInfo = NULL; 1.722 + object->infoFree = (SFTKFree) NULL; 1.723 + 1.724 + /* now just verify the required date fields */ 1.725 + crv = sftk_defaultAttribute(object, CKA_ID, NULL, 0); 1.726 + if (crv != CKR_OK) { return crv; } 1.727 + 1.728 + if (sftk_isTrue(object,CKA_TOKEN)) { 1.729 + SFTKSlot *slot = session->slot; 1.730 + SFTKDBHandle *certHandle = sftk_getCertDB(slot); 1.731 + 1.732 + if (certHandle == NULL) { 1.733 + return CKR_TOKEN_WRITE_PROTECTED; 1.734 + } 1.735 + 1.736 + crv = sftkdb_write(certHandle, object, &object->handle); 1.737 + sftk_freeDB(certHandle); 1.738 + return crv; 1.739 + } 1.740 + 1.741 + return CKR_OK; 1.742 +} 1.743 + 1.744 +/* 1.745 + * check the consistancy and initialize a Trust Object 1.746 + */ 1.747 +static CK_RV 1.748 +sftk_handleTrustObject(SFTKSession *session,SFTKObject *object) 1.749 +{ 1.750 + /* we can't store any certs private */ 1.751 + if (sftk_isTrue(object,CKA_PRIVATE)) { 1.752 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.753 + } 1.754 + 1.755 + /* certificates must have a type */ 1.756 + if ( !sftk_hasAttribute(object,CKA_ISSUER) ) { 1.757 + return CKR_TEMPLATE_INCOMPLETE; 1.758 + } 1.759 + if ( !sftk_hasAttribute(object,CKA_SERIAL_NUMBER) ) { 1.760 + return CKR_TEMPLATE_INCOMPLETE; 1.761 + } 1.762 + if ( !sftk_hasAttribute(object,CKA_CERT_SHA1_HASH) ) { 1.763 + return CKR_TEMPLATE_INCOMPLETE; 1.764 + } 1.765 + if ( !sftk_hasAttribute(object,CKA_CERT_MD5_HASH) ) { 1.766 + return CKR_TEMPLATE_INCOMPLETE; 1.767 + } 1.768 + 1.769 + if (sftk_isTrue(object,CKA_TOKEN)) { 1.770 + SFTKSlot *slot = session->slot; 1.771 + SFTKDBHandle *certHandle = sftk_getCertDB(slot); 1.772 + CK_RV crv; 1.773 + 1.774 + if (certHandle == NULL) { 1.775 + return CKR_TOKEN_WRITE_PROTECTED; 1.776 + } 1.777 + 1.778 + crv = sftkdb_write(certHandle, object, &object->handle); 1.779 + sftk_freeDB(certHandle); 1.780 + return crv; 1.781 + } 1.782 + 1.783 + return CKR_OK; 1.784 +} 1.785 + 1.786 +/* 1.787 + * check the consistancy and initialize a Trust Object 1.788 + */ 1.789 +static CK_RV 1.790 +sftk_handleSMimeObject(SFTKSession *session,SFTKObject *object) 1.791 +{ 1.792 + 1.793 + /* we can't store any certs private */ 1.794 + if (sftk_isTrue(object,CKA_PRIVATE)) { 1.795 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.796 + } 1.797 + 1.798 + /* certificates must have a type */ 1.799 + if ( !sftk_hasAttribute(object,CKA_SUBJECT) ) { 1.800 + return CKR_TEMPLATE_INCOMPLETE; 1.801 + } 1.802 + if ( !sftk_hasAttribute(object,CKA_NETSCAPE_EMAIL) ) { 1.803 + return CKR_TEMPLATE_INCOMPLETE; 1.804 + } 1.805 + 1.806 + if (sftk_isTrue(object,CKA_TOKEN)) { 1.807 + SFTKSlot *slot = session->slot; 1.808 + SFTKDBHandle *certHandle; 1.809 + CK_RV crv; 1.810 + 1.811 + PORT_Assert(slot); 1.812 + if (slot == NULL) { 1.813 + return CKR_SESSION_HANDLE_INVALID; 1.814 + } 1.815 + 1.816 + certHandle = sftk_getCertDB(slot); 1.817 + if (certHandle == NULL) { 1.818 + return CKR_TOKEN_WRITE_PROTECTED; 1.819 + } 1.820 + 1.821 + crv = sftkdb_write(certHandle, object, &object->handle); 1.822 + sftk_freeDB(certHandle); 1.823 + return crv; 1.824 + } 1.825 + 1.826 + return CKR_OK; 1.827 +} 1.828 + 1.829 +/* 1.830 + * check the consistancy and initialize a Trust Object 1.831 + */ 1.832 +static CK_RV 1.833 +sftk_handleCrlObject(SFTKSession *session,SFTKObject *object) 1.834 +{ 1.835 + 1.836 + /* we can't store any certs private */ 1.837 + if (sftk_isTrue(object,CKA_PRIVATE)) { 1.838 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.839 + } 1.840 + 1.841 + /* certificates must have a type */ 1.842 + if ( !sftk_hasAttribute(object,CKA_SUBJECT) ) { 1.843 + return CKR_TEMPLATE_INCOMPLETE; 1.844 + } 1.845 + if ( !sftk_hasAttribute(object,CKA_VALUE) ) { 1.846 + return CKR_TEMPLATE_INCOMPLETE; 1.847 + } 1.848 + 1.849 + if (sftk_isTrue(object,CKA_TOKEN)) { 1.850 + SFTKSlot *slot = session->slot; 1.851 + SFTKDBHandle *certHandle = sftk_getCertDB(slot); 1.852 + CK_RV crv; 1.853 + 1.854 + if (certHandle == NULL) { 1.855 + return CKR_TOKEN_WRITE_PROTECTED; 1.856 + } 1.857 + 1.858 + crv = sftkdb_write(certHandle, object, &object->handle); 1.859 + sftk_freeDB(certHandle); 1.860 + return crv; 1.861 + } 1.862 + 1.863 + return CKR_OK; 1.864 +} 1.865 + 1.866 +/* 1.867 + * check the consistancy and initialize a Public Key Object 1.868 + */ 1.869 +static CK_RV 1.870 +sftk_handlePublicKeyObject(SFTKSession *session, SFTKObject *object, 1.871 + CK_KEY_TYPE key_type) 1.872 +{ 1.873 + CK_BBOOL encrypt = CK_TRUE; 1.874 + CK_BBOOL recover = CK_TRUE; 1.875 + CK_BBOOL wrap = CK_TRUE; 1.876 + CK_BBOOL derive = CK_FALSE; 1.877 + CK_BBOOL verify = CK_TRUE; 1.878 + CK_RV crv; 1.879 + 1.880 + switch (key_type) { 1.881 + case CKK_RSA: 1.882 + crv = sftk_ConstrainAttribute(object, CKA_MODULUS, 1.883 + RSA_MIN_MODULUS_BITS, 0, 0); 1.884 + if (crv != CKR_OK) { 1.885 + return crv; 1.886 + } 1.887 + crv = sftk_ConstrainAttribute(object, CKA_PUBLIC_EXPONENT, 2, 0, 0); 1.888 + if (crv != CKR_OK) { 1.889 + return crv; 1.890 + } 1.891 + break; 1.892 + case CKK_DSA: 1.893 + crv = sftk_ConstrainAttribute(object, CKA_SUBPRIME, 1.894 + DSA_MIN_Q_BITS, DSA_MAX_Q_BITS, 0); 1.895 + if (crv != CKR_OK) { 1.896 + return crv; 1.897 + } 1.898 + crv = sftk_ConstrainAttribute(object, CKA_PRIME, 1.899 + DSA_MIN_P_BITS, DSA_MAX_P_BITS, 64); 1.900 + if (crv != CKR_OK) { 1.901 + return crv; 1.902 + } 1.903 + crv = sftk_ConstrainAttribute(object, CKA_BASE, 2, DSA_MAX_P_BITS, 0); 1.904 + if (crv != CKR_OK) { 1.905 + return crv; 1.906 + } 1.907 + crv = sftk_ConstrainAttribute(object, CKA_VALUE, 2, DSA_MAX_P_BITS, 0); 1.908 + if (crv != CKR_OK) { 1.909 + return crv; 1.910 + } 1.911 + encrypt = CK_FALSE; 1.912 + recover = CK_FALSE; 1.913 + wrap = CK_FALSE; 1.914 + break; 1.915 + case CKK_DH: 1.916 + crv = sftk_ConstrainAttribute(object, CKA_PRIME, 1.917 + DH_MIN_P_BITS, DH_MAX_P_BITS, 0); 1.918 + if (crv != CKR_OK) { 1.919 + return crv; 1.920 + } 1.921 + crv = sftk_ConstrainAttribute(object, CKA_BASE, 2, DH_MAX_P_BITS, 0); 1.922 + if (crv != CKR_OK) { 1.923 + return crv; 1.924 + } 1.925 + crv = sftk_ConstrainAttribute(object, CKA_VALUE, 2, DH_MAX_P_BITS, 0); 1.926 + if (crv != CKR_OK) { 1.927 + return crv; 1.928 + } 1.929 + verify = CK_FALSE; 1.930 + derive = CK_TRUE; 1.931 + encrypt = CK_FALSE; 1.932 + recover = CK_FALSE; 1.933 + wrap = CK_FALSE; 1.934 + break; 1.935 +#ifndef NSS_DISABLE_ECC 1.936 + case CKK_EC: 1.937 + if ( !sftk_hasAttribute(object, CKA_EC_PARAMS)) { 1.938 + return CKR_TEMPLATE_INCOMPLETE; 1.939 + } 1.940 + if ( !sftk_hasAttribute(object, CKA_EC_POINT)) { 1.941 + return CKR_TEMPLATE_INCOMPLETE; 1.942 + } 1.943 + derive = CK_TRUE; /* for ECDH */ 1.944 + verify = CK_TRUE; /* for ECDSA */ 1.945 + encrypt = CK_FALSE; 1.946 + recover = CK_FALSE; 1.947 + wrap = CK_FALSE; 1.948 + break; 1.949 +#endif /* NSS_DISABLE_ECC */ 1.950 + default: 1.951 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.952 + } 1.953 + 1.954 + /* make sure the required fields exist */ 1.955 + crv = sftk_defaultAttribute(object,CKA_SUBJECT,NULL,0); 1.956 + if (crv != CKR_OK) return crv; 1.957 + crv = sftk_defaultAttribute(object,CKA_ENCRYPT,&encrypt,sizeof(CK_BBOOL)); 1.958 + if (crv != CKR_OK) return crv; 1.959 + crv = sftk_defaultAttribute(object,CKA_VERIFY,&verify,sizeof(CK_BBOOL)); 1.960 + if (crv != CKR_OK) return crv; 1.961 + crv = sftk_defaultAttribute(object,CKA_VERIFY_RECOVER, 1.962 + &recover,sizeof(CK_BBOOL)); 1.963 + if (crv != CKR_OK) return crv; 1.964 + crv = sftk_defaultAttribute(object,CKA_WRAP,&wrap,sizeof(CK_BBOOL)); 1.965 + if (crv != CKR_OK) return crv; 1.966 + crv = sftk_defaultAttribute(object,CKA_DERIVE,&derive,sizeof(CK_BBOOL)); 1.967 + if (crv != CKR_OK) return crv; 1.968 + 1.969 + object->objectInfo = sftk_GetPubKey(object,key_type, &crv); 1.970 + if (object->objectInfo == NULL) { 1.971 + return crv; 1.972 + } 1.973 + object->infoFree = (SFTKFree) nsslowkey_DestroyPublicKey; 1.974 + 1.975 + /* Check that an imported EC key is valid */ 1.976 + if (key_type == CKK_EC) { 1.977 + NSSLOWKEYPublicKey *pubKey = (NSSLOWKEYPublicKey*) object->objectInfo; 1.978 + SECStatus rv = EC_ValidatePublicKey(&pubKey->u.ec.ecParams, 1.979 + &pubKey->u.ec.publicValue); 1.980 + 1.981 + if (rv != SECSuccess) { 1.982 + return CKR_TEMPLATE_INCONSISTENT; 1.983 + } 1.984 + } 1.985 + 1.986 + if (sftk_isTrue(object,CKA_TOKEN)) { 1.987 + SFTKSlot *slot = session->slot; 1.988 + SFTKDBHandle *certHandle = sftk_getCertDB(slot); 1.989 + 1.990 + if (certHandle == NULL) { 1.991 + return CKR_TOKEN_WRITE_PROTECTED; 1.992 + } 1.993 + 1.994 + crv = sftkdb_write(certHandle, object, &object->handle); 1.995 + sftk_freeDB(certHandle); 1.996 + return crv; 1.997 + } 1.998 + 1.999 + return CKR_OK; 1.1000 +} 1.1001 + 1.1002 +static NSSLOWKEYPrivateKey * 1.1003 +sftk_mkPrivKey(SFTKObject *object,CK_KEY_TYPE key, CK_RV *rvp); 1.1004 + 1.1005 +static SECStatus 1.1006 +sftk_verifyRSAPrivateKey(SFTKObject *object, PRBool fillIfNeeded); 1.1007 + 1.1008 +/* 1.1009 + * check the consistancy and initialize a Private Key Object 1.1010 + */ 1.1011 +static CK_RV 1.1012 +sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE key_type) 1.1013 +{ 1.1014 + CK_BBOOL cktrue = CK_TRUE; 1.1015 + CK_BBOOL encrypt = CK_TRUE; 1.1016 + CK_BBOOL sign = CK_FALSE; 1.1017 + CK_BBOOL recover = CK_TRUE; 1.1018 + CK_BBOOL wrap = CK_TRUE; 1.1019 + CK_BBOOL derive = CK_TRUE; 1.1020 + CK_BBOOL ckfalse = CK_FALSE; 1.1021 + PRBool createObjectInfo = PR_TRUE; 1.1022 + PRBool fillPrivateKey = PR_FALSE; 1.1023 + int missing_rsa_mod_component = 0; 1.1024 + int missing_rsa_exp_component = 0; 1.1025 + int missing_rsa_crt_component = 0; 1.1026 + 1.1027 + SECItem mod; 1.1028 + CK_RV crv; 1.1029 + SECStatus rv; 1.1030 + 1.1031 + switch (key_type) { 1.1032 + case CKK_RSA: 1.1033 + if ( !sftk_hasAttribute(object, CKA_MODULUS)) { 1.1034 + missing_rsa_mod_component++; 1.1035 + } 1.1036 + if ( !sftk_hasAttribute(object, CKA_PUBLIC_EXPONENT)) { 1.1037 + missing_rsa_exp_component++; 1.1038 + } 1.1039 + if ( !sftk_hasAttribute(object, CKA_PRIVATE_EXPONENT)) { 1.1040 + missing_rsa_exp_component++; 1.1041 + } 1.1042 + if ( !sftk_hasAttribute(object, CKA_PRIME_1)) { 1.1043 + missing_rsa_mod_component++; 1.1044 + } 1.1045 + if ( !sftk_hasAttribute(object, CKA_PRIME_2)) { 1.1046 + missing_rsa_mod_component++; 1.1047 + } 1.1048 + if ( !sftk_hasAttribute(object, CKA_EXPONENT_1)) { 1.1049 + missing_rsa_crt_component++; 1.1050 + } 1.1051 + if ( !sftk_hasAttribute(object, CKA_EXPONENT_2)) { 1.1052 + missing_rsa_crt_component++; 1.1053 + } 1.1054 + if ( !sftk_hasAttribute(object, CKA_COEFFICIENT)) { 1.1055 + missing_rsa_crt_component++; 1.1056 + } 1.1057 + if (missing_rsa_mod_component || missing_rsa_exp_component || 1.1058 + missing_rsa_crt_component) { 1.1059 + /* we are missing a component, see if we have enough to rebuild 1.1060 + * the rest */ 1.1061 + int have_exp = 2- missing_rsa_exp_component; 1.1062 + int have_component = 5- 1.1063 + (missing_rsa_exp_component+missing_rsa_mod_component); 1.1064 + 1.1065 + if ((have_exp == 0) || (have_component < 3)) { 1.1066 + /* nope, not enough to reconstruct the private key */ 1.1067 + return CKR_TEMPLATE_INCOMPLETE; 1.1068 + } 1.1069 + fillPrivateKey = PR_TRUE; 1.1070 + } 1.1071 + /*verify the parameters for consistency*/ 1.1072 + rv = sftk_verifyRSAPrivateKey(object, fillPrivateKey); 1.1073 + if (rv != SECSuccess) { 1.1074 + return CKR_TEMPLATE_INCOMPLETE; 1.1075 + } 1.1076 + 1.1077 + /* make sure Netscape DB attribute is set correctly */ 1.1078 + crv = sftk_Attribute2SSecItem(NULL, &mod, object, CKA_MODULUS); 1.1079 + if (crv != CKR_OK) return crv; 1.1080 + crv = sftk_forceAttribute(object, CKA_NETSCAPE_DB, 1.1081 + sftk_item_expand(&mod)); 1.1082 + if (mod.data) PORT_Free(mod.data); 1.1083 + if (crv != CKR_OK) return crv; 1.1084 + 1.1085 + sign = CK_TRUE; 1.1086 + derive = CK_FALSE; 1.1087 + break; 1.1088 + case CKK_DSA: 1.1089 + if ( !sftk_hasAttribute(object, CKA_SUBPRIME)) { 1.1090 + return CKR_TEMPLATE_INCOMPLETE; 1.1091 + } 1.1092 + sign = CK_TRUE; 1.1093 + derive = CK_FALSE; 1.1094 + /* fall through */ 1.1095 + case CKK_DH: 1.1096 + if ( !sftk_hasAttribute(object, CKA_PRIME)) { 1.1097 + return CKR_TEMPLATE_INCOMPLETE; 1.1098 + } 1.1099 + if ( !sftk_hasAttribute(object, CKA_BASE)) { 1.1100 + return CKR_TEMPLATE_INCOMPLETE; 1.1101 + } 1.1102 + if ( !sftk_hasAttribute(object, CKA_VALUE)) { 1.1103 + return CKR_TEMPLATE_INCOMPLETE; 1.1104 + } 1.1105 + encrypt = CK_FALSE; 1.1106 + recover = CK_FALSE; 1.1107 + wrap = CK_FALSE; 1.1108 + break; 1.1109 +#ifndef NSS_DISABLE_ECC 1.1110 + case CKK_EC: 1.1111 + if ( !sftk_hasAttribute(object, CKA_EC_PARAMS)) { 1.1112 + return CKR_TEMPLATE_INCOMPLETE; 1.1113 + } 1.1114 + if ( !sftk_hasAttribute(object, CKA_VALUE)) { 1.1115 + return CKR_TEMPLATE_INCOMPLETE; 1.1116 + } 1.1117 + encrypt = CK_FALSE; 1.1118 + sign = CK_TRUE; 1.1119 + recover = CK_FALSE; 1.1120 + wrap = CK_FALSE; 1.1121 + break; 1.1122 +#endif /* NSS_DISABLE_ECC */ 1.1123 + case CKK_NSS_JPAKE_ROUND1: 1.1124 + if (!sftk_hasAttribute(object, CKA_PRIME) || 1.1125 + !sftk_hasAttribute(object, CKA_SUBPRIME) || 1.1126 + !sftk_hasAttribute(object, CKA_BASE)) { 1.1127 + return CKR_TEMPLATE_INCOMPLETE; 1.1128 + } 1.1129 + /* fall through */ 1.1130 + case CKK_NSS_JPAKE_ROUND2: 1.1131 + /* CKA_NSS_JPAKE_SIGNERID and CKA_NSS_JPAKE_PEERID are checked in 1.1132 + the J-PAKE code. */ 1.1133 + encrypt = sign = recover = wrap = CK_FALSE; 1.1134 + derive = CK_TRUE; 1.1135 + createObjectInfo = PR_FALSE; 1.1136 + break; 1.1137 + default: 1.1138 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.1139 + } 1.1140 + crv = sftk_defaultAttribute(object,CKA_SUBJECT,NULL,0); 1.1141 + if (crv != CKR_OK) return crv; 1.1142 + crv = sftk_defaultAttribute(object,CKA_SENSITIVE,&cktrue,sizeof(CK_BBOOL)); 1.1143 + if (crv != CKR_OK) return crv; 1.1144 + crv = sftk_defaultAttribute(object,CKA_EXTRACTABLE,&cktrue,sizeof(CK_BBOOL)); 1.1145 + if (crv != CKR_OK) return crv; 1.1146 + crv = sftk_defaultAttribute(object,CKA_DECRYPT,&encrypt,sizeof(CK_BBOOL)); 1.1147 + if (crv != CKR_OK) return crv; 1.1148 + crv = sftk_defaultAttribute(object,CKA_SIGN,&sign,sizeof(CK_BBOOL)); 1.1149 + if (crv != CKR_OK) return crv; 1.1150 + crv = sftk_defaultAttribute(object,CKA_SIGN_RECOVER,&recover, 1.1151 + sizeof(CK_BBOOL)); 1.1152 + if (crv != CKR_OK) return crv; 1.1153 + crv = sftk_defaultAttribute(object,CKA_UNWRAP,&wrap,sizeof(CK_BBOOL)); 1.1154 + if (crv != CKR_OK) return crv; 1.1155 + crv = sftk_defaultAttribute(object,CKA_DERIVE,&derive,sizeof(CK_BBOOL)); 1.1156 + if (crv != CKR_OK) return crv; 1.1157 + /* the next two bits get modified only in the key gen and token cases */ 1.1158 + crv = sftk_forceAttribute(object,CKA_ALWAYS_SENSITIVE, 1.1159 + &ckfalse,sizeof(CK_BBOOL)); 1.1160 + if (crv != CKR_OK) return crv; 1.1161 + crv = sftk_forceAttribute(object,CKA_NEVER_EXTRACTABLE, 1.1162 + &ckfalse,sizeof(CK_BBOOL)); 1.1163 + if (crv != CKR_OK) return crv; 1.1164 + 1.1165 + /* should we check the non-token RSA private keys? */ 1.1166 + 1.1167 + if (sftk_isTrue(object,CKA_TOKEN)) { 1.1168 + SFTKSlot *slot = session->slot; 1.1169 + SFTKDBHandle *keyHandle = sftk_getKeyDB(slot); 1.1170 + 1.1171 + if (keyHandle == NULL) { 1.1172 + return CKR_TOKEN_WRITE_PROTECTED; 1.1173 + } 1.1174 + 1.1175 + crv = sftkdb_write(keyHandle, object, &object->handle); 1.1176 + sftk_freeDB(keyHandle); 1.1177 + return crv; 1.1178 + } else if (createObjectInfo) { 1.1179 + object->objectInfo = sftk_mkPrivKey(object,key_type,&crv); 1.1180 + if (object->objectInfo == NULL) return crv; 1.1181 + object->infoFree = (SFTKFree) nsslowkey_DestroyPrivateKey; 1.1182 + } 1.1183 + return CKR_OK; 1.1184 +} 1.1185 + 1.1186 +/* forward declare the DES formating function for handleSecretKey */ 1.1187 +void sftk_FormatDESKey(unsigned char *key, int length); 1.1188 + 1.1189 +/* Validate secret key data, and set defaults */ 1.1190 +static CK_RV 1.1191 +validateSecretKey(SFTKSession *session, SFTKObject *object, 1.1192 + CK_KEY_TYPE key_type, PRBool isFIPS) 1.1193 +{ 1.1194 + CK_RV crv; 1.1195 + CK_BBOOL cktrue = CK_TRUE; 1.1196 + CK_BBOOL ckfalse = CK_FALSE; 1.1197 + SFTKAttribute *attribute = NULL; 1.1198 + unsigned long requiredLen; 1.1199 + 1.1200 + crv = sftk_defaultAttribute(object,CKA_SENSITIVE, 1.1201 + isFIPS?&cktrue:&ckfalse,sizeof(CK_BBOOL)); 1.1202 + if (crv != CKR_OK) return crv; 1.1203 + crv = sftk_defaultAttribute(object,CKA_EXTRACTABLE, 1.1204 + &cktrue,sizeof(CK_BBOOL)); 1.1205 + if (crv != CKR_OK) return crv; 1.1206 + crv = sftk_defaultAttribute(object,CKA_ENCRYPT,&cktrue,sizeof(CK_BBOOL)); 1.1207 + if (crv != CKR_OK) return crv; 1.1208 + crv = sftk_defaultAttribute(object,CKA_DECRYPT,&cktrue,sizeof(CK_BBOOL)); 1.1209 + if (crv != CKR_OK) return crv; 1.1210 + crv = sftk_defaultAttribute(object,CKA_SIGN,&ckfalse,sizeof(CK_BBOOL)); 1.1211 + if (crv != CKR_OK) return crv; 1.1212 + crv = sftk_defaultAttribute(object,CKA_VERIFY,&ckfalse,sizeof(CK_BBOOL)); 1.1213 + if (crv != CKR_OK) return crv; 1.1214 + crv = sftk_defaultAttribute(object,CKA_WRAP,&cktrue,sizeof(CK_BBOOL)); 1.1215 + if (crv != CKR_OK) return crv; 1.1216 + crv = sftk_defaultAttribute(object,CKA_UNWRAP,&cktrue,sizeof(CK_BBOOL)); 1.1217 + if (crv != CKR_OK) return crv; 1.1218 + 1.1219 + if ( !sftk_hasAttribute(object, CKA_VALUE)) { 1.1220 + return CKR_TEMPLATE_INCOMPLETE; 1.1221 + } 1.1222 + /* the next two bits get modified only in the key gen and token cases */ 1.1223 + crv = sftk_forceAttribute(object,CKA_ALWAYS_SENSITIVE, 1.1224 + &ckfalse,sizeof(CK_BBOOL)); 1.1225 + if (crv != CKR_OK) return crv; 1.1226 + crv = sftk_forceAttribute(object,CKA_NEVER_EXTRACTABLE, 1.1227 + &ckfalse,sizeof(CK_BBOOL)); 1.1228 + if (crv != CKR_OK) return crv; 1.1229 + 1.1230 + /* some types of keys have a value length */ 1.1231 + crv = CKR_OK; 1.1232 + switch (key_type) { 1.1233 + /* force CKA_VALUE_LEN to be set */ 1.1234 + case CKK_GENERIC_SECRET: 1.1235 + case CKK_RC2: 1.1236 + case CKK_RC4: 1.1237 +#if NSS_SOFTOKEN_DOES_RC5 1.1238 + case CKK_RC5: 1.1239 +#endif 1.1240 +#ifdef NSS_SOFTOKEN_DOES_CAST 1.1241 + case CKK_CAST: 1.1242 + case CKK_CAST3: 1.1243 + case CKK_CAST5: 1.1244 +#endif 1.1245 +#if NSS_SOFTOKEN_DOES_IDEA 1.1246 + case CKK_IDEA: 1.1247 +#endif 1.1248 + attribute = sftk_FindAttribute(object,CKA_VALUE); 1.1249 + /* shouldn't happen */ 1.1250 + if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; 1.1251 + crv = sftk_forceAttribute(object, CKA_VALUE_LEN, 1.1252 + &attribute->attrib.ulValueLen, sizeof(CK_ULONG)); 1.1253 + sftk_FreeAttribute(attribute); 1.1254 + break; 1.1255 + /* force the value to have the correct parity */ 1.1256 + case CKK_DES: 1.1257 + case CKK_DES2: 1.1258 + case CKK_DES3: 1.1259 + case CKK_CDMF: 1.1260 + attribute = sftk_FindAttribute(object,CKA_VALUE); 1.1261 + /* shouldn't happen */ 1.1262 + if (attribute == NULL) 1.1263 + return CKR_TEMPLATE_INCOMPLETE; 1.1264 + requiredLen = sftk_MapKeySize(key_type); 1.1265 + if (attribute->attrib.ulValueLen != requiredLen) { 1.1266 + sftk_FreeAttribute(attribute); 1.1267 + return CKR_KEY_SIZE_RANGE; 1.1268 + } 1.1269 + sftk_FormatDESKey((unsigned char*)attribute->attrib.pValue, 1.1270 + attribute->attrib.ulValueLen); 1.1271 + sftk_FreeAttribute(attribute); 1.1272 + break; 1.1273 + case CKK_AES: 1.1274 + attribute = sftk_FindAttribute(object,CKA_VALUE); 1.1275 + /* shouldn't happen */ 1.1276 + if (attribute == NULL) 1.1277 + return CKR_TEMPLATE_INCOMPLETE; 1.1278 + if (attribute->attrib.ulValueLen != 16 && 1.1279 + attribute->attrib.ulValueLen != 24 && 1.1280 + attribute->attrib.ulValueLen != 32) { 1.1281 + sftk_FreeAttribute(attribute); 1.1282 + return CKR_KEY_SIZE_RANGE; 1.1283 + } 1.1284 + crv = sftk_forceAttribute(object, CKA_VALUE_LEN, 1.1285 + &attribute->attrib.ulValueLen, sizeof(CK_ULONG)); 1.1286 + sftk_FreeAttribute(attribute); 1.1287 + break; 1.1288 + default: 1.1289 + break; 1.1290 + } 1.1291 + 1.1292 + return crv; 1.1293 +} 1.1294 + 1.1295 +/* 1.1296 + * check the consistancy and initialize a Secret Key Object 1.1297 + */ 1.1298 +static CK_RV 1.1299 +sftk_handleSecretKeyObject(SFTKSession *session,SFTKObject *object, 1.1300 + CK_KEY_TYPE key_type, PRBool isFIPS) 1.1301 +{ 1.1302 + CK_RV crv; 1.1303 + 1.1304 + /* First validate and set defaults */ 1.1305 + crv = validateSecretKey(session, object, key_type, isFIPS); 1.1306 + if (crv != CKR_OK) goto loser; 1.1307 + 1.1308 + /* If the object is a TOKEN object, store in the database */ 1.1309 + if (sftk_isTrue(object,CKA_TOKEN)) { 1.1310 + SFTKSlot *slot = session->slot; 1.1311 + SFTKDBHandle *keyHandle = sftk_getKeyDB(slot); 1.1312 + CK_RV crv; 1.1313 + 1.1314 + if (keyHandle == NULL) { 1.1315 + return CKR_TOKEN_WRITE_PROTECTED; 1.1316 + } 1.1317 + 1.1318 + crv = sftkdb_write(keyHandle, object, &object->handle); 1.1319 + sftk_freeDB(keyHandle); 1.1320 + return crv; 1.1321 + } 1.1322 + 1.1323 +loser: 1.1324 + 1.1325 + return crv; 1.1326 +} 1.1327 + 1.1328 +/* 1.1329 + * check the consistancy and initialize a Key Object 1.1330 + */ 1.1331 +static CK_RV 1.1332 +sftk_handleKeyObject(SFTKSession *session, SFTKObject *object) 1.1333 +{ 1.1334 + SFTKAttribute *attribute; 1.1335 + CK_KEY_TYPE key_type; 1.1336 + CK_BBOOL ckfalse = CK_FALSE; 1.1337 + CK_RV crv; 1.1338 + 1.1339 + /* verify the required fields */ 1.1340 + if ( !sftk_hasAttribute(object,CKA_KEY_TYPE) ) { 1.1341 + return CKR_TEMPLATE_INCOMPLETE; 1.1342 + } 1.1343 + 1.1344 + /* now verify the common fields */ 1.1345 + crv = sftk_defaultAttribute(object,CKA_ID,NULL,0); 1.1346 + if (crv != CKR_OK) return crv; 1.1347 + crv = sftk_defaultAttribute(object,CKA_START_DATE,NULL,0); 1.1348 + if (crv != CKR_OK) return crv; 1.1349 + crv = sftk_defaultAttribute(object,CKA_END_DATE,NULL,0); 1.1350 + if (crv != CKR_OK) return crv; 1.1351 + /* CKA_DERIVE is common to all keys, but it's default value is 1.1352 + * key dependent */ 1.1353 + crv = sftk_defaultAttribute(object,CKA_LOCAL,&ckfalse,sizeof(CK_BBOOL)); 1.1354 + if (crv != CKR_OK) return crv; 1.1355 + 1.1356 + /* get the key type */ 1.1357 + attribute = sftk_FindAttribute(object,CKA_KEY_TYPE); 1.1358 + if (!attribute) { 1.1359 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.1360 + } 1.1361 + key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue; 1.1362 + sftk_FreeAttribute(attribute); 1.1363 + 1.1364 + switch (object->objclass) { 1.1365 + case CKO_PUBLIC_KEY: 1.1366 + return sftk_handlePublicKeyObject(session,object,key_type); 1.1367 + case CKO_PRIVATE_KEY: 1.1368 + return sftk_handlePrivateKeyObject(session,object,key_type); 1.1369 + case CKO_SECRET_KEY: 1.1370 + /* make sure the required fields exist */ 1.1371 + return sftk_handleSecretKeyObject(session,object,key_type, 1.1372 + (PRBool)(session->slot->slotID == FIPS_SLOT_ID)); 1.1373 + default: 1.1374 + break; 1.1375 + } 1.1376 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.1377 +} 1.1378 + 1.1379 +/* 1.1380 + * check the consistancy and Verify a DSA Parameter Object 1.1381 + */ 1.1382 +static CK_RV 1.1383 +sftk_handleDSAParameterObject(SFTKSession *session, SFTKObject *object) 1.1384 +{ 1.1385 + SFTKAttribute *primeAttr = NULL; 1.1386 + SFTKAttribute *subPrimeAttr = NULL; 1.1387 + SFTKAttribute *baseAttr = NULL; 1.1388 + SFTKAttribute *seedAttr = NULL; 1.1389 + SFTKAttribute *hAttr = NULL; 1.1390 + SFTKAttribute *attribute; 1.1391 + CK_RV crv = CKR_TEMPLATE_INCOMPLETE; 1.1392 + PQGParams params; 1.1393 + PQGVerify vfy, *verify = NULL; 1.1394 + SECStatus result,rv; 1.1395 + /* This bool keeps track of whether or not we need verify parameters. 1.1396 + * If a P, Q and G or supplied, we dont' need verify parameters, as we 1.1397 + * have PQ and G. 1.1398 + * - If G is not supplied, the presumption is that we want to 1.1399 + * verify P and Q only. 1.1400 + * - If counter is supplied, it is presumed we want to verify PQ because 1.1401 + * the counter is only used in verification. 1.1402 + * - If H is supplied, is is presumed we want to verify G because H is 1.1403 + * only used to verify G. 1.1404 + * - Any verification step must have the SEED (counter or H could be 1.1405 + * missing depending on exactly what we want to verify). If SEED is supplied, 1.1406 + * the code just goes ahead and runs verify (other errors are parameter 1.1407 + * errors are detected by the PQG_VerifyParams function). If SEED is not 1.1408 + * supplied, but we determined that we are trying to verify (because needVfy 1.1409 + * is set, go ahead and return CKR_TEMPLATE_INCOMPLETE. 1.1410 + */ 1.1411 + PRBool needVfy = PR_FALSE; 1.1412 + 1.1413 + primeAttr = sftk_FindAttribute(object,CKA_PRIME); 1.1414 + if (primeAttr == NULL) goto loser; 1.1415 + params.prime.data = primeAttr->attrib.pValue; 1.1416 + params.prime.len = primeAttr->attrib.ulValueLen; 1.1417 + 1.1418 + subPrimeAttr = sftk_FindAttribute(object,CKA_SUBPRIME); 1.1419 + if (subPrimeAttr == NULL) goto loser; 1.1420 + params.subPrime.data = subPrimeAttr->attrib.pValue; 1.1421 + params.subPrime.len = subPrimeAttr->attrib.ulValueLen; 1.1422 + 1.1423 + baseAttr = sftk_FindAttribute(object,CKA_BASE); 1.1424 + if (baseAttr != NULL) { 1.1425 + params.base.data = baseAttr->attrib.pValue; 1.1426 + params.base.len = baseAttr->attrib.ulValueLen; 1.1427 + } else { 1.1428 + params.base.data = NULL; 1.1429 + params.base.len = 0; 1.1430 + needVfy = PR_TRUE; /* presumably only including PQ so we can verify 1.1431 + * them. */ 1.1432 + } 1.1433 + 1.1434 + attribute = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_COUNTER); 1.1435 + if (attribute != NULL) { 1.1436 + vfy.counter = *(CK_ULONG *) attribute->attrib.pValue; 1.1437 + sftk_FreeAttribute(attribute); 1.1438 + needVfy = PR_TRUE; /* included a count so we can verify PQ */ 1.1439 + } else { 1.1440 + vfy.counter = -1; 1.1441 + } 1.1442 + 1.1443 + hAttr = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_H); 1.1444 + if (hAttr != NULL) { 1.1445 + vfy.h.data = hAttr->attrib.pValue; 1.1446 + vfy.h.len = hAttr->attrib.ulValueLen; 1.1447 + needVfy = PR_TRUE; /* included H so we can verify G */ 1.1448 + } else { 1.1449 + vfy.h.data = NULL; 1.1450 + vfy.h.len = 0; 1.1451 + } 1.1452 + seedAttr = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_SEED); 1.1453 + if (seedAttr != NULL) { 1.1454 + vfy.seed.data = seedAttr->attrib.pValue; 1.1455 + vfy.seed.len = seedAttr->attrib.ulValueLen; 1.1456 + 1.1457 + verify = &vfy; 1.1458 + } else if (needVfy) { 1.1459 + goto loser; /* Verify always needs seed, if we need verify and not seed 1.1460 + * then fail */ 1.1461 + } 1.1462 + 1.1463 + crv = CKR_FUNCTION_FAILED; 1.1464 + rv = PQG_VerifyParams(¶ms,verify,&result); 1.1465 + if (rv == SECSuccess) { 1.1466 + crv = (result== SECSuccess) ? CKR_OK : CKR_ATTRIBUTE_VALUE_INVALID; 1.1467 + } 1.1468 + 1.1469 +loser: 1.1470 + if (hAttr) sftk_FreeAttribute(hAttr); 1.1471 + if (seedAttr) sftk_FreeAttribute(seedAttr); 1.1472 + if (baseAttr) sftk_FreeAttribute(baseAttr); 1.1473 + if (subPrimeAttr) sftk_FreeAttribute(subPrimeAttr); 1.1474 + if (primeAttr) sftk_FreeAttribute(primeAttr); 1.1475 + 1.1476 + return crv; 1.1477 +} 1.1478 + 1.1479 +/* 1.1480 + * check the consistancy and initialize a Key Parameter Object 1.1481 + */ 1.1482 +static CK_RV 1.1483 +sftk_handleKeyParameterObject(SFTKSession *session, SFTKObject *object) 1.1484 +{ 1.1485 + SFTKAttribute *attribute; 1.1486 + CK_KEY_TYPE key_type; 1.1487 + CK_BBOOL ckfalse = CK_FALSE; 1.1488 + CK_RV crv; 1.1489 + 1.1490 + /* verify the required fields */ 1.1491 + if ( !sftk_hasAttribute(object,CKA_KEY_TYPE) ) { 1.1492 + return CKR_TEMPLATE_INCOMPLETE; 1.1493 + } 1.1494 + 1.1495 + /* now verify the common fields */ 1.1496 + crv = sftk_defaultAttribute(object,CKA_LOCAL,&ckfalse,sizeof(CK_BBOOL)); 1.1497 + if (crv != CKR_OK) return crv; 1.1498 + 1.1499 + /* get the key type */ 1.1500 + attribute = sftk_FindAttribute(object,CKA_KEY_TYPE); 1.1501 + if (!attribute) { 1.1502 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.1503 + } 1.1504 + key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue; 1.1505 + sftk_FreeAttribute(attribute); 1.1506 + 1.1507 + switch (key_type) { 1.1508 + case CKK_DSA: 1.1509 + return sftk_handleDSAParameterObject(session,object); 1.1510 + 1.1511 + default: 1.1512 + break; 1.1513 + } 1.1514 + return CKR_KEY_TYPE_INCONSISTENT; 1.1515 +} 1.1516 + 1.1517 +/* 1.1518 + * Handle Object does all the object consistancy checks, automatic attribute 1.1519 + * generation, attribute defaulting, etc. If handleObject succeeds, the object 1.1520 + * will be assigned an object handle, and the object installed in the session 1.1521 + * or stored in the DB. 1.1522 + */ 1.1523 +CK_RV 1.1524 +sftk_handleObject(SFTKObject *object, SFTKSession *session) 1.1525 +{ 1.1526 + SFTKSlot *slot = session->slot; 1.1527 + SFTKAttribute *attribute; 1.1528 + SFTKObject *duplicateObject = NULL; 1.1529 + CK_OBJECT_HANDLE handle; 1.1530 + CK_BBOOL ckfalse = CK_FALSE; 1.1531 + CK_BBOOL cktrue = CK_TRUE; 1.1532 + CK_RV crv; 1.1533 + 1.1534 + /* make sure all the base object types are defined. If not set the 1.1535 + * defaults */ 1.1536 + crv = sftk_defaultAttribute(object,CKA_TOKEN,&ckfalse,sizeof(CK_BBOOL)); 1.1537 + if (crv != CKR_OK) return crv; 1.1538 + crv = sftk_defaultAttribute(object,CKA_PRIVATE,&ckfalse,sizeof(CK_BBOOL)); 1.1539 + if (crv != CKR_OK) return crv; 1.1540 + crv = sftk_defaultAttribute(object,CKA_LABEL,NULL,0); 1.1541 + if (crv != CKR_OK) return crv; 1.1542 + crv = sftk_defaultAttribute(object,CKA_MODIFIABLE,&cktrue,sizeof(CK_BBOOL)); 1.1543 + if (crv != CKR_OK) return crv; 1.1544 + 1.1545 + /* don't create a private object if we aren't logged in */ 1.1546 + if ((!slot->isLoggedIn) && (slot->needLogin) && 1.1547 + (sftk_isTrue(object,CKA_PRIVATE))) { 1.1548 + return CKR_USER_NOT_LOGGED_IN; 1.1549 + } 1.1550 + 1.1551 + 1.1552 + if (((session->info.flags & CKF_RW_SESSION) == 0) && 1.1553 + (sftk_isTrue(object,CKA_TOKEN))) { 1.1554 + return CKR_SESSION_READ_ONLY; 1.1555 + } 1.1556 + 1.1557 + /* Assign a unique SESSION object handle to every new object, 1.1558 + * whether it is a session object or a token object. 1.1559 + * At this point, all new objects are structured as session objects. 1.1560 + * Objects with the CKA_TOKEN attribute true will be turned into 1.1561 + * token objects and will have a token object handle assigned to 1.1562 + * them by a call to sftk_mkHandle in the handler for each object 1.1563 + * class, invoked below. 1.1564 + * 1.1565 + * It may be helpful to note/remember that 1.1566 + * sftk_narrowToXxxObject uses sftk_isToken, 1.1567 + * sftk_isToken examines the sign bit of the object's handle, but 1.1568 + * sftk_isTrue(...,CKA_TOKEN) examines the CKA_TOKEN attribute. 1.1569 + */ 1.1570 + do { 1.1571 + PRUint32 wrappedAround; 1.1572 + 1.1573 + duplicateObject = NULL; 1.1574 + PZ_Lock(slot->objectLock); 1.1575 + wrappedAround = slot->sessionObjectHandleCount & SFTK_TOKEN_MASK; 1.1576 + handle = slot->sessionObjectHandleCount & ~SFTK_TOKEN_MASK; 1.1577 + if (!handle) /* don't allow zero handle */ 1.1578 + handle = minSessionObjectHandle; 1.1579 + slot->sessionObjectHandleCount = (handle + 1U) | wrappedAround; 1.1580 + /* Is there already a session object with this handle? */ 1.1581 + if (wrappedAround) { 1.1582 + sftkqueue_find(duplicateObject, handle, slot->sessObjHashTable, \ 1.1583 + slot->sessObjHashSize); 1.1584 + } 1.1585 + PZ_Unlock(slot->objectLock); 1.1586 + } while (duplicateObject != NULL); 1.1587 + object->handle = handle; 1.1588 + 1.1589 + /* get the object class */ 1.1590 + attribute = sftk_FindAttribute(object,CKA_CLASS); 1.1591 + if (attribute == NULL) { 1.1592 + return CKR_TEMPLATE_INCOMPLETE; 1.1593 + } 1.1594 + object->objclass = *(CK_OBJECT_CLASS *)attribute->attrib.pValue; 1.1595 + sftk_FreeAttribute(attribute); 1.1596 + 1.1597 + /* Now handle the specific object class. 1.1598 + * At this point, all objects are session objects, and the session 1.1599 + * number must be passed to the object class handlers. 1.1600 + */ 1.1601 + switch (object->objclass) { 1.1602 + case CKO_DATA: 1.1603 + crv = sftk_handleDataObject(session,object); 1.1604 + break; 1.1605 + case CKO_CERTIFICATE: 1.1606 + crv = sftk_handleCertObject(session,object); 1.1607 + break; 1.1608 + case CKO_NETSCAPE_TRUST: 1.1609 + crv = sftk_handleTrustObject(session,object); 1.1610 + break; 1.1611 + case CKO_NETSCAPE_CRL: 1.1612 + crv = sftk_handleCrlObject(session,object); 1.1613 + break; 1.1614 + case CKO_NETSCAPE_SMIME: 1.1615 + crv = sftk_handleSMimeObject(session,object); 1.1616 + break; 1.1617 + case CKO_PRIVATE_KEY: 1.1618 + case CKO_PUBLIC_KEY: 1.1619 + case CKO_SECRET_KEY: 1.1620 + crv = sftk_handleKeyObject(session,object); 1.1621 + break; 1.1622 + case CKO_KG_PARAMETERS: 1.1623 + crv = sftk_handleKeyParameterObject(session,object); 1.1624 + break; 1.1625 + default: 1.1626 + crv = CKR_ATTRIBUTE_VALUE_INVALID; 1.1627 + break; 1.1628 + } 1.1629 + 1.1630 + /* can't fail from here on out unless the pk_handlXXX functions have 1.1631 + * failed the request */ 1.1632 + if (crv != CKR_OK) { 1.1633 + return crv; 1.1634 + } 1.1635 + 1.1636 + /* Now link the object into the slot and session structures. 1.1637 + * If the object has a true CKA_TOKEN attribute, the above object 1.1638 + * class handlers will have set the sign bit in the object handle, 1.1639 + * causing the following test to be true. 1.1640 + */ 1.1641 + if (sftk_isToken(object->handle)) { 1.1642 + sftk_convertSessionToToken(object); 1.1643 + } else { 1.1644 + object->slot = slot; 1.1645 + sftk_AddObject(session,object); 1.1646 + } 1.1647 + 1.1648 + return CKR_OK; 1.1649 +} 1.1650 + 1.1651 +/* 1.1652 + * ******************** Public Key Utilities *************************** 1.1653 + */ 1.1654 +/* Generate a low public key structure from an object */ 1.1655 +NSSLOWKEYPublicKey *sftk_GetPubKey(SFTKObject *object,CK_KEY_TYPE key_type, 1.1656 + CK_RV *crvp) 1.1657 +{ 1.1658 + NSSLOWKEYPublicKey *pubKey; 1.1659 + PLArenaPool *arena; 1.1660 + CK_RV crv; 1.1661 + 1.1662 + if (object->objclass != CKO_PUBLIC_KEY) { 1.1663 + *crvp = CKR_KEY_TYPE_INCONSISTENT; 1.1664 + return NULL; 1.1665 + } 1.1666 + 1.1667 + if (sftk_isToken(object->handle)) { 1.1668 +/* ferret out the token object handle */ 1.1669 + } 1.1670 + 1.1671 + /* If we already have a key, use it */ 1.1672 + if (object->objectInfo) { 1.1673 + *crvp = CKR_OK; 1.1674 + return (NSSLOWKEYPublicKey *)object->objectInfo; 1.1675 + } 1.1676 + 1.1677 + /* allocate the structure */ 1.1678 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.1679 + if (arena == NULL) { 1.1680 + *crvp = CKR_HOST_MEMORY; 1.1681 + return NULL; 1.1682 + } 1.1683 + 1.1684 + pubKey = (NSSLOWKEYPublicKey *) 1.1685 + PORT_ArenaAlloc(arena,sizeof(NSSLOWKEYPublicKey)); 1.1686 + if (pubKey == NULL) { 1.1687 + PORT_FreeArena(arena,PR_FALSE); 1.1688 + *crvp = CKR_HOST_MEMORY; 1.1689 + return NULL; 1.1690 + } 1.1691 + 1.1692 + /* fill in the structure */ 1.1693 + pubKey->arena = arena; 1.1694 + switch (key_type) { 1.1695 + case CKK_RSA: 1.1696 + pubKey->keyType = NSSLOWKEYRSAKey; 1.1697 + crv = sftk_Attribute2SSecItem(arena,&pubKey->u.rsa.modulus, 1.1698 + object,CKA_MODULUS); 1.1699 + if (crv != CKR_OK) break; 1.1700 + crv = sftk_Attribute2SSecItem(arena,&pubKey->u.rsa.publicExponent, 1.1701 + object,CKA_PUBLIC_EXPONENT); 1.1702 + break; 1.1703 + case CKK_DSA: 1.1704 + pubKey->keyType = NSSLOWKEYDSAKey; 1.1705 + crv = sftk_Attribute2SSecItem(arena,&pubKey->u.dsa.params.prime, 1.1706 + object,CKA_PRIME); 1.1707 + if (crv != CKR_OK) break; 1.1708 + crv = sftk_Attribute2SSecItem(arena,&pubKey->u.dsa.params.subPrime, 1.1709 + object,CKA_SUBPRIME); 1.1710 + if (crv != CKR_OK) break; 1.1711 + crv = sftk_Attribute2SSecItem(arena,&pubKey->u.dsa.params.base, 1.1712 + object,CKA_BASE); 1.1713 + if (crv != CKR_OK) break; 1.1714 + crv = sftk_Attribute2SSecItem(arena,&pubKey->u.dsa.publicValue, 1.1715 + object,CKA_VALUE); 1.1716 + break; 1.1717 + case CKK_DH: 1.1718 + pubKey->keyType = NSSLOWKEYDHKey; 1.1719 + crv = sftk_Attribute2SSecItem(arena,&pubKey->u.dh.prime, 1.1720 + object,CKA_PRIME); 1.1721 + if (crv != CKR_OK) break; 1.1722 + crv = sftk_Attribute2SSecItem(arena,&pubKey->u.dh.base, 1.1723 + object,CKA_BASE); 1.1724 + if (crv != CKR_OK) break; 1.1725 + crv = sftk_Attribute2SSecItem(arena,&pubKey->u.dh.publicValue, 1.1726 + object,CKA_VALUE); 1.1727 + break; 1.1728 +#ifndef NSS_DISABLE_ECC 1.1729 + case CKK_EC: 1.1730 + pubKey->keyType = NSSLOWKEYECKey; 1.1731 + crv = sftk_Attribute2SSecItem(arena, 1.1732 + &pubKey->u.ec.ecParams.DEREncoding, 1.1733 + object,CKA_EC_PARAMS); 1.1734 + if (crv != CKR_OK) break; 1.1735 + 1.1736 + /* Fill out the rest of the ecParams structure 1.1737 + * based on the encoded params 1.1738 + */ 1.1739 + if (EC_FillParams(arena, &pubKey->u.ec.ecParams.DEREncoding, 1.1740 + &pubKey->u.ec.ecParams) != SECSuccess) { 1.1741 + crv = CKR_DOMAIN_PARAMS_INVALID; 1.1742 + break; 1.1743 + } 1.1744 + 1.1745 + crv = sftk_Attribute2SSecItem(arena,&pubKey->u.ec.publicValue, 1.1746 + object,CKA_EC_POINT); 1.1747 + if (crv == CKR_OK) { 1.1748 + int keyLen,curveLen; 1.1749 + 1.1750 + curveLen = (pubKey->u.ec.ecParams.fieldID.size +7)/8; 1.1751 + keyLen = (2*curveLen)+1; 1.1752 + 1.1753 + /* special note: We can't just use the first byte to determine 1.1754 + * between these 2 cases because both EC_POINT_FORM_UNCOMPRESSED 1.1755 + * and SEC_ASN1_OCTET_STRING are 0x04 */ 1.1756 + 1.1757 + /* handle the non-DER encoded case (UNCOMPRESSED only) */ 1.1758 + if (pubKey->u.ec.publicValue.data[0] == EC_POINT_FORM_UNCOMPRESSED 1.1759 + && pubKey->u.ec.publicValue.len == keyLen) { 1.1760 + break; /* key was not DER encoded, no need to unwrap */ 1.1761 + } 1.1762 + 1.1763 + /* if we ever support compressed, handle it here */ 1.1764 + 1.1765 + /* handle the encoded case */ 1.1766 + if ((pubKey->u.ec.publicValue.data[0] == SEC_ASN1_OCTET_STRING) 1.1767 + && pubKey->u.ec.publicValue.len > keyLen) { 1.1768 + SECItem publicValue; 1.1769 + SECStatus rv; 1.1770 + 1.1771 + rv = SEC_QuickDERDecodeItem(arena, &publicValue, 1.1772 + SEC_ASN1_GET(SEC_OctetStringTemplate), 1.1773 + &pubKey->u.ec.publicValue); 1.1774 + /* nope, didn't decode correctly */ 1.1775 + if ((rv != SECSuccess) 1.1776 + || (publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) 1.1777 + || (publicValue.len != keyLen)) { 1.1778 + crv = CKR_ATTRIBUTE_VALUE_INVALID; 1.1779 + break; 1.1780 + } 1.1781 + /* replace our previous with the decoded key */ 1.1782 + pubKey->u.ec.publicValue = publicValue; 1.1783 + break; 1.1784 + } 1.1785 + crv = CKR_ATTRIBUTE_VALUE_INVALID; 1.1786 + } 1.1787 + break; 1.1788 +#endif /* NSS_DISABLE_ECC */ 1.1789 + default: 1.1790 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.1791 + break; 1.1792 + } 1.1793 + *crvp = crv; 1.1794 + if (crv != CKR_OK) { 1.1795 + PORT_FreeArena(arena,PR_FALSE); 1.1796 + return NULL; 1.1797 + } 1.1798 + 1.1799 + object->objectInfo = pubKey; 1.1800 + object->infoFree = (SFTKFree) nsslowkey_DestroyPublicKey; 1.1801 + return pubKey; 1.1802 +} 1.1803 + 1.1804 +/* make a private key from a verified object */ 1.1805 +static NSSLOWKEYPrivateKey * 1.1806 +sftk_mkPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp) 1.1807 +{ 1.1808 + NSSLOWKEYPrivateKey *privKey; 1.1809 + SFTKItemTemplate itemTemplate[SFTK_MAX_ITEM_TEMPLATE]; 1.1810 + int itemTemplateCount = 0; 1.1811 + PLArenaPool *arena; 1.1812 + CK_RV crv = CKR_OK; 1.1813 + SECStatus rv; 1.1814 + 1.1815 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.1816 + if (arena == NULL) { 1.1817 + *crvp = CKR_HOST_MEMORY; 1.1818 + return NULL; 1.1819 + } 1.1820 + 1.1821 + privKey = (NSSLOWKEYPrivateKey *) 1.1822 + PORT_ArenaZAlloc(arena,sizeof(NSSLOWKEYPrivateKey)); 1.1823 + if (privKey == NULL) { 1.1824 + PORT_FreeArena(arena,PR_FALSE); 1.1825 + *crvp = CKR_HOST_MEMORY; 1.1826 + return NULL; 1.1827 + } 1.1828 + 1.1829 + /* in future this would be a switch on key_type */ 1.1830 + privKey->arena = arena; 1.1831 + switch (key_type) { 1.1832 + case CKK_RSA: 1.1833 + privKey->keyType = NSSLOWKEYRSAKey; 1.1834 + 1.1835 + SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 1.1836 + &privKey->u.rsa.modulus,CKA_MODULUS); 1.1837 + itemTemplateCount++; 1.1838 + SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 1.1839 + &privKey->u.rsa.publicExponent, CKA_PUBLIC_EXPONENT); 1.1840 + itemTemplateCount++; 1.1841 + SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 1.1842 + &privKey->u.rsa.privateExponent, CKA_PRIVATE_EXPONENT); 1.1843 + itemTemplateCount++; 1.1844 + SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 1.1845 + &privKey->u.rsa.prime1, CKA_PRIME_1); 1.1846 + itemTemplateCount++; 1.1847 + SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 1.1848 + &privKey->u.rsa.prime2, CKA_PRIME_2); 1.1849 + itemTemplateCount++; 1.1850 + SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 1.1851 + &privKey->u.rsa.exponent1, CKA_EXPONENT_1); 1.1852 + itemTemplateCount++; 1.1853 + SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 1.1854 + &privKey->u.rsa.exponent2, CKA_EXPONENT_2); 1.1855 + itemTemplateCount++; 1.1856 + SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 1.1857 + &privKey->u.rsa.coefficient, CKA_COEFFICIENT); 1.1858 + itemTemplateCount++; 1.1859 + rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version, 1.1860 + NSSLOWKEY_PRIVATE_KEY_INFO_VERSION); 1.1861 + if (rv != SECSuccess) crv = CKR_HOST_MEMORY; 1.1862 + break; 1.1863 + 1.1864 + case CKK_DSA: 1.1865 + privKey->keyType = NSSLOWKEYDSAKey; 1.1866 + SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 1.1867 + &privKey->u.dsa.params.prime, CKA_PRIME); 1.1868 + itemTemplateCount++; 1.1869 + SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 1.1870 + &privKey->u.dsa.params.subPrime, CKA_SUBPRIME); 1.1871 + itemTemplateCount++; 1.1872 + SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 1.1873 + &privKey->u.dsa.params.base, CKA_BASE); 1.1874 + itemTemplateCount++; 1.1875 + SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 1.1876 + &privKey->u.dsa.privateValue, CKA_VALUE); 1.1877 + itemTemplateCount++; 1.1878 + /* privKey was zero'd so public value is already set to NULL, 0 1.1879 + * if we don't set it explicitly */ 1.1880 + break; 1.1881 + 1.1882 + case CKK_DH: 1.1883 + privKey->keyType = NSSLOWKEYDHKey; 1.1884 + SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 1.1885 + &privKey->u.dh.prime, CKA_PRIME); 1.1886 + itemTemplateCount++; 1.1887 + SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 1.1888 + &privKey->u.dh.base, CKA_BASE); 1.1889 + itemTemplateCount++; 1.1890 + SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount, 1.1891 + &privKey->u.dh.privateValue, CKA_VALUE); 1.1892 + itemTemplateCount++; 1.1893 + /* privKey was zero'd so public value is already set to NULL, 0 1.1894 + * if we don't set it explicitly */ 1.1895 + break; 1.1896 + 1.1897 +#ifndef NSS_DISABLE_ECC 1.1898 + case CKK_EC: 1.1899 + privKey->keyType = NSSLOWKEYECKey; 1.1900 + crv = sftk_Attribute2SSecItem(arena, 1.1901 + &privKey->u.ec.ecParams.DEREncoding, 1.1902 + object,CKA_EC_PARAMS); 1.1903 + if (crv != CKR_OK) break; 1.1904 + 1.1905 + /* Fill out the rest of the ecParams structure 1.1906 + * based on the encoded params 1.1907 + */ 1.1908 + if (EC_FillParams(arena, &privKey->u.ec.ecParams.DEREncoding, 1.1909 + &privKey->u.ec.ecParams) != SECSuccess) { 1.1910 + crv = CKR_DOMAIN_PARAMS_INVALID; 1.1911 + break; 1.1912 + } 1.1913 + crv = sftk_Attribute2SSecItem(arena,&privKey->u.ec.privateValue, 1.1914 + object,CKA_VALUE); 1.1915 + if (crv != CKR_OK) break; 1.1916 + 1.1917 + if (sftk_hasAttribute(object, CKA_NETSCAPE_DB)) { 1.1918 + crv = sftk_Attribute2SSecItem(arena, &privKey->u.ec.publicValue, 1.1919 + object, CKA_NETSCAPE_DB); 1.1920 + if (crv != CKR_OK) break; 1.1921 + /* privKey was zero'd so public value is already set to NULL, 0 1.1922 + * if we don't set it explicitly */ 1.1923 + } 1.1924 + rv = DER_SetUInteger(privKey->arena, &privKey->u.ec.version, 1.1925 + NSSLOWKEY_EC_PRIVATE_KEY_VERSION); 1.1926 + if (rv != SECSuccess) { 1.1927 + crv = CKR_HOST_MEMORY; 1.1928 + /* The following ifdef is needed for Linux arm distros and 1.1929 + * Android as gcc 4.6 has a bug when targeting arm (but not 1.1930 + * thumb). The bug has been fixed in gcc 4.7. 1.1931 + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56561 1.1932 + */ 1.1933 +#if defined (__arm__) && !defined(__thumb__) && defined (__GNUC__) 1.1934 + *crvp = CKR_HOST_MEMORY; 1.1935 + break; 1.1936 +#endif 1.1937 + } 1.1938 + break; 1.1939 +#endif /* NSS_DISABLE_ECC */ 1.1940 + 1.1941 + default: 1.1942 + crv = CKR_KEY_TYPE_INCONSISTENT; 1.1943 + break; 1.1944 + } 1.1945 + if (crv == CKR_OK && itemTemplateCount != 0) { 1.1946 + PORT_Assert(itemTemplateCount > 0); 1.1947 + PORT_Assert(itemTemplateCount <= SFTK_MAX_ITEM_TEMPLATE); 1.1948 + crv = sftk_MultipleAttribute2SecItem(arena, object, itemTemplate, 1.1949 + itemTemplateCount); 1.1950 + } 1.1951 + *crvp = crv; 1.1952 + if (crv != CKR_OK) { 1.1953 + PORT_FreeArena(arena,PR_FALSE); 1.1954 + return NULL; 1.1955 + } 1.1956 + return privKey; 1.1957 +} 1.1958 + 1.1959 +/* 1.1960 + * If a partial RSA private key is present, fill in the rest if necessary, 1.1961 + * and then verify the parameters are well-formed 1.1962 + */ 1.1963 +static SECStatus 1.1964 +sftk_verifyRSAPrivateKey(SFTKObject *object, PRBool fillIfNeeded) 1.1965 +{ 1.1966 + RSAPrivateKey tmpKey = { 0 }; 1.1967 + SFTKAttribute *modulus = NULL; 1.1968 + SFTKAttribute *prime1 = NULL; 1.1969 + SFTKAttribute *prime2 = NULL; 1.1970 + SFTKAttribute *privateExponent = NULL; 1.1971 + SFTKAttribute *publicExponent = NULL; 1.1972 + SFTKAttribute *exponent1 = NULL; 1.1973 + SFTKAttribute *exponent2 = NULL; 1.1974 + SFTKAttribute *coefficient = NULL; 1.1975 + SECStatus rv; 1.1976 + CK_RV crv; 1.1977 + 1.1978 + /* first fill in the components that we have. Populate only uses 1.1979 + * the non-crt components, so only fill those in */ 1.1980 + tmpKey.arena = NULL; 1.1981 + modulus = sftk_FindAttribute(object, CKA_MODULUS); 1.1982 + if (modulus) { 1.1983 + tmpKey.modulus.data = modulus->attrib.pValue; 1.1984 + tmpKey.modulus.len = modulus->attrib.ulValueLen; 1.1985 + } 1.1986 + prime1 = sftk_FindAttribute(object, CKA_PRIME_1); 1.1987 + if (prime1) { 1.1988 + tmpKey.prime1.data = prime1->attrib.pValue; 1.1989 + tmpKey.prime1.len = prime1->attrib.ulValueLen; 1.1990 + } 1.1991 + prime2 = sftk_FindAttribute(object, CKA_PRIME_2); 1.1992 + if (prime2) { 1.1993 + tmpKey.prime2.data = prime2->attrib.pValue; 1.1994 + tmpKey.prime2.len = prime2->attrib.ulValueLen; 1.1995 + } 1.1996 + privateExponent = sftk_FindAttribute(object, CKA_PRIVATE_EXPONENT); 1.1997 + if (privateExponent) { 1.1998 + tmpKey.privateExponent.data = privateExponent->attrib.pValue; 1.1999 + tmpKey.privateExponent.len = privateExponent->attrib.ulValueLen; 1.2000 + } 1.2001 + publicExponent = sftk_FindAttribute(object, CKA_PUBLIC_EXPONENT); 1.2002 + if (publicExponent) { 1.2003 + tmpKey.publicExponent.data = publicExponent->attrib.pValue; 1.2004 + tmpKey.publicExponent.len = publicExponent->attrib.ulValueLen; 1.2005 + } 1.2006 + exponent1 = sftk_FindAttribute(object, CKA_EXPONENT_1); 1.2007 + if (exponent1) { 1.2008 + tmpKey.exponent1.data = exponent1->attrib.pValue; 1.2009 + tmpKey.exponent1.len = exponent1->attrib.ulValueLen; 1.2010 + } 1.2011 + exponent2 = sftk_FindAttribute(object, CKA_EXPONENT_2); 1.2012 + if (exponent2) { 1.2013 + tmpKey.exponent2.data = exponent2->attrib.pValue; 1.2014 + tmpKey.exponent2.len = exponent2->attrib.ulValueLen; 1.2015 + } 1.2016 + coefficient = sftk_FindAttribute(object, CKA_COEFFICIENT); 1.2017 + if (coefficient) { 1.2018 + tmpKey.coefficient.data = coefficient->attrib.pValue; 1.2019 + tmpKey.coefficient.len = coefficient->attrib.ulValueLen; 1.2020 + } 1.2021 + 1.2022 + if (fillIfNeeded) { 1.2023 + /* 1.2024 + * populate requires one exponent plus 2 other components to work. 1.2025 + * we expected our caller to check that first. If that didn't happen, 1.2026 + * populate will simply return an error here. 1.2027 + */ 1.2028 + rv = RSA_PopulatePrivateKey(&tmpKey); 1.2029 + if (rv != SECSuccess) { 1.2030 + goto loser; 1.2031 + } 1.2032 + } 1.2033 + rv = RSA_PrivateKeyCheck(&tmpKey); 1.2034 + if (rv != SECSuccess) { 1.2035 + goto loser; 1.2036 + } 1.2037 + /* now that we have a fully populated key, set all our attribute values */ 1.2038 + rv = SECFailure; 1.2039 + if (!modulus || modulus->attrib.pValue != tmpKey.modulus.data) { 1.2040 + crv = sftk_forceAttribute(object,CKA_MODULUS, 1.2041 + sftk_item_expand(&tmpKey.modulus)); 1.2042 + if (crv != CKR_OK) goto loser; 1.2043 + } 1.2044 + if (!publicExponent || 1.2045 + publicExponent->attrib.pValue != tmpKey.publicExponent.data) { 1.2046 + crv = sftk_forceAttribute(object, CKA_PUBLIC_EXPONENT, 1.2047 + sftk_item_expand(&tmpKey.publicExponent)); 1.2048 + if (crv != CKR_OK) goto loser; 1.2049 + } 1.2050 + if (!privateExponent || 1.2051 + privateExponent->attrib.pValue != tmpKey.privateExponent.data) { 1.2052 + crv = sftk_forceAttribute(object, CKA_PRIVATE_EXPONENT, 1.2053 + sftk_item_expand(&tmpKey.privateExponent)); 1.2054 + if (crv != CKR_OK) goto loser; 1.2055 + } 1.2056 + if (!prime1 || prime1->attrib.pValue != tmpKey.prime1.data) { 1.2057 + crv = sftk_forceAttribute(object, CKA_PRIME_1, 1.2058 + sftk_item_expand(&tmpKey.prime1)); 1.2059 + if (crv != CKR_OK) goto loser; 1.2060 + } 1.2061 + if (!prime2 || prime2->attrib.pValue != tmpKey.prime2.data) { 1.2062 + crv = sftk_forceAttribute(object, CKA_PRIME_2, 1.2063 + sftk_item_expand(&tmpKey.prime2)); 1.2064 + if (crv != CKR_OK) goto loser; 1.2065 + } 1.2066 + if (!exponent1 || exponent1->attrib.pValue != tmpKey.exponent1.data) { 1.2067 + crv = sftk_forceAttribute(object, CKA_EXPONENT_1, 1.2068 + sftk_item_expand(&tmpKey.exponent1)); 1.2069 + if (crv != CKR_OK) goto loser; 1.2070 + } 1.2071 + if (!exponent2 || exponent2->attrib.pValue != tmpKey.exponent2.data) { 1.2072 + crv = sftk_forceAttribute(object, CKA_EXPONENT_2, 1.2073 + sftk_item_expand(&tmpKey.exponent2)); 1.2074 + if (crv != CKR_OK) goto loser; 1.2075 + } 1.2076 + if (!coefficient || coefficient->attrib.pValue != tmpKey.coefficient.data) { 1.2077 + crv = sftk_forceAttribute(object, CKA_COEFFICIENT, 1.2078 + sftk_item_expand(&tmpKey.coefficient)); 1.2079 + if (crv != CKR_OK) goto loser; 1.2080 + } 1.2081 + rv = SECSuccess; 1.2082 + 1.2083 + /* we're done (one way or the other), clean up all our stuff */ 1.2084 +loser: 1.2085 + if (tmpKey.arena) { 1.2086 + PORT_FreeArena(tmpKey.arena,PR_TRUE); 1.2087 + } 1.2088 + if (modulus) { 1.2089 + sftk_FreeAttribute(modulus); 1.2090 + } 1.2091 + if (prime1) { 1.2092 + sftk_FreeAttribute(prime1); 1.2093 + } 1.2094 + if (prime2) { 1.2095 + sftk_FreeAttribute(prime2); 1.2096 + } 1.2097 + if (privateExponent) { 1.2098 + sftk_FreeAttribute(privateExponent); 1.2099 + } 1.2100 + if (publicExponent) { 1.2101 + sftk_FreeAttribute(publicExponent); 1.2102 + } 1.2103 + if (exponent1) { 1.2104 + sftk_FreeAttribute(exponent1); 1.2105 + } 1.2106 + if (exponent2) { 1.2107 + sftk_FreeAttribute(exponent2); 1.2108 + } 1.2109 + if (coefficient) { 1.2110 + sftk_FreeAttribute(coefficient); 1.2111 + } 1.2112 + return rv; 1.2113 +} 1.2114 + 1.2115 +/* Generate a low private key structure from an object */ 1.2116 +NSSLOWKEYPrivateKey * 1.2117 +sftk_GetPrivKey(SFTKObject *object,CK_KEY_TYPE key_type, CK_RV *crvp) 1.2118 +{ 1.2119 + NSSLOWKEYPrivateKey *priv = NULL; 1.2120 + 1.2121 + if (object->objclass != CKO_PRIVATE_KEY) { 1.2122 + *crvp = CKR_KEY_TYPE_INCONSISTENT; 1.2123 + return NULL; 1.2124 + } 1.2125 + if (object->objectInfo) { 1.2126 + *crvp = CKR_OK; 1.2127 + return (NSSLOWKEYPrivateKey *)object->objectInfo; 1.2128 + } 1.2129 + 1.2130 + priv = sftk_mkPrivKey(object, key_type, crvp); 1.2131 + object->objectInfo = priv; 1.2132 + object->infoFree = (SFTKFree) nsslowkey_DestroyPrivateKey; 1.2133 + return priv; 1.2134 +} 1.2135 + 1.2136 +/* 1.2137 + **************************** Symetric Key utils ************************ 1.2138 + */ 1.2139 +/* 1.2140 + * set the DES key with parity bits correctly 1.2141 + */ 1.2142 +void 1.2143 +sftk_FormatDESKey(unsigned char *key, int length) 1.2144 +{ 1.2145 + int i; 1.2146 + 1.2147 + /* format the des key */ 1.2148 + for (i=0; i < length; i++) { 1.2149 + key[i] = parityTable[key[i]>>1]; 1.2150 + } 1.2151 +} 1.2152 + 1.2153 +/* 1.2154 + * check a des key (des2 or des3 subkey) for weak keys. 1.2155 + */ 1.2156 +PRBool 1.2157 +sftk_CheckDESKey(unsigned char *key) 1.2158 +{ 1.2159 + int i; 1.2160 + 1.2161 + /* format the des key with parity */ 1.2162 + sftk_FormatDESKey(key, 8); 1.2163 + 1.2164 + for (i=0; i < sftk_desWeakTableSize; i++) { 1.2165 + if (PORT_Memcmp(key,sftk_desWeakTable[i],8) == 0) { 1.2166 + return PR_TRUE; 1.2167 + } 1.2168 + } 1.2169 + return PR_FALSE; 1.2170 +} 1.2171 + 1.2172 +/* 1.2173 + * check if a des or triple des key is weak. 1.2174 + */ 1.2175 +PRBool 1.2176 +sftk_IsWeakKey(unsigned char *key,CK_KEY_TYPE key_type) 1.2177 +{ 1.2178 + 1.2179 + switch(key_type) { 1.2180 + case CKK_DES: 1.2181 + return sftk_CheckDESKey(key); 1.2182 + case CKM_DES2_KEY_GEN: 1.2183 + if (sftk_CheckDESKey(key)) return PR_TRUE; 1.2184 + return sftk_CheckDESKey(&key[8]); 1.2185 + case CKM_DES3_KEY_GEN: 1.2186 + if (sftk_CheckDESKey(key)) return PR_TRUE; 1.2187 + if (sftk_CheckDESKey(&key[8])) return PR_TRUE; 1.2188 + return sftk_CheckDESKey(&key[16]); 1.2189 + default: 1.2190 + break; 1.2191 + } 1.2192 + return PR_FALSE; 1.2193 +} 1.2194 + 1.2195 + 1.2196 +/********************************************************************** 1.2197 + * 1.2198 + * Start of PKCS 11 functions 1.2199 + * 1.2200 + **********************************************************************/ 1.2201 + 1.2202 + 1.2203 +/* return the function list */ 1.2204 +CK_RV NSC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) 1.2205 +{ 1.2206 + CHECK_FORK(); 1.2207 + 1.2208 + *pFunctionList = (CK_FUNCTION_LIST_PTR) &sftk_funcList; 1.2209 + return CKR_OK; 1.2210 +} 1.2211 + 1.2212 +/* return the function list */ 1.2213 +CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) 1.2214 +{ 1.2215 + CHECK_FORK(); 1.2216 + 1.2217 + return NSC_GetFunctionList(pFunctionList); 1.2218 +} 1.2219 + 1.2220 +static PLHashNumber 1.2221 +sftk_HashNumber(const void *key) 1.2222 +{ 1.2223 + return (PLHashNumber) key; 1.2224 +} 1.2225 + 1.2226 +/* 1.2227 + * eventually I'd like to expunge all occurances of XXX_SLOT_ID and 1.2228 + * just go with the info in the slot. This is one place, however, 1.2229 + * where it might be a little difficult. 1.2230 + */ 1.2231 +const char * 1.2232 +sftk_getDefTokName(CK_SLOT_ID slotID) 1.2233 +{ 1.2234 + static char buf[33]; 1.2235 + 1.2236 + switch (slotID) { 1.2237 + case NETSCAPE_SLOT_ID: 1.2238 + return "NSS Generic Crypto Services "; 1.2239 + case PRIVATE_KEY_SLOT_ID: 1.2240 + return "NSS Certificate DB "; 1.2241 + case FIPS_SLOT_ID: 1.2242 + return "NSS FIPS 140-2 Certificate DB "; 1.2243 + default: 1.2244 + break; 1.2245 + } 1.2246 + sprintf(buf,"NSS Application Token %08x ",(unsigned int) slotID); 1.2247 + return buf; 1.2248 +} 1.2249 + 1.2250 +const char * 1.2251 +sftk_getDefSlotName(CK_SLOT_ID slotID) 1.2252 +{ 1.2253 + static char buf[65]; 1.2254 + 1.2255 + switch (slotID) { 1.2256 + case NETSCAPE_SLOT_ID: 1.2257 + return 1.2258 + "NSS Internal Cryptographic Services "; 1.2259 + case PRIVATE_KEY_SLOT_ID: 1.2260 + return 1.2261 + "NSS User Private Key and Certificate Services "; 1.2262 + case FIPS_SLOT_ID: 1.2263 + return 1.2264 + "NSS FIPS 140-2 User Private Key Services "; 1.2265 + default: 1.2266 + break; 1.2267 + } 1.2268 + sprintf(buf, 1.2269 + "NSS Application Slot %08x ", 1.2270 + (unsigned int) slotID); 1.2271 + return buf; 1.2272 +} 1.2273 + 1.2274 +static CK_ULONG nscSlotCount[2] = {0 , 0}; 1.2275 +static CK_SLOT_ID_PTR nscSlotList[2] = {NULL, NULL}; 1.2276 +static CK_ULONG nscSlotListSize[2] = {0, 0}; 1.2277 +static PLHashTable *nscSlotHashTable[2] = {NULL, NULL}; 1.2278 + 1.2279 +static int 1.2280 +sftk_GetModuleIndex(CK_SLOT_ID slotID) 1.2281 +{ 1.2282 + if ((slotID == FIPS_SLOT_ID) || (slotID >= SFTK_MIN_FIPS_USER_SLOT_ID)) { 1.2283 + return NSC_FIPS_MODULE; 1.2284 + } 1.2285 + return NSC_NON_FIPS_MODULE; 1.2286 +} 1.2287 + 1.2288 +/* look up a slot structure from the ID (used to be a macro when we only 1.2289 + * had two slots) */ 1.2290 +/* if all is true, return the slot even if it has been 'unloaded' */ 1.2291 +/* if all is false, only return the slots which are present */ 1.2292 +SFTKSlot * 1.2293 +sftk_SlotFromID(CK_SLOT_ID slotID, PRBool all) 1.2294 +{ 1.2295 + SFTKSlot *slot; 1.2296 + int index = sftk_GetModuleIndex(slotID); 1.2297 + 1.2298 + if (nscSlotHashTable[index] == NULL) return NULL; 1.2299 + slot = (SFTKSlot *)PL_HashTableLookupConst(nscSlotHashTable[index], 1.2300 + (void *)slotID); 1.2301 + /* cleared slots shouldn't 'show up' */ 1.2302 + if (slot && !all && !slot->present) slot = NULL; 1.2303 + return slot; 1.2304 +} 1.2305 + 1.2306 +SFTKSlot * 1.2307 +sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle) 1.2308 +{ 1.2309 + CK_ULONG slotIDIndex = (handle >> 24) & 0x7f; 1.2310 + CK_ULONG moduleIndex = (handle >> 31) & 1; 1.2311 + 1.2312 + if (slotIDIndex >= nscSlotCount[moduleIndex]) { 1.2313 + return NULL; 1.2314 + } 1.2315 + 1.2316 + return sftk_SlotFromID(nscSlotList[moduleIndex][slotIDIndex], PR_FALSE); 1.2317 +} 1.2318 + 1.2319 +static CK_RV 1.2320 +sftk_RegisterSlot(SFTKSlot *slot, int moduleIndex) 1.2321 +{ 1.2322 + PLHashEntry *entry; 1.2323 + int index; 1.2324 + 1.2325 + index = sftk_GetModuleIndex(slot->slotID); 1.2326 + 1.2327 + /* make sure the slotID for this module is valid */ 1.2328 + if (moduleIndex != index) { 1.2329 + return CKR_SLOT_ID_INVALID; 1.2330 + } 1.2331 + 1.2332 + if (nscSlotList[index] == NULL) { 1.2333 + nscSlotListSize[index] = NSC_SLOT_LIST_BLOCK_SIZE; 1.2334 + nscSlotList[index] = (CK_SLOT_ID *) 1.2335 + PORT_ZAlloc(nscSlotListSize[index]*sizeof(CK_SLOT_ID)); 1.2336 + if (nscSlotList[index] == NULL) { 1.2337 + return CKR_HOST_MEMORY; 1.2338 + } 1.2339 + } 1.2340 + if (nscSlotCount[index] >= nscSlotListSize[index]) { 1.2341 + CK_SLOT_ID* oldNscSlotList = nscSlotList[index]; 1.2342 + CK_ULONG oldNscSlotListSize = nscSlotListSize[index]; 1.2343 + nscSlotListSize[index] += NSC_SLOT_LIST_BLOCK_SIZE; 1.2344 + nscSlotList[index] = (CK_SLOT_ID *) PORT_Realloc(oldNscSlotList, 1.2345 + nscSlotListSize[index]*sizeof(CK_SLOT_ID)); 1.2346 + if (nscSlotList[index] == NULL) { 1.2347 + nscSlotList[index] = oldNscSlotList; 1.2348 + nscSlotListSize[index] = oldNscSlotListSize; 1.2349 + return CKR_HOST_MEMORY; 1.2350 + } 1.2351 + } 1.2352 + 1.2353 + if (nscSlotHashTable[index] == NULL) { 1.2354 + nscSlotHashTable[index] = PL_NewHashTable(64,sftk_HashNumber, 1.2355 + PL_CompareValues, PL_CompareValues, NULL, 0); 1.2356 + if (nscSlotHashTable[index] == NULL) { 1.2357 + return CKR_HOST_MEMORY; 1.2358 + } 1.2359 + } 1.2360 + 1.2361 + entry = PL_HashTableAdd(nscSlotHashTable[index],(void *)slot->slotID,slot); 1.2362 + if (entry == NULL) { 1.2363 + return CKR_HOST_MEMORY; 1.2364 + } 1.2365 + slot->index = (nscSlotCount[index] & 0x7f) | ((index << 7) & 0x80); 1.2366 + nscSlotList[index][nscSlotCount[index]++] = slot->slotID; 1.2367 + 1.2368 + return CKR_OK; 1.2369 +} 1.2370 + 1.2371 + 1.2372 +/* 1.2373 + * ths function has all the common initialization that happens whenever we 1.2374 + * create a new slot or repurpose an old slot (only valid for slotID's 4 1.2375 + * and greater). 1.2376 + * 1.2377 + * things that are not reinitialized are: 1.2378 + * slotID (can't change) 1.2379 + * slotDescription (can't change once defined) 1.2380 + * the locks and hash tables (difficult to change in running code, and 1.2381 + * unnecessary. hash tables and list are cleared on shutdown, but they 1.2382 + * are cleared in a 'friendly' way). 1.2383 + * session and object ID counters -- so any old sessions and objects in the 1.2384 + * application will get properly notified that the world has changed. 1.2385 + * 1.2386 + * things that are reinitialized: 1.2387 + * database (otherwise what would the point be;). 1.2388 + * state variables related to databases. 1.2389 + * session count stat info. 1.2390 + * tokenDescription. 1.2391 + * 1.2392 + * NOTE: slotID's 4 and greater show up as removable devices. 1.2393 + * 1.2394 + */ 1.2395 +CK_RV 1.2396 +SFTK_SlotReInit(SFTKSlot *slot, char *configdir, char *updatedir, 1.2397 + char *updateID, sftk_token_parameters *params, int moduleIndex) 1.2398 +{ 1.2399 + PRBool needLogin = !params->noKeyDB; 1.2400 + CK_RV crv; 1.2401 + 1.2402 + slot->hasTokens = PR_FALSE; 1.2403 + slot->sessionIDConflict = 0; 1.2404 + slot->sessionCount = 0; 1.2405 + slot->rwSessionCount = 0; 1.2406 + slot->needLogin = PR_FALSE; 1.2407 + slot->isLoggedIn = PR_FALSE; 1.2408 + slot->ssoLoggedIn = PR_FALSE; 1.2409 + slot->DB_loaded = PR_FALSE; 1.2410 + slot->certDB = NULL; 1.2411 + slot->keyDB = NULL; 1.2412 + slot->minimumPinLen = 0; 1.2413 + slot->readOnly = params->readOnly; 1.2414 + sftk_setStringName(params->tokdes ? params->tokdes : 1.2415 + sftk_getDefTokName(slot->slotID), slot->tokDescription, 1.2416 + sizeof(slot->tokDescription),PR_TRUE); 1.2417 + sftk_setStringName(params->updtokdes ? params->updtokdes : " ", 1.2418 + slot->updateTokDescription, 1.2419 + sizeof(slot->updateTokDescription),PR_TRUE); 1.2420 + 1.2421 + if ((!params->noCertDB) || (!params->noKeyDB)) { 1.2422 + SFTKDBHandle * certHandle = NULL; 1.2423 + SFTKDBHandle *keyHandle = NULL; 1.2424 + crv = sftk_DBInit(params->configdir ? params->configdir : configdir, 1.2425 + params->certPrefix, params->keyPrefix, 1.2426 + params->updatedir ? params->updatedir : updatedir, 1.2427 + params->updCertPrefix, params->updKeyPrefix, 1.2428 + params->updateID ? params->updateID : updateID, 1.2429 + params->readOnly, params->noCertDB, params->noKeyDB, 1.2430 + params->forceOpen, 1.2431 + moduleIndex == NSC_FIPS_MODULE, 1.2432 + &certHandle, &keyHandle); 1.2433 + if (crv != CKR_OK) { 1.2434 + goto loser; 1.2435 + } 1.2436 + 1.2437 + slot->certDB = certHandle; 1.2438 + slot->keyDB = keyHandle; 1.2439 + } 1.2440 + if (needLogin) { 1.2441 + /* if the data base is initialized with a null password,remember that */ 1.2442 + slot->needLogin = 1.2443 + (PRBool)!sftk_hasNullPassword(slot, slot->keyDB); 1.2444 + if ((params->minPW >= 0) && (params->minPW <= SFTK_MAX_PIN)) { 1.2445 + slot->minimumPinLen = params->minPW; 1.2446 + } 1.2447 + if ((slot->minimumPinLen == 0) && (params->pwRequired)) { 1.2448 + slot->minimumPinLen = 1; 1.2449 + } 1.2450 + if ((moduleIndex == NSC_FIPS_MODULE) && 1.2451 + (slot->minimumPinLen < FIPS_MIN_PIN)) { 1.2452 + slot->minimumPinLen = FIPS_MIN_PIN; 1.2453 + } 1.2454 + } 1.2455 + 1.2456 + slot->present = PR_TRUE; 1.2457 + return CKR_OK; 1.2458 + 1.2459 +loser: 1.2460 + SFTK_ShutdownSlot(slot); 1.2461 + return crv; 1.2462 +} 1.2463 + 1.2464 +/* 1.2465 + * initialize one of the slot structures. figure out which by the ID 1.2466 + */ 1.2467 +CK_RV 1.2468 +SFTK_SlotInit(char *configdir, char *updatedir, char *updateID, 1.2469 + sftk_token_parameters *params, int moduleIndex) 1.2470 +{ 1.2471 + unsigned int i; 1.2472 + CK_SLOT_ID slotID = params->slotID; 1.2473 + SFTKSlot *slot; 1.2474 + CK_RV crv = CKR_HOST_MEMORY; 1.2475 + 1.2476 + /* 1.2477 + * first we initialize everything that is 'permanent' with this slot. 1.2478 + * that is everything we aren't going to shutdown if we close this slot 1.2479 + * and open it up again with different databases */ 1.2480 + 1.2481 + slot = PORT_ZNew(SFTKSlot); 1.2482 + 1.2483 + if (slot == NULL) { 1.2484 + return CKR_HOST_MEMORY; 1.2485 + } 1.2486 + 1.2487 + slot->optimizeSpace = params->optimizeSpace; 1.2488 + if (slot->optimizeSpace) { 1.2489 + slot->sessObjHashSize = SPACE_SESSION_OBJECT_HASH_SIZE; 1.2490 + slot->sessHashSize = SPACE_SESSION_HASH_SIZE; 1.2491 + slot->numSessionLocks = 1; 1.2492 + } else { 1.2493 + slot->sessObjHashSize = TIME_SESSION_OBJECT_HASH_SIZE; 1.2494 + slot->sessHashSize = TIME_SESSION_HASH_SIZE; 1.2495 + slot->numSessionLocks = slot->sessHashSize/BUCKETS_PER_SESSION_LOCK; 1.2496 + } 1.2497 + slot->sessionLockMask = slot->numSessionLocks-1; 1.2498 + 1.2499 + slot->slotLock = PZ_NewLock(nssILockSession); 1.2500 + if (slot->slotLock == NULL) 1.2501 + goto mem_loser; 1.2502 + slot->sessionLock = PORT_ZNewArray(PZLock *, slot->numSessionLocks); 1.2503 + if (slot->sessionLock == NULL) 1.2504 + goto mem_loser; 1.2505 + for (i=0; i < slot->numSessionLocks; i++) { 1.2506 + slot->sessionLock[i] = PZ_NewLock(nssILockSession); 1.2507 + if (slot->sessionLock[i] == NULL) 1.2508 + goto mem_loser; 1.2509 + } 1.2510 + slot->objectLock = PZ_NewLock(nssILockObject); 1.2511 + if (slot->objectLock == NULL) 1.2512 + goto mem_loser; 1.2513 + slot->pwCheckLock = PR_NewLock(); 1.2514 + if (slot->pwCheckLock == NULL) 1.2515 + goto mem_loser; 1.2516 + slot->head = PORT_ZNewArray(SFTKSession *, slot->sessHashSize); 1.2517 + if (slot->head == NULL) 1.2518 + goto mem_loser; 1.2519 + slot->sessObjHashTable = PORT_ZNewArray(SFTKObject *, slot->sessObjHashSize); 1.2520 + if (slot->sessObjHashTable == NULL) 1.2521 + goto mem_loser; 1.2522 + slot->tokObjHashTable = PL_NewHashTable(64,sftk_HashNumber,PL_CompareValues, 1.2523 + SECITEM_HashCompare, NULL, 0); 1.2524 + if (slot->tokObjHashTable == NULL) 1.2525 + goto mem_loser; 1.2526 + 1.2527 + slot->sessionIDCount = 0; 1.2528 + slot->sessionObjectHandleCount = minSessionObjectHandle; 1.2529 + slot->slotID = slotID; 1.2530 + sftk_setStringName(params->slotdes ? params->slotdes : 1.2531 + sftk_getDefSlotName(slotID), slot->slotDescription, 1.2532 + sizeof(slot->slotDescription), PR_TRUE); 1.2533 + 1.2534 + /* call the reinit code to set everything that changes between token 1.2535 + * init calls */ 1.2536 + crv = SFTK_SlotReInit(slot, configdir, updatedir, updateID, 1.2537 + params, moduleIndex); 1.2538 + if (crv != CKR_OK) { 1.2539 + goto loser; 1.2540 + } 1.2541 + crv = sftk_RegisterSlot(slot, moduleIndex); 1.2542 + if (crv != CKR_OK) { 1.2543 + goto loser; 1.2544 + } 1.2545 + return CKR_OK; 1.2546 + 1.2547 +mem_loser: 1.2548 + crv = CKR_HOST_MEMORY; 1.2549 +loser: 1.2550 + SFTK_DestroySlotData(slot); 1.2551 + return crv; 1.2552 +} 1.2553 + 1.2554 + 1.2555 +CK_RV sftk_CloseAllSessions(SFTKSlot *slot, PRBool logout) 1.2556 +{ 1.2557 + SFTKSession *session; 1.2558 + unsigned int i; 1.2559 + SFTKDBHandle *handle; 1.2560 + 1.2561 + /* first log out the card */ 1.2562 + /* special case - if we are in a middle of upgrade, we want to close the 1.2563 + * sessions to fake a token removal to tell the upper level code we have 1.2564 + * switched from one database to another, but we don't want to 1.2565 + * explicity logout in case we can continue the upgrade with the 1.2566 + * existing password if possible. 1.2567 + */ 1.2568 + if (logout) { 1.2569 + handle = sftk_getKeyDB(slot); 1.2570 + SKIP_AFTER_FORK(PZ_Lock(slot->slotLock)); 1.2571 + slot->isLoggedIn = PR_FALSE; 1.2572 + if (slot->needLogin && handle) { 1.2573 + sftkdb_ClearPassword(handle); 1.2574 + } 1.2575 + SKIP_AFTER_FORK(PZ_Unlock(slot->slotLock)); 1.2576 + if (handle) { 1.2577 + sftk_freeDB(handle); 1.2578 + } 1.2579 + } 1.2580 + 1.2581 + /* now close all the current sessions */ 1.2582 + /* NOTE: If you try to open new sessions before NSC_CloseAllSessions 1.2583 + * completes, some of those new sessions may or may not be closed by 1.2584 + * NSC_CloseAllSessions... but any session running when this code starts 1.2585 + * will guarrenteed be close, and no session will be partially closed */ 1.2586 + for (i=0; i < slot->sessHashSize; i++) { 1.2587 + PZLock *lock = SFTK_SESSION_LOCK(slot,i); 1.2588 + do { 1.2589 + SKIP_AFTER_FORK(PZ_Lock(lock)); 1.2590 + session = slot->head[i]; 1.2591 + /* hand deque */ 1.2592 + /* this duplicates function of NSC_close session functions, but 1.2593 + * because we know that we are freeing all the sessions, we can 1.2594 + * do more efficient processing */ 1.2595 + if (session) { 1.2596 + slot->head[i] = session->next; 1.2597 + if (session->next) session->next->prev = NULL; 1.2598 + session->next = session->prev = NULL; 1.2599 + SKIP_AFTER_FORK(PZ_Unlock(lock)); 1.2600 + SKIP_AFTER_FORK(PZ_Lock(slot->slotLock)); 1.2601 + --slot->sessionCount; 1.2602 + SKIP_AFTER_FORK(PZ_Unlock(slot->slotLock)); 1.2603 + if (session->info.flags & CKF_RW_SESSION) { 1.2604 + PR_ATOMIC_DECREMENT(&slot->rwSessionCount); 1.2605 + } 1.2606 + } else { 1.2607 + SKIP_AFTER_FORK(PZ_Unlock(lock)); 1.2608 + } 1.2609 + if (session) sftk_FreeSession(session); 1.2610 + } while (session != NULL); 1.2611 + } 1.2612 + return CKR_OK; 1.2613 +} 1.2614 + 1.2615 +/* 1.2616 + * shut down the databases. 1.2617 + * we get the slot lock (which also protects slot->certDB and slot->keyDB) 1.2618 + * and clear the values so the new users will not find the databases. 1.2619 + * once things are clear, we can release our references to the databases. 1.2620 + * The databases will close when the last reference is released. 1.2621 + * 1.2622 + * We use reference counts so that we don't crash if someone shuts down 1.2623 + * a token that another thread is actively using. 1.2624 + */ 1.2625 +static void 1.2626 +sftk_DBShutdown(SFTKSlot *slot) 1.2627 +{ 1.2628 + SFTKDBHandle *certHandle; 1.2629 + SFTKDBHandle *keyHandle; 1.2630 + SKIP_AFTER_FORK(PZ_Lock(slot->slotLock)); 1.2631 + certHandle = slot->certDB; 1.2632 + slot->certDB = NULL; 1.2633 + keyHandle = slot->keyDB; 1.2634 + slot->keyDB = NULL; 1.2635 + SKIP_AFTER_FORK(PZ_Unlock(slot->slotLock)); 1.2636 + if (certHandle) { 1.2637 + sftk_freeDB(certHandle); 1.2638 + } 1.2639 + if (keyHandle) { 1.2640 + sftk_freeDB(keyHandle); 1.2641 + } 1.2642 +} 1.2643 + 1.2644 +CK_RV 1.2645 +SFTK_ShutdownSlot(SFTKSlot *slot) 1.2646 +{ 1.2647 + /* make sure no new PK11 calls work except C_GetSlotInfo */ 1.2648 + slot->present = PR_FALSE; 1.2649 + 1.2650 + /* close all outstanding sessions 1.2651 + * the sessHashSize variable guarentees we have all the session 1.2652 + * mechanism set up */ 1.2653 + if (slot->head) { 1.2654 + sftk_CloseAllSessions(slot, PR_TRUE); 1.2655 + } 1.2656 + 1.2657 + /* clear all objects.. session objects are cleared as a result of 1.2658 + * closing all the sessions. We just need to clear the token object 1.2659 + * cache. slot->tokObjHashTable guarentees we have the token 1.2660 + * infrastructure set up. */ 1.2661 + if (slot->tokObjHashTable) { 1.2662 + SFTK_ClearTokenKeyHashTable(slot); 1.2663 + } 1.2664 + 1.2665 + /* clear the slot description for the next guy */ 1.2666 + PORT_Memset(slot->tokDescription, 0, sizeof(slot->tokDescription)); 1.2667 + 1.2668 + /* now shut down the databases. */ 1.2669 + sftk_DBShutdown(slot); 1.2670 + return CKR_OK; 1.2671 +} 1.2672 + 1.2673 +/* 1.2674 + * initialize one of the slot structures. figure out which by the ID 1.2675 + */ 1.2676 +CK_RV 1.2677 +SFTK_DestroySlotData(SFTKSlot *slot) 1.2678 +{ 1.2679 + unsigned int i; 1.2680 + 1.2681 + SFTK_ShutdownSlot(slot); 1.2682 + 1.2683 + if (slot->tokObjHashTable) { 1.2684 + PL_HashTableDestroy(slot->tokObjHashTable); 1.2685 + slot->tokObjHashTable = NULL; 1.2686 + } 1.2687 + 1.2688 + if (slot->sessObjHashTable) { 1.2689 + PORT_Free(slot->sessObjHashTable); 1.2690 + slot->sessObjHashTable = NULL; 1.2691 + } 1.2692 + slot->sessObjHashSize = 0; 1.2693 + 1.2694 + if (slot->head) { 1.2695 + PORT_Free(slot->head); 1.2696 + slot->head = NULL; 1.2697 + } 1.2698 + slot->sessHashSize = 0; 1.2699 + 1.2700 + /* OK everything has been disassembled, now we can finally get rid 1.2701 + * of the locks */ 1.2702 + SKIP_AFTER_FORK(PZ_DestroyLock(slot->slotLock)); 1.2703 + slot->slotLock = NULL; 1.2704 + if (slot->sessionLock) { 1.2705 + for (i=0; i < slot->numSessionLocks; i++) { 1.2706 + if (slot->sessionLock[i]) { 1.2707 + SKIP_AFTER_FORK(PZ_DestroyLock(slot->sessionLock[i])); 1.2708 + slot->sessionLock[i] = NULL; 1.2709 + } 1.2710 + } 1.2711 + PORT_Free(slot->sessionLock); 1.2712 + slot->sessionLock = NULL; 1.2713 + } 1.2714 + if (slot->objectLock) { 1.2715 + SKIP_AFTER_FORK(PZ_DestroyLock(slot->objectLock)); 1.2716 + slot->objectLock = NULL; 1.2717 + } 1.2718 + if (slot->pwCheckLock) { 1.2719 + SKIP_AFTER_FORK(PR_DestroyLock(slot->pwCheckLock)); 1.2720 + slot->pwCheckLock = NULL; 1.2721 + } 1.2722 + PORT_Free(slot); 1.2723 + return CKR_OK; 1.2724 +} 1.2725 + 1.2726 +/* 1.2727 + * handle the SECMOD.db 1.2728 + */ 1.2729 +char ** 1.2730 +NSC_ModuleDBFunc(unsigned long function,char *parameters, void *args) 1.2731 +{ 1.2732 + char *secmod = NULL; 1.2733 + char *appName = NULL; 1.2734 + char *filename = NULL; 1.2735 + NSSDBType dbType = NSS_DB_TYPE_NONE; 1.2736 + PRBool rw; 1.2737 + static char *success="Success"; 1.2738 + char **rvstr = NULL; 1.2739 + 1.2740 + rvstr = NSSUTIL_DoModuleDBFunction(function, parameters, args); 1.2741 + if (rvstr != NULL) { 1.2742 + return rvstr; 1.2743 + } 1.2744 + 1.2745 + if (PORT_GetError() != SEC_ERROR_LEGACY_DATABASE) { 1.2746 + return NULL; 1.2747 + } 1.2748 + 1.2749 + /* The legacy database uses the old dbm, which is only linked with the 1.2750 + * legacy DB handler, which is only callable from softoken */ 1.2751 + 1.2752 + secmod = _NSSUTIL_GetSecmodName(parameters, &dbType, &appName, 1.2753 + &filename, &rw); 1.2754 + 1.2755 + switch (function) { 1.2756 + case SECMOD_MODULE_DB_FUNCTION_FIND: 1.2757 + if (secmod == NULL) { 1.2758 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.2759 + return NULL; 1.2760 + } 1.2761 + if (rw && (dbType != NSS_DB_TYPE_LEGACY) && 1.2762 + (dbType != NSS_DB_TYPE_MULTIACCESS)) { 1.2763 + /* if we get here, we are trying to update the local database */ 1.2764 + /* force data from the legacy DB */ 1.2765 + char *oldSecmod = NULL; 1.2766 + char *oldAppName = NULL; 1.2767 + char *oldFilename = NULL; 1.2768 + PRBool oldrw; 1.2769 + char **strings = NULL; 1.2770 + int i; 1.2771 + 1.2772 + dbType = NSS_DB_TYPE_LEGACY; 1.2773 + oldSecmod = _NSSUTIL_GetSecmodName(parameters,&dbType, &oldAppName, 1.2774 + &oldFilename, &oldrw); 1.2775 + strings = sftkdbCall_ReadSecmodDB(appName, oldFilename, oldSecmod, 1.2776 + (char *)parameters, oldrw); 1.2777 + if (strings) { 1.2778 + /* write out the strings */ 1.2779 + for (i=0; strings[i]; i++) { 1.2780 + NSSUTIL_DoModuleDBFunction(SECMOD_MODULE_DB_FUNCTION_ADD, 1.2781 + parameters, strings[i]); 1.2782 + } 1.2783 + sftkdbCall_ReleaseSecmodDBData(oldAppName,oldFilename,oldSecmod, 1.2784 + (char **)strings,oldrw); 1.2785 + } else { 1.2786 + /* write out a dummy record */ 1.2787 + NSSUTIL_DoModuleDBFunction(SECMOD_MODULE_DB_FUNCTION_ADD, 1.2788 + parameters, " "); 1.2789 + } 1.2790 + if (oldSecmod) { PR_smprintf_free(oldSecmod); } 1.2791 + if (oldAppName) { PORT_Free(oldAppName); } 1.2792 + if (oldFilename) { PORT_Free(oldFilename); } 1.2793 + rvstr = NSSUTIL_DoModuleDBFunction(function, parameters, args); 1.2794 + break; 1.2795 + } 1.2796 + rvstr = sftkdbCall_ReadSecmodDB(appName,filename,secmod, 1.2797 + (char *)parameters,rw); 1.2798 + break; 1.2799 + case SECMOD_MODULE_DB_FUNCTION_ADD: 1.2800 + if (secmod == NULL) { 1.2801 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.2802 + return NULL; 1.2803 + } 1.2804 + rvstr = (sftkdbCall_AddSecmodDB(appName,filename,secmod, 1.2805 + (char *)args,rw) == SECSuccess) ? &success: NULL; 1.2806 + break; 1.2807 + case SECMOD_MODULE_DB_FUNCTION_DEL: 1.2808 + if (secmod == NULL) { 1.2809 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.2810 + return NULL; 1.2811 + } 1.2812 + rvstr = (sftkdbCall_DeleteSecmodDB(appName,filename,secmod, 1.2813 + (char *)args,rw) == SECSuccess) ? &success: NULL; 1.2814 + break; 1.2815 + case SECMOD_MODULE_DB_FUNCTION_RELEASE: 1.2816 + rvstr = (sftkdbCall_ReleaseSecmodDBData(appName,filename,secmod, 1.2817 + (char **)args,rw) == SECSuccess) ? &success: NULL; 1.2818 + break; 1.2819 + } 1.2820 + if (secmod) PR_smprintf_free(secmod); 1.2821 + if (appName) PORT_Free(appName); 1.2822 + if (filename) PORT_Free(filename); 1.2823 + return rvstr; 1.2824 +} 1.2825 + 1.2826 +static void nscFreeAllSlots(int moduleIndex) 1.2827 +{ 1.2828 + /* free all the slots */ 1.2829 + SFTKSlot *slot = NULL; 1.2830 + CK_SLOT_ID slotID; 1.2831 + int i; 1.2832 + 1.2833 + if (nscSlotList[moduleIndex]) { 1.2834 + CK_ULONG tmpSlotCount = nscSlotCount[moduleIndex]; 1.2835 + CK_SLOT_ID_PTR tmpSlotList = nscSlotList[moduleIndex]; 1.2836 + PLHashTable *tmpSlotHashTable = nscSlotHashTable[moduleIndex]; 1.2837 + 1.2838 + /* first close all the session */ 1.2839 + for (i=0; i < (int) tmpSlotCount; i++) { 1.2840 + slotID = tmpSlotList[i]; 1.2841 + (void) NSC_CloseAllSessions(slotID); 1.2842 + } 1.2843 + 1.2844 + /* now clear out the statics */ 1.2845 + nscSlotList[moduleIndex] = NULL; 1.2846 + nscSlotCount[moduleIndex] = 0; 1.2847 + nscSlotHashTable[moduleIndex] = NULL; 1.2848 + nscSlotListSize[moduleIndex] = 0; 1.2849 + 1.2850 + for (i=0; i < (int) tmpSlotCount; i++) { 1.2851 + slotID = tmpSlotList[i]; 1.2852 + slot = (SFTKSlot *) 1.2853 + PL_HashTableLookup(tmpSlotHashTable, (void *)slotID); 1.2854 + PORT_Assert(slot); 1.2855 + if (!slot) continue; 1.2856 + SFTK_DestroySlotData(slot); 1.2857 + PL_HashTableRemove(tmpSlotHashTable, (void *)slotID); 1.2858 + } 1.2859 + PORT_Free(tmpSlotList); 1.2860 + PL_HashTableDestroy(tmpSlotHashTable); 1.2861 + } 1.2862 +} 1.2863 + 1.2864 +static void 1.2865 +sftk_closePeer(PRBool isFIPS) 1.2866 +{ 1.2867 + CK_SLOT_ID slotID = isFIPS ? PRIVATE_KEY_SLOT_ID: FIPS_SLOT_ID; 1.2868 + SFTKSlot *slot; 1.2869 + int moduleIndex = isFIPS? NSC_NON_FIPS_MODULE : NSC_FIPS_MODULE; 1.2870 + PLHashTable *tmpSlotHashTable = nscSlotHashTable[moduleIndex]; 1.2871 + 1.2872 + slot = (SFTKSlot *) PL_HashTableLookup(tmpSlotHashTable, (void *)slotID); 1.2873 + if (slot == NULL) { 1.2874 + return; 1.2875 + } 1.2876 + sftk_DBShutdown(slot); 1.2877 + return; 1.2878 +} 1.2879 + 1.2880 +/* NSC_Initialize initializes the Cryptoki library. */ 1.2881 +CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) 1.2882 +{ 1.2883 + CK_RV crv = CKR_OK; 1.2884 + SECStatus rv; 1.2885 + CK_C_INITIALIZE_ARGS *init_args = (CK_C_INITIALIZE_ARGS *) pReserved; 1.2886 + int i; 1.2887 + int moduleIndex = isFIPS? NSC_FIPS_MODULE : NSC_NON_FIPS_MODULE; 1.2888 + 1.2889 + if (isFIPS) { 1.2890 + loginWaitTime = PR_SecondsToInterval(1); 1.2891 + } 1.2892 + 1.2893 + ENABLE_FORK_CHECK(); 1.2894 + 1.2895 + rv = SECOID_Init(); 1.2896 + if (rv != SECSuccess) { 1.2897 + crv = CKR_DEVICE_ERROR; 1.2898 + return crv; 1.2899 + } 1.2900 + 1.2901 + rv = RNG_RNGInit(); /* initialize random number generator */ 1.2902 + if (rv != SECSuccess) { 1.2903 + crv = CKR_DEVICE_ERROR; 1.2904 + return crv; 1.2905 + } 1.2906 + rv = BL_Init(); /* initialize freebl engine */ 1.2907 + if (rv != SECSuccess) { 1.2908 + crv = CKR_DEVICE_ERROR; 1.2909 + return crv; 1.2910 + } 1.2911 + 1.2912 + /* NOTE: 1.2913 + * we should be getting out mutexes from this list, not statically binding 1.2914 + * them from NSPR. This should happen before we allow the internal to split 1.2915 + * off from the rest on NSS. 1.2916 + */ 1.2917 + 1.2918 + /* initialize the key and cert db's */ 1.2919 + if (init_args && (!(init_args->flags & CKF_OS_LOCKING_OK))) { 1.2920 + if (init_args->CreateMutex && init_args->DestroyMutex && 1.2921 + init_args->LockMutex && init_args->UnlockMutex) { 1.2922 + /* softoken always uses NSPR (ie. OS locking), and doesn't know how 1.2923 + * to use the lock functions provided by the application. 1.2924 + */ 1.2925 + crv = CKR_CANT_LOCK; 1.2926 + return crv; 1.2927 + } 1.2928 + if (init_args->CreateMutex || init_args->DestroyMutex || 1.2929 + init_args->LockMutex || init_args->UnlockMutex) { 1.2930 + /* only some of the lock functions were provided by the 1.2931 + * application. This is invalid per PKCS#11 spec. 1.2932 + */ 1.2933 + crv = CKR_ARGUMENTS_BAD; 1.2934 + return crv; 1.2935 + } 1.2936 + } 1.2937 + crv = CKR_ARGUMENTS_BAD; 1.2938 + if ((init_args && init_args->LibraryParameters)) { 1.2939 + sftk_parameters paramStrings; 1.2940 + 1.2941 + crv = sftk_parseParameters 1.2942 + ((char *)init_args->LibraryParameters, ¶mStrings, isFIPS); 1.2943 + if (crv != CKR_OK) { 1.2944 + return crv; 1.2945 + } 1.2946 + crv = sftk_configure(paramStrings.man, paramStrings.libdes); 1.2947 + if (crv != CKR_OK) { 1.2948 + goto loser; 1.2949 + } 1.2950 + 1.2951 + /* if we have a peer already open, have him close his DB's so we 1.2952 + * don't clobber each other. */ 1.2953 + if ((isFIPS && nsc_init) || (!isFIPS && nsf_init)) { 1.2954 + sftk_closePeer(isFIPS); 1.2955 + if (sftk_audit_enabled) { 1.2956 + if (isFIPS && nsc_init) { 1.2957 + sftk_LogAuditMessage(NSS_AUDIT_INFO, NSS_AUDIT_FIPS_STATE, 1.2958 + "enabled FIPS mode"); 1.2959 + } else { 1.2960 + sftk_LogAuditMessage(NSS_AUDIT_INFO, NSS_AUDIT_FIPS_STATE, 1.2961 + "disabled FIPS mode"); 1.2962 + } 1.2963 + } 1.2964 + } 1.2965 + 1.2966 + for (i=0; i < paramStrings.token_count; i++) { 1.2967 + crv = SFTK_SlotInit(paramStrings.configdir, 1.2968 + paramStrings.updatedir, paramStrings.updateID, 1.2969 + ¶mStrings.tokens[i], moduleIndex); 1.2970 + if (crv != CKR_OK) { 1.2971 + nscFreeAllSlots(moduleIndex); 1.2972 + break; 1.2973 + } 1.2974 + } 1.2975 +loser: 1.2976 + sftk_freeParams(¶mStrings); 1.2977 + } 1.2978 + if (CKR_OK == crv) { 1.2979 + sftk_InitFreeLists(); 1.2980 + } 1.2981 + 1.2982 +#ifndef NO_FORK_CHECK 1.2983 + if (CKR_OK == crv) { 1.2984 +#if defined(CHECK_FORK_MIXED) 1.2985 + /* Before Solaris 10, fork handlers are not unregistered at dlclose() 1.2986 + * time. So, we only use pthread_atfork on Solaris 10 and later. For 1.2987 + * earlier versions, we use PID checks. 1.2988 + */ 1.2989 + char buf[200]; 1.2990 + int major = 0, minor = 0; 1.2991 + 1.2992 + long rv = sysinfo(SI_RELEASE, buf, sizeof(buf)); 1.2993 + if (rv > 0 && rv < sizeof(buf)) { 1.2994 + if (2 == sscanf(buf, "%d.%d", &major, &minor)) { 1.2995 + /* Are we on Solaris 10 or greater ? */ 1.2996 + if (major >5 || (5 == major && minor >= 10)) { 1.2997 + /* we are safe to use pthread_atfork */ 1.2998 + usePthread_atfork = PR_TRUE; 1.2999 + } 1.3000 + } 1.3001 + } 1.3002 + if (usePthread_atfork) { 1.3003 + pthread_atfork(NULL, NULL, ForkedChild); 1.3004 + } else { 1.3005 + myPid = getpid(); 1.3006 + } 1.3007 + 1.3008 +#elif defined(CHECK_FORK_PTHREAD) 1.3009 + pthread_atfork(NULL, NULL, ForkedChild); 1.3010 +#elif defined(CHECK_FORK_GETPID) 1.3011 + myPid = getpid(); 1.3012 +#else 1.3013 +#error Incorrect fork check method. 1.3014 +#endif 1.3015 + } 1.3016 +#endif 1.3017 + return crv; 1.3018 +} 1.3019 + 1.3020 +CK_RV NSC_Initialize(CK_VOID_PTR pReserved) 1.3021 +{ 1.3022 + CK_RV crv; 1.3023 + 1.3024 + sftk_ForkReset(pReserved, &crv); 1.3025 + 1.3026 + if (nsc_init) { 1.3027 + return CKR_CRYPTOKI_ALREADY_INITIALIZED; 1.3028 + } 1.3029 + crv = nsc_CommonInitialize(pReserved,PR_FALSE); 1.3030 + nsc_init = (PRBool) (crv == CKR_OK); 1.3031 + return crv; 1.3032 +} 1.3033 + 1.3034 + 1.3035 +/* NSC_Finalize indicates that an application is done with the 1.3036 + * Cryptoki library.*/ 1.3037 +CK_RV nsc_CommonFinalize (CK_VOID_PTR pReserved, PRBool isFIPS) 1.3038 +{ 1.3039 + /* propagate the fork status to freebl and util */ 1.3040 + BL_SetForkState(parentForkedAfterC_Initialize); 1.3041 + UTIL_SetForkState(parentForkedAfterC_Initialize); 1.3042 + 1.3043 + nscFreeAllSlots(isFIPS ? NSC_FIPS_MODULE : NSC_NON_FIPS_MODULE); 1.3044 + 1.3045 + /* don't muck with the globals if our peer is still initialized */ 1.3046 + if (isFIPS && nsc_init) { 1.3047 + return CKR_OK; 1.3048 + } 1.3049 + if (!isFIPS && nsf_init) { 1.3050 + return CKR_OK; 1.3051 + } 1.3052 + 1.3053 + sftk_CleanupFreeLists(); 1.3054 + sftkdb_Shutdown(); 1.3055 + 1.3056 + /* This function does not discard all our previously aquired entropy. */ 1.3057 + RNG_RNGShutdown(); 1.3058 + 1.3059 + /* tell freeBL to clean up after itself */ 1.3060 + BL_Cleanup(); 1.3061 + 1.3062 + /* reset fork status in freebl. We must do this before BL_Unload so that 1.3063 + * this call doesn't force freebl to be reloaded. */ 1.3064 + BL_SetForkState(PR_FALSE); 1.3065 + 1.3066 + /* unload freeBL shared library from memory. This may only decrement the 1.3067 + * OS refcount if it's been loaded multiple times, eg. by libssl */ 1.3068 + BL_Unload(); 1.3069 + 1.3070 + /* clean up the default OID table */ 1.3071 + SECOID_Shutdown(); 1.3072 + 1.3073 + /* reset fork status in util */ 1.3074 + UTIL_SetForkState(PR_FALSE); 1.3075 + 1.3076 + nsc_init = PR_FALSE; 1.3077 + 1.3078 +#ifdef CHECK_FORK_MIXED 1.3079 + if (!usePthread_atfork) { 1.3080 + myPid = 0; /* allow CHECK_FORK in the next softoken initialization to 1.3081 + * succeed */ 1.3082 + } else { 1.3083 + forked = PR_FALSE; /* allow reinitialization */ 1.3084 + } 1.3085 +#elif defined(CHECK_FORK_GETPID) 1.3086 + myPid = 0; /* allow reinitialization */ 1.3087 +#elif defined (CHECK_FORK_PTHREAD) 1.3088 + forked = PR_FALSE; /* allow reinitialization */ 1.3089 +#endif 1.3090 + return CKR_OK; 1.3091 +} 1.3092 + 1.3093 +/* Hard-reset the entire softoken PKCS#11 module if the parent process forked 1.3094 + * while it was initialized. */ 1.3095 +PRBool sftk_ForkReset(CK_VOID_PTR pReserved, CK_RV* crv) 1.3096 +{ 1.3097 +#ifndef NO_FORK_CHECK 1.3098 + if (PARENT_FORKED()) { 1.3099 + parentForkedAfterC_Initialize = PR_TRUE; 1.3100 + if (nsc_init) { 1.3101 + /* finalize non-FIPS token */ 1.3102 + *crv = nsc_CommonFinalize(pReserved, PR_FALSE); 1.3103 + PORT_Assert(CKR_OK == *crv); 1.3104 + nsc_init = (PRBool) !(*crv == CKR_OK); 1.3105 + } 1.3106 + if (nsf_init) { 1.3107 + /* finalize FIPS token */ 1.3108 + *crv = nsc_CommonFinalize(pReserved, PR_TRUE); 1.3109 + PORT_Assert(CKR_OK == *crv); 1.3110 + nsf_init = (PRBool) !(*crv == CKR_OK); 1.3111 + } 1.3112 + parentForkedAfterC_Initialize = PR_FALSE; 1.3113 + return PR_TRUE; 1.3114 + } 1.3115 +#endif 1.3116 + return PR_FALSE; 1.3117 +} 1.3118 + 1.3119 +/* NSC_Finalize indicates that an application is done with the 1.3120 + * Cryptoki library.*/ 1.3121 +CK_RV NSC_Finalize (CK_VOID_PTR pReserved) 1.3122 +{ 1.3123 + CK_RV crv; 1.3124 + 1.3125 + /* reset entire PKCS#11 module upon fork */ 1.3126 + if (sftk_ForkReset(pReserved, &crv)) { 1.3127 + return crv; 1.3128 + } 1.3129 + 1.3130 + if (!nsc_init) { 1.3131 + return CKR_OK; 1.3132 + } 1.3133 + 1.3134 + crv = nsc_CommonFinalize (pReserved, PR_FALSE); 1.3135 + 1.3136 + nsc_init = (PRBool) !(crv == CKR_OK); 1.3137 + 1.3138 + return crv; 1.3139 +} 1.3140 + 1.3141 +extern const char __nss_softokn_rcsid[]; 1.3142 +extern const char __nss_softokn_sccsid[]; 1.3143 + 1.3144 +/* NSC_GetInfo returns general information about Cryptoki. */ 1.3145 +CK_RV NSC_GetInfo(CK_INFO_PTR pInfo) 1.3146 +{ 1.3147 + volatile char c; /* force a reference that won't get optimized away */ 1.3148 + 1.3149 + CHECK_FORK(); 1.3150 + 1.3151 + c = __nss_softokn_rcsid[0] + __nss_softokn_sccsid[0]; 1.3152 + pInfo->cryptokiVersion.major = 2; 1.3153 + pInfo->cryptokiVersion.minor = 20; 1.3154 + PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); 1.3155 + pInfo->libraryVersion.major = SOFTOKEN_VMAJOR; 1.3156 + pInfo->libraryVersion.minor = SOFTOKEN_VMINOR; 1.3157 + PORT_Memcpy(pInfo->libraryDescription,libraryDescription,32); 1.3158 + pInfo->flags = 0; 1.3159 + return CKR_OK; 1.3160 +} 1.3161 + 1.3162 + 1.3163 +/* NSC_GetSlotList obtains a list of slots in the system. */ 1.3164 +CK_RV nsc_CommonGetSlotList(CK_BBOOL tokenPresent, 1.3165 + CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount, int moduleIndex) 1.3166 +{ 1.3167 + *pulCount = nscSlotCount[moduleIndex]; 1.3168 + if (pSlotList != NULL) { 1.3169 + PORT_Memcpy(pSlotList,nscSlotList[moduleIndex], 1.3170 + nscSlotCount[moduleIndex]*sizeof(CK_SLOT_ID)); 1.3171 + } 1.3172 + return CKR_OK; 1.3173 +} 1.3174 + 1.3175 +/* NSC_GetSlotList obtains a list of slots in the system. */ 1.3176 +CK_RV NSC_GetSlotList(CK_BBOOL tokenPresent, 1.3177 + CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) 1.3178 +{ 1.3179 + CHECK_FORK(); 1.3180 + return nsc_CommonGetSlotList(tokenPresent, pSlotList, pulCount, 1.3181 + NSC_NON_FIPS_MODULE); 1.3182 +} 1.3183 + 1.3184 +/* NSC_GetSlotInfo obtains information about a particular slot in the system. */ 1.3185 +CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) 1.3186 +{ 1.3187 + SFTKSlot *slot = sftk_SlotFromID(slotID, PR_TRUE); 1.3188 + 1.3189 + CHECK_FORK(); 1.3190 + 1.3191 + if (slot == NULL) return CKR_SLOT_ID_INVALID; 1.3192 + 1.3193 + PORT_Memcpy(pInfo->manufacturerID,manufacturerID, 1.3194 + sizeof(pInfo->manufacturerID)); 1.3195 + PORT_Memcpy(pInfo->slotDescription,slot->slotDescription, 1.3196 + sizeof(pInfo->slotDescription)); 1.3197 + pInfo->flags = (slot->present) ? CKF_TOKEN_PRESENT : 0; 1.3198 + 1.3199 + /* all user defined slots are defined as removable */ 1.3200 + if (slotID >= SFTK_MIN_USER_SLOT_ID) { 1.3201 + pInfo->flags |= CKF_REMOVABLE_DEVICE; 1.3202 + } else { 1.3203 + /* In the case where we are doing a merge update, we need 1.3204 + * the DB slot to be removable so the token name can change 1.3205 + * appropriately. */ 1.3206 + SFTKDBHandle *handle = sftk_getKeyDB(slot); 1.3207 + if (handle) { 1.3208 + if (sftkdb_InUpdateMerge(handle)) { 1.3209 + pInfo->flags |= CKF_REMOVABLE_DEVICE; 1.3210 + } 1.3211 + sftk_freeDB(handle); 1.3212 + } 1.3213 + } 1.3214 + 1.3215 + /* ok we really should read it out of the keydb file. */ 1.3216 + /* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */ 1.3217 + pInfo->hardwareVersion.major = SOFTOKEN_VMAJOR; 1.3218 + pInfo->hardwareVersion.minor = SOFTOKEN_VMINOR; 1.3219 + pInfo->firmwareVersion.major = SOFTOKEN_VPATCH; 1.3220 + pInfo->firmwareVersion.minor = SOFTOKEN_VBUILD; 1.3221 + return CKR_OK; 1.3222 +} 1.3223 + 1.3224 +/* 1.3225 + * check the current state of the 'needLogin' flag in case the database has 1.3226 + * been changed underneath us. 1.3227 + */ 1.3228 +static PRBool 1.3229 +sftk_checkNeedLogin(SFTKSlot *slot, SFTKDBHandle *keyHandle) 1.3230 +{ 1.3231 + if (sftkdb_PWCached(keyHandle) == SECSuccess) { 1.3232 + return slot->needLogin; 1.3233 + } 1.3234 + slot->needLogin = (PRBool)!sftk_hasNullPassword(slot, keyHandle); 1.3235 + return (slot->needLogin); 1.3236 +} 1.3237 + 1.3238 +static PRBool 1.3239 +sftk_isBlank(const char *s, int len) 1.3240 +{ 1.3241 + int i; 1.3242 + for (i=0; i < len; i++) { 1.3243 + if (s[i] != ' ') { 1.3244 + return PR_FALSE; 1.3245 + } 1.3246 + } 1.3247 + return PR_TRUE; 1.3248 +} 1.3249 + 1.3250 +/* NSC_GetTokenInfo obtains information about a particular token in 1.3251 + * the system. */ 1.3252 +CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) 1.3253 +{ 1.3254 + SFTKSlot *slot; 1.3255 + SFTKDBHandle *handle; 1.3256 + 1.3257 + CHECK_FORK(); 1.3258 + 1.3259 + if (!nsc_init && !nsf_init) return CKR_CRYPTOKI_NOT_INITIALIZED; 1.3260 + slot = sftk_SlotFromID(slotID, PR_FALSE); 1.3261 + if (slot == NULL) return CKR_SLOT_ID_INVALID; 1.3262 + 1.3263 + PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); 1.3264 + PORT_Memcpy(pInfo->model,"NSS 3 ",16); 1.3265 + PORT_Memcpy(pInfo->serialNumber,"0000000000000000",16); 1.3266 + PORT_Memcpy(pInfo->utcTime,"0000000000000000",16); 1.3267 + pInfo->ulMaxSessionCount = 0; /* arbitrarily large */ 1.3268 + pInfo->ulSessionCount = slot->sessionCount; 1.3269 + pInfo->ulMaxRwSessionCount = 0; /* arbitarily large */ 1.3270 + pInfo->ulRwSessionCount = slot->rwSessionCount; 1.3271 + pInfo->firmwareVersion.major = 0; 1.3272 + pInfo->firmwareVersion.minor = 0; 1.3273 + PORT_Memcpy(pInfo->label,slot->tokDescription,sizeof(pInfo->label)); 1.3274 + handle = sftk_getKeyDB(slot); 1.3275 + pInfo->flags = CKF_RNG | CKF_DUAL_CRYPTO_OPERATIONS; 1.3276 + if (handle == NULL) { 1.3277 + pInfo->flags |= CKF_WRITE_PROTECTED; 1.3278 + pInfo->ulMaxPinLen = 0; 1.3279 + pInfo->ulMinPinLen = 0; 1.3280 + pInfo->ulTotalPublicMemory = 0; 1.3281 + pInfo->ulFreePublicMemory = 0; 1.3282 + pInfo->ulTotalPrivateMemory = 0; 1.3283 + pInfo->ulFreePrivateMemory = 0; 1.3284 + pInfo->hardwareVersion.major = 4; 1.3285 + pInfo->hardwareVersion.minor = 0; 1.3286 + } else { 1.3287 + /* 1.3288 + * we have three possible states which we may be in: 1.3289 + * (1) No DB password has been initialized. This also means we 1.3290 + * have no keys in the key db. 1.3291 + * (2) Password initialized to NULL. This means we have keys, but 1.3292 + * the user has chosen not use a password. 1.3293 + * (3) Finally we have an initialized password whicn is not NULL, and 1.3294 + * we will need to prompt for it. 1.3295 + */ 1.3296 + if (sftkdb_HasPasswordSet(handle) == SECFailure) { 1.3297 + pInfo->flags |= CKF_LOGIN_REQUIRED; 1.3298 + } else if (!sftk_checkNeedLogin(slot,handle)) { 1.3299 + pInfo->flags |= CKF_USER_PIN_INITIALIZED; 1.3300 + } else { 1.3301 + pInfo->flags |= CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED; 1.3302 + /* 1.3303 + * if we are doing a merge style update, and we need to get the password 1.3304 + * of our source database (the database we are updating from), make sure we 1.3305 + * return a token name that will match the database we are prompting for. 1.3306 + */ 1.3307 + if (sftkdb_NeedUpdateDBPassword(handle)) { 1.3308 + /* if we have an update tok description, use it. otherwise 1.3309 + * use the updateID for this database */ 1.3310 + if (!sftk_isBlank(slot->updateTokDescription, 1.3311 + sizeof(pInfo->label))) { 1.3312 + PORT_Memcpy(pInfo->label,slot->updateTokDescription, 1.3313 + sizeof(pInfo->label)); 1.3314 + } else { 1.3315 + /* build from updateID */ 1.3316 + const char *updateID = sftkdb_GetUpdateID(handle); 1.3317 + if (updateID) { 1.3318 + sftk_setStringName(updateID, (char *)pInfo->label, 1.3319 + sizeof(pInfo->label), PR_FALSE); 1.3320 + } 1.3321 + } 1.3322 + } 1.3323 + } 1.3324 + pInfo->ulMaxPinLen = SFTK_MAX_PIN; 1.3325 + pInfo->ulMinPinLen = (CK_ULONG)slot->minimumPinLen; 1.3326 + pInfo->ulTotalPublicMemory = 1; 1.3327 + pInfo->ulFreePublicMemory = 1; 1.3328 + pInfo->ulTotalPrivateMemory = 1; 1.3329 + pInfo->ulFreePrivateMemory = 1; 1.3330 +#ifdef SHDB_FIXME 1.3331 + pInfo->hardwareVersion.major = CERT_DB_FILE_VERSION; 1.3332 + pInfo->hardwareVersion.minor = handle->version; 1.3333 +#else 1.3334 + pInfo->hardwareVersion.major = 0; 1.3335 + pInfo->hardwareVersion.minor = 0; 1.3336 +#endif 1.3337 + sftk_freeDB(handle); 1.3338 + } 1.3339 + /* 1.3340 + * CKF_LOGIN_REQUIRED CKF_USER_PIN_INITIALIZED how CKF_TOKEN_INITIALIZED 1.3341 + * should be set 1.3342 + * 0 0 1 1.3343 + * 1 0 0 1.3344 + * 0 1 1 1.3345 + * 1 1 1 1.3346 + */ 1.3347 + if (!(pInfo->flags & CKF_LOGIN_REQUIRED) || 1.3348 + (pInfo->flags & CKF_USER_PIN_INITIALIZED)) { 1.3349 + pInfo->flags |= CKF_TOKEN_INITIALIZED; 1.3350 + } 1.3351 + return CKR_OK; 1.3352 +} 1.3353 + 1.3354 +/* NSC_GetMechanismList obtains a list of mechanism types 1.3355 + * supported by a token. */ 1.3356 +CK_RV NSC_GetMechanismList(CK_SLOT_ID slotID, 1.3357 + CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount) 1.3358 +{ 1.3359 + CK_ULONG i; 1.3360 + 1.3361 + CHECK_FORK(); 1.3362 + 1.3363 + switch (slotID) { 1.3364 + /* default: */ 1.3365 + case NETSCAPE_SLOT_ID: 1.3366 + *pulCount = mechanismCount; 1.3367 + if (pMechanismList != NULL) { 1.3368 + for (i=0; i < mechanismCount; i++) { 1.3369 + pMechanismList[i] = mechanisms[i].type; 1.3370 + } 1.3371 + } 1.3372 + break; 1.3373 + default: 1.3374 + *pulCount = 0; 1.3375 + for (i=0; i < mechanismCount; i++) { 1.3376 + if (mechanisms[i].privkey) { 1.3377 + (*pulCount)++; 1.3378 + if (pMechanismList != NULL) { 1.3379 + *pMechanismList++ = mechanisms[i].type; 1.3380 + } 1.3381 + } 1.3382 + } 1.3383 + break; 1.3384 + } 1.3385 + return CKR_OK; 1.3386 +} 1.3387 + 1.3388 + 1.3389 +/* NSC_GetMechanismInfo obtains information about a particular mechanism 1.3390 + * possibly supported by a token. */ 1.3391 +CK_RV NSC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, 1.3392 + CK_MECHANISM_INFO_PTR pInfo) 1.3393 +{ 1.3394 + PRBool isPrivateKey; 1.3395 + CK_ULONG i; 1.3396 + 1.3397 + CHECK_FORK(); 1.3398 + 1.3399 + switch (slotID) { 1.3400 + case NETSCAPE_SLOT_ID: 1.3401 + isPrivateKey = PR_FALSE; 1.3402 + break; 1.3403 + default: 1.3404 + isPrivateKey = PR_TRUE; 1.3405 + break; 1.3406 + } 1.3407 + for (i=0; i < mechanismCount; i++) { 1.3408 + if (type == mechanisms[i].type) { 1.3409 + if (isPrivateKey && !mechanisms[i].privkey) { 1.3410 + return CKR_MECHANISM_INVALID; 1.3411 + } 1.3412 + PORT_Memcpy(pInfo,&mechanisms[i].info, sizeof(CK_MECHANISM_INFO)); 1.3413 + return CKR_OK; 1.3414 + } 1.3415 + } 1.3416 + return CKR_MECHANISM_INVALID; 1.3417 +} 1.3418 + 1.3419 +CK_RV sftk_MechAllowsOperation(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE op) 1.3420 +{ 1.3421 + CK_ULONG i; 1.3422 + CK_FLAGS flags; 1.3423 + 1.3424 + switch (op) { 1.3425 + case CKA_ENCRYPT: flags = CKF_ENCRYPT; break; 1.3426 + case CKA_DECRYPT: flags = CKF_DECRYPT; break; 1.3427 + case CKA_WRAP: flags = CKF_WRAP; break; 1.3428 + case CKA_UNWRAP: flags = CKF_UNWRAP; break; 1.3429 + case CKA_SIGN: flags = CKF_SIGN; break; 1.3430 + case CKA_SIGN_RECOVER: flags = CKF_SIGN_RECOVER; break; 1.3431 + case CKA_VERIFY: flags = CKF_VERIFY; break; 1.3432 + case CKA_VERIFY_RECOVER: flags = CKF_VERIFY_RECOVER; break; 1.3433 + case CKA_DERIVE: flags = CKF_DERIVE; break; 1.3434 + default: 1.3435 + return CKR_ARGUMENTS_BAD; 1.3436 + } 1.3437 + for (i=0; i < mechanismCount; i++) { 1.3438 + if (type == mechanisms[i].type) { 1.3439 + return (flags & mechanisms[i].info.flags) ? CKR_OK 1.3440 + : CKR_MECHANISM_INVALID; 1.3441 + } 1.3442 + } 1.3443 + return CKR_MECHANISM_INVALID; 1.3444 +} 1.3445 + 1.3446 +/* NSC_InitToken initializes a token. */ 1.3447 +CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin, 1.3448 + CK_ULONG ulPinLen,CK_CHAR_PTR pLabel) { 1.3449 + SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE); 1.3450 + SFTKDBHandle *handle; 1.3451 + SFTKDBHandle *certHandle; 1.3452 + SECStatus rv; 1.3453 + unsigned int i; 1.3454 + SFTKObject *object; 1.3455 + 1.3456 + CHECK_FORK(); 1.3457 + 1.3458 + if (slot == NULL) return CKR_SLOT_ID_INVALID; 1.3459 + 1.3460 + /* don't initialize the database if we aren't talking to a token 1.3461 + * that uses the key database. 1.3462 + */ 1.3463 + if (slotID == NETSCAPE_SLOT_ID) { 1.3464 + return CKR_TOKEN_WRITE_PROTECTED; 1.3465 + } 1.3466 + 1.3467 + /* first, delete all our loaded key and cert objects from our 1.3468 + * internal list. */ 1.3469 + PZ_Lock(slot->objectLock); 1.3470 + for (i=0; i < slot->sessObjHashSize; i++) { 1.3471 + do { 1.3472 + object = slot->sessObjHashTable[i]; 1.3473 + /* hand deque */ 1.3474 + /* this duplicates function of NSC_close session functions, but 1.3475 + * because we know that we are freeing all the sessions, we can 1.3476 + * do more efficient processing */ 1.3477 + if (object) { 1.3478 + slot->sessObjHashTable[i] = object->next; 1.3479 + 1.3480 + if (object->next) object->next->prev = NULL; 1.3481 + object->next = object->prev = NULL; 1.3482 + } 1.3483 + if (object) sftk_FreeObject(object); 1.3484 + } while (object != NULL); 1.3485 + } 1.3486 + slot->DB_loaded = PR_FALSE; 1.3487 + PZ_Unlock(slot->objectLock); 1.3488 + 1.3489 + /* then clear out the key database */ 1.3490 + handle = sftk_getKeyDB(slot); 1.3491 + if (handle == NULL) { 1.3492 + return CKR_TOKEN_WRITE_PROTECTED; 1.3493 + } 1.3494 + 1.3495 + rv = sftkdb_ResetKeyDB(handle); 1.3496 + sftk_freeDB(handle); 1.3497 + if (rv != SECSuccess) { 1.3498 + return CKR_DEVICE_ERROR; 1.3499 + } 1.3500 + 1.3501 + /* finally mark all the user certs as non-user certs */ 1.3502 + certHandle = sftk_getCertDB(slot); 1.3503 + if (certHandle == NULL) return CKR_OK; 1.3504 + 1.3505 + sftk_freeDB(certHandle); 1.3506 + 1.3507 + return CKR_OK; /*is this the right function for not implemented*/ 1.3508 +} 1.3509 + 1.3510 + 1.3511 +/* NSC_InitPIN initializes the normal user's PIN. */ 1.3512 +CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession, 1.3513 + CK_CHAR_PTR pPin, CK_ULONG ulPinLen) 1.3514 +{ 1.3515 + SFTKSession *sp = NULL; 1.3516 + SFTKSlot *slot; 1.3517 + SFTKDBHandle *handle = NULL; 1.3518 + char newPinStr[SFTK_MAX_PIN+1]; 1.3519 + SECStatus rv; 1.3520 + CK_RV crv = CKR_SESSION_HANDLE_INVALID; 1.3521 + PRBool tokenRemoved = PR_FALSE; 1.3522 + 1.3523 + CHECK_FORK(); 1.3524 + 1.3525 + sp = sftk_SessionFromHandle(hSession); 1.3526 + if (sp == NULL) { 1.3527 + goto loser; 1.3528 + } 1.3529 + 1.3530 + slot = sftk_SlotFromSession(sp); 1.3531 + if (slot == NULL) { 1.3532 + goto loser; 1.3533 + } 1.3534 + 1.3535 + handle = sftk_getKeyDB(slot); 1.3536 + if (handle == NULL) { 1.3537 + crv = CKR_PIN_LEN_RANGE; 1.3538 + goto loser; 1.3539 + } 1.3540 + 1.3541 + 1.3542 + if (sp->info.state != CKS_RW_SO_FUNCTIONS) { 1.3543 + crv = CKR_USER_NOT_LOGGED_IN; 1.3544 + goto loser; 1.3545 + } 1.3546 + 1.3547 + sftk_FreeSession(sp); 1.3548 + sp = NULL; 1.3549 + 1.3550 + /* make sure the pins aren't too long */ 1.3551 + if (ulPinLen > SFTK_MAX_PIN) { 1.3552 + crv = CKR_PIN_LEN_RANGE; 1.3553 + goto loser; 1.3554 + } 1.3555 + if (ulPinLen < (CK_ULONG)slot->minimumPinLen) { 1.3556 + crv = CKR_PIN_LEN_RANGE; 1.3557 + goto loser; 1.3558 + } 1.3559 + 1.3560 + if (sftkdb_HasPasswordSet(handle) != SECFailure) { 1.3561 + crv = CKR_DEVICE_ERROR; 1.3562 + goto loser; 1.3563 + } 1.3564 + 1.3565 + /* convert to null terminated string */ 1.3566 + PORT_Memcpy(newPinStr, pPin, ulPinLen); 1.3567 + newPinStr[ulPinLen] = 0; 1.3568 + 1.3569 + /* build the hashed pins which we pass around */ 1.3570 + 1.3571 + /* change the data base */ 1.3572 + rv = sftkdb_ChangePassword(handle, NULL, newPinStr, &tokenRemoved); 1.3573 + if (tokenRemoved) { 1.3574 + sftk_CloseAllSessions(slot, PR_FALSE); 1.3575 + } 1.3576 + sftk_freeDB(handle); 1.3577 + handle = NULL; 1.3578 + 1.3579 + /* Now update our local copy of the pin */ 1.3580 + if (rv == SECSuccess) { 1.3581 + if (ulPinLen == 0) slot->needLogin = PR_FALSE; 1.3582 + return CKR_OK; 1.3583 + } 1.3584 + crv = CKR_PIN_INCORRECT; 1.3585 + 1.3586 +loser: 1.3587 + if (sp) { 1.3588 + sftk_FreeSession(sp); 1.3589 + } 1.3590 + if (handle) { 1.3591 + sftk_freeDB(handle); 1.3592 + } 1.3593 + return crv; 1.3594 +} 1.3595 + 1.3596 + 1.3597 +/* NSC_SetPIN modifies the PIN of user that is currently logged in. */ 1.3598 +/* NOTE: This is only valid for the PRIVATE_KEY_SLOT */ 1.3599 +CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, 1.3600 + CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen) 1.3601 +{ 1.3602 + SFTKSession *sp = NULL; 1.3603 + SFTKSlot *slot; 1.3604 + SFTKDBHandle *handle = NULL; 1.3605 + char newPinStr[SFTK_MAX_PIN+1],oldPinStr[SFTK_MAX_PIN+1]; 1.3606 + SECStatus rv; 1.3607 + CK_RV crv = CKR_SESSION_HANDLE_INVALID; 1.3608 + PRBool tokenRemoved = PR_FALSE; 1.3609 + 1.3610 + CHECK_FORK(); 1.3611 + 1.3612 + sp = sftk_SessionFromHandle(hSession); 1.3613 + if (sp == NULL) { 1.3614 + goto loser; 1.3615 + } 1.3616 + 1.3617 + slot = sftk_SlotFromSession(sp); 1.3618 + if (!slot) { 1.3619 + goto loser; 1.3620 + } 1.3621 + 1.3622 + handle = sftk_getKeyDB(slot); 1.3623 + if (handle == NULL) { 1.3624 + sftk_FreeSession(sp); 1.3625 + return CKR_PIN_LEN_RANGE; /* XXX FIXME wrong return value */ 1.3626 + } 1.3627 + 1.3628 + if (slot->needLogin && sp->info.state != CKS_RW_USER_FUNCTIONS) { 1.3629 + crv = CKR_USER_NOT_LOGGED_IN; 1.3630 + goto loser; 1.3631 + } 1.3632 + 1.3633 + sftk_FreeSession(sp); 1.3634 + sp = NULL; 1.3635 + 1.3636 + /* make sure the pins aren't too long */ 1.3637 + if ((ulNewLen > SFTK_MAX_PIN) || (ulOldLen > SFTK_MAX_PIN)) { 1.3638 + crv = CKR_PIN_LEN_RANGE; 1.3639 + goto loser; 1.3640 + } 1.3641 + if (ulNewLen < (CK_ULONG)slot->minimumPinLen) { 1.3642 + crv = CKR_PIN_LEN_RANGE; 1.3643 + goto loser; 1.3644 + } 1.3645 + 1.3646 + 1.3647 + /* convert to null terminated string */ 1.3648 + PORT_Memcpy(newPinStr,pNewPin,ulNewLen); 1.3649 + newPinStr[ulNewLen] = 0; 1.3650 + PORT_Memcpy(oldPinStr,pOldPin,ulOldLen); 1.3651 + oldPinStr[ulOldLen] = 0; 1.3652 + 1.3653 + /* change the data base password */ 1.3654 + PR_Lock(slot->pwCheckLock); 1.3655 + rv = sftkdb_ChangePassword(handle, oldPinStr, newPinStr, &tokenRemoved); 1.3656 + if (tokenRemoved) { 1.3657 + sftk_CloseAllSessions(slot, PR_FALSE); 1.3658 + } 1.3659 + if ((rv != SECSuccess) && (slot->slotID == FIPS_SLOT_ID)) { 1.3660 + PR_Sleep(loginWaitTime); 1.3661 + } 1.3662 + PR_Unlock(slot->pwCheckLock); 1.3663 + 1.3664 + /* Now update our local copy of the pin */ 1.3665 + if (rv == SECSuccess) { 1.3666 + slot->needLogin = (PRBool)(ulNewLen != 0); 1.3667 + /* Reset login flags. */ 1.3668 + if (ulNewLen == 0) { 1.3669 + PRBool tokenRemoved = PR_FALSE; 1.3670 + PZ_Lock(slot->slotLock); 1.3671 + slot->isLoggedIn = PR_FALSE; 1.3672 + slot->ssoLoggedIn = PR_FALSE; 1.3673 + PZ_Unlock(slot->slotLock); 1.3674 + 1.3675 + rv = sftkdb_CheckPassword(handle, "", &tokenRemoved); 1.3676 + if (tokenRemoved) { 1.3677 + sftk_CloseAllSessions(slot, PR_FALSE); 1.3678 + } 1.3679 + } 1.3680 + sftk_update_all_states(slot); 1.3681 + sftk_freeDB(handle); 1.3682 + return CKR_OK; 1.3683 + } 1.3684 + crv = CKR_PIN_INCORRECT; 1.3685 +loser: 1.3686 + if (sp) { 1.3687 + sftk_FreeSession(sp); 1.3688 + } 1.3689 + if (handle) { 1.3690 + sftk_freeDB(handle); 1.3691 + } 1.3692 + return crv; 1.3693 +} 1.3694 + 1.3695 +/* NSC_OpenSession opens a session between an application and a token. */ 1.3696 +CK_RV NSC_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, 1.3697 + CK_VOID_PTR pApplication,CK_NOTIFY Notify,CK_SESSION_HANDLE_PTR phSession) 1.3698 +{ 1.3699 + SFTKSlot *slot; 1.3700 + CK_SESSION_HANDLE sessionID; 1.3701 + SFTKSession *session; 1.3702 + SFTKSession *sameID; 1.3703 + 1.3704 + CHECK_FORK(); 1.3705 + 1.3706 + slot = sftk_SlotFromID(slotID, PR_FALSE); 1.3707 + if (slot == NULL) return CKR_SLOT_ID_INVALID; 1.3708 + 1.3709 + /* new session (we only have serial sessions) */ 1.3710 + session = sftk_NewSession(slotID, Notify, pApplication, 1.3711 + flags | CKF_SERIAL_SESSION); 1.3712 + if (session == NULL) return CKR_HOST_MEMORY; 1.3713 + 1.3714 + if (slot->readOnly && (flags & CKF_RW_SESSION)) { 1.3715 + /* NETSCAPE_SLOT_ID is Read ONLY */ 1.3716 + session->info.flags &= ~CKF_RW_SESSION; 1.3717 + } 1.3718 + PZ_Lock(slot->slotLock); 1.3719 + ++slot->sessionCount; 1.3720 + PZ_Unlock(slot->slotLock); 1.3721 + if (session->info.flags & CKF_RW_SESSION) { 1.3722 + PR_ATOMIC_INCREMENT(&slot->rwSessionCount); 1.3723 + } 1.3724 + 1.3725 + do { 1.3726 + PZLock *lock; 1.3727 + do { 1.3728 + sessionID = (PR_ATOMIC_INCREMENT(&slot->sessionIDCount) & 0xffffff) 1.3729 + | (slot->index << 24); 1.3730 + } while (sessionID == CK_INVALID_HANDLE); 1.3731 + lock = SFTK_SESSION_LOCK(slot,sessionID); 1.3732 + PZ_Lock(lock); 1.3733 + sftkqueue_find(sameID, sessionID, slot->head, slot->sessHashSize); 1.3734 + if (sameID == NULL) { 1.3735 + session->handle = sessionID; 1.3736 + sftk_update_state(slot, session); 1.3737 + sftkqueue_add(session, sessionID, slot->head,slot->sessHashSize); 1.3738 + } else { 1.3739 + slot->sessionIDConflict++; /* for debugging */ 1.3740 + } 1.3741 + PZ_Unlock(lock); 1.3742 + } while (sameID != NULL); 1.3743 + 1.3744 + *phSession = sessionID; 1.3745 + return CKR_OK; 1.3746 +} 1.3747 + 1.3748 + 1.3749 +/* NSC_CloseSession closes a session between an application and a token. */ 1.3750 +CK_RV NSC_CloseSession(CK_SESSION_HANDLE hSession) 1.3751 +{ 1.3752 + SFTKSlot *slot; 1.3753 + SFTKSession *session; 1.3754 + PRBool sessionFound; 1.3755 + PZLock *lock; 1.3756 + 1.3757 + CHECK_FORK(); 1.3758 + 1.3759 + session = sftk_SessionFromHandle(hSession); 1.3760 + if (session == NULL) return CKR_SESSION_HANDLE_INVALID; 1.3761 + slot = sftk_SlotFromSession(session); 1.3762 + sessionFound = PR_FALSE; 1.3763 + 1.3764 + /* lock */ 1.3765 + lock = SFTK_SESSION_LOCK(slot,hSession); 1.3766 + PZ_Lock(lock); 1.3767 + if (sftkqueue_is_queued(session,hSession,slot->head,slot->sessHashSize)) { 1.3768 + sessionFound = PR_TRUE; 1.3769 + sftkqueue_delete(session,hSession,slot->head,slot->sessHashSize); 1.3770 + session->refCount--; /* can't go to zero while we hold the reference */ 1.3771 + PORT_Assert(session->refCount > 0); 1.3772 + } 1.3773 + PZ_Unlock(lock); 1.3774 + 1.3775 + if (sessionFound) { 1.3776 + SFTKDBHandle *handle; 1.3777 + handle = sftk_getKeyDB(slot); 1.3778 + PZ_Lock(slot->slotLock); 1.3779 + if (--slot->sessionCount == 0) { 1.3780 + slot->isLoggedIn = PR_FALSE; 1.3781 + if (slot->needLogin && handle) { 1.3782 + sftkdb_ClearPassword(handle); 1.3783 + } 1.3784 + } 1.3785 + PZ_Unlock(slot->slotLock); 1.3786 + if (handle) { 1.3787 + sftk_freeDB(handle); 1.3788 + } 1.3789 + if (session->info.flags & CKF_RW_SESSION) { 1.3790 + PR_ATOMIC_DECREMENT(&slot->rwSessionCount); 1.3791 + } 1.3792 + } 1.3793 + 1.3794 + sftk_FreeSession(session); 1.3795 + return CKR_OK; 1.3796 +} 1.3797 + 1.3798 + 1.3799 +/* NSC_CloseAllSessions closes all sessions with a token. */ 1.3800 +CK_RV NSC_CloseAllSessions (CK_SLOT_ID slotID) 1.3801 +{ 1.3802 + SFTKSlot *slot; 1.3803 + 1.3804 +#ifndef NO_FORK_CHECK 1.3805 + /* skip fork check if we are being called from C_Initialize or C_Finalize */ 1.3806 + if (!parentForkedAfterC_Initialize) { 1.3807 + CHECK_FORK(); 1.3808 + } 1.3809 +#endif 1.3810 + 1.3811 + slot = sftk_SlotFromID(slotID, PR_FALSE); 1.3812 + if (slot == NULL) return CKR_SLOT_ID_INVALID; 1.3813 + 1.3814 + return sftk_CloseAllSessions(slot, PR_TRUE); 1.3815 +} 1.3816 + 1.3817 + 1.3818 + 1.3819 +/* NSC_GetSessionInfo obtains information about the session. */ 1.3820 +CK_RV NSC_GetSessionInfo(CK_SESSION_HANDLE hSession, 1.3821 + CK_SESSION_INFO_PTR pInfo) 1.3822 +{ 1.3823 + SFTKSession *session; 1.3824 + 1.3825 + CHECK_FORK(); 1.3826 + 1.3827 + session = sftk_SessionFromHandle(hSession); 1.3828 + if (session == NULL) return CKR_SESSION_HANDLE_INVALID; 1.3829 + 1.3830 + PORT_Memcpy(pInfo,&session->info,sizeof(CK_SESSION_INFO)); 1.3831 + sftk_FreeSession(session); 1.3832 + return CKR_OK; 1.3833 +} 1.3834 + 1.3835 +/* NSC_Login logs a user into a token. */ 1.3836 +CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, 1.3837 + CK_CHAR_PTR pPin, CK_ULONG ulPinLen) 1.3838 +{ 1.3839 + SFTKSlot *slot; 1.3840 + SFTKSession *session; 1.3841 + SFTKDBHandle *handle; 1.3842 + CK_FLAGS sessionFlags; 1.3843 + SECStatus rv; 1.3844 + CK_RV crv; 1.3845 + char pinStr[SFTK_MAX_PIN+1]; 1.3846 + PRBool tokenRemoved = PR_FALSE; 1.3847 + 1.3848 + CHECK_FORK(); 1.3849 + 1.3850 + /* get the slot */ 1.3851 + slot = sftk_SlotFromSessionHandle(hSession); 1.3852 + if (slot == NULL) { 1.3853 + return CKR_SESSION_HANDLE_INVALID; 1.3854 + } 1.3855 + 1.3856 + /* make sure the session is valid */ 1.3857 + session = sftk_SessionFromHandle(hSession); 1.3858 + if (session == NULL) { 1.3859 + return CKR_SESSION_HANDLE_INVALID; 1.3860 + } 1.3861 + sessionFlags = session->info.flags; 1.3862 + sftk_FreeSession(session); 1.3863 + session = NULL; 1.3864 + 1.3865 + /* can't log into the Netscape Slot */ 1.3866 + if (slot->slotID == NETSCAPE_SLOT_ID) { 1.3867 + return CKR_USER_TYPE_INVALID; 1.3868 + } 1.3869 + 1.3870 + if (slot->isLoggedIn) return CKR_USER_ALREADY_LOGGED_IN; 1.3871 + if (!slot->needLogin) { 1.3872 + return ulPinLen ? CKR_PIN_INCORRECT : CKR_OK; 1.3873 + } 1.3874 + slot->ssoLoggedIn = PR_FALSE; 1.3875 + 1.3876 + if (ulPinLen > SFTK_MAX_PIN) return CKR_PIN_LEN_RANGE; 1.3877 + 1.3878 + /* convert to null terminated string */ 1.3879 + PORT_Memcpy(pinStr,pPin,ulPinLen); 1.3880 + pinStr[ulPinLen] = 0; 1.3881 + 1.3882 + handle = sftk_getKeyDB(slot); 1.3883 + if (handle == NULL) { 1.3884 + return CKR_USER_TYPE_INVALID; 1.3885 + } 1.3886 + 1.3887 + /* 1.3888 + * Deal with bootstrap. We allow the SSO to login in with a NULL 1.3889 + * password if and only if we haven't initialized the KEY DB yet. 1.3890 + * We only allow this on a RW session. 1.3891 + */ 1.3892 + rv = sftkdb_HasPasswordSet(handle); 1.3893 + if (rv == SECFailure) { 1.3894 + /* allow SSO's to log in only if there is not password on the 1.3895 + * key database */ 1.3896 + if (((userType == CKU_SO) && (sessionFlags & CKF_RW_SESSION)) 1.3897 + /* fips always needs to authenticate, even if there isn't a db */ 1.3898 + || (slot->slotID == FIPS_SLOT_ID)) { 1.3899 + /* should this be a fixed password? */ 1.3900 + if (ulPinLen == 0) { 1.3901 + sftkdb_ClearPassword(handle); 1.3902 + PZ_Lock(slot->slotLock); 1.3903 + slot->isLoggedIn = PR_TRUE; 1.3904 + slot->ssoLoggedIn = (PRBool)(userType == CKU_SO); 1.3905 + PZ_Unlock(slot->slotLock); 1.3906 + sftk_update_all_states(slot); 1.3907 + crv = CKR_OK; 1.3908 + goto done; 1.3909 + } 1.3910 + crv = CKR_PIN_INCORRECT; 1.3911 + goto done; 1.3912 + } 1.3913 + crv = CKR_USER_TYPE_INVALID; 1.3914 + goto done; 1.3915 + } 1.3916 + 1.3917 + /* don't allow the SSO to log in if the user is already initialized */ 1.3918 + if (userType != CKU_USER) { 1.3919 + crv = CKR_USER_TYPE_INVALID; 1.3920 + goto done; 1.3921 + } 1.3922 + 1.3923 + 1.3924 + /* build the hashed pins which we pass around */ 1.3925 + PR_Lock(slot->pwCheckLock); 1.3926 + rv = sftkdb_CheckPassword(handle,pinStr, &tokenRemoved); 1.3927 + if (tokenRemoved) { 1.3928 + sftk_CloseAllSessions(slot, PR_FALSE); 1.3929 + } 1.3930 + if ((rv != SECSuccess) && (slot->slotID == FIPS_SLOT_ID)) { 1.3931 + PR_Sleep(loginWaitTime); 1.3932 + } 1.3933 + PR_Unlock(slot->pwCheckLock); 1.3934 + if (rv == SECSuccess) { 1.3935 + PZ_Lock(slot->slotLock); 1.3936 + /* make sure the login state matches the underlying 1.3937 + * database state */ 1.3938 + slot->isLoggedIn = sftkdb_PWCached(handle) == SECSuccess ? 1.3939 + PR_TRUE : PR_FALSE; 1.3940 + PZ_Unlock(slot->slotLock); 1.3941 + 1.3942 + sftk_freeDB(handle); 1.3943 + handle = NULL; 1.3944 + 1.3945 + /* update all sessions */ 1.3946 + sftk_update_all_states(slot); 1.3947 + return CKR_OK; 1.3948 + } 1.3949 + 1.3950 + crv = CKR_PIN_INCORRECT; 1.3951 +done: 1.3952 + if (handle) { 1.3953 + sftk_freeDB(handle); 1.3954 + } 1.3955 + return crv; 1.3956 +} 1.3957 + 1.3958 +/* NSC_Logout logs a user out from a token. */ 1.3959 +CK_RV NSC_Logout(CK_SESSION_HANDLE hSession) 1.3960 +{ 1.3961 + SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); 1.3962 + SFTKSession *session; 1.3963 + SFTKDBHandle *handle; 1.3964 + 1.3965 + CHECK_FORK(); 1.3966 + 1.3967 + if (slot == NULL) { 1.3968 + return CKR_SESSION_HANDLE_INVALID; 1.3969 + } 1.3970 + session = sftk_SessionFromHandle(hSession); 1.3971 + if (session == NULL) return CKR_SESSION_HANDLE_INVALID; 1.3972 + sftk_FreeSession(session); 1.3973 + session = NULL; 1.3974 + 1.3975 + if (!slot->isLoggedIn) return CKR_USER_NOT_LOGGED_IN; 1.3976 + 1.3977 + handle = sftk_getKeyDB(slot); 1.3978 + PZ_Lock(slot->slotLock); 1.3979 + slot->isLoggedIn = PR_FALSE; 1.3980 + slot->ssoLoggedIn = PR_FALSE; 1.3981 + if (slot->needLogin && handle) { 1.3982 + sftkdb_ClearPassword(handle); 1.3983 + } 1.3984 + PZ_Unlock(slot->slotLock); 1.3985 + if (handle) { 1.3986 + sftk_freeDB(handle); 1.3987 + } 1.3988 + 1.3989 + sftk_update_all_states(slot); 1.3990 + return CKR_OK; 1.3991 +} 1.3992 + 1.3993 +/* 1.3994 + * Create or remove a new slot on the fly. 1.3995 + * When creating a slot, "slot" is the slot that the request came from. The 1.3996 + * resulting slot will live in the same module as "slot". 1.3997 + * When removing a slot, "slot" is the slot to be removed. 1.3998 + * "object" is the creation object that specifies the module spec for the slot 1.3999 + * to add or remove. 1.4000 + */ 1.4001 +static CK_RV sftk_CreateNewSlot(SFTKSlot *slot, CK_OBJECT_CLASS class, 1.4002 + SFTKObject *object) 1.4003 +{ 1.4004 + PRBool isValidUserSlot = PR_FALSE; 1.4005 + PRBool isValidFIPSUserSlot = PR_FALSE; 1.4006 + PRBool isValidSlot = PR_FALSE; 1.4007 + PRBool isFIPS = PR_FALSE; 1.4008 + unsigned long moduleIndex; 1.4009 + SFTKAttribute *attribute; 1.4010 + sftk_parameters paramStrings; 1.4011 + char *paramString; 1.4012 + CK_SLOT_ID slotID = 0; 1.4013 + SFTKSlot *newSlot = NULL; 1.4014 + CK_RV crv = CKR_OK; 1.4015 + 1.4016 + if (class != CKO_NETSCAPE_DELSLOT && class != CKO_NETSCAPE_NEWSLOT) { 1.4017 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.4018 + } 1.4019 + if (class == CKO_NETSCAPE_NEWSLOT && slot->slotID == FIPS_SLOT_ID) { 1.4020 + isFIPS = PR_TRUE; 1.4021 + } 1.4022 + attribute = sftk_FindAttribute(object, CKA_NETSCAPE_MODULE_SPEC); 1.4023 + if (attribute == NULL) { 1.4024 + return CKR_TEMPLATE_INCOMPLETE; 1.4025 + } 1.4026 + paramString = (char *)attribute->attrib.pValue; 1.4027 + crv = sftk_parseParameters(paramString, ¶mStrings, isFIPS); 1.4028 + if (crv != CKR_OK) { 1.4029 + goto loser; 1.4030 + } 1.4031 + 1.4032 + /* enforce only one at a time */ 1.4033 + if (paramStrings.token_count != 1) { 1.4034 + crv = CKR_ATTRIBUTE_VALUE_INVALID; 1.4035 + goto loser; 1.4036 + } 1.4037 + 1.4038 + slotID = paramStrings.tokens[0].slotID; 1.4039 + 1.4040 + /* stay within the valid ID space */ 1.4041 + isValidUserSlot = (slotID >= SFTK_MIN_USER_SLOT_ID && 1.4042 + slotID <= SFTK_MAX_USER_SLOT_ID); 1.4043 + isValidFIPSUserSlot = (slotID >= SFTK_MIN_FIPS_USER_SLOT_ID && 1.4044 + slotID <= SFTK_MAX_FIPS_USER_SLOT_ID); 1.4045 + 1.4046 + if (class == CKO_NETSCAPE_DELSLOT) { 1.4047 + if (slot->slotID == slotID) { 1.4048 + isValidSlot = isValidUserSlot || isValidFIPSUserSlot; 1.4049 + } 1.4050 + } else { 1.4051 + /* only the crypto or FIPS slots can create new slot objects */ 1.4052 + if (slot->slotID == NETSCAPE_SLOT_ID) { 1.4053 + isValidSlot = isValidUserSlot; 1.4054 + moduleIndex = NSC_NON_FIPS_MODULE; 1.4055 + } else if (slot->slotID == FIPS_SLOT_ID) { 1.4056 + isValidSlot = isValidFIPSUserSlot; 1.4057 + moduleIndex = NSC_FIPS_MODULE; 1.4058 + } 1.4059 + } 1.4060 + 1.4061 + if (!isValidSlot) { 1.4062 + crv = CKR_ATTRIBUTE_VALUE_INVALID; 1.4063 + goto loser; 1.4064 + } 1.4065 + 1.4066 + /* unload any existing slot at this id */ 1.4067 + newSlot = sftk_SlotFromID(slotID, PR_TRUE); 1.4068 + if (newSlot && newSlot->present) { 1.4069 + crv = SFTK_ShutdownSlot(newSlot); 1.4070 + if (crv != CKR_OK) { 1.4071 + goto loser; 1.4072 + } 1.4073 + } 1.4074 + 1.4075 + /* if we were just planning on deleting the slot, then do so now */ 1.4076 + if (class == CKO_NETSCAPE_DELSLOT) { 1.4077 + /* sort of a unconventional use of this error code, be we are 1.4078 + * overusing CKR_ATTRIBUTE_VALUE_INVALID, and it does apply */ 1.4079 + crv = newSlot ? CKR_OK : CKR_SLOT_ID_INVALID; 1.4080 + goto loser; /* really exit */ 1.4081 + } 1.4082 + 1.4083 + if (newSlot) { 1.4084 + crv = SFTK_SlotReInit(newSlot, paramStrings.configdir, 1.4085 + paramStrings.updatedir, paramStrings.updateID, 1.4086 + ¶mStrings.tokens[0], moduleIndex); 1.4087 + } else { 1.4088 + crv = SFTK_SlotInit(paramStrings.configdir, 1.4089 + paramStrings.updatedir, paramStrings.updateID, 1.4090 + ¶mStrings.tokens[0], moduleIndex); 1.4091 + } 1.4092 + 1.4093 +loser: 1.4094 + sftk_freeParams(¶mStrings); 1.4095 + sftk_FreeAttribute(attribute); 1.4096 + 1.4097 + return crv; 1.4098 +} 1.4099 + 1.4100 + 1.4101 +/* NSC_CreateObject creates a new object. */ 1.4102 +CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession, 1.4103 + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, 1.4104 + CK_OBJECT_HANDLE_PTR phObject) 1.4105 +{ 1.4106 + SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); 1.4107 + SFTKSession *session; 1.4108 + SFTKObject *object; 1.4109 + /* make sure class isn't randomly CKO_NETSCAPE_NEWSLOT or 1.4110 + * CKO_NETSCPE_DELSLOT. */ 1.4111 + CK_OBJECT_CLASS class = CKO_VENDOR_DEFINED; 1.4112 + CK_RV crv; 1.4113 + int i; 1.4114 + 1.4115 + CHECK_FORK(); 1.4116 + 1.4117 + *phObject = CK_INVALID_HANDLE; 1.4118 + 1.4119 + if (slot == NULL) { 1.4120 + return CKR_SESSION_HANDLE_INVALID; 1.4121 + } 1.4122 + /* 1.4123 + * now lets create an object to hang the attributes off of 1.4124 + */ 1.4125 + object = sftk_NewObject(slot); /* fill in the handle later */ 1.4126 + if (object == NULL) { 1.4127 + return CKR_HOST_MEMORY; 1.4128 + } 1.4129 + 1.4130 + /* 1.4131 + * load the template values into the object 1.4132 + */ 1.4133 + for (i=0; i < (int) ulCount; i++) { 1.4134 + crv = sftk_AddAttributeType(object,sftk_attr_expand(&pTemplate[i])); 1.4135 + if (crv != CKR_OK) { 1.4136 + sftk_FreeObject(object); 1.4137 + return crv; 1.4138 + } 1.4139 + if ((pTemplate[i].type == CKA_CLASS) && pTemplate[i].pValue) { 1.4140 + class = *(CK_OBJECT_CLASS *)pTemplate[i].pValue; 1.4141 + } 1.4142 + } 1.4143 + 1.4144 + /* get the session */ 1.4145 + session = sftk_SessionFromHandle(hSession); 1.4146 + if (session == NULL) { 1.4147 + sftk_FreeObject(object); 1.4148 + return CKR_SESSION_HANDLE_INVALID; 1.4149 + } 1.4150 + 1.4151 + /* 1.4152 + * handle pseudo objects (CKO_NEWSLOT) 1.4153 + */ 1.4154 + if ((class == CKO_NETSCAPE_NEWSLOT) || (class == CKO_NETSCAPE_DELSLOT)) { 1.4155 + crv = sftk_CreateNewSlot(slot, class, object); 1.4156 + goto done; 1.4157 + } 1.4158 + 1.4159 + /* 1.4160 + * handle the base object stuff 1.4161 + */ 1.4162 + crv = sftk_handleObject(object,session); 1.4163 + *phObject = object->handle; 1.4164 +done: 1.4165 + sftk_FreeSession(session); 1.4166 + sftk_FreeObject(object); 1.4167 + 1.4168 + return crv; 1.4169 +} 1.4170 + 1.4171 + 1.4172 + 1.4173 +/* NSC_CopyObject copies an object, creating a new object for the copy. */ 1.4174 +CK_RV NSC_CopyObject(CK_SESSION_HANDLE hSession, 1.4175 + CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, 1.4176 + CK_OBJECT_HANDLE_PTR phNewObject) 1.4177 +{ 1.4178 + SFTKObject *destObject,*srcObject; 1.4179 + SFTKSession *session; 1.4180 + CK_RV crv = CKR_OK; 1.4181 + SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); 1.4182 + int i; 1.4183 + 1.4184 + CHECK_FORK(); 1.4185 + 1.4186 + if (slot == NULL) { 1.4187 + return CKR_SESSION_HANDLE_INVALID; 1.4188 + } 1.4189 + /* Get srcObject so we can find the class */ 1.4190 + session = sftk_SessionFromHandle(hSession); 1.4191 + if (session == NULL) { 1.4192 + return CKR_SESSION_HANDLE_INVALID; 1.4193 + } 1.4194 + srcObject = sftk_ObjectFromHandle(hObject,session); 1.4195 + if (srcObject == NULL) { 1.4196 + sftk_FreeSession(session); 1.4197 + return CKR_OBJECT_HANDLE_INVALID; 1.4198 + } 1.4199 + /* 1.4200 + * create an object to hang the attributes off of 1.4201 + */ 1.4202 + destObject = sftk_NewObject(slot); /* fill in the handle later */ 1.4203 + if (destObject == NULL) { 1.4204 + sftk_FreeSession(session); 1.4205 + sftk_FreeObject(srcObject); 1.4206 + return CKR_HOST_MEMORY; 1.4207 + } 1.4208 + 1.4209 + /* 1.4210 + * load the template values into the object 1.4211 + */ 1.4212 + for (i=0; i < (int) ulCount; i++) { 1.4213 + if (sftk_modifyType(pTemplate[i].type,srcObject->objclass) == SFTK_NEVER) { 1.4214 + crv = CKR_ATTRIBUTE_READ_ONLY; 1.4215 + break; 1.4216 + } 1.4217 + crv = sftk_AddAttributeType(destObject,sftk_attr_expand(&pTemplate[i])); 1.4218 + if (crv != CKR_OK) { break; } 1.4219 + } 1.4220 + if (crv != CKR_OK) { 1.4221 + sftk_FreeSession(session); 1.4222 + sftk_FreeObject(srcObject); 1.4223 + sftk_FreeObject(destObject); 1.4224 + return crv; 1.4225 + } 1.4226 + 1.4227 + /* sensitive can only be changed to CK_TRUE */ 1.4228 + if (sftk_hasAttribute(destObject,CKA_SENSITIVE)) { 1.4229 + if (!sftk_isTrue(destObject,CKA_SENSITIVE)) { 1.4230 + sftk_FreeSession(session); 1.4231 + sftk_FreeObject(srcObject); 1.4232 + sftk_FreeObject(destObject); 1.4233 + return CKR_ATTRIBUTE_READ_ONLY; 1.4234 + } 1.4235 + } 1.4236 + 1.4237 + /* 1.4238 + * now copy the old attributes from the new attributes 1.4239 + */ 1.4240 + /* don't create a token object if we aren't in a rw session */ 1.4241 + /* we need to hold the lock to copy a consistant version of 1.4242 + * the object. */ 1.4243 + crv = sftk_CopyObject(destObject,srcObject); 1.4244 + 1.4245 + destObject->objclass = srcObject->objclass; 1.4246 + sftk_FreeObject(srcObject); 1.4247 + if (crv != CKR_OK) { 1.4248 + sftk_FreeObject(destObject); 1.4249 + sftk_FreeSession(session); 1.4250 + return crv; 1.4251 + } 1.4252 + 1.4253 + crv = sftk_handleObject(destObject,session); 1.4254 + *phNewObject = destObject->handle; 1.4255 + sftk_FreeSession(session); 1.4256 + sftk_FreeObject(destObject); 1.4257 + 1.4258 + return crv; 1.4259 +} 1.4260 + 1.4261 + 1.4262 +/* NSC_GetObjectSize gets the size of an object in bytes. */ 1.4263 +CK_RV NSC_GetObjectSize(CK_SESSION_HANDLE hSession, 1.4264 + CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize) 1.4265 +{ 1.4266 + CHECK_FORK(); 1.4267 + 1.4268 + *pulSize = 0; 1.4269 + return CKR_OK; 1.4270 +} 1.4271 + 1.4272 + 1.4273 +/* NSC_GetAttributeValue obtains the value of one or more object attributes. */ 1.4274 +CK_RV NSC_GetAttributeValue(CK_SESSION_HANDLE hSession, 1.4275 + CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount) 1.4276 +{ 1.4277 + SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); 1.4278 + SFTKSession *session; 1.4279 + SFTKObject *object; 1.4280 + SFTKAttribute *attribute; 1.4281 + PRBool sensitive; 1.4282 + CK_RV crv; 1.4283 + int i; 1.4284 + 1.4285 + CHECK_FORK(); 1.4286 + 1.4287 + if (slot == NULL) { 1.4288 + return CKR_SESSION_HANDLE_INVALID; 1.4289 + } 1.4290 + /* 1.4291 + * make sure we're allowed 1.4292 + */ 1.4293 + session = sftk_SessionFromHandle(hSession); 1.4294 + if (session == NULL) { 1.4295 + return CKR_SESSION_HANDLE_INVALID; 1.4296 + } 1.4297 + 1.4298 + /* short circuit everything for token objects */ 1.4299 + if (sftk_isToken(hObject)) { 1.4300 + SFTKSlot *slot = sftk_SlotFromSession(session); 1.4301 + SFTKDBHandle *dbHandle = sftk_getDBForTokenObject(slot, hObject); 1.4302 + SFTKDBHandle *keydb = NULL; 1.4303 + 1.4304 + if (dbHandle == NULL) { 1.4305 + sftk_FreeSession(session); 1.4306 + return CKR_OBJECT_HANDLE_INVALID; 1.4307 + } 1.4308 + 1.4309 + crv = sftkdb_GetAttributeValue(dbHandle, hObject, pTemplate, ulCount); 1.4310 + 1.4311 + /* make sure we don't export any sensitive information */ 1.4312 + keydb = sftk_getKeyDB(slot); 1.4313 + if (dbHandle == keydb) { 1.4314 + for (i=0; i < (int) ulCount; i++) { 1.4315 + if (sftk_isSensitive(pTemplate[i].type,CKO_PRIVATE_KEY)) { 1.4316 + crv = CKR_ATTRIBUTE_SENSITIVE; 1.4317 + if (pTemplate[i].pValue && (pTemplate[i].ulValueLen!= -1)){ 1.4318 + PORT_Memset(pTemplate[i].pValue, 0, 1.4319 + pTemplate[i].ulValueLen); 1.4320 + } 1.4321 + pTemplate[i].ulValueLen = -1; 1.4322 + } 1.4323 + } 1.4324 + } 1.4325 + 1.4326 + sftk_FreeSession(session); 1.4327 + sftk_freeDB(dbHandle); 1.4328 + if (keydb) { 1.4329 + sftk_freeDB(keydb); 1.4330 + } 1.4331 + return crv; 1.4332 + } 1.4333 + 1.4334 + /* handle the session object */ 1.4335 + object = sftk_ObjectFromHandle(hObject,session); 1.4336 + sftk_FreeSession(session); 1.4337 + if (object == NULL) { 1.4338 + return CKR_OBJECT_HANDLE_INVALID; 1.4339 + } 1.4340 + 1.4341 + /* don't read a private object if we aren't logged in */ 1.4342 + if ((!slot->isLoggedIn) && (slot->needLogin) && 1.4343 + (sftk_isTrue(object,CKA_PRIVATE))) { 1.4344 + sftk_FreeObject(object); 1.4345 + return CKR_USER_NOT_LOGGED_IN; 1.4346 + } 1.4347 + 1.4348 + crv = CKR_OK; 1.4349 + sensitive = sftk_isTrue(object,CKA_SENSITIVE); 1.4350 + for (i=0; i < (int) ulCount; i++) { 1.4351 + /* Make sure that this attribute is retrievable */ 1.4352 + if (sensitive && sftk_isSensitive(pTemplate[i].type,object->objclass)) { 1.4353 + crv = CKR_ATTRIBUTE_SENSITIVE; 1.4354 + pTemplate[i].ulValueLen = -1; 1.4355 + continue; 1.4356 + } 1.4357 + attribute = sftk_FindAttribute(object,pTemplate[i].type); 1.4358 + if (attribute == NULL) { 1.4359 + crv = CKR_ATTRIBUTE_TYPE_INVALID; 1.4360 + pTemplate[i].ulValueLen = -1; 1.4361 + continue; 1.4362 + } 1.4363 + if (pTemplate[i].pValue != NULL) { 1.4364 + PORT_Memcpy(pTemplate[i].pValue,attribute->attrib.pValue, 1.4365 + attribute->attrib.ulValueLen); 1.4366 + } 1.4367 + pTemplate[i].ulValueLen = attribute->attrib.ulValueLen; 1.4368 + sftk_FreeAttribute(attribute); 1.4369 + } 1.4370 + 1.4371 + sftk_FreeObject(object); 1.4372 + return crv; 1.4373 +} 1.4374 + 1.4375 +/* NSC_SetAttributeValue modifies the value of one or more object attributes */ 1.4376 +CK_RV NSC_SetAttributeValue (CK_SESSION_HANDLE hSession, 1.4377 + CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount) 1.4378 +{ 1.4379 + SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); 1.4380 + SFTKSession *session; 1.4381 + SFTKAttribute *attribute; 1.4382 + SFTKObject *object; 1.4383 + PRBool isToken; 1.4384 + CK_RV crv = CKR_OK; 1.4385 + CK_BBOOL legal; 1.4386 + int i; 1.4387 + 1.4388 + CHECK_FORK(); 1.4389 + 1.4390 + if (slot == NULL) { 1.4391 + return CKR_SESSION_HANDLE_INVALID; 1.4392 + } 1.4393 + /* 1.4394 + * make sure we're allowed 1.4395 + */ 1.4396 + session = sftk_SessionFromHandle(hSession); 1.4397 + if (session == NULL) { 1.4398 + return CKR_SESSION_HANDLE_INVALID; 1.4399 + } 1.4400 + 1.4401 + object = sftk_ObjectFromHandle(hObject,session); 1.4402 + if (object == NULL) { 1.4403 + sftk_FreeSession(session); 1.4404 + return CKR_OBJECT_HANDLE_INVALID; 1.4405 + } 1.4406 + 1.4407 + /* don't modify a private object if we aren't logged in */ 1.4408 + if ((!slot->isLoggedIn) && (slot->needLogin) && 1.4409 + (sftk_isTrue(object,CKA_PRIVATE))) { 1.4410 + sftk_FreeSession(session); 1.4411 + sftk_FreeObject(object); 1.4412 + return CKR_USER_NOT_LOGGED_IN; 1.4413 + } 1.4414 + 1.4415 + /* don't modify a token object if we aren't in a rw session */ 1.4416 + isToken = sftk_isTrue(object,CKA_TOKEN); 1.4417 + if (((session->info.flags & CKF_RW_SESSION) == 0) && isToken) { 1.4418 + sftk_FreeSession(session); 1.4419 + sftk_FreeObject(object); 1.4420 + return CKR_SESSION_READ_ONLY; 1.4421 + } 1.4422 + sftk_FreeSession(session); 1.4423 + 1.4424 + /* only change modifiable objects */ 1.4425 + if (!sftk_isTrue(object,CKA_MODIFIABLE)) { 1.4426 + sftk_FreeObject(object); 1.4427 + return CKR_ATTRIBUTE_READ_ONLY; 1.4428 + } 1.4429 + 1.4430 + for (i=0; i < (int) ulCount; i++) { 1.4431 + /* Make sure that this attribute is changeable */ 1.4432 + switch (sftk_modifyType(pTemplate[i].type,object->objclass)) { 1.4433 + case SFTK_NEVER: 1.4434 + case SFTK_ONCOPY: 1.4435 + default: 1.4436 + crv = CKR_ATTRIBUTE_READ_ONLY; 1.4437 + break; 1.4438 + 1.4439 + case SFTK_SENSITIVE: 1.4440 + legal = (pTemplate[i].type == CKA_EXTRACTABLE) ? CK_FALSE : CK_TRUE; 1.4441 + if ((*(CK_BBOOL *)pTemplate[i].pValue) != legal) { 1.4442 + crv = CKR_ATTRIBUTE_READ_ONLY; 1.4443 + } 1.4444 + break; 1.4445 + case SFTK_ALWAYS: 1.4446 + break; 1.4447 + } 1.4448 + if (crv != CKR_OK) break; 1.4449 + 1.4450 + /* find the old attribute */ 1.4451 + attribute = sftk_FindAttribute(object,pTemplate[i].type); 1.4452 + if (attribute == NULL) { 1.4453 + crv =CKR_ATTRIBUTE_TYPE_INVALID; 1.4454 + break; 1.4455 + } 1.4456 + sftk_FreeAttribute(attribute); 1.4457 + crv = sftk_forceAttribute(object,sftk_attr_expand(&pTemplate[i])); 1.4458 + if (crv != CKR_OK) break; 1.4459 + 1.4460 + } 1.4461 + 1.4462 + sftk_FreeObject(object); 1.4463 + return crv; 1.4464 +} 1.4465 + 1.4466 +static CK_RV 1.4467 +sftk_expandSearchList(SFTKSearchResults *search, int count) 1.4468 +{ 1.4469 + search->array_size += count; 1.4470 + search->handles = (CK_OBJECT_HANDLE *)PORT_Realloc(search->handles, 1.4471 + sizeof(CK_OBJECT_HANDLE)*search->array_size); 1.4472 + return search->handles ? CKR_OK : CKR_HOST_MEMORY; 1.4473 +} 1.4474 + 1.4475 + 1.4476 + 1.4477 +static CK_RV 1.4478 +sftk_searchDatabase(SFTKDBHandle *handle, SFTKSearchResults *search, 1.4479 + const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) 1.4480 +{ 1.4481 + CK_RV crv; 1.4482 + int objectListSize = search->array_size-search->size; 1.4483 + CK_OBJECT_HANDLE *array = &search->handles[search->size]; 1.4484 + SDBFind *find; 1.4485 + CK_ULONG count; 1.4486 + 1.4487 + crv = sftkdb_FindObjectsInit(handle, pTemplate, ulCount, &find); 1.4488 + if (crv != CKR_OK) 1.4489 + return crv; 1.4490 + do { 1.4491 + crv = sftkdb_FindObjects(handle, find, array, objectListSize, &count); 1.4492 + if ((crv != CKR_OK) || (count == 0)) 1.4493 + break; 1.4494 + search->size += count; 1.4495 + objectListSize -= count; 1.4496 + if (objectListSize > 0) 1.4497 + break; 1.4498 + crv = sftk_expandSearchList(search,NSC_SEARCH_BLOCK_SIZE); 1.4499 + objectListSize = NSC_SEARCH_BLOCK_SIZE; 1.4500 + array = &search->handles[search->size]; 1.4501 + } while (crv == CKR_OK); 1.4502 + sftkdb_FindObjectsFinal(handle, find); 1.4503 + 1.4504 + return crv; 1.4505 +} 1.4506 + 1.4507 +/* softoken used to search the SMimeEntries automatically instead of 1.4508 + * doing this in pk11wrap. This code should really be up in 1.4509 + * pk11wrap so that it will work with other tokens other than softoken. 1.4510 + */ 1.4511 +CK_RV 1.4512 +sftk_emailhack(SFTKSlot *slot, SFTKDBHandle *handle, 1.4513 + SFTKSearchResults *search, CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) 1.4514 +{ 1.4515 + PRBool isCert = PR_FALSE; 1.4516 + int emailIndex = -1; 1.4517 + int i; 1.4518 + SFTKSearchResults smime_search; 1.4519 + CK_ATTRIBUTE smime_template[2]; 1.4520 + CK_OBJECT_CLASS smime_class = CKO_NETSCAPE_SMIME; 1.4521 + SFTKAttribute *attribute = NULL; 1.4522 + SFTKObject *object = NULL; 1.4523 + CK_RV crv = CKR_OK; 1.4524 + 1.4525 + 1.4526 + smime_search.handles = NULL; /* paranoia, some one is bound to add a goto 1.4527 + * loser before this gets initialized */ 1.4528 + 1.4529 + /* see if we are looking for email certs */ 1.4530 + for (i=0; i < ulCount; i++) { 1.4531 + if (pTemplate[i].type == CKA_CLASS) { 1.4532 + if ((pTemplate[i].ulValueLen != sizeof(CK_OBJECT_CLASS) || 1.4533 + (*(CK_OBJECT_CLASS *)pTemplate[i].pValue) != CKO_CERTIFICATE)) { 1.4534 + /* not a cert, skip out */ 1.4535 + break; 1.4536 + } 1.4537 + isCert = PR_TRUE; 1.4538 + } else if (pTemplate[i].type == CKA_NETSCAPE_EMAIL) { 1.4539 + emailIndex = i; 1.4540 + 1.4541 + } 1.4542 + if (isCert && (emailIndex != -1)) break; 1.4543 + } 1.4544 + 1.4545 + if (!isCert || (emailIndex == -1)) { 1.4546 + return CKR_OK; 1.4547 + } 1.4548 + 1.4549 + /* we are doing a cert and email search, find the SMimeEntry */ 1.4550 + smime_template[0].type = CKA_CLASS; 1.4551 + smime_template[0].pValue = &smime_class; 1.4552 + smime_template[0].ulValueLen = sizeof(smime_class); 1.4553 + smime_template[1] = pTemplate[emailIndex]; 1.4554 + 1.4555 + smime_search.handles = (CK_OBJECT_HANDLE *) 1.4556 + PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * NSC_SEARCH_BLOCK_SIZE); 1.4557 + if (smime_search.handles == NULL) { 1.4558 + crv = CKR_HOST_MEMORY; 1.4559 + goto loser; 1.4560 + } 1.4561 + smime_search.index = 0; 1.4562 + smime_search.size = 0; 1.4563 + smime_search.array_size = NSC_SEARCH_BLOCK_SIZE; 1.4564 + 1.4565 + crv = sftk_searchDatabase(handle, &smime_search, smime_template, 2); 1.4566 + if (crv != CKR_OK || smime_search.size == 0) { 1.4567 + goto loser; 1.4568 + } 1.4569 + 1.4570 + /* get the SMime subject */ 1.4571 + object = sftk_NewTokenObject(slot, NULL, smime_search.handles[0]); 1.4572 + if (object == NULL) { 1.4573 + crv = CKR_HOST_MEMORY; /* is there any other reason for this failure? */ 1.4574 + goto loser; 1.4575 + } 1.4576 + attribute = sftk_FindAttribute(object,CKA_SUBJECT); 1.4577 + if (attribute == NULL) { 1.4578 + crv = CKR_ATTRIBUTE_TYPE_INVALID; 1.4579 + goto loser; 1.4580 + } 1.4581 + 1.4582 + /* now find the certs with that subject */ 1.4583 + pTemplate[emailIndex] = attribute->attrib; 1.4584 + /* now add the appropriate certs to the search list */ 1.4585 + crv = sftk_searchDatabase(handle, search, pTemplate, ulCount); 1.4586 + pTemplate[emailIndex] = smime_template[1]; /* restore the user's template*/ 1.4587 + 1.4588 +loser: 1.4589 + if (attribute) { 1.4590 + sftk_FreeAttribute(attribute); 1.4591 + } 1.4592 + if (object) { 1.4593 + sftk_FreeObject(object); 1.4594 + } 1.4595 + if (smime_search.handles) { 1.4596 + PORT_Free(smime_search.handles); 1.4597 + } 1.4598 + 1.4599 + return crv; 1.4600 +} 1.4601 + 1.4602 +static void 1.4603 +sftk_pruneSearch(CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount, 1.4604 + PRBool *searchCertDB, PRBool *searchKeyDB) { 1.4605 + CK_ULONG i; 1.4606 + 1.4607 + *searchCertDB = PR_TRUE; 1.4608 + *searchKeyDB = PR_TRUE; 1.4609 + for (i = 0; i < ulCount; i++) { 1.4610 + if (pTemplate[i].type == CKA_CLASS && pTemplate[i].pValue != NULL) { 1.4611 + CK_OBJECT_CLASS class = *((CK_OBJECT_CLASS*)pTemplate[i].pValue); 1.4612 + if (class == CKO_PRIVATE_KEY || class == CKO_SECRET_KEY) { 1.4613 + *searchCertDB = PR_FALSE; 1.4614 + } else { 1.4615 + *searchKeyDB = PR_FALSE; 1.4616 + } 1.4617 + break; 1.4618 + } 1.4619 + } 1.4620 +} 1.4621 + 1.4622 +static CK_RV 1.4623 +sftk_searchTokenList(SFTKSlot *slot, SFTKSearchResults *search, 1.4624 + CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount, 1.4625 + PRBool *tokenOnly, PRBool isLoggedIn) 1.4626 +{ 1.4627 + CK_RV crv = CKR_OK; 1.4628 + CK_RV crv2; 1.4629 + PRBool searchCertDB; 1.4630 + PRBool searchKeyDB; 1.4631 + 1.4632 + sftk_pruneSearch(pTemplate, ulCount, &searchCertDB, &searchKeyDB); 1.4633 + 1.4634 + if (searchCertDB) { 1.4635 + SFTKDBHandle *certHandle = sftk_getCertDB(slot); 1.4636 + crv = sftk_searchDatabase(certHandle, search, pTemplate, ulCount); 1.4637 + crv2 = sftk_emailhack(slot, certHandle, search, pTemplate, ulCount); 1.4638 + if (crv == CKR_OK) crv = crv2; 1.4639 + sftk_freeDB(certHandle); 1.4640 + } 1.4641 + 1.4642 + if (crv == CKR_OK && isLoggedIn && searchKeyDB) { 1.4643 + SFTKDBHandle *keyHandle = sftk_getKeyDB(slot); 1.4644 + crv = sftk_searchDatabase(keyHandle, search, pTemplate, ulCount); 1.4645 + sftk_freeDB(keyHandle); 1.4646 + } 1.4647 + return crv; 1.4648 +} 1.4649 + 1.4650 +/* NSC_FindObjectsInit initializes a search for token and session objects 1.4651 + * that match a template. */ 1.4652 +CK_RV NSC_FindObjectsInit(CK_SESSION_HANDLE hSession, 1.4653 + CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount) 1.4654 +{ 1.4655 + SFTKSearchResults *search = NULL, *freeSearch = NULL; 1.4656 + SFTKSession *session = NULL; 1.4657 + SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); 1.4658 + PRBool tokenOnly = PR_FALSE; 1.4659 + CK_RV crv = CKR_OK; 1.4660 + PRBool isLoggedIn; 1.4661 + 1.4662 + CHECK_FORK(); 1.4663 + 1.4664 + if (slot == NULL) { 1.4665 + return CKR_SESSION_HANDLE_INVALID; 1.4666 + } 1.4667 + session = sftk_SessionFromHandle(hSession); 1.4668 + if (session == NULL) { 1.4669 + crv = CKR_SESSION_HANDLE_INVALID; 1.4670 + goto loser; 1.4671 + } 1.4672 + 1.4673 + search = (SFTKSearchResults *)PORT_Alloc(sizeof(SFTKSearchResults)); 1.4674 + if (search == NULL) { 1.4675 + crv = CKR_HOST_MEMORY; 1.4676 + goto loser; 1.4677 + } 1.4678 + search->handles = (CK_OBJECT_HANDLE *) 1.4679 + PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * NSC_SEARCH_BLOCK_SIZE); 1.4680 + if (search->handles == NULL) { 1.4681 + crv = CKR_HOST_MEMORY; 1.4682 + goto loser; 1.4683 + } 1.4684 + search->index = 0; 1.4685 + search->size = 0; 1.4686 + search->array_size = NSC_SEARCH_BLOCK_SIZE; 1.4687 + isLoggedIn = (PRBool)((!slot->needLogin) || slot->isLoggedIn); 1.4688 + 1.4689 + crv = sftk_searchTokenList(slot, search, pTemplate, ulCount, &tokenOnly, 1.4690 + isLoggedIn); 1.4691 + if (crv != CKR_OK) { 1.4692 + goto loser; 1.4693 + } 1.4694 + 1.4695 + /* build list of found objects in the session */ 1.4696 + if (!tokenOnly) { 1.4697 + crv = sftk_searchObjectList(search, slot->sessObjHashTable, 1.4698 + slot->sessObjHashSize, slot->objectLock, 1.4699 + pTemplate, ulCount, isLoggedIn); 1.4700 + } 1.4701 + if (crv != CKR_OK) { 1.4702 + goto loser; 1.4703 + } 1.4704 + 1.4705 + if ((freeSearch = session->search) != NULL) { 1.4706 + session->search = NULL; 1.4707 + sftk_FreeSearch(freeSearch); 1.4708 + } 1.4709 + session->search = search; 1.4710 + sftk_FreeSession(session); 1.4711 + return CKR_OK; 1.4712 + 1.4713 +loser: 1.4714 + if (search) { 1.4715 + sftk_FreeSearch(search); 1.4716 + } 1.4717 + if (session) { 1.4718 + sftk_FreeSession(session); 1.4719 + } 1.4720 + return crv; 1.4721 +} 1.4722 + 1.4723 + 1.4724 +/* NSC_FindObjects continues a search for token and session objects 1.4725 + * that match a template, obtaining additional object handles. */ 1.4726 +CK_RV NSC_FindObjects(CK_SESSION_HANDLE hSession, 1.4727 + CK_OBJECT_HANDLE_PTR phObject,CK_ULONG ulMaxObjectCount, 1.4728 + CK_ULONG_PTR pulObjectCount) 1.4729 +{ 1.4730 + SFTKSession *session; 1.4731 + SFTKSearchResults *search; 1.4732 + int transfer; 1.4733 + int left; 1.4734 + 1.4735 + CHECK_FORK(); 1.4736 + 1.4737 + *pulObjectCount = 0; 1.4738 + session = sftk_SessionFromHandle(hSession); 1.4739 + if (session == NULL) return CKR_SESSION_HANDLE_INVALID; 1.4740 + if (session->search == NULL) { 1.4741 + sftk_FreeSession(session); 1.4742 + return CKR_OK; 1.4743 + } 1.4744 + search = session->search; 1.4745 + left = session->search->size - session->search->index; 1.4746 + transfer = ((int)ulMaxObjectCount > left) ? left : ulMaxObjectCount; 1.4747 + if (transfer > 0) { 1.4748 + PORT_Memcpy(phObject,&search->handles[search->index], 1.4749 + transfer*sizeof(CK_OBJECT_HANDLE)); 1.4750 + } else { 1.4751 + *phObject = CK_INVALID_HANDLE; 1.4752 + } 1.4753 + 1.4754 + search->index += transfer; 1.4755 + if (search->index == search->size) { 1.4756 + session->search = NULL; 1.4757 + sftk_FreeSearch(search); 1.4758 + } 1.4759 + *pulObjectCount = transfer; 1.4760 + sftk_FreeSession(session); 1.4761 + return CKR_OK; 1.4762 +} 1.4763 + 1.4764 +/* NSC_FindObjectsFinal finishes a search for token and session objects. */ 1.4765 +CK_RV NSC_FindObjectsFinal(CK_SESSION_HANDLE hSession) 1.4766 +{ 1.4767 + SFTKSession *session; 1.4768 + SFTKSearchResults *search; 1.4769 + 1.4770 + CHECK_FORK(); 1.4771 + 1.4772 + session = sftk_SessionFromHandle(hSession); 1.4773 + if (session == NULL) return CKR_SESSION_HANDLE_INVALID; 1.4774 + search = session->search; 1.4775 + session->search = NULL; 1.4776 + sftk_FreeSession(session); 1.4777 + if (search != NULL) { 1.4778 + sftk_FreeSearch(search); 1.4779 + } 1.4780 + return CKR_OK; 1.4781 +} 1.4782 + 1.4783 + 1.4784 + 1.4785 +CK_RV NSC_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, 1.4786 + CK_VOID_PTR pReserved) 1.4787 +{ 1.4788 + CHECK_FORK(); 1.4789 + 1.4790 + return CKR_FUNCTION_NOT_SUPPORTED; 1.4791 +} 1.4792 +