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