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