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