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