comparison nss/lib/softoken/pkcs11.c @ 0:1e5118fa0cb1

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