1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
22 * Dr Stephen Henson <stephen.henson@gemplus.com>
23 * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 * This file implements PKCS 11 on top of our existing security modules
41 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
42 * This implementation has two slots:
43 * slot 1 is our generic crypto support. It does not require login.
44 * It supports Public Key ops, and all they bulk ciphers and hashes.
45 * It can also support Private Key ops for imported Private keys. It does
46 * not have any token storage.
47 * slot 2 is our private key support. It requires a login before use. It
48 * can store Private Keys and Certs as token objects. Currently only private
49 * keys and their associated Certificates are saved on the token.
51 * In this implementation, session objects are only visible to the session
52 * that created or generated them.
73 * ******************** Static data *******************************
76 /* The next three strings must be exactly 32 characters long */
77 static char *manufacturerID
= "Mozilla Foundation ";
78 static char manufacturerID_space
[33];
79 static char *libraryDescription
= "NSS Internal Crypto Services ";
80 static char libraryDescription_space
[33];
83 * In FIPS mode, we disallow login attempts for 1 second after a login
84 * failure so that there are at most 60 login attempts per minute.
86 static PRIntervalTime loginWaitTime
;
87 static PRUint32 minSessionObjectHandle
= 1U;
89 #define __PASTE(x,y) x##y
92 * we renamed all our internal functions, get the correct
93 * definitions for them...
95 #undef CK_PKCS11_FUNCTION_INFO
96 #undef CK_NEED_ARG_LIST
98 #define CK_EXTERN extern
99 #define CK_PKCS11_FUNCTION_INFO(func) \
100 CK_RV __PASTE(NS,func)
101 #define CK_NEED_ARG_LIST 1
107 /* build the crypto module table */
108 static const CK_FUNCTION_LIST sftk_funcList
= {
111 #undef CK_PKCS11_FUNCTION_INFO
112 #undef CK_NEED_ARG_LIST
114 #define CK_PKCS11_FUNCTION_INFO(func) \
120 #undef CK_PKCS11_FUNCTION_INFO
121 #undef CK_NEED_ARG_LIST
126 /* List of DES Weak Keys */
127 typedef unsigned char desKey
[8];
128 static const desKey sftk_desWeakTable
[] = {
131 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
132 { 0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e },
133 { 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0 },
134 { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
136 { 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe },
137 { 0xfe, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0xfe },
139 { 0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0 },
140 { 0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e },
142 { 0x00, 0xe0, 0x00, 0xe0, 0x00, 0x0f, 0x00, 0x0f },
143 { 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00 },
145 { 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe },
146 { 0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e },
148 { 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e },
149 { 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00 },
151 { 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe },
152 { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0 },
155 { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
156 { 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e },
157 { 0xe0, 0xe0, 0xe0, 0xe0, 0xf1, 0xf1, 0xf1, 0xf1 },
158 { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
161 { 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe },
162 { 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01 },
164 { 0x1f, 0xe0, 0x1f, 0xe0, 0x0e, 0xf1, 0x0e, 0xf1 },
165 { 0xe0, 0x1f, 0xe0, 0x1f, 0xf1, 0x0e, 0xf1, 0x0e },
167 { 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1 },
168 { 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1, 0x01 },
170 { 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe },
171 { 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e },
173 { 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e },
174 { 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e, 0x01 },
176 { 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1, 0xfe },
177 { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1 }
182 static const int sftk_desWeakTableSize
= sizeof(sftk_desWeakTable
)/
183 sizeof(sftk_desWeakTable
[0]);
185 /* DES KEY Parity conversion table. Takes each byte/2 as an index, returns
186 * that byte with the proper parity bit set */
187 static const unsigned char parityTable
[256] = {
188 /* Even...0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e */
189 /* E */ 0x01,0x02,0x04,0x07,0x08,0x0b,0x0d,0x0e,
190 /* Odd....0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e */
191 /* O */ 0x10,0x13,0x15,0x16,0x19,0x1a,0x1c,0x1f,
192 /* Odd....0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e */
193 /* O */ 0x20,0x23,0x25,0x26,0x29,0x2a,0x2c,0x2f,
194 /* Even...0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e */
195 /* E */ 0x31,0x32,0x34,0x37,0x38,0x3b,0x3d,0x3e,
196 /* Odd....0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e */
197 /* O */ 0x40,0x43,0x45,0x46,0x49,0x4a,0x4c,0x4f,
198 /* Even...0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e */
199 /* E */ 0x51,0x52,0x54,0x57,0x58,0x5b,0x5d,0x5e,
200 /* Even...0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e */
201 /* E */ 0x61,0x62,0x64,0x67,0x68,0x6b,0x6d,0x6e,
202 /* Odd....0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e */
203 /* O */ 0x70,0x73,0x75,0x76,0x79,0x7a,0x7c,0x7f,
204 /* Odd....0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e */
205 /* O */ 0x80,0x83,0x85,0x86,0x89,0x8a,0x8c,0x8f,
206 /* Even...0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e */
207 /* E */ 0x91,0x92,0x94,0x97,0x98,0x9b,0x9d,0x9e,
208 /* Even...0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae */
209 /* E */ 0xa1,0xa2,0xa4,0xa7,0xa8,0xab,0xad,0xae,
210 /* Odd....0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe */
211 /* O */ 0xb0,0xb3,0xb5,0xb6,0xb9,0xba,0xbc,0xbf,
212 /* Even...0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce */
213 /* E */ 0xc1,0xc2,0xc4,0xc7,0xc8,0xcb,0xcd,0xce,
214 /* Odd....0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde */
215 /* O */ 0xd0,0xd3,0xd5,0xd6,0xd9,0xda,0xdc,0xdf,
216 /* Odd....0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee */
217 /* O */ 0xe0,0xe3,0xe5,0xe6,0xe9,0xea,0xec,0xef,
218 /* Even...0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe */
219 /* E */ 0xf1,0xf2,0xf4,0xf7,0xf8,0xfb,0xfd,0xfe,
223 struct mechanismList
{
224 CK_MECHANISM_TYPE type
;
225 CK_MECHANISM_INFO info
;
230 * the following table includes a complete list of mechanism defined by
231 * PKCS #11 version 2.01. Those Mechanisms not supported by this PKCS #11
232 * module are ifdef'ed out.
234 #define CKF_EN_DE CKF_ENCRYPT | CKF_DECRYPT
235 #define CKF_WR_UN CKF_WRAP | CKF_UNWRAP
236 #define CKF_SN_VR CKF_SIGN | CKF_VERIFY
237 #define CKF_SN_RE CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER
239 #define CKF_EN_DE_WR_UN CKF_EN_DE | CKF_WR_UN
240 #define CKF_SN_VR_RE CKF_SN_VR | CKF_SN_RE
241 #define CKF_DUZ_IT_ALL CKF_EN_DE_WR_UN | CKF_SN_VR_RE
243 #define CKF_EC_PNU CKF_EC_FP | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS
245 #define CKF_EC_BPNU CKF_EC_F_2M | CKF_EC_PNU
247 #define CK_MAX 0xffffffff
249 static const struct mechanismList mechanisms
[] = {
252 * PKCS #11 Mechanism List.
254 * The first argument is the PKCS #11 Mechanism we support.
255 * The second argument is Mechanism info structure. It includes:
256 * The minimum key size,
257 * in bits for RSA, DSA, DH, EC*, KEA, RC2 and RC4 * algs.
258 * in bytes for RC5, AES, Camellia, and CAST*
259 * ignored for DES*, IDEA and FORTEZZA based
260 * The maximum key size,
261 * in bits for RSA, DSA, DH, EC*, KEA, RC2 and RC4 * algs.
262 * in bytes for RC5, AES, Camellia, and CAST*
263 * ignored for DES*, IDEA and FORTEZZA based
265 * What operations are supported by this mechanism.
266 * The third argument is a bool which tells if this mechanism is
267 * supported in the database token.
271 /* ------------------------- RSA Operations ---------------------------*/
272 {CKM_RSA_PKCS_KEY_PAIR_GEN
,{RSA_MIN_MODULUS_BITS
,CK_MAX
,
273 CKF_GENERATE_KEY_PAIR
},PR_TRUE
},
274 {CKM_RSA_PKCS
, {RSA_MIN_MODULUS_BITS
,CK_MAX
,
275 CKF_DUZ_IT_ALL
}, PR_TRUE
},
276 #ifdef SFTK_RSA9796_SUPPORTED
277 {CKM_RSA_9796
, {RSA_MIN_MODULUS_BITS
,CK_MAX
,
278 CKF_DUZ_IT_ALL
}, PR_TRUE
},
280 {CKM_RSA_X_509
, {RSA_MIN_MODULUS_BITS
,CK_MAX
,
281 CKF_DUZ_IT_ALL
}, PR_TRUE
},
282 /* -------------- RSA Multipart Signing Operations -------------------- */
283 {CKM_MD2_RSA_PKCS
, {RSA_MIN_MODULUS_BITS
,CK_MAX
,
284 CKF_SN_VR
}, PR_TRUE
},
285 {CKM_MD5_RSA_PKCS
, {RSA_MIN_MODULUS_BITS
,CK_MAX
,
286 CKF_SN_VR
}, PR_TRUE
},
287 {CKM_SHA1_RSA_PKCS
, {RSA_MIN_MODULUS_BITS
,CK_MAX
,
288 CKF_SN_VR
}, PR_TRUE
},
289 {CKM_SHA256_RSA_PKCS
, {RSA_MIN_MODULUS_BITS
,CK_MAX
,
290 CKF_SN_VR
}, PR_TRUE
},
291 {CKM_SHA384_RSA_PKCS
, {RSA_MIN_MODULUS_BITS
,CK_MAX
,
292 CKF_SN_VR
}, PR_TRUE
},
293 {CKM_SHA512_RSA_PKCS
, {RSA_MIN_MODULUS_BITS
,CK_MAX
,
294 CKF_SN_VR
}, PR_TRUE
},
295 /* ------------------------- DSA Operations --------------------------- */
296 {CKM_DSA_KEY_PAIR_GEN
, {DSA_MIN_P_BITS
, DSA_MAX_P_BITS
,
297 CKF_GENERATE_KEY_PAIR
}, PR_TRUE
},
298 {CKM_DSA
, {DSA_MIN_P_BITS
, DSA_MAX_P_BITS
,
299 CKF_SN_VR
}, PR_TRUE
},
300 {CKM_DSA_SHA1
, {DSA_MIN_P_BITS
, DSA_MAX_P_BITS
,
301 CKF_SN_VR
}, PR_TRUE
},
302 /* -------------------- Diffie Hellman Operations --------------------- */
303 /* no diffie hellman yet */
304 {CKM_DH_PKCS_KEY_PAIR_GEN
, {DH_MIN_P_BITS
, DH_MAX_P_BITS
,
305 CKF_GENERATE_KEY_PAIR
}, PR_TRUE
},
306 {CKM_DH_PKCS_DERIVE
, {DH_MIN_P_BITS
, DH_MAX_P_BITS
,
307 CKF_DERIVE
}, PR_TRUE
},
308 #ifdef NSS_ENABLE_ECC
309 /* -------------------- Elliptic Curve Operations --------------------- */
310 {CKM_EC_KEY_PAIR_GEN
, {112, 571, CKF_GENERATE_KEY_PAIR
|CKF_EC_BPNU
}, PR_TRUE
},
311 {CKM_ECDH1_DERIVE
, {112, 571, CKF_DERIVE
|CKF_EC_BPNU
}, PR_TRUE
},
312 {CKM_ECDSA
, {112, 571, CKF_SN_VR
|CKF_EC_BPNU
}, PR_TRUE
},
313 {CKM_ECDSA_SHA1
, {112, 571, CKF_SN_VR
|CKF_EC_BPNU
}, PR_TRUE
},
314 #endif /* NSS_ENABLE_ECC */
315 /* ------------------------- RC2 Operations --------------------------- */
316 {CKM_RC2_KEY_GEN
, {1, 128, CKF_GENERATE
}, PR_TRUE
},
317 {CKM_RC2_ECB
, {1, 128, CKF_EN_DE_WR_UN
}, PR_TRUE
},
318 {CKM_RC2_CBC
, {1, 128, CKF_EN_DE_WR_UN
}, PR_TRUE
},
319 {CKM_RC2_MAC
, {1, 128, CKF_SN_VR
}, PR_TRUE
},
320 {CKM_RC2_MAC_GENERAL
, {1, 128, CKF_SN_VR
}, PR_TRUE
},
321 {CKM_RC2_CBC_PAD
, {1, 128, CKF_EN_DE_WR_UN
}, PR_TRUE
},
322 /* ------------------------- RC4 Operations --------------------------- */
323 {CKM_RC4_KEY_GEN
, {1, 256, CKF_GENERATE
}, PR_FALSE
},
324 {CKM_RC4
, {1, 256, CKF_EN_DE_WR_UN
}, PR_FALSE
},
325 /* ------------------------- DES Operations --------------------------- */
326 {CKM_DES_KEY_GEN
, { 8, 8, CKF_GENERATE
}, PR_TRUE
},
327 {CKM_DES_ECB
, { 8, 8, CKF_EN_DE_WR_UN
}, PR_TRUE
},
328 {CKM_DES_CBC
, { 8, 8, CKF_EN_DE_WR_UN
}, PR_TRUE
},
329 {CKM_DES_MAC
, { 8, 8, CKF_SN_VR
}, PR_TRUE
},
330 {CKM_DES_MAC_GENERAL
, { 8, 8, CKF_SN_VR
}, PR_TRUE
},
331 {CKM_DES_CBC_PAD
, { 8, 8, CKF_EN_DE_WR_UN
}, PR_TRUE
},
332 {CKM_DES2_KEY_GEN
, {24, 24, CKF_GENERATE
}, PR_TRUE
},
333 {CKM_DES3_KEY_GEN
, {24, 24, CKF_GENERATE
}, PR_TRUE
},
334 {CKM_DES3_ECB
, {24, 24, CKF_EN_DE_WR_UN
}, PR_TRUE
},
335 {CKM_DES3_CBC
, {24, 24, CKF_EN_DE_WR_UN
}, PR_TRUE
},
336 {CKM_DES3_MAC
, {24, 24, CKF_SN_VR
}, PR_TRUE
},
337 {CKM_DES3_MAC_GENERAL
, {24, 24, CKF_SN_VR
}, PR_TRUE
},
338 {CKM_DES3_CBC_PAD
, {24, 24, CKF_EN_DE_WR_UN
}, PR_TRUE
},
339 /* ------------------------- CDMF Operations --------------------------- */
340 {CKM_CDMF_KEY_GEN
, {8, 8, CKF_GENERATE
}, PR_TRUE
},
341 {CKM_CDMF_ECB
, {8, 8, CKF_EN_DE_WR_UN
}, PR_TRUE
},
342 {CKM_CDMF_CBC
, {8, 8, CKF_EN_DE_WR_UN
}, PR_TRUE
},
343 {CKM_CDMF_MAC
, {8, 8, CKF_SN_VR
}, PR_TRUE
},
344 {CKM_CDMF_MAC_GENERAL
, {8, 8, CKF_SN_VR
}, PR_TRUE
},
345 {CKM_CDMF_CBC_PAD
, {8, 8, CKF_EN_DE_WR_UN
}, PR_TRUE
},
346 /* ------------------------- AES Operations --------------------------- */
347 {CKM_AES_KEY_GEN
, {16, 32, CKF_GENERATE
}, PR_TRUE
},
348 {CKM_AES_ECB
, {16, 32, CKF_EN_DE_WR_UN
}, PR_TRUE
},
349 {CKM_AES_CBC
, {16, 32, CKF_EN_DE_WR_UN
}, PR_TRUE
},
350 {CKM_AES_MAC
, {16, 32, CKF_SN_VR
}, PR_TRUE
},
351 {CKM_AES_MAC_GENERAL
, {16, 32, CKF_SN_VR
}, PR_TRUE
},
352 {CKM_AES_CBC_PAD
, {16, 32, CKF_EN_DE_WR_UN
}, PR_TRUE
},
353 /* ------------------------- Camellia Operations --------------------- */
354 {CKM_CAMELLIA_KEY_GEN
, {16, 32, CKF_GENERATE
}, PR_TRUE
},
355 {CKM_CAMELLIA_ECB
, {16, 32, CKF_EN_DE_WR_UN
}, PR_TRUE
},
356 {CKM_CAMELLIA_CBC
, {16, 32, CKF_EN_DE_WR_UN
}, PR_TRUE
},
357 {CKM_CAMELLIA_MAC
, {16, 32, CKF_SN_VR
}, PR_TRUE
},
358 {CKM_CAMELLIA_MAC_GENERAL
, {16, 32, CKF_SN_VR
}, PR_TRUE
},
359 {CKM_CAMELLIA_CBC_PAD
, {16, 32, CKF_EN_DE_WR_UN
}, PR_TRUE
},
360 /* ------------------------- Hashing Operations ----------------------- */
361 {CKM_MD2
, {0, 0, CKF_DIGEST
}, PR_FALSE
},
362 {CKM_MD2_HMAC
, {1, 128, CKF_SN_VR
}, PR_TRUE
},
363 {CKM_MD2_HMAC_GENERAL
, {1, 128, CKF_SN_VR
}, PR_TRUE
},
364 {CKM_MD5
, {0, 0, CKF_DIGEST
}, PR_FALSE
},
365 {CKM_MD5_HMAC
, {1, 128, CKF_SN_VR
}, PR_TRUE
},
366 {CKM_MD5_HMAC_GENERAL
, {1, 128, CKF_SN_VR
}, PR_TRUE
},
367 {CKM_SHA_1
, {0, 0, CKF_DIGEST
}, PR_FALSE
},
368 {CKM_SHA_1_HMAC
, {1, 128, CKF_SN_VR
}, PR_TRUE
},
369 {CKM_SHA_1_HMAC_GENERAL
, {1, 128, CKF_SN_VR
}, PR_TRUE
},
370 {CKM_SHA256
, {0, 0, CKF_DIGEST
}, PR_FALSE
},
371 {CKM_SHA256_HMAC
, {1, 128, CKF_SN_VR
}, PR_TRUE
},
372 {CKM_SHA256_HMAC_GENERAL
, {1, 128, CKF_SN_VR
}, PR_TRUE
},
373 {CKM_SHA384
, {0, 0, CKF_DIGEST
}, PR_FALSE
},
374 {CKM_SHA384_HMAC
, {1, 128, CKF_SN_VR
}, PR_TRUE
},
375 {CKM_SHA384_HMAC_GENERAL
, {1, 128, CKF_SN_VR
}, PR_TRUE
},
376 {CKM_SHA512
, {0, 0, CKF_DIGEST
}, PR_FALSE
},
377 {CKM_SHA512_HMAC
, {1, 128, CKF_SN_VR
}, PR_TRUE
},
378 {CKM_SHA512_HMAC_GENERAL
, {1, 128, CKF_SN_VR
}, PR_TRUE
},
379 {CKM_TLS_PRF_GENERAL
, {0, 512, CKF_SN_VR
}, PR_FALSE
},
380 /* ------------------------- CAST Operations --------------------------- */
381 #ifdef NSS_SOFTOKEN_DOES_CAST
382 /* Cast operations are not supported ( yet? ) */
383 {CKM_CAST_KEY_GEN
, {1, 8, CKF_GENERATE
}, PR_TRUE
},
384 {CKM_CAST_ECB
, {1, 8, CKF_EN_DE_WR_UN
}, PR_TRUE
},
385 {CKM_CAST_CBC
, {1, 8, CKF_EN_DE_WR_UN
}, PR_TRUE
},
386 {CKM_CAST_MAC
, {1, 8, CKF_SN_VR
}, PR_TRUE
},
387 {CKM_CAST_MAC_GENERAL
, {1, 8, CKF_SN_VR
}, PR_TRUE
},
388 {CKM_CAST_CBC_PAD
, {1, 8, CKF_EN_DE_WR_UN
}, PR_TRUE
},
389 {CKM_CAST3_KEY_GEN
, {1, 16, CKF_GENERATE
}, PR_TRUE
},
390 {CKM_CAST3_ECB
, {1, 16, CKF_EN_DE_WR_UN
}, PR_TRUE
},
391 {CKM_CAST3_CBC
, {1, 16, CKF_EN_DE_WR_UN
}, PR_TRUE
},
392 {CKM_CAST3_MAC
, {1, 16, CKF_SN_VR
}, PR_TRUE
},
393 {CKM_CAST3_MAC_GENERAL
, {1, 16, CKF_SN_VR
}, PR_TRUE
},
394 {CKM_CAST3_CBC_PAD
, {1, 16, CKF_EN_DE_WR_UN
}, PR_TRUE
},
395 {CKM_CAST5_KEY_GEN
, {1, 16, CKF_GENERATE
}, PR_TRUE
},
396 {CKM_CAST5_ECB
, {1, 16, CKF_EN_DE_WR_UN
}, PR_TRUE
},
397 {CKM_CAST5_CBC
, {1, 16, CKF_EN_DE_WR_UN
}, PR_TRUE
},
398 {CKM_CAST5_MAC
, {1, 16, CKF_SN_VR
}, PR_TRUE
},
399 {CKM_CAST5_MAC_GENERAL
, {1, 16, CKF_SN_VR
}, PR_TRUE
},
400 {CKM_CAST5_CBC_PAD
, {1, 16, CKF_EN_DE_WR_UN
}, PR_TRUE
},
402 #if NSS_SOFTOKEN_DOES_RC5
403 /* ------------------------- RC5 Operations --------------------------- */
404 {CKM_RC5_KEY_GEN
, {1, 32, CKF_GENERATE
}, PR_TRUE
},
405 {CKM_RC5_ECB
, {1, 32, CKF_EN_DE_WR_UN
}, PR_TRUE
},
406 {CKM_RC5_CBC
, {1, 32, CKF_EN_DE_WR_UN
}, PR_TRUE
},
407 {CKM_RC5_MAC
, {1, 32, CKF_SN_VR
}, PR_TRUE
},
408 {CKM_RC5_MAC_GENERAL
, {1, 32, CKF_SN_VR
}, PR_TRUE
},
409 {CKM_RC5_CBC_PAD
, {1, 32, CKF_EN_DE_WR_UN
}, PR_TRUE
},
411 #ifdef NSS_SOFTOKEN_DOES_IDEA
412 /* ------------------------- IDEA Operations -------------------------- */
413 {CKM_IDEA_KEY_GEN
, {16, 16, CKF_GENERATE
}, PR_TRUE
},
414 {CKM_IDEA_ECB
, {16, 16, CKF_EN_DE_WR_UN
}, PR_TRUE
},
415 {CKM_IDEA_CBC
, {16, 16, CKF_EN_DE_WR_UN
}, PR_TRUE
},
416 {CKM_IDEA_MAC
, {16, 16, CKF_SN_VR
}, PR_TRUE
},
417 {CKM_IDEA_MAC_GENERAL
, {16, 16, CKF_SN_VR
}, PR_TRUE
},
418 {CKM_IDEA_CBC_PAD
, {16, 16, CKF_EN_DE_WR_UN
}, PR_TRUE
},
420 /* --------------------- Secret Key Operations ------------------------ */
421 {CKM_GENERIC_SECRET_KEY_GEN
, {1, 32, CKF_GENERATE
}, PR_TRUE
},
422 {CKM_CONCATENATE_BASE_AND_KEY
, {1, 32, CKF_GENERATE
}, PR_FALSE
},
423 {CKM_CONCATENATE_BASE_AND_DATA
, {1, 32, CKF_GENERATE
}, PR_FALSE
},
424 {CKM_CONCATENATE_DATA_AND_BASE
, {1, 32, CKF_GENERATE
}, PR_FALSE
},
425 {CKM_XOR_BASE_AND_DATA
, {1, 32, CKF_GENERATE
}, PR_FALSE
},
426 {CKM_EXTRACT_KEY_FROM_KEY
, {1, 32, CKF_DERIVE
}, PR_FALSE
},
427 /* ---------------------- SSL Key Derivations ------------------------- */
428 {CKM_SSL3_PRE_MASTER_KEY_GEN
, {48, 48, CKF_GENERATE
}, PR_FALSE
},
429 {CKM_SSL3_MASTER_KEY_DERIVE
, {48, 48, CKF_DERIVE
}, PR_FALSE
},
430 {CKM_SSL3_MASTER_KEY_DERIVE_DH
, {8, 128, CKF_DERIVE
}, PR_FALSE
},
431 {CKM_SSL3_KEY_AND_MAC_DERIVE
, {48, 48, CKF_DERIVE
}, PR_FALSE
},
432 {CKM_SSL3_MD5_MAC
, { 0, 16, CKF_DERIVE
}, PR_FALSE
},
433 {CKM_SSL3_SHA1_MAC
, { 0, 20, CKF_DERIVE
}, PR_FALSE
},
434 {CKM_MD5_KEY_DERIVATION
, { 0, 16, CKF_DERIVE
}, PR_FALSE
},
435 {CKM_MD2_KEY_DERIVATION
, { 0, 16, CKF_DERIVE
}, PR_FALSE
},
436 {CKM_SHA1_KEY_DERIVATION
, { 0, 20, CKF_DERIVE
}, PR_FALSE
},
437 {CKM_TLS_MASTER_KEY_DERIVE
, {48, 48, CKF_DERIVE
}, PR_FALSE
},
438 {CKM_TLS_MASTER_KEY_DERIVE_DH
, {8, 128, CKF_DERIVE
}, PR_FALSE
},
439 {CKM_TLS_KEY_AND_MAC_DERIVE
, {48, 48, CKF_DERIVE
}, PR_FALSE
},
440 /* ---------------------- PBE Key Derivations ------------------------ */
441 {CKM_PBE_MD2_DES_CBC
, {8, 8, CKF_DERIVE
}, PR_TRUE
},
442 {CKM_PBE_MD5_DES_CBC
, {8, 8, CKF_DERIVE
}, PR_TRUE
},
443 /* ------------------ NETSCAPE PBE Key Derivations ------------------- */
444 {CKM_NETSCAPE_PBE_SHA1_DES_CBC
, { 8, 8, CKF_GENERATE
}, PR_TRUE
},
445 {CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC
, {24,24, CKF_GENERATE
}, PR_TRUE
},
446 {CKM_PBE_SHA1_DES3_EDE_CBC
, {24,24, CKF_GENERATE
}, PR_TRUE
},
447 {CKM_PBE_SHA1_DES2_EDE_CBC
, {24,24, CKF_GENERATE
}, PR_TRUE
},
448 {CKM_PBE_SHA1_RC2_40_CBC
, {40,40, CKF_GENERATE
}, PR_TRUE
},
449 {CKM_PBE_SHA1_RC2_128_CBC
, {128,128, CKF_GENERATE
}, PR_TRUE
},
450 {CKM_PBE_SHA1_RC4_40
, {40,40, CKF_GENERATE
}, PR_TRUE
},
451 {CKM_PBE_SHA1_RC4_128
, {128,128, CKF_GENERATE
}, PR_TRUE
},
452 {CKM_PBA_SHA1_WITH_SHA1_HMAC
, {20,20, CKF_GENERATE
}, PR_TRUE
},
453 {CKM_PKCS5_PBKD2
, {1,256, CKF_GENERATE
}, PR_TRUE
},
454 {CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN
, {20,20, CKF_GENERATE
}, PR_TRUE
},
455 {CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN
, {16,16, CKF_GENERATE
}, PR_TRUE
},
456 {CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN
, {16,16, CKF_GENERATE
}, PR_TRUE
},
457 /* ------------------ AES Key Wrap (also encrypt) ------------------- */
458 {CKM_NETSCAPE_AES_KEY_WRAP
, {16, 32, CKF_EN_DE_WR_UN
}, PR_TRUE
},
459 {CKM_NETSCAPE_AES_KEY_WRAP_PAD
, {16, 32, CKF_EN_DE_WR_UN
}, PR_TRUE
},
461 static const CK_ULONG mechanismCount
= sizeof(mechanisms
)/sizeof(mechanisms
[0]);
463 static PRBool nsc_init
= PR_FALSE
;
465 #if defined(XP_UNIX) && !defined(NO_PTHREADS)
469 PRBool forked
= PR_FALSE
;
471 void ForkedChild(void)
473 if (nsc_init
|| nsf_init
) {
481 sftk_setStringName(const char *inString
, char *buffer
, int buffer_length
, PRBool nullTerminate
)
483 int full_length
, string_length
;
485 full_length
= nullTerminate
? buffer_length
-1 : buffer_length
;
486 string_length
= PORT_Strlen(inString
);
488 * shorten the string, respecting utf8 encoding
489 * to do so, we work backward from the end
490 * bytes looking from the end are either:
491 * - ascii [0x00,0x7f]
492 * - the [2-n]th byte of a multibyte sequence
493 * [0x3F,0xBF], i.e, most significant 2 bits are '10'
494 * - the first byte of a multibyte sequence [0xC0,0xFD],
495 * i.e, most significant 2 bits are '11'
497 * When the string is too long, we lop off any trailing '10' bytes,
498 * if any. When these are all eliminated we lop off
499 * one additional byte. Thus if we lopped any '10'
500 * we'll be lopping a '11' byte (the first byte of the multibyte sequence),
501 * otherwise we're lopping off an ascii character.
503 * To test for '10' bytes, we first AND it with
504 * 11000000 (0xc0) so that we get 10000000 (0x80) if and only if
505 * the byte starts with 10. We test for equality.
507 while ( string_length
> full_length
) {
508 /* need to shorten */
509 while ( string_length
> 0 &&
510 ((inString
[string_length
-1]&(char)0xc0) == (char)0x80)) {
511 /* lop off '10' byte */
515 * test string_length in case bad data is received
516 * and string consisted of all '10' bytes,
517 * avoiding any infinite loop
519 if ( string_length
) {
520 /* remove either '11' byte or an asci byte */
524 PORT_Memset(buffer
,' ',full_length
);
526 buffer
[full_length
] = 0;
528 PORT_Memcpy(buffer
,inString
,string_length
);
532 * Configuration utils
535 sftk_configure(const char *man
, const char *libdes
)
538 /* make sure the internationalization was done correctly... */
540 manufacturerID
= sftk_setStringName(man
,manufacturerID_space
,
541 sizeof(manufacturerID_space
), PR_TRUE
);
544 libraryDescription
= sftk_setStringName(libdes
,
545 libraryDescription_space
, sizeof(libraryDescription_space
),
553 * ******************** Password Utilities *******************************
557 * see if the key DB password is enabled
560 sftk_hasNullPassword(SFTKSlot
*slot
, SFTKDBHandle
*keydb
)
564 pwenabled
= PR_FALSE
;
565 if (sftkdb_HasPasswordSet(keydb
) == SECSuccess
) {
566 PRBool tokenRemoved
= PR_FALSE
;
567 SECStatus rv
= sftkdb_CheckPassword(keydb
, "", &tokenRemoved
);
569 sftk_CloseAllSessions(slot
);
571 return (rv
== SECSuccess
);
578 * ******************** Object Creation Utilities ***************************
582 /* Make sure a given attribute exists. If it doesn't, initialize it to
586 sftk_defaultAttribute(SFTKObject
*object
,CK_ATTRIBUTE_TYPE type
,void *value
,
589 if ( !sftk_hasAttribute(object
, type
)) {
590 return sftk_AddAttributeType(object
,type
,value
,len
);
596 * check the consistancy and initialize a Data Object
599 sftk_handleDataObject(SFTKSession
*session
,SFTKObject
*object
)
603 /* first reject private and token data objects */
604 if (sftk_isTrue(object
,CKA_PRIVATE
) || sftk_isTrue(object
,CKA_TOKEN
)) {
605 return CKR_ATTRIBUTE_VALUE_INVALID
;
608 /* now just verify the required date fields */
609 crv
= sftk_defaultAttribute(object
,CKA_APPLICATION
,NULL
,0);
610 if (crv
!= CKR_OK
) return crv
;
611 crv
= sftk_defaultAttribute(object
,CKA_VALUE
,NULL
,0);
612 if (crv
!= CKR_OK
) return crv
;
618 * check the consistancy and initialize a Certificate Object
621 sftk_handleCertObject(SFTKSession
*session
,SFTKObject
*object
)
623 CK_CERTIFICATE_TYPE type
;
624 SFTKAttribute
*attribute
;
627 /* certificates must have a type */
628 if ( !sftk_hasAttribute(object
,CKA_CERTIFICATE_TYPE
) ) {
629 return CKR_TEMPLATE_INCOMPLETE
;
632 /* we can't store any certs private */
633 if (sftk_isTrue(object
,CKA_PRIVATE
)) {
634 return CKR_ATTRIBUTE_VALUE_INVALID
;
637 /* We only support X.509 Certs for now */
638 attribute
= sftk_FindAttribute(object
,CKA_CERTIFICATE_TYPE
);
639 if (attribute
== NULL
) return CKR_TEMPLATE_INCOMPLETE
;
640 type
= *(CK_CERTIFICATE_TYPE
*)attribute
->attrib
.pValue
;
641 sftk_FreeAttribute(attribute
);
643 if (type
!= CKC_X_509
) {
644 return CKR_ATTRIBUTE_VALUE_INVALID
;
647 /* X.509 Certificate */
649 /* make sure we have a cert */
650 if ( !sftk_hasAttribute(object
,CKA_VALUE
) ) {
651 return CKR_TEMPLATE_INCOMPLETE
;
654 /* in PKCS #11, Subject is a required field */
655 if ( !sftk_hasAttribute(object
,CKA_SUBJECT
) ) {
656 return CKR_TEMPLATE_INCOMPLETE
;
659 /* in PKCS #11, Issuer is a required field */
660 if ( !sftk_hasAttribute(object
,CKA_ISSUER
) ) {
661 return CKR_TEMPLATE_INCOMPLETE
;
664 /* in PKCS #11, Serial is a required field */
665 if ( !sftk_hasAttribute(object
,CKA_SERIAL_NUMBER
) ) {
666 return CKR_TEMPLATE_INCOMPLETE
;
669 /* add it to the object */
670 object
->objectInfo
= NULL
;
671 object
->infoFree
= (SFTKFree
) NULL
;
673 /* now just verify the required date fields */
674 crv
= sftk_defaultAttribute(object
, CKA_ID
, NULL
, 0);
675 if (crv
!= CKR_OK
) { return crv
; }
677 if (sftk_isTrue(object
,CKA_TOKEN
)) {
678 SFTKSlot
*slot
= session
->slot
;
679 SFTKDBHandle
*certHandle
= sftk_getCertDB(slot
);
681 if (certHandle
== NULL
) {
682 return CKR_TOKEN_WRITE_PROTECTED
;
685 crv
= sftkdb_write(certHandle
, object
, &object
->handle
);
686 sftk_freeDB(certHandle
);
694 * check the consistancy and initialize a Trust Object
697 sftk_handleTrustObject(SFTKSession
*session
,SFTKObject
*object
)
699 /* we can't store any certs private */
700 if (sftk_isTrue(object
,CKA_PRIVATE
)) {
701 return CKR_ATTRIBUTE_VALUE_INVALID
;
704 /* certificates must have a type */
705 if ( !sftk_hasAttribute(object
,CKA_ISSUER
) ) {
706 return CKR_TEMPLATE_INCOMPLETE
;
708 if ( !sftk_hasAttribute(object
,CKA_SERIAL_NUMBER
) ) {
709 return CKR_TEMPLATE_INCOMPLETE
;
711 if ( !sftk_hasAttribute(object
,CKA_CERT_SHA1_HASH
) ) {
712 return CKR_TEMPLATE_INCOMPLETE
;
714 if ( !sftk_hasAttribute(object
,CKA_CERT_MD5_HASH
) ) {
715 return CKR_TEMPLATE_INCOMPLETE
;
718 if (sftk_isTrue(object
,CKA_TOKEN
)) {
719 SFTKSlot
*slot
= session
->slot
;
720 SFTKDBHandle
*certHandle
= sftk_getCertDB(slot
);
723 if (certHandle
== NULL
) {
724 return CKR_TOKEN_WRITE_PROTECTED
;
727 crv
= sftkdb_write(certHandle
, object
, &object
->handle
);
728 sftk_freeDB(certHandle
);
736 * check the consistancy and initialize a Trust Object
739 sftk_handleSMimeObject(SFTKSession
*session
,SFTKObject
*object
)
742 /* we can't store any certs private */
743 if (sftk_isTrue(object
,CKA_PRIVATE
)) {
744 return CKR_ATTRIBUTE_VALUE_INVALID
;
747 /* certificates must have a type */
748 if ( !sftk_hasAttribute(object
,CKA_SUBJECT
) ) {
749 return CKR_TEMPLATE_INCOMPLETE
;
751 if ( !sftk_hasAttribute(object
,CKA_NETSCAPE_EMAIL
) ) {
752 return CKR_TEMPLATE_INCOMPLETE
;
755 if (sftk_isTrue(object
,CKA_TOKEN
)) {
756 SFTKSlot
*slot
= session
->slot
;
757 SFTKDBHandle
*certHandle
;
762 return CKR_SESSION_HANDLE_INVALID
;
765 certHandle
= sftk_getCertDB(slot
);
766 if (certHandle
== NULL
) {
767 return CKR_TOKEN_WRITE_PROTECTED
;
770 crv
= sftkdb_write(certHandle
, object
, &object
->handle
);
771 sftk_freeDB(certHandle
);
779 * check the consistancy and initialize a Trust Object
782 sftk_handleCrlObject(SFTKSession
*session
,SFTKObject
*object
)
785 /* we can't store any certs private */
786 if (sftk_isTrue(object
,CKA_PRIVATE
)) {
787 return CKR_ATTRIBUTE_VALUE_INVALID
;
790 /* certificates must have a type */
791 if ( !sftk_hasAttribute(object
,CKA_SUBJECT
) ) {
792 return CKR_TEMPLATE_INCOMPLETE
;
794 if ( !sftk_hasAttribute(object
,CKA_VALUE
) ) {
795 return CKR_TEMPLATE_INCOMPLETE
;
798 if (sftk_isTrue(object
,CKA_TOKEN
)) {
799 SFTKSlot
*slot
= session
->slot
;
800 SFTKDBHandle
*certHandle
= sftk_getCertDB(slot
);
803 if (certHandle
== NULL
) {
804 return CKR_TOKEN_WRITE_PROTECTED
;
807 crv
= sftkdb_write(certHandle
, object
, &object
->handle
);
808 sftk_freeDB(certHandle
);
816 * check the consistancy and initialize a Public Key Object
819 sftk_handlePublicKeyObject(SFTKSession
*session
, SFTKObject
*object
,
820 CK_KEY_TYPE key_type
)
822 CK_BBOOL encrypt
= CK_TRUE
;
823 CK_BBOOL recover
= CK_TRUE
;
824 CK_BBOOL wrap
= CK_TRUE
;
825 CK_BBOOL derive
= CK_FALSE
;
826 CK_BBOOL verify
= CK_TRUE
;
827 CK_ATTRIBUTE_TYPE pubKeyAttr
= CKA_VALUE
;
832 crv
= sftk_ConstrainAttribute(object
, CKA_MODULUS
,
833 RSA_MIN_MODULUS_BITS
, 0, 0);
837 crv
= sftk_ConstrainAttribute(object
, CKA_PUBLIC_EXPONENT
, 2, 0, 0);
841 pubKeyAttr
= CKA_MODULUS
;
844 crv
= sftk_ConstrainAttribute(object
, CKA_SUBPRIME
,
845 DSA_Q_BITS
, DSA_Q_BITS
, 0);
849 crv
= sftk_ConstrainAttribute(object
, CKA_PRIME
,
850 DSA_MIN_P_BITS
, DSA_MAX_P_BITS
, 64);
854 crv
= sftk_ConstrainAttribute(object
, CKA_BASE
, 1, DSA_MAX_P_BITS
, 0);
858 crv
= sftk_ConstrainAttribute(object
, CKA_VALUE
, 1, DSA_MAX_P_BITS
, 0);
867 crv
= sftk_ConstrainAttribute(object
, CKA_PRIME
,
868 DH_MIN_P_BITS
, DH_MAX_P_BITS
, 0);
872 crv
= sftk_ConstrainAttribute(object
, CKA_BASE
, 1, DH_MAX_P_BITS
, 0);
876 crv
= sftk_ConstrainAttribute(object
, CKA_VALUE
, 1, DH_MAX_P_BITS
, 0);
886 #ifdef NSS_ENABLE_ECC
888 if ( !sftk_hasAttribute(object
, CKA_EC_PARAMS
)) {
889 return CKR_TEMPLATE_INCOMPLETE
;
891 if ( !sftk_hasAttribute(object
, CKA_EC_POINT
)) {
892 return CKR_TEMPLATE_INCOMPLETE
;
894 pubKeyAttr
= CKA_EC_POINT
;
895 derive
= CK_TRUE
; /* for ECDH */
896 verify
= CK_TRUE
; /* for ECDSA */
901 #endif /* NSS_ENABLE_ECC */
903 return CKR_ATTRIBUTE_VALUE_INVALID
;
906 /* make sure the required fields exist */
907 crv
= sftk_defaultAttribute(object
,CKA_SUBJECT
,NULL
,0);
908 if (crv
!= CKR_OK
) return crv
;
909 crv
= sftk_defaultAttribute(object
,CKA_ENCRYPT
,&encrypt
,sizeof(CK_BBOOL
));
910 if (crv
!= CKR_OK
) return crv
;
911 crv
= sftk_defaultAttribute(object
,CKA_VERIFY
,&verify
,sizeof(CK_BBOOL
));
912 if (crv
!= CKR_OK
) return crv
;
913 crv
= sftk_defaultAttribute(object
,CKA_VERIFY_RECOVER
,
914 &recover
,sizeof(CK_BBOOL
));
915 if (crv
!= CKR_OK
) return crv
;
916 crv
= sftk_defaultAttribute(object
,CKA_WRAP
,&wrap
,sizeof(CK_BBOOL
));
917 if (crv
!= CKR_OK
) return crv
;
918 crv
= sftk_defaultAttribute(object
,CKA_DERIVE
,&derive
,sizeof(CK_BBOOL
));
919 if (crv
!= CKR_OK
) return crv
;
921 object
->objectInfo
= sftk_GetPubKey(object
,key_type
, &crv
);
922 if (object
->objectInfo
== NULL
) {
925 object
->infoFree
= (SFTKFree
) nsslowkey_DestroyPublicKey
;
927 if (sftk_isTrue(object
,CKA_TOKEN
)) {
928 SFTKSlot
*slot
= session
->slot
;
929 SFTKDBHandle
*certHandle
= sftk_getCertDB(slot
);
931 if (certHandle
== NULL
) {
932 return CKR_TOKEN_WRITE_PROTECTED
;
935 crv
= sftkdb_write(certHandle
, object
, &object
->handle
);
936 sftk_freeDB(certHandle
);
943 static NSSLOWKEYPrivateKey
*
944 sftk_mkPrivKey(SFTKObject
*object
,CK_KEY_TYPE key
, CK_RV
*rvp
);
947 * check the consistancy and initialize a Private Key Object
950 sftk_handlePrivateKeyObject(SFTKSession
*session
,SFTKObject
*object
,CK_KEY_TYPE key_type
)
952 CK_BBOOL cktrue
= CK_TRUE
;
953 CK_BBOOL encrypt
= CK_TRUE
;
954 CK_BBOOL sign
= CK_FALSE
;
955 CK_BBOOL recover
= CK_TRUE
;
956 CK_BBOOL wrap
= CK_TRUE
;
957 CK_BBOOL derive
= CK_TRUE
;
958 CK_BBOOL ckfalse
= CK_FALSE
;
964 if ( !sftk_hasAttribute(object
, CKA_MODULUS
)) {
965 return CKR_TEMPLATE_INCOMPLETE
;
967 if ( !sftk_hasAttribute(object
, CKA_PUBLIC_EXPONENT
)) {
968 return CKR_TEMPLATE_INCOMPLETE
;
970 if ( !sftk_hasAttribute(object
, CKA_PRIVATE_EXPONENT
)) {
971 return CKR_TEMPLATE_INCOMPLETE
;
973 if ( !sftk_hasAttribute(object
, CKA_PRIME_1
)) {
974 return CKR_TEMPLATE_INCOMPLETE
;
976 if ( !sftk_hasAttribute(object
, CKA_PRIME_2
)) {
977 return CKR_TEMPLATE_INCOMPLETE
;
979 if ( !sftk_hasAttribute(object
, CKA_EXPONENT_1
)) {
980 return CKR_TEMPLATE_INCOMPLETE
;
982 if ( !sftk_hasAttribute(object
, CKA_EXPONENT_2
)) {
983 return CKR_TEMPLATE_INCOMPLETE
;
985 if ( !sftk_hasAttribute(object
, CKA_COEFFICIENT
)) {
986 return CKR_TEMPLATE_INCOMPLETE
;
988 /* make sure Netscape DB attribute is set correctly */
989 crv
= sftk_Attribute2SSecItem(NULL
, &mod
, object
, CKA_MODULUS
);
990 if (crv
!= CKR_OK
) return crv
;
991 crv
= sftk_forceAttribute(object
, CKA_NETSCAPE_DB
,
992 sftk_item_expand(&mod
));
993 if (mod
.data
) PORT_Free(mod
.data
);
994 if (crv
!= CKR_OK
) return crv
;
1000 if ( !sftk_hasAttribute(object
, CKA_SUBPRIME
)) {
1001 return CKR_TEMPLATE_INCOMPLETE
;
1007 if ( !sftk_hasAttribute(object
, CKA_PRIME
)) {
1008 return CKR_TEMPLATE_INCOMPLETE
;
1010 if ( !sftk_hasAttribute(object
, CKA_BASE
)) {
1011 return CKR_TEMPLATE_INCOMPLETE
;
1013 if ( !sftk_hasAttribute(object
, CKA_VALUE
)) {
1014 return CKR_TEMPLATE_INCOMPLETE
;
1020 #ifdef NSS_ENABLE_ECC
1022 if ( !sftk_hasAttribute(object
, CKA_EC_PARAMS
)) {
1023 return CKR_TEMPLATE_INCOMPLETE
;
1025 if ( !sftk_hasAttribute(object
, CKA_VALUE
)) {
1026 return CKR_TEMPLATE_INCOMPLETE
;
1033 #endif /* NSS_ENABLE_ECC */
1035 return CKR_ATTRIBUTE_VALUE_INVALID
;
1037 crv
= sftk_defaultAttribute(object
,CKA_SUBJECT
,NULL
,0);
1038 if (crv
!= CKR_OK
) return crv
;
1039 crv
= sftk_defaultAttribute(object
,CKA_SENSITIVE
,&cktrue
,sizeof(CK_BBOOL
));
1040 if (crv
!= CKR_OK
) return crv
;
1041 crv
= sftk_defaultAttribute(object
,CKA_EXTRACTABLE
,&cktrue
,sizeof(CK_BBOOL
));
1042 if (crv
!= CKR_OK
) return crv
;
1043 crv
= sftk_defaultAttribute(object
,CKA_DECRYPT
,&encrypt
,sizeof(CK_BBOOL
));
1044 if (crv
!= CKR_OK
) return crv
;
1045 crv
= sftk_defaultAttribute(object
,CKA_SIGN
,&sign
,sizeof(CK_BBOOL
));
1046 if (crv
!= CKR_OK
) return crv
;
1047 crv
= sftk_defaultAttribute(object
,CKA_SIGN_RECOVER
,&recover
,
1049 if (crv
!= CKR_OK
) return crv
;
1050 crv
= sftk_defaultAttribute(object
,CKA_UNWRAP
,&wrap
,sizeof(CK_BBOOL
));
1051 if (crv
!= CKR_OK
) return crv
;
1052 crv
= sftk_defaultAttribute(object
,CKA_DERIVE
,&derive
,sizeof(CK_BBOOL
));
1053 if (crv
!= CKR_OK
) return crv
;
1054 /* the next two bits get modified only in the key gen and token cases */
1055 crv
= sftk_forceAttribute(object
,CKA_ALWAYS_SENSITIVE
,
1056 &ckfalse
,sizeof(CK_BBOOL
));
1057 if (crv
!= CKR_OK
) return crv
;
1058 crv
= sftk_forceAttribute(object
,CKA_NEVER_EXTRACTABLE
,
1059 &ckfalse
,sizeof(CK_BBOOL
));
1060 if (crv
!= CKR_OK
) return crv
;
1062 /* should we check the non-token RSA private keys? */
1064 if (sftk_isTrue(object
,CKA_TOKEN
)) {
1065 SFTKSlot
*slot
= session
->slot
;
1066 SFTKDBHandle
*keyHandle
= sftk_getKeyDB(slot
);
1069 if (keyHandle
== NULL
) {
1070 return CKR_TOKEN_WRITE_PROTECTED
;
1073 crv
= sftkdb_write(keyHandle
, object
, &object
->handle
);
1074 sftk_freeDB(keyHandle
);
1077 object
->objectInfo
= sftk_mkPrivKey(object
,key_type
,&crv
);
1078 if (object
->objectInfo
== NULL
) return crv
;
1079 object
->infoFree
= (SFTKFree
) nsslowkey_DestroyPrivateKey
;
1084 /* forward declare the DES formating function for handleSecretKey */
1085 void sftk_FormatDESKey(unsigned char *key
, int length
);
1087 /* Validate secret key data, and set defaults */
1089 validateSecretKey(SFTKSession
*session
, SFTKObject
*object
,
1090 CK_KEY_TYPE key_type
, PRBool isFIPS
)
1093 CK_BBOOL cktrue
= CK_TRUE
;
1094 CK_BBOOL ckfalse
= CK_FALSE
;
1095 SFTKAttribute
*attribute
= NULL
;
1096 unsigned long requiredLen
;
1098 crv
= sftk_defaultAttribute(object
,CKA_SENSITIVE
,
1099 isFIPS
?&cktrue
:&ckfalse
,sizeof(CK_BBOOL
));
1100 if (crv
!= CKR_OK
) return crv
;
1101 crv
= sftk_defaultAttribute(object
,CKA_EXTRACTABLE
,
1102 &cktrue
,sizeof(CK_BBOOL
));
1103 if (crv
!= CKR_OK
) return crv
;
1104 crv
= sftk_defaultAttribute(object
,CKA_ENCRYPT
,&cktrue
,sizeof(CK_BBOOL
));
1105 if (crv
!= CKR_OK
) return crv
;
1106 crv
= sftk_defaultAttribute(object
,CKA_DECRYPT
,&cktrue
,sizeof(CK_BBOOL
));
1107 if (crv
!= CKR_OK
) return crv
;
1108 crv
= sftk_defaultAttribute(object
,CKA_SIGN
,&ckfalse
,sizeof(CK_BBOOL
));
1109 if (crv
!= CKR_OK
) return crv
;
1110 crv
= sftk_defaultAttribute(object
,CKA_VERIFY
,&ckfalse
,sizeof(CK_BBOOL
));
1111 if (crv
!= CKR_OK
) return crv
;
1112 crv
= sftk_defaultAttribute(object
,CKA_WRAP
,&cktrue
,sizeof(CK_BBOOL
));
1113 if (crv
!= CKR_OK
) return crv
;
1114 crv
= sftk_defaultAttribute(object
,CKA_UNWRAP
,&cktrue
,sizeof(CK_BBOOL
));
1115 if (crv
!= CKR_OK
) return crv
;
1117 if ( !sftk_hasAttribute(object
, CKA_VALUE
)) {
1118 return CKR_TEMPLATE_INCOMPLETE
;
1120 /* the next two bits get modified only in the key gen and token cases */
1121 crv
= sftk_forceAttribute(object
,CKA_ALWAYS_SENSITIVE
,
1122 &ckfalse
,sizeof(CK_BBOOL
));
1123 if (crv
!= CKR_OK
) return crv
;
1124 crv
= sftk_forceAttribute(object
,CKA_NEVER_EXTRACTABLE
,
1125 &ckfalse
,sizeof(CK_BBOOL
));
1126 if (crv
!= CKR_OK
) return crv
;
1128 /* some types of keys have a value length */
1131 /* force CKA_VALUE_LEN to be set */
1132 case CKK_GENERIC_SECRET
:
1135 #if NSS_SOFTOKEN_DOES_RC5
1138 #ifdef NSS_SOFTOKEN_DOES_CAST
1143 #if NSS_SOFTOKEN_DOES_IDEA
1146 attribute
= sftk_FindAttribute(object
,CKA_VALUE
);
1147 /* shouldn't happen */
1148 if (attribute
== NULL
) return CKR_TEMPLATE_INCOMPLETE
;
1149 crv
= sftk_forceAttribute(object
, CKA_VALUE_LEN
,
1150 &attribute
->attrib
.ulValueLen
, sizeof(CK_ULONG
));
1151 sftk_FreeAttribute(attribute
);
1153 /* force the value to have the correct parity */
1158 attribute
= sftk_FindAttribute(object
,CKA_VALUE
);
1159 /* shouldn't happen */
1160 if (attribute
== NULL
)
1161 return CKR_TEMPLATE_INCOMPLETE
;
1162 requiredLen
= sftk_MapKeySize(key_type
);
1163 if (attribute
->attrib
.ulValueLen
!= requiredLen
) {
1164 sftk_FreeAttribute(attribute
);
1165 return CKR_KEY_SIZE_RANGE
;
1167 sftk_FormatDESKey((unsigned char*)attribute
->attrib
.pValue
,
1168 attribute
->attrib
.ulValueLen
);
1169 sftk_FreeAttribute(attribute
);
1179 * check the consistancy and initialize a Secret Key Object
1182 sftk_handleSecretKeyObject(SFTKSession
*session
,SFTKObject
*object
,
1183 CK_KEY_TYPE key_type
, PRBool isFIPS
)
1187 /* First validate and set defaults */
1188 crv
= validateSecretKey(session
, object
, key_type
, isFIPS
);
1189 if (crv
!= CKR_OK
) goto loser
;
1191 /* If the object is a TOKEN object, store in the database */
1192 if (sftk_isTrue(object
,CKA_TOKEN
)) {
1193 SFTKSlot
*slot
= session
->slot
;
1194 SFTKDBHandle
*keyHandle
= sftk_getKeyDB(slot
);
1197 if (keyHandle
== NULL
) {
1198 return CKR_TOKEN_WRITE_PROTECTED
;
1201 crv
= sftkdb_write(keyHandle
, object
, &object
->handle
);
1202 sftk_freeDB(keyHandle
);
1212 * check the consistancy and initialize a Key Object
1215 sftk_handleKeyObject(SFTKSession
*session
, SFTKObject
*object
)
1217 SFTKAttribute
*attribute
;
1218 CK_KEY_TYPE key_type
;
1219 CK_BBOOL cktrue
= CK_TRUE
;
1220 CK_BBOOL ckfalse
= CK_FALSE
;
1223 /* verify the required fields */
1224 if ( !sftk_hasAttribute(object
,CKA_KEY_TYPE
) ) {
1225 return CKR_TEMPLATE_INCOMPLETE
;
1228 /* now verify the common fields */
1229 crv
= sftk_defaultAttribute(object
,CKA_ID
,NULL
,0);
1230 if (crv
!= CKR_OK
) return crv
;
1231 crv
= sftk_defaultAttribute(object
,CKA_START_DATE
,NULL
,0);
1232 if (crv
!= CKR_OK
) return crv
;
1233 crv
= sftk_defaultAttribute(object
,CKA_END_DATE
,NULL
,0);
1234 if (crv
!= CKR_OK
) return crv
;
1235 /* CKA_DERIVE is common to all keys, but it's default value is
1237 crv
= sftk_defaultAttribute(object
,CKA_LOCAL
,&ckfalse
,sizeof(CK_BBOOL
));
1238 if (crv
!= CKR_OK
) return crv
;
1240 /* get the key type */
1241 attribute
= sftk_FindAttribute(object
,CKA_KEY_TYPE
);
1243 return CKR_ATTRIBUTE_VALUE_INVALID
;
1245 key_type
= *(CK_KEY_TYPE
*)attribute
->attrib
.pValue
;
1246 sftk_FreeAttribute(attribute
);
1248 switch (object
->objclass
) {
1249 case CKO_PUBLIC_KEY
:
1250 return sftk_handlePublicKeyObject(session
,object
,key_type
);
1251 case CKO_PRIVATE_KEY
:
1252 return sftk_handlePrivateKeyObject(session
,object
,key_type
);
1253 case CKO_SECRET_KEY
:
1254 /* make sure the required fields exist */
1255 return sftk_handleSecretKeyObject(session
,object
,key_type
,
1256 (PRBool
)(session
->slot
->slotID
== FIPS_SLOT_ID
));
1260 return CKR_ATTRIBUTE_VALUE_INVALID
;
1264 * check the consistancy and Verify a DSA Parameter Object
1267 sftk_handleDSAParameterObject(SFTKSession
*session
, SFTKObject
*object
)
1269 SFTKAttribute
*primeAttr
= NULL
;
1270 SFTKAttribute
*subPrimeAttr
= NULL
;
1271 SFTKAttribute
*baseAttr
= NULL
;
1272 SFTKAttribute
*seedAttr
= NULL
;
1273 SFTKAttribute
*hAttr
= NULL
;
1274 SFTKAttribute
*attribute
;
1275 CK_RV crv
= CKR_TEMPLATE_INCOMPLETE
;
1277 PQGVerify vfy
, *verify
= NULL
;
1278 SECStatus result
,rv
;
1280 primeAttr
= sftk_FindAttribute(object
,CKA_PRIME
);
1281 if (primeAttr
== NULL
) goto loser
;
1282 params
.prime
.data
= primeAttr
->attrib
.pValue
;
1283 params
.prime
.len
= primeAttr
->attrib
.ulValueLen
;
1285 subPrimeAttr
= sftk_FindAttribute(object
,CKA_SUBPRIME
);
1286 if (subPrimeAttr
== NULL
) goto loser
;
1287 params
.subPrime
.data
= subPrimeAttr
->attrib
.pValue
;
1288 params
.subPrime
.len
= subPrimeAttr
->attrib
.ulValueLen
;
1290 baseAttr
= sftk_FindAttribute(object
,CKA_BASE
);
1291 if (baseAttr
== NULL
) goto loser
;
1292 params
.base
.data
= baseAttr
->attrib
.pValue
;
1293 params
.base
.len
= baseAttr
->attrib
.ulValueLen
;
1295 attribute
= sftk_FindAttribute(object
, CKA_NETSCAPE_PQG_COUNTER
);
1296 if (attribute
!= NULL
) {
1297 vfy
.counter
= *(CK_ULONG
*) attribute
->attrib
.pValue
;
1298 sftk_FreeAttribute(attribute
);
1300 seedAttr
= sftk_FindAttribute(object
, CKA_NETSCAPE_PQG_SEED
);
1301 if (seedAttr
== NULL
) goto loser
;
1302 vfy
.seed
.data
= seedAttr
->attrib
.pValue
;
1303 vfy
.seed
.len
= seedAttr
->attrib
.ulValueLen
;
1305 hAttr
= sftk_FindAttribute(object
, CKA_NETSCAPE_PQG_H
);
1306 if (hAttr
== NULL
) goto loser
;
1307 vfy
.h
.data
= hAttr
->attrib
.pValue
;
1308 vfy
.h
.len
= hAttr
->attrib
.ulValueLen
;
1313 crv
= CKR_FUNCTION_FAILED
;
1314 rv
= PQG_VerifyParams(¶ms
,verify
,&result
);
1315 if (rv
== SECSuccess
) {
1316 crv
= (result
== SECSuccess
) ? CKR_OK
: CKR_ATTRIBUTE_VALUE_INVALID
;
1320 if (hAttr
) sftk_FreeAttribute(hAttr
);
1321 if (seedAttr
) sftk_FreeAttribute(seedAttr
);
1322 if (baseAttr
) sftk_FreeAttribute(baseAttr
);
1323 if (subPrimeAttr
) sftk_FreeAttribute(subPrimeAttr
);
1324 if (primeAttr
) sftk_FreeAttribute(primeAttr
);
1330 * check the consistancy and initialize a Key Parameter Object
1333 sftk_handleKeyParameterObject(SFTKSession
*session
, SFTKObject
*object
)
1335 SFTKAttribute
*attribute
;
1336 CK_KEY_TYPE key_type
;
1337 CK_BBOOL ckfalse
= CK_FALSE
;
1340 /* verify the required fields */
1341 if ( !sftk_hasAttribute(object
,CKA_KEY_TYPE
) ) {
1342 return CKR_TEMPLATE_INCOMPLETE
;
1345 /* now verify the common fields */
1346 crv
= sftk_defaultAttribute(object
,CKA_LOCAL
,&ckfalse
,sizeof(CK_BBOOL
));
1347 if (crv
!= CKR_OK
) return crv
;
1349 /* get the key type */
1350 attribute
= sftk_FindAttribute(object
,CKA_KEY_TYPE
);
1352 return CKR_ATTRIBUTE_VALUE_INVALID
;
1354 key_type
= *(CK_KEY_TYPE
*)attribute
->attrib
.pValue
;
1355 sftk_FreeAttribute(attribute
);
1359 return sftk_handleDSAParameterObject(session
,object
);
1364 return CKR_KEY_TYPE_INCONSISTENT
;
1368 * Handle Object does all the object consistancy checks, automatic attribute
1369 * generation, attribute defaulting, etc. If handleObject succeeds, the object
1370 * will be assigned an object handle, and the object installed in the session
1371 * or stored in the DB.
1374 sftk_handleObject(SFTKObject
*object
, SFTKSession
*session
)
1376 SFTKSlot
*slot
= session
->slot
;
1377 SFTKAttribute
*attribute
;
1378 SFTKObject
*duplicateObject
= NULL
;
1379 CK_OBJECT_HANDLE handle
;
1380 CK_BBOOL ckfalse
= CK_FALSE
;
1381 CK_BBOOL cktrue
= CK_TRUE
;
1384 /* make sure all the base object types are defined. If not set the
1386 crv
= sftk_defaultAttribute(object
,CKA_TOKEN
,&ckfalse
,sizeof(CK_BBOOL
));
1387 if (crv
!= CKR_OK
) return crv
;
1388 crv
= sftk_defaultAttribute(object
,CKA_PRIVATE
,&ckfalse
,sizeof(CK_BBOOL
));
1389 if (crv
!= CKR_OK
) return crv
;
1390 crv
= sftk_defaultAttribute(object
,CKA_LABEL
,NULL
,0);
1391 if (crv
!= CKR_OK
) return crv
;
1392 crv
= sftk_defaultAttribute(object
,CKA_MODIFIABLE
,&cktrue
,sizeof(CK_BBOOL
));
1393 if (crv
!= CKR_OK
) return crv
;
1395 /* don't create a private object if we aren't logged in */
1396 if ((!slot
->isLoggedIn
) && (slot
->needLogin
) &&
1397 (sftk_isTrue(object
,CKA_PRIVATE
))) {
1398 return CKR_USER_NOT_LOGGED_IN
;
1402 if (((session
->info
.flags
& CKF_RW_SESSION
) == 0) &&
1403 (sftk_isTrue(object
,CKA_TOKEN
))) {
1404 return CKR_SESSION_READ_ONLY
;
1407 /* Assign a unique SESSION object handle to every new object,
1408 * whether it is a session object or a token object.
1409 * At this point, all new objects are structured as session objects.
1410 * Objects with the CKA_TOKEN attribute true will be turned into
1411 * token objects and will have a token object handle assigned to
1412 * them by a call to sftk_mkHandle in the handler for each object
1413 * class, invoked below.
1415 * It may be helpful to note/remember that
1416 * sftk_narrowToXxxObject uses sftk_isToken,
1417 * sftk_isToken examines the sign bit of the object's handle, but
1418 * sftk_isTrue(...,CKA_TOKEN) examines the CKA_TOKEN attribute.
1421 PRUint32 wrappedAround
;
1423 duplicateObject
= NULL
;
1424 PZ_Lock(slot
->objectLock
);
1425 wrappedAround
= slot
->sessionObjectHandleCount
& SFTK_TOKEN_MASK
;
1426 handle
= slot
->sessionObjectHandleCount
& ~SFTK_TOKEN_MASK
;
1427 if (!handle
) /* don't allow zero handle */
1428 handle
= minSessionObjectHandle
;
1429 slot
->sessionObjectHandleCount
= (handle
+ 1U) | wrappedAround
;
1430 /* Is there already a session object with this handle? */
1431 if (wrappedAround
) {
1432 sftkqueue_find(duplicateObject
, handle
, slot
->sessObjHashTable
, \
1433 slot
->sessObjHashSize
);
1435 PZ_Unlock(slot
->objectLock
);
1436 } while (duplicateObject
!= NULL
);
1437 object
->handle
= handle
;
1439 /* get the object class */
1440 attribute
= sftk_FindAttribute(object
,CKA_CLASS
);
1441 if (attribute
== NULL
) {
1442 return CKR_TEMPLATE_INCOMPLETE
;
1444 object
->objclass
= *(CK_OBJECT_CLASS
*)attribute
->attrib
.pValue
;
1445 sftk_FreeAttribute(attribute
);
1447 /* Now handle the specific object class.
1448 * At this point, all objects are session objects, and the session
1449 * number must be passed to the object class handlers.
1451 switch (object
->objclass
) {
1453 crv
= sftk_handleDataObject(session
,object
);
1455 case CKO_CERTIFICATE
:
1456 crv
= sftk_handleCertObject(session
,object
);
1458 case CKO_NETSCAPE_TRUST
:
1459 crv
= sftk_handleTrustObject(session
,object
);
1461 case CKO_NETSCAPE_CRL
:
1462 crv
= sftk_handleCrlObject(session
,object
);
1464 case CKO_NETSCAPE_SMIME
:
1465 crv
= sftk_handleSMimeObject(session
,object
);
1467 case CKO_PRIVATE_KEY
:
1468 case CKO_PUBLIC_KEY
:
1469 case CKO_SECRET_KEY
:
1470 crv
= sftk_handleKeyObject(session
,object
);
1472 case CKO_KG_PARAMETERS
:
1473 crv
= sftk_handleKeyParameterObject(session
,object
);
1476 crv
= CKR_ATTRIBUTE_VALUE_INVALID
;
1480 /* can't fail from here on out unless the pk_handlXXX functions have
1481 * failed the request */
1482 if (crv
!= CKR_OK
) {
1486 /* Now link the object into the slot and session structures.
1487 * If the object has a true CKA_TOKEN attribute, the above object
1488 * class handlers will have set the sign bit in the object handle,
1489 * causing the following test to be true.
1491 if (sftk_isToken(object
->handle
)) {
1492 sftk_convertSessionToToken(object
);
1494 object
->slot
= slot
;
1495 sftk_AddObject(session
,object
);
1502 * ******************** Public Key Utilities ***************************
1504 /* Generate a low public key structure from an object */
1505 NSSLOWKEYPublicKey
*sftk_GetPubKey(SFTKObject
*object
,CK_KEY_TYPE key_type
,
1508 NSSLOWKEYPublicKey
*pubKey
;
1512 if (object
->objclass
!= CKO_PUBLIC_KEY
) {
1513 *crvp
= CKR_KEY_TYPE_INCONSISTENT
;
1517 if (sftk_isToken(object
->handle
)) {
1518 /* ferret out the token object handle */
1521 /* If we already have a key, use it */
1522 if (object
->objectInfo
) {
1524 return (NSSLOWKEYPublicKey
*)object
->objectInfo
;
1527 /* allocate the structure */
1528 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1529 if (arena
== NULL
) {
1530 *crvp
= CKR_HOST_MEMORY
;
1534 pubKey
= (NSSLOWKEYPublicKey
*)
1535 PORT_ArenaAlloc(arena
,sizeof(NSSLOWKEYPublicKey
));
1536 if (pubKey
== NULL
) {
1537 PORT_FreeArena(arena
,PR_FALSE
);
1538 *crvp
= CKR_HOST_MEMORY
;
1542 /* fill in the structure */
1543 pubKey
->arena
= arena
;
1546 pubKey
->keyType
= NSSLOWKEYRSAKey
;
1547 crv
= sftk_Attribute2SSecItem(arena
,&pubKey
->u
.rsa
.modulus
,
1548 object
,CKA_MODULUS
);
1549 if (crv
!= CKR_OK
) break;
1550 crv
= sftk_Attribute2SSecItem(arena
,&pubKey
->u
.rsa
.publicExponent
,
1551 object
,CKA_PUBLIC_EXPONENT
);
1554 pubKey
->keyType
= NSSLOWKEYDSAKey
;
1555 crv
= sftk_Attribute2SSecItem(arena
,&pubKey
->u
.dsa
.params
.prime
,
1557 if (crv
!= CKR_OK
) break;
1558 crv
= sftk_Attribute2SSecItem(arena
,&pubKey
->u
.dsa
.params
.subPrime
,
1559 object
,CKA_SUBPRIME
);
1560 if (crv
!= CKR_OK
) break;
1561 crv
= sftk_Attribute2SSecItem(arena
,&pubKey
->u
.dsa
.params
.base
,
1563 if (crv
!= CKR_OK
) break;
1564 crv
= sftk_Attribute2SSecItem(arena
,&pubKey
->u
.dsa
.publicValue
,
1568 pubKey
->keyType
= NSSLOWKEYDHKey
;
1569 crv
= sftk_Attribute2SSecItem(arena
,&pubKey
->u
.dh
.prime
,
1571 if (crv
!= CKR_OK
) break;
1572 crv
= sftk_Attribute2SSecItem(arena
,&pubKey
->u
.dh
.base
,
1574 if (crv
!= CKR_OK
) break;
1575 crv
= sftk_Attribute2SSecItem(arena
,&pubKey
->u
.dh
.publicValue
,
1578 #ifdef NSS_ENABLE_ECC
1580 pubKey
->keyType
= NSSLOWKEYECKey
;
1581 crv
= sftk_Attribute2SSecItem(arena
,
1582 &pubKey
->u
.ec
.ecParams
.DEREncoding
,
1583 object
,CKA_EC_PARAMS
);
1584 if (crv
!= CKR_OK
) break;
1586 /* Fill out the rest of the ecParams structure
1587 * based on the encoded params
1589 if (EC_FillParams(arena
, &pubKey
->u
.ec
.ecParams
.DEREncoding
,
1590 &pubKey
->u
.ec
.ecParams
) != SECSuccess
) {
1591 crv
= CKR_DOMAIN_PARAMS_INVALID
;
1595 crv
= sftk_Attribute2SSecItem(arena
,&pubKey
->u
.ec
.publicValue
,
1596 object
,CKA_EC_POINT
);
1598 #endif /* NSS_ENABLE_ECC */
1600 crv
= CKR_KEY_TYPE_INCONSISTENT
;
1604 if (crv
!= CKR_OK
) {
1605 PORT_FreeArena(arena
,PR_FALSE
);
1609 object
->objectInfo
= pubKey
;
1610 object
->infoFree
= (SFTKFree
) nsslowkey_DestroyPublicKey
;
1614 /* make a private key from a verified object */
1615 static NSSLOWKEYPrivateKey
*
1616 sftk_mkPrivKey(SFTKObject
*object
, CK_KEY_TYPE key_type
, CK_RV
*crvp
)
1618 NSSLOWKEYPrivateKey
*privKey
;
1619 SFTKItemTemplate itemTemplate
[SFTK_MAX_ITEM_TEMPLATE
];
1620 int itemTemplateCount
= 0;
1625 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1626 if (arena
== NULL
) {
1627 *crvp
= CKR_HOST_MEMORY
;
1631 privKey
= (NSSLOWKEYPrivateKey
*)
1632 PORT_ArenaZAlloc(arena
,sizeof(NSSLOWKEYPrivateKey
));
1633 if (privKey
== NULL
) {
1634 PORT_FreeArena(arena
,PR_FALSE
);
1635 *crvp
= CKR_HOST_MEMORY
;
1639 /* in future this would be a switch on key_type */
1640 privKey
->arena
= arena
;
1643 privKey
->keyType
= NSSLOWKEYRSAKey
;
1645 SFTK_SET_ITEM_TEMPLATE(itemTemplate
, itemTemplateCount
,
1646 &privKey
->u
.rsa
.modulus
,CKA_MODULUS
);
1647 itemTemplateCount
++;
1648 SFTK_SET_ITEM_TEMPLATE(itemTemplate
, itemTemplateCount
,
1649 &privKey
->u
.rsa
.publicExponent
, CKA_PUBLIC_EXPONENT
);
1650 itemTemplateCount
++;
1651 SFTK_SET_ITEM_TEMPLATE(itemTemplate
, itemTemplateCount
,
1652 &privKey
->u
.rsa
.privateExponent
, CKA_PRIVATE_EXPONENT
);
1653 itemTemplateCount
++;
1654 SFTK_SET_ITEM_TEMPLATE(itemTemplate
, itemTemplateCount
,
1655 &privKey
->u
.rsa
.prime1
, CKA_PRIME_1
);
1656 itemTemplateCount
++;
1657 SFTK_SET_ITEM_TEMPLATE(itemTemplate
, itemTemplateCount
,
1658 &privKey
->u
.rsa
.prime2
, CKA_PRIME_2
);
1659 itemTemplateCount
++;
1660 SFTK_SET_ITEM_TEMPLATE(itemTemplate
, itemTemplateCount
,
1661 &privKey
->u
.rsa
.exponent1
, CKA_EXPONENT_1
);
1662 itemTemplateCount
++;
1663 SFTK_SET_ITEM_TEMPLATE(itemTemplate
, itemTemplateCount
,
1664 &privKey
->u
.rsa
.exponent2
, CKA_EXPONENT_2
);
1665 itemTemplateCount
++;
1666 SFTK_SET_ITEM_TEMPLATE(itemTemplate
, itemTemplateCount
,
1667 &privKey
->u
.rsa
.coefficient
, CKA_COEFFICIENT
);
1668 itemTemplateCount
++;
1669 rv
= DER_SetUInteger(privKey
->arena
, &privKey
->u
.rsa
.version
,
1670 NSSLOWKEY_PRIVATE_KEY_INFO_VERSION
);
1671 if (rv
!= SECSuccess
) crv
= CKR_HOST_MEMORY
;
1675 privKey
->keyType
= NSSLOWKEYDSAKey
;
1676 SFTK_SET_ITEM_TEMPLATE(itemTemplate
, itemTemplateCount
,
1677 &privKey
->u
.dsa
.params
.prime
, CKA_PRIME
);
1678 itemTemplateCount
++;
1679 SFTK_SET_ITEM_TEMPLATE(itemTemplate
, itemTemplateCount
,
1680 &privKey
->u
.dsa
.params
.subPrime
, CKA_SUBPRIME
);
1681 itemTemplateCount
++;
1682 SFTK_SET_ITEM_TEMPLATE(itemTemplate
, itemTemplateCount
,
1683 &privKey
->u
.dsa
.params
.base
, CKA_BASE
);
1684 itemTemplateCount
++;
1685 SFTK_SET_ITEM_TEMPLATE(itemTemplate
, itemTemplateCount
,
1686 &privKey
->u
.dsa
.privateValue
, CKA_VALUE
);
1687 itemTemplateCount
++;
1688 /* privKey was zero'd so public value is already set to NULL, 0
1689 * if we don't set it explicitly */
1693 privKey
->keyType
= NSSLOWKEYDHKey
;
1694 SFTK_SET_ITEM_TEMPLATE(itemTemplate
, itemTemplateCount
,
1695 &privKey
->u
.dh
.prime
, CKA_PRIME
);
1696 itemTemplateCount
++;
1697 SFTK_SET_ITEM_TEMPLATE(itemTemplate
, itemTemplateCount
,
1698 &privKey
->u
.dh
.base
, CKA_BASE
);
1699 itemTemplateCount
++;
1700 SFTK_SET_ITEM_TEMPLATE(itemTemplate
, itemTemplateCount
,
1701 &privKey
->u
.dh
.privateValue
, CKA_VALUE
);
1702 itemTemplateCount
++;
1703 /* privKey was zero'd so public value is already set to NULL, 0
1704 * if we don't set it explicitly */
1707 #ifdef NSS_ENABLE_ECC
1709 privKey
->keyType
= NSSLOWKEYECKey
;
1710 crv
= sftk_Attribute2SSecItem(arena
,
1711 &privKey
->u
.ec
.ecParams
.DEREncoding
,
1712 object
,CKA_EC_PARAMS
);
1713 if (crv
!= CKR_OK
) break;
1715 /* Fill out the rest of the ecParams structure
1716 * based on the encoded params
1718 if (EC_FillParams(arena
, &privKey
->u
.ec
.ecParams
.DEREncoding
,
1719 &privKey
->u
.ec
.ecParams
) != SECSuccess
) {
1720 crv
= CKR_DOMAIN_PARAMS_INVALID
;
1723 crv
= sftk_Attribute2SSecItem(arena
,&privKey
->u
.ec
.privateValue
,
1725 if (crv
!= CKR_OK
) break;
1727 if (sftk_hasAttribute(object
, CKA_NETSCAPE_DB
)) {
1728 crv
= sftk_Attribute2SSecItem(arena
, &privKey
->u
.ec
.publicValue
,
1729 object
, CKA_NETSCAPE_DB
);
1730 if (crv
!= CKR_OK
) break;
1731 /* privKey was zero'd so public value is already set to NULL, 0
1732 * if we don't set it explicitly */
1734 rv
= DER_SetUInteger(privKey
->arena
, &privKey
->u
.ec
.version
,
1735 NSSLOWKEY_EC_PRIVATE_KEY_VERSION
);
1736 if (rv
!= SECSuccess
) crv
= CKR_HOST_MEMORY
;
1738 #endif /* NSS_ENABLE_ECC */
1741 crv
= CKR_KEY_TYPE_INCONSISTENT
;
1744 if (crv
== CKR_OK
&& itemTemplateCount
!= 0) {
1745 PORT_Assert(itemTemplateCount
> 0);
1746 PORT_Assert(itemTemplateCount
<= SFTK_MAX_ITEM_TEMPLATE
);
1747 crv
= sftk_MultipleAttribute2SecItem(arena
, object
, itemTemplate
,
1751 if (crv
!= CKR_OK
) {
1752 PORT_FreeArena(arena
,PR_FALSE
);
1759 /* Generate a low private key structure from an object */
1760 NSSLOWKEYPrivateKey
*
1761 sftk_GetPrivKey(SFTKObject
*object
,CK_KEY_TYPE key_type
, CK_RV
*crvp
)
1763 NSSLOWKEYPrivateKey
*priv
= NULL
;
1765 if (object
->objclass
!= CKO_PRIVATE_KEY
) {
1766 *crvp
= CKR_KEY_TYPE_INCONSISTENT
;
1769 if (object
->objectInfo
) {
1771 return (NSSLOWKEYPrivateKey
*)object
->objectInfo
;
1774 priv
= sftk_mkPrivKey(object
, key_type
, crvp
);
1775 object
->objectInfo
= priv
;
1776 object
->infoFree
= (SFTKFree
) nsslowkey_DestroyPrivateKey
;
1781 **************************** Symetric Key utils ************************
1784 * set the DES key with parity bits correctly
1787 sftk_FormatDESKey(unsigned char *key
, int length
)
1791 /* format the des key */
1792 for (i
=0; i
< length
; i
++) {
1793 key
[i
] = parityTable
[key
[i
]>>1];
1798 * check a des key (des2 or des3 subkey) for weak keys.
1801 sftk_CheckDESKey(unsigned char *key
)
1805 /* format the des key with parity */
1806 sftk_FormatDESKey(key
, 8);
1808 for (i
=0; i
< sftk_desWeakTableSize
; i
++) {
1809 if (PORT_Memcmp(key
,sftk_desWeakTable
[i
],8) == 0) {
1817 * check if a des or triple des key is weak.
1820 sftk_IsWeakKey(unsigned char *key
,CK_KEY_TYPE key_type
)
1825 return sftk_CheckDESKey(key
);
1826 case CKM_DES2_KEY_GEN
:
1827 if (sftk_CheckDESKey(key
)) return PR_TRUE
;
1828 return sftk_CheckDESKey(&key
[8]);
1829 case CKM_DES3_KEY_GEN
:
1830 if (sftk_CheckDESKey(key
)) return PR_TRUE
;
1831 if (sftk_CheckDESKey(&key
[8])) return PR_TRUE
;
1832 return sftk_CheckDESKey(&key
[16]);
1840 /**********************************************************************
1842 * Start of PKCS 11 functions
1844 **********************************************************************/
1847 /* return the function list */
1848 CK_RV
NSC_GetFunctionList(CK_FUNCTION_LIST_PTR
*pFunctionList
)
1852 *pFunctionList
= (CK_FUNCTION_LIST_PTR
) &sftk_funcList
;
1856 /* return the function list */
1857 CK_RV
C_GetFunctionList(CK_FUNCTION_LIST_PTR
*pFunctionList
)
1861 return NSC_GetFunctionList(pFunctionList
);
1865 sftk_HashNumber(const void *key
)
1867 return (PLHashNumber
) key
;
1871 * eventually I'd like to expunge all occurances of XXX_SLOT_ID and
1872 * just go with the info in the slot. This is one place, however,
1873 * where it might be a little difficult.
1876 sftk_getDefTokName(CK_SLOT_ID slotID
)
1878 static char buf
[33];
1881 case NETSCAPE_SLOT_ID
:
1882 return "NSS Generic Crypto Services ";
1883 case PRIVATE_KEY_SLOT_ID
:
1884 return "NSS Certificate DB ";
1886 return "NSS FIPS 140-2 Certificate DB ";
1890 sprintf(buf
,"NSS Application Token %08x ",(unsigned int) slotID
);
1895 sftk_getDefSlotName(CK_SLOT_ID slotID
)
1897 static char buf
[65];
1900 case NETSCAPE_SLOT_ID
:
1902 "NSS Internal Cryptographic Services ";
1903 case PRIVATE_KEY_SLOT_ID
:
1905 "NSS User Private Key and Certificate Services ";
1908 "NSS FIPS 140-2 User Private Key Services ";
1913 "NSS Application Slot %08x ",
1914 (unsigned int) slotID
);
1918 static CK_ULONG nscSlotCount
[2] = {0 , 0};
1919 static CK_SLOT_ID_PTR nscSlotList
[2] = {NULL
, NULL
};
1920 static CK_ULONG nscSlotListSize
[2] = {0, 0};
1921 static PLHashTable
*nscSlotHashTable
[2] = {NULL
, NULL
};
1924 sftk_GetModuleIndex(CK_SLOT_ID slotID
)
1926 if ((slotID
== FIPS_SLOT_ID
) || (slotID
>= SFTK_MIN_FIPS_USER_SLOT_ID
)) {
1927 return NSC_FIPS_MODULE
;
1929 return NSC_NON_FIPS_MODULE
;
1932 /* look up a slot structure from the ID (used to be a macro when we only
1934 /* if all is true, return the slot even if it has been 'unloaded' */
1935 /* if all is false, only return the slots which are present */
1937 sftk_SlotFromID(CK_SLOT_ID slotID
, PRBool all
)
1940 int index
= sftk_GetModuleIndex(slotID
);
1942 if (nscSlotHashTable
[index
] == NULL
) return NULL
;
1943 slot
= (SFTKSlot
*)PL_HashTableLookupConst(nscSlotHashTable
[index
],
1945 /* cleared slots shouldn't 'show up' */
1946 if (slot
&& !all
&& !slot
->present
) slot
= NULL
;
1951 sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle
)
1953 CK_ULONG slotIDIndex
= (handle
>> 24) & 0x7f;
1954 CK_ULONG moduleIndex
= (handle
>> 31) & 1;
1956 if (slotIDIndex
>= nscSlotCount
[moduleIndex
]) {
1960 return sftk_SlotFromID(nscSlotList
[moduleIndex
][slotIDIndex
], PR_FALSE
);
1964 sftk_RegisterSlot(SFTKSlot
*slot
, int moduleIndex
)
1969 index
= sftk_GetModuleIndex(slot
->slotID
);
1971 /* make sure the slotID for this module is valid */
1972 if (moduleIndex
!= index
) {
1973 return CKR_SLOT_ID_INVALID
;
1976 if (nscSlotList
[index
] == NULL
) {
1977 nscSlotListSize
[index
] = NSC_SLOT_LIST_BLOCK_SIZE
;
1978 nscSlotList
[index
] = (CK_SLOT_ID
*)
1979 PORT_ZAlloc(nscSlotListSize
[index
]*sizeof(CK_SLOT_ID
));
1980 if (nscSlotList
[index
] == NULL
) {
1981 return CKR_HOST_MEMORY
;
1984 if (nscSlotCount
[index
] >= nscSlotListSize
[index
]) {
1985 CK_SLOT_ID
* oldNscSlotList
= nscSlotList
[index
];
1986 CK_ULONG oldNscSlotListSize
= nscSlotListSize
[index
];
1987 nscSlotListSize
[index
] += NSC_SLOT_LIST_BLOCK_SIZE
;
1988 nscSlotList
[index
] = (CK_SLOT_ID
*) PORT_Realloc(oldNscSlotList
,
1989 nscSlotListSize
[index
]*sizeof(CK_SLOT_ID
));
1990 if (nscSlotList
[index
] == NULL
) {
1991 nscSlotList
[index
] = oldNscSlotList
;
1992 nscSlotListSize
[index
] = oldNscSlotListSize
;
1993 return CKR_HOST_MEMORY
;
1997 if (nscSlotHashTable
[index
] == NULL
) {
1998 nscSlotHashTable
[index
] = PL_NewHashTable(64,sftk_HashNumber
,
1999 PL_CompareValues
, PL_CompareValues
, NULL
, 0);
2000 if (nscSlotHashTable
[index
] == NULL
) {
2001 return CKR_HOST_MEMORY
;
2005 entry
= PL_HashTableAdd(nscSlotHashTable
[index
],(void *)slot
->slotID
,slot
);
2006 if (entry
== NULL
) {
2007 return CKR_HOST_MEMORY
;
2009 slot
->index
= (nscSlotCount
[index
] & 0x7f) | ((index
<< 7) & 0x80);
2010 nscSlotList
[index
][nscSlotCount
[index
]++] = slot
->slotID
;
2017 * ths function has all the common initialization that happens whenever we
2018 * create a new slot or repurpose an old slot (only valid for slotID's 4
2021 * things that are not reinitialized are:
2022 * slotID (can't change)
2023 * slotDescription (can't change once defined)
2024 * the locks and hash tables (difficult to change in running code, and
2025 * unnecessary. hash tables and list are cleared on shutdown, but they
2026 * are cleared in a 'friendly' way).
2027 * session and object ID counters -- so any old sessions and objects in the
2028 * application will get properly notified that the world has changed.
2030 * things that are reinitialized:
2031 * database (otherwise what would the point be;).
2032 * state variables related to databases.
2033 * session count stat info.
2036 * NOTE: slotID's 4 and greater show up as removable devices.
2040 SFTK_SlotReInit(SFTKSlot
*slot
, char *configdir
, char *updatedir
,
2041 char *updateID
, sftk_token_parameters
*params
, int moduleIndex
)
2043 PRBool needLogin
= !params
->noKeyDB
;
2046 slot
->hasTokens
= PR_FALSE
;
2047 slot
->sessionIDConflict
= 0;
2048 slot
->sessionCount
= 0;
2049 slot
->rwSessionCount
= 0;
2050 slot
->needLogin
= PR_FALSE
;
2051 slot
->isLoggedIn
= PR_FALSE
;
2052 slot
->ssoLoggedIn
= PR_FALSE
;
2053 slot
->DB_loaded
= PR_FALSE
;
2054 slot
->certDB
= NULL
;
2056 slot
->minimumPinLen
= 0;
2057 slot
->readOnly
= params
->readOnly
;
2058 sftk_setStringName(params
->tokdes
? params
->tokdes
:
2059 sftk_getDefTokName(slot
->slotID
), slot
->tokDescription
,
2060 sizeof(slot
->tokDescription
),PR_TRUE
);
2061 sftk_setStringName(params
->updtokdes
? params
->updtokdes
: " ",
2062 slot
->updateTokDescription
,
2063 sizeof(slot
->updateTokDescription
),PR_TRUE
);
2065 if ((!params
->noCertDB
) || (!params
->noKeyDB
)) {
2066 SFTKDBHandle
* certHandle
= NULL
;
2067 SFTKDBHandle
*keyHandle
= NULL
;
2068 crv
= sftk_DBInit(params
->configdir
? params
->configdir
: configdir
,
2069 params
->certPrefix
, params
->keyPrefix
,
2070 params
->updatedir
? params
->updatedir
: updatedir
,
2071 params
->updCertPrefix
, params
->updKeyPrefix
,
2072 params
->updateID
? params
->updateID
: updateID
,
2073 params
->readOnly
, params
->noCertDB
, params
->noKeyDB
,
2074 params
->forceOpen
, &certHandle
, &keyHandle
);
2075 if (crv
!= CKR_OK
) {
2079 slot
->certDB
= certHandle
;
2080 slot
->keyDB
= keyHandle
;
2083 /* if the data base is initialized with a null password,remember that */
2085 (PRBool
)!sftk_hasNullPassword(slot
, slot
->keyDB
);
2086 if ((params
->minPW
>= 0) && (params
->minPW
<= SFTK_MAX_PIN
)) {
2087 slot
->minimumPinLen
= params
->minPW
;
2089 if ((slot
->minimumPinLen
== 0) && (params
->pwRequired
)) {
2090 slot
->minimumPinLen
= 1;
2092 if ((moduleIndex
== NSC_FIPS_MODULE
) &&
2093 (slot
->minimumPinLen
< FIPS_MIN_PIN
)) {
2094 slot
->minimumPinLen
= FIPS_MIN_PIN
;
2098 slot
->present
= PR_TRUE
;
2102 SFTK_ShutdownSlot(slot
);
2107 * initialize one of the slot structures. figure out which by the ID
2110 SFTK_SlotInit(char *configdir
, char *updatedir
, char *updateID
,
2111 sftk_token_parameters
*params
, int moduleIndex
)
2114 CK_SLOT_ID slotID
= params
->slotID
;
2116 CK_RV crv
= CKR_HOST_MEMORY
;
2119 * first we initialize everything that is 'permanent' with this slot.
2120 * that is everything we aren't going to shutdown if we close this slot
2121 * and open it up again with different databases */
2123 slot
= PORT_ZNew(SFTKSlot
);
2126 return CKR_HOST_MEMORY
;
2129 slot
->optimizeSpace
= params
->optimizeSpace
;
2130 if (slot
->optimizeSpace
) {
2131 slot
->sessObjHashSize
= SPACE_SESSION_OBJECT_HASH_SIZE
;
2132 slot
->sessHashSize
= SPACE_SESSION_HASH_SIZE
;
2133 slot
->numSessionLocks
= 1;
2135 slot
->sessObjHashSize
= TIME_SESSION_OBJECT_HASH_SIZE
;
2136 slot
->sessHashSize
= TIME_SESSION_HASH_SIZE
;
2137 slot
->numSessionLocks
= slot
->sessHashSize
/BUCKETS_PER_SESSION_LOCK
;
2139 slot
->sessionLockMask
= slot
->numSessionLocks
-1;
2141 slot
->slotLock
= PZ_NewLock(nssILockSession
);
2142 if (slot
->slotLock
== NULL
)
2144 slot
->sessionLock
= PORT_ZNewArray(PZLock
*, slot
->numSessionLocks
);
2145 if (slot
->sessionLock
== NULL
)
2147 for (i
=0; i
< slot
->numSessionLocks
; i
++) {
2148 slot
->sessionLock
[i
] = PZ_NewLock(nssILockSession
);
2149 if (slot
->sessionLock
[i
] == NULL
)
2152 slot
->objectLock
= PZ_NewLock(nssILockObject
);
2153 if (slot
->objectLock
== NULL
)
2155 slot
->pwCheckLock
= PR_NewLock();
2156 if (slot
->pwCheckLock
== NULL
)
2158 slot
->head
= PORT_ZNewArray(SFTKSession
*, slot
->sessHashSize
);
2159 if (slot
->head
== NULL
)
2161 slot
->sessObjHashTable
= PORT_ZNewArray(SFTKObject
*, slot
->sessObjHashSize
);
2162 if (slot
->sessObjHashTable
== NULL
)
2164 slot
->tokObjHashTable
= PL_NewHashTable(64,sftk_HashNumber
,PL_CompareValues
,
2165 SECITEM_HashCompare
, NULL
, 0);
2166 if (slot
->tokObjHashTable
== NULL
)
2169 slot
->sessionIDCount
= 0;
2170 slot
->sessionObjectHandleCount
= minSessionObjectHandle
;
2171 slot
->slotID
= slotID
;
2172 sftk_setStringName(params
->slotdes
? params
->slotdes
:
2173 sftk_getDefSlotName(slotID
), slot
->slotDescription
,
2174 sizeof(slot
->slotDescription
), PR_TRUE
);
2176 /* call the reinit code to set everything that changes between token
2178 crv
= SFTK_SlotReInit(slot
, configdir
, updatedir
, updateID
,
2179 params
, moduleIndex
);
2180 if (crv
!= CKR_OK
) {
2183 crv
= sftk_RegisterSlot(slot
, moduleIndex
);
2184 if (crv
!= CKR_OK
) {
2190 crv
= CKR_HOST_MEMORY
;
2192 SFTK_DestroySlotData(slot
);
2197 CK_RV
sftk_CloseAllSessions(SFTKSlot
*slot
)
2199 SFTKSession
*session
;
2201 SFTKDBHandle
*handle
;
2203 /* first log out the card */
2204 handle
= sftk_getKeyDB(slot
);
2205 PZ_Lock(slot
->slotLock
);
2206 slot
->isLoggedIn
= PR_FALSE
;
2208 sftkdb_ClearPassword(handle
);
2210 PZ_Unlock(slot
->slotLock
);
2212 sftk_freeDB(handle
);
2215 /* now close all the current sessions */
2216 /* NOTE: If you try to open new sessions before NSC_CloseAllSessions
2217 * completes, some of those new sessions may or may not be closed by
2218 * NSC_CloseAllSessions... but any session running when this code starts
2219 * will guarrenteed be close, and no session will be partially closed */
2220 for (i
=0; i
< slot
->sessHashSize
; i
++) {
2221 PZLock
*lock
= SFTK_SESSION_LOCK(slot
,i
);
2224 session
= slot
->head
[i
];
2226 /* this duplicates function of NSC_close session functions, but
2227 * because we know that we are freeing all the sessions, we can
2228 * do more efficient processing */
2230 slot
->head
[i
] = session
->next
;
2231 if (session
->next
) session
->next
->prev
= NULL
;
2232 session
->next
= session
->prev
= NULL
;
2234 PZ_Lock(slot
->slotLock
);
2235 --slot
->sessionCount
;
2236 PZ_Unlock(slot
->slotLock
);
2237 if (session
->info
.flags
& CKF_RW_SESSION
) {
2238 PR_AtomicDecrement(&slot
->rwSessionCount
);
2243 if (session
) sftk_FreeSession(session
);
2244 } while (session
!= NULL
);
2250 * shut down the databases.
2251 * we get the slot lock (which also protects slot->certDB and slot->keyDB)
2252 * and clear the values so the new users will not find the databases.
2253 * once things are clear, we can release our references to the databases.
2254 * The databases will close when the last reference is released.
2256 * We use reference counts so that we don't crash if someone shuts down
2257 * a token that another thread is actively using.
2260 sftk_DBShutdown(SFTKSlot
*slot
)
2262 SFTKDBHandle
*certHandle
;
2263 SFTKDBHandle
*keyHandle
;
2264 PZ_Lock(slot
->slotLock
);
2265 certHandle
= slot
->certDB
;
2266 slot
->certDB
= NULL
;
2267 keyHandle
= slot
->keyDB
;
2269 PZ_Unlock(slot
->slotLock
);
2271 sftk_freeDB(certHandle
);
2274 sftk_freeDB(keyHandle
);
2279 SFTK_ShutdownSlot(SFTKSlot
*slot
)
2281 /* make sure no new PK11 calls work except C_GetSlotInfo */
2282 slot
->present
= PR_FALSE
;
2284 /* close all outstanding sessions
2285 * the sessHashSize variable guarentees we have all the session
2286 * mechanism set up */
2288 sftk_CloseAllSessions(slot
);
2291 /* clear all objects.. session objects are cleared as a result of
2292 * closing all the sessions. We just need to clear the token object
2293 * cache. slot->tokObjHashTable guarentees we have the token
2294 * infrastructure set up. */
2295 if (slot
->tokObjHashTable
) {
2296 SFTK_ClearTokenKeyHashTable(slot
);
2299 /* clear the slot description for the next guy */
2300 PORT_Memset(slot
->tokDescription
, 0, sizeof(slot
->tokDescription
));
2302 /* now shut down the databases. */
2303 sftk_DBShutdown(slot
);
2308 * initialize one of the slot structures. figure out which by the ID
2311 SFTK_DestroySlotData(SFTKSlot
*slot
)
2315 SFTK_ShutdownSlot(slot
);
2317 if (slot
->tokObjHashTable
) {
2318 PL_HashTableDestroy(slot
->tokObjHashTable
);
2319 slot
->tokObjHashTable
= NULL
;
2322 if (slot
->sessObjHashTable
) {
2323 PORT_Free(slot
->sessObjHashTable
);
2324 slot
->sessObjHashTable
= NULL
;
2326 slot
->sessObjHashSize
= 0;
2329 PORT_Free(slot
->head
);
2332 slot
->sessHashSize
= 0;
2334 /* OK everything has been disassembled, now we can finally get rid
2336 PZ_DestroyLock(slot
->slotLock
);
2337 slot
->slotLock
= NULL
;
2338 if (slot
->sessionLock
) {
2339 for (i
=0; i
< slot
->numSessionLocks
; i
++) {
2340 if (slot
->sessionLock
[i
]) {
2341 PZ_DestroyLock(slot
->sessionLock
[i
]);
2342 slot
->sessionLock
[i
] = NULL
;
2345 PORT_Free(slot
->sessionLock
);
2346 slot
->sessionLock
= NULL
;
2348 if (slot
->objectLock
) {
2349 PZ_DestroyLock(slot
->objectLock
);
2350 slot
->objectLock
= NULL
;
2352 if (slot
->pwCheckLock
) {
2353 PR_DestroyLock(slot
->pwCheckLock
);
2354 slot
->pwCheckLock
= NULL
;
2361 * handle the SECMOD.db
2364 NSC_ModuleDBFunc(unsigned long function
,char *parameters
, void *args
)
2366 char *secmod
= NULL
;
2367 char *appName
= NULL
;
2368 char *filename
= NULL
;
2369 SDBType dbType
= SDB_LEGACY
;
2371 static char *success
="Success";
2372 char **rvstr
= NULL
;
2374 #if defined(XP_UNIX) && !defined(NO_PTHREADS)
2375 if (forked
) return NULL
;
2378 secmod
= sftk_getSecmodName(parameters
, &dbType
, &appName
,&filename
, &rw
);
2381 case SECMOD_MODULE_DB_FUNCTION_FIND
:
2382 rvstr
= sftkdb_ReadSecmodDB(dbType
,appName
,filename
,secmod
,(char *)parameters
,rw
);
2384 case SECMOD_MODULE_DB_FUNCTION_ADD
:
2385 rvstr
= (sftkdb_AddSecmodDB(dbType
,appName
,filename
,secmod
,(char *)args
,rw
)
2386 == SECSuccess
) ? &success
: NULL
;
2388 case SECMOD_MODULE_DB_FUNCTION_DEL
:
2389 rvstr
= (sftkdb_DeleteSecmodDB(dbType
,appName
,filename
,secmod
,(char *)args
,rw
)
2390 == SECSuccess
) ? &success
: NULL
;
2392 case SECMOD_MODULE_DB_FUNCTION_RELEASE
:
2393 rvstr
= (sftkdb_ReleaseSecmodDBData(dbType
, appName
,filename
,secmod
,
2394 (char **)args
,rw
) == SECSuccess
) ? &success
: NULL
;
2397 if (secmod
) PR_smprintf_free(secmod
);
2398 if (appName
) PORT_Free(appName
);
2399 if (filename
) PORT_Free(filename
);
2403 static void nscFreeAllSlots(int moduleIndex
)
2405 /* free all the slots */
2406 SFTKSlot
*slot
= NULL
;
2410 if (nscSlotList
[moduleIndex
]) {
2411 CK_ULONG tmpSlotCount
= nscSlotCount
[moduleIndex
];
2412 CK_SLOT_ID_PTR tmpSlotList
= nscSlotList
[moduleIndex
];
2413 PLHashTable
*tmpSlotHashTable
= nscSlotHashTable
[moduleIndex
];
2415 /* first close all the session */
2416 for (i
=0; i
< (int) tmpSlotCount
; i
++) {
2417 slotID
= tmpSlotList
[i
];
2418 (void) NSC_CloseAllSessions(slotID
);
2421 /* now clear out the statics */
2422 nscSlotList
[moduleIndex
] = NULL
;
2423 nscSlotCount
[moduleIndex
] = 0;
2424 nscSlotHashTable
[moduleIndex
] = NULL
;
2425 nscSlotListSize
[moduleIndex
] = 0;
2427 for (i
=0; i
< (int) tmpSlotCount
; i
++) {
2428 slotID
= tmpSlotList
[i
];
2430 PL_HashTableLookup(tmpSlotHashTable
, (void *)slotID
);
2432 if (!slot
) continue;
2433 SFTK_DestroySlotData(slot
);
2434 PL_HashTableRemove(tmpSlotHashTable
, (void *)slotID
);
2436 PORT_Free(tmpSlotList
);
2437 PL_HashTableDestroy(tmpSlotHashTable
);
2442 sftk_closePeer(PRBool isFIPS
)
2444 CK_SLOT_ID slotID
= isFIPS
? PRIVATE_KEY_SLOT_ID
: FIPS_SLOT_ID
;
2446 int moduleIndex
= isFIPS
? NSC_NON_FIPS_MODULE
: NSC_FIPS_MODULE
;
2447 PLHashTable
*tmpSlotHashTable
= nscSlotHashTable
[moduleIndex
];
2449 slot
= (SFTKSlot
*) PL_HashTableLookup(tmpSlotHashTable
, (void *)slotID
);
2453 sftk_DBShutdown(slot
);
2457 /* NSC_Initialize initializes the Cryptoki library. */
2458 CK_RV
nsc_CommonInitialize(CK_VOID_PTR pReserved
, PRBool isFIPS
)
2462 CK_C_INITIALIZE_ARGS
*init_args
= (CK_C_INITIALIZE_ARGS
*) pReserved
;
2464 int moduleIndex
= isFIPS
? NSC_FIPS_MODULE
: NSC_NON_FIPS_MODULE
;
2467 loginWaitTime
= PR_SecondsToInterval(1);
2471 if (rv
!= SECSuccess
) {
2472 crv
= CKR_DEVICE_ERROR
;
2476 rv
= RNG_RNGInit(); /* initialize random number generator */
2477 if (rv
!= SECSuccess
) {
2478 crv
= CKR_DEVICE_ERROR
;
2481 RNG_SystemInfoForRNG();
2485 * we should be getting out mutexes from this list, not statically binding
2486 * them from NSPR. This should happen before we allow the internal to split
2487 * off from the rest on NSS.
2490 /* initialize the key and cert db's */
2491 if (init_args
&& (!(init_args
->flags
& CKF_OS_LOCKING_OK
))) {
2492 if (init_args
->CreateMutex
&& init_args
->DestroyMutex
&&
2493 init_args
->LockMutex
&& init_args
->UnlockMutex
) {
2494 /* softoken always uses NSPR (ie. OS locking), and doesn't know how
2495 * to use the lock functions provided by the application.
2497 crv
= CKR_CANT_LOCK
;
2500 if (init_args
->CreateMutex
|| init_args
->DestroyMutex
||
2501 init_args
->LockMutex
|| init_args
->UnlockMutex
) {
2502 /* only some of the lock functions were provided by the
2503 * application. This is invalid per PKCS#11 spec.
2505 crv
= CKR_ARGUMENTS_BAD
;
2509 crv
= CKR_ARGUMENTS_BAD
;
2510 if ((init_args
&& init_args
->LibraryParameters
)) {
2511 sftk_parameters paramStrings
;
2513 crv
= sftk_parseParameters
2514 ((char *)init_args
->LibraryParameters
, ¶mStrings
, isFIPS
);
2515 if (crv
!= CKR_OK
) {
2518 crv
= sftk_configure(paramStrings
.man
, paramStrings
.libdes
);
2519 if (crv
!= CKR_OK
) {
2523 /* if we have a peer already open, have him close his DB's so we
2524 * don't clobber each other. */
2525 if ((isFIPS
&& nsc_init
) || (!isFIPS
&& nsf_init
)) {
2526 sftk_closePeer(isFIPS
);
2527 if (sftk_audit_enabled
) {
2528 if (isFIPS
&& nsc_init
) {
2529 sftk_LogAuditMessage(NSS_AUDIT_INFO
, "enabled FIPS mode");
2531 sftk_LogAuditMessage(NSS_AUDIT_INFO
, "disabled FIPS mode");
2536 for (i
=0; i
< paramStrings
.token_count
; i
++) {
2537 crv
= SFTK_SlotInit(paramStrings
.configdir
,
2538 paramStrings
.updatedir
, paramStrings
.updateID
,
2539 ¶mStrings
.tokens
[i
], moduleIndex
);
2540 if (crv
!= CKR_OK
) {
2541 nscFreeAllSlots(moduleIndex
);
2546 sftk_freeParams(¶mStrings
);
2548 if (CKR_OK
== crv
) {
2549 sftk_InitFreeLists();
2552 #if defined(XP_UNIX) && !defined(NO_PTHREADS)
2553 if (CKR_OK
== crv
) {
2554 pthread_atfork(NULL
, NULL
, ForkedChild
);
2560 CK_RV
NSC_Initialize(CK_VOID_PTR pReserved
)
2567 return CKR_CRYPTOKI_ALREADY_INITIALIZED
;
2569 crv
= nsc_CommonInitialize(pReserved
,PR_FALSE
);
2570 nsc_init
= (PRBool
) (crv
== CKR_OK
);
2575 /* NSC_Finalize indicates that an application is done with the
2576 * Cryptoki library.*/
2577 CK_RV
nsc_CommonFinalize (CK_VOID_PTR pReserved
, PRBool isFIPS
)
2579 nscFreeAllSlots(isFIPS
? NSC_FIPS_MODULE
: NSC_NON_FIPS_MODULE
);
2581 /* don't muck with the globals is our peer is still initialized */
2582 if (isFIPS
&& nsc_init
) {
2585 if (!isFIPS
&& nsf_init
) {
2589 sftk_CleanupFreeLists();
2592 /* This function does not discard all our previously aquired entropy. */
2595 /* tell freeBL to clean up after itself */
2597 /* unload freeBL shared library from memory */
2599 /* clean up the default OID table */
2601 nsc_init
= PR_FALSE
;
2606 /* NSC_Finalize indicates that an application is done with the
2607 * Cryptoki library.*/
2608 CK_RV
NSC_Finalize (CK_VOID_PTR pReserved
)
2618 crv
= nsc_CommonFinalize (pReserved
, PR_FALSE
);
2620 nsc_init
= (PRBool
) !(crv
== CKR_OK
);
2625 extern const char __nss_softokn_rcsid
[];
2626 extern const char __nss_softokn_sccsid
[];
2628 /* NSC_GetInfo returns general information about Cryptoki. */
2629 CK_RV
NSC_GetInfo(CK_INFO_PTR pInfo
)
2631 volatile char c
; /* force a reference that won't get optimized away */
2635 c
= __nss_softokn_rcsid
[0] + __nss_softokn_sccsid
[0];
2636 pInfo
->cryptokiVersion
.major
= 2;
2637 pInfo
->cryptokiVersion
.minor
= 20;
2638 PORT_Memcpy(pInfo
->manufacturerID
,manufacturerID
,32);
2639 pInfo
->libraryVersion
.major
= SOFTOKEN_VMAJOR
;
2640 pInfo
->libraryVersion
.minor
= SOFTOKEN_VMINOR
;
2641 PORT_Memcpy(pInfo
->libraryDescription
,libraryDescription
,32);
2647 /* NSC_GetSlotList obtains a list of slots in the system. */
2648 CK_RV
nsc_CommonGetSlotList(CK_BBOOL tokenPresent
,
2649 CK_SLOT_ID_PTR pSlotList
, CK_ULONG_PTR pulCount
, int moduleIndex
)
2651 *pulCount
= nscSlotCount
[moduleIndex
];
2652 if (pSlotList
!= NULL
) {
2653 PORT_Memcpy(pSlotList
,nscSlotList
[moduleIndex
],
2654 nscSlotCount
[moduleIndex
]*sizeof(CK_SLOT_ID
));
2659 /* NSC_GetSlotList obtains a list of slots in the system. */
2660 CK_RV
NSC_GetSlotList(CK_BBOOL tokenPresent
,
2661 CK_SLOT_ID_PTR pSlotList
, CK_ULONG_PTR pulCount
)
2664 return nsc_CommonGetSlotList(tokenPresent
, pSlotList
, pulCount
,
2665 NSC_NON_FIPS_MODULE
);
2668 /* NSC_GetSlotInfo obtains information about a particular slot in the system. */
2669 CK_RV
NSC_GetSlotInfo(CK_SLOT_ID slotID
, CK_SLOT_INFO_PTR pInfo
)
2671 SFTKSlot
*slot
= sftk_SlotFromID(slotID
, PR_TRUE
);
2675 if (slot
== NULL
) return CKR_SLOT_ID_INVALID
;
2677 pInfo
->firmwareVersion
.major
= 0;
2678 pInfo
->firmwareVersion
.minor
= 0;
2680 PORT_Memcpy(pInfo
->manufacturerID
,manufacturerID
,
2681 sizeof(pInfo
->manufacturerID
));
2682 PORT_Memcpy(pInfo
->slotDescription
,slot
->slotDescription
,
2683 sizeof(pInfo
->slotDescription
));
2684 pInfo
->flags
= (slot
->present
) ? CKF_TOKEN_PRESENT
: 0;
2686 /* all user defined slots are defined as removable */
2687 if (slotID
>= SFTK_MIN_USER_SLOT_ID
) {
2688 pInfo
->flags
|= CKF_REMOVABLE_DEVICE
;
2690 /* In the case where we are doing a merge update, we need
2691 * the DB slot to be removable so the token name can change
2693 SFTKDBHandle
*handle
= sftk_getKeyDB(slot
);
2695 if (sftkdb_InUpdateMerge(handle
)) {
2696 pInfo
->flags
|= CKF_REMOVABLE_DEVICE
;
2698 sftk_freeDB(handle
);
2702 /* ok we really should read it out of the keydb file. */
2703 /* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */
2704 pInfo
->hardwareVersion
.major
= SOFTOKEN_VMAJOR
;
2705 pInfo
->hardwareVersion
.minor
= SOFTOKEN_VMINOR
;
2710 * check the current state of the 'needLogin' flag in case the database has
2711 * been changed underneath us.
2714 sftk_checkNeedLogin(SFTKSlot
*slot
, SFTKDBHandle
*keyHandle
)
2716 if (sftkdb_PWCached(keyHandle
) == SECSuccess
) {
2717 return slot
->needLogin
;
2719 slot
->needLogin
= (PRBool
)!sftk_hasNullPassword(slot
, keyHandle
);
2720 return (slot
->needLogin
);
2724 sftk_isBlank(const char *s
, int len
)
2727 for (i
=0; i
< len
; i
++) {
2735 /* NSC_GetTokenInfo obtains information about a particular token in
2737 CK_RV
NSC_GetTokenInfo(CK_SLOT_ID slotID
,CK_TOKEN_INFO_PTR pInfo
)
2740 SFTKDBHandle
*handle
;
2744 if (!nsc_init
&& !nsf_init
) return CKR_CRYPTOKI_NOT_INITIALIZED
;
2745 slot
= sftk_SlotFromID(slotID
, PR_FALSE
);
2746 if (slot
== NULL
) return CKR_SLOT_ID_INVALID
;
2748 PORT_Memcpy(pInfo
->manufacturerID
,manufacturerID
,32);
2749 PORT_Memcpy(pInfo
->model
,"NSS 3 ",16);
2750 PORT_Memcpy(pInfo
->serialNumber
,"0000000000000000",16);
2751 PORT_Memcpy(pInfo
->utcTime
,"0000000000000000",16);
2752 pInfo
->ulMaxSessionCount
= 0; /* arbitrarily large */
2753 pInfo
->ulSessionCount
= slot
->sessionCount
;
2754 pInfo
->ulMaxRwSessionCount
= 0; /* arbitarily large */
2755 pInfo
->ulRwSessionCount
= slot
->rwSessionCount
;
2756 pInfo
->firmwareVersion
.major
= 0;
2757 pInfo
->firmwareVersion
.minor
= 0;
2758 PORT_Memcpy(pInfo
->label
,slot
->tokDescription
,sizeof(pInfo
->label
));
2759 handle
= sftk_getKeyDB(slot
);
2760 pInfo
->flags
= CKF_RNG
| CKF_DUAL_CRYPTO_OPERATIONS
;
2761 if (handle
== NULL
) {
2762 pInfo
->flags
|= CKF_WRITE_PROTECTED
;
2763 pInfo
->ulMaxPinLen
= 0;
2764 pInfo
->ulMinPinLen
= 0;
2765 pInfo
->ulTotalPublicMemory
= 0;
2766 pInfo
->ulFreePublicMemory
= 0;
2767 pInfo
->ulTotalPrivateMemory
= 0;
2768 pInfo
->ulFreePrivateMemory
= 0;
2769 pInfo
->hardwareVersion
.major
= 4;
2770 pInfo
->hardwareVersion
.minor
= 0;
2773 * we have three possible states which we may be in:
2774 * (1) No DB password has been initialized. This also means we
2775 * have no keys in the key db.
2776 * (2) Password initialized to NULL. This means we have keys, but
2777 * the user has chosen not use a password.
2778 * (3) Finally we have an initialized password whicn is not NULL, and
2779 * we will need to prompt for it.
2781 if (sftkdb_HasPasswordSet(handle
) == SECFailure
) {
2782 pInfo
->flags
|= CKF_LOGIN_REQUIRED
;
2783 } else if (!sftk_checkNeedLogin(slot
,handle
)) {
2784 pInfo
->flags
|= CKF_USER_PIN_INITIALIZED
;
2786 pInfo
->flags
|= CKF_LOGIN_REQUIRED
| CKF_USER_PIN_INITIALIZED
;
2788 * if we are doing a merge style update, and we need to get the password
2789 * of our source database (the database we are updating from), make sure we
2790 * return a token name that will match the database we are prompting for.
2792 if (sftkdb_NeedUpdateDBPassword(handle
)) {
2793 /* if we have an update tok description, use it. otherwise
2794 * use the updateID for this database */
2795 if (!sftk_isBlank(slot
->updateTokDescription
,
2796 sizeof(pInfo
->label
))) {
2797 PORT_Memcpy(pInfo
->label
,slot
->updateTokDescription
,
2798 sizeof(pInfo
->label
));
2800 /* build from updateID */
2801 const char *updateID
= sftkdb_GetUpdateID(handle
);
2803 sftk_setStringName(updateID
, (char *)pInfo
->label
,
2804 sizeof(pInfo
->label
), PR_FALSE
);
2809 pInfo
->ulMaxPinLen
= SFTK_MAX_PIN
;
2810 pInfo
->ulMinPinLen
= (CK_ULONG
)slot
->minimumPinLen
;
2811 pInfo
->ulTotalPublicMemory
= 1;
2812 pInfo
->ulFreePublicMemory
= 1;
2813 pInfo
->ulTotalPrivateMemory
= 1;
2814 pInfo
->ulFreePrivateMemory
= 1;
2816 pInfo
->hardwareVersion
.major
= CERT_DB_FILE_VERSION
;
2817 pInfo
->hardwareVersion
.minor
= handle
->version
;
2819 pInfo
->hardwareVersion
.major
= 0;
2820 pInfo
->hardwareVersion
.minor
= 0;
2822 sftk_freeDB(handle
);
2825 * CKF_LOGIN_REQUIRED CKF_USER_PIN_INITIALIZED how CKF_TOKEN_INITIALIZED
2832 if (!(pInfo
->flags
& CKF_LOGIN_REQUIRED
) ||
2833 (pInfo
->flags
& CKF_USER_PIN_INITIALIZED
)) {
2834 pInfo
->flags
|= CKF_TOKEN_INITIALIZED
;
2839 /* NSC_GetMechanismList obtains a list of mechanism types
2840 * supported by a token. */
2841 CK_RV
NSC_GetMechanismList(CK_SLOT_ID slotID
,
2842 CK_MECHANISM_TYPE_PTR pMechanismList
, CK_ULONG_PTR pulCount
)
2850 case NETSCAPE_SLOT_ID
:
2851 *pulCount
= mechanismCount
;
2852 if (pMechanismList
!= NULL
) {
2853 for (i
=0; i
< mechanismCount
; i
++) {
2854 pMechanismList
[i
] = mechanisms
[i
].type
;
2860 for (i
=0; i
< mechanismCount
; i
++) {
2861 if (mechanisms
[i
].privkey
) {
2863 if (pMechanismList
!= NULL
) {
2864 *pMechanismList
++ = mechanisms
[i
].type
;
2874 /* NSC_GetMechanismInfo obtains information about a particular mechanism
2875 * possibly supported by a token. */
2876 CK_RV
NSC_GetMechanismInfo(CK_SLOT_ID slotID
, CK_MECHANISM_TYPE type
,
2877 CK_MECHANISM_INFO_PTR pInfo
)
2879 PRBool isPrivateKey
;
2885 case NETSCAPE_SLOT_ID
:
2886 isPrivateKey
= PR_FALSE
;
2889 isPrivateKey
= PR_TRUE
;
2892 for (i
=0; i
< mechanismCount
; i
++) {
2893 if (type
== mechanisms
[i
].type
) {
2894 if (isPrivateKey
&& !mechanisms
[i
].privkey
) {
2895 return CKR_MECHANISM_INVALID
;
2897 PORT_Memcpy(pInfo
,&mechanisms
[i
].info
, sizeof(CK_MECHANISM_INFO
));
2901 return CKR_MECHANISM_INVALID
;
2904 CK_RV
sftk_MechAllowsOperation(CK_MECHANISM_TYPE type
, CK_ATTRIBUTE_TYPE op
)
2910 case CKA_ENCRYPT
: flags
= CKF_ENCRYPT
; break;
2911 case CKA_DECRYPT
: flags
= CKF_DECRYPT
; break;
2912 case CKA_WRAP
: flags
= CKF_WRAP
; break;
2913 case CKA_UNWRAP
: flags
= CKF_UNWRAP
; break;
2914 case CKA_SIGN
: flags
= CKF_SIGN
; break;
2915 case CKA_SIGN_RECOVER
: flags
= CKF_SIGN_RECOVER
; break;
2916 case CKA_VERIFY
: flags
= CKF_VERIFY
; break;
2917 case CKA_VERIFY_RECOVER
: flags
= CKF_VERIFY_RECOVER
; break;
2918 case CKA_DERIVE
: flags
= CKF_DERIVE
; break;
2920 return CKR_ARGUMENTS_BAD
;
2922 for (i
=0; i
< mechanismCount
; i
++) {
2923 if (type
== mechanisms
[i
].type
) {
2924 return (flags
& mechanisms
[i
].info
.flags
) ? CKR_OK
2925 : CKR_MECHANISM_INVALID
;
2928 return CKR_MECHANISM_INVALID
;
2931 /* NSC_InitToken initializes a token. */
2932 CK_RV
NSC_InitToken(CK_SLOT_ID slotID
,CK_CHAR_PTR pPin
,
2933 CK_ULONG ulPinLen
,CK_CHAR_PTR pLabel
) {
2934 SFTKSlot
*slot
= sftk_SlotFromID(slotID
, PR_FALSE
);
2935 SFTKDBHandle
*handle
;
2936 SFTKDBHandle
*certHandle
;
2943 if (slot
== NULL
) return CKR_SLOT_ID_INVALID
;
2945 /* don't initialize the database if we aren't talking to a token
2946 * that uses the key database.
2948 if (slotID
== NETSCAPE_SLOT_ID
) {
2949 return CKR_TOKEN_WRITE_PROTECTED
;
2952 /* first, delete all our loaded key and cert objects from our
2954 PZ_Lock(slot
->objectLock
);
2955 for (i
=0; i
< slot
->sessObjHashSize
; i
++) {
2957 object
= slot
->sessObjHashTable
[i
];
2959 /* this duplicates function of NSC_close session functions, but
2960 * because we know that we are freeing all the sessions, we can
2961 * do more efficient processing */
2963 slot
->sessObjHashTable
[i
] = object
->next
;
2965 if (object
->next
) object
->next
->prev
= NULL
;
2966 object
->next
= object
->prev
= NULL
;
2968 if (object
) sftk_FreeObject(object
);
2969 } while (object
!= NULL
);
2971 slot
->DB_loaded
= PR_FALSE
;
2972 PZ_Unlock(slot
->objectLock
);
2974 /* then clear out the key database */
2975 handle
= sftk_getKeyDB(slot
);
2976 if (handle
== NULL
) {
2977 return CKR_TOKEN_WRITE_PROTECTED
;
2980 rv
= sftkdb_ResetKeyDB(handle
);
2981 sftk_freeDB(handle
);
2982 if (rv
!= SECSuccess
) {
2983 return CKR_DEVICE_ERROR
;
2986 /* finally mark all the user certs as non-user certs */
2987 certHandle
= sftk_getCertDB(slot
);
2988 if (certHandle
== NULL
) return CKR_OK
;
2990 sftk_freeDB(certHandle
);
2992 return CKR_OK
; /*is this the right function for not implemented*/
2996 /* NSC_InitPIN initializes the normal user's PIN. */
2997 CK_RV
NSC_InitPIN(CK_SESSION_HANDLE hSession
,
2998 CK_CHAR_PTR pPin
, CK_ULONG ulPinLen
)
3000 SFTKSession
*sp
= NULL
;
3002 SFTKDBHandle
*handle
= NULL
;
3003 char newPinStr
[SFTK_MAX_PIN
+1];
3005 CK_RV crv
= CKR_SESSION_HANDLE_INVALID
;
3006 PRBool tokenRemoved
= PR_FALSE
;
3010 sp
= sftk_SessionFromHandle(hSession
);
3015 slot
= sftk_SlotFromSession(sp
);
3020 handle
= sftk_getKeyDB(slot
);
3021 if (handle
== NULL
) {
3022 crv
= CKR_PIN_LEN_RANGE
;
3027 if (sp
->info
.state
!= CKS_RW_SO_FUNCTIONS
) {
3028 crv
= CKR_USER_NOT_LOGGED_IN
;
3032 sftk_FreeSession(sp
);
3035 /* make sure the pins aren't too long */
3036 if (ulPinLen
> SFTK_MAX_PIN
) {
3037 crv
= CKR_PIN_LEN_RANGE
;
3040 if (ulPinLen
< (CK_ULONG
)slot
->minimumPinLen
) {
3041 crv
= CKR_PIN_LEN_RANGE
;
3045 if (sftkdb_HasPasswordSet(handle
) != SECFailure
) {
3046 crv
= CKR_DEVICE_ERROR
;
3050 /* convert to null terminated string */
3051 PORT_Memcpy(newPinStr
, pPin
, ulPinLen
);
3052 newPinStr
[ulPinLen
] = 0;
3054 /* build the hashed pins which we pass around */
3056 /* change the data base */
3057 rv
= sftkdb_ChangePassword(handle
, NULL
, newPinStr
, &tokenRemoved
);
3059 sftk_CloseAllSessions(slot
);
3061 sftk_freeDB(handle
);
3064 /* Now update our local copy of the pin */
3065 if (rv
== SECSuccess
) {
3066 if (ulPinLen
== 0) slot
->needLogin
= PR_FALSE
;
3069 crv
= CKR_PIN_INCORRECT
;
3073 sftk_FreeSession(sp
);
3076 sftk_freeDB(handle
);
3082 /* NSC_SetPIN modifies the PIN of user that is currently logged in. */
3083 /* NOTE: This is only valid for the PRIVATE_KEY_SLOT */
3084 CK_RV
NSC_SetPIN(CK_SESSION_HANDLE hSession
, CK_CHAR_PTR pOldPin
,
3085 CK_ULONG ulOldLen
, CK_CHAR_PTR pNewPin
, CK_ULONG ulNewLen
)
3087 SFTKSession
*sp
= NULL
;
3089 SFTKDBHandle
*handle
= NULL
;
3090 char newPinStr
[SFTK_MAX_PIN
+1],oldPinStr
[SFTK_MAX_PIN
+1];
3092 CK_RV crv
= CKR_SESSION_HANDLE_INVALID
;
3093 PRBool tokenRemoved
= PR_FALSE
;
3097 sp
= sftk_SessionFromHandle(hSession
);
3102 slot
= sftk_SlotFromSession(sp
);
3107 handle
= sftk_getKeyDB(slot
);
3108 if (handle
== NULL
) {
3109 sftk_FreeSession(sp
);
3110 return CKR_PIN_LEN_RANGE
; /* XXX FIXME wrong return value */
3113 if (slot
->needLogin
&& sp
->info
.state
!= CKS_RW_USER_FUNCTIONS
) {
3114 crv
= CKR_USER_NOT_LOGGED_IN
;
3118 sftk_FreeSession(sp
);
3121 /* make sure the pins aren't too long */
3122 if ((ulNewLen
> SFTK_MAX_PIN
) || (ulOldLen
> SFTK_MAX_PIN
)) {
3123 crv
= CKR_PIN_LEN_RANGE
;
3126 if (ulNewLen
< (CK_ULONG
)slot
->minimumPinLen
) {
3127 crv
= CKR_PIN_LEN_RANGE
;
3132 /* convert to null terminated string */
3133 PORT_Memcpy(newPinStr
,pNewPin
,ulNewLen
);
3134 newPinStr
[ulNewLen
] = 0;
3135 PORT_Memcpy(oldPinStr
,pOldPin
,ulOldLen
);
3136 oldPinStr
[ulOldLen
] = 0;
3138 /* change the data base password */
3139 PR_Lock(slot
->pwCheckLock
);
3140 rv
= sftkdb_ChangePassword(handle
, oldPinStr
, newPinStr
, &tokenRemoved
);
3142 sftk_CloseAllSessions(slot
);
3144 sftk_freeDB(handle
);
3146 if ((rv
!= SECSuccess
) && (slot
->slotID
== FIPS_SLOT_ID
)) {
3147 PR_Sleep(loginWaitTime
);
3149 PR_Unlock(slot
->pwCheckLock
);
3151 /* Now update our local copy of the pin */
3152 if (rv
== SECSuccess
) {
3153 slot
->needLogin
= (PRBool
)(ulNewLen
!= 0);
3156 crv
= CKR_PIN_INCORRECT
;
3159 sftk_FreeSession(sp
);
3162 sftk_freeDB(handle
);
3167 /* NSC_OpenSession opens a session between an application and a token. */
3168 CK_RV
NSC_OpenSession(CK_SLOT_ID slotID
, CK_FLAGS flags
,
3169 CK_VOID_PTR pApplication
,CK_NOTIFY Notify
,CK_SESSION_HANDLE_PTR phSession
)
3172 CK_SESSION_HANDLE sessionID
;
3173 SFTKSession
*session
;
3174 SFTKSession
*sameID
;
3178 slot
= sftk_SlotFromID(slotID
, PR_FALSE
);
3179 if (slot
== NULL
) return CKR_SLOT_ID_INVALID
;
3181 /* new session (we only have serial sessions) */
3182 session
= sftk_NewSession(slotID
, Notify
, pApplication
,
3183 flags
| CKF_SERIAL_SESSION
);
3184 if (session
== NULL
) return CKR_HOST_MEMORY
;
3186 if (slot
->readOnly
&& (flags
& CKF_RW_SESSION
)) {
3187 /* NETSCAPE_SLOT_ID is Read ONLY */
3188 session
->info
.flags
&= ~CKF_RW_SESSION
;
3190 PZ_Lock(slot
->slotLock
);
3191 ++slot
->sessionCount
;
3192 PZ_Unlock(slot
->slotLock
);
3193 if (session
->info
.flags
& CKF_RW_SESSION
) {
3194 PR_AtomicIncrement(&slot
->rwSessionCount
);
3200 sessionID
= (PR_AtomicIncrement(&slot
->sessionIDCount
) & 0xffffff)
3201 | (slot
->index
<< 24);
3202 } while (sessionID
== CK_INVALID_HANDLE
);
3203 lock
= SFTK_SESSION_LOCK(slot
,sessionID
);
3205 sftkqueue_find(sameID
, sessionID
, slot
->head
, slot
->sessHashSize
);
3206 if (sameID
== NULL
) {
3207 session
->handle
= sessionID
;
3208 sftk_update_state(slot
, session
);
3209 sftkqueue_add(session
, sessionID
, slot
->head
,slot
->sessHashSize
);
3211 slot
->sessionIDConflict
++; /* for debugging */
3214 } while (sameID
!= NULL
);
3216 *phSession
= sessionID
;
3221 /* NSC_CloseSession closes a session between an application and a token. */
3222 CK_RV
NSC_CloseSession(CK_SESSION_HANDLE hSession
)
3225 SFTKSession
*session
;
3226 PRBool sessionFound
;
3231 session
= sftk_SessionFromHandle(hSession
);
3232 if (session
== NULL
) return CKR_SESSION_HANDLE_INVALID
;
3233 slot
= sftk_SlotFromSession(session
);
3234 sessionFound
= PR_FALSE
;
3237 lock
= SFTK_SESSION_LOCK(slot
,hSession
);
3239 if (sftkqueue_is_queued(session
,hSession
,slot
->head
,slot
->sessHashSize
)) {
3240 sessionFound
= PR_TRUE
;
3241 sftkqueue_delete(session
,hSession
,slot
->head
,slot
->sessHashSize
);
3242 session
->refCount
--; /* can't go to zero while we hold the reference */
3243 PORT_Assert(session
->refCount
> 0);
3248 SFTKDBHandle
*handle
;
3249 handle
= sftk_getKeyDB(slot
);
3250 PZ_Lock(slot
->slotLock
);
3251 if (--slot
->sessionCount
== 0) {
3252 slot
->isLoggedIn
= PR_FALSE
;
3254 sftkdb_ClearPassword(handle
);
3257 PZ_Unlock(slot
->slotLock
);
3259 sftk_freeDB(handle
);
3261 if (session
->info
.flags
& CKF_RW_SESSION
) {
3262 PR_AtomicDecrement(&slot
->rwSessionCount
);
3266 sftk_FreeSession(session
);
3271 /* NSC_CloseAllSessions closes all sessions with a token. */
3272 CK_RV
NSC_CloseAllSessions (CK_SLOT_ID slotID
)
3278 slot
= sftk_SlotFromID(slotID
, PR_FALSE
);
3279 if (slot
== NULL
) return CKR_SLOT_ID_INVALID
;
3281 return sftk_CloseAllSessions(slot
);
3286 /* NSC_GetSessionInfo obtains information about the session. */
3287 CK_RV
NSC_GetSessionInfo(CK_SESSION_HANDLE hSession
,
3288 CK_SESSION_INFO_PTR pInfo
)
3290 SFTKSession
*session
;
3294 session
= sftk_SessionFromHandle(hSession
);
3295 if (session
== NULL
) return CKR_SESSION_HANDLE_INVALID
;
3297 PORT_Memcpy(pInfo
,&session
->info
,sizeof(CK_SESSION_INFO
));
3298 sftk_FreeSession(session
);
3302 /* NSC_Login logs a user into a token. */
3303 CK_RV
NSC_Login(CK_SESSION_HANDLE hSession
, CK_USER_TYPE userType
,
3304 CK_CHAR_PTR pPin
, CK_ULONG ulPinLen
)
3307 SFTKSession
*session
;
3308 SFTKDBHandle
*handle
;
3309 CK_FLAGS sessionFlags
;
3312 char pinStr
[SFTK_MAX_PIN
+1];
3313 PRBool tokenRemoved
= PR_FALSE
;
3318 slot
= sftk_SlotFromSessionHandle(hSession
);
3320 return CKR_SESSION_HANDLE_INVALID
;
3323 /* make sure the session is valid */
3324 session
= sftk_SessionFromHandle(hSession
);
3325 if (session
== NULL
) {
3326 return CKR_SESSION_HANDLE_INVALID
;
3328 sessionFlags
= session
->info
.flags
;
3329 sftk_FreeSession(session
);
3332 /* can't log into the Netscape Slot */
3333 if (slot
->slotID
== NETSCAPE_SLOT_ID
) {
3334 return CKR_USER_TYPE_INVALID
;
3337 if (slot
->isLoggedIn
) return CKR_USER_ALREADY_LOGGED_IN
;
3338 slot
->ssoLoggedIn
= PR_FALSE
;
3340 if (ulPinLen
> SFTK_MAX_PIN
) return CKR_PIN_LEN_RANGE
;
3342 /* convert to null terminated string */
3343 PORT_Memcpy(pinStr
,pPin
,ulPinLen
);
3344 pinStr
[ulPinLen
] = 0;
3346 handle
= sftk_getKeyDB(slot
);
3347 if (handle
== NULL
) {
3348 return CKR_USER_TYPE_INVALID
;
3352 * Deal with bootstrap. We allow the SSO to login in with a NULL
3353 * password if and only if we haven't initialized the KEY DB yet.
3354 * We only allow this on a RW session.
3356 rv
= sftkdb_HasPasswordSet(handle
);
3357 if (rv
== SECFailure
) {
3358 /* allow SSO's to log in only if there is not password on the
3360 if (((userType
== CKU_SO
) && (sessionFlags
& CKF_RW_SESSION
))
3361 /* fips always needs to authenticate, even if there isn't a db */
3362 || (slot
->slotID
== FIPS_SLOT_ID
)) {
3363 /* should this be a fixed password? */
3364 if (ulPinLen
== 0) {
3365 sftkdb_ClearPassword(handle
);
3366 PZ_Lock(slot
->slotLock
);
3367 slot
->isLoggedIn
= PR_TRUE
;
3368 slot
->ssoLoggedIn
= (PRBool
)(userType
== CKU_SO
);
3369 PZ_Unlock(slot
->slotLock
);
3370 sftk_update_all_states(slot
);
3374 crv
= CKR_PIN_INCORRECT
;
3377 crv
= CKR_USER_TYPE_INVALID
;
3381 /* don't allow the SSO to log in if the user is already initialized */
3382 if (userType
!= CKU_USER
) {
3383 crv
= CKR_USER_TYPE_INVALID
;
3388 /* build the hashed pins which we pass around */
3389 PR_Lock(slot
->pwCheckLock
);
3390 rv
= sftkdb_CheckPassword(handle
,pinStr
, &tokenRemoved
);
3392 sftk_CloseAllSessions(slot
);
3394 if ((rv
!= SECSuccess
) && (slot
->slotID
== FIPS_SLOT_ID
)) {
3395 PR_Sleep(loginWaitTime
);
3397 PR_Unlock(slot
->pwCheckLock
);
3398 if (rv
== SECSuccess
) {
3399 PZ_Lock(slot
->slotLock
);
3400 /* make sure the login state matches the underlying
3402 slot
->isLoggedIn
= sftkdb_PWCached(handle
) == SECSuccess
?
3404 PZ_Unlock(slot
->slotLock
);
3406 sftk_freeDB(handle
);
3409 /* update all sessions */
3410 sftk_update_all_states(slot
);
3414 crv
= CKR_PIN_INCORRECT
;
3417 sftk_freeDB(handle
);
3422 /* NSC_Logout logs a user out from a token. */
3423 CK_RV
NSC_Logout(CK_SESSION_HANDLE hSession
)
3425 SFTKSlot
*slot
= sftk_SlotFromSessionHandle(hSession
);
3426 SFTKSession
*session
;
3427 SFTKDBHandle
*handle
;
3432 return CKR_SESSION_HANDLE_INVALID
;
3434 session
= sftk_SessionFromHandle(hSession
);
3435 if (session
== NULL
) return CKR_SESSION_HANDLE_INVALID
;
3436 sftk_FreeSession(session
);
3439 if (!slot
->isLoggedIn
) return CKR_USER_NOT_LOGGED_IN
;
3441 handle
= sftk_getKeyDB(slot
);
3442 PZ_Lock(slot
->slotLock
);
3443 slot
->isLoggedIn
= PR_FALSE
;
3444 slot
->ssoLoggedIn
= PR_FALSE
;
3446 sftkdb_ClearPassword(handle
);
3448 PZ_Unlock(slot
->slotLock
);
3450 sftk_freeDB(handle
);
3453 sftk_update_all_states(slot
);
3458 * Create a new slot on the fly. The slot that is passed in is the
3459 * slot the request came from. Only the crypto or FIPS slots can
3460 * be used. The resulting slot will live in the same module as
3461 * the slot the request was passed to. object is the creation object
3462 * that specifies the module spec for the new slot.
3464 static CK_RV
sftk_CreateNewSlot(SFTKSlot
*slot
, CK_OBJECT_CLASS
class,
3467 CK_SLOT_ID idMin
, idMax
;
3468 PRBool isFIPS
= PR_FALSE
;
3469 unsigned long moduleIndex
;
3470 SFTKAttribute
*attribute
;
3471 sftk_parameters paramStrings
;
3473 CK_SLOT_ID slotID
= 0;
3474 SFTKSlot
*newSlot
= NULL
;
3477 /* only the crypto or FIPS slots can create new slot objects */
3478 if (slot
->slotID
== NETSCAPE_SLOT_ID
) {
3479 idMin
= SFTK_MIN_USER_SLOT_ID
;
3480 idMax
= SFTK_MAX_USER_SLOT_ID
;
3481 moduleIndex
= NSC_NON_FIPS_MODULE
;
3483 } else if (slot
->slotID
== FIPS_SLOT_ID
) {
3484 idMin
= SFTK_MIN_FIPS_USER_SLOT_ID
;
3485 idMax
= SFTK_MAX_FIPS_USER_SLOT_ID
;
3486 moduleIndex
= NSC_FIPS_MODULE
;
3489 return CKR_ATTRIBUTE_VALUE_INVALID
;
3491 attribute
= sftk_FindAttribute(object
,CKA_NETSCAPE_MODULE_SPEC
);
3492 if (attribute
== NULL
) {
3493 return CKR_TEMPLATE_INCOMPLETE
;
3495 paramString
= (char *)attribute
->attrib
.pValue
;
3496 crv
= sftk_parseParameters(paramString
, ¶mStrings
, isFIPS
);
3497 if (crv
!= CKR_OK
) {
3501 /* enforce only one at a time */
3502 if (paramStrings
.token_count
!= 1) {
3503 crv
= CKR_ATTRIBUTE_VALUE_INVALID
;
3507 slotID
= paramStrings
.tokens
[0].slotID
;
3509 /* stay within the valid ID space */
3510 if ((slotID
< idMin
) || (slotID
> idMax
)) {
3511 crv
= CKR_ATTRIBUTE_VALUE_INVALID
;
3515 /* unload any existing slot at this id */
3516 newSlot
= sftk_SlotFromID(slotID
, PR_TRUE
);
3517 if (newSlot
&& newSlot
->present
) {
3518 crv
= SFTK_ShutdownSlot(newSlot
);
3519 if (crv
!= CKR_OK
) {
3524 /* if we were just planning on deleting the slot, then do so now */
3525 if (class == CKO_NETSCAPE_DELSLOT
) {
3526 /* sort of a unconventional use of this error code, be we are
3527 * overusing CKR_ATTRIBUTE_VALUE_INVALID, and it does apply */
3528 crv
= newSlot
? CKR_OK
: CKR_SLOT_ID_INVALID
;
3529 goto loser
; /* really exit */
3533 crv
= SFTK_SlotReInit(newSlot
, paramStrings
.configdir
,
3534 paramStrings
.updatedir
, paramStrings
.updateID
,
3535 ¶mStrings
.tokens
[0], moduleIndex
);
3537 crv
= SFTK_SlotInit(paramStrings
.configdir
,
3538 paramStrings
.updatedir
, paramStrings
.updateID
,
3539 ¶mStrings
.tokens
[0], moduleIndex
);
3541 if (crv
!= CKR_OK
) {
3545 sftk_freeParams(¶mStrings
);
3546 sftk_FreeAttribute(attribute
);
3552 /* NSC_CreateObject creates a new object. */
3553 CK_RV
NSC_CreateObject(CK_SESSION_HANDLE hSession
,
3554 CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulCount
,
3555 CK_OBJECT_HANDLE_PTR phObject
)
3557 SFTKSlot
*slot
= sftk_SlotFromSessionHandle(hSession
);
3558 SFTKSession
*session
;
3560 /* make sure class isn't randomly CKO_NETSCAPE_NEWSLOT or
3561 * CKO_NETSCPE_DELSLOT. */
3562 CK_OBJECT_CLASS
class = CKO_VENDOR_DEFINED
;
3568 *phObject
= CK_INVALID_HANDLE
;
3571 return CKR_SESSION_HANDLE_INVALID
;
3574 * now lets create an object to hang the attributes off of
3576 object
= sftk_NewObject(slot
); /* fill in the handle later */
3577 if (object
== NULL
) {
3578 return CKR_HOST_MEMORY
;
3582 * load the template values into the object
3584 for (i
=0; i
< (int) ulCount
; i
++) {
3585 crv
= sftk_AddAttributeType(object
,sftk_attr_expand(&pTemplate
[i
]));
3586 if (crv
!= CKR_OK
) {
3587 sftk_FreeObject(object
);
3590 if ((pTemplate
[i
].type
== CKA_CLASS
) && pTemplate
[i
].pValue
) {
3591 class = *(CK_OBJECT_CLASS
*)pTemplate
[i
].pValue
;
3595 /* get the session */
3596 session
= sftk_SessionFromHandle(hSession
);
3597 if (session
== NULL
) {
3598 sftk_FreeObject(object
);
3599 return CKR_SESSION_HANDLE_INVALID
;
3603 * handle pseudo objects (CKO_NEWSLOT)
3605 if ((class == CKO_NETSCAPE_NEWSLOT
) || (class == CKO_NETSCAPE_DELSLOT
)) {
3606 crv
= sftk_CreateNewSlot(slot
, class, object
);
3611 * handle the base object stuff
3613 crv
= sftk_handleObject(object
,session
);
3614 *phObject
= object
->handle
;
3616 sftk_FreeSession(session
);
3617 sftk_FreeObject(object
);
3624 /* NSC_CopyObject copies an object, creating a new object for the copy. */
3625 CK_RV
NSC_CopyObject(CK_SESSION_HANDLE hSession
,
3626 CK_OBJECT_HANDLE hObject
, CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulCount
,
3627 CK_OBJECT_HANDLE_PTR phNewObject
)
3629 SFTKObject
*destObject
,*srcObject
;
3630 SFTKSession
*session
;
3632 SFTKSlot
*slot
= sftk_SlotFromSessionHandle(hSession
);
3638 return CKR_SESSION_HANDLE_INVALID
;
3640 /* Get srcObject so we can find the class */
3641 session
= sftk_SessionFromHandle(hSession
);
3642 if (session
== NULL
) {
3643 return CKR_SESSION_HANDLE_INVALID
;
3645 srcObject
= sftk_ObjectFromHandle(hObject
,session
);
3646 if (srcObject
== NULL
) {
3647 sftk_FreeSession(session
);
3648 return CKR_OBJECT_HANDLE_INVALID
;
3651 * create an object to hang the attributes off of
3653 destObject
= sftk_NewObject(slot
); /* fill in the handle later */
3654 if (destObject
== NULL
) {
3655 sftk_FreeSession(session
);
3656 sftk_FreeObject(srcObject
);
3657 return CKR_HOST_MEMORY
;
3661 * load the template values into the object
3663 for (i
=0; i
< (int) ulCount
; i
++) {
3664 if (sftk_modifyType(pTemplate
[i
].type
,srcObject
->objclass
) == SFTK_NEVER
) {
3665 crv
= CKR_ATTRIBUTE_READ_ONLY
;
3668 crv
= sftk_AddAttributeType(destObject
,sftk_attr_expand(&pTemplate
[i
]));
3669 if (crv
!= CKR_OK
) { break; }
3671 if (crv
!= CKR_OK
) {
3672 sftk_FreeSession(session
);
3673 sftk_FreeObject(srcObject
);
3674 sftk_FreeObject(destObject
);
3678 /* sensitive can only be changed to CK_TRUE */
3679 if (sftk_hasAttribute(destObject
,CKA_SENSITIVE
)) {
3680 if (!sftk_isTrue(destObject
,CKA_SENSITIVE
)) {
3681 sftk_FreeSession(session
);
3682 sftk_FreeObject(srcObject
);
3683 sftk_FreeObject(destObject
);
3684 return CKR_ATTRIBUTE_READ_ONLY
;
3689 * now copy the old attributes from the new attributes
3691 /* don't create a token object if we aren't in a rw session */
3692 /* we need to hold the lock to copy a consistant version of
3694 crv
= sftk_CopyObject(destObject
,srcObject
);
3696 destObject
->objclass
= srcObject
->objclass
;
3697 sftk_FreeObject(srcObject
);
3698 if (crv
!= CKR_OK
) {
3699 sftk_FreeObject(destObject
);
3700 sftk_FreeSession(session
);
3704 crv
= sftk_handleObject(destObject
,session
);
3705 *phNewObject
= destObject
->handle
;
3706 sftk_FreeSession(session
);
3707 sftk_FreeObject(destObject
);
3713 /* NSC_GetObjectSize gets the size of an object in bytes. */
3714 CK_RV
NSC_GetObjectSize(CK_SESSION_HANDLE hSession
,
3715 CK_OBJECT_HANDLE hObject
, CK_ULONG_PTR pulSize
)
3724 /* NSC_GetAttributeValue obtains the value of one or more object attributes. */
3725 CK_RV
NSC_GetAttributeValue(CK_SESSION_HANDLE hSession
,
3726 CK_OBJECT_HANDLE hObject
,CK_ATTRIBUTE_PTR pTemplate
,CK_ULONG ulCount
)
3728 SFTKSlot
*slot
= sftk_SlotFromSessionHandle(hSession
);
3729 SFTKSession
*session
;
3731 SFTKAttribute
*attribute
;
3739 return CKR_SESSION_HANDLE_INVALID
;
3742 * make sure we're allowed
3744 session
= sftk_SessionFromHandle(hSession
);
3745 if (session
== NULL
) {
3746 return CKR_SESSION_HANDLE_INVALID
;
3749 /* short circuit everything for token objects */
3750 if (sftk_isToken(hObject
)) {
3751 SFTKSlot
*slot
= sftk_SlotFromSession(session
);
3752 SFTKDBHandle
*dbHandle
= sftk_getDBForTokenObject(slot
, hObject
);
3753 SFTKDBHandle
*keydb
= NULL
;
3755 if (dbHandle
== NULL
) {
3756 sftk_FreeSession(session
);
3757 return CKR_OBJECT_HANDLE_INVALID
;
3760 crv
= sftkdb_GetAttributeValue(dbHandle
, hObject
, pTemplate
, ulCount
);
3762 /* make sure we don't export any sensitive information */
3763 keydb
= sftk_getKeyDB(slot
);
3764 if (dbHandle
== keydb
) {
3765 for (i
=0; i
< (int) ulCount
; i
++) {
3766 if (sftk_isSensitive(pTemplate
[i
].type
,CKO_PRIVATE_KEY
)) {
3767 crv
= CKR_ATTRIBUTE_SENSITIVE
;
3768 if (pTemplate
[i
].pValue
&& (pTemplate
[i
].ulValueLen
!= -1)){
3769 PORT_Memset(pTemplate
[i
].pValue
, 0,
3770 pTemplate
[i
].ulValueLen
);
3772 pTemplate
[i
].ulValueLen
= -1;
3777 sftk_FreeSession(session
);
3778 sftk_freeDB(dbHandle
);
3785 /* handle the session object */
3786 object
= sftk_ObjectFromHandle(hObject
,session
);
3787 sftk_FreeSession(session
);
3788 if (object
== NULL
) {
3789 return CKR_OBJECT_HANDLE_INVALID
;
3792 /* don't read a private object if we aren't logged in */
3793 if ((!slot
->isLoggedIn
) && (slot
->needLogin
) &&
3794 (sftk_isTrue(object
,CKA_PRIVATE
))) {
3795 sftk_FreeObject(object
);
3796 return CKR_USER_NOT_LOGGED_IN
;
3800 sensitive
= sftk_isTrue(object
,CKA_SENSITIVE
);
3801 for (i
=0; i
< (int) ulCount
; i
++) {
3802 /* Make sure that this attribute is retrievable */
3803 if (sensitive
&& sftk_isSensitive(pTemplate
[i
].type
,object
->objclass
)) {
3804 crv
= CKR_ATTRIBUTE_SENSITIVE
;
3805 pTemplate
[i
].ulValueLen
= -1;
3808 attribute
= sftk_FindAttribute(object
,pTemplate
[i
].type
);
3809 if (attribute
== NULL
) {
3810 crv
= CKR_ATTRIBUTE_TYPE_INVALID
;
3811 pTemplate
[i
].ulValueLen
= -1;
3814 if (pTemplate
[i
].pValue
!= NULL
) {
3815 PORT_Memcpy(pTemplate
[i
].pValue
,attribute
->attrib
.pValue
,
3816 attribute
->attrib
.ulValueLen
);
3818 pTemplate
[i
].ulValueLen
= attribute
->attrib
.ulValueLen
;
3819 sftk_FreeAttribute(attribute
);
3822 sftk_FreeObject(object
);
3826 /* NSC_SetAttributeValue modifies the value of one or more object attributes */
3827 CK_RV
NSC_SetAttributeValue (CK_SESSION_HANDLE hSession
,
3828 CK_OBJECT_HANDLE hObject
,CK_ATTRIBUTE_PTR pTemplate
,CK_ULONG ulCount
)
3830 SFTKSlot
*slot
= sftk_SlotFromSessionHandle(hSession
);
3831 SFTKSession
*session
;
3832 SFTKAttribute
*attribute
;
3842 return CKR_SESSION_HANDLE_INVALID
;
3845 * make sure we're allowed
3847 session
= sftk_SessionFromHandle(hSession
);
3848 if (session
== NULL
) {
3849 return CKR_SESSION_HANDLE_INVALID
;
3852 object
= sftk_ObjectFromHandle(hObject
,session
);
3853 if (object
== NULL
) {
3854 sftk_FreeSession(session
);
3855 return CKR_OBJECT_HANDLE_INVALID
;
3858 /* don't modify a private object if we aren't logged in */
3859 if ((!slot
->isLoggedIn
) && (slot
->needLogin
) &&
3860 (sftk_isTrue(object
,CKA_PRIVATE
))) {
3861 sftk_FreeSession(session
);
3862 sftk_FreeObject(object
);
3863 return CKR_USER_NOT_LOGGED_IN
;
3866 /* don't modify a token object if we aren't in a rw session */
3867 isToken
= sftk_isTrue(object
,CKA_TOKEN
);
3868 if (((session
->info
.flags
& CKF_RW_SESSION
) == 0) && isToken
) {
3869 sftk_FreeSession(session
);
3870 sftk_FreeObject(object
);
3871 return CKR_SESSION_READ_ONLY
;
3873 sftk_FreeSession(session
);
3875 /* only change modifiable objects */
3876 if (!sftk_isTrue(object
,CKA_MODIFIABLE
)) {
3877 sftk_FreeObject(object
);
3878 return CKR_ATTRIBUTE_READ_ONLY
;
3881 for (i
=0; i
< (int) ulCount
; i
++) {
3882 /* Make sure that this attribute is changeable */
3883 switch (sftk_modifyType(pTemplate
[i
].type
,object
->objclass
)) {
3887 crv
= CKR_ATTRIBUTE_READ_ONLY
;
3890 case SFTK_SENSITIVE
:
3891 legal
= (pTemplate
[i
].type
== CKA_EXTRACTABLE
) ? CK_FALSE
: CK_TRUE
;
3892 if ((*(CK_BBOOL
*)pTemplate
[i
].pValue
) != legal
) {
3893 crv
= CKR_ATTRIBUTE_READ_ONLY
;
3899 if (crv
!= CKR_OK
) break;
3901 /* find the old attribute */
3902 attribute
= sftk_FindAttribute(object
,pTemplate
[i
].type
);
3903 if (attribute
== NULL
) {
3904 crv
=CKR_ATTRIBUTE_TYPE_INVALID
;
3907 sftk_FreeAttribute(attribute
);
3908 crv
= sftk_forceAttribute(object
,sftk_attr_expand(&pTemplate
[i
]));
3909 if (crv
!= CKR_OK
) break;
3913 sftk_FreeObject(object
);
3918 sftk_expandSearchList(SFTKSearchResults
*search
, int count
)
3920 search
->array_size
+= count
;
3921 search
->handles
= (CK_OBJECT_HANDLE
*)PORT_Realloc(search
->handles
,
3922 sizeof(CK_OBJECT_HANDLE
)*search
->array_size
);
3923 return search
->handles
? CKR_OK
: CKR_HOST_MEMORY
;
3929 sftk_searchDatabase(SFTKDBHandle
*handle
, SFTKSearchResults
*search
,
3930 const CK_ATTRIBUTE
*pTemplate
, CK_LONG ulCount
)
3933 int objectListSize
= search
->array_size
-search
->size
;
3934 CK_OBJECT_HANDLE
*array
= &search
->handles
[search
->size
];
3938 crv
= sftkdb_FindObjectsInit(handle
, pTemplate
, ulCount
, &find
);
3942 crv
= sftkdb_FindObjects(handle
, find
, array
, objectListSize
, &count
);
3943 if ((crv
!= CKR_OK
) || (count
== 0))
3945 search
->size
+= count
;
3946 objectListSize
-= count
;
3947 if (objectListSize
> 0)
3949 crv
= sftk_expandSearchList(search
,NSC_SEARCH_BLOCK_SIZE
);
3950 objectListSize
= NSC_SEARCH_BLOCK_SIZE
;
3951 array
= &search
->handles
[search
->size
];
3952 } while (crv
== CKR_OK
);
3953 sftkdb_FindObjectsFinal(handle
, find
);
3958 /* softoken used to search the SMimeEntries automatically instead of
3959 * doing this in pk11wrap. This code should really be up in
3960 * pk11wrap so that it will work with other tokens other than softoken.
3963 sftk_emailhack(SFTKSlot
*slot
, SFTKDBHandle
*handle
,
3964 SFTKSearchResults
*search
, CK_ATTRIBUTE
*pTemplate
, CK_LONG ulCount
)
3966 PRBool isCert
= PR_FALSE
;
3967 int emailIndex
= -1;
3969 SFTKSearchResults smime_search
;
3970 CK_ATTRIBUTE smime_template
[2];
3971 CK_OBJECT_CLASS smime_class
= CKO_NETSCAPE_SMIME
;
3972 SFTKAttribute
*attribute
= NULL
;
3973 SFTKObject
*object
= NULL
;
3977 smime_search
.handles
= NULL
; /* paranoia, some one is bound to add a goto
3978 * loser before this gets initialized */
3980 /* see if we are looking for email certs */
3981 for (i
=0; i
< ulCount
; i
++) {
3982 if (pTemplate
[i
].type
== CKA_CLASS
) {
3983 if ((pTemplate
[i
].ulValueLen
!= sizeof(CK_OBJECT_CLASS
) ||
3984 (*(CK_OBJECT_CLASS
*)pTemplate
[i
].pValue
) != CKO_CERTIFICATE
)) {
3985 /* not a cert, skip out */
3989 } else if (pTemplate
[i
].type
== CKA_NETSCAPE_EMAIL
) {
3993 if (isCert
&& (emailIndex
!= -1)) break;
3996 if (!isCert
|| (emailIndex
== -1)) {
4000 /* we are doing a cert and email search, find the SMimeEntry */
4001 smime_template
[0].type
= CKA_CLASS
;
4002 smime_template
[0].pValue
= &smime_class
;
4003 smime_template
[0].ulValueLen
= sizeof(smime_class
);
4004 smime_template
[1] = pTemplate
[emailIndex
];
4006 smime_search
.handles
= (CK_OBJECT_HANDLE
*)
4007 PORT_Alloc(sizeof(CK_OBJECT_HANDLE
) * NSC_SEARCH_BLOCK_SIZE
);
4008 if (smime_search
.handles
== NULL
) {
4009 crv
= CKR_HOST_MEMORY
;
4012 smime_search
.index
= 0;
4013 smime_search
.size
= 0;
4014 smime_search
.array_size
= NSC_SEARCH_BLOCK_SIZE
;
4016 crv
= sftk_searchDatabase(handle
, &smime_search
, smime_template
, 2);
4017 if (crv
!= CKR_OK
|| smime_search
.size
== 0) {
4021 /* get the SMime subject */
4022 object
= sftk_NewTokenObject(slot
, NULL
, smime_search
.handles
[0]);
4023 if (object
== NULL
) {
4024 crv
= CKR_HOST_MEMORY
; /* is there any other reason for this failure? */
4027 attribute
= sftk_FindAttribute(object
,CKA_SUBJECT
);
4028 if (attribute
== NULL
) {
4029 crv
= CKR_ATTRIBUTE_TYPE_INVALID
;
4033 /* now find the certs with that subject */
4034 pTemplate
[emailIndex
] = attribute
->attrib
;
4035 /* now add the appropriate certs to the search list */
4036 crv
= sftk_searchDatabase(handle
, search
, pTemplate
, ulCount
);
4037 pTemplate
[emailIndex
] = smime_template
[1]; /* restore the user's template*/
4041 sftk_FreeAttribute(attribute
);
4044 sftk_FreeObject(object
);
4046 if (smime_search
.handles
) {
4047 PORT_Free(smime_search
.handles
);
4055 sftk_searchTokenList(SFTKSlot
*slot
, SFTKSearchResults
*search
,
4056 CK_ATTRIBUTE
*pTemplate
, CK_LONG ulCount
,
4057 PRBool
*tokenOnly
, PRBool isLoggedIn
)
4061 SFTKDBHandle
*certHandle
= sftk_getCertDB(slot
);
4063 crv
= sftk_searchDatabase(certHandle
, search
, pTemplate
, ulCount
);
4064 crv2
= sftk_emailhack(slot
, certHandle
, search
, pTemplate
, ulCount
);
4065 if (crv
== CKR_OK
) crv2
= crv
;
4066 sftk_freeDB(certHandle
);
4068 if (crv
== CKR_OK
&& isLoggedIn
) {
4069 SFTKDBHandle
*keyHandle
= sftk_getKeyDB(slot
);
4070 crv
= sftk_searchDatabase(keyHandle
, search
, pTemplate
, ulCount
);
4071 sftk_freeDB(keyHandle
);
4076 /* NSC_FindObjectsInit initializes a search for token and session objects
4077 * that match a template. */
4078 CK_RV
NSC_FindObjectsInit(CK_SESSION_HANDLE hSession
,
4079 CK_ATTRIBUTE_PTR pTemplate
,CK_ULONG ulCount
)
4081 SFTKSearchResults
*search
= NULL
, *freeSearch
= NULL
;
4082 SFTKSession
*session
= NULL
;
4083 SFTKSlot
*slot
= sftk_SlotFromSessionHandle(hSession
);
4084 PRBool tokenOnly
= PR_FALSE
;
4091 return CKR_SESSION_HANDLE_INVALID
;
4093 session
= sftk_SessionFromHandle(hSession
);
4094 if (session
== NULL
) {
4095 crv
= CKR_SESSION_HANDLE_INVALID
;
4099 search
= (SFTKSearchResults
*)PORT_Alloc(sizeof(SFTKSearchResults
));
4100 if (search
== NULL
) {
4101 crv
= CKR_HOST_MEMORY
;
4104 search
->handles
= (CK_OBJECT_HANDLE
*)
4105 PORT_Alloc(sizeof(CK_OBJECT_HANDLE
) * NSC_SEARCH_BLOCK_SIZE
);
4106 if (search
->handles
== NULL
) {
4107 crv
= CKR_HOST_MEMORY
;
4112 search
->array_size
= NSC_SEARCH_BLOCK_SIZE
;
4113 isLoggedIn
= (PRBool
)((!slot
->needLogin
) || slot
->isLoggedIn
);
4115 crv
= sftk_searchTokenList(slot
, search
, pTemplate
, ulCount
, &tokenOnly
,
4117 if (crv
!= CKR_OK
) {
4121 /* build list of found objects in the session */
4123 crv
= sftk_searchObjectList(search
, slot
->sessObjHashTable
,
4124 slot
->sessObjHashSize
, slot
->objectLock
,
4125 pTemplate
, ulCount
, isLoggedIn
);
4127 if (crv
!= CKR_OK
) {
4131 if ((freeSearch
= session
->search
) != NULL
) {
4132 session
->search
= NULL
;
4133 sftk_FreeSearch(freeSearch
);
4135 session
->search
= search
;
4136 sftk_FreeSession(session
);
4141 sftk_FreeSearch(search
);
4144 sftk_FreeSession(session
);
4150 /* NSC_FindObjects continues a search for token and session objects
4151 * that match a template, obtaining additional object handles. */
4152 CK_RV
NSC_FindObjects(CK_SESSION_HANDLE hSession
,
4153 CK_OBJECT_HANDLE_PTR phObject
,CK_ULONG ulMaxObjectCount
,
4154 CK_ULONG_PTR pulObjectCount
)
4156 SFTKSession
*session
;
4157 SFTKSearchResults
*search
;
4163 *pulObjectCount
= 0;
4164 session
= sftk_SessionFromHandle(hSession
);
4165 if (session
== NULL
) return CKR_SESSION_HANDLE_INVALID
;
4166 if (session
->search
== NULL
) {
4167 sftk_FreeSession(session
);
4170 search
= session
->search
;
4171 left
= session
->search
->size
- session
->search
->index
;
4172 transfer
= ((int)ulMaxObjectCount
> left
) ? left
: ulMaxObjectCount
;
4174 PORT_Memcpy(phObject
,&search
->handles
[search
->index
],
4175 transfer
*sizeof(CK_OBJECT_HANDLE
));
4177 *phObject
= CK_INVALID_HANDLE
;
4180 search
->index
+= transfer
;
4181 if (search
->index
== search
->size
) {
4182 session
->search
= NULL
;
4183 sftk_FreeSearch(search
);
4185 *pulObjectCount
= transfer
;
4186 sftk_FreeSession(session
);
4190 /* NSC_FindObjectsFinal finishes a search for token and session objects. */
4191 CK_RV
NSC_FindObjectsFinal(CK_SESSION_HANDLE hSession
)
4193 SFTKSession
*session
;
4194 SFTKSearchResults
*search
;
4198 session
= sftk_SessionFromHandle(hSession
);
4199 if (session
== NULL
) return CKR_SESSION_HANDLE_INVALID
;
4200 search
= session
->search
;
4201 session
->search
= NULL
;
4202 sftk_FreeSession(session
);
4203 if (search
!= NULL
) {
4204 sftk_FreeSearch(search
);
4211 CK_RV
NSC_WaitForSlotEvent(CK_FLAGS flags
, CK_SLOT_ID_PTR pSlot
,
4212 CK_VOID_PTR pReserved
)
4216 return CKR_FUNCTION_NOT_SUPPORTED
;