xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSlotToken.c (revision 5328fc53d11d7151861fa272e4fb0248b8f0e145)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright 2018, Joyent, Inc.
25  */
26 
27 #include <strings.h>
28 #include <cryptoutil.h>
29 #include <security/cryptoki.h>
30 #include <sys/crypto/common.h>
31 #include <arcfour.h>
32 #include "softGlobal.h"
33 #include "softSession.h"
34 #include <aes_impl.h>
35 #include <blowfish_impl.h>
36 #include <des_impl.h>
37 #include <ecc_impl.h>
38 #include "softDH.h"
39 #include "softObject.h"
40 #include "softKeystore.h"
41 #include "softKeystoreUtil.h"
42 
43 
44 static CK_MECHANISM_TYPE soft_mechanisms[] = {
45 	CKM_DES_CBC,
46 	CKM_DES_CBC_PAD,
47 	CKM_DES_ECB,
48 	CKM_DES_KEY_GEN,
49 	CKM_DES_MAC_GENERAL,
50 	CKM_DES_MAC,
51 	CKM_DES3_CBC,
52 	CKM_DES3_CBC_PAD,
53 	CKM_DES3_ECB,
54 	CKM_DES2_KEY_GEN,
55 	CKM_DES3_KEY_GEN,
56 	CKM_AES_CBC,
57 	CKM_AES_CBC_PAD,
58 	CKM_AES_CTR,
59 	CKM_AES_CMAC_GENERAL,
60 	CKM_AES_CMAC,
61 	CKM_AES_ECB,
62 	CKM_AES_KEY_GEN,
63 	CKM_AES_GCM,
64 	CKM_AES_CCM,
65 	CKM_BLOWFISH_CBC,
66 	CKM_BLOWFISH_KEY_GEN,
67 	CKM_SHA_1,
68 	CKM_SHA_1_HMAC,
69 	CKM_SHA_1_HMAC_GENERAL,
70 	CKM_SHA256,
71 	CKM_SHA256_HMAC,
72 	CKM_SHA256_HMAC_GENERAL,
73 	CKM_SHA384,
74 	CKM_SHA384_HMAC,
75 	CKM_SHA384_HMAC_GENERAL,
76 	CKM_SHA512,
77 	CKM_SHA512_HMAC,
78 	CKM_SHA512_HMAC_GENERAL,
79 	CKM_SHA512_224,
80 	CKM_SHA512_256,
81 	CKM_SSL3_SHA1_MAC,
82 	CKM_MD5,
83 	CKM_MD5_HMAC,
84 	CKM_MD5_HMAC_GENERAL,
85 	CKM_SSL3_MD5_MAC,
86 	CKM_RC4,
87 	CKM_RC4_KEY_GEN,
88 	CKM_DSA,
89 	CKM_DSA_SHA1,
90 	CKM_DSA_KEY_PAIR_GEN,
91 	CKM_RSA_PKCS,
92 	CKM_RSA_PKCS_KEY_PAIR_GEN,
93 	CKM_RSA_X_509,
94 	CKM_MD5_RSA_PKCS,
95 	CKM_SHA1_RSA_PKCS,
96 	CKM_SHA256_RSA_PKCS,
97 	CKM_SHA384_RSA_PKCS,
98 	CKM_SHA512_RSA_PKCS,
99 	CKM_DH_PKCS_KEY_PAIR_GEN,
100 	CKM_DH_PKCS_DERIVE,
101 	CKM_MD5_KEY_DERIVATION,
102 	CKM_SHA1_KEY_DERIVATION,
103 	CKM_SHA256_KEY_DERIVATION,
104 	CKM_SHA384_KEY_DERIVATION,
105 	CKM_SHA512_KEY_DERIVATION,
106 	CKM_SHA512_224_KEY_DERIVATION,
107 	CKM_SHA512_256_KEY_DERIVATION,
108 	CKM_PBE_SHA1_RC4_128,
109 	CKM_PKCS5_PBKD2,
110 	CKM_SSL3_PRE_MASTER_KEY_GEN,
111 	CKM_TLS_PRE_MASTER_KEY_GEN,
112 	CKM_SSL3_MASTER_KEY_DERIVE,
113 	CKM_TLS_MASTER_KEY_DERIVE,
114 	CKM_SSL3_MASTER_KEY_DERIVE_DH,
115 	CKM_TLS_MASTER_KEY_DERIVE_DH,
116 	CKM_SSL3_KEY_AND_MAC_DERIVE,
117 	CKM_TLS_KEY_AND_MAC_DERIVE,
118 	CKM_TLS_PRF,
119 	CKM_EC_KEY_PAIR_GEN,
120 	CKM_ECDSA,
121 	CKM_ECDSA_SHA1,
122 	CKM_ECDH1_DERIVE
123 };
124 
125 /*
126  * This is the table of CK_MECHANISM_INFO structs for the supported mechanisms.
127  * The index for this table is the same as the one above for the same
128  * mechanism.
129  * The minimum and maximum sizes of the key for the mechanism can be measured
130  * in bits or in bytes (i.e. mechanism-dependent). This table specifies the
131  * supported range of key sizes in bytes; unless noted as in bits.
132  */
133 static CK_MECHANISM_INFO soft_mechanism_info[] = {
134 	{DES_MINBYTES, DES_MAXBYTES,
135 		CKF_ENCRYPT|CKF_DECRYPT|
136 		CKF_WRAP|CKF_UNWRAP},		/* CKM_DES_CBC */
137 	{DES_MINBYTES, DES_MAXBYTES,
138 		CKF_ENCRYPT|CKF_DECRYPT|
139 		CKF_WRAP|CKF_UNWRAP},		/* CKM_DES_CBC_PAD */
140 	{DES_MINBYTES, DES_MAXBYTES,
141 		CKF_ENCRYPT|CKF_DECRYPT|
142 		CKF_WRAP|CKF_UNWRAP},		/* CKM_DES_ECB */
143 	{DES_MINBYTES, DES_MAXBYTES,
144 		CKF_GENERATE},			/* CKM_DES_KEY_GEN */
145 	{DES_MINBYTES, DES_MAXBYTES,
146 		CKF_SIGN|CKF_VERIFY},		/* CKM_DES_MAC_GENERAL */
147 	{DES_MINBYTES, DES_MAXBYTES,
148 		CKF_SIGN|CKF_VERIFY},		/* CKM_DES_MAC */
149 	{DES3_MINBYTES, DES3_MAXBYTES,
150 		CKF_ENCRYPT|CKF_DECRYPT|
151 		CKF_WRAP|CKF_UNWRAP},		/* CKM_DES3_CBC */
152 	{DES3_MINBYTES, DES3_MAXBYTES,
153 		CKF_ENCRYPT|CKF_DECRYPT|
154 		CKF_WRAP|CKF_UNWRAP},		/* CKM_DES3_CBC_PAD */
155 	{DES3_MINBYTES, DES3_MAXBYTES,
156 		CKF_ENCRYPT|CKF_DECRYPT|
157 		CKF_WRAP|CKF_UNWRAP},		/* CKM_DES3_ECB */
158 	{DES2_MAXBYTES, DES2_MAXBYTES,
159 		CKF_GENERATE},			/* CKM_DES2_KEY_GEN */
160 	{DES3_MAXBYTES, DES3_MAXBYTES,		/* CKK_DES3 only */
161 		CKF_GENERATE},			/* CKM_DES3_KEY_GEN */
162 	{AES_MINBYTES, AES_MAXBYTES,
163 		CKF_ENCRYPT|CKF_DECRYPT|
164 		CKF_WRAP|CKF_UNWRAP},		/* CKM_AES_CBC */
165 	{AES_MINBYTES, AES_MAXBYTES,
166 		CKF_ENCRYPT|CKF_DECRYPT|
167 		CKF_WRAP|CKF_UNWRAP},		/* CKM_AES_CBC_PAD */
168 	{AES_MINBYTES, AES_MAXBYTES,
169 		CKF_ENCRYPT|CKF_DECRYPT|
170 		CKF_WRAP|CKF_UNWRAP},		/* CKM_AES_CTR */
171 	{AES_MINBYTES, AES_MAXBYTES,
172 		CKF_SIGN|CKF_VERIFY},		/* CKM_AES_CMAC_GENERAL */
173 	{AES_MINBYTES, AES_MAXBYTES,
174 		CKF_SIGN|CKF_VERIFY},		/* CKM_AES_CMAC */
175 	{AES_MINBYTES, AES_MAXBYTES,
176 		CKF_ENCRYPT|CKF_DECRYPT|
177 		CKF_WRAP|CKF_UNWRAP},		/* CKM_AES_ECB */
178 	{AES_MINBYTES, AES_MAXBYTES,
179 		CKF_GENERATE},			/* CKM_AES_KEY_GEN */
180 	{AES_MINBYTES, AES_MAXBYTES,
181 		CKF_ENCRYPT|CKF_DECRYPT|
182 		CKF_WRAP|CKF_UNWRAP},		/* CKM_AES_GCM */
183 	{AES_MINBYTES, AES_MAXBYTES,
184 		CKF_ENCRYPT|CKF_DECRYPT|
185 		CKF_WRAP|CKF_UNWRAP},		/* CKM_AES_CCM */
186 	{BLOWFISH_MINBYTES, BLOWFISH_MAXBYTES,
187 		CKF_ENCRYPT|CKF_DECRYPT|
188 		CKF_WRAP|CKF_UNWRAP},		/* CKM_BLOWFISH_ECB */
189 	{BLOWFISH_MINBYTES, BLOWFISH_MAXBYTES,
190 		CKF_GENERATE},			/* CKM_BLOWFISH_KEY_GEN */
191 	{0, 0, CKF_DIGEST},			/* CKM_SHA_1 */
192 	{1, 64, CKF_SIGN|CKF_VERIFY},		/* CKM_SHA_1_HMAC */
193 	{1, 64, CKF_SIGN|CKF_VERIFY},		/* CKM_SHA_1_HMAC_GENERAL */
194 	{0, 0, CKF_DIGEST},			/* CKM_SHA256 */
195 	{1, 64, CKF_SIGN|CKF_VERIFY},		/* CKM_SHA256_HMAC */
196 	{1, 64, CKF_SIGN|CKF_VERIFY},		/* CKM_SHA256_HMAC_GENERAL */
197 	{0, 0, CKF_DIGEST},			/* CKM_SHA384 */
198 	{1, 128, CKF_SIGN|CKF_VERIFY},		/* CKM_SHA384_HMAC */
199 	{1, 128, CKF_SIGN|CKF_VERIFY},		/* CKM_SHA384_HMAC_GENERAL */
200 	{0, 0, CKF_DIGEST},			/* CKM_SHA512 */
201 	{1, 128, CKF_SIGN|CKF_VERIFY},		/* CKM_SHA512_HMAC */
202 	{1, 128, CKF_SIGN|CKF_VERIFY},		/* CKM_SHA512_HMAC_GENERAL */
203 	{0, 0, CKF_DIGEST},			/* CKM_SHA512_224 */
204 	{0, 0, CKF_DIGEST},			/* CKM_SHA512_256 */
205 	{1, 512, CKF_SIGN|CKF_VERIFY},		/* CKM_SSL3_SHA1_MAC */
206 	{0, 0, CKF_DIGEST},			/* CKM_MD5 */
207 	{1, 64, CKF_SIGN|CKF_VERIFY},		/* CKM_MD5_HMAC */
208 	{1, 64, CKF_SIGN|CKF_VERIFY},		/* CKM_MD5_HMAC_GENERAL */
209 	{1, 512, CKF_SIGN|CKF_VERIFY},		/* CKM_SSL3_MD5_MAC */
210 	{8, ARCFOUR_MAX_KEY_BITS, CKF_ENCRYPT|CKF_DECRYPT}, /* CKM_RC4; */
211 							    /* in bits  */
212 	{8, ARCFOUR_MAX_KEY_BITS, CKF_GENERATE }, /* CKM_RC4_KEY_GEN; in bits */
213 	{512, 1024, CKF_SIGN|CKF_VERIFY},	/* CKM_DSA; in bits */
214 	{512, 1024, CKF_SIGN|CKF_VERIFY},	/* CKM_DSA_SHA1; in bits */
215 	{512, 1024, CKF_GENERATE_KEY_PAIR},	/* CKM_DSA_KEY_PAIR_GEN; */
216 						/* in bits */
217 	{256, 4096, CKF_ENCRYPT|CKF_DECRYPT|
218 		CKF_SIGN|CKF_SIGN_RECOVER|
219 		CKF_WRAP|CKF_UNWRAP|
220 		CKF_VERIFY|CKF_VERIFY_RECOVER},	/* CKM_RSA_PKCS; in bits */
221 	{256, 4096, CKF_GENERATE_KEY_PAIR},	/* CKM_RSA_PKCS_KEY_PAIR_GEN; */
222 						/* in bits */
223 	{256, 4096, CKF_ENCRYPT|CKF_DECRYPT|
224 		CKF_SIGN|CKF_SIGN_RECOVER|
225 		CKF_WRAP|CKF_UNWRAP|
226 		CKF_VERIFY|CKF_VERIFY_RECOVER},	/* CKM_RSA_X_509 in bits */
227 	{256, 4096, CKF_SIGN|CKF_VERIFY},	/* CKM_MD5_RSA_PKCS in bits */
228 	{256, 4096, CKF_SIGN|CKF_VERIFY},	/* CKM_SHA1_RSA_PKCS in bits */
229 	{256, 4096, CKF_SIGN|CKF_VERIFY}, /* CKM_SHA256_RSA_PKCS in bits */
230 	{256, 4096, CKF_SIGN|CKF_VERIFY}, /* CKM_SHA384_RSA_PKCS in bits */
231 	{256, 4096, CKF_SIGN|CKF_VERIFY}, /* CKM_SHA512_RSA_PKCS in bits */
232 	{DH_MIN_KEY_LEN, DH_MAX_KEY_LEN, CKF_GENERATE_KEY_PAIR},
233 						/* CKM_DH_PKCS_KEY_PAIR_GEN */
234 						/* in bits */
235 	{DH_MIN_KEY_LEN, DH_MAX_KEY_LEN, CKF_DERIVE},
236 						/* CKM_DH_PKCS_DERIVE; */
237 						/* in bits */
238 	{1, 16, CKF_DERIVE},		/* CKM_MD5_KEY_DERIVATION */
239 	{1, 20, CKF_DERIVE},		/* CKM_SHA1_KEY_DERIVATION */
240 	{1, 32, CKF_DERIVE},		/* CKM_SHA256_KEY_DERIVATION */
241 	{1, 48, CKF_DERIVE},		/* CKM_SHA384_KEY_DERIVATION */
242 	{1, 64, CKF_DERIVE},		/* CKM_SHA512_KEY_DERIVATION */
243 	{1, 28, CKF_DERIVE},		/* CKM_SHA512_224_KEY_DERIVATION */
244 	{1, 32, CKF_DERIVE},		/* CKM_SHA512_256_KEY_DERIVATION */
245 	{0, 0, CKF_GENERATE},		/* CKM_PBE_SHA1_RC4_128 */
246 	{0, 0, CKF_GENERATE},		/* CKM_PKCS5_PBKD2 */
247 	{48, 48, CKF_GENERATE},		/* CKM_SSL3_PRE_MASTER_KEY_GEN */
248 	{48, 48, CKF_GENERATE},		/* CKM_TLS_PRE_MASTER_KEY_GEN */
249 	{48, 48, CKF_DERIVE},		/* CKM_SSL3_MASTER_KEY_DERIVE */
250 	{48, 48, CKF_DERIVE},		/* CKM_TLS_MASTER_KEY_DERIVE */
251 	{48, 48, CKF_DERIVE},		/* CKM_SSL3_MASTER_KEY_DERIVE_DH */
252 	{48, 48, CKF_DERIVE},		/* CKM_TLS_MASTER_KEY_DERIVE_DH */
253 	{0, 0, CKF_DERIVE},		/* CKM_SSL3_KEY_AND_MAC_DERIVE */
254 	{0, 0, CKF_DERIVE},		/* CKM_TLS_KEY_AND_MAC_DERIVE */
255 	{0, 0, CKF_DERIVE},		/* CKM_TLS_PRF */
256 	{EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, CKF_GENERATE_KEY_PAIR},
257 	{EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, CKF_SIGN|CKF_VERIFY},
258 	{EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, CKF_SIGN|CKF_VERIFY},
259 	{EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, CKF_DERIVE}
260 };
261 
262 /*
263  * Slot ID for softtoken is always 1. tokenPresent is ignored.
264  * Also, only one slot is used.
265  */
266 /*ARGSUSED*/
267 CK_RV
268 C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
269     CK_ULONG_PTR pulCount)
270 {
271 
272 	CK_RV rv;
273 
274 	if (!softtoken_initialized)
275 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
276 
277 	if (pulCount == NULL) {
278 		return (CKR_ARGUMENTS_BAD);
279 	}
280 
281 	if (pSlotList == NULL) {
282 		/*
283 		 * Application only wants to know the number of slots.
284 		 */
285 		*pulCount = 1;
286 		return (CKR_OK);
287 	}
288 
289 	if ((*pulCount < 1) && (pSlotList != NULL)) {
290 		rv = CKR_BUFFER_TOO_SMALL;
291 	} else {
292 		pSlotList[0] = SOFTTOKEN_SLOTID;
293 		rv = CKR_OK;
294 	}
295 
296 	*pulCount = 1;
297 	return (rv);
298 }
299 
300 
301 CK_RV
302 C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
303 {
304 
305 	if (!softtoken_initialized)
306 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
307 
308 	if (pInfo == NULL)
309 		return (CKR_ARGUMENTS_BAD);
310 
311 	/* Make sure the slot ID is valid */
312 	if (slotID != SOFTTOKEN_SLOTID)
313 		return (CKR_SLOT_ID_INVALID);
314 
315 	/* Provide information about the slot in the provided buffer */
316 	(void) strncpy((char *)pInfo->slotDescription, SOFT_SLOT_DESCRIPTION,
317 	    64);
318 	(void) strncpy((char *)pInfo->manufacturerID, SOFT_MANUFACTURER_ID, 32);
319 	pInfo->flags = CKF_TOKEN_PRESENT;
320 	pInfo->hardwareVersion.major = HARDWARE_VERSION_MAJOR;
321 	pInfo->hardwareVersion.minor = HARDWARE_VERSION_MINOR;
322 	pInfo->firmwareVersion.major = FIRMWARE_VERSION_MAJOR;
323 	pInfo->firmwareVersion.minor = FIRMWARE_VERSION_MINOR;
324 
325 	return (CKR_OK);
326 }
327 
328 CK_RV
329 C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
330 {
331 	boolean_t pin_initialized = B_FALSE;
332 	char	*ks_cryptpin = NULL;
333 
334 	if (!softtoken_initialized)
335 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
336 
337 	/* Make sure the slot ID is valid */
338 	if (slotID != SOFTTOKEN_SLOTID)
339 		return (CKR_SLOT_ID_INVALID);
340 
341 	if (pInfo == NULL)
342 		return (CKR_ARGUMENTS_BAD);
343 
344 	/*
345 	 * It is intentional that we don't forward the error code
346 	 * returned from soft_keystore_pin_initialized() to the caller
347 	 */
348 	pInfo->flags = SOFT_TOKEN_FLAGS;
349 	if (soft_slot.keystore_load_status == KEYSTORE_UNAVAILABLE) {
350 		pInfo->flags |= CKF_WRITE_PROTECTED;
351 	} else {
352 		if ((soft_keystore_pin_initialized(&pin_initialized,
353 		    &ks_cryptpin, B_FALSE) == CKR_OK) && !pin_initialized)
354 			pInfo->flags |= CKF_USER_PIN_TO_BE_CHANGED;
355 	}
356 
357 	if (ks_cryptpin != NULL) {
358 		size_t cplen = strlen(ks_cryptpin) + 1;
359 
360 		freezero(ks_cryptpin, cplen);
361 	}
362 
363 	/* Provide information about a token in the provided buffer */
364 	(void) strncpy((char *)pInfo->label, SOFT_TOKEN_LABEL, 32);
365 	(void) strncpy((char *)pInfo->manufacturerID, SOFT_MANUFACTURER_ID, 32);
366 	(void) strncpy((char *)pInfo->model, TOKEN_MODEL, 16);
367 	(void) strncpy((char *)pInfo->serialNumber, SOFT_TOKEN_SERIAL, 16);
368 
369 	pInfo->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE;
370 	pInfo->ulSessionCount = soft_session_cnt;
371 	pInfo->ulMaxRwSessionCount = CK_EFFECTIVELY_INFINITE;
372 	pInfo->ulRwSessionCount = soft_session_rw_cnt;
373 	pInfo->ulMaxPinLen = MAX_PIN_LEN;
374 	pInfo->ulMinPinLen = MIN_PIN_LEN;
375 	pInfo->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
376 	pInfo->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
377 	pInfo->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
378 	pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
379 	pInfo->hardwareVersion.major = HARDWARE_VERSION_MAJOR;
380 	pInfo->hardwareVersion.minor = HARDWARE_VERSION_MINOR;
381 	pInfo->firmwareVersion.major = FIRMWARE_VERSION_MAJOR;
382 	pInfo->firmwareVersion.minor = FIRMWARE_VERSION_MINOR;
383 	(void) memset(pInfo->utcTime, ' ', 16);
384 
385 	return (CKR_OK);
386 }
387 
388 /*ARGSUSED*/
389 CK_RV
390 C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved)
391 {
392 	if (!softtoken_initialized)
393 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
394 
395 	/*
396 	 * This is currently not implemented, however we could cause this
397 	 * to wait for the token files to appear if soft_token_present is
398 	 * false.
399 	 * However there is currently no polite and portable way to do that
400 	 * because we might not even be able to get to an fd to the
401 	 * parent directory, so instead we don't support any slot events.
402 	 */
403 	return (CKR_FUNCTION_NOT_SUPPORTED);
404 }
405 
406 
407 CK_RV
408 C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList,
409     CK_ULONG_PTR pulCount)
410 {
411 
412 	ulong_t i;
413 	ulong_t mechnum;
414 
415 	if (!softtoken_initialized)
416 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
417 
418 	if (slotID != SOFTTOKEN_SLOTID)
419 		return (CKR_SLOT_ID_INVALID);
420 
421 	mechnum = sizeof (soft_mechanisms) / sizeof (CK_MECHANISM_TYPE);
422 
423 	if (pMechanismList == NULL) {
424 		/*
425 		 * Application only wants to know the number of
426 		 * supported mechanism types.
427 		 */
428 		*pulCount = mechnum;
429 		return (CKR_OK);
430 	}
431 
432 	if (*pulCount < mechnum) {
433 		*pulCount = mechnum;
434 		return (CKR_BUFFER_TOO_SMALL);
435 	}
436 
437 	for (i = 0; i < mechnum; i++) {
438 		pMechanismList[i] = soft_mechanisms[i];
439 	}
440 
441 	*pulCount = mechnum;
442 
443 	return (CKR_OK);
444 }
445 
446 
447 CK_RV
448 C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
449     CK_MECHANISM_INFO_PTR pInfo)
450 {
451 
452 	ulong_t i;
453 	ulong_t mechnum;
454 
455 	if (!softtoken_initialized)
456 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
457 
458 	if (slotID != SOFTTOKEN_SLOTID)
459 		return (CKR_SLOT_ID_INVALID);
460 
461 	if (pInfo == NULL) {
462 		return (CKR_ARGUMENTS_BAD);
463 	}
464 
465 	mechnum = sizeof (soft_mechanisms) / sizeof (CK_MECHANISM_TYPE);
466 	for (i = 0; i < mechnum; i++) {
467 		if (soft_mechanisms[i] == type)
468 			break;
469 	}
470 
471 	if (i == mechnum)
472 		/* unsupported mechanism */
473 		return (CKR_MECHANISM_INVALID);
474 
475 	pInfo->ulMinKeySize = soft_mechanism_info[i].ulMinKeySize;
476 	pInfo->ulMaxKeySize = soft_mechanism_info[i].ulMaxKeySize;
477 	pInfo->flags = soft_mechanism_info[i].flags;
478 
479 	return (CKR_OK);
480 }
481 
482 
483 /*ARGSUSED*/
484 CK_RV
485 C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen,
486     CK_UTF8CHAR_PTR pLabel)
487 {
488 	if (!softtoken_initialized)
489 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
490 
491 	if (create_keystore() != 0)
492 		return (CKR_FUNCTION_FAILED);
493 
494 	return (CKR_OK);
495 }
496 
497 /*ARGSUSED*/
498 CK_RV
499 C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
500 {
501 	if (!softtoken_initialized)
502 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
503 
504 	return (CKR_FUNCTION_NOT_SUPPORTED);
505 }
506 
507 
508 CK_RV
509 C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin,
510     CK_ULONG ulOldPinLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewPinLen)
511 {
512 
513 	soft_session_t *session_p;
514 	CK_RV rv;
515 	boolean_t lock_held = B_FALSE;
516 
517 	if (!softtoken_initialized)
518 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
519 
520 	/*
521 	 * Obtain the session pointer. Also, increment the session
522 	 * reference count.
523 	 */
524 	rv = handle2session(hSession, &session_p);
525 	if (rv != CKR_OK)
526 		return (rv);
527 
528 	if (!soft_keystore_status(KEYSTORE_LOAD)) {
529 		SES_REFRELE(session_p, lock_held);
530 		return (CKR_DEVICE_REMOVED);
531 	}
532 
533 	if ((ulOldPinLen < MIN_PIN_LEN) || (ulOldPinLen > MAX_PIN_LEN) ||
534 	    (ulNewPinLen < MIN_PIN_LEN) ||(ulNewPinLen > MAX_PIN_LEN)) {
535 		SES_REFRELE(session_p, lock_held);
536 		return (CKR_PIN_LEN_RANGE);
537 	}
538 
539 	if ((pOldPin == NULL_PTR) || (pNewPin == NULL_PTR)) {
540 		/*
541 		 * We don't support CKF_PROTECTED_AUTHENTICATION_PATH
542 		 */
543 		SES_REFRELE(session_p, lock_held);
544 		return (CKR_ARGUMENTS_BAD);
545 	}
546 
547 	/* check the state of the session */
548 	if ((session_p->state != CKS_RW_PUBLIC_SESSION) &&
549 	    (session_p->state != CKS_RW_USER_FUNCTIONS)) {
550 		SES_REFRELE(session_p, lock_held);
551 		return (CKR_SESSION_READ_ONLY);
552 	}
553 
554 	rv = soft_setpin(pOldPin, ulOldPinLen, pNewPin, ulNewPinLen);
555 
556 	SES_REFRELE(session_p, lock_held);
557 	return (rv);
558 }
559