xref: /titanic_50/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeysUtil.c (revision 84f7a9b9dca4f23b5f50edef0e59d7eb44301114)
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 <pthread.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <strings.h>
33 #include <sys/types.h>
34 #include <security/cryptoki.h>
35 #include <aes_impl.h>
36 #include <blowfish_impl.h>
37 #include <des_impl.h>
38 #include <arcfour.h>
39 #include "softGlobal.h"
40 #include "softSession.h"
41 #include "softObject.h"
42 #include "softDSA.h"
43 #include "softRSA.h"
44 #include "softDH.h"
45 #include "softRandom.h"
46 #include "softMAC.h"
47 #include "softOps.h"
48 #include "softKeys.h"
49 #include "softKeystore.h"
50 #include "softSSL.h"
51 #include "softASN1.h"
52 
53 
54 #define	local_min(a, b)	((a) < (b) ? (a) : (b))
55 
56 static CK_RV
57 soft_pkcs12_pbe(soft_session_t *, CK_MECHANISM_PTR, soft_object_t *);
58 
59 /*
60  * Create a temporary key object struct by filling up its template attributes.
61  */
62 CK_RV
63 soft_gen_keyobject(CK_ATTRIBUTE_PTR pTemplate,  CK_ULONG ulCount,
64     CK_ULONG *objecthandle_p, soft_session_t *sp,
65     CK_OBJECT_CLASS class, CK_KEY_TYPE key_type, CK_ULONG keylen, CK_ULONG mode,
66     boolean_t internal)
67 {
68 
69 	CK_RV rv;
70 	soft_object_t *new_objp = NULL;
71 
72 	new_objp = calloc(1, sizeof (soft_object_t));
73 	if (new_objp == NULL) {
74 		return (CKR_HOST_MEMORY);
75 	}
76 
77 	new_objp->extra_attrlistp = NULL;
78 
79 	/*
80 	 * Validate attribute template and fill in the attributes
81 	 * in the soft_object_t.
82 	 */
83 	rv = soft_build_key(pTemplate, ulCount, new_objp, class, key_type,
84 	    keylen, mode);
85 	if (rv != CKR_OK) {
86 		goto fail_cleanup1;
87 	}
88 
89 	/*
90 	 * If generating a key is an internal request (i.e. not a C_XXX
91 	 * API request), then skip the following checks.
92 	 */
93 	if (!internal) {
94 		rv = soft_pin_expired_check(new_objp);
95 		if (rv != CKR_OK) {
96 			goto fail_cleanup2;
97 		}
98 
99 		rv = soft_object_write_access_check(sp, new_objp);
100 		if (rv != CKR_OK) {
101 			goto fail_cleanup2;
102 		}
103 	}
104 
105 	/* Initialize the rest of stuffs in soft_object_t. */
106 	(void) pthread_mutex_init(&new_objp->object_mutex, NULL);
107 	new_objp->magic_marker = SOFTTOKEN_OBJECT_MAGIC;
108 
109 	/* Write the new token object to the keystore */
110 	if (IS_TOKEN_OBJECT(new_objp)) {
111 		new_objp->version = 1;
112 		new_objp->session_handle = (CK_SESSION_HANDLE)NULL;
113 		soft_add_token_object_to_slot(new_objp);
114 		/*
115 		 * Type casting the address of an object struct to
116 		 * an object handle.
117 		 */
118 		*objecthandle_p = (CK_ULONG)new_objp;
119 
120 		return (CKR_OK);
121 	}
122 
123 	new_objp->session_handle = (CK_SESSION_HANDLE)sp;
124 
125 	/* Add the new object to the session's object list. */
126 	soft_add_object_to_session(new_objp, sp);
127 
128 	/* Type casting the address of an object struct to an object handle. */
129 	*objecthandle_p =  (CK_ULONG)new_objp;
130 
131 	return (CKR_OK);
132 
133 fail_cleanup2:
134 	/*
135 	 * When any error occurs after soft_build_key(), we will need to
136 	 * clean up the memory allocated by the soft_build_key().
137 	 */
138 	soft_cleanup_object(new_objp);
139 
140 fail_cleanup1:
141 	if (new_objp) {
142 		/*
143 		 * The storage allocated inside of this object should have
144 		 * been cleaned up by the soft_build_key() if it failed.
145 		 * Therefore, we can safely free the object.
146 		 */
147 		free(new_objp);
148 	}
149 
150 	return (rv);
151 }
152 
153 CK_RV
154 soft_genkey(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
155     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
156 {
157 
158 	CK_RV rv = CKR_OK;
159 	soft_object_t *secret_key;
160 	CK_KEY_TYPE key_type;
161 	CK_ULONG keylen = 0;
162 	CK_ULONG i;
163 	int des_strength = 0;
164 	int retry = 0;
165 	int keyfound = 0;
166 	boolean_t is_ssl_mech = B_FALSE;
167 
168 	switch (pMechanism->mechanism) {
169 	case CKM_DES_KEY_GEN:
170 		key_type = CKK_DES;
171 		break;
172 
173 	case CKM_DES3_KEY_GEN:
174 		key_type = CKK_DES3;
175 		break;
176 
177 	case CKM_AES_KEY_GEN:
178 		key_type = CKK_AES;
179 		break;
180 
181 	case CKM_BLOWFISH_KEY_GEN:
182 		key_type = CKK_BLOWFISH;
183 		break;
184 
185 	case CKM_RC4_KEY_GEN:
186 		key_type = CKK_RC4;
187 		break;
188 
189 	case CKM_SSL3_PRE_MASTER_KEY_GEN:
190 	case CKM_TLS_PRE_MASTER_KEY_GEN:
191 		if (pMechanism->pParameter == NULL ||
192 		    pMechanism->ulParameterLen != sizeof (CK_VERSION))
193 			return (CKR_TEMPLATE_INCOMPLETE);
194 		is_ssl_mech = B_TRUE;
195 		key_type = CKK_GENERIC_SECRET;
196 		keylen = 48;
197 		break;
198 
199 	case CKM_PKCS5_PBKD2:
200 		keyfound = 0;
201 		for (i = 0; i < ulCount && !keyfound; i++) {
202 			if (pTemplate[i].type == CKA_KEY_TYPE &&
203 			    pTemplate[i].pValue != NULL) {
204 				key_type = *((CK_KEY_TYPE*)pTemplate[i].pValue);
205 				keyfound = 1;
206 			}
207 		}
208 		if (!keyfound)
209 			return (CKR_TEMPLATE_INCOMPLETE);
210 		/*
211 		 * Make sure that parameters were given for this
212 		 * mechanism.
213 		 */
214 		if (pMechanism->pParameter == NULL ||
215 		    pMechanism->ulParameterLen !=
216 			sizeof (CK_PKCS5_PBKD2_PARAMS))
217 			return (CKR_TEMPLATE_INCOMPLETE);
218 		break;
219 
220 	case CKM_PBE_SHA1_RC4_128:
221 		keyfound = 0;
222 		for (i = 0; i < ulCount; i++) {
223 			if (pTemplate[i].type == CKA_KEY_TYPE &&
224 			    pTemplate[i].pValue != NULL) {
225 				key_type = *((CK_KEY_TYPE*)pTemplate[i].pValue);
226 				keyfound = 1;
227 			}
228 			if (pTemplate[i].type == CKA_VALUE_LEN &&
229 			    pTemplate[i].pValue != NULL) {
230 				keylen = *((CK_ULONG*)pTemplate[i].pValue);
231 			}
232 		}
233 		/* If a keytype was specified, it had better be CKK_RC4 */
234 		if (keyfound && key_type != CKK_RC4)
235 			return (CKR_TEMPLATE_INCONSISTENT);
236 		else if (!keyfound)
237 			key_type = CKK_RC4;
238 
239 		/* If key length was specified, it better be 16 bytes */
240 		if (keylen != 0 && keylen != 16)
241 			return (CKR_TEMPLATE_INCONSISTENT);
242 
243 		/*
244 		 * Make sure that parameters were given for this
245 		 * mechanism.
246 		 */
247 		if (pMechanism->pParameter == NULL ||
248 		    pMechanism->ulParameterLen !=
249 			sizeof (CK_PBE_PARAMS))
250 			return (CKR_TEMPLATE_INCOMPLETE);
251 		break;
252 	default:
253 		return (CKR_MECHANISM_INVALID);
254 	}
255 
256 	/* Create a new object for secret key. */
257 	rv = soft_gen_keyobject(pTemplate, ulCount, phKey, session_p,
258 	    CKO_SECRET_KEY, key_type, keylen, SOFT_GEN_KEY, B_FALSE);
259 
260 	if (rv != CKR_OK) {
261 		return (rv);
262 	}
263 
264 	/* Obtain the secret object pointer. */
265 	secret_key = (soft_object_t *)*phKey;
266 
267 	switch (pMechanism->mechanism) {
268 	case CKM_DES_KEY_GEN:
269 		/*
270 		 * Set up key value len since it is not a required
271 		 * attribute for C_GenerateKey.
272 		 */
273 		keylen = OBJ_SEC_VALUE_LEN(secret_key) = DES_KEYSIZE;
274 		des_strength = DES;
275 		break;
276 
277 	case CKM_DES3_KEY_GEN:
278 		/*
279 		 * Set up key value len since it is not a required
280 		 * attribute for C_GenerateKey.
281 		 */
282 		keylen = OBJ_SEC_VALUE_LEN(secret_key) = DES3_KEYSIZE;
283 		des_strength = DES3;
284 		break;
285 
286 	case CKM_SSL3_PRE_MASTER_KEY_GEN:
287 	case CKM_TLS_PRE_MASTER_KEY_GEN:
288 		secret_key->bool_attr_mask |= DERIVE_BOOL_ON;
289 	/* FALLTHRU */
290 
291 	case CKM_AES_KEY_GEN:
292 	case CKM_BLOWFISH_KEY_GEN:
293 	case CKM_PBE_SHA1_RC4_128:
294 	case CKM_RC4_KEY_GEN:
295 		keylen = OBJ_SEC_VALUE_LEN(secret_key);
296 		break;
297 
298 	case CKM_PKCS5_PBKD2:
299 		/*
300 		 * PKCS#11 does not allow one to specify key
301 		 * sizes for DES and 3DES, so we must set it here
302 		 * when using PBKD2 algorithms.
303 		 */
304 		if (key_type == CKK_DES) {
305 			OBJ_SEC_VALUE_LEN(secret_key) = DES_KEYSIZE;
306 			des_strength = DES;
307 		} else if (key_type == CKK_DES3) {
308 			OBJ_SEC_VALUE_LEN(secret_key) = DES3_KEYSIZE;
309 			des_strength = DES3;
310 		}
311 
312 		keylen = OBJ_SEC_VALUE_LEN(secret_key);
313 		break;
314 	}
315 
316 	if ((OBJ_SEC_VALUE(secret_key) = malloc(keylen)) == NULL) {
317 		if (IS_TOKEN_OBJECT(secret_key))
318 			soft_delete_token_object(secret_key, B_FALSE, B_FALSE);
319 		else
320 			soft_delete_object(session_p, secret_key, B_FALSE);
321 
322 		return (CKR_HOST_MEMORY);
323 	}
324 	switch (pMechanism->mechanism) {
325 	case CKM_PBE_SHA1_RC4_128:
326 		/*
327 		 * Use the PBE algorithm described in PKCS#11 section
328 		 * 12.33 to derive the key.
329 		 */
330 		rv = soft_pkcs12_pbe(session_p, pMechanism, secret_key);
331 		break;
332 	case CKM_PKCS5_PBKD2:
333 		/* Generate keys using PKCS#5 PBKD2 algorithm */
334 		rv = soft_generate_pkcs5_pbkdf2_key(session_p, pMechanism,
335 					secret_key);
336 		if (rv == CKR_OK && des_strength > 0) {
337 			/* Perform weak key checking for DES and DES3. */
338 			if (des_keycheck(OBJ_SEC_VALUE(secret_key),
339 			    des_strength, OBJ_SEC_VALUE(secret_key)) ==
340 			    B_FALSE) {
341 				/* We got a weak secret key. */
342 				rv = CKR_FUNCTION_FAILED;
343 			}
344 		}
345 		break;
346 	default:
347 		do {
348 			rv = soft_random_generator(
349 				OBJ_SEC_VALUE(secret_key), keylen, B_FALSE);
350 
351 			/* If this fails, bail out */
352 			if (rv != CKR_OK)
353 				break;
354 
355 			/* Perform weak key checking for DES and DES3. */
356 			if (des_strength > 0) {
357 				rv = CKR_OK;
358 				if (des_keycheck(OBJ_SEC_VALUE(secret_key),
359 				    des_strength, OBJ_SEC_VALUE(secret_key)) ==
360 				    B_FALSE) {
361 					/* We got a weak key, retry! */
362 					retry++;
363 					rv = CKR_FUNCTION_FAILED;
364 				}
365 			}
366 			/*
367 			 * Copy over the SSL client version For SSL mechs
368 			 * The first two bytes of the key is the version
369 			 */
370 			if (is_ssl_mech)
371 				bcopy(pMechanism->pParameter,
372 				    OBJ_SEC_VALUE(secret_key),
373 				    sizeof (CK_VERSION));
374 
375 		} while (rv != CKR_OK && retry < KEYGEN_RETRY);
376 		if (retry == KEYGEN_RETRY)
377 			rv = CKR_FUNCTION_FAILED;
378 		break;
379 	}
380 
381 	if (rv != CKR_OK)
382 		if (IS_TOKEN_OBJECT(secret_key))
383 			soft_delete_token_object(secret_key, B_FALSE, B_FALSE);
384 		else
385 			soft_delete_object(session_p, secret_key, B_FALSE);
386 
387 	if (IS_TOKEN_OBJECT(secret_key)) {
388 		/*
389 		 * All the info has been filled, so we can write to
390 		 * keystore now.
391 		 */
392 		rv = soft_put_object_to_keystore(secret_key);
393 		if (rv != CKR_OK)
394 			soft_delete_token_object(secret_key, B_FALSE, B_FALSE);
395 	}
396 
397 	return (rv);
398 }
399 
400 CK_RV
401 soft_genkey_pair(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
402     CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicAttrCount,
403     CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateAttrCount,
404     CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey)
405 {
406 
407 	CK_RV rv;
408 	soft_object_t *public_key, *private_key;
409 	CK_KEY_TYPE key_type;
410 
411 	switch (pMechanism->mechanism) {
412 
413 	case CKM_RSA_PKCS_KEY_PAIR_GEN:
414 		key_type = CKK_RSA;
415 		break;
416 
417 	case CKM_DSA_KEY_PAIR_GEN:
418 		key_type = CKK_DSA;
419 		break;
420 
421 	case CKM_DH_PKCS_KEY_PAIR_GEN:
422 		key_type = CKK_DH;
423 		break;
424 
425 	default:
426 		return (CKR_MECHANISM_INVALID);
427 	}
428 
429 	/* Create a new object for public key. */
430 	rv = soft_gen_keyobject(pPublicKeyTemplate, ulPublicAttrCount,
431 	    phPublicKey, session_p, CKO_PUBLIC_KEY, key_type, 0,
432 	    SOFT_GEN_KEY, B_FALSE);
433 
434 	if (rv != CKR_OK) {
435 		return (rv);
436 	}
437 
438 	/* Obtain the public object pointer. */
439 	public_key = (soft_object_t *)*phPublicKey;
440 
441 	/* Create a new object for private key. */
442 	rv = soft_gen_keyobject(pPrivateKeyTemplate, ulPrivateAttrCount,
443 	    phPrivateKey, session_p, CKO_PRIVATE_KEY, key_type, 0,
444 	    SOFT_GEN_KEY, B_FALSE);
445 
446 	if (rv != CKR_OK) {
447 		/*
448 		 * Both public key and private key must be successful.
449 		 */
450 		if (IS_TOKEN_OBJECT(public_key))
451 			soft_delete_token_object(public_key, B_FALSE, B_FALSE);
452 		else
453 			soft_delete_object(session_p, public_key, B_FALSE);
454 		return (rv);
455 	}
456 
457 	/* Obtain the private object pointer. */
458 	private_key = (soft_object_t *)*phPrivateKey;
459 
460 	/*
461 	 * At this point, both public key and private key objects
462 	 * are settled with the application specified attributes.
463 	 * We are ready to generate the rest of key attributes based
464 	 * on the existing attributes.
465 	 */
466 
467 	switch (key_type) {
468 	case CKK_RSA:
469 		rv = soft_rsa_genkey_pair(public_key, private_key);
470 		break;
471 
472 	case CKK_DSA:
473 		rv = soft_dsa_genkey_pair(public_key, private_key);
474 		break;
475 
476 	case CKK_DH:
477 		rv = soft_dh_genkey_pair(public_key, private_key);
478 		private_key->bool_attr_mask |= DERIVE_BOOL_ON;
479 		break;
480 	}
481 
482 	if (rv != CKR_OK) {
483 		if (IS_TOKEN_OBJECT(public_key)) {
484 			soft_delete_token_object(public_key, B_FALSE, B_FALSE);
485 			soft_delete_token_object(private_key, B_FALSE, B_FALSE);
486 		} else {
487 			soft_delete_object(session_p, public_key, B_FALSE);
488 			soft_delete_object(session_p, private_key, B_FALSE);
489 		}
490 	}
491 
492 	if (IS_TOKEN_OBJECT(public_key)) {
493 		/*
494 		 * All the info has been filled, so we can write to
495 		 * keystore now.
496 		 */
497 		rv = soft_put_object_to_keystore(public_key);
498 		if (rv != CKR_OK) {
499 			soft_delete_token_object(public_key, B_FALSE, B_FALSE);
500 			soft_delete_token_object(private_key, B_FALSE, B_FALSE);
501 		}
502 	}
503 
504 	if (IS_TOKEN_OBJECT(private_key)) {
505 		rv = soft_put_object_to_keystore(private_key);
506 		if (rv != CKR_OK) {
507 			/*
508 			 * We also need to delete the public token object
509 			 * from keystore.
510 			 */
511 			soft_delete_token_object(public_key, B_TRUE, B_FALSE);
512 			soft_delete_token_object(private_key, B_FALSE, B_FALSE);
513 		}
514 	}
515 
516 	return (rv);
517 }
518 
519 
520 CK_RV
521 soft_key_derive_check_length(soft_object_t *secret_key, CK_ULONG max_keylen)
522 {
523 
524 	switch (secret_key->key_type) {
525 	case CKK_GENERIC_SECRET:
526 		if (OBJ_SEC_VALUE_LEN(secret_key) == 0) {
527 			OBJ_SEC_VALUE_LEN(secret_key) = max_keylen;
528 			return (CKR_OK);
529 		} else if (OBJ_SEC_VALUE_LEN(secret_key) > max_keylen) {
530 			return (CKR_ATTRIBUTE_VALUE_INVALID);
531 		}
532 		break;
533 	case CKK_RC4:
534 	case CKK_AES:
535 	case CKK_BLOWFISH:
536 		if ((OBJ_SEC_VALUE_LEN(secret_key) == 0) ||
537 			(OBJ_SEC_VALUE_LEN(secret_key) > max_keylen)) {
538 			/* RC4 and AES has variable key length */
539 			return (CKR_ATTRIBUTE_VALUE_INVALID);
540 		}
541 		break;
542 	case CKK_DES:
543 		if (OBJ_SEC_VALUE_LEN(secret_key) == 0) {
544 			/* DES has a well-defined length */
545 			OBJ_SEC_VALUE_LEN(secret_key) = DES_KEYSIZE;
546 			return (CKR_OK);
547 		} else if (OBJ_SEC_VALUE_LEN(secret_key) != DES_KEYSIZE) {
548 			return (CKR_ATTRIBUTE_VALUE_INVALID);
549 		}
550 		break;
551 	case CKK_DES2:
552 		if (OBJ_SEC_VALUE_LEN(secret_key) == 0) {
553 			/* DES2 has a well-defined length */
554 			OBJ_SEC_VALUE_LEN(secret_key) = DES2_KEYSIZE;
555 			return (CKR_OK);
556 		} else if (OBJ_SEC_VALUE_LEN(secret_key) != DES2_KEYSIZE) {
557 			return (CKR_ATTRIBUTE_VALUE_INVALID);
558 		}
559 		break;
560 
561 	default:
562 		return (CKR_MECHANISM_INVALID);
563 	}
564 
565 	return (CKR_OK);
566 }
567 
568 /*
569  * PKCS#11 (12.33) says that v = 512 bits (64 bytes) for SHA1
570  * PBE methods.
571  */
572 #define	PKCS12_BUFFER_SIZE 64
573 /*
574  * PKCS#12 defines 3 different ID bytes to be used for
575  * deriving keys for different operations.
576  */
577 #define	PBE_ID_ENCRYPT	1
578 #define	PBE_ID_IV	2
579 #define	PBE_ID_MAC	3
580 #define	PBE_CEIL(a, b)	(((a)/(b)) + (((a)%(b)) > 0))
581 
582 static CK_RV
583 soft_pkcs12_pbe(soft_session_t *session_p,
584 		CK_MECHANISM_PTR pMechanism,
585 		soft_object_t *derived_key)
586 {
587 	CK_RV rv = CKR_OK;
588 	CK_PBE_PARAMS *params = pMechanism->pParameter;
589 	CK_ULONG c, i, j, k;
590 	CK_ULONG hashSize;
591 	CK_ULONG buffSize;
592 	/*
593 	 * Terse variable names are used to make following
594 	 * the PKCS#12 spec easier.
595 	 */
596 	CK_BYTE *A = NULL;
597 	CK_BYTE *Ai = NULL;
598 	CK_BYTE *B = NULL;
599 	CK_BYTE *D = NULL;
600 	CK_BYTE *I = NULL, *S, *P;
601 	CK_BYTE *keybuf = NULL;
602 	CK_ULONG Alen, Ilen, Slen, Plen, AiLen, Blen, Dlen;
603 	CK_ULONG keysize = OBJ_SEC_VALUE_LEN(derived_key);
604 	CK_MECHANISM digest_mech;
605 
606 	/* U = hash function output bits */
607 	if (pMechanism->mechanism == CKM_PBE_SHA1_RC4_128) {
608 		hashSize = SHA1_HASH_SIZE;
609 		buffSize = PKCS12_BUFFER_SIZE;
610 		digest_mech.mechanism = CKM_SHA_1;
611 		digest_mech.pParameter = NULL;
612 		digest_mech.ulParameterLen = 0;
613 	} else {
614 		/* we only support 1 PBE mech for now */
615 		return (CKR_MECHANISM_INVALID);
616 	}
617 	keybuf = OBJ_SEC_VALUE(derived_key);
618 
619 	Blen = Dlen = buffSize;
620 	D = (CK_BYTE *)malloc(Dlen);
621 	if (D == NULL) {
622 		rv = CKR_HOST_MEMORY;
623 		goto cleanup;
624 	}
625 
626 	B = (CK_BYTE *)malloc(Blen);
627 	if (B == NULL) {
628 		rv = CKR_HOST_MEMORY;
629 		goto cleanup;
630 	}
631 
632 	/*
633 	 * Initialize some values and create some buffers
634 	 * that we need later.
635 	 *
636 	 * Slen = buffSize * CEIL(SaltLength/buffSize)
637 	 */
638 	Slen = buffSize * PBE_CEIL(params->ulSaltLen, buffSize);
639 
640 	/*
641 	 * Plen = buffSize * CEIL(PasswordLength/buffSize)
642 	 */
643 	Plen = buffSize * PBE_CEIL(params->ulPasswordLen, buffSize);
644 
645 	/*
646 	 * From step 4: I = S + P, so: Ilen = Slen + Plen
647 	 */
648 	Ilen = Slen + Plen;
649 	I = (CK_BYTE *)malloc(Ilen);
650 	if (I == NULL) {
651 		rv = CKR_HOST_MEMORY;
652 		goto cleanup;
653 	}
654 
655 	S = I;
656 	P = I + Slen;
657 
658 	/*
659 	 * Step 1.
660 	 * We are only interested in deriving keys for encrypt/decrypt
661 	 * for now, so construct the "D"iversifier accordingly.
662 	 */
663 	(void) memset(D, PBE_ID_ENCRYPT, Dlen);
664 
665 	/*
666 	 * Step 2.
667 	 * Concatenate copies of the salt together to make S.
668 	 */
669 	for (i = 0; i < Slen; i += params->ulSaltLen) {
670 		(void) memcpy(S+i, params->pSalt,
671 			((Slen - i) > params->ulSaltLen ?
672 			params->ulSaltLen : (Slen - i)));
673 	}
674 
675 	/*
676 	 * Step 3.
677 	 * Concatenate copies of the password together to make
678 	 * a string P.
679 	 */
680 	for (i = 0; i < Plen; i += params->ulPasswordLen) {
681 		(void) memcpy(P+i, params->pPassword,
682 			((Plen - i) > params->ulPasswordLen ?
683 			params->ulPasswordLen : (Plen - i)));
684 	}
685 
686 	/*
687 	 * Step 4.
688 	 * I = S+P - this is now done because S and P are
689 	 * pointers into I.
690 	 *
691 	 * Step 5.
692 	 * c= CEIL[n/u]
693 	 * where n = pseudorandom bits of output desired.
694 	 */
695 	c = PBE_CEIL(keysize, hashSize);
696 
697 	/*
698 	 * Step 6.
699 	 */
700 	Alen = c * hashSize;
701 	A = (CK_BYTE *)malloc(Alen);
702 	if (A == NULL) {
703 		rv = CKR_HOST_MEMORY;
704 		goto cleanup;
705 	}
706 	AiLen = hashSize;
707 	Ai = (CK_BYTE *)malloc(AiLen);
708 	if (Ai == NULL) {
709 		rv = CKR_HOST_MEMORY;
710 		goto cleanup;
711 	}
712 
713 	/*
714 	 * Step 6a.
715 	 * Ai = Hr(D+I)
716 	 */
717 	for (i = 0; i < c; i++) {
718 		(void) pthread_mutex_lock(&session_p->session_mutex);
719 
720 		if (session_p->sign.flags & CRYPTO_OPERATION_ACTIVE) {
721 			(void) pthread_mutex_unlock(&session_p->session_mutex);
722 			rv = CKR_OPERATION_ACTIVE;
723 			goto cleanup;
724 		}
725 		session_p->sign.flags |= CRYPTO_OPERATION_ACTIVE;
726 		(void) pthread_mutex_unlock(&session_p->session_mutex);
727 
728 		for (j = 0; j < params->ulIteration; j++) {
729 			rv = soft_digest_init(session_p, &digest_mech);
730 			if (rv != CKR_OK)
731 				goto digest_done;
732 
733 			if (j == 0) {
734 				rv = soft_digest_update(session_p, D,
735 					Dlen);
736 				if (rv != CKR_OK)
737 					goto digest_done;
738 
739 				rv = soft_digest_update(session_p, I,
740 					Ilen);
741 			} else {
742 				rv = soft_digest_update(session_p,
743 					Ai, AiLen);
744 			}
745 			if (rv != CKR_OK)
746 				goto digest_done;
747 
748 			rv = soft_digest_final(session_p, Ai, &AiLen);
749 			if (rv != CKR_OK)
750 				goto digest_done;
751 		}
752 digest_done:
753 		(void) pthread_mutex_lock(&session_p->session_mutex);
754 		session_p->sign.flags &= ~CRYPTO_OPERATION_ACTIVE;
755 		(void) pthread_mutex_unlock(&session_p->session_mutex);
756 
757 		if (rv != CKR_OK)
758 			goto cleanup;
759 		/*
760 		 * Step 6b.
761 		 * Concatenate Ai to make B
762 		 */
763 		for (j = 0; j < Blen; j += hashSize) {
764 			(void) memcpy(B+j, Ai, ((Blen - j > hashSize) ?
765 				hashSize : Blen - j));
766 		}
767 
768 		/*
769 		 * Step 6c.
770 		 */
771 		k = Ilen / Blen;
772 		for (j = 0; j < k; j++) {
773 			uchar_t idx;
774 			CK_ULONG m, q = 1, cbit = 0;
775 
776 			for (m = Blen - 1; m >= (CK_ULONG)0; m--, q = 0) {
777 				idx = m + j*Blen;
778 
779 				q += (CK_ULONG)I[idx] + (CK_ULONG)B[m];
780 				q += cbit;
781 				I[idx] = (CK_BYTE)(q & 0xff);
782 				cbit = (q > 0xff);
783 			}
784 		}
785 
786 		/*
787 		 * Step 7.
788 		 *  A += Ai
789 		 */
790 		(void) memcpy(A + i*hashSize, Ai, AiLen);
791 	}
792 
793 	/*
794 	 * Step 8.
795 	 * The final output of this process is the A buffer
796 	 */
797 	(void) memcpy(keybuf, A, keysize);
798 
799 cleanup:
800 	if (A) {
801 		bzero(A, Alen);
802 		free(A);
803 	}
804 	if (Ai) {
805 		bzero(Ai, AiLen);
806 		free(Ai);
807 	}
808 	if (B) {
809 		bzero(B, Blen);
810 		free(B);
811 	}
812 	if (D) {
813 		bzero(D, Dlen);
814 		free(D);
815 	}
816 	if (I) {
817 		bzero(I, Ilen);
818 		free(I);
819 	}
820 	return (rv);
821 }
822 
823 CK_RV
824 soft_derivekey(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
825     soft_object_t *basekey_p, CK_ATTRIBUTE_PTR pTemplate,
826     CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
827 {
828 
829 	CK_RV rv = CKR_OK;
830 	soft_object_t *secret_key;
831 	CK_BYTE *public_value;
832 	CK_ULONG public_value_len;
833 	CK_MECHANISM digest_mech;
834 	CK_BYTE hash[SHA512_DIGEST_LENGTH]; /* space enough for all mechs */
835 	CK_ULONG hash_len = SHA512_DIGEST_LENGTH;
836 	CK_ULONG secret_key_len;
837 	CK_ULONG hash_size;
838 
839 	switch (pMechanism->mechanism) {
840 
841 	case CKM_DH_PKCS_DERIVE:
842 		/* Get public value and value_len from the parameters. */
843 		public_value = (CK_BYTE *)(pMechanism->pParameter);
844 		public_value_len = pMechanism->ulParameterLen;
845 
846 		if (phKey == NULL_PTR)
847 			return (CKR_ARGUMENTS_BAD);
848 		/*
849 		 * Create a new object for secret key. The key type should
850 		 * be provided in the template.
851 		 */
852 		rv = soft_gen_keyobject(pTemplate, ulAttributeCount,
853 		    phKey, session_p, CKO_SECRET_KEY, (CK_KEY_TYPE)~0UL, 0,
854 		    SOFT_DERIVE_KEY_DH, B_FALSE);
855 
856 		if (rv != CKR_OK) {
857 			return (rv);
858 		}
859 
860 		/* Obtain the secret object pointer. */
861 		secret_key = (soft_object_t *)*phKey;
862 
863 		rv = soft_dh_key_derive(basekey_p, secret_key, public_value,
864 			public_value_len);
865 
866 		if (rv != CKR_OK) {
867 			if (IS_TOKEN_OBJECT(secret_key))
868 				soft_delete_token_object(secret_key, B_FALSE,
869 				    B_FALSE);
870 			else
871 				soft_delete_object(session_p, secret_key,
872 				    B_FALSE);
873 			return (rv);
874 		}
875 
876 		break;
877 
878 	case CKM_SHA1_KEY_DERIVATION:
879 		hash_size = SHA1_HASH_SIZE;
880 		digest_mech.mechanism = CKM_SHA_1;
881 		goto common;
882 
883 	case CKM_MD5_KEY_DERIVATION:
884 		hash_size = MD5_HASH_SIZE;
885 		digest_mech.mechanism = CKM_MD5;
886 		goto common;
887 
888 	case CKM_SHA256_KEY_DERIVATION:
889 		hash_size = SHA256_DIGEST_LENGTH;
890 		digest_mech.mechanism = CKM_SHA256;
891 		goto common;
892 
893 	case CKM_SHA384_KEY_DERIVATION:
894 		hash_size = SHA384_DIGEST_LENGTH;
895 		digest_mech.mechanism = CKM_SHA384;
896 		goto common;
897 
898 	case CKM_SHA512_KEY_DERIVATION:
899 		hash_size = SHA512_DIGEST_LENGTH;
900 		digest_mech.mechanism = CKM_SHA512;
901 		goto common;
902 
903 common:
904 		/*
905 		 * Create a new object for secret key. The key type is optional
906 		 * to be provided in the template. If it is not specified in
907 		 * the template, the default is CKK_GENERIC_SECRET.
908 		 */
909 		if (phKey == NULL_PTR)
910 			return (CKR_ARGUMENTS_BAD);
911 
912 		rv = soft_gen_keyobject(pTemplate, ulAttributeCount,
913 		    phKey, session_p, CKO_SECRET_KEY,
914 		    (CK_KEY_TYPE)CKK_GENERIC_SECRET, 0,
915 		    SOFT_DERIVE_KEY_OTHER, B_FALSE);
916 
917 		if (rv != CKR_OK) {
918 			return (rv);
919 		}
920 
921 		/* Obtain the secret object pointer. */
922 		secret_key = (soft_object_t *)*phKey;
923 
924 		/* Validate the key type and key length */
925 		rv = soft_key_derive_check_length(secret_key, hash_size);
926 		if (rv != CKR_OK) {
927 			if (IS_TOKEN_OBJECT(secret_key))
928 				soft_delete_token_object(secret_key, B_FALSE,
929 				    B_FALSE);
930 			else
931 				soft_delete_object(session_p, secret_key,
932 				    B_FALSE);
933 			return (rv);
934 		}
935 
936 		/*
937 		 * Derive the secret key by digesting the value of another
938 		 * secret key (base key) with SHA-1 or MD5.
939 		 */
940 		rv = soft_digest_init_internal(session_p, &digest_mech);
941 		if (rv != CKR_OK) {
942 			if (IS_TOKEN_OBJECT(secret_key))
943 				soft_delete_token_object(secret_key, B_FALSE,
944 				    B_FALSE);
945 			else
946 				soft_delete_object(session_p, secret_key,
947 				    B_FALSE);
948 			return (rv);
949 		}
950 
951 		rv = soft_digest(session_p, OBJ_SEC_VALUE(basekey_p),
952 			OBJ_SEC_VALUE_LEN(basekey_p), hash, &hash_len);
953 
954 		(void) pthread_mutex_lock(&session_p->session_mutex);
955 		/* soft_digest_common() has freed the digest context */
956 		session_p->digest.flags = 0;
957 		(void) pthread_mutex_unlock(&session_p->session_mutex);
958 
959 		if (rv != CKR_OK) {
960 			if (IS_TOKEN_OBJECT(secret_key))
961 				soft_delete_token_object(secret_key, B_FALSE,
962 				    B_FALSE);
963 			else
964 				soft_delete_object(session_p, secret_key,
965 				    B_FALSE);
966 			return (rv);
967 		}
968 
969 		secret_key_len = OBJ_SEC_VALUE_LEN(secret_key);
970 
971 		if ((OBJ_SEC_VALUE(secret_key) = malloc(secret_key_len)) ==
972 		    NULL) {
973 			if (IS_TOKEN_OBJECT(secret_key))
974 				soft_delete_token_object(secret_key, B_FALSE,
975 				    B_FALSE);
976 			else
977 				soft_delete_object(session_p, secret_key,
978 				    B_FALSE);
979 			return (CKR_HOST_MEMORY);
980 		}
981 
982 		/*
983 		 * The key produced by this mechanism will be of the
984 		 * specified type and length.
985 		 * The truncation removes extra bytes from the leading
986 		 * of the digested key value.
987 		 */
988 		(void) memcpy(OBJ_SEC_VALUE(secret_key),
989 		    (hash + hash_len - secret_key_len),
990 		    secret_key_len);
991 
992 		break;
993 
994 	/*
995 	 * The key sensitivity and extractability rules for the generated
996 	 * keys will be enforced inside soft_ssl_master_key_derive() and
997 	 * soft_ssl_key_and_mac_derive()
998 	 */
999 	case CKM_SSL3_MASTER_KEY_DERIVE:
1000 	case CKM_SSL3_MASTER_KEY_DERIVE_DH:
1001 	case CKM_TLS_MASTER_KEY_DERIVE:
1002 	case CKM_TLS_MASTER_KEY_DERIVE_DH:
1003 		if (phKey == NULL_PTR)
1004 			return (CKR_ARGUMENTS_BAD);
1005 		return (soft_ssl_master_key_derive(session_p, pMechanism,
1006 		    basekey_p, pTemplate, ulAttributeCount, phKey));
1007 
1008 	case CKM_SSL3_KEY_AND_MAC_DERIVE:
1009 	case CKM_TLS_KEY_AND_MAC_DERIVE:
1010 		return (soft_ssl_key_and_mac_derive(session_p, pMechanism,
1011 		    basekey_p, pTemplate, ulAttributeCount));
1012 
1013 	case CKM_TLS_PRF:
1014 		if (pMechanism->pParameter == NULL ||
1015 		    pMechanism->ulParameterLen != sizeof (CK_TLS_PRF_PARAMS) ||
1016 		    phKey != NULL)
1017 			return (CKR_ARGUMENTS_BAD);
1018 
1019 		if (pTemplate != NULL)
1020 			return (CKR_TEMPLATE_INCONSISTENT);
1021 
1022 		return (derive_tls_prf(
1023 			(CK_TLS_PRF_PARAMS_PTR)pMechanism->pParameter,
1024 			basekey_p));
1025 
1026 	default:
1027 		return (CKR_MECHANISM_INVALID);
1028 	}
1029 
1030 	soft_derive_enforce_flags(basekey_p, secret_key);
1031 
1032 	if (IS_TOKEN_OBJECT(secret_key)) {
1033 		/*
1034 		 * All the info has been filled, so we can write to
1035 		 * keystore now.
1036 		 */
1037 		rv = soft_put_object_to_keystore(secret_key);
1038 		if (rv != CKR_OK)
1039 			soft_delete_token_object(secret_key, B_FALSE, B_FALSE);
1040 	}
1041 
1042 	return (rv);
1043 }
1044 
1045 
1046 /*
1047  * Perform key derivation rules on key's sensitivity and extractability.
1048  */
1049 void
1050 soft_derive_enforce_flags(soft_object_t *basekey, soft_object_t *newkey)
1051 {
1052 
1053 	boolean_t new_sensitive = B_FALSE;
1054 	boolean_t new_extractable = B_FALSE;
1055 
1056 	/*
1057 	 * The sensitive and extractable bits have been set when
1058 	 * the newkey was built.
1059 	 */
1060 	if (newkey->bool_attr_mask & SENSITIVE_BOOL_ON) {
1061 		new_sensitive = B_TRUE;
1062 	}
1063 
1064 	if (newkey->bool_attr_mask & EXTRACTABLE_BOOL_ON) {
1065 		new_extractable = B_TRUE;
1066 	}
1067 
1068 	/* Derive the CKA_ALWAYS_SENSITIVE flag */
1069 	if (!basekey->bool_attr_mask & ALWAYS_SENSITIVE_BOOL_ON) {
1070 		/*
1071 		 * If the base key has its CKA_ALWAYS_SENSITIVE set to
1072 		 * FALSE, then the derived key will as well.
1073 		 */
1074 		newkey->bool_attr_mask &= ~ALWAYS_SENSITIVE_BOOL_ON;
1075 	} else {
1076 		/*
1077 		 * If the base key has its CKA_ALWAYS_SENSITIVE set to TRUE,
1078 		 * then the derived key has the CKA_ALWAYS_SENSITIVE set to
1079 		 * the same value as its CKA_SENSITIVE;
1080 		 */
1081 		if (new_sensitive) {
1082 			newkey->bool_attr_mask |= ALWAYS_SENSITIVE_BOOL_ON;
1083 		} else {
1084 			newkey->bool_attr_mask &= ~ALWAYS_SENSITIVE_BOOL_ON;
1085 		}
1086 	}
1087 
1088 	/* Derive the CKA_NEVER_EXTRACTABLE flag */
1089 	if (!basekey->bool_attr_mask & NEVER_EXTRACTABLE_BOOL_ON) {
1090 		/*
1091 		 * If the base key has its CKA_NEVER_EXTRACTABLE set to
1092 		 * FALSE, then the derived key will as well.
1093 		 */
1094 		newkey->bool_attr_mask &= ~NEVER_EXTRACTABLE_BOOL_ON;
1095 	} else {
1096 		/*
1097 		 * If the base key has its CKA_NEVER_EXTRACTABLE set to TRUE,
1098 		 * then the derived key has the CKA_NEVER_EXTRACTABLE set to
1099 		 * the opposite value from its CKA_EXTRACTABLE;
1100 		 */
1101 		if (new_extractable) {
1102 			newkey->bool_attr_mask &= ~NEVER_EXTRACTABLE_BOOL_ON;
1103 		} else {
1104 			newkey->bool_attr_mask |= NEVER_EXTRACTABLE_BOOL_ON;
1105 		}
1106 	}
1107 
1108 	/* Set the CKA_LOCAL flag to false */
1109 	newkey->bool_attr_mask &= ~LOCAL_BOOL_ON;
1110 }
1111 
1112 
1113 /*
1114  * do_prf
1115  *
1116  * This routine implements Step 3. of the PBKDF2 function
1117  * defined in PKCS#5 for generating derived keys from a
1118  * password.
1119  *
1120  * Currently, PRF is always SHA_1_HMAC.
1121  */
1122 static CK_RV
1123 do_prf(soft_session_t *session_p,
1124 	CK_PKCS5_PBKD2_PARAMS_PTR params,
1125 	soft_object_t *hmac_key,
1126 	CK_BYTE *newsalt, CK_ULONG saltlen,
1127 	CK_BYTE *blockdata, CK_ULONG blocklen)
1128 {
1129 	CK_RV rv = CKR_OK;
1130 	CK_MECHANISM digest_mech = {CKM_SHA_1_HMAC, NULL, 0};
1131 	CK_BYTE buffer[2][SHA1_HASH_SIZE];
1132 	CK_ULONG hmac_outlen = SHA1_HASH_SIZE;
1133 	CK_ULONG inlen;
1134 	CK_BYTE *input, *output;
1135 	CK_ULONG i, j;
1136 
1137 	input = newsalt;
1138 	inlen = saltlen;
1139 
1140 	output = buffer[1];
1141 	(void) pthread_mutex_lock(&session_p->session_mutex);
1142 
1143 	if (session_p->sign.flags & CRYPTO_OPERATION_ACTIVE) {
1144 		(void) pthread_mutex_unlock(&session_p->session_mutex);
1145 		return (CKR_OPERATION_ACTIVE);
1146 	}
1147 	session_p->sign.flags |= CRYPTO_OPERATION_ACTIVE;
1148 	(void) pthread_mutex_unlock(&session_p->session_mutex);
1149 
1150 	for (i = 0; i < params->iterations; i++) {
1151 		/*
1152 		 * The key doesn't change, its always the
1153 		 * password iniitally given.
1154 		 */
1155 		rv = soft_sign_init(session_p, &digest_mech, hmac_key);
1156 
1157 		if (rv != CKR_OK) {
1158 			goto cleanup;
1159 		}
1160 
1161 		/* Call PRF function (SHA1_HMAC for now). */
1162 		rv = soft_sign(session_p, input, inlen,
1163 			output, &hmac_outlen);
1164 
1165 		if (rv != CKR_OK) {
1166 			goto cleanup;
1167 		}
1168 		/*
1169 		 * The first time, initialize the output buffer
1170 		 * with the HMAC signature.
1171 		 */
1172 		if (i == 0) {
1173 			(void) memcpy(blockdata, output,
1174 				local_min(blocklen, hmac_outlen));
1175 		} else {
1176 			/*
1177 			 * XOR the existing data with output from PRF.
1178 			 *
1179 			 * Only XOR up to the length of the blockdata,
1180 			 * it may be less than a full hmac buffer when
1181 			 * the final block is being computed.
1182 			 */
1183 			for (j = 0; j < hmac_outlen && j < blocklen; j++)
1184 				blockdata[j] ^= output[j];
1185 		}
1186 		/* Output from previous PRF is input for next round */
1187 		input = output;
1188 		inlen = hmac_outlen;
1189 
1190 		/*
1191 		 * Switch buffers to avoid overuse of memcpy.
1192 		 * Initially we used buffer[1], so after the end of
1193 		 * the first iteration (i==0), we switch to buffer[0]
1194 		 * and continue swapping with each iteration.
1195 		 */
1196 		output = buffer[i%2];
1197 	}
1198 cleanup:
1199 	(void) pthread_mutex_lock(&session_p->session_mutex);
1200 	session_p->sign.flags &= ~CRYPTO_OPERATION_ACTIVE;
1201 	(void) pthread_mutex_unlock(&session_p->session_mutex);
1202 
1203 	return (rv);
1204 }
1205 
1206 static CK_RV
1207 soft_create_hmac_key(soft_session_t *session_p,  CK_BYTE *passwd,
1208 		CK_ULONG passwd_len, CK_OBJECT_HANDLE_PTR phKey)
1209 {
1210 	CK_RV rv = CKR_OK;
1211 	CK_OBJECT_CLASS keyclass = CKO_SECRET_KEY;
1212 	CK_KEY_TYPE keytype = CKK_GENERIC_SECRET;
1213 	CK_BBOOL True = TRUE;
1214 	CK_ATTRIBUTE keytemplate[4];
1215 	/*
1216 	 * We must initialize each template member individually
1217 	 * because at the time of initial coding for ON10, the
1218 	 * compiler was using the "-xc99=%none" option
1219 	 * which prevents us from being able to declare the whole
1220 	 * template in place as usual.
1221 	 */
1222 	keytemplate[0].type = CKA_CLASS;
1223 	keytemplate[0].pValue = &keyclass;
1224 	keytemplate[0].ulValueLen =  sizeof (keyclass);
1225 
1226 	keytemplate[1].type = CKA_KEY_TYPE;
1227 	keytemplate[1].pValue = &keytype;
1228 	keytemplate[1].ulValueLen =  sizeof (keytype);
1229 
1230 	keytemplate[2].type = CKA_SIGN;
1231 	keytemplate[2].pValue = &True;
1232 	keytemplate[2].ulValueLen =  sizeof (True);
1233 
1234 	keytemplate[3].type = CKA_VALUE;
1235 	keytemplate[3].pValue = passwd;
1236 	keytemplate[3].ulValueLen = passwd_len;
1237 	/*
1238 	 * Create a generic key object to be used for HMAC operations.
1239 	 * The "value" for this key is the password from the
1240 	 * mechanism parameter structure.
1241 	 */
1242 	rv = soft_gen_keyobject(keytemplate,
1243 			sizeof (keytemplate)/sizeof (CK_ATTRIBUTE),
1244 			phKey, session_p, CKO_SECRET_KEY,
1245 			(CK_KEY_TYPE)CKK_GENERIC_SECRET, 0,
1246 			SOFT_CREATE_OBJ, B_TRUE);
1247 
1248 	return (rv);
1249 }
1250 
1251 CK_RV
1252 soft_generate_pkcs5_pbkdf2_key(soft_session_t *session_p,
1253 		CK_MECHANISM_PTR pMechanism,
1254 		soft_object_t *secret_key)
1255 {
1256 	CK_RV rv = CKR_OK;
1257 	CK_PKCS5_PBKD2_PARAMS	*params =
1258 		(CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter;
1259 	CK_ULONG hLen = SHA1_HASH_SIZE;
1260 	CK_ULONG dkLen, i;
1261 	CK_ULONG blocks, remainder;
1262 	CK_OBJECT_HANDLE phKey = 0;
1263 	soft_object_t *hmac_key = NULL;
1264 	CK_BYTE *salt = NULL;
1265 	CK_BYTE *keydata = NULL;
1266 
1267 	params = (CK_PKCS5_PBKD2_PARAMS_PTR) pMechanism->pParameter;
1268 
1269 	if (params->prf != CKP_PKCS5_PBKD2_HMAC_SHA1)
1270 		return (CKR_MECHANISM_PARAM_INVALID);
1271 
1272 	if (params->pPrfData != NULL || params->ulPrfDataLen != 0)
1273 		return (CKR_DATA_INVALID);
1274 
1275 	if (params->saltSource != CKZ_SALT_SPECIFIED ||
1276 	    params->iterations == 0)
1277 		return (CKR_MECHANISM_PARAM_INVALID);
1278 
1279 	/*
1280 	 * Create a key object to use for HMAC operations.
1281 	 */
1282 	rv = soft_create_hmac_key(session_p, params->pPassword,
1283 		*params->ulPasswordLen, &phKey);
1284 
1285 	if (rv != CKR_OK)
1286 		return (rv);
1287 
1288 	hmac_key = (soft_object_t *)phKey;
1289 
1290 	/* Step 1. */
1291 	dkLen = OBJ_SEC_VALUE_LEN(secret_key);  /* length of desired key */
1292 
1293 	if (dkLen > ((((u_longlong_t)1)<<32)-1)*hLen) {
1294 		(void) soft_delete_object(session_p, hmac_key, B_FALSE);
1295 		return (CKR_KEY_SIZE_RANGE);
1296 	}
1297 
1298 	/* Step 2. */
1299 	blocks = dkLen / hLen;
1300 
1301 	/* crude "Ceiling" function to adjust the number of blocks to use */
1302 	if (blocks * hLen != dkLen)
1303 		blocks++;
1304 
1305 	remainder = dkLen - ((blocks - 1) * hLen);
1306 
1307 	/* Step 3 */
1308 	salt = (CK_BYTE *)malloc(params->ulSaltSourceDataLen + 4);
1309 	if (salt == NULL) {
1310 		(void) soft_delete_object(session_p, hmac_key, B_FALSE);
1311 		return (CKR_HOST_MEMORY);
1312 	}
1313 	/*
1314 	 * Nothing in PKCS#5 says you cannot pass an empty
1315 	 * salt, so we will allow for this and not return error
1316 	 * if the salt is not specified.
1317 	 */
1318 	if (params->pSaltSourceData != NULL &&
1319 		params->ulSaltSourceDataLen > 0)
1320 		(void) memcpy(salt, params->pSaltSourceData,
1321 			params->ulSaltSourceDataLen);
1322 
1323 	/*
1324 	 * Get pointer to the data section of the key,
1325 	 * this will be used below as output from the
1326 	 * PRF iteration/concatenations so that when the
1327 	 * blocks are all iterated, the secret_key will
1328 	 * have the resulting derived key value.
1329 	 */
1330 	keydata = (CK_BYTE *)OBJ_SEC_VALUE(secret_key);
1331 
1332 	/* Step 4. */
1333 	for (i = 0; i < blocks && (rv == CKR_OK); i++) {
1334 		CK_BYTE *s;
1335 
1336 		s = salt + params->ulSaltSourceDataLen;
1337 
1338 		/*
1339 		 * Append the block index to the salt as input
1340 		 * to the PRF.  Block index should start at 1
1341 		 * not 0.
1342 		 */
1343 		*s++ = ((i+1) >> 24) & 0xff;
1344 		*s++ = ((i+1) >> 16) & 0xff;
1345 		*s++ = ((i+1) >> 8) & 0xff;
1346 		*s   = ((i+1)) & 0xff;
1347 
1348 		/*
1349 		 * Adjust the key pointer so we always append the
1350 		 * PRF output to the current key.
1351 		 */
1352 		rv = do_prf(session_p, params, hmac_key,
1353 			salt, params->ulSaltSourceDataLen + 4,
1354 			keydata,
1355 			((i + 1) == blocks ? remainder : hLen));
1356 
1357 		keydata += hLen;
1358 	}
1359 	(void) soft_delete_object(session_p, hmac_key, B_FALSE);
1360 	free(salt);
1361 
1362 	return (rv);
1363 }
1364 
1365 CK_RV
1366 soft_wrapkey(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
1367 		soft_object_t *wrappingKey_p, soft_object_t *hkey_p,
1368 		CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen)
1369 {
1370 	CK_RV		rv = CKR_OK;
1371 	CK_ULONG	plain_len = 0;
1372 	CK_BYTE_PTR	plain_data = NULL;
1373 	CK_ULONG	padded_len = 0;
1374 	CK_BYTE_PTR	padded_data = NULL;
1375 	CK_ULONG	wkey_blksz = 1;		/* so modulo will work right */
1376 
1377 	/* Check if the mechanism is supported. */
1378 	switch (pMechanism->mechanism) {
1379 	case CKM_DES_CBC_PAD:
1380 	case CKM_DES3_CBC_PAD:
1381 	case CKM_AES_CBC_PAD:
1382 		/*
1383 		 * Secret key mechs with padding can be used to wrap secret
1384 		 * keys and private keys only.  See PKCS#11, * sec 11.14,
1385 		 * C_WrapKey and secs 12.* for each mechanism's wrapping/
1386 		 * unwrapping constraints.
1387 		 */
1388 		if (hkey_p->class != CKO_SECRET_KEY && hkey_p->class !=
1389 		    CKO_PRIVATE_KEY)
1390 			return (CKR_MECHANISM_INVALID);
1391 		break;
1392 	case CKM_RSA_PKCS:
1393 	case CKM_RSA_X_509:
1394 	case CKM_DES_ECB:
1395 	case CKM_DES3_ECB:
1396 	case CKM_AES_ECB:
1397 	case CKM_DES_CBC:
1398 	case CKM_DES3_CBC:
1399 	case CKM_AES_CBC:
1400 	case CKM_BLOWFISH_CBC:
1401 		/*
1402 		 * Unpadded secret key mechs and private key mechs are only
1403 		 * defined for wrapping secret keys.  See PKCS#11 refs above.
1404 		 */
1405 		if (hkey_p->class != CKO_SECRET_KEY)
1406 			return (CKR_MECHANISM_INVALID);
1407 		break;
1408 	default:
1409 		return (CKR_MECHANISM_INVALID);
1410 	}
1411 
1412 	if (hkey_p->class == CKO_SECRET_KEY) {
1413 		plain_data = OBJ_SEC_VALUE(hkey_p);
1414 		plain_len = OBJ_SEC_VALUE_LEN(hkey_p);
1415 	} else {
1416 		/*
1417 		 * BER-encode the object to be wrapped:  call first with
1418 		 * plain_data = NULL to get the size needed, allocate that
1419 		 * much space, call again to fill space with actual data.
1420 		 */
1421 		rv = soft_object_to_asn1(hkey_p, NULL, &plain_len);
1422 		if (rv != CKR_OK)
1423 			return (rv);
1424 		if ((plain_data = malloc(plain_len)) == NULL)
1425 			return (CKR_HOST_MEMORY);
1426 		(void) memset(plain_data, 0x0, plain_len);
1427 		rv = soft_object_to_asn1(hkey_p, plain_data, &plain_len);
1428 		if (rv != CKR_OK)
1429 			goto cleanup_wrap;
1430 	}
1431 
1432 	/*
1433 	 * For unpadded ECB and CBC mechanisms, the object needs to be
1434 	 * padded to the wrapping key's blocksize prior to the encryption.
1435 	 */
1436 	padded_len = plain_len;
1437 	padded_data = plain_data;
1438 
1439 	switch (pMechanism->mechanism) {
1440 	case CKM_DES_ECB:
1441 	case CKM_DES3_ECB:
1442 	case CKM_AES_ECB:
1443 	case CKM_DES_CBC:
1444 	case CKM_DES3_CBC:
1445 	case CKM_AES_CBC:
1446 	case CKM_BLOWFISH_CBC:
1447 		/* Find the block size of the wrapping key. */
1448 		if (wrappingKey_p->class == CKO_SECRET_KEY) {
1449 			switch (wrappingKey_p->key_type) {
1450 			case CKK_DES:
1451 			case CKK_DES2:
1452 			case CKK_DES3:
1453 				wkey_blksz = DES_BLOCK_LEN;
1454 				break;
1455 			case CKK_AES:
1456 				wkey_blksz = AES_BLOCK_LEN;
1457 				break;
1458 			case CKK_BLOWFISH:
1459 				wkey_blksz = BLOWFISH_BLOCK_LEN;
1460 				break;
1461 			default:
1462 				break;
1463 			}
1464 		} else {
1465 			rv = CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
1466 			goto cleanup_wrap;
1467 		}
1468 
1469 		/* Extend the plain text data to block size boundary.  */
1470 		if ((padded_len % wkey_blksz) != 0) {
1471 			padded_len += (wkey_blksz - (plain_len % wkey_blksz));
1472 			if ((padded_data = malloc(padded_len)) == NULL) {
1473 				rv = CKR_HOST_MEMORY;
1474 				goto cleanup_wrap;
1475 			}
1476 			(void) memset(padded_data, 0x0, padded_len);
1477 			(void) memcpy(padded_data, plain_data, plain_len);
1478 		}
1479 		break;
1480 	default:
1481 		break;
1482 	}
1483 
1484 	rv = soft_encrypt_init(session_p, pMechanism, wrappingKey_p);
1485 	if (rv != CKR_OK)
1486 		goto cleanup_wrap;
1487 
1488 	rv = soft_encrypt(session_p, padded_data, padded_len,
1489 	    pWrappedKey, pulWrappedKeyLen);
1490 
1491 cleanup_wrap:
1492 	if (padded_data != NULL && padded_len != plain_len) {
1493 		/* Clear buffer before returning to memory pool. */
1494 		(void) memset(padded_data, 0x0, padded_len);
1495 		free(padded_data);
1496 	}
1497 
1498 	if ((hkey_p->class != CKO_SECRET_KEY) && (plain_data != NULL)) {
1499 		/* Clear buffer before returning to memory pool. */
1500 		(void) memset(plain_data, 0x0, plain_len);
1501 		free(plain_data);
1502 	}
1503 
1504 	return (rv);
1505 }
1506 
1507 /*
1508  * Quick check for whether unwrapped key length is appropriate for key type
1509  * and whether it needs to be truncated (in case the wrapping function had
1510  * to pad the key prior to wrapping).
1511  */
1512 static CK_RV
1513 soft_unwrap_secret_len_check(CK_KEY_TYPE keytype, CK_MECHANISM_TYPE mechtype,
1514 	CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount)
1515 {
1516 	CK_ULONG	i;
1517 	boolean_t	isValueLen = B_FALSE;
1518 
1519 	/*
1520 	 * Based on the key type and the mech used to unwrap, need to
1521 	 * determine if CKA_VALUE_LEN should or should not be specified.
1522 	 * PKCS#11 v2.11 restricts CKA_VALUE_LEN from being specified
1523 	 * for C_UnwrapKey for all mechs and key types, but v2.20 loosens
1524 	 * that restriction, perhaps because it makes it impossible to
1525 	 * determine the original length of unwrapped variable-length secret
1526 	 * keys, such as RC4, AES, and GENERIC_SECRET.  These variable-length
1527 	 * secret keys would have been padded with trailing null-bytes so
1528 	 * that they could be successfully wrapped with *_ECB and *_CBC
1529 	 * mechanisms.  Hence for unwrapping with these mechs, CKA_VALUE_LEN
1530 	 * must be specified.  For unwrapping with other mechs, such as
1531 	 * *_CBC_PAD, the CKA_VALUE_LEN is not needed.
1532 	 */
1533 
1534 	/* Find out if template has CKA_VALUE_LEN. */
1535 	for (i = 0; i < ulAttributeCount; i++) {
1536 		if (pTemplate[i].type == CKA_VALUE_LEN &&
1537 		    pTemplate[i].pValue != NULL) {
1538 			isValueLen = B_TRUE;
1539 			break;
1540 		    }
1541 	}
1542 
1543 	/* Does its presence  conflict with the mech type and key type? */
1544 	switch (mechtype) {
1545 	case CKM_DES_ECB:
1546 	case CKM_DES3_ECB:
1547 	case CKM_AES_ECB:
1548 	case CKM_DES_CBC:
1549 	case CKM_DES3_CBC:
1550 	case CKM_AES_CBC:
1551 	case CKM_BLOWFISH_CBC:
1552 		/*
1553 		 * CKA_VALUE_LEN must be specified
1554 		 * if keytype is CKK_RC4, CKK_AES and CKK_GENERIC_SECRET
1555 		 * and must not be specified otherwise
1556 		 */
1557 		switch (keytype) {
1558 		case CKK_DES:
1559 		case CKK_DES2:
1560 		case CKK_DES3:
1561 			if (isValueLen)
1562 				return (CKR_TEMPLATE_INCONSISTENT);
1563 			break;
1564 		case CKK_GENERIC_SECRET:
1565 		case CKK_RC4:
1566 		case CKK_AES:
1567 		case CKK_BLOWFISH:
1568 			if (!isValueLen)
1569 				return (CKR_TEMPLATE_INCOMPLETE);
1570 			break;
1571 		default:
1572 			return (CKR_FUNCTION_NOT_SUPPORTED);
1573 		}
1574 		break;
1575 	default:
1576 		/* CKA_VALUE_LEN must not be specified */
1577 		if (isValueLen)
1578 			return (CKR_TEMPLATE_INCONSISTENT);
1579 		break;
1580 	}
1581 
1582 	return (CKR_OK);
1583 }
1584 
1585 CK_RV
1586 soft_unwrapkey(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
1587 		soft_object_t *unwrappingkey_p,
1588 		CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
1589 		CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
1590 		CK_OBJECT_HANDLE_PTR phKey)
1591 {
1592 	CK_RV			rv = CKR_OK;
1593 	CK_OBJECT_CLASS		new_obj_class = ~0UL;
1594 	int			i = 0;
1595 	soft_object_t		*new_objp = NULL;
1596 	boolean_t		persistent = B_FALSE;
1597 	CK_BYTE_PTR		plain_data = NULL;
1598 	CK_ULONG		plain_len = 0;
1599 	secret_key_obj_t	*sck = NULL;
1600 
1601 	/* Scan the attribute template for the object class. */
1602 	if (pTemplate != NULL && ulAttributeCount != 0) {
1603 		for (i = 0; i < ulAttributeCount; i++) {
1604 			if (pTemplate[i].type == CKA_CLASS) {
1605 				new_obj_class =
1606 				    *((CK_OBJECT_CLASS *)pTemplate[i].pValue);
1607 				break;
1608 			}
1609 		}
1610 		if (new_obj_class == ~0UL)
1611 			return (CKR_TEMPLATE_INCOMPLETE);
1612 	}
1613 
1614 	/*
1615 	 * Check if the mechanism is supported, and now that the new
1616 	 * object's class is known, the mechanism selected should be
1617 	 * capable of doing the unwrap.
1618 	 */
1619 	switch (pMechanism->mechanism) {
1620 	case CKM_RSA_PKCS:
1621 	case CKM_RSA_X_509:
1622 	case CKM_DES_ECB:
1623 	case CKM_DES3_ECB:
1624 	case CKM_AES_ECB:
1625 	case CKM_DES_CBC:
1626 	case CKM_DES3_CBC:
1627 	case CKM_AES_CBC:
1628 	case CKM_BLOWFISH_CBC:
1629 		if (new_obj_class != CKO_SECRET_KEY)
1630 			return (CKR_MECHANISM_INVALID);
1631 		break;
1632 	case CKM_DES_CBC_PAD:
1633 	case CKM_DES3_CBC_PAD:
1634 	case CKM_AES_CBC_PAD:
1635 		if (new_obj_class != CKO_SECRET_KEY && new_obj_class !=
1636 		    CKO_PRIVATE_KEY)
1637 			return (CKR_MECHANISM_INVALID);
1638 		break;
1639 	default:
1640 		return (CKR_MECHANISM_INVALID);
1641 	}
1642 
1643 	/* Create a new object based on the attribute template. */
1644 	rv = soft_gen_keyobject(pTemplate, ulAttributeCount,
1645 	    (CK_ULONG *)&new_objp, session_p, (CK_OBJECT_CLASS)~0UL,
1646 	    (CK_KEY_TYPE)~0UL, 0, SOFT_UNWRAP_KEY, B_FALSE);
1647 	if (rv != CKR_OK)
1648 		return (rv);
1649 
1650 	/*
1651 	 * New key will have CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE
1652 	 * both set to FALSE.  CKA_EXTRACTABLE will be set _by_default_ to
1653 	 * true -- leaving the possibility that it may be set FALSE by the
1654 	 * supplied attribute template.  If the precise template cannot be
1655 	 * supported, unwrap fails.  PKCS#11 spec, Sec. 11.14, C_UnwrapKey.
1656 	 *
1657 	 * Therefore, check the new object's NEVER_EXTRACTABLE_BOOL_ON and
1658 	 * ALWAYS_SENSITVE_BOOL_ON; if they are TRUE, the template must
1659 	 * have supplied them and therefore we cannot honor the unwrap.
1660 	 */
1661 	if ((new_objp->bool_attr_mask & NEVER_EXTRACTABLE_BOOL_ON) ||
1662 	    (new_objp->bool_attr_mask & ALWAYS_SENSITIVE_BOOL_ON)) {
1663 		rv = CKR_TEMPLATE_INCONSISTENT;
1664 		goto cleanup_unwrap;
1665 	}
1666 
1667 	rv = soft_decrypt_init(session_p, pMechanism, unwrappingkey_p);
1668 	if (rv != CKR_OK)
1669 		goto cleanup_unwrap;
1670 
1671 	/* First get the length of the plain data */
1672 	rv = soft_decrypt(session_p, pWrappedKey, ulWrappedKeyLen, NULL,
1673 	    &plain_len);
1674 	if (rv != CKR_OK)
1675 		goto cleanup_unwrap;
1676 
1677 	/* Allocate space for the unwrapped data */
1678 	if ((plain_data = malloc(plain_len)) == NULL) {
1679 		rv = CKR_HOST_MEMORY;
1680 		goto cleanup_unwrap;
1681 	}
1682 	(void) memset(plain_data, 0x0, plain_len);
1683 
1684 	/* Perform actual decryption into the allocated space. */
1685 	rv = soft_decrypt(session_p, pWrappedKey, ulWrappedKeyLen, plain_data,
1686 	    &plain_len);
1687 	if (rv != CKR_OK)
1688 		goto cleanup_unwrap;
1689 
1690 	if (new_objp->class == CKO_SECRET_KEY) {
1691 		/*
1692 		 * Since no ASN.1 encoding is done for secret keys, check for
1693 		 * appropriateness and copy decrypted buffer to the key object.
1694 		 */
1695 
1696 		/* Check keytype and mechtype don't conflict with valuelen */
1697 		rv = soft_unwrap_secret_len_check(new_objp->key_type,
1698 		    pMechanism->mechanism, pTemplate, ulAttributeCount);
1699 		if (rv != CKR_OK)
1700 			goto cleanup_unwrap;
1701 
1702 		/*
1703 		 * Allocate the secret key structure if not already there;
1704 		 * it will exist for variable length keys since CKA_VALUE_LEN
1705 		 * is specified and saved, but not for fixed length keys.
1706 		 */
1707 		if (OBJ_SEC(new_objp) == NULL) {
1708 			if ((sck = calloc(1, sizeof (secret_key_obj_t))) ==
1709 			    NULL) {
1710 				rv = CKR_HOST_MEMORY;
1711 				goto cleanup_unwrap;
1712 			}
1713 			OBJ_SEC(new_objp) = sck;
1714 		}
1715 
1716 		switch (new_objp->key_type) {
1717 		/* Fixed length secret keys don't have CKA_VALUE_LEN */
1718 		case CKK_DES:
1719 			OBJ_SEC_VALUE_LEN(new_objp) = DES_KEYSIZE;
1720 			break;
1721 		case CKK_DES2:
1722 			OBJ_SEC_VALUE_LEN(new_objp) = DES2_KEYSIZE;
1723 			break;
1724 		case CKK_DES3:
1725 			OBJ_SEC_VALUE_LEN(new_objp) = DES3_KEYSIZE;
1726 			break;
1727 
1728 		/*
1729 		 * Variable length secret keys.  CKA_VALUE_LEN must be
1730 		 * provided by the template when mech is *_ECB or *_CBC, and
1731 		 * should already have been set during soft_gen_keyobject().
1732 		 * Otherwise we don't need CKA_VALUE_LEN.
1733 		 */
1734 		case CKK_GENERIC_SECRET:
1735 		case CKK_RC4:
1736 		case CKK_AES:
1737 		case CKK_BLOWFISH:
1738 			break;
1739 		default:
1740 			rv = CKR_WRAPPED_KEY_INVALID;
1741 			goto cleanup_unwrap;
1742 		};
1743 
1744 		if (OBJ_SEC_VALUE_LEN(new_objp) == 0) {
1745 			/* No CKA_VALUE_LEN set so set it now and save data */
1746 			OBJ_SEC_VALUE_LEN(new_objp) = plain_len;
1747 			OBJ_SEC_VALUE(new_objp) = plain_data;
1748 		} else if (OBJ_SEC_VALUE_LEN(new_objp) == plain_len) {
1749 			/* No need to truncate, just save the data */
1750 			OBJ_SEC_VALUE(new_objp) = plain_data;
1751 		} else if (OBJ_SEC_VALUE_LEN(new_objp) > plain_len) {
1752 			/* Length can't be bigger than what was decrypted */
1753 			rv = CKR_WRAPPED_KEY_LEN_RANGE;
1754 			goto cleanup_unwrap;
1755 		} else {	/* betw 0 and plain_len, hence padded */
1756 			/* Truncate the data before saving. */
1757 			OBJ_SEC_VALUE(new_objp) = realloc(plain_data,
1758 			    OBJ_SEC_VALUE_LEN(new_objp));
1759 			if (OBJ_SEC_VALUE(new_objp) == NULL) {
1760 				rv = CKR_HOST_MEMORY;
1761 				goto cleanup_unwrap;
1762 			}
1763 		}
1764 	} else {
1765 		/* BER-decode the object to be unwrapped. */
1766 		rv = soft_asn1_to_object(new_objp, plain_data, plain_len);
1767 		if (rv != CKR_OK)
1768 			goto cleanup_unwrap;
1769 	}
1770 
1771 	/* If it needs to be persistent, write it to the keystore */
1772 	if (IS_TOKEN_OBJECT(new_objp)) {
1773 		persistent = B_TRUE;
1774 		rv = soft_put_object_to_keystore(new_objp);
1775 		if (rv != CKR_OK)
1776 			goto cleanup_unwrap;
1777 	}
1778 
1779 	if (new_objp->class != CKO_SECRET_KEY) {
1780 		/* Clear buffer before returning to memory pool. */
1781 		(void) memset(plain_data, 0x0, plain_len);
1782 		free(plain_data);
1783 	}
1784 
1785 	*phKey = (CK_OBJECT_HANDLE)new_objp;
1786 
1787 	return (CKR_OK);
1788 
1789 cleanup_unwrap:
1790 	/* The decrypted private key buffer must be freed explicitly. */
1791 	if ((new_objp->class != CKO_SECRET_KEY) && (plain_data != NULL)) {
1792 		/* Clear buffer before returning to memory pool. */
1793 		(void) memset(plain_data, 0x0, plain_len);
1794 		free(plain_data);
1795 	}
1796 
1797 	/* sck and new_objp are indirectly free()d inside these functions */
1798 	if (IS_TOKEN_OBJECT(new_objp))
1799 		soft_delete_token_object(new_objp, persistent, B_FALSE);
1800 	else
1801 		soft_delete_object(session_p, new_objp, B_FALSE);
1802 
1803 	return (rv);
1804 }
1805