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