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