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