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