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