Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(134)

Side by Side Diff: nss/lib/softoken/pkcs11.c

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

Powered by Google App Engine
This is Rietveld 408576698