xref: /titanic_50/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelAttributeUtil.c (revision 29e83d4b25fd82feb8e0e0fbe89f7e2a8438533d)
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 2007 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 <stdlib.h>
29 #include <string.h>
30 #include <security/cryptoki.h>
31 #include <aes_impl.h>
32 #include <blowfish_impl.h>
33 #include <arcfour.h>
34 #include <des_impl.h>
35 #include "kernelGlobal.h"
36 #include "kernelObject.h"
37 #include "kernelSession.h"
38 #include "kernelSlot.h"
39 
40 
41 /*
42  * This attribute table is used by the kernel_lookup_attr()
43  * to validate the attributes.
44  */
45 CK_ATTRIBUTE_TYPE attr_map[] = {
46 	CKA_PRIVATE,
47 	CKA_LABEL,
48 	CKA_APPLICATION,
49 	CKA_OBJECT_ID,
50 	CKA_CERTIFICATE_TYPE,
51 	CKA_ISSUER,
52 	CKA_SERIAL_NUMBER,
53 	CKA_AC_ISSUER,
54 	CKA_OWNER,
55 	CKA_ATTR_TYPES,
56 	CKA_SUBJECT,
57 	CKA_ID,
58 	CKA_SENSITIVE,
59 	CKA_START_DATE,
60 	CKA_END_DATE,
61 	CKA_MODULUS,
62 	CKA_MODULUS_BITS,
63 	CKA_PUBLIC_EXPONENT,
64 	CKA_PRIVATE_EXPONENT,
65 	CKA_PRIME_1,
66 	CKA_PRIME_2,
67 	CKA_EXPONENT_1,
68 	CKA_EXPONENT_2,
69 	CKA_COEFFICIENT,
70 	CKA_PRIME,
71 	CKA_SUBPRIME,
72 	CKA_BASE,
73 	CKA_EXTRACTABLE,
74 	CKA_LOCAL,
75 	CKA_NEVER_EXTRACTABLE,
76 	CKA_ALWAYS_SENSITIVE,
77 	CKA_MODIFIABLE,
78 	CKA_ECDSA_PARAMS,
79 	CKA_EC_POINT,
80 	CKA_SECONDARY_AUTH,
81 	CKA_AUTH_PIN_FLAGS,
82 	CKA_HW_FEATURE_TYPE,
83 	CKA_RESET_ON_INIT,
84 	CKA_HAS_RESET
85 };
86 
87 /*
88  * attributes that exists only in public key objects
89  * Note: some attributes may also exist in one or two
90  *       other object classes, but they are also listed
91  *       because not all object have them.
92  */
93 CK_ATTRIBUTE_TYPE PUB_KEY_ATTRS[] =
94 {
95 	CKA_SUBJECT,
96 	CKA_ENCRYPT,
97 	CKA_WRAP,
98 	CKA_VERIFY,
99 	CKA_VERIFY_RECOVER,
100 	CKA_MODULUS,
101 	CKA_MODULUS_BITS,
102 	CKA_PUBLIC_EXPONENT,
103 	CKA_PRIME,
104 	CKA_SUBPRIME,
105 	CKA_BASE,
106 	CKA_TRUSTED,
107 	CKA_ECDSA_PARAMS,
108 	CKA_EC_PARAMS,
109 	CKA_EC_POINT
110 };
111 
112 /*
113  * attributes that exists only in private key objects
114  * Note: some attributes may also exist in one or two
115  *       other object classes, but they are also listed
116  *       because not all object have them.
117  */
118 CK_ATTRIBUTE_TYPE PRIV_KEY_ATTRS[] =
119 {
120 	CKA_DECRYPT,
121 	CKA_UNWRAP,
122 	CKA_SIGN,
123 	CKA_SIGN_RECOVER,
124 	CKA_MODULUS,
125 	CKA_PUBLIC_EXPONENT,
126 	CKA_PRIVATE_EXPONENT,
127 	CKA_PRIME,
128 	CKA_SUBPRIME,
129 	CKA_BASE,
130 	CKA_PRIME_1,
131 	CKA_PRIME_2,
132 	CKA_EXPONENT_1,
133 	CKA_EXPONENT_2,
134 	CKA_COEFFICIENT,
135 	CKA_VALUE_BITS,
136 	CKA_SUBJECT,
137 	CKA_SENSITIVE,
138 	CKA_EXTRACTABLE,
139 	CKA_NEVER_EXTRACTABLE,
140 	CKA_ALWAYS_SENSITIVE,
141 	CKA_ECDSA_PARAMS,
142 	CKA_EC_PARAMS
143 };
144 
145 /*
146  * attributes that exists only in secret key objects
147  * Note: some attributes may also exist in one or two
148  *       other object classes, but they are also listed
149  *       because not all object have them.
150  */
151 CK_ATTRIBUTE_TYPE SECRET_KEY_ATTRS[] =
152 {
153 	CKA_VALUE_LEN,
154 	CKA_ENCRYPT,
155 	CKA_DECRYPT,
156 	CKA_WRAP,
157 	CKA_UNWRAP,
158 	CKA_SIGN,
159 	CKA_VERIFY,
160 	CKA_SENSITIVE,
161 	CKA_EXTRACTABLE,
162 	CKA_NEVER_EXTRACTABLE,
163 	CKA_ALWAYS_SENSITIVE
164 };
165 
166 /*
167  * attributes that exists only in domain parameter objects
168  * Note: some attributes may also exist in one or two
169  *       other object classes, but they are also listed
170  *       because not all object have them.
171  */
172 CK_ATTRIBUTE_TYPE DOMAIN_ATTRS[] =
173 {
174 	CKA_PRIME,
175 	CKA_SUBPRIME,
176 	CKA_BASE,
177 	CKA_PRIME_BITS,
178 	CKA_SUBPRIME_BITS,
179 	CKA_SUB_PRIME_BITS
180 };
181 
182 /*
183  * attributes that exists only in hardware feature objects
184  */
185 CK_ATTRIBUTE_TYPE HARDWARE_ATTRS[] =
186 {
187 	CKA_HW_FEATURE_TYPE,
188 	CKA_RESET_ON_INIT,
189 	CKA_HAS_RESET
190 };
191 
192 /*
193  * attributes that exists only in certificate objects
194  */
195 CK_ATTRIBUTE_TYPE CERT_ATTRS[] =
196 {
197 	CKA_CERTIFICATE_TYPE,
198 	CKA_SUBJECT,
199 	CKA_ID,
200 	CKA_ISSUER,
201 	CKA_AC_ISSUER,
202 	CKA_SERIAL_NUMBER,
203 	CKA_OWNER,
204 	CKA_ATTR_TYPES
205 };
206 
207 
208 /*
209  * Validate the attribute by using binary search algorithm.
210  */
211 CK_RV
212 kernel_lookup_attr(CK_ATTRIBUTE_TYPE type)
213 {
214 
215 	size_t lower, middle, upper;
216 
217 	lower = 0;
218 	upper = (sizeof (attr_map) / sizeof (CK_ATTRIBUTE_TYPE)) - 1;
219 
220 	while (lower <= upper) {
221 		/* Always starts from middle. */
222 		middle = (lower + upper) / 2;
223 
224 		if (type > attr_map[middle]) {
225 			/* Adjust the lower bound to upper half. */
226 			lower = middle + 1;
227 			continue;
228 		}
229 
230 		if (type == attr_map[middle]) {
231 			/* Found it. */
232 			return (CKR_OK);
233 		}
234 
235 		if (type < attr_map[middle]) {
236 			/* Adjust the upper bound to lower half. */
237 			upper = middle - 1;
238 			continue;
239 		}
240 	}
241 
242 	/* Failed to find the matching attribute from the attribute table. */
243 	return (CKR_ATTRIBUTE_TYPE_INVALID);
244 }
245 
246 
247 /*
248  * Validate the attribute by using the following search algorithm:
249  *
250  * 1) Search for the most frequently used attributes first.
251  * 2) If not found, search for the usage-purpose attributes - these
252  *    attributes have dense set of values, therefore compiler will
253  *    optimize it with a branch table and branch to the appropriate
254  *    case.
255  * 3) If still not found, use binary search for the rest of the
256  *    attributes in the attr_map[] table.
257  */
258 CK_RV
259 kernel_validate_attr(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
260 	CK_OBJECT_CLASS *class)
261 {
262 
263 	CK_ULONG i;
264 	CK_RV rv = CKR_OK;
265 
266 	for (i = 0; i < ulAttrNum; i++) {
267 		/* First tier search */
268 		switch (template[i].type) {
269 		case CKA_CLASS:
270 			*class = *((CK_OBJECT_CLASS*)template[i].pValue);
271 			break;
272 		case CKA_TOKEN:
273 			break;
274 		case CKA_KEY_TYPE:
275 			break;
276 		case CKA_VALUE:
277 			break;
278 		case CKA_VALUE_LEN:
279 			break;
280 		case CKA_VALUE_BITS:
281 			break;
282 		default:
283 			/* Second tier search */
284 			switch (template[i].type) {
285 			case CKA_ENCRYPT:
286 				break;
287 			case CKA_DECRYPT:
288 				break;
289 			case CKA_WRAP:
290 				break;
291 			case CKA_UNWRAP:
292 				break;
293 			case CKA_SIGN:
294 				break;
295 			case CKA_SIGN_RECOVER:
296 				break;
297 			case CKA_VERIFY:
298 				break;
299 			case CKA_VERIFY_RECOVER:
300 				break;
301 			case CKA_DERIVE:
302 				break;
303 			default:
304 				/* Third tier search */
305 				rv = kernel_lookup_attr(template[i].type);
306 				if (rv != CKR_OK)
307 					return (rv);
308 				break;
309 			}
310 			break;
311 		}
312 	}
313 	return (rv);
314 }
315 
316 
317 /*
318  * Clean up and release all the storage in the extra attribute list
319  * of an object.
320  */
321 void
322 kernel_cleanup_extra_attr(kernel_object_t *object_p)
323 {
324 
325 	CK_ATTRIBUTE_INFO_PTR extra_attr;
326 	CK_ATTRIBUTE_INFO_PTR tmp;
327 
328 	extra_attr = object_p->extra_attrlistp;
329 	while (extra_attr) {
330 		tmp = extra_attr->next;
331 		if (extra_attr->attr.pValue)
332 			/*
333 			 * All extra attributes in the extra attribute
334 			 * list have pValue points to the value of the
335 			 * attribute (with simple byte array type).
336 			 * Free the storage for the value of the attribute.
337 			 */
338 			free(extra_attr->attr.pValue);
339 
340 		/* Free the storage for the attribute_info struct. */
341 		free(extra_attr);
342 		extra_attr = tmp;
343 	}
344 
345 	object_p->extra_attrlistp = NULL;
346 }
347 
348 
349 /*
350  * Create the attribute_info struct to hold the object's attribute,
351  * and add it to the extra attribute list of an object.
352  */
353 CK_RV
354 kernel_add_extra_attr(CK_ATTRIBUTE_PTR template, kernel_object_t *object_p)
355 {
356 
357 	CK_ATTRIBUTE_INFO_PTR attrp;
358 
359 	/* Allocate the storage for the attribute_info struct. */
360 	attrp = calloc(1, sizeof (attribute_info_t));
361 	if (attrp == NULL) {
362 		return (CKR_HOST_MEMORY);
363 	}
364 
365 	/* Set up attribute_info struct. */
366 	attrp->attr.type = template->type;
367 	attrp->attr.ulValueLen = template->ulValueLen;
368 
369 	if ((template->pValue != NULL) &&
370 	    (template->ulValueLen > 0)) {
371 		/* Allocate storage for the value of the attribute. */
372 		attrp->attr.pValue = malloc(template->ulValueLen);
373 		if (attrp->attr.pValue == NULL) {
374 			free(attrp);
375 			return (CKR_HOST_MEMORY);
376 		}
377 
378 		(void) memcpy(attrp->attr.pValue, template->pValue,
379 		    template->ulValueLen);
380 	} else {
381 		attrp->attr.pValue = NULL;
382 	}
383 
384 	/* Insert the new attribute in front of extra attribute list. */
385 	if (object_p->extra_attrlistp == NULL) {
386 		object_p->extra_attrlistp = attrp;
387 		attrp->next = NULL;
388 	} else {
389 		attrp->next = object_p->extra_attrlistp;
390 		object_p->extra_attrlistp = attrp;
391 	}
392 
393 	return (CKR_OK);
394 }
395 
396 
397 /*
398  * Copy the attribute_info struct from the old object to a new attribute_info
399  * struct, and add that new struct to the extra attribute list of the new
400  * object.
401  */
402 CK_RV
403 kernel_copy_extra_attr(CK_ATTRIBUTE_INFO_PTR old_attrp,
404     kernel_object_t *object_p)
405 {
406 	CK_ATTRIBUTE_INFO_PTR attrp;
407 
408 	/* Allocate attribute_info struct. */
409 	attrp = calloc(1, sizeof (attribute_info_t));
410 	if (attrp == NULL) {
411 		return (CKR_HOST_MEMORY);
412 	}
413 
414 	attrp->attr.type = old_attrp->attr.type;
415 	attrp->attr.ulValueLen = old_attrp->attr.ulValueLen;
416 
417 	if ((old_attrp->attr.pValue != NULL) &&
418 		(old_attrp->attr.ulValueLen > 0)) {
419 		attrp->attr.pValue = malloc(old_attrp->attr.ulValueLen);
420 		if (attrp->attr.pValue == NULL) {
421 			free(attrp);
422 			return (CKR_HOST_MEMORY);
423 		}
424 
425 		(void) memcpy(attrp->attr.pValue, old_attrp->attr.pValue,
426 		    old_attrp->attr.ulValueLen);
427 	} else {
428 		attrp->attr.pValue = NULL;
429 	}
430 
431 	/* Insert the new attribute in front of extra attribute list */
432 	if (object_p->extra_attrlistp == NULL) {
433 		object_p->extra_attrlistp = attrp;
434 		attrp->next = NULL;
435 	} else {
436 		attrp->next = object_p->extra_attrlistp;
437 		object_p->extra_attrlistp = attrp;
438 	}
439 
440 	return (CKR_OK);
441 }
442 
443 
444 /*
445  * Get the attribute triple from the extra attribute list in the object
446  * (if the specified attribute type is found), and copy it to a template.
447  * Note the type of the attribute to be copied is specified by the template,
448  * and the storage is pre-allocated for the atrribute value in the template
449  * for doing the copy.
450  */
451 CK_RV
452 get_extra_attr_from_object(kernel_object_t *object_p, CK_ATTRIBUTE_PTR template)
453 {
454 
455 	CK_ATTRIBUTE_INFO_PTR extra_attr;
456 	CK_ATTRIBUTE_TYPE type = template->type;
457 
458 	extra_attr = object_p->extra_attrlistp;
459 
460 	while (extra_attr) {
461 		if (type == extra_attr->attr.type) {
462 			/* Found it. */
463 			break;
464 		} else {
465 			/* Does not match, try next one. */
466 			extra_attr = extra_attr->next;
467 		}
468 	}
469 
470 	if (extra_attr == NULL) {
471 		/* A valid but un-initialized attribute. */
472 		template->ulValueLen = 0;
473 		return (CKR_OK);
474 	}
475 
476 	/*
477 	 * We found the attribute in the extra attribute list.
478 	 */
479 	if (template->pValue == NULL) {
480 		template->ulValueLen = extra_attr->attr.ulValueLen;
481 		return (CKR_OK);
482 	}
483 
484 	if (template->ulValueLen >= extra_attr->attr.ulValueLen) {
485 		/*
486 		 * The buffer provided by the application is large
487 		 * enough to hold the value of the attribute.
488 		 */
489 		(void) memcpy(template->pValue, extra_attr->attr.pValue,
490 		    extra_attr->attr.ulValueLen);
491 		template->ulValueLen = extra_attr->attr.ulValueLen;
492 		return (CKR_OK);
493 	} else {
494 		/*
495 		 * The buffer provided by the application does
496 		 * not have enough space to hold the value.
497 		 */
498 		template->ulValueLen = (CK_ULONG)-1;
499 		return (CKR_BUFFER_TOO_SMALL);
500 	}
501 }
502 
503 
504 /*
505  * Modify the attribute triple in the extra attribute list of the object
506  * if the specified attribute type is found. Otherwise, just add it to
507  * list.
508  */
509 CK_RV
510 set_extra_attr_to_object(kernel_object_t *object_p, CK_ATTRIBUTE_TYPE type,
511 	CK_ATTRIBUTE_PTR template)
512 {
513 
514 	CK_ATTRIBUTE_INFO_PTR extra_attr;
515 
516 	extra_attr = object_p->extra_attrlistp;
517 
518 	while (extra_attr) {
519 		if (type == extra_attr->attr.type) {
520 			/* Found it. */
521 			break;
522 		} else {
523 			/* Does not match, try next one. */
524 			extra_attr = extra_attr->next;
525 		}
526 	}
527 
528 	if (extra_attr == NULL) {
529 		/*
530 		 * This attribute is a new one, go ahead adding it to
531 		 * the extra attribute list.
532 		 */
533 		return (kernel_add_extra_attr(template, object_p));
534 	}
535 
536 	/* We found the attribute in the extra attribute list. */
537 	if ((template->pValue != NULL) &&
538 	    (template->ulValueLen > 0)) {
539 		if (template->ulValueLen > extra_attr->attr.ulValueLen) {
540 			/* The old buffer is too small to hold the new value. */
541 			if (extra_attr->attr.pValue != NULL)
542 				/* Free storage for the old attribute value. */
543 				free(extra_attr->attr.pValue);
544 
545 			/* Allocate storage for the new attribute value. */
546 			extra_attr->attr.pValue = malloc(template->ulValueLen);
547 			if (extra_attr->attr.pValue == NULL) {
548 				return (CKR_HOST_MEMORY);
549 			}
550 		}
551 
552 		/* Replace the attribute with new value. */
553 		extra_attr->attr.ulValueLen = template->ulValueLen;
554 		(void) memcpy(extra_attr->attr.pValue, template->pValue,
555 		    template->ulValueLen);
556 	} else {
557 		extra_attr->attr.pValue = NULL;
558 	}
559 
560 	return (CKR_OK);
561 }
562 
563 
564 /*
565  * Copy the big integer attribute value from template to a biginteger_t struct.
566  */
567 CK_RV
568 get_bigint_attr_from_template(biginteger_t *big, CK_ATTRIBUTE_PTR template)
569 {
570 
571 	if ((template->pValue != NULL) &&
572 	    (template->ulValueLen > 0)) {
573 		/* Allocate storage for the value of the attribute. */
574 		big->big_value = malloc(template->ulValueLen);
575 		if (big->big_value == NULL) {
576 			return (CKR_HOST_MEMORY);
577 		}
578 
579 		(void) memcpy(big->big_value, template->pValue,
580 		    template->ulValueLen);
581 		big->big_value_len = template->ulValueLen;
582 	} else {
583 		big->big_value = NULL;
584 		big->big_value_len = 0;
585 	}
586 
587 	return (CKR_OK);
588 }
589 
590 
591 /*
592  * Copy the big integer attribute value from a biginteger_t struct in the
593  * object to a template.
594  */
595 CK_RV
596 get_bigint_attr_from_object(biginteger_t *big, CK_ATTRIBUTE_PTR template)
597 {
598 
599 	if (template->pValue == NULL) {
600 		template->ulValueLen = big->big_value_len;
601 		return (CKR_OK);
602 	}
603 
604 	if (big->big_value == NULL) {
605 		template->ulValueLen = 0;
606 		return (CKR_OK);
607 	}
608 
609 	if (template->ulValueLen >= big->big_value_len) {
610 		/*
611 		 * The buffer provided by the application is large
612 		 * enough to hold the value of the attribute.
613 		 */
614 		(void) memcpy(template->pValue, big->big_value,
615 		    big->big_value_len);
616 		template->ulValueLen = big->big_value_len;
617 		return (CKR_OK);
618 	} else {
619 		/*
620 		 * The buffer provided by the application does
621 		 * not have enough space to hold the value.
622 		 */
623 		template->ulValueLen = (CK_ULONG)-1;
624 		return (CKR_BUFFER_TOO_SMALL);
625 	}
626 }
627 
628 
629 /*
630  * Copy the boolean data type attribute value from an object for the
631  * specified attribute to the template.
632  */
633 CK_RV
634 get_bool_attr_from_object(kernel_object_t *object_p, CK_ULONG bool_flag,
635 	CK_ATTRIBUTE_PTR template)
636 {
637 
638 	if (template->pValue == NULL) {
639 		template->ulValueLen = sizeof (CK_BBOOL);
640 		return (CKR_OK);
641 	}
642 
643 	if (template->ulValueLen >= sizeof (CK_BBOOL)) {
644 		/*
645 		 * The buffer provided by the application is large
646 		 * enough to hold the value of the attribute.
647 		 */
648 		if (object_p->bool_attr_mask & bool_flag) {
649 			*((CK_BBOOL *)template->pValue) = B_TRUE;
650 		} else {
651 			*((CK_BBOOL *)template->pValue) = B_FALSE;
652 		}
653 
654 		template->ulValueLen = sizeof (CK_BBOOL);
655 		return (CKR_OK);
656 	} else {
657 		/*
658 		 * The buffer provided by the application does
659 		 * not have enough space to hold the value.
660 		 */
661 		template->ulValueLen = (CK_ULONG)-1;
662 		return (CKR_BUFFER_TOO_SMALL);
663 	}
664 }
665 
666 /*
667  * Set the boolean data type attribute value in the object.
668  */
669 CK_RV
670 set_bool_attr_to_object(kernel_object_t *object_p, CK_ULONG bool_flag,
671 	CK_ATTRIBUTE_PTR template)
672 {
673 
674 	if (*(CK_BBOOL *)template->pValue)
675 		object_p->bool_attr_mask |= bool_flag;
676 	else
677 		object_p->bool_attr_mask &= ~bool_flag;
678 
679 	return (CKR_OK);
680 }
681 
682 
683 /*
684  * Copy the CK_ULONG data type attribute value from an object to the
685  * template.
686  */
687 CK_RV
688 get_ulong_attr_from_object(CK_ULONG value, CK_ATTRIBUTE_PTR template)
689 {
690 
691 	if (template->pValue == NULL) {
692 		template->ulValueLen = sizeof (CK_ULONG);
693 		return (CKR_OK);
694 	}
695 
696 	if (template->ulValueLen >= sizeof (CK_ULONG)) {
697 		/*
698 		 * The buffer provided by the application is large
699 		 * enough to hold the value of the attribute.
700 		 */
701 		*(CK_ULONG_PTR)template->pValue = value;
702 		template->ulValueLen = sizeof (CK_ULONG);
703 		return (CKR_OK);
704 	} else {
705 		/*
706 		 * The buffer provided by the application does
707 		 * not have enough space to hold the value.
708 		 */
709 		template->ulValueLen = (CK_ULONG)-1;
710 		return (CKR_BUFFER_TOO_SMALL);
711 	}
712 }
713 
714 
715 /*
716  * Copy the CK_ULONG data type attribute value from a template to the
717  * object.
718  */
719 void
720 get_ulong_attr_from_template(CK_ULONG *value, CK_ATTRIBUTE_PTR template)
721 {
722 
723 	if (template->pValue != NULL) {
724 		*value = *(CK_ULONG_PTR)template->pValue;
725 	} else {
726 		*value = 0;
727 	}
728 
729 }
730 
731 /*
732  * Copy the big integer attribute value from source's biginteger_t to
733  * destination's biginteger_t.
734  */
735 void
736 copy_bigint_attr(biginteger_t *src, biginteger_t *dst)
737 {
738 
739 	if ((src->big_value != NULL) &&
740 	    (src->big_value_len > 0)) {
741 		/*
742 		 * To do the copy, just have dst's big_value points
743 		 * to src's.
744 		 */
745 		dst->big_value = src->big_value;
746 		dst->big_value_len = src->big_value_len;
747 
748 		/*
749 		 * After the copy, nullify the src's big_value pointer.
750 		 * It prevents any double freeing the value.
751 		 */
752 		src->big_value = NULL;
753 		src->big_value_len = 0;
754 	} else {
755 		dst->big_value = NULL;
756 		dst->big_value_len = 0;
757 	}
758 
759 }
760 
761 
762 CK_RV
763 get_string_from_template(CK_ATTRIBUTE_PTR dest, CK_ATTRIBUTE_PTR src)
764 {
765 	if ((src->pValue != NULL) &&
766 	    (src->ulValueLen > 0)) {
767 		/* Allocate storage for the value of the attribute. */
768 		dest->pValue = malloc(src->ulValueLen);
769 		if (dest->pValue == NULL) {
770 			return (CKR_HOST_MEMORY);
771 		}
772 
773 		(void) memcpy(dest->pValue, src->pValue,
774 		    src->ulValueLen);
775 		dest->ulValueLen = src->ulValueLen;
776 		dest->type = src->type;
777 	} else {
778 		dest->pValue = NULL;
779 		dest->ulValueLen = 0;
780 		dest->type = src->type;
781 	}
782 
783 	return (CKR_OK);
784 
785 }
786 
787 void
788 string_attr_cleanup(CK_ATTRIBUTE_PTR template)
789 {
790 
791 	if (template->pValue) {
792 		free(template->pValue);
793 		template->pValue = NULL;
794 		template->ulValueLen = 0;
795 	}
796 }
797 
798 /*
799  * Release the storage allocated for object attribute with big integer
800  * value.
801  */
802 void
803 bigint_attr_cleanup(biginteger_t *big)
804 {
805 
806 	if (big == NULL)
807 		return;
808 
809 	if (big->big_value) {
810 		(void) memset(big->big_value, 0, big->big_value_len);
811 		free(big->big_value);
812 		big->big_value = NULL;
813 		big->big_value_len = 0;
814 	}
815 }
816 
817 
818 /*
819  * Clean up and release all the storage allocated to hold the big integer
820  * attributes associated with the type (i.e. class) of the object. Also,
821  * release the storage allocated to the type of the object.
822  */
823 void
824 kernel_cleanup_object_bigint_attrs(kernel_object_t *object_p)
825 {
826 
827 	CK_OBJECT_CLASS class = object_p->class;
828 	CK_KEY_TYPE	keytype = object_p->key_type;
829 
830 
831 	switch (class) {
832 	case CKO_PUBLIC_KEY:
833 		if (OBJ_PUB(object_p)) {
834 			switch (keytype) {
835 			case CKK_RSA:
836 				bigint_attr_cleanup(OBJ_PUB_RSA_MOD(
837 				    object_p));
838 				bigint_attr_cleanup(OBJ_PUB_RSA_PUBEXPO(
839 				    object_p));
840 				break;
841 
842 			case CKK_DSA:
843 				bigint_attr_cleanup(OBJ_PUB_DSA_PRIME(
844 				    object_p));
845 				bigint_attr_cleanup(OBJ_PUB_DSA_SUBPRIME(
846 				    object_p));
847 				bigint_attr_cleanup(OBJ_PUB_DSA_BASE(
848 				    object_p));
849 				bigint_attr_cleanup(OBJ_PUB_DSA_VALUE(
850 				    object_p));
851 				break;
852 
853 			case CKK_DH:
854 				bigint_attr_cleanup(OBJ_PUB_DH_PRIME(object_p));
855 				bigint_attr_cleanup(OBJ_PUB_DH_BASE(object_p));
856 				bigint_attr_cleanup(OBJ_PUB_DH_VALUE(object_p));
857 				break;
858 
859 			case CKK_EC:
860 				bigint_attr_cleanup(OBJ_PUB_EC_POINT(object_p));
861 				break;
862 			}
863 
864 			/* Release Public Key Object struct */
865 			free(OBJ_PUB(object_p));
866 			OBJ_PUB(object_p) = NULL;
867 		}
868 		break;
869 
870 	case CKO_PRIVATE_KEY:
871 		if (OBJ_PRI(object_p)) {
872 			switch (keytype) {
873 			case CKK_RSA:
874 				bigint_attr_cleanup(OBJ_PRI_RSA_MOD(
875 				    object_p));
876 				bigint_attr_cleanup(OBJ_PRI_RSA_PUBEXPO(
877 				    object_p));
878 				bigint_attr_cleanup(OBJ_PRI_RSA_PRIEXPO(
879 				    object_p));
880 				bigint_attr_cleanup(OBJ_PRI_RSA_PRIME1(
881 				    object_p));
882 				bigint_attr_cleanup(OBJ_PRI_RSA_PRIME2(
883 				    object_p));
884 				bigint_attr_cleanup(OBJ_PRI_RSA_EXPO1(
885 				    object_p));
886 				bigint_attr_cleanup(OBJ_PRI_RSA_EXPO2(
887 				    object_p));
888 				bigint_attr_cleanup(OBJ_PRI_RSA_COEF(
889 				    object_p));
890 				break;
891 
892 			case CKK_DSA:
893 				bigint_attr_cleanup(OBJ_PRI_DSA_PRIME(
894 				    object_p));
895 				bigint_attr_cleanup(OBJ_PRI_DSA_SUBPRIME(
896 				    object_p));
897 				bigint_attr_cleanup(OBJ_PRI_DSA_BASE(
898 				    object_p));
899 				bigint_attr_cleanup(OBJ_PRI_DSA_VALUE(
900 				    object_p));
901 				break;
902 
903 			case CKK_DH:
904 				bigint_attr_cleanup(OBJ_PRI_DH_PRIME(object_p));
905 				bigint_attr_cleanup(OBJ_PRI_DH_BASE(object_p));
906 				bigint_attr_cleanup(OBJ_PRI_DH_VALUE(object_p));
907 				break;
908 
909 			case CKK_EC:
910 				bigint_attr_cleanup(OBJ_PRI_EC_VALUE(object_p));
911 				break;
912 			}
913 
914 			/* Release Private Key Object struct. */
915 			free(OBJ_PRI(object_p));
916 			OBJ_PRI(object_p) = NULL;
917 		}
918 		break;
919 	}
920 }
921 
922 
923 /*
924  * Parse the common attributes. Return to caller with appropriate return
925  * value to indicate if the supplied template specifies a valid attribute
926  * with a valid value.
927  */
928 CK_RV
929 kernel_parse_common_attrs(CK_ATTRIBUTE_PTR template, kernel_session_t *sp,
930     uint64_t *attr_mask_p)
931 {
932 
933 	CK_RV rv = CKR_OK;
934 	kernel_slot_t *pslot = slot_table[sp->ses_slotid];
935 
936 	switch (template->type) {
937 	case CKA_CLASS:
938 		break;
939 
940 	/* default boolean attributes */
941 	case CKA_TOKEN:
942 		if ((*(CK_BBOOL *)template->pValue) == TRUE) {
943 			rv = CKR_ATTRIBUTE_VALUE_INVALID;
944 		}
945 		break;
946 
947 	case CKA_PRIVATE:
948 		if ((*(CK_BBOOL *)template->pValue) == TRUE) {
949 			/*
950 			 * Cannot create a private object if the token
951 			 * has a keystore and the user isn't logged in.
952 			 */
953 			if (pslot->sl_func_list.fl_object_create &&
954 			    pslot->sl_state != CKU_USER) {
955 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
956 			} else {
957 				*attr_mask_p |= PRIVATE_BOOL_ON;
958 			}
959 		}
960 		break;
961 
962 	case CKA_MODIFIABLE:
963 		if ((*(CK_BBOOL *)template->pValue) == FALSE) {
964 			*attr_mask_p &= ~MODIFIABLE_BOOL_ON;
965 		}
966 		break;
967 
968 	case CKA_LABEL:
969 		break;
970 
971 	default:
972 		rv = CKR_TEMPLATE_INCONSISTENT;
973 	}
974 
975 	return (rv);
976 }
977 
978 
979 
980 
981 /*
982  * Build a Public Key Object.
983  *
984  * - Parse the object's template, and when an error is detected such as
985  *   invalid attribute type, invalid attribute value, etc., return
986  *   with appropriate return value.
987  * - Set up attribute mask field in the object for the supplied common
988  *   attributes that have boolean type.
989  * - Build the attribute_info struct to hold the value of each supplied
990  *   attribute that has byte array type. Link attribute_info structs
991  *   together to form the extra attribute list of the object.
992  * - Allocate storage for the Public Key object.
993  * - Build the Public Key object according to the key type. Allocate
994  *   storage to hold the big integer value for the supplied attributes
995  *   that are required for a certain key type.
996  *
997  */
998 CK_RV
999 kernel_build_public_key_object(CK_ATTRIBUTE_PTR template,
1000     CK_ULONG ulAttrNum,	kernel_object_t *new_object, kernel_session_t *sp,
1001     uint_t mode)
1002 {
1003 
1004 	int		i;
1005 	CK_KEY_TYPE	keytype = (CK_KEY_TYPE)~0UL;
1006 	uint64_t	attr_mask = PUBLIC_KEY_DEFAULT;
1007 	CK_RV 		rv = CKR_OK;
1008 	int		isLabel = 0;
1009 	/* Must set flags */
1010 	int		isModulus = 0;
1011 	int		isPubExpo = 0;
1012 	int		isPrime = 0;
1013 	int		isSubprime = 0;
1014 	int		isBase = 0;
1015 	int		isValue = 0;
1016 	int		isPoint = 0;
1017 	int		isParams = 0;
1018 	/* Must not set flags */
1019 	int		isModulusBits = 0;
1020 	CK_ULONG	modulus_bits = 0;
1021 
1022 	biginteger_t	modulus;
1023 	biginteger_t	pubexpo;
1024 	biginteger_t	prime;
1025 	biginteger_t	subprime;
1026 	biginteger_t	base;
1027 	biginteger_t	value;
1028 	biginteger_t	point;
1029 	CK_ATTRIBUTE	string_tmp;
1030 	CK_ATTRIBUTE	param_tmp;
1031 
1032 	public_key_obj_t  *pbk;
1033 
1034 	/* prevent bigint_attr_cleanup from freeing invalid attr value */
1035 	(void) memset(&modulus, 0x0, sizeof (biginteger_t));
1036 	(void) memset(&pubexpo, 0x0, sizeof (biginteger_t));
1037 	(void) memset(&prime, 0x0, sizeof (biginteger_t));
1038 	(void) memset(&subprime, 0x0, sizeof (biginteger_t));
1039 	(void) memset(&base, 0x0, sizeof (biginteger_t));
1040 	(void) memset(&value, 0x0, sizeof (biginteger_t));
1041 	(void) memset(&point, 0x0, sizeof (biginteger_t));
1042 	string_tmp.pValue = NULL;
1043 	param_tmp.pValue = NULL;
1044 
1045 	for (i = 0; i < ulAttrNum; i++) {
1046 
1047 		/* Public Key Object Attributes */
1048 		switch (template[i].type) {
1049 
1050 		/* common key attributes */
1051 		case CKA_KEY_TYPE:
1052 			keytype = *((CK_KEY_TYPE*)template[i].pValue);
1053 			break;
1054 
1055 		case CKA_ID:
1056 		case CKA_START_DATE:
1057 		case CKA_END_DATE:
1058 
1059 		/* common public key attribute */
1060 		case CKA_SUBJECT:
1061 			/*
1062 			 * Allocate storage to hold the attribute
1063 			 * value with byte array type, and add it to
1064 			 * the extra attribute list of the object.
1065 			 */
1066 			rv = kernel_add_extra_attr(&template[i],
1067 			    new_object);
1068 			if (rv != CKR_OK) {
1069 				goto fail_cleanup;
1070 			}
1071 			break;
1072 
1073 		/*
1074 		 * The following key related attribute types must
1075 		 * not be specified by C_CreateObject.
1076 		 */
1077 		case CKA_LOCAL:
1078 		case CKA_KEY_GEN_MECHANISM:
1079 			rv = CKR_TEMPLATE_INCONSISTENT;
1080 			goto fail_cleanup;
1081 
1082 		/* Key related boolean attributes */
1083 		case CKA_DERIVE:
1084 			if (*(CK_BBOOL *)template[i].pValue)
1085 				attr_mask |= DERIVE_BOOL_ON;
1086 			break;
1087 
1088 		case CKA_ENCRYPT:
1089 			if (*(CK_BBOOL *)template[i].pValue)
1090 				attr_mask |= ENCRYPT_BOOL_ON;
1091 			else
1092 				attr_mask &= ~ENCRYPT_BOOL_ON;
1093 			break;
1094 
1095 		case CKA_VERIFY:
1096 			if (*(CK_BBOOL *)template[i].pValue)
1097 				attr_mask |= VERIFY_BOOL_ON;
1098 			else
1099 				attr_mask &= ~VERIFY_BOOL_ON;
1100 			break;
1101 
1102 		case CKA_VERIFY_RECOVER:
1103 			if (*(CK_BBOOL *)template[i].pValue)
1104 				attr_mask |= VERIFY_RECOVER_BOOL_ON;
1105 			else
1106 				attr_mask &= ~VERIFY_RECOVER_BOOL_ON;
1107 			break;
1108 
1109 		case CKA_WRAP:
1110 			if (*(CK_BBOOL *)template[i].pValue)
1111 				attr_mask |= WRAP_BOOL_ON;
1112 			break;
1113 
1114 		case CKA_TRUSTED:
1115 			if (*(CK_BBOOL *)template[i].pValue)
1116 				attr_mask |= TRUSTED_BOOL_ON;
1117 			break;
1118 
1119 		/*
1120 		 * The following key related attribute types must
1121 		 * be specified according to the key type by
1122 		 * C_CreateObject.
1123 		 */
1124 		case CKA_MODULUS:
1125 			isModulus = 1;
1126 			/*
1127 			 * Copyin big integer attribute from template
1128 			 * to a local variable.
1129 			 */
1130 			rv = get_bigint_attr_from_template(&modulus,
1131 			    &template[i]);
1132 			if (rv != CKR_OK)
1133 				goto fail_cleanup;
1134 			break;
1135 
1136 		case CKA_PUBLIC_EXPONENT:
1137 			isPubExpo = 1;
1138 			rv = get_bigint_attr_from_template(&pubexpo,
1139 			    &template[i]);
1140 			if (rv != CKR_OK)
1141 				goto fail_cleanup;
1142 			break;
1143 
1144 		case CKA_PRIME:
1145 			isPrime = 1;
1146 			rv = get_bigint_attr_from_template(&prime,
1147 			    &template[i]);
1148 			if (rv != CKR_OK)
1149 				goto fail_cleanup;
1150 			break;
1151 
1152 		case CKA_SUBPRIME:
1153 			isSubprime = 1;
1154 			rv = get_bigint_attr_from_template(&subprime,
1155 			    &template[i]);
1156 			if (rv != CKR_OK)
1157 				goto fail_cleanup;
1158 			break;
1159 
1160 		case CKA_BASE:
1161 			isBase = 1;
1162 			rv = get_bigint_attr_from_template(&base,
1163 			    &template[i]);
1164 			if (rv != CKR_OK)
1165 				goto fail_cleanup;
1166 			break;
1167 
1168 		case CKA_VALUE:
1169 			isValue = 1;
1170 			rv = get_bigint_attr_from_template(&value,
1171 			    &template[i]);
1172 			if (rv != CKR_OK)
1173 				goto fail_cleanup;
1174 			break;
1175 
1176 		case CKA_MODULUS_BITS:
1177 			isModulusBits = 1;
1178 			get_ulong_attr_from_template(&modulus_bits,
1179 			    &template[i]);
1180 			break;
1181 
1182 		case CKA_LABEL:
1183 			isLabel = 1;
1184 			rv = get_string_from_template(&string_tmp,
1185 			    &template[i]);
1186 			if (rv != CKR_OK)
1187 				goto fail_cleanup;
1188 			break;
1189 
1190 		case CKA_EC_POINT:
1191 			isPoint = 1;
1192 			rv = get_bigint_attr_from_template(&point,
1193 			    &template[i]);
1194 			if (rv != CKR_OK)
1195 				goto fail_cleanup;
1196 			break;
1197 
1198 		case CKA_EC_PARAMS:
1199 			isParams = 1;
1200 			rv = get_string_from_template(&param_tmp,
1201 			    &template[i]);
1202 			if (rv != CKR_OK)
1203 				goto fail_cleanup;
1204 			break;
1205 
1206 		default:
1207 			rv = kernel_parse_common_attrs(&template[i], sp,
1208 			    &attr_mask);
1209 			if (rv != CKR_OK)
1210 				goto fail_cleanup;
1211 			break;
1212 		}
1213 	} /* For */
1214 
1215 	/* Allocate storage for Public Key Object. */
1216 	pbk = calloc(1, sizeof (public_key_obj_t));
1217 	if (pbk == NULL) {
1218 		rv = CKR_HOST_MEMORY;
1219 		goto fail_cleanup;
1220 	}
1221 
1222 	new_object->object_class_u.public_key = pbk;
1223 	new_object->class = CKO_PUBLIC_KEY;
1224 
1225 	if (keytype == (CK_KEY_TYPE)~0UL) {
1226 		rv = CKR_TEMPLATE_INCOMPLETE;
1227 		goto fail_cleanup;
1228 	}
1229 	new_object->key_type = keytype;
1230 
1231 	/* Supported key types of the Public Key Object */
1232 	switch (keytype) {
1233 	case CKK_RSA:
1234 		if (mode == KERNEL_CREATE_OBJ) {
1235 			if (isModulusBits || isPrime || isSubprime ||
1236 			    isBase|| isValue) {
1237 				rv = CKR_TEMPLATE_INCONSISTENT;
1238 				goto fail_cleanup;
1239 			}
1240 		}
1241 
1242 		if (isModulus && isPubExpo) {
1243 			/*
1244 			 * Copy big integer attribute value to the
1245 			 * designated place in the public key object.
1246 			 */
1247 			copy_bigint_attr(&modulus,
1248 			    KEY_PUB_RSA_MOD(pbk));
1249 
1250 			copy_bigint_attr(&pubexpo,
1251 			    KEY_PUB_RSA_PUBEXPO(pbk));
1252 		} else {
1253 			rv = CKR_TEMPLATE_INCOMPLETE;
1254 			goto fail_cleanup;
1255 		}
1256 
1257 		/* must be generating a RSA key pair by value */
1258 		if (isModulusBits) {
1259 			KEY_PUB_RSA_MOD_BITS(pbk) = modulus_bits;
1260 		}
1261 		break;
1262 
1263 	case CKK_DSA:
1264 		if (isModulusBits || isModulus || isPubExpo) {
1265 			rv = CKR_TEMPLATE_INCONSISTENT;
1266 			goto fail_cleanup;
1267 		}
1268 
1269 		if (!(isPrime && isSubprime && isBase && isValue)) {
1270 			rv = CKR_TEMPLATE_INCOMPLETE;
1271 			goto fail_cleanup;
1272 		}
1273 
1274 		copy_bigint_attr(&prime, KEY_PUB_DSA_PRIME(pbk));
1275 
1276 		copy_bigint_attr(&subprime, KEY_PUB_DSA_SUBPRIME(pbk));
1277 
1278 		copy_bigint_attr(&base, KEY_PUB_DSA_BASE(pbk));
1279 
1280 		copy_bigint_attr(&value, KEY_PUB_DSA_VALUE(pbk));
1281 
1282 		break;
1283 
1284 	case CKK_DH:
1285 		if (!(isPrime && isBase && isValue)) {
1286 			rv = CKR_TEMPLATE_INCOMPLETE;
1287 			goto fail_cleanup;
1288 		}
1289 
1290 		copy_bigint_attr(&prime, KEY_PUB_DH_PRIME(pbk));
1291 
1292 		copy_bigint_attr(&base, KEY_PUB_DH_BASE(pbk));
1293 
1294 		copy_bigint_attr(&value, KEY_PUB_DH_VALUE(pbk));
1295 
1296 		break;
1297 
1298 	case CKK_EC:
1299 		if (!isPoint || !isParams) {
1300 			rv = CKR_TEMPLATE_INCOMPLETE;
1301 			goto fail_cleanup;
1302 		}
1303 
1304 		copy_bigint_attr(&point, KEY_PUB_EC_POINT(pbk));
1305 		rv = kernel_add_extra_attr(&param_tmp, new_object);
1306 		if (rv != CKR_OK)
1307 			goto fail_cleanup;
1308 		string_attr_cleanup(&param_tmp);
1309 		break;
1310 	default:
1311 		rv = CKR_TEMPLATE_INCONSISTENT;
1312 		goto fail_cleanup;
1313 	}
1314 
1315 	/* Set up object. */
1316 	new_object->bool_attr_mask = attr_mask;
1317 	if (isLabel) {
1318 		rv = kernel_add_extra_attr(&string_tmp, new_object);
1319 		if (rv != CKR_OK)
1320 			goto fail_cleanup;
1321 		string_attr_cleanup(&string_tmp);
1322 	}
1323 
1324 	return (rv);
1325 
1326 fail_cleanup:
1327 	/*
1328 	 * cleanup the storage allocated to the local variables.
1329 	 */
1330 	bigint_attr_cleanup(&modulus);
1331 	bigint_attr_cleanup(&pubexpo);
1332 	bigint_attr_cleanup(&prime);
1333 	bigint_attr_cleanup(&subprime);
1334 	bigint_attr_cleanup(&base);
1335 	bigint_attr_cleanup(&value);
1336 	bigint_attr_cleanup(&point);
1337 	string_attr_cleanup(&string_tmp);
1338 	string_attr_cleanup(&param_tmp);
1339 
1340 	/*
1341 	 * cleanup the storage allocated inside the object itself.
1342 	 */
1343 	kernel_cleanup_object(new_object);
1344 
1345 	return (rv);
1346 }
1347 
1348 
1349 /*
1350  * Build a Private Key Object.
1351  *
1352  * - Parse the object's template, and when an error is detected such as
1353  *   invalid attribute type, invalid attribute value, etc., return
1354  *   with appropriate return value.
1355  * - Set up attribute mask field in the object for the supplied common
1356  *   attributes that have boolean type.
1357  * - Build the attribute_info struct to hold the value of each supplied
1358  *   attribute that has byte array type. Link attribute_info structs
1359  *   together to form the extra attribute list of the object.
1360  * - Allocate storage for the Private Key object.
1361  * - Build the Private Key object according to the key type. Allocate
1362  *   storage to hold the big integer value for the supplied attributes
1363  *   that are required for a certain key type.
1364  *
1365  */
1366 CK_RV
1367 kernel_build_private_key_object(CK_ATTRIBUTE_PTR template,
1368     CK_ULONG ulAttrNum,	kernel_object_t *new_object, kernel_session_t *sp,
1369     uint_t mode)
1370 {
1371 	ulong_t		i;
1372 	CK_KEY_TYPE	keytype = (CK_KEY_TYPE)~0UL;
1373 	uint64_t	attr_mask = PRIVATE_KEY_DEFAULT;
1374 	CK_RV 		rv = CKR_OK;
1375 	int		isLabel = 0;
1376 	/* Must set flags */
1377 	int		isModulus = 0;
1378 	int		isPriExpo = 0;
1379 	int		isPrime = 0;
1380 	int		isSubprime = 0;
1381 	int		isBase = 0;
1382 	int		isValue = 0;
1383 	int		isParams = 0;
1384 	/* Must not set flags */
1385 	int		isValueBits = 0;
1386 	CK_ULONG	value_bits = 0;
1387 
1388 	/* Private Key RSA optional */
1389 	int		isPubExpo = 0;
1390 	int		isPrime1 = 0;
1391 	int		isPrime2 = 0;
1392 	int		isExpo1 = 0;
1393 	int		isExpo2 = 0;
1394 	int		isCoef = 0;
1395 
1396 	biginteger_t	modulus;
1397 	biginteger_t	priexpo;
1398 	biginteger_t	prime;
1399 	biginteger_t	subprime;
1400 	biginteger_t	base;
1401 	biginteger_t	value;
1402 
1403 	biginteger_t	pubexpo;
1404 	biginteger_t	prime1;
1405 	biginteger_t	prime2;
1406 	biginteger_t	expo1;
1407 	biginteger_t	expo2;
1408 	biginteger_t	coef;
1409 	CK_ATTRIBUTE	string_tmp;
1410 	CK_ATTRIBUTE	param_tmp;
1411 
1412 	private_key_obj_t *pvk;
1413 
1414 	/* prevent bigint_attr_cleanup from freeing invalid attr value */
1415 	(void) memset(&modulus, 0x0, sizeof (biginteger_t));
1416 	(void) memset(&priexpo, 0x0, sizeof (biginteger_t));
1417 	(void) memset(&prime, 0x0, sizeof (biginteger_t));
1418 	(void) memset(&subprime, 0x0, sizeof (biginteger_t));
1419 	(void) memset(&base, 0x0, sizeof (biginteger_t));
1420 	(void) memset(&value, 0x0, sizeof (biginteger_t));
1421 	(void) memset(&pubexpo, 0x0, sizeof (biginteger_t));
1422 	(void) memset(&prime1, 0x0, sizeof (biginteger_t));
1423 	(void) memset(&prime2, 0x0, sizeof (biginteger_t));
1424 	(void) memset(&expo1, 0x0, sizeof (biginteger_t));
1425 	(void) memset(&expo2, 0x0, sizeof (biginteger_t));
1426 	(void) memset(&coef, 0x0, sizeof (biginteger_t));
1427 	string_tmp.pValue = NULL;
1428 	param_tmp.pValue = NULL;
1429 
1430 	for (i = 0; i < ulAttrNum; i++) {
1431 
1432 		/* Private Key Object Attributes */
1433 		switch (template[i].type) {
1434 
1435 		/* common key attributes */
1436 		case CKA_KEY_TYPE:
1437 			keytype = *((CK_KEY_TYPE*)template[i].pValue);
1438 			break;
1439 
1440 		case CKA_ID:
1441 		case CKA_START_DATE:
1442 		case CKA_END_DATE:
1443 
1444 		/* common private key attribute */
1445 		case CKA_SUBJECT:
1446 			/*
1447 			 * Allocate storage to hold the attribute
1448 			 * value with byte array type, and add it to
1449 			 * the extra attribute list of the object.
1450 			 */
1451 			rv = kernel_add_extra_attr(&template[i],
1452 			    new_object);
1453 			if (rv != CKR_OK) {
1454 				goto fail_cleanup;
1455 			}
1456 			break;
1457 
1458 		/*
1459 		 * The following key related attribute types must
1460 		 * not be specified by C_CreateObject.
1461 		 */
1462 		case CKA_LOCAL:
1463 		case CKA_KEY_GEN_MECHANISM:
1464 		case CKA_AUTH_PIN_FLAGS:
1465 		case CKA_ALWAYS_SENSITIVE:
1466 		case CKA_NEVER_EXTRACTABLE:
1467 			rv = CKR_TEMPLATE_INCONSISTENT;
1468 			goto fail_cleanup;
1469 
1470 		/* Key related boolean attributes */
1471 		case CKA_DERIVE:
1472 			if (*(CK_BBOOL *)template[i].pValue)
1473 				attr_mask |= DERIVE_BOOL_ON;
1474 			break;
1475 
1476 		case CKA_SENSITIVE:
1477 			if (*(CK_BBOOL *)template[i].pValue)
1478 				attr_mask |= SENSITIVE_BOOL_ON;
1479 			break;
1480 
1481 		case CKA_SECONDARY_AUTH:
1482 			if (*(CK_BBOOL *)template[i].pValue) {
1483 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
1484 				goto fail_cleanup;
1485 			}
1486 			break;
1487 
1488 		case CKA_DECRYPT:
1489 			if (*(CK_BBOOL *)template[i].pValue)
1490 				attr_mask |= DECRYPT_BOOL_ON;
1491 			else
1492 				attr_mask &= ~DECRYPT_BOOL_ON;
1493 			break;
1494 
1495 		case CKA_SIGN:
1496 			if (*(CK_BBOOL *)template[i].pValue)
1497 				attr_mask |= SIGN_BOOL_ON;
1498 			else
1499 				attr_mask &= ~SIGN_BOOL_ON;
1500 			break;
1501 
1502 		case CKA_SIGN_RECOVER:
1503 			if (*(CK_BBOOL *)template[i].pValue)
1504 				attr_mask |= SIGN_RECOVER_BOOL_ON;
1505 			else
1506 				attr_mask &= ~SIGN_RECOVER_BOOL_ON;
1507 			break;
1508 
1509 		case CKA_UNWRAP:
1510 			if (*(CK_BBOOL *)template[i].pValue)
1511 				attr_mask |= UNWRAP_BOOL_ON;
1512 			break;
1513 
1514 		case CKA_EXTRACTABLE:
1515 			if (*(CK_BBOOL *)template[i].pValue)
1516 				attr_mask |= EXTRACTABLE_BOOL_ON;
1517 			else
1518 				attr_mask &= ~EXTRACTABLE_BOOL_ON;
1519 			break;
1520 
1521 		/*
1522 		 * The following key related attribute types must
1523 		 * be specified according to the key type by
1524 		 * C_CreateObject.
1525 		 */
1526 		case CKA_MODULUS:
1527 			isModulus = 1;
1528 			/*
1529 			 * Copyin big integer attribute from template
1530 			 * to a local variable.
1531 			 */
1532 			rv = get_bigint_attr_from_template(&modulus,
1533 			    &template[i]);
1534 			if (rv != CKR_OK)
1535 				goto fail_cleanup;
1536 			break;
1537 
1538 		case CKA_PUBLIC_EXPONENT:
1539 			isPubExpo = 1;
1540 			rv = get_bigint_attr_from_template(&pubexpo,
1541 			    &template[i]);
1542 			if (rv != CKR_OK)
1543 				goto fail_cleanup;
1544 			break;
1545 
1546 		case CKA_PRIVATE_EXPONENT:
1547 			isPriExpo = 1;
1548 			rv = get_bigint_attr_from_template(&priexpo,
1549 			    &template[i]);
1550 			if (rv != CKR_OK)
1551 				goto fail_cleanup;
1552 			break;
1553 
1554 		case CKA_PRIME_1:
1555 			isPrime1 = 1;
1556 			rv = get_bigint_attr_from_template(&prime1,
1557 			    &template[i]);
1558 			if (rv != CKR_OK)
1559 				goto fail_cleanup;
1560 			break;
1561 
1562 		case CKA_PRIME_2:
1563 			isPrime2 = 1;
1564 			rv = get_bigint_attr_from_template(&prime2,
1565 			    &template[i]);
1566 			if (rv != CKR_OK)
1567 				goto fail_cleanup;
1568 			break;
1569 
1570 		case CKA_EXPONENT_1:
1571 			isExpo1 = 1;
1572 			rv = get_bigint_attr_from_template(&expo1,
1573 			    &template[i]);
1574 			if (rv != CKR_OK)
1575 				goto fail_cleanup;
1576 			break;
1577 
1578 		case CKA_EXPONENT_2:
1579 			isExpo2 = 1;
1580 			rv = get_bigint_attr_from_template(&expo2,
1581 			    &template[i]);
1582 			if (rv != CKR_OK)
1583 				goto fail_cleanup;
1584 			break;
1585 
1586 		case CKA_COEFFICIENT:
1587 			isCoef = 1;
1588 			rv = get_bigint_attr_from_template(&coef,
1589 			    &template[i]);
1590 			if (rv != CKR_OK)
1591 				goto fail_cleanup;
1592 			break;
1593 
1594 		case CKA_PRIME:
1595 			isPrime = 1;
1596 			rv = get_bigint_attr_from_template(&prime,
1597 			    &template[i]);
1598 			if (rv != CKR_OK)
1599 				goto fail_cleanup;
1600 			break;
1601 
1602 		case CKA_SUBPRIME:
1603 			isSubprime = 1;
1604 			rv = get_bigint_attr_from_template(&subprime,
1605 			    &template[i]);
1606 			if (rv != CKR_OK)
1607 				goto fail_cleanup;
1608 			break;
1609 
1610 		case CKA_BASE:
1611 			isBase = 1;
1612 			rv = get_bigint_attr_from_template(&base,
1613 			    &template[i]);
1614 			if (rv != CKR_OK)
1615 				goto fail_cleanup;
1616 			break;
1617 
1618 		case CKA_VALUE:
1619 			isValue = 1;
1620 			rv = get_bigint_attr_from_template(&value,
1621 			    &template[i]);
1622 			if (rv != CKR_OK)
1623 				goto fail_cleanup;
1624 			break;
1625 
1626 		case CKA_VALUE_BITS:
1627 			isValueBits = 1;
1628 			get_ulong_attr_from_template(&value_bits,
1629 			    &template[i]);
1630 			break;
1631 
1632 		case CKA_LABEL:
1633 			isLabel = 1;
1634 			rv = get_string_from_template(&string_tmp,
1635 			    &template[i]);
1636 			if (rv != CKR_OK)
1637 				goto fail_cleanup;
1638 			break;
1639 
1640 		case CKA_EC_PARAMS:
1641 			isParams = 1;
1642 			rv = get_string_from_template(&param_tmp,
1643 			    &template[i]);
1644 			if (rv != CKR_OK)
1645 				goto fail_cleanup;
1646 			break;
1647 
1648 		default:
1649 			rv = kernel_parse_common_attrs(&template[i], sp,
1650 			    &attr_mask);
1651 			if (rv != CKR_OK)
1652 				goto fail_cleanup;
1653 			break;
1654 
1655 		}
1656 	} /* For */
1657 
1658 	/* Allocate storage for Private Key Object. */
1659 	pvk = calloc(1, sizeof (private_key_obj_t));
1660 	if (pvk == NULL) {
1661 		rv = CKR_HOST_MEMORY;
1662 		goto fail_cleanup;
1663 	}
1664 
1665 	new_object->object_class_u.private_key = pvk;
1666 	new_object->class = CKO_PRIVATE_KEY;
1667 
1668 	if (keytype == (CK_KEY_TYPE)~0UL) {
1669 		rv = CKR_TEMPLATE_INCOMPLETE;
1670 		goto fail_cleanup;
1671 	}
1672 
1673 	new_object->key_type = keytype;
1674 
1675 	/* Supported key types of the Private Key Object */
1676 	switch (keytype) {
1677 	case CKK_RSA:
1678 		if (isPrime || isSubprime || isBase || isValue ||
1679 		    isValueBits) {
1680 			rv = CKR_TEMPLATE_INCONSISTENT;
1681 			goto fail_cleanup;
1682 		}
1683 
1684 		if (isModulus && isPriExpo) {
1685 			/*
1686 			 * Copy big integer attribute value to the
1687 			 * designated place in the Private Key object.
1688 			 */
1689 			copy_bigint_attr(&modulus, KEY_PRI_RSA_MOD(pvk));
1690 
1691 			copy_bigint_attr(&priexpo, KEY_PRI_RSA_PRIEXPO(pvk));
1692 
1693 		} else {
1694 			rv = CKR_TEMPLATE_INCOMPLETE;
1695 			goto fail_cleanup;
1696 		}
1697 
1698 		/* The following attributes are optional. */
1699 		if (isPubExpo) {
1700 			copy_bigint_attr(&pubexpo, KEY_PRI_RSA_PUBEXPO(pvk));
1701 		}
1702 
1703 		if (isPrime1) {
1704 			copy_bigint_attr(&prime1, KEY_PRI_RSA_PRIME1(pvk));
1705 		}
1706 
1707 		if (isPrime2) {
1708 			copy_bigint_attr(&prime2, KEY_PRI_RSA_PRIME2(pvk));
1709 		}
1710 
1711 		if (isExpo1) {
1712 			copy_bigint_attr(&expo1, KEY_PRI_RSA_EXPO1(pvk));
1713 		}
1714 
1715 		if (isExpo2) {
1716 			copy_bigint_attr(&expo2, KEY_PRI_RSA_EXPO2(pvk));
1717 		}
1718 
1719 		if (isCoef) {
1720 			copy_bigint_attr(&coef, KEY_PRI_RSA_COEF(pvk));
1721 		}
1722 		break;
1723 
1724 	case CKK_DSA:
1725 		if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
1726 		    isPrime2 || isExpo1 || isExpo2 || isCoef ||
1727 		    isValueBits) {
1728 			rv = CKR_TEMPLATE_INCONSISTENT;
1729 			goto fail_cleanup;
1730 		}
1731 
1732 		if (!(isPrime && isSubprime && isBase && isValue)) {
1733 			rv = CKR_TEMPLATE_INCOMPLETE;
1734 			goto fail_cleanup;
1735 		}
1736 
1737 		copy_bigint_attr(&prime, KEY_PRI_DSA_PRIME(pvk));
1738 
1739 		copy_bigint_attr(&subprime, KEY_PRI_DSA_SUBPRIME(pvk));
1740 
1741 		copy_bigint_attr(&base, KEY_PRI_DSA_BASE(pvk));
1742 
1743 		copy_bigint_attr(&value, KEY_PRI_DSA_VALUE(pvk));
1744 
1745 		break;
1746 
1747 	case CKK_DH:
1748 		if (mode == KERNEL_CREATE_OBJ && isValueBits) {
1749 			rv = CKR_TEMPLATE_INCONSISTENT;
1750 			goto fail_cleanup;
1751 		}
1752 		if (!(isPrime && isBase && isValue)) {
1753 			rv = CKR_TEMPLATE_INCOMPLETE;
1754 			goto fail_cleanup;
1755 		}
1756 
1757 		copy_bigint_attr(&prime, KEY_PRI_DH_PRIME(pvk));
1758 
1759 		copy_bigint_attr(&base, KEY_PRI_DH_BASE(pvk));
1760 
1761 		copy_bigint_attr(&value, KEY_PRI_DH_VALUE(pvk));
1762 
1763 		KEY_PRI_DH_VAL_BITS(pvk) = (isValueBits) ? value_bits : 0;
1764 
1765 		break;
1766 
1767 	case CKK_EC:
1768 		if (!isValue || !isParams) {
1769 			rv = CKR_TEMPLATE_INCOMPLETE;
1770 			goto fail_cleanup;
1771 		}
1772 
1773 		copy_bigint_attr(&value, KEY_PRI_EC_VALUE(pvk));
1774 		rv = kernel_add_extra_attr(&param_tmp, new_object);
1775 		if (rv != CKR_OK)
1776 			goto fail_cleanup;
1777 		string_attr_cleanup(&param_tmp);
1778 		break;
1779 	default:
1780 		rv = CKR_TEMPLATE_INCONSISTENT;
1781 		goto fail_cleanup;
1782 	}
1783 
1784 	/* Set up object. */
1785 	new_object->bool_attr_mask = attr_mask;
1786 	if (isLabel) {
1787 		rv = kernel_add_extra_attr(&string_tmp, new_object);
1788 		if (rv != CKR_OK)
1789 			goto fail_cleanup;
1790 		string_attr_cleanup(&string_tmp);
1791 	}
1792 
1793 	return (rv);
1794 
1795 fail_cleanup:
1796 	/*
1797 	 * cleanup the storage allocated to the local variables.
1798 	 */
1799 	bigint_attr_cleanup(&modulus);
1800 	bigint_attr_cleanup(&priexpo);
1801 	bigint_attr_cleanup(&prime);
1802 	bigint_attr_cleanup(&subprime);
1803 	bigint_attr_cleanup(&base);
1804 	bigint_attr_cleanup(&value);
1805 	bigint_attr_cleanup(&pubexpo);
1806 	bigint_attr_cleanup(&prime1);
1807 	bigint_attr_cleanup(&prime2);
1808 	bigint_attr_cleanup(&expo1);
1809 	bigint_attr_cleanup(&expo2);
1810 	bigint_attr_cleanup(&coef);
1811 	string_attr_cleanup(&string_tmp);
1812 	string_attr_cleanup(&param_tmp);
1813 
1814 	/*
1815 	 * cleanup the storage allocated inside the object itself.
1816 	 */
1817 	kernel_cleanup_object(new_object);
1818 
1819 	return (rv);
1820 }
1821 
1822 
1823 /*
1824  * Build a Secret Key Object.
1825  *
1826  * - Parse the object's template, and when an error is detected such as
1827  *   invalid attribute type, invalid attribute value, etc., return
1828  *   with appropriate return value.
1829  * - Set up attribute mask field in the object for the supplied common
1830  *   attributes that have boolean type.
1831  * - Build the attribute_info struct to hold the value of each supplied
1832  *   attribute that has byte array type. Link attribute_info structs
1833  *   together to form the extra attribute list of the object.
1834  * - Allocate storage for the Secret Key object.
1835  * - Build the Secret Key object. Allocate storage to hold the big integer
1836  *   value for the attribute CKA_VALUE that is required for all the key
1837  *   types supported by secret key object.
1838  *
1839  */
1840 CK_RV
1841 kernel_build_secret_key_object(CK_ATTRIBUTE_PTR template,
1842     CK_ULONG ulAttrNum,	kernel_object_t *new_object, kernel_session_t *sp)
1843 {
1844 
1845 	int		i;
1846 	CK_KEY_TYPE	keytype = (CK_KEY_TYPE)~0UL;
1847 	uint64_t	attr_mask = SECRET_KEY_DEFAULT;
1848 	CK_RV 		rv = CKR_OK;
1849 	int		isLabel = 0;
1850 	/* Must set flags */
1851 	int		isValue = 0;
1852 	/* Must not set flags */
1853 	int		isValueLen = 0;
1854 
1855 	CK_ATTRIBUTE	string_tmp;
1856 
1857 	secret_key_obj_t  *sck;
1858 
1859 	string_tmp.pValue = NULL;
1860 
1861 	/* Allocate storage for Secret Key Object. */
1862 	sck = calloc(1, sizeof (secret_key_obj_t));
1863 	if (sck == NULL) {
1864 		rv = CKR_HOST_MEMORY;
1865 		goto fail_cleanup;
1866 	}
1867 
1868 	new_object->object_class_u.secret_key = sck;
1869 	new_object->class = CKO_SECRET_KEY;
1870 
1871 	for (i = 0; i < ulAttrNum; i++) {
1872 
1873 		/* Secret Key Object Attributes */
1874 		switch (template[i].type) {
1875 
1876 		/* common key attributes */
1877 		case CKA_KEY_TYPE:
1878 		keytype = *((CK_KEY_TYPE*)template[i].pValue);
1879 			break;
1880 
1881 		case CKA_ID:
1882 		case CKA_START_DATE:
1883 		case CKA_END_DATE:
1884 			/*
1885 			 * Allocate storage to hold the attribute
1886 			 * value with byte array type, and add it to
1887 			 * the extra attribute list of the object.
1888 			 */
1889 			rv = kernel_add_extra_attr(&template[i],
1890 			    new_object);
1891 			if (rv != CKR_OK) {
1892 				goto fail_cleanup;
1893 			}
1894 			break;
1895 
1896 		/*
1897 		 * The following key related attribute types must
1898 		 * not be specified by C_CreateObject.
1899 		 */
1900 		case CKA_LOCAL:
1901 		case CKA_KEY_GEN_MECHANISM:
1902 		case CKA_ALWAYS_SENSITIVE:
1903 		case CKA_NEVER_EXTRACTABLE:
1904 			rv = CKR_TEMPLATE_INCONSISTENT;
1905 			goto fail_cleanup;
1906 
1907 		/* Key related boolean attributes */
1908 		case CKA_DERIVE:
1909 			if (*(CK_BBOOL *)template[i].pValue)
1910 				attr_mask |= DERIVE_BOOL_ON;
1911 			break;
1912 
1913 		case CKA_SENSITIVE:
1914 			if (*(CK_BBOOL *)template[i].pValue)
1915 				attr_mask |= SENSITIVE_BOOL_ON;
1916 			break;
1917 
1918 		case CKA_ENCRYPT:
1919 			if (*(CK_BBOOL *)template[i].pValue)
1920 				attr_mask |= ENCRYPT_BOOL_ON;
1921 			else
1922 				attr_mask &= ~ENCRYPT_BOOL_ON;
1923 			break;
1924 
1925 		case CKA_DECRYPT:
1926 			if (*(CK_BBOOL *)template[i].pValue)
1927 				attr_mask |= DECRYPT_BOOL_ON;
1928 			else
1929 				attr_mask &= ~DECRYPT_BOOL_ON;
1930 			break;
1931 
1932 		case CKA_SIGN:
1933 			if (*(CK_BBOOL *)template[i].pValue)
1934 				attr_mask |= SIGN_BOOL_ON;
1935 			else
1936 				attr_mask &= ~SIGN_BOOL_ON;
1937 			break;
1938 
1939 		case CKA_VERIFY:
1940 			if (*(CK_BBOOL *)template[i].pValue)
1941 				attr_mask |= VERIFY_BOOL_ON;
1942 			else
1943 				attr_mask &= ~VERIFY_BOOL_ON;
1944 			break;
1945 
1946 		case CKA_WRAP:
1947 			if (*(CK_BBOOL *)template[i].pValue)
1948 				attr_mask |= WRAP_BOOL_ON;
1949 			break;
1950 
1951 		case CKA_UNWRAP:
1952 			if (*(CK_BBOOL *)template[i].pValue)
1953 				attr_mask |= UNWRAP_BOOL_ON;
1954 			break;
1955 
1956 		case CKA_EXTRACTABLE:
1957 			if (*(CK_BBOOL *)template[i].pValue)
1958 				attr_mask |= EXTRACTABLE_BOOL_ON;
1959 			else
1960 				attr_mask &= ~EXTRACTABLE_BOOL_ON;
1961 			break;
1962 
1963 		case CKA_VALUE:
1964 			isValue = 1;
1965 			if ((template[i].ulValueLen == 0) ||
1966 			    (template[i].pValue == NULL)) {
1967 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
1968 				goto fail_cleanup;
1969 			}
1970 
1971 			/*
1972 			 * Copyin attribute from template
1973 			 * to a local variable.
1974 			 */
1975 			sck->sk_value = malloc(template[i].ulValueLen);
1976 			if (sck->sk_value == NULL) {
1977 				rv = CKR_HOST_MEMORY;
1978 				goto fail_cleanup;
1979 			}
1980 			(void) memcpy(sck->sk_value, template[i].pValue,
1981 			    template[i].ulValueLen);
1982 			sck->sk_value_len = template[i].ulValueLen;
1983 			break;
1984 
1985 		case CKA_VALUE_LEN:
1986 			isValueLen = 1;
1987 			break;
1988 
1989 		case CKA_LABEL:
1990 			isLabel = 1;
1991 			rv = get_string_from_template(&string_tmp,
1992 			    &template[i]);
1993 			if (rv != CKR_OK)
1994 				goto fail_cleanup;
1995 			break;
1996 
1997 		default:
1998 			rv = kernel_parse_common_attrs(&template[i], sp,
1999 			    &attr_mask);
2000 			if (rv != CKR_OK)
2001 				goto fail_cleanup;
2002 			break;
2003 
2004 		}
2005 	} /* For */
2006 
2007 	if (keytype == (CK_KEY_TYPE)~0UL) {
2008 		rv = CKR_TEMPLATE_INCOMPLETE;
2009 		goto fail_cleanup;
2010 	}
2011 
2012 	new_object->key_type = keytype;
2013 
2014 	/* Supported key types of the Secret Key Object */
2015 	switch (keytype) {
2016 	case CKK_RC4:
2017 		if (!isValue) {
2018 			rv = CKR_TEMPLATE_INCOMPLETE;
2019 			goto fail_cleanup;
2020 		}
2021 		if ((sck->sk_value_len < ARCFOUR_MIN_KEY_BYTES) ||
2022 		    (sck->sk_value_len > ARCFOUR_MAX_KEY_BYTES)) {
2023 			rv = CKR_ATTRIBUTE_VALUE_INVALID;
2024 			goto fail_cleanup;
2025 		}
2026 		break;
2027 
2028 	case CKK_GENERIC_SECRET:
2029 		if (!isValue) {
2030 			rv = CKR_TEMPLATE_INCOMPLETE;
2031 			goto fail_cleanup;
2032 		}
2033 		break;
2034 
2035 	case CKK_AES:
2036 		if (!isValue) {
2037 			rv = CKR_TEMPLATE_INCOMPLETE;
2038 			goto fail_cleanup;
2039 		}
2040 		if (sck->sk_value_len < AES_MIN_KEY_BYTES) {
2041 			rv = CKR_ATTRIBUTE_VALUE_INVALID;
2042 			goto fail_cleanup;
2043 		}
2044 		break;
2045 
2046 	case CKK_BLOWFISH:
2047 		if (!isValue) {
2048 			rv = CKR_TEMPLATE_INCOMPLETE;
2049 			goto fail_cleanup;
2050 		}
2051 		if (sck->sk_value_len < BLOWFISH_MINBYTES) {
2052 			rv = CKR_ATTRIBUTE_VALUE_INVALID;
2053 			goto fail_cleanup;
2054 		}
2055 		break;
2056 
2057 	case CKK_DES:
2058 		if (!isValue) {
2059 			rv = CKR_TEMPLATE_INCOMPLETE;
2060 			goto fail_cleanup;
2061 		}
2062 		if (sck->sk_value_len != DES_KEYSIZE) {
2063 			rv = CKR_ATTRIBUTE_VALUE_INVALID;
2064 			goto fail_cleanup;
2065 		}
2066 		break;
2067 
2068 	case CKK_DES2:
2069 		if (!isValue) {
2070 			rv = CKR_TEMPLATE_INCOMPLETE;
2071 			goto fail_cleanup;
2072 		}
2073 		if (sck->sk_value_len != DES2_KEYSIZE) {
2074 			rv = CKR_ATTRIBUTE_VALUE_INVALID;
2075 			goto fail_cleanup;
2076 		}
2077 		break;
2078 
2079 	case CKK_DES3:
2080 		if (!isValue) {
2081 			rv = CKR_TEMPLATE_INCOMPLETE;
2082 			goto fail_cleanup;
2083 		}
2084 		if (sck->sk_value_len != DES3_KEYSIZE) {
2085 			rv = CKR_ATTRIBUTE_VALUE_INVALID;
2086 			goto fail_cleanup;
2087 		}
2088 		break;
2089 
2090 	default:
2091 		rv = CKR_TEMPLATE_INCONSISTENT;
2092 		goto fail_cleanup;
2093 	}
2094 
2095 	if (isValueLen) {
2096 		rv = CKR_TEMPLATE_INCONSISTENT;
2097 		goto fail_cleanup;
2098 	}
2099 
2100 	/* Set up object. */
2101 	new_object->bool_attr_mask = attr_mask;
2102 	if (isLabel) {
2103 		rv = kernel_add_extra_attr(&string_tmp, new_object);
2104 		if (rv != CKR_OK)
2105 			goto fail_cleanup;
2106 		string_attr_cleanup(&string_tmp);
2107 	}
2108 
2109 	return (rv);
2110 
2111 fail_cleanup:
2112 	/*
2113 	 * cleanup the storage allocated to the local variables.
2114 	 */
2115 	string_attr_cleanup(&string_tmp);
2116 
2117 	/*
2118 	 * cleanup the storage allocated inside the object itself.
2119 	 */
2120 	kernel_cleanup_object(new_object);
2121 
2122 	return (rv);
2123 }
2124 
2125 
2126 /*
2127  * Validate the attribute types in the object's template. Then,
2128  * call the appropriate build function according to the class of
2129  * the object specified in the template.
2130  *
2131  * Note: The following classes of objects are supported:
2132  * - CKO_SECRET_KEY
2133  * - CKO_PUBLIC_KEY
2134  * - CKO_PRIVATE_KEY
2135  */
2136 CK_RV
2137 kernel_build_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
2138     kernel_object_t *new_object, kernel_session_t *sp, uint_t mode)
2139 {
2140 
2141 	CK_OBJECT_CLASS class = (CK_OBJECT_CLASS)~0UL;
2142 	CK_RV 		rv = CKR_OK;
2143 
2144 	if (template == NULL) {
2145 		return (CKR_ARGUMENTS_BAD);
2146 	}
2147 
2148 	/* Validate the attribute type in the template. */
2149 	rv = kernel_validate_attr(template, ulAttrNum, &class);
2150 	if (rv != CKR_OK)
2151 		return (rv);
2152 
2153 	if (class == (CK_OBJECT_CLASS)~0UL)
2154 		return (CKR_TEMPLATE_INCOMPLETE);
2155 
2156 	/*
2157 	 * Call the appropriate function based on the supported class
2158 	 * of the object.
2159 	 */
2160 	switch (class) {
2161 	case CKO_PUBLIC_KEY:
2162 		rv = kernel_build_public_key_object(template, ulAttrNum,
2163 		    new_object, sp, mode);
2164 		break;
2165 
2166 	case CKO_PRIVATE_KEY:
2167 		rv = kernel_build_private_key_object(template, ulAttrNum,
2168 		    new_object, sp, mode);
2169 		break;
2170 
2171 	case CKO_SECRET_KEY:
2172 		rv = kernel_build_secret_key_object(template, ulAttrNum,
2173 		    new_object, sp);
2174 		break;
2175 
2176 	case CKO_DOMAIN_PARAMETERS:
2177 	case CKO_DATA:
2178 	case CKO_CERTIFICATE:
2179 	case CKO_HW_FEATURE:
2180 	case CKO_VENDOR_DEFINED:
2181 	default:
2182 		return (CKR_ATTRIBUTE_VALUE_INVALID);
2183 	}
2184 
2185 	return (rv);
2186 }
2187 
2188 
2189 /*
2190  * Get the value of a requested attribute that is common to all supported
2191  * classes (i.e. public key, private key, secret key classes).
2192  */
2193 CK_RV
2194 kernel_get_common_attrs(kernel_object_t *object_p, CK_ATTRIBUTE_PTR template)
2195 {
2196 
2197 	CK_RV rv = CKR_OK;
2198 
2199 	switch (template->type) {
2200 
2201 	case CKA_CLASS:
2202 		return (get_ulong_attr_from_object(object_p->class,
2203 		    template));
2204 
2205 	/* default boolean attributes */
2206 	case CKA_TOKEN:
2207 
2208 		template->ulValueLen = sizeof (CK_BBOOL);
2209 		if (template->pValue == NULL) {
2210 			return (CKR_OK);
2211 		}
2212 
2213 		/*
2214 		 * A token object will not be created in the library, so we
2215 		 * return FALSE.
2216 		 */
2217 		*((CK_BBOOL *)template->pValue) = B_FALSE;
2218 		break;
2219 
2220 	case CKA_PRIVATE:
2221 
2222 		template->ulValueLen = sizeof (CK_BBOOL);
2223 		if (template->pValue == NULL) {
2224 			return (CKR_OK);
2225 		}
2226 		if (object_p->bool_attr_mask & PRIVATE_BOOL_ON) {
2227 			*((CK_BBOOL *)template->pValue) = B_TRUE;
2228 		} else {
2229 			*((CK_BBOOL *)template->pValue) = B_FALSE;
2230 		}
2231 		break;
2232 
2233 	case CKA_MODIFIABLE:
2234 		template->ulValueLen = sizeof (CK_BBOOL);
2235 		if (template->pValue == NULL) {
2236 			return (CKR_OK);
2237 		}
2238 		if ((object_p->bool_attr_mask) & MODIFIABLE_BOOL_ON)
2239 			*((CK_BBOOL *)template->pValue) = B_TRUE;
2240 		else
2241 			*((CK_BBOOL *)template->pValue) = B_FALSE;
2242 		break;
2243 
2244 	case CKA_LABEL:
2245 		return (get_extra_attr_from_object(object_p,
2246 		    template));
2247 		break;
2248 
2249 	default:
2250 		/*
2251 		 * The specified attribute for the object is invalid.
2252 		 * (the object does not possess such an attribute.)
2253 		 */
2254 		template->ulValueLen = (CK_ULONG)-1;
2255 		return (CKR_ATTRIBUTE_TYPE_INVALID);
2256 	}
2257 
2258 	return (rv);
2259 }
2260 
2261 /*
2262  * Get the value of a requested attribute that is common to all key objects
2263  * (i.e. public key, private key and secret key).
2264  */
2265 CK_RV
2266 kernel_get_common_key_attrs(kernel_object_t *object_p,
2267     CK_ATTRIBUTE_PTR template)
2268 {
2269 
2270 	switch (template->type) {
2271 
2272 	case CKA_KEY_TYPE:
2273 		return (get_ulong_attr_from_object(object_p->key_type,
2274 		    template));
2275 
2276 	case CKA_ID:
2277 	case CKA_START_DATE:
2278 	case CKA_END_DATE:
2279 		/*
2280 		 * The above extra attributes have byte array type.
2281 		 */
2282 		return (get_extra_attr_from_object(object_p,
2283 		    template));
2284 
2285 	/* Key related boolean attributes */
2286 	case CKA_LOCAL:
2287 		return (get_bool_attr_from_object(object_p,
2288 		    LOCAL_BOOL_ON, template));
2289 
2290 	case CKA_DERIVE:
2291 		return (get_bool_attr_from_object(object_p,
2292 		    DERIVE_BOOL_ON, template));
2293 
2294 	case CKA_KEY_GEN_MECHANISM:
2295 		return (get_ulong_attr_from_object(object_p->mechanism,
2296 		    template));
2297 
2298 	default:
2299 		return (CKR_ATTRIBUTE_TYPE_INVALID);
2300 	}
2301 }
2302 
2303 
2304 /*
2305  * Get the value of a requested attribute of a Public Key Object.
2306  *
2307  * Rule: All the attributes in the public key object can be revealed.
2308  */
2309 CK_RV
2310 kernel_get_public_key_attribute(kernel_object_t *object_p,
2311     CK_ATTRIBUTE_PTR template)
2312 {
2313 
2314 	CK_RV		rv = CKR_OK;
2315 	CK_KEY_TYPE	keytype = object_p->key_type;
2316 
2317 	switch (template->type) {
2318 
2319 	case CKA_SUBJECT:
2320 	case CKA_EC_PARAMS:
2321 		/*
2322 		 * The above extra attributes have byte array type.
2323 		 */
2324 		return (get_extra_attr_from_object(object_p,
2325 		    template));
2326 
2327 	/* Key related boolean attributes */
2328 	case CKA_ENCRYPT:
2329 		return (get_bool_attr_from_object(object_p,
2330 		    ENCRYPT_BOOL_ON, template));
2331 
2332 	case CKA_VERIFY:
2333 		return (get_bool_attr_from_object(object_p,
2334 		    VERIFY_BOOL_ON, template));
2335 
2336 	case CKA_VERIFY_RECOVER:
2337 		return (get_bool_attr_from_object(object_p,
2338 		    VERIFY_RECOVER_BOOL_ON, template));
2339 
2340 	case CKA_WRAP:
2341 		return (get_bool_attr_from_object(object_p,
2342 		    WRAP_BOOL_ON, template));
2343 
2344 	case CKA_TRUSTED:
2345 		return (get_bool_attr_from_object(object_p,
2346 		    TRUSTED_BOOL_ON, template));
2347 
2348 	case CKA_MODULUS:
2349 		/*
2350 		 * This attribute is valid only for RSA public key
2351 		 * object.
2352 		 */
2353 		if (keytype == CKK_RSA) {
2354 			return (get_bigint_attr_from_object(
2355 			    OBJ_PUB_RSA_MOD(object_p), template));
2356 		} else {
2357 			template->ulValueLen = (CK_ULONG)-1;
2358 			return (CKR_ATTRIBUTE_TYPE_INVALID);
2359 		}
2360 
2361 	case CKA_PUBLIC_EXPONENT:
2362 		if (keytype == CKK_RSA) {
2363 			return (get_bigint_attr_from_object(
2364 			    OBJ_PUB_RSA_PUBEXPO(object_p), template));
2365 		} else {
2366 			template->ulValueLen = (CK_ULONG)-1;
2367 			return (CKR_ATTRIBUTE_TYPE_INVALID);
2368 		}
2369 
2370 	case CKA_MODULUS_BITS:
2371 		if (keytype == CKK_RSA) {
2372 			return (get_ulong_attr_from_object(
2373 			    OBJ_PUB_RSA_MOD_BITS(object_p), template));
2374 		} else {
2375 			template->ulValueLen = (CK_ULONG)-1;
2376 			return (CKR_ATTRIBUTE_TYPE_INVALID);
2377 		}
2378 
2379 	case CKA_PRIME:
2380 		switch (keytype) {
2381 		case CKK_DSA:
2382 			return (get_bigint_attr_from_object(
2383 			    OBJ_PUB_DSA_PRIME(object_p), template));
2384 		case CKK_DH:
2385 			return (get_bigint_attr_from_object(
2386 			    OBJ_PUB_DH_PRIME(object_p), template));
2387 		default:
2388 			template->ulValueLen = (CK_ULONG)-1;
2389 			return (CKR_ATTRIBUTE_TYPE_INVALID);
2390 		}
2391 
2392 	case CKA_SUBPRIME:
2393 		switch (keytype) {
2394 		case CKK_DSA:
2395 			return (get_bigint_attr_from_object(
2396 			    OBJ_PUB_DSA_SUBPRIME(object_p), template));
2397 		default:
2398 			template->ulValueLen = (CK_ULONG)-1;
2399 			return (CKR_ATTRIBUTE_TYPE_INVALID);
2400 		}
2401 
2402 	case CKA_BASE:
2403 		switch (keytype) {
2404 		case CKK_DSA:
2405 			return (get_bigint_attr_from_object(
2406 			    OBJ_PUB_DSA_BASE(object_p), template));
2407 		case CKK_DH:
2408 			return (get_bigint_attr_from_object(
2409 			    OBJ_PUB_DH_BASE(object_p), template));
2410 		default:
2411 			template->ulValueLen = (CK_ULONG)-1;
2412 			return (CKR_ATTRIBUTE_TYPE_INVALID);
2413 		}
2414 
2415 	case CKA_VALUE:
2416 		switch (keytype) {
2417 		case CKK_DSA:
2418 			return (get_bigint_attr_from_object(
2419 			    OBJ_PUB_DSA_VALUE(object_p), template));
2420 		case CKK_DH:
2421 			return (get_bigint_attr_from_object(
2422 			    OBJ_PUB_DH_VALUE(object_p), template));
2423 		default:
2424 			template->ulValueLen = (CK_ULONG)-1;
2425 			return (CKR_ATTRIBUTE_TYPE_INVALID);
2426 		}
2427 
2428 	case CKA_EC_POINT:
2429 		switch (keytype) {
2430 		case CKK_EC:
2431 			return (get_bigint_attr_from_object(
2432 			    OBJ_PUB_EC_POINT(object_p), template));
2433 		default:
2434 			template->ulValueLen = (CK_ULONG)-1;
2435 			return (CKR_ATTRIBUTE_TYPE_INVALID);
2436 		}
2437 	default:
2438 		/*
2439 		 * First, get the value of the request attribute defined
2440 		 * in the list of common key attributes. If the request
2441 		 * attribute is not found in that list, then get the
2442 		 * attribute from the list of common attributes.
2443 		 */
2444 		rv = kernel_get_common_key_attrs(object_p, template);
2445 		if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
2446 			rv = kernel_get_common_attrs(object_p, template);
2447 		}
2448 		break;
2449 	}
2450 
2451 	return (rv);
2452 }
2453 
2454 
2455 /*
2456  * Get the value of a requested attribute of a Private Key Object.
2457  *
2458  * Rule: All the attributes in the private key object can be revealed
2459  *       except those marked with footnote number "7" when the object
2460  *       has its CKA_SENSITIVE attribute set to TRUE or its
2461  *       CKA_EXTRACTABLE attribute set to FALSE (p.88 in PKCS11 spec.).
2462  */
2463 CK_RV
2464 kernel_get_private_key_attribute(kernel_object_t *object_p,
2465     CK_ATTRIBUTE_PTR template)
2466 {
2467 
2468 	CK_RV		rv = CKR_OK;
2469 	CK_KEY_TYPE	keytype = object_p->key_type;
2470 
2471 
2472 	/*
2473 	 * If the following specified attributes for the private key
2474 	 * object cannot be revealed because the object is sensitive
2475 	 * or unextractable, then the ulValueLen is set to -1.
2476 	 */
2477 	if ((object_p->bool_attr_mask & SENSITIVE_BOOL_ON) ||
2478 	    !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
2479 
2480 		switch (template->type) {
2481 		case CKA_PRIVATE_EXPONENT:
2482 		case CKA_PRIME_1:
2483 		case CKA_PRIME_2:
2484 		case CKA_EXPONENT_1:
2485 		case CKA_EXPONENT_2:
2486 		case CKA_COEFFICIENT:
2487 		case CKA_VALUE:
2488 			template->ulValueLen = (CK_ULONG)-1;
2489 			return (CKR_ATTRIBUTE_SENSITIVE);
2490 		}
2491 	}
2492 
2493 	switch (template->type) {
2494 
2495 	case CKA_SUBJECT:
2496 	case CKA_EC_PARAMS:
2497 		/*
2498 		 * The above extra attributes have byte array type.
2499 		 */
2500 		return (get_extra_attr_from_object(object_p,
2501 		    template));
2502 
2503 	/* Key related boolean attributes */
2504 	case CKA_SENSITIVE:
2505 		return (get_bool_attr_from_object(object_p,
2506 		    SENSITIVE_BOOL_ON, template));
2507 
2508 	case CKA_SECONDARY_AUTH:
2509 		return (get_bool_attr_from_object(object_p,
2510 		    SECONDARY_AUTH_BOOL_ON, template));
2511 
2512 	case CKA_DECRYPT:
2513 		return (get_bool_attr_from_object(object_p,
2514 		    DECRYPT_BOOL_ON, template));
2515 
2516 	case CKA_SIGN:
2517 		return (get_bool_attr_from_object(object_p,
2518 		    SIGN_BOOL_ON, template));
2519 
2520 	case CKA_SIGN_RECOVER:
2521 		return (get_bool_attr_from_object(object_p,
2522 		    SIGN_RECOVER_BOOL_ON, template));
2523 
2524 	case CKA_UNWRAP:
2525 		return (get_bool_attr_from_object(object_p,
2526 		    UNWRAP_BOOL_ON, template));
2527 
2528 	case CKA_EXTRACTABLE:
2529 		return (get_bool_attr_from_object(object_p,
2530 		    EXTRACTABLE_BOOL_ON, template));
2531 
2532 	case CKA_ALWAYS_SENSITIVE:
2533 		return (get_bool_attr_from_object(object_p,
2534 		    ALWAYS_SENSITIVE_BOOL_ON, template));
2535 
2536 	case CKA_NEVER_EXTRACTABLE:
2537 		return (get_bool_attr_from_object(object_p,
2538 		    NEVER_EXTRACTABLE_BOOL_ON, template));
2539 
2540 	case CKA_MODULUS:
2541 		if (keytype == CKK_RSA) {
2542 			return (get_bigint_attr_from_object(
2543 			    OBJ_PRI_RSA_MOD(object_p), template));
2544 		} else {
2545 			template->ulValueLen = (CK_ULONG)-1;
2546 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
2547 			break;
2548 		}
2549 
2550 	case CKA_PUBLIC_EXPONENT:
2551 		if (keytype == CKK_RSA) {
2552 			return (get_bigint_attr_from_object(
2553 			    OBJ_PRI_RSA_PUBEXPO(object_p), template));
2554 		} else {
2555 			template->ulValueLen = (CK_ULONG)-1;
2556 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
2557 			break;
2558 		}
2559 
2560 	case CKA_PRIVATE_EXPONENT:
2561 		if (keytype == CKK_RSA) {
2562 			return (get_bigint_attr_from_object(
2563 			    OBJ_PRI_RSA_PRIEXPO(object_p), template));
2564 		} else {
2565 			template->ulValueLen = (CK_ULONG)-1;
2566 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
2567 			break;
2568 		}
2569 
2570 	case CKA_PRIME_1:
2571 		if (keytype == CKK_RSA) {
2572 			return (get_bigint_attr_from_object(
2573 			    OBJ_PRI_RSA_PRIME1(object_p), template));
2574 		} else {
2575 			template->ulValueLen = (CK_ULONG)-1;
2576 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
2577 			break;
2578 		}
2579 
2580 	case CKA_PRIME_2:
2581 		if (keytype == CKK_RSA) {
2582 			return (get_bigint_attr_from_object(
2583 			    OBJ_PRI_RSA_PRIME2(object_p), template));
2584 		} else {
2585 			template->ulValueLen = (CK_ULONG)-1;
2586 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
2587 			break;
2588 		}
2589 
2590 	case CKA_EXPONENT_1:
2591 		if (keytype == CKK_RSA) {
2592 			return (get_bigint_attr_from_object(
2593 			    OBJ_PRI_RSA_EXPO1(object_p), template));
2594 		} else {
2595 			template->ulValueLen = (CK_ULONG)-1;
2596 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
2597 			break;
2598 		}
2599 
2600 	case CKA_EXPONENT_2:
2601 		if (keytype == CKK_RSA) {
2602 			return (get_bigint_attr_from_object(
2603 			    OBJ_PRI_RSA_EXPO2(object_p), template));
2604 		} else {
2605 			template->ulValueLen = (CK_ULONG)-1;
2606 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
2607 			break;
2608 		}
2609 
2610 	case CKA_COEFFICIENT:
2611 		if (keytype == CKK_RSA) {
2612 			return (get_bigint_attr_from_object(
2613 			    OBJ_PRI_RSA_COEF(object_p), template));
2614 		} else {
2615 			template->ulValueLen = (CK_ULONG)-1;
2616 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
2617 			break;
2618 		}
2619 
2620 	case CKA_VALUE_BITS:
2621 		if (keytype == CKK_DH) {
2622 			return (get_ulong_attr_from_object(
2623 			    OBJ_PRI_DH_VAL_BITS(object_p), template));
2624 		} else {
2625 			template->ulValueLen = (CK_ULONG)-1;
2626 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
2627 			break;
2628 		}
2629 
2630 	case CKA_PRIME:
2631 		switch (keytype) {
2632 		case CKK_DSA:
2633 			return (get_bigint_attr_from_object(
2634 			    OBJ_PRI_DSA_PRIME(object_p), template));
2635 		case CKK_DH:
2636 			return (get_bigint_attr_from_object(
2637 			    OBJ_PRI_DH_PRIME(object_p), template));
2638 		default:
2639 			template->ulValueLen = (CK_ULONG)-1;
2640 			return (CKR_ATTRIBUTE_TYPE_INVALID);
2641 		}
2642 
2643 	case CKA_SUBPRIME:
2644 		switch (keytype) {
2645 		case CKK_DSA:
2646 			return (get_bigint_attr_from_object(
2647 			    OBJ_PRI_DSA_SUBPRIME(object_p), template));
2648 		default:
2649 			template->ulValueLen = (CK_ULONG)-1;
2650 			return (CKR_ATTRIBUTE_TYPE_INVALID);
2651 		}
2652 
2653 	case CKA_BASE:
2654 		switch (keytype) {
2655 		case CKK_DSA:
2656 			return (get_bigint_attr_from_object(
2657 			    OBJ_PRI_DSA_BASE(object_p), template));
2658 		case CKK_DH:
2659 			return (get_bigint_attr_from_object(
2660 			    OBJ_PRI_DH_BASE(object_p), template));
2661 		default:
2662 			template->ulValueLen = (CK_ULONG)-1;
2663 			return (CKR_ATTRIBUTE_TYPE_INVALID);
2664 		}
2665 
2666 	case CKA_VALUE:
2667 		switch (keytype) {
2668 		case CKK_DSA:
2669 			return (get_bigint_attr_from_object(
2670 			    OBJ_PRI_DSA_VALUE(object_p), template));
2671 		case CKK_DH:
2672 			return (get_bigint_attr_from_object(
2673 			    OBJ_PRI_DH_VALUE(object_p), template));
2674 		case CKK_EC:
2675 			return (get_bigint_attr_from_object(
2676 			    OBJ_PRI_EC_VALUE(object_p), template));
2677 		default:
2678 			template->ulValueLen = (CK_ULONG)-1;
2679 			return (CKR_ATTRIBUTE_TYPE_INVALID);
2680 		}
2681 
2682 	default:
2683 		/*
2684 		 * First, get the value of the request attribute defined
2685 		 * in the list of common key attributes. If the request
2686 		 * attribute is not found in that list, then get the
2687 		 * attribute from the list of common attributes.
2688 		 */
2689 		rv = kernel_get_common_key_attrs(object_p, template);
2690 		if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
2691 			rv = kernel_get_common_attrs(object_p, template);
2692 		}
2693 		break;
2694 	}
2695 
2696 	return (rv);
2697 }
2698 
2699 
2700 /*
2701  * Get the value of a requested attribute of a Secret Key Object.
2702  *
2703  * Rule: All the attributes in the secret key object can be revealed
2704  *       except those marked with footnote number "7" when the object
2705  *       has its CKA_SENSITIVE attribute set to TRUE or its
2706  *       CKA_EXTRACTABLE attribute set to FALSE (p.88 in PKCS11 spec.).
2707  */
2708 CK_RV
2709 kernel_get_secret_key_attribute(kernel_object_t *object_p,
2710     CK_ATTRIBUTE_PTR template)
2711 {
2712 
2713 	CK_RV		rv = CKR_OK;
2714 	CK_KEY_TYPE	keytype = object_p->key_type;
2715 
2716 	switch (template->type) {
2717 
2718 	/* Key related boolean attributes */
2719 	case CKA_SENSITIVE:
2720 		return (get_bool_attr_from_object(object_p,
2721 		    SENSITIVE_BOOL_ON, template));
2722 
2723 	case CKA_ENCRYPT:
2724 		return (get_bool_attr_from_object(object_p,
2725 		    ENCRYPT_BOOL_ON, template));
2726 
2727 	case CKA_DECRYPT:
2728 		return (get_bool_attr_from_object(object_p,
2729 		    DECRYPT_BOOL_ON, template));
2730 
2731 	case CKA_SIGN:
2732 		return (get_bool_attr_from_object(object_p,
2733 		    SIGN_BOOL_ON, template));
2734 
2735 	case CKA_VERIFY:
2736 		return (get_bool_attr_from_object(object_p,
2737 		    VERIFY_BOOL_ON, template));
2738 
2739 	case CKA_WRAP:
2740 		return (get_bool_attr_from_object(object_p,
2741 		    WRAP_BOOL_ON, template));
2742 
2743 	case CKA_UNWRAP:
2744 		return (get_bool_attr_from_object(object_p,
2745 		    UNWRAP_BOOL_ON, template));
2746 
2747 	case CKA_EXTRACTABLE:
2748 		return (get_bool_attr_from_object(object_p,
2749 		    EXTRACTABLE_BOOL_ON, template));
2750 
2751 	case CKA_ALWAYS_SENSITIVE:
2752 		return (get_bool_attr_from_object(object_p,
2753 		    ALWAYS_SENSITIVE_BOOL_ON, template));
2754 
2755 	case CKA_NEVER_EXTRACTABLE:
2756 		return (get_bool_attr_from_object(object_p,
2757 		    NEVER_EXTRACTABLE_BOOL_ON, template));
2758 
2759 	case CKA_VALUE:
2760 		/*
2761 		 * If the specified attribute for the secret key object
2762 		 * cannot be revealed because the object is sensitive
2763 		 * or unextractable, then the ulValueLen is set to -1.
2764 		 */
2765 		if ((object_p->bool_attr_mask & SENSITIVE_BOOL_ON) ||
2766 		    !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
2767 			template->ulValueLen = (CK_ULONG)-1;
2768 			return (CKR_ATTRIBUTE_SENSITIVE);
2769 		}
2770 
2771 		switch (keytype) {
2772 		case CKK_RC4:
2773 		case CKK_GENERIC_SECRET:
2774 		case CKK_RC5:
2775 		case CKK_DES:
2776 		case CKK_DES2:
2777 		case CKK_DES3:
2778 		case CKK_CDMF:
2779 		case CKK_AES:
2780 		case CKK_BLOWFISH:
2781 			/*
2782 			 * Copy secret key object attributes to template.
2783 			 */
2784 			if (template->pValue == NULL) {
2785 				template->ulValueLen =
2786 				    OBJ_SEC_VALUE_LEN(object_p);
2787 				return (CKR_OK);
2788 			}
2789 
2790 			if (OBJ_SEC_VALUE(object_p) == NULL) {
2791 				template->ulValueLen = 0;
2792 				return (CKR_OK);
2793 			}
2794 
2795 			if (template->ulValueLen >=
2796 			    OBJ_SEC_VALUE_LEN(object_p)) {
2797 				(void) memcpy(template->pValue,
2798 				    OBJ_SEC_VALUE(object_p),
2799 				    OBJ_SEC_VALUE_LEN(object_p));
2800 				template->ulValueLen =
2801 				    OBJ_SEC_VALUE_LEN(object_p);
2802 				return (CKR_OK);
2803 			} else {
2804 				template->ulValueLen = (CK_ULONG)-1;
2805 				return (CKR_BUFFER_TOO_SMALL);
2806 			}
2807 
2808 		default:
2809 			template->ulValueLen = (CK_ULONG)-1;
2810 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
2811 			break;
2812 		}
2813 		break;
2814 
2815 	case CKA_VALUE_LEN:
2816 		return (get_ulong_attr_from_object(OBJ_SEC_VALUE_LEN(object_p),
2817 		    template));
2818 
2819 	default:
2820 		/*
2821 		 * First, get the value of the request attribute defined
2822 		 * in the list of common key attributes. If the request
2823 		 * attribute is not found in that list, then get the
2824 		 * attribute from the list of common attributes.
2825 		 */
2826 		rv = kernel_get_common_key_attrs(object_p, template);
2827 		if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
2828 			rv = kernel_get_common_attrs(object_p, template);
2829 		}
2830 		break;
2831 	}
2832 
2833 	return (rv);
2834 
2835 }
2836 
2837 
2838 
2839 
2840 /*
2841  * Call the appropriate get attribute function according to the class
2842  * of object.
2843  *
2844  * The caller of this function holds the lock on the object.
2845  */
2846 CK_RV
2847 kernel_get_attribute(kernel_object_t *object_p, CK_ATTRIBUTE_PTR template)
2848 {
2849 
2850 	CK_RV		rv = CKR_OK;
2851 	CK_OBJECT_CLASS class = object_p->class;
2852 
2853 	switch (class) {
2854 
2855 	case CKO_PUBLIC_KEY:
2856 		rv =  kernel_get_public_key_attribute(object_p, template);
2857 		break;
2858 
2859 	case CKO_PRIVATE_KEY:
2860 		rv = kernel_get_private_key_attribute(object_p, template);
2861 		break;
2862 
2863 	case CKO_SECRET_KEY:
2864 		rv = kernel_get_secret_key_attribute(object_p, template);
2865 		break;
2866 
2867 	default:
2868 		/*
2869 		 * If the specified attribute for the object is invalid
2870 		 * (the object does not possess such as attribute), then
2871 		 * the ulValueLen is modified to hold the value -1.
2872 		 */
2873 		template->ulValueLen = (CK_ULONG)-1;
2874 		return (CKR_ATTRIBUTE_TYPE_INVALID);
2875 	}
2876 
2877 	return (rv);
2878 
2879 }
2880 
2881 /*
2882  * Set the value of an attribute that is common to all key objects
2883  * (i.e. public key, private key and secret key).
2884  */
2885 CK_RV
2886 kernel_set_common_key_attribute(kernel_object_t *object_p,
2887     CK_ATTRIBUTE_PTR template, boolean_t copy, kernel_session_t *sp)
2888 {
2889 
2890 	kernel_slot_t *pslot = slot_table[sp->ses_slotid];
2891 	CK_RV rv = CKR_OK;
2892 
2893 	switch (template->type) {
2894 
2895 	case CKA_LABEL:
2896 		/*
2897 		 * Only the LABEL can be modified in the common storage
2898 		 * object attributes after the object is created.
2899 		 */
2900 		return (set_extra_attr_to_object(object_p,
2901 		    CKA_LABEL, template));
2902 
2903 	case CKA_ID:
2904 		return (set_extra_attr_to_object(object_p,
2905 		    CKA_ID, template));
2906 
2907 	case CKA_START_DATE:
2908 		return (set_extra_attr_to_object(object_p,
2909 		    CKA_START_DATE, template));
2910 
2911 	case CKA_END_DATE:
2912 		return (set_extra_attr_to_object(object_p,
2913 		    CKA_END_DATE, template));
2914 
2915 	case CKA_DERIVE:
2916 		return (set_bool_attr_to_object(object_p,
2917 		    DERIVE_BOOL_ON, template));
2918 
2919 	case CKA_CLASS:
2920 	case CKA_KEY_TYPE:
2921 	case CKA_LOCAL:
2922 		return (CKR_ATTRIBUTE_READ_ONLY);
2923 
2924 	case CKA_PRIVATE:
2925 		if (!copy) {
2926 			/* called from C_SetAttributeValue() */
2927 			return (CKR_ATTRIBUTE_READ_ONLY);
2928 		}
2929 
2930 		/* called from C_CopyObject() */
2931 		if ((*(CK_BBOOL *)template->pValue) != B_TRUE) {
2932 			return (CKR_OK);
2933 		}
2934 
2935 		(void) pthread_mutex_lock(&pslot->sl_mutex);
2936 		/*
2937 		 * Cannot create a private object if the token
2938 		 * has a keystore and the user isn't logged in.
2939 		 */
2940 		if (pslot->sl_func_list.fl_object_create &&
2941 		    pslot->sl_state != CKU_USER) {
2942 			rv = CKR_USER_NOT_LOGGED_IN;
2943 		} else {
2944 			rv = set_bool_attr_to_object(object_p,
2945 			    PRIVATE_BOOL_ON, template);
2946 		}
2947 		(void) pthread_mutex_unlock(&pslot->sl_mutex);
2948 		return (rv);
2949 
2950 	case CKA_MODIFIABLE:
2951 		if (copy) {
2952 			rv = set_bool_attr_to_object(object_p,
2953 			    MODIFIABLE_BOOL_ON, template);
2954 		} else {
2955 			rv = CKR_ATTRIBUTE_READ_ONLY;
2956 		}
2957 		return (rv);
2958 
2959 	default:
2960 		return (CKR_TEMPLATE_INCONSISTENT);
2961 	}
2962 
2963 }
2964 
2965 
2966 /*
2967  * Set the value of an attribute of a Public Key Object.
2968  *
2969  * Rule: The attributes marked with footnote number "8" in the PKCS11
2970  *       spec may be modified (p.88 in PKCS11 spec.).
2971  */
2972 CK_RV
2973 kernel_set_public_key_attribute(kernel_object_t *object_p,
2974     CK_ATTRIBUTE_PTR template, boolean_t copy, kernel_session_t *sp)
2975 {
2976 	CK_KEY_TYPE	keytype = object_p->key_type;
2977 
2978 	switch (template->type) {
2979 
2980 	case CKA_SUBJECT:
2981 		return (set_extra_attr_to_object(object_p,
2982 		    CKA_SUBJECT, template));
2983 
2984 	case CKA_ENCRYPT:
2985 		return (set_bool_attr_to_object(object_p,
2986 		    ENCRYPT_BOOL_ON, template));
2987 
2988 	case CKA_VERIFY:
2989 		return (set_bool_attr_to_object(object_p,
2990 		    VERIFY_BOOL_ON, template));
2991 
2992 	case CKA_VERIFY_RECOVER:
2993 		return (set_bool_attr_to_object(object_p,
2994 		    VERIFY_RECOVER_BOOL_ON, template));
2995 
2996 	case CKA_WRAP:
2997 		return (set_bool_attr_to_object(object_p,
2998 		    WRAP_BOOL_ON, template));
2999 
3000 	case CKA_MODULUS:
3001 	case CKA_MODULUS_BITS:
3002 	case CKA_PUBLIC_EXPONENT:
3003 		if (keytype == CKK_RSA)
3004 			return (CKR_ATTRIBUTE_READ_ONLY);
3005 		break;
3006 
3007 	case CKA_SUBPRIME:
3008 	case CKA_PRIME:
3009 	case CKA_BASE:
3010 	case CKA_VALUE:
3011 		if (keytype == CKK_DSA)
3012 			return (CKR_ATTRIBUTE_READ_ONLY);
3013 		break;
3014 
3015 	default:
3016 		/*
3017 		 * Set the value of a common key attribute.
3018 		 */
3019 		return (kernel_set_common_key_attribute(object_p,
3020 		    template, copy, sp));
3021 
3022 	}
3023 
3024 	/*
3025 	 * If we got this far, then the combination of key type
3026 	 * and requested attribute is invalid.
3027 	 */
3028 	return (CKR_ATTRIBUTE_TYPE_INVALID);
3029 }
3030 
3031 
3032 /*
3033  * Set the value of an attribute of a Private Key Object.
3034  *
3035  * Rule: The attributes marked with footnote number "8" in the PKCS11
3036  *       spec may be modified (p.88 in PKCS11 spec.).
3037  */
3038 CK_RV
3039 kernel_set_private_key_attribute(kernel_object_t *object_p,
3040     CK_ATTRIBUTE_PTR template, boolean_t copy, kernel_session_t *sp)
3041 {
3042 	CK_KEY_TYPE	keytype = object_p->key_type;
3043 
3044 	switch (template->type) {
3045 
3046 	case CKA_SUBJECT:
3047 		return (set_extra_attr_to_object(object_p,
3048 		    CKA_SUBJECT, template));
3049 
3050 	case CKA_SENSITIVE:
3051 		/*
3052 		 * Cannot set SENSITIVE to FALSE if it is already ON.
3053 		 */
3054 		if (((*(CK_BBOOL *)template->pValue) == B_FALSE) &&
3055 		    (object_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
3056 			return (CKR_ATTRIBUTE_READ_ONLY);
3057 		}
3058 
3059 		if (*(CK_BBOOL *)template->pValue)
3060 			object_p->bool_attr_mask |= SENSITIVE_BOOL_ON;
3061 		return (CKR_OK);
3062 
3063 	case CKA_DECRYPT:
3064 		return (set_bool_attr_to_object(object_p,
3065 		    DECRYPT_BOOL_ON, template));
3066 
3067 	case CKA_SIGN:
3068 		return (set_bool_attr_to_object(object_p,
3069 		    SIGN_BOOL_ON, template));
3070 
3071 	case CKA_SIGN_RECOVER:
3072 		return (set_bool_attr_to_object(object_p,
3073 		    SIGN_RECOVER_BOOL_ON, template));
3074 
3075 	case CKA_UNWRAP:
3076 		return (set_bool_attr_to_object(object_p,
3077 		    UNWRAP_BOOL_ON, template));
3078 
3079 	case CKA_EXTRACTABLE:
3080 		/*
3081 		 * Cannot set EXTRACTABLE to TRUE if it is already OFF.
3082 		 */
3083 		if ((*(CK_BBOOL *)template->pValue) &&
3084 		    !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
3085 			return (CKR_ATTRIBUTE_READ_ONLY);
3086 		}
3087 
3088 		if ((*(CK_BBOOL *)template->pValue) == B_FALSE)
3089 			object_p->bool_attr_mask &= ~EXTRACTABLE_BOOL_ON;
3090 		return (CKR_OK);
3091 
3092 	case CKA_MODULUS:
3093 	case CKA_PUBLIC_EXPONENT:
3094 	case CKA_PRIVATE_EXPONENT:
3095 	case CKA_PRIME_1:
3096 	case CKA_PRIME_2:
3097 	case CKA_EXPONENT_1:
3098 	case CKA_EXPONENT_2:
3099 	case CKA_COEFFICIENT:
3100 		if (keytype == CKK_RSA) {
3101 			return (CKR_ATTRIBUTE_READ_ONLY);
3102 		}
3103 		break;
3104 
3105 	case CKA_SUBPRIME:
3106 	case CKA_PRIME:
3107 	case CKA_BASE:
3108 	case CKA_VALUE:
3109 		if (keytype == CKK_DSA)
3110 			return (CKR_ATTRIBUTE_READ_ONLY);
3111 		break;
3112 
3113 	default:
3114 		/*
3115 		 * Set the value of a common key attribute.
3116 		 */
3117 		return (kernel_set_common_key_attribute(object_p,
3118 		    template, copy, sp));
3119 	}
3120 
3121 	/*
3122 	 * If we got this far, then the combination of key type
3123 	 * and requested attribute is invalid.
3124 	 */
3125 	return (CKR_ATTRIBUTE_TYPE_INVALID);
3126 }
3127 
3128 
3129 
3130 /*
3131  * Set the value of an attribute of a Secret Key Object.
3132  *
3133  * Rule: The attributes marked with footnote number "8" in the PKCS11
3134  *       spec may be modified (p.88 in PKCS11 spec.).
3135  */
3136 CK_RV
3137 kernel_set_secret_key_attribute(kernel_object_t *object_p,
3138     CK_ATTRIBUTE_PTR template, boolean_t copy, kernel_session_t *sp)
3139 {
3140 	CK_KEY_TYPE	keytype = object_p->key_type;
3141 
3142 	switch (template->type) {
3143 
3144 	case CKA_SENSITIVE:
3145 		/*
3146 		 * Cannot set SENSITIVE to FALSE if it is already ON.
3147 		 */
3148 		if (((*(CK_BBOOL *)template->pValue) == B_FALSE) &&
3149 		    (object_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
3150 			return (CKR_ATTRIBUTE_READ_ONLY);
3151 		}
3152 
3153 		if (*(CK_BBOOL *)template->pValue)
3154 			object_p->bool_attr_mask |= SENSITIVE_BOOL_ON;
3155 		return (CKR_OK);
3156 
3157 	case CKA_ENCRYPT:
3158 		return (set_bool_attr_to_object(object_p,
3159 		    ENCRYPT_BOOL_ON, template));
3160 
3161 	case CKA_DECRYPT:
3162 		return (set_bool_attr_to_object(object_p,
3163 		    DECRYPT_BOOL_ON, template));
3164 
3165 	case CKA_SIGN:
3166 		return (set_bool_attr_to_object(object_p,
3167 		    SIGN_BOOL_ON, template));
3168 
3169 	case CKA_VERIFY:
3170 		return (set_bool_attr_to_object(object_p,
3171 		    VERIFY_BOOL_ON, template));
3172 
3173 	case CKA_WRAP:
3174 		return (set_bool_attr_to_object(object_p,
3175 		    WRAP_BOOL_ON, template));
3176 
3177 	case CKA_UNWRAP:
3178 		return (set_bool_attr_to_object(object_p,
3179 		    UNWRAP_BOOL_ON, template));
3180 
3181 	case CKA_EXTRACTABLE:
3182 		/*
3183 		 * Cannot set EXTRACTABLE to TRUE if it is already OFF.
3184 		 */
3185 		if ((*(CK_BBOOL *)template->pValue) &&
3186 		    !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
3187 			return (CKR_ATTRIBUTE_READ_ONLY);
3188 		}
3189 
3190 		if ((*(CK_BBOOL *)template->pValue) == B_FALSE)
3191 			object_p->bool_attr_mask &= ~EXTRACTABLE_BOOL_ON;
3192 		return (CKR_OK);
3193 
3194 	case CKA_VALUE:
3195 		return (CKR_ATTRIBUTE_READ_ONLY);
3196 
3197 	case CKA_VALUE_LEN:
3198 		if ((keytype == CKK_RC4) ||
3199 		    (keytype == CKK_GENERIC_SECRET) ||
3200 		    (keytype == CKK_AES) ||
3201 		    (keytype == CKK_BLOWFISH))
3202 			return (CKR_ATTRIBUTE_READ_ONLY);
3203 		break;
3204 
3205 	default:
3206 		/*
3207 		 * Set the value of a common key attribute.
3208 		 */
3209 		return (kernel_set_common_key_attribute(object_p,
3210 		    template, copy, sp));
3211 	}
3212 
3213 	/*
3214 	 * If we got this far, then the combination of key type
3215 	 * and requested attribute is invalid.
3216 	 */
3217 	return (CKR_ATTRIBUTE_TYPE_INVALID);
3218 }
3219 
3220 
3221 /*
3222  * Call the appropriate set attribute function according to the class
3223  * of object.
3224  *
3225  * The caller of this function does not hold the lock on the original
3226  * object, since this function is setting the attribute on the new object
3227  * that is being modified.
3228  *
3229  */
3230 CK_RV
3231 kernel_set_attribute(kernel_object_t *object_p, CK_ATTRIBUTE_PTR template,
3232     boolean_t copy, kernel_session_t *sp)
3233 {
3234 
3235 	CK_RV		rv = CKR_OK;
3236 	CK_OBJECT_CLASS	class = object_p->class;
3237 
3238 	switch (class) {
3239 
3240 	case CKO_PUBLIC_KEY:
3241 		rv = kernel_set_public_key_attribute(object_p, template,
3242 		    copy, sp);
3243 		break;
3244 
3245 	case CKO_PRIVATE_KEY:
3246 		rv = kernel_set_private_key_attribute(object_p, template,
3247 		    copy, sp);
3248 		break;
3249 
3250 	case CKO_SECRET_KEY:
3251 		rv = kernel_set_secret_key_attribute(object_p, template,
3252 		    copy, sp);
3253 		break;
3254 
3255 	default:
3256 		/*
3257 		 * If the template specifies a value of an attribute
3258 		 * which is incompatible with other existing attributes
3259 		 * of the object, then fails with return code
3260 		 * CKR_TEMPLATE_INCONSISTENT.
3261 		 */
3262 		rv = CKR_TEMPLATE_INCONSISTENT;
3263 		break;
3264 	}
3265 
3266 	return (rv);
3267 }
3268 
3269 
3270 static CK_RV
3271 copy_bigint(biginteger_t *new_bigint, biginteger_t *old_bigint)
3272 {
3273 	new_bigint->big_value =
3274 	    malloc((sizeof (CK_BYTE) * new_bigint->big_value_len));
3275 
3276 	if (new_bigint->big_value == NULL) {
3277 		return (CKR_HOST_MEMORY);
3278 	}
3279 
3280 	(void) memcpy(new_bigint->big_value, old_bigint->big_value,
3281 	    (sizeof (CK_BYTE) * new_bigint->big_value_len));
3282 
3283 	return (CKR_OK);
3284 }
3285 
3286 static void
3287 free_public_key_attr(public_key_obj_t *pbk, CK_KEY_TYPE key_type)
3288 {
3289 	if (pbk == NULL) {
3290 		return;
3291 	}
3292 
3293 	switch (key_type) {
3294 		case CKK_RSA:
3295 			bigint_attr_cleanup(KEY_PUB_RSA_MOD(pbk));
3296 			bigint_attr_cleanup(KEY_PUB_RSA_PUBEXPO(pbk));
3297 			break;
3298 		case CKK_DSA:
3299 			bigint_attr_cleanup(KEY_PUB_DSA_PRIME(pbk));
3300 			bigint_attr_cleanup(KEY_PUB_DSA_SUBPRIME(pbk));
3301 			bigint_attr_cleanup(KEY_PUB_DSA_BASE(pbk));
3302 			bigint_attr_cleanup(KEY_PUB_DSA_VALUE(pbk));
3303 			break;
3304 		default:
3305 			break;
3306 	}
3307 	free(pbk);
3308 }
3309 
3310 
3311 CK_RV
3312 kernel_copy_public_key_attr(public_key_obj_t *old_pub_key_obj_p,
3313     public_key_obj_t **new_pub_key_obj_p, CK_KEY_TYPE key_type)
3314 {
3315 
3316 	public_key_obj_t *pbk;
3317 	CK_RV rv = CKR_OK;
3318 
3319 	pbk = calloc(1, sizeof (public_key_obj_t));
3320 	if (pbk == NULL) {
3321 		return (CKR_HOST_MEMORY);
3322 	}
3323 
3324 	switch (key_type) {
3325 		case CKK_RSA:
3326 			(void) memcpy(KEY_PUB_RSA(pbk),
3327 			    KEY_PUB_RSA(old_pub_key_obj_p),
3328 			    sizeof (rsa_pub_key_t));
3329 			/* copy modulus */
3330 			rv = copy_bigint(KEY_PUB_RSA_MOD(pbk),
3331 			    KEY_PUB_RSA_MOD(old_pub_key_obj_p));
3332 			if (rv != CKR_OK) {
3333 				free_public_key_attr(pbk, key_type);
3334 				return (rv);
3335 			}
3336 			/* copy public exponent */
3337 			rv = copy_bigint(KEY_PUB_RSA_PUBEXPO(pbk),
3338 			    KEY_PUB_RSA_PUBEXPO(old_pub_key_obj_p));
3339 			if (rv != CKR_OK) {
3340 				free_public_key_attr(pbk, key_type);
3341 				return (rv);
3342 			}
3343 			break;
3344 		case CKK_DSA:
3345 			(void) memcpy(KEY_PUB_DSA(pbk),
3346 			    KEY_PUB_DSA(old_pub_key_obj_p),
3347 			    sizeof (dsa_pub_key_t));
3348 
3349 			/* copy prime */
3350 			rv = copy_bigint(KEY_PUB_DSA_PRIME(pbk),
3351 			    KEY_PUB_DSA_PRIME(old_pub_key_obj_p));
3352 			if (rv != CKR_OK) {
3353 				free_public_key_attr(pbk, key_type);
3354 				return (rv);
3355 			}
3356 
3357 			/* copy subprime */
3358 			rv = copy_bigint(KEY_PUB_DSA_SUBPRIME(pbk),
3359 			    KEY_PUB_DSA_SUBPRIME(old_pub_key_obj_p));
3360 			if (rv != CKR_OK) {
3361 				free_public_key_attr(pbk, key_type);
3362 				return (rv);
3363 			}
3364 
3365 			/* copy base */
3366 			rv = copy_bigint(KEY_PUB_DSA_BASE(pbk),
3367 			    KEY_PUB_DSA_BASE(old_pub_key_obj_p));
3368 			if (rv != CKR_OK) {
3369 				free_public_key_attr(pbk, key_type);
3370 				return (rv);
3371 			}
3372 
3373 			/* copy value */
3374 			rv = copy_bigint(KEY_PUB_DSA_VALUE(pbk),
3375 			    KEY_PUB_DSA_VALUE(old_pub_key_obj_p));
3376 			if (rv != CKR_OK) {
3377 				free_public_key_attr(pbk, key_type);
3378 				return (rv);
3379 			}
3380 			break;
3381 		default:
3382 			break;
3383 	}
3384 	*new_pub_key_obj_p = pbk;
3385 	return (rv);
3386 }
3387 
3388 
3389 static void
3390 free_private_key_attr(private_key_obj_t *pbk, CK_KEY_TYPE key_type)
3391 {
3392 	if (pbk == NULL) {
3393 		return;
3394 	}
3395 
3396 	switch (key_type) {
3397 		case CKK_RSA:
3398 			bigint_attr_cleanup(KEY_PRI_RSA_MOD(pbk));
3399 			bigint_attr_cleanup(KEY_PRI_RSA_PUBEXPO(pbk));
3400 			bigint_attr_cleanup(KEY_PRI_RSA_PRIEXPO(pbk));
3401 			bigint_attr_cleanup(KEY_PRI_RSA_PRIME1(pbk));
3402 			bigint_attr_cleanup(KEY_PRI_RSA_PRIME2(pbk));
3403 			bigint_attr_cleanup(KEY_PRI_RSA_EXPO1(pbk));
3404 			bigint_attr_cleanup(KEY_PRI_RSA_EXPO2(pbk));
3405 			bigint_attr_cleanup(KEY_PRI_RSA_COEF(pbk));
3406 			break;
3407 		case CKK_DSA:
3408 			bigint_attr_cleanup(KEY_PRI_DSA_PRIME(pbk));
3409 			bigint_attr_cleanup(KEY_PRI_DSA_SUBPRIME(pbk));
3410 			bigint_attr_cleanup(KEY_PRI_DSA_BASE(pbk));
3411 			bigint_attr_cleanup(KEY_PRI_DSA_VALUE(pbk));
3412 			break;
3413 		default:
3414 			break;
3415 	}
3416 	free(pbk);
3417 }
3418 
3419 CK_RV
3420 kernel_copy_private_key_attr(private_key_obj_t *old_pri_key_obj_p,
3421     private_key_obj_t **new_pri_key_obj_p, CK_KEY_TYPE key_type)
3422 {
3423 	CK_RV rv = CKR_OK;
3424 	private_key_obj_t *pbk;
3425 
3426 	pbk = calloc(1, sizeof (private_key_obj_t));
3427 	if (pbk == NULL) {
3428 		return (CKR_HOST_MEMORY);
3429 	}
3430 
3431 	switch (key_type) {
3432 		case CKK_RSA:
3433 			(void) memcpy(KEY_PRI_RSA(pbk),
3434 			    KEY_PRI_RSA(old_pri_key_obj_p),
3435 			    sizeof (rsa_pri_key_t));
3436 			/* copy modulus */
3437 			rv = copy_bigint(KEY_PRI_RSA_MOD(pbk),
3438 			    KEY_PRI_RSA_MOD(old_pri_key_obj_p));
3439 			if (rv != CKR_OK) {
3440 				free_private_key_attr(pbk, key_type);
3441 				return (rv);
3442 			}
3443 			/* copy public exponent */
3444 			rv = copy_bigint(KEY_PRI_RSA_PUBEXPO(pbk),
3445 			    KEY_PRI_RSA_PUBEXPO(old_pri_key_obj_p));
3446 			if (rv != CKR_OK) {
3447 				free_private_key_attr(pbk, key_type);
3448 				return (rv);
3449 			}
3450 			/* copy private exponent */
3451 			rv = copy_bigint(KEY_PRI_RSA_PRIEXPO(pbk),
3452 			    KEY_PRI_RSA_PRIEXPO(old_pri_key_obj_p));
3453 			if (rv != CKR_OK) {
3454 				free_private_key_attr(pbk, key_type);
3455 				return (rv);
3456 			}
3457 			/* copy prime_1 */
3458 			rv = copy_bigint(KEY_PRI_RSA_PRIME1(pbk),
3459 			    KEY_PRI_RSA_PRIME1(old_pri_key_obj_p));
3460 			if (rv != CKR_OK) {
3461 				free_private_key_attr(pbk, key_type);
3462 				return (rv);
3463 			}
3464 			/* copy prime_2 */
3465 			rv = copy_bigint(KEY_PRI_RSA_PRIME2(pbk),
3466 			    KEY_PRI_RSA_PRIME2(old_pri_key_obj_p));
3467 			if (rv != CKR_OK) {
3468 				free_private_key_attr(pbk, key_type);
3469 				return (rv);
3470 			}
3471 			/* copy exponent_1 */
3472 			rv = copy_bigint(KEY_PRI_RSA_EXPO1(pbk),
3473 			    KEY_PRI_RSA_EXPO1(old_pri_key_obj_p));
3474 			if (rv != CKR_OK) {
3475 				free_private_key_attr(pbk, key_type);
3476 				return (rv);
3477 			}
3478 			/* copy exponent_2 */
3479 			rv = copy_bigint(KEY_PRI_RSA_EXPO2(pbk),
3480 			    KEY_PRI_RSA_EXPO2(old_pri_key_obj_p));
3481 			if (rv != CKR_OK) {
3482 				free_private_key_attr(pbk, key_type);
3483 				return (rv);
3484 			}
3485 			/* copy coefficient */
3486 			rv = copy_bigint(KEY_PRI_RSA_COEF(pbk),
3487 			    KEY_PRI_RSA_COEF(old_pri_key_obj_p));
3488 			if (rv != CKR_OK) {
3489 				free_private_key_attr(pbk, key_type);
3490 				return (rv);
3491 			}
3492 			break;
3493 		case CKK_DSA:
3494 			(void) memcpy(KEY_PRI_DSA(pbk),
3495 			    KEY_PRI_DSA(old_pri_key_obj_p),
3496 			    sizeof (dsa_pri_key_t));
3497 
3498 			/* copy prime */
3499 			rv = copy_bigint(KEY_PRI_DSA_PRIME(pbk),
3500 			    KEY_PRI_DSA_PRIME(old_pri_key_obj_p));
3501 			if (rv != CKR_OK) {
3502 				free_private_key_attr(pbk, key_type);
3503 				return (rv);
3504 			}
3505 
3506 			/* copy subprime */
3507 			rv = copy_bigint(KEY_PRI_DSA_SUBPRIME(pbk),
3508 			    KEY_PRI_DSA_SUBPRIME(old_pri_key_obj_p));
3509 			if (rv != CKR_OK) {
3510 				free_private_key_attr(pbk, key_type);
3511 				return (rv);
3512 			}
3513 
3514 			/* copy base */
3515 			rv = copy_bigint(KEY_PRI_DSA_BASE(pbk),
3516 			    KEY_PRI_DSA_BASE(old_pri_key_obj_p));
3517 			if (rv != CKR_OK) {
3518 				free_private_key_attr(pbk, key_type);
3519 				return (rv);
3520 			}
3521 
3522 			/* copy value */
3523 			rv = copy_bigint(KEY_PRI_DSA_VALUE(pbk),
3524 			    KEY_PRI_DSA_VALUE(old_pri_key_obj_p));
3525 			if (rv != CKR_OK) {
3526 				free_private_key_attr(pbk, key_type);
3527 				return (rv);
3528 			}
3529 			break;
3530 		default:
3531 			break;
3532 	}
3533 	*new_pri_key_obj_p = pbk;
3534 	return (rv);
3535 }
3536 
3537 
3538 CK_RV
3539 kernel_copy_secret_key_attr(secret_key_obj_t *old_secret_key_obj_p,
3540     secret_key_obj_t **new_secret_key_obj_p)
3541 {
3542 	secret_key_obj_t *sk;
3543 
3544 	sk = malloc(sizeof (secret_key_obj_t));
3545 	if (sk == NULL) {
3546 		return (CKR_HOST_MEMORY);
3547 	}
3548 	(void) memcpy(sk, old_secret_key_obj_p, sizeof (secret_key_obj_t));
3549 
3550 	/* copy the secret key value */
3551 	sk->sk_value = malloc((sizeof (CK_BYTE) * sk->sk_value_len));
3552 	if (sk->sk_value == NULL) {
3553 		free(sk);
3554 		return (CKR_HOST_MEMORY);
3555 	}
3556 	(void) memcpy(sk->sk_value, old_secret_key_obj_p->sk_value,
3557 	    (sizeof (CK_BYTE) * sk->sk_value_len));
3558 
3559 	*new_secret_key_obj_p = sk;
3560 
3561 	return (CKR_OK);
3562 }
3563 
3564 
3565 
3566 /*
3567  * If CKA_CLASS not given, guess CKA_CLASS using
3568  * attributes on template .
3569  *
3570  * Some attributes are specific to an object class.  If one or more
3571  * of these attributes are in the template, make a list of classes
3572  * that can have these attributes.  This would speed up the search later,
3573  * because we can immediately skip an object if the class of that
3574  * object can not possiblely contain one of the attributes.
3575  *
3576  */
3577 void
3578 kernel_process_find_attr(CK_OBJECT_CLASS *pclasses,
3579     CK_ULONG *num_result_pclasses, CK_ATTRIBUTE_PTR pTemplate,
3580     CK_ULONG ulCount)
3581 {
3582 	ulong_t i;
3583 	int j;
3584 	boolean_t pub_found = B_FALSE,
3585 	    priv_found = B_FALSE,
3586 	    secret_found = B_FALSE,
3587 	    domain_found = B_FALSE,
3588 	    hardware_found = B_FALSE,
3589 	    cert_found = B_FALSE;
3590 	int num_pub_key_attrs, num_priv_key_attrs,
3591 	    num_secret_key_attrs, num_domain_attrs,
3592 	    num_hardware_attrs, num_cert_attrs;
3593 	int num_pclasses = 0;
3594 
3595 	for (i = 0; i < ulCount; i++) {
3596 		if (pTemplate[i].type == CKA_CLASS) {
3597 			/*
3598 			 * don't need to guess the class, it is specified.
3599 			 * Just record the class, and return.
3600 			 */
3601 			pclasses[0] =
3602 			    (*((CK_OBJECT_CLASS *)pTemplate[i].pValue));
3603 			*num_result_pclasses = 1;
3604 			return;
3605 		}
3606 	}
3607 
3608 	num_pub_key_attrs =
3609 	    sizeof (PUB_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
3610 	num_priv_key_attrs =
3611 	    sizeof (PRIV_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
3612 	num_secret_key_attrs =
3613 	    sizeof (SECRET_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
3614 	num_domain_attrs =
3615 	    sizeof (DOMAIN_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
3616 	num_hardware_attrs =
3617 	    sizeof (HARDWARE_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
3618 	num_cert_attrs =
3619 	    sizeof (CERT_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
3620 
3621 	/*
3622 	 * Get the list of objects class that might contain
3623 	 * some attributes.
3624 	 */
3625 	for (i = 0; i < ulCount; i++) {
3626 		/*
3627 		 * only check if this attribute can belong to public key object
3628 		 * class if public key object isn't already in the list
3629 		 */
3630 		if (!pub_found) {
3631 			for (j = 0; j < num_pub_key_attrs; j++) {
3632 				if (pTemplate[i].type == PUB_KEY_ATTRS[j]) {
3633 					pub_found = B_TRUE;
3634 					pclasses[num_pclasses++] =
3635 					    CKO_PUBLIC_KEY;
3636 					break;
3637 				}
3638 			}
3639 		}
3640 
3641 		if (!priv_found) {
3642 			for (j = 0; j < num_priv_key_attrs; j++) {
3643 				if (pTemplate[i].type == PRIV_KEY_ATTRS[j]) {
3644 					priv_found = B_TRUE;
3645 					pclasses[num_pclasses++] =
3646 					    CKO_PRIVATE_KEY;
3647 					break;
3648 				}
3649 			}
3650 		}
3651 
3652 		if (!secret_found) {
3653 			for (j = 0; j < num_secret_key_attrs; j++) {
3654 				if (pTemplate[i].type == SECRET_KEY_ATTRS[j]) {
3655 					secret_found = B_TRUE;
3656 					pclasses[num_pclasses++] =
3657 					    CKO_SECRET_KEY;
3658 					break;
3659 				}
3660 			}
3661 		}
3662 
3663 		if (!domain_found) {
3664 			for (j = 0; j < num_domain_attrs; j++) {
3665 				if (pTemplate[i].type == DOMAIN_ATTRS[j]) {
3666 					domain_found = B_TRUE;
3667 					pclasses[num_pclasses++] =
3668 					    CKO_DOMAIN_PARAMETERS;
3669 					break;
3670 				}
3671 			}
3672 		}
3673 
3674 		if (!hardware_found) {
3675 			for (j = 0; j < num_hardware_attrs; j++) {
3676 				if (pTemplate[i].type == HARDWARE_ATTRS[j]) {
3677 					hardware_found = B_TRUE;
3678 					pclasses[num_pclasses++] =
3679 					    CKO_HW_FEATURE;
3680 					break;
3681 				}
3682 			}
3683 		}
3684 
3685 		if (!cert_found) {
3686 			for (j = 0; j < num_cert_attrs; j++) {
3687 				if (pTemplate[i].type == CERT_ATTRS[j]) {
3688 					cert_found = B_TRUE;
3689 					pclasses[num_pclasses++] =
3690 					    CKO_CERTIFICATE;
3691 					break;
3692 				}
3693 			}
3694 		}
3695 	}
3696 	*num_result_pclasses = num_pclasses;
3697 }
3698 
3699 
3700 boolean_t
3701 kernel_find_match_attrs(kernel_object_t *obj, CK_OBJECT_CLASS *pclasses,
3702     CK_ULONG num_pclasses, CK_ATTRIBUTE *template, CK_ULONG num_attr)
3703 {
3704 	ulong_t i;
3705 	CK_ATTRIBUTE *tmpl_attr, *obj_attr;
3706 	uint64_t attr_mask;
3707 	biginteger_t *bigint;
3708 	boolean_t compare_attr, compare_bigint, compare_boolean;
3709 
3710 	/*
3711 	 * Check if the class of this object match with any
3712 	 * of object classes that can possiblely contain the
3713 	 * requested attributes.
3714 	 */
3715 	if (num_pclasses > 0) {
3716 		for (i = 0; i < num_pclasses; i++) {
3717 			if (obj->class == pclasses[i]) {
3718 				break;
3719 			}
3720 		}
3721 		if (i == num_pclasses) {
3722 			/*
3723 			 * this object can't possiblely contain one or
3724 			 * more attributes, don't need to check this object
3725 			 */
3726 			return (B_FALSE);
3727 		}
3728 	}
3729 
3730 	/* need to examine everything */
3731 	for (i = 0; i < num_attr; i++) {
3732 		tmpl_attr = &(template[i]);
3733 		compare_attr = B_FALSE;
3734 		compare_bigint = B_FALSE;
3735 		compare_boolean = B_FALSE;
3736 		switch (tmpl_attr->type) {
3737 		/* First, check the most common attributes */
3738 		case CKA_CLASS:
3739 			if (*((CK_OBJECT_CLASS *)tmpl_attr->pValue) !=
3740 			    obj->class) {
3741 				return (B_FALSE);
3742 			}
3743 			break;
3744 		case CKA_KEY_TYPE:
3745 			if (*((CK_KEY_TYPE *)tmpl_attr->pValue) !=
3746 			    obj->key_type) {
3747 				return (B_FALSE);
3748 			}
3749 			break;
3750 		case CKA_ENCRYPT:
3751 			attr_mask = (obj->bool_attr_mask) & ENCRYPT_BOOL_ON;
3752 			compare_boolean = B_TRUE;
3753 			break;
3754 		case CKA_DECRYPT:
3755 			attr_mask = (obj->bool_attr_mask) & DECRYPT_BOOL_ON;
3756 			compare_boolean = B_TRUE;
3757 			break;
3758 		case CKA_WRAP:
3759 			attr_mask = (obj->bool_attr_mask) & WRAP_BOOL_ON;
3760 			compare_boolean = B_TRUE;
3761 			break;
3762 		case CKA_UNWRAP:
3763 			attr_mask = (obj->bool_attr_mask) & UNWRAP_BOOL_ON;
3764 			compare_boolean = B_TRUE;
3765 			break;
3766 		case CKA_SIGN:
3767 			attr_mask = (obj->bool_attr_mask) & SIGN_BOOL_ON;
3768 			compare_boolean = B_TRUE;
3769 			break;
3770 		case CKA_SIGN_RECOVER:
3771 			attr_mask = (obj->bool_attr_mask) &
3772 			    SIGN_RECOVER_BOOL_ON;
3773 			compare_boolean = B_TRUE;
3774 			break;
3775 		case CKA_VERIFY:
3776 			attr_mask = (obj->bool_attr_mask) & VERIFY_BOOL_ON;
3777 			compare_boolean = B_TRUE;
3778 			break;
3779 		case CKA_VERIFY_RECOVER:
3780 			attr_mask = (obj->bool_attr_mask) &
3781 			    VERIFY_RECOVER_BOOL_ON;
3782 			compare_boolean = B_TRUE;
3783 			break;
3784 		case CKA_DERIVE:
3785 			attr_mask = (obj->bool_attr_mask) & DERIVE_BOOL_ON;
3786 			compare_boolean = B_TRUE;
3787 			break;
3788 		case CKA_LOCAL:
3789 			attr_mask = (obj->bool_attr_mask) & LOCAL_BOOL_ON;
3790 			compare_boolean = B_TRUE;
3791 			break;
3792 		case CKA_SENSITIVE:
3793 			attr_mask = (obj->bool_attr_mask) & SENSITIVE_BOOL_ON;
3794 			compare_boolean = B_TRUE;
3795 			break;
3796 		case CKA_SECONDARY_AUTH:
3797 			attr_mask = (obj->bool_attr_mask) &
3798 			    SECONDARY_AUTH_BOOL_ON;
3799 			compare_boolean = B_TRUE;
3800 			break;
3801 		case CKA_TRUSTED:
3802 			attr_mask = (obj->bool_attr_mask) & TRUSTED_BOOL_ON;
3803 			compare_boolean = B_TRUE;
3804 			break;
3805 		case CKA_EXTRACTABLE:
3806 			attr_mask = (obj->bool_attr_mask) &
3807 			    EXTRACTABLE_BOOL_ON;
3808 			compare_boolean = B_TRUE;
3809 			break;
3810 		case CKA_ALWAYS_SENSITIVE:
3811 			attr_mask = (obj->bool_attr_mask) &
3812 			    ALWAYS_SENSITIVE_BOOL_ON;
3813 			compare_boolean = B_TRUE;
3814 			break;
3815 		case CKA_NEVER_EXTRACTABLE:
3816 			attr_mask = (obj->bool_attr_mask) &
3817 			    NEVER_EXTRACTABLE_BOOL_ON;
3818 			compare_boolean = B_TRUE;
3819 			break;
3820 		case CKA_TOKEN:
3821 			/*
3822 			 * CKA_TOKEN value is not applicable to an object
3823 			 * created in the library, it should only contain
3824 			 * the default value FALSE
3825 			 */
3826 			attr_mask = 0;
3827 			compare_boolean = B_TRUE;
3828 			break;
3829 		case CKA_PRIVATE:
3830 			attr_mask = (obj->bool_attr_mask) & PRIVATE_BOOL_ON;
3831 			compare_boolean = B_TRUE;
3832 			break;
3833 		case CKA_MODIFIABLE:
3834 			attr_mask = (obj->bool_attr_mask) & MODIFIABLE_BOOL_ON;
3835 			compare_boolean = B_TRUE;
3836 			break;
3837 		case CKA_SUBJECT:
3838 		case CKA_ID:
3839 		case CKA_START_DATE:
3840 		case CKA_END_DATE:
3841 		case CKA_KEY_GEN_MECHANISM:
3842 		case CKA_LABEL:
3843 			/* find these attributes from extra_attrlistp */
3844 			obj_attr = get_extra_attr(tmpl_attr->type, obj);
3845 			compare_attr = B_TRUE;
3846 			break;
3847 		case CKA_VALUE_LEN:
3848 			/* only secret key has this attribute */
3849 			if (obj->class == CKO_SECRET_KEY) {
3850 				if (*((CK_ULONG *)tmpl_attr->pValue) !=
3851 				    OBJ_SEC_VALUE_LEN(obj)) {
3852 					return (B_FALSE);
3853 				}
3854 			} else {
3855 				return (B_FALSE);
3856 			}
3857 			break;
3858 		case CKA_VALUE:
3859 			switch (obj->class) {
3860 			case CKO_SECRET_KEY:
3861 				/*
3862 				 * secret_key_obj_t is the same as
3863 				 * biginteger_t
3864 				 */
3865 				bigint = (biginteger_t *)OBJ_SEC(obj);
3866 				break;
3867 			case CKO_PRIVATE_KEY:
3868 				if (obj->key_type == CKK_DSA) {
3869 					bigint = OBJ_PRI_DSA_VALUE(obj);
3870 				} else {
3871 					return (B_FALSE);
3872 				}
3873 				break;
3874 			case CKO_PUBLIC_KEY:
3875 				if (obj->key_type == CKK_DSA) {
3876 					bigint = OBJ_PUB_DSA_VALUE(obj);
3877 				} else {
3878 					return (B_FALSE);
3879 				}
3880 				break;
3881 			default:
3882 				return (B_FALSE);
3883 			}
3884 			compare_bigint = B_TRUE;
3885 			break;
3886 		case CKA_MODULUS:
3887 			/* only RSA public and private key have this attr */
3888 			if (obj->key_type == CKK_RSA) {
3889 				if (obj->class == CKO_PUBLIC_KEY) {
3890 					bigint = OBJ_PUB_RSA_MOD(obj);
3891 				} else if (obj->class == CKO_PRIVATE_KEY) {
3892 					bigint = OBJ_PRI_RSA_MOD(obj);
3893 				} else {
3894 					return (B_FALSE);
3895 				}
3896 				compare_bigint = B_TRUE;
3897 			} else {
3898 				return (B_FALSE);
3899 			}
3900 			break;
3901 		case CKA_MODULUS_BITS:
3902 			/* only RSA public key has this attribute */
3903 			if ((obj->key_type == CKK_RSA) &&
3904 			    (obj->class == CKO_PUBLIC_KEY)) {
3905 				CK_ULONG mod_bits = OBJ_PUB_RSA_MOD_BITS(obj);
3906 				if (mod_bits !=
3907 				    *((CK_ULONG *)tmpl_attr->pValue)) {
3908 					return (B_FALSE);
3909 				}
3910 			} else {
3911 				return (B_FALSE);
3912 			}
3913 			break;
3914 		case CKA_PUBLIC_EXPONENT:
3915 			/* only RSA public and private key have this attr */
3916 			if (obj->key_type == CKK_RSA) {
3917 				if (obj->class == CKO_PUBLIC_KEY) {
3918 					bigint = OBJ_PUB_RSA_PUBEXPO(obj);
3919 				} else if (obj->class == CKO_PRIVATE_KEY) {
3920 					bigint = OBJ_PRI_RSA_PUBEXPO(obj);
3921 				} else {
3922 					return (B_FALSE);
3923 				}
3924 				compare_bigint = B_TRUE;
3925 			} else {
3926 				return (B_FALSE);
3927 			}
3928 			break;
3929 		case CKA_PRIVATE_EXPONENT:
3930 			/* only RSA private key has this attribute */
3931 			if ((obj->key_type == CKK_RSA) &&
3932 			    (obj->class == CKO_PRIVATE_KEY)) {
3933 				bigint = OBJ_PRI_RSA_PRIEXPO(obj);
3934 				compare_bigint = B_TRUE;
3935 			} else {
3936 				return (B_FALSE);
3937 			}
3938 			break;
3939 		case CKA_PRIME_1:
3940 			/* only RSA private key has this attribute */
3941 			if ((obj->key_type == CKK_RSA) &&
3942 			    (obj->class == CKO_PRIVATE_KEY)) {
3943 				bigint = OBJ_PRI_RSA_PRIME1(obj);
3944 				compare_bigint = B_TRUE;
3945 			} else {
3946 				return (B_FALSE);
3947 			}
3948 			break;
3949 		case CKA_PRIME_2:
3950 			/* only RSA private key has this attribute */
3951 			if ((obj->key_type == CKK_RSA) &&
3952 			    (obj->class == CKO_PRIVATE_KEY)) {
3953 				bigint = OBJ_PRI_RSA_PRIME2(obj);
3954 				compare_bigint = B_TRUE;
3955 			} else {
3956 				return (B_FALSE);
3957 			}
3958 			break;
3959 		case CKA_EXPONENT_1:
3960 			/* only RSA private key has this attribute */
3961 			if ((obj->key_type == CKK_RSA) &&
3962 			    (obj->class == CKO_PRIVATE_KEY)) {
3963 				bigint = OBJ_PRI_RSA_EXPO1(obj);
3964 				compare_bigint = B_TRUE;
3965 			} else {
3966 				return (B_FALSE);
3967 			}
3968 			break;
3969 		case CKA_EXPONENT_2:
3970 			/* only RSA private key has this attribute */
3971 			if ((obj->key_type == CKK_RSA) &&
3972 			    (obj->class == CKO_PRIVATE_KEY)) {
3973 				bigint = OBJ_PRI_RSA_EXPO2(obj);
3974 				compare_bigint = B_TRUE;
3975 			} else {
3976 				return (B_FALSE);
3977 			}
3978 			break;
3979 		case CKA_COEFFICIENT:
3980 			/* only RSA private key has this attribute */
3981 			if ((obj->key_type == CKK_RSA) &&
3982 			    (obj->class == CKO_PRIVATE_KEY)) {
3983 				bigint = OBJ_PRI_RSA_COEF(obj);
3984 				compare_bigint = B_TRUE;
3985 			} else {
3986 				return (B_FALSE);
3987 			}
3988 			break;
3989 		case CKA_VALUE_BITS:
3990 			return (B_FALSE);
3991 		case CKA_PRIME:
3992 			if (obj->class == CKO_PUBLIC_KEY) {
3993 				switch (obj->key_type) {
3994 				case CKK_DSA:
3995 					bigint = OBJ_PUB_DSA_PRIME(obj);
3996 					break;
3997 				default:
3998 					return (B_FALSE);
3999 				}
4000 			} else if (obj->class == CKO_PRIVATE_KEY) {
4001 				switch (obj->key_type) {
4002 				case CKK_DSA:
4003 					bigint = OBJ_PRI_DSA_PRIME(obj);
4004 					break;
4005 				default:
4006 					return (B_FALSE);
4007 				}
4008 			} else {
4009 				return (B_FALSE);
4010 			}
4011 			compare_bigint = B_TRUE;
4012 			break;
4013 		case CKA_SUBPRIME:
4014 			if (obj->class == CKO_PUBLIC_KEY) {
4015 				switch (obj->key_type) {
4016 				case CKK_DSA:
4017 					bigint = OBJ_PUB_DSA_SUBPRIME(obj);
4018 					break;
4019 				default:
4020 					return (B_FALSE);
4021 				}
4022 			} else if (obj->class == CKO_PRIVATE_KEY) {
4023 				switch (obj->key_type) {
4024 				case CKK_DSA:
4025 					bigint = OBJ_PRI_DSA_SUBPRIME(obj);
4026 					break;
4027 				default:
4028 					return (B_FALSE);
4029 				}
4030 			} else {
4031 				return (B_FALSE);
4032 			}
4033 			compare_bigint = B_TRUE;
4034 			break;
4035 		case CKA_BASE:
4036 			if (obj->class == CKO_PUBLIC_KEY) {
4037 				switch (obj->key_type) {
4038 				case CKK_DSA:
4039 					bigint = OBJ_PUB_DSA_BASE(obj);
4040 					break;
4041 				default:
4042 					return (B_FALSE);
4043 				}
4044 			} else if (obj->class == CKO_PRIVATE_KEY) {
4045 				switch (obj->key_type) {
4046 				case CKK_DSA:
4047 					bigint = OBJ_PRI_DSA_BASE(obj);
4048 					break;
4049 				default:
4050 					return (B_FALSE);
4051 				}
4052 			} else {
4053 				return (B_FALSE);
4054 			}
4055 			compare_bigint = B_TRUE;
4056 			break;
4057 		case CKA_PRIME_BITS:
4058 			return (B_FALSE);
4059 		case CKA_SUBPRIME_BITS:
4060 			return (B_FALSE);
4061 		default:
4062 			/*
4063 			 * any other attributes are currently not supported.
4064 			 * so, it's not possible for them to be in the
4065 			 * object
4066 			 */
4067 			return (B_FALSE);
4068 		}
4069 		if (compare_boolean) {
4070 			CK_BBOOL bval;
4071 
4072 			if (attr_mask) {
4073 				bval = TRUE;
4074 			} else {
4075 				bval = FALSE;
4076 			}
4077 			if (bval != *((CK_BBOOL *)tmpl_attr->pValue)) {
4078 				return (B_FALSE);
4079 			}
4080 		} else if (compare_bigint) {
4081 			if (bigint == NULL) {
4082 				return (B_FALSE);
4083 			}
4084 			if (tmpl_attr->ulValueLen != bigint->big_value_len) {
4085 				return (B_FALSE);
4086 			}
4087 			if (memcmp(tmpl_attr->pValue, bigint->big_value,
4088 			    tmpl_attr->ulValueLen) != 0) {
4089 				return (B_FALSE);
4090 			}
4091 		} else if (compare_attr) {
4092 			if (obj_attr == NULL) {
4093 				/*
4094 				 * The attribute type is valid, and its value
4095 				 * has not been initialized in the object. In
4096 				 * this case, it only matches the template's
4097 				 * attribute if the template's value length
4098 				 * is 0.
4099 				 */
4100 				if (tmpl_attr->ulValueLen != 0)
4101 					return (B_FALSE);
4102 			} else {
4103 				if (tmpl_attr->ulValueLen !=
4104 				    obj_attr->ulValueLen) {
4105 					return (B_FALSE);
4106 				}
4107 				if (memcmp(tmpl_attr->pValue, obj_attr->pValue,
4108 				    tmpl_attr->ulValueLen) != 0) {
4109 					return (B_FALSE);
4110 				}
4111 			}
4112 		}
4113 	}
4114 	return (B_TRUE);
4115 }
4116 
4117 CK_ATTRIBUTE_PTR
4118 get_extra_attr(CK_ATTRIBUTE_TYPE type, kernel_object_t *obj)
4119 {
4120 	CK_ATTRIBUTE_INFO_PTR tmp;
4121 
4122 	tmp = obj->extra_attrlistp;
4123 	while (tmp != NULL) {
4124 		if (tmp->attr.type == type) {
4125 			return (&(tmp->attr));
4126 		}
4127 		tmp = tmp->next;
4128 	}
4129 	/* if get there, the specified attribute is not found */
4130 	return (NULL);
4131 }
4132