xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_softtoken/common/softAttributeUtil.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 <arcfour.h>
33 #include <aes_impl.h>
34 #include <bignum.h>
35 #include <des_impl.h>
36 #include <rsa_impl.h>
37 #include "softGlobal.h"
38 #include "softObject.h"
39 #include "softSession.h"
40 #include "softKeystore.h"
41 #include "softKeystoreUtil.h"
42 
43 
44 /*
45  * This attribute table is used by the soft_lookup_attr()
46  * to validate the attributes.
47  */
48 CK_ATTRIBUTE_TYPE attr_map[] = {
49 	CKA_PRIVATE,
50 	CKA_LABEL,
51 	CKA_APPLICATION,
52 	CKA_OBJECT_ID,
53 	CKA_CERTIFICATE_TYPE,
54 	CKA_ISSUER,
55 	CKA_SERIAL_NUMBER,
56 	CKA_AC_ISSUER,
57 	CKA_OWNER,
58 	CKA_ATTR_TYPES,
59 	CKA_SUBJECT,
60 	CKA_ID,
61 	CKA_SENSITIVE,
62 	CKA_START_DATE,
63 	CKA_END_DATE,
64 	CKA_MODULUS,
65 	CKA_MODULUS_BITS,
66 	CKA_PUBLIC_EXPONENT,
67 	CKA_PRIVATE_EXPONENT,
68 	CKA_PRIME_1,
69 	CKA_PRIME_2,
70 	CKA_EXPONENT_1,
71 	CKA_EXPONENT_2,
72 	CKA_COEFFICIENT,
73 	CKA_PRIME,
74 	CKA_SUBPRIME,
75 	CKA_BASE,
76 	CKA_EXTRACTABLE,
77 	CKA_LOCAL,
78 	CKA_NEVER_EXTRACTABLE,
79 	CKA_ALWAYS_SENSITIVE,
80 	CKA_MODIFIABLE,
81 	CKA_ECDSA_PARAMS,
82 	CKA_EC_POINT,
83 	CKA_SECONDARY_AUTH,
84 	CKA_AUTH_PIN_FLAGS,
85 	CKA_HW_FEATURE_TYPE,
86 	CKA_RESET_ON_INIT,
87 	CKA_HAS_RESET
88 };
89 
90 /*
91  * attributes that exists only in public key objects
92  * Note: some attributes may also exist in one or two
93  *       other object classes, but they are also listed
94  *       because not all object have them.
95  */
96 CK_ATTRIBUTE_TYPE PUB_KEY_ATTRS[] =
97 {
98 	CKA_SUBJECT,
99 	CKA_ENCRYPT,
100 	CKA_WRAP,
101 	CKA_VERIFY,
102 	CKA_VERIFY_RECOVER,
103 	CKA_MODULUS,
104 	CKA_MODULUS_BITS,
105 	CKA_PUBLIC_EXPONENT,
106 	CKA_PRIME,
107 	CKA_SUBPRIME,
108 	CKA_BASE,
109 	CKA_TRUSTED,
110 	CKA_ECDSA_PARAMS,
111 	CKA_EC_PARAMS,
112 	CKA_EC_POINT
113 };
114 
115 /*
116  * attributes that exists only in private key objects
117  * Note: some attributes may also exist in one or two
118  *       other object classes, but they are also listed
119  *       because not all object have them.
120  */
121 CK_ATTRIBUTE_TYPE PRIV_KEY_ATTRS[] =
122 {
123 	CKA_DECRYPT,
124 	CKA_UNWRAP,
125 	CKA_SIGN,
126 	CKA_SIGN_RECOVER,
127 	CKA_MODULUS,
128 	CKA_PUBLIC_EXPONENT,
129 	CKA_PRIVATE_EXPONENT,
130 	CKA_PRIME,
131 	CKA_SUBPRIME,
132 	CKA_BASE,
133 	CKA_PRIME_1,
134 	CKA_PRIME_2,
135 	CKA_EXPONENT_1,
136 	CKA_EXPONENT_2,
137 	CKA_COEFFICIENT,
138 	CKA_VALUE_BITS,
139 	CKA_SUBJECT,
140 	CKA_SENSITIVE,
141 	CKA_EXTRACTABLE,
142 	CKA_NEVER_EXTRACTABLE,
143 	CKA_ALWAYS_SENSITIVE,
144 	CKA_ECDSA_PARAMS,
145 	CKA_EC_PARAMS
146 };
147 
148 /*
149  * attributes that exists only in secret key objects
150  * Note: some attributes may also exist in one or two
151  *       other object classes, but they are also listed
152  *       because not all object have them.
153  */
154 CK_ATTRIBUTE_TYPE SECRET_KEY_ATTRS[] =
155 {
156 	CKA_VALUE_LEN,
157 	CKA_ENCRYPT,
158 	CKA_DECRYPT,
159 	CKA_WRAP,
160 	CKA_UNWRAP,
161 	CKA_SIGN,
162 	CKA_VERIFY,
163 	CKA_SENSITIVE,
164 	CKA_EXTRACTABLE,
165 	CKA_NEVER_EXTRACTABLE,
166 	CKA_ALWAYS_SENSITIVE
167 };
168 
169 /*
170  * attributes that exists only in domain parameter objects
171  * Note: some attributes may also exist in one or two
172  *       other object classes, but they are also listed
173  *       because not all object have them.
174  */
175 CK_ATTRIBUTE_TYPE DOMAIN_ATTRS[] =
176 {
177 	CKA_PRIME,
178 	CKA_SUBPRIME,
179 	CKA_BASE,
180 	CKA_PRIME_BITS,
181 	CKA_SUBPRIME_BITS,
182 	CKA_SUB_PRIME_BITS
183 };
184 
185 /*
186  * attributes that exists only in hardware feature objects
187  *
188  */
189 CK_ATTRIBUTE_TYPE HARDWARE_ATTRS[] =
190 {
191 	CKA_HW_FEATURE_TYPE,
192 	CKA_RESET_ON_INIT,
193 	CKA_HAS_RESET
194 };
195 
196 /*
197  * attributes that exists only in certificate objects
198  */
199 CK_ATTRIBUTE_TYPE CERT_ATTRS[] =
200 {
201 	CKA_CERTIFICATE_TYPE,
202 	CKA_TRUSTED,
203 	CKA_SUBJECT,
204 	CKA_ID,
205 	CKA_ISSUER,
206 	CKA_AC_ISSUER,
207 	CKA_SERIAL_NUMBER,
208 	CKA_OWNER,
209 	CKA_ATTR_TYPES
210 };
211 
212 
213 /*
214  * Validate the attribute by using binary search algorithm.
215  */
216 CK_RV
217 soft_lookup_attr(CK_ATTRIBUTE_TYPE type)
218 {
219 
220 	size_t lower, middle, upper;
221 
222 	lower = 0;
223 	upper = (sizeof (attr_map) / sizeof (CK_ATTRIBUTE_TYPE)) - 1;
224 
225 	while (lower <= upper) {
226 		/* Always starts from middle. */
227 		middle = (lower + upper) / 2;
228 
229 		if (type > attr_map[middle]) {
230 			/* Adjust the lower bound to upper half. */
231 			lower = middle + 1;
232 			continue;
233 		}
234 
235 		if (type == attr_map[middle]) {
236 			/* Found it. */
237 			return (CKR_OK);
238 		}
239 
240 		if (type < attr_map[middle]) {
241 			/* Adjust the upper bound to lower half. */
242 			upper = middle - 1;
243 			continue;
244 		}
245 	}
246 
247 	/* Failed to find the matching attribute from the attribute table. */
248 	return (CKR_ATTRIBUTE_TYPE_INVALID);
249 }
250 
251 
252 /*
253  * Validate the attribute by using the following search algorithm:
254  *
255  * 1) Search for the most frequently used attributes first.
256  * 2) If not found, search for the usage-purpose attributes - these
257  *    attributes have dense set of values, therefore compiler will
258  *    optimize it with a branch table and branch to the appropriate
259  *    case.
260  * 3) If still not found, use binary search for the rest of the
261  *    attributes in the attr_map[] table.
262  */
263 CK_RV
264 soft_validate_attr(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
265 	CK_OBJECT_CLASS *class)
266 {
267 
268 	CK_ULONG i;
269 	CK_RV rv = CKR_OK;
270 
271 	for (i = 0; i < ulAttrNum; i++) {
272 		/* First tier search */
273 		switch (template[i].type) {
274 		case CKA_CLASS:
275 			*class = *((CK_OBJECT_CLASS*)template[i].pValue);
276 			break;
277 		case CKA_TOKEN:
278 			break;
279 		case CKA_KEY_TYPE:
280 			break;
281 		case CKA_VALUE:
282 			break;
283 		case CKA_VALUE_LEN:
284 			break;
285 		case CKA_VALUE_BITS:
286 			break;
287 		default:
288 			/* Second tier search */
289 			switch (template[i].type) {
290 			case CKA_ENCRYPT:
291 				break;
292 			case CKA_DECRYPT:
293 				break;
294 			case CKA_WRAP:
295 				break;
296 			case CKA_UNWRAP:
297 				break;
298 			case CKA_SIGN:
299 				break;
300 			case CKA_SIGN_RECOVER:
301 				break;
302 			case CKA_VERIFY:
303 				break;
304 			case CKA_VERIFY_RECOVER:
305 				break;
306 			case CKA_DERIVE:
307 				break;
308 			default:
309 				/* Third tier search */
310 				rv = soft_lookup_attr(template[i].type);
311 				if (rv != CKR_OK)
312 					return (rv);
313 				break;
314 			}
315 			break;
316 		}
317 	}
318 	return (rv);
319 }
320 
321 static void
322 cleanup_cert_attr(cert_attr_t *attr)
323 {
324 	if (attr) {
325 		if (attr->value) {
326 			(void) memset(attr->value, 0, attr->length);
327 			free(attr->value);
328 		}
329 		attr->value = NULL;
330 		attr->length = 0;
331 	}
332 }
333 
334 static CK_RV
335 copy_cert_attr(cert_attr_t *src_attr, cert_attr_t **dest_attr)
336 {
337 	CK_RV rv = CKR_OK;
338 
339 	if (src_attr == NULL || dest_attr == NULL)
340 		return (CKR_HOST_MEMORY);
341 
342 	if (src_attr->value == NULL)
343 		return (CKR_HOST_MEMORY);
344 
345 	/* free memory if its already allocated */
346 	if (*dest_attr != NULL) {
347 		if ((*dest_attr)->value != (CK_BYTE *)NULL)
348 			free((*dest_attr)->value);
349 	} else {
350 		*dest_attr = malloc(sizeof (cert_attr_t));
351 		if (*dest_attr == NULL)
352 			return (CKR_HOST_MEMORY);
353 	}
354 
355 	(*dest_attr)->value = NULL;
356 	(*dest_attr)->length = 0;
357 
358 	if (src_attr->length) {
359 		(*dest_attr)->value = malloc(src_attr->length);
360 		if ((*dest_attr)->value == NULL) {
361 			free(*dest_attr);
362 			return (CKR_HOST_MEMORY);
363 		}
364 
365 		(void) memcpy((*dest_attr)->value, src_attr->value,
366 			src_attr->length);
367 		(*dest_attr)->length = src_attr->length;
368 	}
369 
370 	return (rv);
371 }
372 
373 void
374 soft_cleanup_cert_object(soft_object_t *object_p)
375 {
376 	CK_CERTIFICATE_TYPE certtype = object_p->cert_type;
377 
378 	if (object_p->class != CKO_CERTIFICATE ||
379 	    OBJ_CERT(object_p) == NULL)
380 		return;
381 
382 	if (certtype == CKC_X_509) {
383 		if (X509_CERT_SUBJECT(object_p) != NULL) {
384 			cleanup_cert_attr(X509_CERT_SUBJECT(object_p));
385 			free(X509_CERT_SUBJECT(object_p));
386 			X509_CERT_SUBJECT(object_p) = NULL;
387 		}
388 		if (X509_CERT_VALUE(object_p) != NULL) {
389 			cleanup_cert_attr(X509_CERT_VALUE(object_p));
390 			free(X509_CERT_VALUE(object_p));
391 			X509_CERT_VALUE(object_p) = NULL;
392 		}
393 		free(OBJ_CERT(object_p));
394 	} else if (certtype == CKC_X_509_ATTR_CERT) {
395 		if (X509_ATTR_CERT_VALUE(object_p) != NULL) {
396 			cleanup_cert_attr(X509_ATTR_CERT_VALUE(object_p));
397 			free(X509_ATTR_CERT_VALUE(object_p));
398 			X509_ATTR_CERT_VALUE(object_p) = NULL;
399 		}
400 		if (X509_ATTR_CERT_OWNER(object_p) != NULL) {
401 			cleanup_cert_attr(X509_ATTR_CERT_OWNER(object_p));
402 			free(X509_ATTR_CERT_OWNER(object_p));
403 			X509_ATTR_CERT_OWNER(object_p) = NULL;
404 		}
405 		free(OBJ_CERT(object_p));
406 	}
407 }
408 
409 /*
410  * Clean up and release all the storage in the extra attribute list
411  * of an object.
412  */
413 void
414 soft_cleanup_extra_attr(soft_object_t *object_p)
415 {
416 
417 	CK_ATTRIBUTE_INFO_PTR extra_attr;
418 	CK_ATTRIBUTE_INFO_PTR tmp;
419 
420 	extra_attr = object_p->extra_attrlistp;
421 	while (extra_attr) {
422 		tmp = extra_attr->next;
423 		if (extra_attr->attr.pValue)
424 			/*
425 			 * All extra attributes in the extra attribute
426 			 * list have pValue points to the value of the
427 			 * attribute (with simple byte array type).
428 			 * Free the storage for the value of the attribute.
429 			 */
430 			free(extra_attr->attr.pValue);
431 
432 		/* Free the storage for the attribute_info struct. */
433 		free(extra_attr);
434 		extra_attr = tmp;
435 	}
436 
437 	object_p->extra_attrlistp = NULL;
438 }
439 
440 
441 /*
442  * Create the attribute_info struct to hold the object's attribute,
443  * and add it to the extra attribute list of an object.
444  */
445 CK_RV
446 soft_add_extra_attr(CK_ATTRIBUTE_PTR template, soft_object_t *object_p)
447 {
448 
449 	CK_ATTRIBUTE_INFO_PTR attrp;
450 
451 	/* Allocate the storage for the attribute_info struct. */
452 	attrp = calloc(1, sizeof (attribute_info_t));
453 	if (attrp == NULL) {
454 		return (CKR_HOST_MEMORY);
455 	}
456 
457 	/* Set up attribute_info struct. */
458 	attrp->attr.type = template->type;
459 	attrp->attr.ulValueLen = template->ulValueLen;
460 
461 	if ((template->pValue != NULL) &&
462 	    (template->ulValueLen > 0)) {
463 		/* Allocate storage for the value of the attribute. */
464 		attrp->attr.pValue = malloc(template->ulValueLen);
465 		if (attrp->attr.pValue == NULL) {
466 			free(attrp);
467 			return (CKR_HOST_MEMORY);
468 		}
469 
470 		(void) memcpy(attrp->attr.pValue, template->pValue,
471 		    template->ulValueLen);
472 	} else {
473 		attrp->attr.pValue = NULL;
474 	}
475 
476 	/* Insert the new attribute in front of extra attribute list. */
477 	if (object_p->extra_attrlistp == NULL) {
478 		object_p->extra_attrlistp = attrp;
479 		attrp->next = NULL;
480 	} else {
481 		attrp->next = object_p->extra_attrlistp;
482 		object_p->extra_attrlistp = attrp;
483 	}
484 
485 	return (CKR_OK);
486 }
487 
488 CK_RV
489 soft_copy_certificate(certificate_obj_t *oldcert, certificate_obj_t **newcert,
490 		CK_CERTIFICATE_TYPE type)
491 {
492 	CK_RV rv = CKR_OK;
493 	certificate_obj_t	*cert;
494 	x509_cert_t		x509;
495 	x509_attr_cert_t	x509_attr;
496 
497 	cert = calloc(1, sizeof (certificate_obj_t));
498 	if (cert == NULL) {
499 		return (CKR_HOST_MEMORY);
500 	}
501 
502 	if (type == CKC_X_509) {
503 		x509 = oldcert->cert_type_u.x509;
504 		if (x509.subject)
505 			if ((rv = copy_cert_attr(x509.subject,
506 					&cert->cert_type_u.x509.subject)))
507 				return (rv);
508 		if (x509.value)
509 			if ((rv = copy_cert_attr(x509.value,
510 					&cert->cert_type_u.x509.value)))
511 				return (rv);
512 	} else if (type == CKC_X_509_ATTR_CERT) {
513 		x509_attr = oldcert->cert_type_u.x509_attr;
514 		if (x509_attr.owner)
515 			if ((rv = copy_cert_attr(x509_attr.owner,
516 					&cert->cert_type_u.x509_attr.owner)))
517 				return (rv);
518 		if (x509_attr.value)
519 			if ((rv = copy_cert_attr(x509_attr.value,
520 					&cert->cert_type_u.x509_attr.value)))
521 				return (rv);
522 	} else {
523 		/* wrong certificate type */
524 		rv = CKR_ATTRIBUTE_TYPE_INVALID;
525 	}
526 	if (rv == CKR_OK)
527 		*newcert = cert;
528 	return (rv);
529 }
530 
531 /*
532  * Copy the attribute_info struct from the old object to a new attribute_info
533  * struct, and add that new struct to the extra attribute list of the new
534  * object.
535  */
536 CK_RV
537 soft_copy_extra_attr(CK_ATTRIBUTE_INFO_PTR old_attrp, soft_object_t *object_p)
538 {
539 	CK_ATTRIBUTE_INFO_PTR attrp;
540 
541 	/* Allocate attribute_info struct. */
542 	attrp = calloc(1, sizeof (attribute_info_t));
543 	if (attrp == NULL) {
544 		return (CKR_HOST_MEMORY);
545 	}
546 
547 	attrp->attr.type = old_attrp->attr.type;
548 	attrp->attr.ulValueLen = old_attrp->attr.ulValueLen;
549 
550 	if ((old_attrp->attr.pValue != NULL) &&
551 		(old_attrp->attr.ulValueLen > 0)) {
552 		attrp->attr.pValue = malloc(old_attrp->attr.ulValueLen);
553 		if (attrp->attr.pValue == NULL) {
554 			free(attrp);
555 			return (CKR_HOST_MEMORY);
556 		}
557 
558 		(void) memcpy(attrp->attr.pValue, old_attrp->attr.pValue,
559 		    old_attrp->attr.ulValueLen);
560 	} else {
561 		attrp->attr.pValue = NULL;
562 	}
563 
564 	/* Insert the new attribute in front of extra attribute list */
565 	if (object_p->extra_attrlistp == NULL) {
566 		object_p->extra_attrlistp = attrp;
567 		attrp->next = NULL;
568 	} else {
569 		attrp->next = object_p->extra_attrlistp;
570 		object_p->extra_attrlistp = attrp;
571 	}
572 
573 	return (CKR_OK);
574 }
575 
576 
577 /*
578  * Get the attribute triple from the extra attribute list in the object
579  * (if the specified attribute type is found), and copy it to a template.
580  * Note the type of the attribute to be copied is specified by the template,
581  * and the storage is pre-allocated for the atrribute value in the template
582  * for doing the copy.
583  */
584 CK_RV
585 get_extra_attr_from_object(soft_object_t *object_p, CK_ATTRIBUTE_PTR template)
586 {
587 
588 	CK_ATTRIBUTE_INFO_PTR extra_attr;
589 	CK_ATTRIBUTE_TYPE type = template->type;
590 
591 	extra_attr = object_p->extra_attrlistp;
592 
593 	while (extra_attr) {
594 		if (type == extra_attr->attr.type) {
595 			/* Found it. */
596 			break;
597 		} else {
598 			/* Does not match, try next one. */
599 			extra_attr = extra_attr->next;
600 		}
601 	}
602 
603 	if (extra_attr == NULL) {
604 		/* A valid but un-initialized attribute. */
605 		template->ulValueLen = 0;
606 		return (CKR_OK);
607 	}
608 
609 	/*
610 	 * We found the attribute in the extra attribute list.
611 	 */
612 	if (template->pValue == NULL) {
613 		template->ulValueLen = extra_attr->attr.ulValueLen;
614 		return (CKR_OK);
615 	}
616 
617 	if (template->ulValueLen >= extra_attr->attr.ulValueLen) {
618 		/*
619 		 * The buffer provided by the application is large
620 		 * enough to hold the value of the attribute.
621 		 */
622 		(void) memcpy(template->pValue, extra_attr->attr.pValue,
623 		    extra_attr->attr.ulValueLen);
624 		template->ulValueLen = extra_attr->attr.ulValueLen;
625 		return (CKR_OK);
626 	} else {
627 		/*
628 		 * The buffer provided by the application does
629 		 * not have enough space to hold the value.
630 		 */
631 		template->ulValueLen = (CK_ULONG)-1;
632 		return (CKR_BUFFER_TOO_SMALL);
633 	}
634 }
635 
636 
637 /*
638  * Modify the attribute triple in the extra attribute list of the object
639  * if the specified attribute type is found. Otherwise, just add it to
640  * list.
641  */
642 CK_RV
643 set_extra_attr_to_object(soft_object_t *object_p, CK_ATTRIBUTE_TYPE type,
644 	CK_ATTRIBUTE_PTR template)
645 {
646 
647 	CK_ATTRIBUTE_INFO_PTR extra_attr;
648 
649 	extra_attr = object_p->extra_attrlistp;
650 
651 	while (extra_attr) {
652 		if (type == extra_attr->attr.type) {
653 			/* Found it. */
654 			break;
655 		} else {
656 			/* Does not match, try next one. */
657 			extra_attr = extra_attr->next;
658 		}
659 	}
660 
661 	if (extra_attr == NULL) {
662 		/*
663 		 * This attribute is a new one, go ahead adding it to
664 		 * the extra attribute list.
665 		 */
666 		return (soft_add_extra_attr(template, object_p));
667 	}
668 
669 	/* We found the attribute in the extra attribute list. */
670 	if ((template->pValue != NULL) &&
671 	    (template->ulValueLen > 0)) {
672 		if (template->ulValueLen > extra_attr->attr.ulValueLen) {
673 			/* The old buffer is too small to hold the new value. */
674 			if (extra_attr->attr.pValue != NULL)
675 				/* Free storage for the old attribute value. */
676 				free(extra_attr->attr.pValue);
677 
678 			/* Allocate storage for the new attribute value. */
679 			extra_attr->attr.pValue = malloc(template->ulValueLen);
680 			if (extra_attr->attr.pValue == NULL) {
681 				return (CKR_HOST_MEMORY);
682 			}
683 		}
684 
685 		/* Replace the attribute with new value. */
686 		extra_attr->attr.ulValueLen = template->ulValueLen;
687 		(void) memcpy(extra_attr->attr.pValue, template->pValue,
688 		    template->ulValueLen);
689 	} else {
690 		extra_attr->attr.pValue = NULL;
691 	}
692 
693 	return (CKR_OK);
694 }
695 
696 
697 /*
698  * Copy the big integer attribute value from template to a biginteger_t struct.
699  */
700 CK_RV
701 get_bigint_attr_from_template(biginteger_t *big, CK_ATTRIBUTE_PTR template)
702 {
703 
704 	if ((template->pValue != NULL) &&
705 	    (template->ulValueLen > 0)) {
706 		/* Allocate storage for the value of the attribute. */
707 		big->big_value = malloc(template->ulValueLen);
708 		if (big->big_value == NULL) {
709 			return (CKR_HOST_MEMORY);
710 		}
711 
712 		(void) memcpy(big->big_value, template->pValue,
713 		    template->ulValueLen);
714 		big->big_value_len = template->ulValueLen;
715 	} else {
716 		big->big_value = NULL;
717 		big->big_value_len = 0;
718 	}
719 
720 	return (CKR_OK);
721 }
722 
723 
724 /*
725  * Copy the big integer attribute value from a biginteger_t struct in the
726  * object to a template.
727  */
728 CK_RV
729 get_bigint_attr_from_object(biginteger_t *big, CK_ATTRIBUTE_PTR template)
730 {
731 
732 	if (template->pValue == NULL) {
733 		template->ulValueLen = big->big_value_len;
734 		return (CKR_OK);
735 	}
736 
737 	if (big->big_value == NULL) {
738 		template->ulValueLen = 0;
739 		return (CKR_OK);
740 	}
741 
742 	if (template->ulValueLen >= big->big_value_len) {
743 		/*
744 		 * The buffer provided by the application is large
745 		 * enough to hold the value of the attribute.
746 		 */
747 		(void) memcpy(template->pValue, big->big_value,
748 		    big->big_value_len);
749 		template->ulValueLen = big->big_value_len;
750 		return (CKR_OK);
751 	} else {
752 		/*
753 		 * The buffer provided by the application does
754 		 * not have enough space to hold the value.
755 		 */
756 		template->ulValueLen = (CK_ULONG)-1;
757 		return (CKR_BUFFER_TOO_SMALL);
758 	}
759 }
760 
761 
762 /*
763  * Copy the boolean data type attribute value from an object for the
764  * specified attribute to the template.
765  */
766 CK_RV
767 get_bool_attr_from_object(soft_object_t *object_p, CK_ULONG bool_flag,
768 	CK_ATTRIBUTE_PTR template)
769 {
770 
771 	if (template->pValue == NULL) {
772 		template->ulValueLen = sizeof (CK_BBOOL);
773 		return (CKR_OK);
774 	}
775 
776 	if (template->ulValueLen >= sizeof (CK_BBOOL)) {
777 		/*
778 		 * The buffer provided by the application is large
779 		 * enough to hold the value of the attribute.
780 		 */
781 		if (object_p->bool_attr_mask & bool_flag) {
782 			*((CK_BBOOL *)template->pValue) = B_TRUE;
783 		} else {
784 			*((CK_BBOOL *)template->pValue) = B_FALSE;
785 		}
786 
787 		template->ulValueLen = sizeof (CK_BBOOL);
788 		return (CKR_OK);
789 	} else {
790 		/*
791 		 * The buffer provided by the application does
792 		 * not have enough space to hold the value.
793 		 */
794 		template->ulValueLen = (CK_ULONG)-1;
795 		return (CKR_BUFFER_TOO_SMALL);
796 	}
797 }
798 
799 /*
800  * Set the boolean data type attribute value in the object.
801  */
802 CK_RV
803 set_bool_attr_to_object(soft_object_t *object_p, CK_ULONG bool_flag,
804 	CK_ATTRIBUTE_PTR template)
805 {
806 
807 	if (*(CK_BBOOL *)template->pValue)
808 		object_p->bool_attr_mask |= bool_flag;
809 	else
810 		object_p->bool_attr_mask &= ~bool_flag;
811 
812 	return (CKR_OK);
813 }
814 
815 
816 /*
817  * Copy the CK_ULONG data type attribute value from an object to the
818  * template.
819  */
820 CK_RV
821 get_ulong_attr_from_object(CK_ULONG value, CK_ATTRIBUTE_PTR template)
822 {
823 
824 	if (template->pValue == NULL) {
825 		template->ulValueLen = sizeof (CK_ULONG);
826 		return (CKR_OK);
827 	}
828 
829 	if (template->ulValueLen >= sizeof (CK_ULONG)) {
830 		/*
831 		 * The buffer provided by the application is large
832 		 * enough to hold the value of the attribute.
833 		 * It is also assumed to be correctly aligned.
834 		 */
835 		*(CK_ULONG_PTR)template->pValue = value;
836 		template->ulValueLen = sizeof (CK_ULONG);
837 		return (CKR_OK);
838 	} else {
839 		/*
840 		 * The buffer provided by the application does
841 		 * not have enough space to hold the value.
842 		 */
843 		template->ulValueLen = (CK_ULONG)-1;
844 		return (CKR_BUFFER_TOO_SMALL);
845 	}
846 }
847 
848 
849 /*
850  * Copy the CK_ULONG data type attribute value from a template to the
851  * object.
852  */
853 void
854 get_ulong_attr_from_template(CK_ULONG *value, CK_ATTRIBUTE_PTR template)
855 {
856 
857 	if (template->pValue != NULL) {
858 		*value = *(CK_ULONG_PTR)template->pValue;
859 	} else {
860 		*value = 0;
861 	}
862 }
863 
864 /*
865  * Copy the big integer attribute value from source's biginteger_t to
866  * destination's biginteger_t.
867  */
868 void
869 copy_bigint_attr(biginteger_t *src, biginteger_t *dst)
870 {
871 
872 	if ((src->big_value != NULL) &&
873 	    (src->big_value_len > 0)) {
874 		/*
875 		 * To do the copy, just have dst's big_value points
876 		 * to src's.
877 		 */
878 		dst->big_value = src->big_value;
879 		dst->big_value_len = src->big_value_len;
880 
881 		/*
882 		 * After the copy, nullify the src's big_value pointer.
883 		 * It prevents any double freeing the value.
884 		 */
885 		src->big_value = NULL;
886 		src->big_value_len = 0;
887 	} else {
888 		dst->big_value = NULL;
889 		dst->big_value_len = 0;
890 	}
891 }
892 
893 CK_RV
894 get_string_from_template(CK_ATTRIBUTE_PTR dest, CK_ATTRIBUTE_PTR src)
895 {
896 	if ((src->pValue != NULL) &&
897 	    (src->ulValueLen > 0)) {
898 		/* Allocate storage for the value of the attribute. */
899 		dest->pValue = malloc(src->ulValueLen);
900 		if (dest->pValue == NULL) {
901 			return (CKR_HOST_MEMORY);
902 		}
903 
904 		(void) memcpy(dest->pValue, src->pValue,
905 		    src->ulValueLen);
906 		dest->ulValueLen = src->ulValueLen;
907 		dest->type = src->type;
908 	} else {
909 		dest->pValue = NULL;
910 		dest->ulValueLen = 0;
911 		dest->type = src->type;
912 	}
913 
914 	return (CKR_OK);
915 
916 }
917 
918 CK_RV
919 get_cert_attr_from_template(cert_attr_t **dest, CK_ATTRIBUTE_PTR src)
920 {
921 	if (src->pValue != NULL && src->ulValueLen > 0) {
922 		/*
923 		 * If the attribute was already set, clear out the
924 		 * existing value and release the memory.
925 		 */
926 		if (*dest != NULL) {
927 			if ((*dest)->value != NULL) {
928 				(void) memset((*dest)->value, 0,
929 					(*dest)->length);
930 				free((*dest)->value);
931 			}
932 		} else {
933 			*dest = malloc(sizeof (cert_attr_t));
934 			if (*dest == NULL) {
935 				return (CKR_HOST_MEMORY);
936 			}
937 			(void) memset(*dest, 0, sizeof (cert_attr_t));
938 		}
939 		(*dest)->value = malloc(src->ulValueLen);
940 		if ((*dest)->value == NULL) {
941 			free(*dest);
942 			*dest = NULL;
943 			return (CKR_HOST_MEMORY);
944 		}
945 		(void) memcpy((*dest)->value, src->pValue, src->ulValueLen);
946 		(*dest)->length = src->ulValueLen;
947 	}
948 
949 	return (CKR_OK);
950 }
951 
952 /*
953  * Copy the certificate attribute information to the template.
954  * If the template attribute is not big enough, set the ulValueLen=-1
955  * and return CKR_BUFFER_TOO_SMALL.
956  */
957 static CK_RV
958 get_cert_attr_from_object(cert_attr_t *src, CK_ATTRIBUTE_PTR template)
959 {
960 	if (template->pValue == NULL) {
961 		template->ulValueLen = src->length;
962 		return (CKR_OK);
963 	} else if (template->ulValueLen >= src->length) {
964 		/*
965 		 * The buffer provided by the application is large
966 		 * enough to hold the value of the attribute.
967 		 */
968 		(void) memcpy(template->pValue, src->value, src->length);
969 		template->ulValueLen = src->length;
970 		return (CKR_OK);
971 	} else {
972 		/*
973 		 * The buffer provided by the application does
974 		 * not have enough space to hold the value.
975 		 */
976 		template->ulValueLen = (CK_ULONG)-1;
977 		return (CKR_BUFFER_TOO_SMALL);
978 	}
979 }
980 
981 void
982 string_attr_cleanup(CK_ATTRIBUTE_PTR template)
983 {
984 
985 	if (template->pValue) {
986 		free(template->pValue);
987 		template->pValue = NULL;
988 		template->ulValueLen = 0;
989 	}
990 }
991 
992 /*
993  * Release the storage allocated for object attribute with big integer
994  * value.
995  */
996 void
997 bigint_attr_cleanup(biginteger_t *big)
998 {
999 
1000 	if (big == NULL)
1001 		return;
1002 
1003 	if (big->big_value) {
1004 		(void) memset(big->big_value, 0, big->big_value_len);
1005 		free(big->big_value);
1006 		big->big_value = NULL;
1007 		big->big_value_len = 0;
1008 	}
1009 }
1010 
1011 
1012 /*
1013  * Clean up and release all the storage allocated to hold the big integer
1014  * attributes associated with the type (i.e. class) of the object. Also,
1015  * release the storage allocated to the type of the object.
1016  */
1017 void
1018 soft_cleanup_object_bigint_attrs(soft_object_t *object_p)
1019 {
1020 
1021 	CK_OBJECT_CLASS class = object_p->class;
1022 	CK_KEY_TYPE	keytype = object_p->key_type;
1023 
1024 
1025 	switch (class) {
1026 	case CKO_PUBLIC_KEY:
1027 		if (OBJ_PUB(object_p)) {
1028 			switch (keytype) {
1029 			case CKK_RSA:
1030 				bigint_attr_cleanup(OBJ_PUB_RSA_MOD(
1031 				    object_p));
1032 				bigint_attr_cleanup(OBJ_PUB_RSA_PUBEXPO(
1033 				    object_p));
1034 				break;
1035 
1036 			case CKK_DSA:
1037 				bigint_attr_cleanup(OBJ_PUB_DSA_PRIME(
1038 				    object_p));
1039 				bigint_attr_cleanup(OBJ_PUB_DSA_SUBPRIME(
1040 				    object_p));
1041 				bigint_attr_cleanup(OBJ_PUB_DSA_BASE(
1042 				    object_p));
1043 				bigint_attr_cleanup(OBJ_PUB_DSA_VALUE(
1044 				    object_p));
1045 				break;
1046 
1047 			case CKK_DH:
1048 				bigint_attr_cleanup(OBJ_PUB_DH_PRIME(
1049 				    object_p));
1050 				bigint_attr_cleanup(OBJ_PUB_DH_BASE(
1051 				    object_p));
1052 				bigint_attr_cleanup(OBJ_PUB_DH_VALUE(
1053 				    object_p));
1054 				break;
1055 
1056 			case CKK_X9_42_DH:
1057 				bigint_attr_cleanup(OBJ_PUB_DH942_PRIME(
1058 				    object_p));
1059 				bigint_attr_cleanup(OBJ_PUB_DH942_BASE(
1060 				    object_p));
1061 				bigint_attr_cleanup(OBJ_PUB_DH942_SUBPRIME(
1062 				    object_p));
1063 				bigint_attr_cleanup(OBJ_PUB_DH942_VALUE(
1064 				    object_p));
1065 				break;
1066 			}
1067 
1068 			/* Release Public Key Object struct */
1069 			free(OBJ_PUB(object_p));
1070 			OBJ_PUB(object_p) = NULL;
1071 		}
1072 		break;
1073 
1074 	case CKO_PRIVATE_KEY:
1075 		if (OBJ_PRI(object_p)) {
1076 			switch (keytype) {
1077 			case CKK_RSA:
1078 				bigint_attr_cleanup(OBJ_PRI_RSA_MOD(
1079 				    object_p));
1080 				bigint_attr_cleanup(OBJ_PRI_RSA_PUBEXPO(
1081 				    object_p));
1082 				bigint_attr_cleanup(OBJ_PRI_RSA_PRIEXPO(
1083 				    object_p));
1084 				bigint_attr_cleanup(OBJ_PRI_RSA_PRIME1(
1085 				    object_p));
1086 				bigint_attr_cleanup(OBJ_PRI_RSA_PRIME2(
1087 				    object_p));
1088 				bigint_attr_cleanup(OBJ_PRI_RSA_EXPO1(
1089 				    object_p));
1090 				bigint_attr_cleanup(OBJ_PRI_RSA_EXPO2(
1091 				    object_p));
1092 				bigint_attr_cleanup(OBJ_PRI_RSA_COEF(
1093 				    object_p));
1094 				break;
1095 
1096 			case CKK_DSA:
1097 				bigint_attr_cleanup(OBJ_PRI_DSA_PRIME(
1098 				    object_p));
1099 				bigint_attr_cleanup(OBJ_PRI_DSA_SUBPRIME(
1100 				    object_p));
1101 				bigint_attr_cleanup(OBJ_PRI_DSA_BASE(
1102 				    object_p));
1103 				bigint_attr_cleanup(OBJ_PRI_DSA_VALUE(
1104 				    object_p));
1105 				break;
1106 
1107 			case CKK_DH:
1108 				bigint_attr_cleanup(OBJ_PRI_DH_PRIME(
1109 				    object_p));
1110 				bigint_attr_cleanup(OBJ_PRI_DH_BASE(
1111 				    object_p));
1112 				bigint_attr_cleanup(OBJ_PRI_DH_VALUE(
1113 				    object_p));
1114 				break;
1115 
1116 			case CKK_X9_42_DH:
1117 				bigint_attr_cleanup(OBJ_PRI_DH942_PRIME(
1118 				    object_p));
1119 				bigint_attr_cleanup(OBJ_PRI_DH942_BASE(
1120 				    object_p));
1121 				bigint_attr_cleanup(OBJ_PRI_DH942_SUBPRIME(
1122 				    object_p));
1123 				bigint_attr_cleanup(OBJ_PRI_DH942_VALUE(
1124 				    object_p));
1125 				break;
1126 			}
1127 
1128 			/* Release Private Key Object struct. */
1129 			free(OBJ_PRI(object_p));
1130 			OBJ_PRI(object_p) = NULL;
1131 		}
1132 		break;
1133 
1134 	case CKO_SECRET_KEY:
1135 		if (OBJ_SEC(object_p)) {
1136 			/* cleanup key data area */
1137 			if (OBJ_SEC_VALUE(object_p) != NULL &&
1138 			    OBJ_SEC_VALUE_LEN(object_p) > 0) {
1139 				(void) memset(OBJ_SEC_VALUE(object_p), 0,
1140 					OBJ_SEC_VALUE_LEN(object_p));
1141 				free(OBJ_SEC_VALUE(object_p));
1142 			}
1143 			/* cleanup key schedule data area */
1144 			if (OBJ_KEY_SCHED(object_p) != NULL &&
1145 			    OBJ_KEY_SCHED_LEN(object_p) > 0) {
1146 				(void) memset(OBJ_KEY_SCHED(object_p), 0,
1147 					OBJ_KEY_SCHED_LEN(object_p));
1148 				free(OBJ_KEY_SCHED(object_p));
1149 			}
1150 
1151 			/* Release Secret Key Object struct. */
1152 			free(OBJ_SEC(object_p));
1153 			OBJ_SEC(object_p) = NULL;
1154 		}
1155 		break;
1156 
1157 	case CKO_DOMAIN_PARAMETERS:
1158 		if (OBJ_DOM(object_p)) {
1159 			switch (keytype) {
1160 			case CKK_DSA:
1161 				bigint_attr_cleanup(OBJ_DOM_DSA_PRIME(
1162 				    object_p));
1163 				bigint_attr_cleanup(OBJ_DOM_DSA_SUBPRIME(
1164 				    object_p));
1165 				bigint_attr_cleanup(OBJ_DOM_DSA_BASE(
1166 				    object_p));
1167 				break;
1168 
1169 			case CKK_DH:
1170 				bigint_attr_cleanup(OBJ_DOM_DH_PRIME(
1171 				    object_p));
1172 				bigint_attr_cleanup(OBJ_DOM_DH_BASE(
1173 				    object_p));
1174 				break;
1175 
1176 			case CKK_X9_42_DH:
1177 				bigint_attr_cleanup(OBJ_DOM_DH942_PRIME(
1178 				    object_p));
1179 				bigint_attr_cleanup(OBJ_DOM_DH942_BASE(
1180 				    object_p));
1181 				bigint_attr_cleanup(OBJ_DOM_DH942_SUBPRIME(
1182 				    object_p));
1183 				break;
1184 			}
1185 
1186 			/* Release Domain Parameters Object struct. */
1187 			free(OBJ_DOM(object_p));
1188 			OBJ_DOM(object_p) = NULL;
1189 		}
1190 		break;
1191 	}
1192 }
1193 
1194 
1195 /*
1196  * Parse the common attributes. Return to caller with appropriate return
1197  * value to indicate if the supplied template specifies a valid attribute
1198  * with a valid value.
1199  */
1200 CK_RV
1201 soft_parse_common_attrs(CK_ATTRIBUTE_PTR template, uchar_t *object_type)
1202 {
1203 
1204 	CK_RV rv = CKR_OK;
1205 
1206 	switch (template->type) {
1207 	case CKA_CLASS:
1208 		break;
1209 
1210 	/* default boolean attributes */
1211 	case CKA_TOKEN:
1212 		if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
1213 			if (!soft_token_present)
1214 				return (CKR_DEVICE_REMOVED);
1215 			*object_type |= TOKEN_OBJECT;
1216 		}
1217 		break;
1218 
1219 	case CKA_PRIVATE:
1220 		if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
1221 			(void) pthread_mutex_lock(&soft_giant_mutex);
1222 			if (!soft_slot.authenticated) {
1223 				/*
1224 				 * Check if this is the special case when
1225 				 * the PIN is never initialized in the keystore.
1226 				 * If true, we will let it pass here and let
1227 				 * it fail with CKR_PIN_EXPIRED later on.
1228 				 */
1229 				if (!soft_slot.userpin_change_needed) {
1230 					(void) pthread_mutex_unlock(
1231 					    &soft_giant_mutex);
1232 					return (CKR_USER_NOT_LOGGED_IN);
1233 				}
1234 			}
1235 			(void) pthread_mutex_unlock(&soft_giant_mutex);
1236 			*object_type |= PRIVATE_OBJECT;
1237 		}
1238 		break;
1239 
1240 	case CKA_LABEL:
1241 		break;
1242 
1243 	default:
1244 		rv = CKR_TEMPLATE_INCONSISTENT;
1245 	}
1246 
1247 	return (rv);
1248 }
1249 
1250 
1251 /*
1252  * Build a Public Key Object.
1253  *
1254  * - Parse the object's template, and when an error is detected such as
1255  *   invalid attribute type, invalid attribute value, etc., return
1256  *   with appropriate return value.
1257  * - Set up attribute mask field in the object for the supplied common
1258  *   attributes that have boolean type.
1259  * - Build the attribute_info struct to hold the value of each supplied
1260  *   attribute that has byte array type. Link attribute_info structs
1261  *   together to form the extra attribute list of the object.
1262  * - Allocate storage for the Public Key object.
1263  * - Build the Public Key object according to the key type. Allocate
1264  *   storage to hold the big integer value for the supplied attributes
1265  *   that are required for a certain key type.
1266  *
1267  */
1268 CK_RV
1269 soft_build_public_key_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
1270 	soft_object_t *new_object, CK_ULONG mode, CK_KEY_TYPE key_type)
1271 {
1272 
1273 	ulong_t		i;
1274 	CK_KEY_TYPE	keytype = (CK_KEY_TYPE)~0UL;
1275 	uint64_t	attr_mask = PUBLIC_KEY_DEFAULT;
1276 	CK_RV 		rv = CKR_OK;
1277 	int		isLabel = 0;
1278 	/* Must set flags */
1279 	int		isModulus = 0;
1280 	int		isPubExpo = 0;
1281 	int		isPrime = 0;
1282 	int		isSubprime = 0;
1283 	int		isBase = 0;
1284 	int		isValue = 0;
1285 	/* Must not set flags */
1286 	int		isModulusBits = 0;
1287 	CK_ULONG	modulus_bits = 0;
1288 
1289 	biginteger_t	modulus;
1290 	biginteger_t	pubexpo;
1291 	biginteger_t	prime;
1292 	biginteger_t	subprime;
1293 	biginteger_t	base;
1294 	biginteger_t	value;
1295 	CK_ATTRIBUTE	string_tmp;
1296 
1297 	public_key_obj_t  *pbk;
1298 	uchar_t	object_type = 0;
1299 
1300 	/* prevent bigint_attr_cleanup from freeing invalid attr value */
1301 	(void) memset(&modulus, 0x0, sizeof (biginteger_t));
1302 	(void) memset(&pubexpo, 0x0, sizeof (biginteger_t));
1303 	(void) memset(&prime, 0x0, sizeof (biginteger_t));
1304 	(void) memset(&subprime, 0x0, sizeof (biginteger_t));
1305 	(void) memset(&base, 0x0, sizeof (biginteger_t));
1306 	(void) memset(&value, 0x0, sizeof (biginteger_t));
1307 	string_tmp.pValue = NULL;
1308 
1309 	for (i = 0; i < ulAttrNum; i++) {
1310 
1311 		/* Public Key Object Attributes */
1312 		switch (template[i].type) {
1313 
1314 		/* common key attributes */
1315 		case CKA_KEY_TYPE:
1316 			keytype = *((CK_KEY_TYPE*)template[i].pValue);
1317 			break;
1318 
1319 		case CKA_ID:
1320 		case CKA_START_DATE:
1321 		case CKA_END_DATE:
1322 
1323 		/* common public key attribute */
1324 		case CKA_SUBJECT:
1325 			/*
1326 			 * Allocate storage to hold the attribute
1327 			 * value with byte array type, and add it to
1328 			 * the extra attribute list of the object.
1329 			 */
1330 			rv = soft_add_extra_attr(&template[i],
1331 			    new_object);
1332 			if (rv != CKR_OK) {
1333 				goto fail_cleanup;
1334 			}
1335 			break;
1336 
1337 		/*
1338 		 * The following key related attribute types must
1339 		 * not be specified by C_CreateObject, C_GenerateKey(Pair).
1340 		 */
1341 		case CKA_LOCAL:
1342 		case CKA_KEY_GEN_MECHANISM:
1343 			rv = CKR_TEMPLATE_INCONSISTENT;
1344 			goto fail_cleanup;
1345 
1346 		/* Key related boolean attributes */
1347 		case CKA_DERIVE:
1348 			if (*(CK_BBOOL *)template[i].pValue)
1349 				attr_mask |= DERIVE_BOOL_ON;
1350 			break;
1351 
1352 		case CKA_ENCRYPT:
1353 			if (*(CK_BBOOL *)template[i].pValue)
1354 				attr_mask |= ENCRYPT_BOOL_ON;
1355 			else
1356 				attr_mask &= ~ENCRYPT_BOOL_ON;
1357 			break;
1358 
1359 		case CKA_VERIFY:
1360 			if (*(CK_BBOOL *)template[i].pValue)
1361 				attr_mask |= VERIFY_BOOL_ON;
1362 			else
1363 				attr_mask &= ~VERIFY_BOOL_ON;
1364 			break;
1365 
1366 		case CKA_VERIFY_RECOVER:
1367 			if (*(CK_BBOOL *)template[i].pValue)
1368 				attr_mask |= VERIFY_RECOVER_BOOL_ON;
1369 			else
1370 				attr_mask &= ~VERIFY_RECOVER_BOOL_ON;
1371 			break;
1372 
1373 		case CKA_WRAP:
1374 			if (*(CK_BBOOL *)template[i].pValue)
1375 				attr_mask |= WRAP_BOOL_ON;
1376 			else
1377 				attr_mask &= ~WRAP_BOOL_ON;
1378 			break;
1379 
1380 		case CKA_TRUSTED:
1381 			if (*(CK_BBOOL *)template[i].pValue)
1382 				attr_mask |= TRUSTED_BOOL_ON;
1383 			break;
1384 
1385 		case CKA_MODIFIABLE:
1386 			if ((*(CK_BBOOL *)template[i].pValue) == B_FALSE)
1387 				attr_mask |= NOT_MODIFIABLE_BOOL_ON;
1388 			break;
1389 
1390 		/*
1391 		 * The following key related attribute types must
1392 		 * be specified according to the key type by
1393 		 * C_CreateObject.
1394 		 */
1395 		case CKA_MODULUS:
1396 
1397 			isModulus = 1;
1398 			/*
1399 			 * Copyin big integer attribute from template
1400 			 * to a local variable.
1401 			 */
1402 			rv = get_bigint_attr_from_template(&modulus,
1403 			    &template[i]);
1404 			if (rv != CKR_OK)
1405 				goto fail_cleanup;
1406 
1407 			/*
1408 			 * Modulus length needs to be between min key length and
1409 			 * max key length.
1410 			 */
1411 			if ((modulus.big_value_len <
1412 			    MIN_RSA_KEYLENGTH_IN_BYTES) ||
1413 			    (modulus.big_value_len >
1414 			    MAX_RSA_KEYLENGTH_IN_BYTES)) {
1415 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
1416 				goto fail_cleanup;
1417 			}
1418 			break;
1419 
1420 		case CKA_PUBLIC_EXPONENT:
1421 			isPubExpo = 1;
1422 			rv = get_bigint_attr_from_template(&pubexpo,
1423 			    &template[i]);
1424 			if (rv != CKR_OK)
1425 				goto fail_cleanup;
1426 			break;
1427 
1428 		case CKA_PRIME:
1429 			isPrime = 1;
1430 			rv = get_bigint_attr_from_template(&prime,
1431 			    &template[i]);
1432 			if (rv != CKR_OK)
1433 				goto fail_cleanup;
1434 			break;
1435 
1436 		case CKA_SUBPRIME:
1437 			isSubprime = 1;
1438 			rv = get_bigint_attr_from_template(&subprime,
1439 			    &template[i]);
1440 			if (rv != CKR_OK)
1441 				goto fail_cleanup;
1442 			break;
1443 
1444 		case CKA_BASE:
1445 			isBase = 1;
1446 			rv = get_bigint_attr_from_template(&base,
1447 			    &template[i]);
1448 			if (rv != CKR_OK)
1449 				goto fail_cleanup;
1450 			break;
1451 
1452 		case CKA_VALUE:
1453 			isValue = 1;
1454 			if (mode == SOFT_CREATE_OBJ) {
1455 				if ((template[i].ulValueLen == 0) ||
1456 				    (template[i].pValue == NULL)) {
1457 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
1458 					goto fail_cleanup;
1459 			    }
1460 			}
1461 
1462 			rv = get_bigint_attr_from_template(&value,
1463 			    &template[i]);
1464 			if (rv != CKR_OK)
1465 				goto fail_cleanup;
1466 			break;
1467 
1468 		case CKA_MODULUS_BITS:
1469 			isModulusBits = 1;
1470 			get_ulong_attr_from_template(&modulus_bits,
1471 			    &template[i]);
1472 			break;
1473 
1474 		case CKA_LABEL:
1475 			isLabel = 1;
1476 			rv = get_string_from_template(&string_tmp,
1477 			    &template[i]);
1478 			if (rv != CKR_OK)
1479 				goto fail_cleanup;
1480 			break;
1481 
1482 		default:
1483 			rv = soft_parse_common_attrs(&template[i],
1484 			    &object_type);
1485 			if (rv != CKR_OK)
1486 				goto fail_cleanup;
1487 			break;
1488 		}
1489 	} /* For */
1490 
1491 	/* Allocate storage for Public Key Object. */
1492 	pbk = calloc(1, sizeof (public_key_obj_t));
1493 	if (pbk == NULL) {
1494 		rv = CKR_HOST_MEMORY;
1495 		goto fail_cleanup;
1496 	}
1497 
1498 	new_object->object_class_u.public_key = pbk;
1499 	new_object->class = CKO_PUBLIC_KEY;
1500 
1501 	if ((mode == SOFT_CREATE_OBJ) && (keytype == (CK_KEY_TYPE)~0UL)) {
1502 		rv = CKR_TEMPLATE_INCOMPLETE;
1503 		goto fail_cleanup;
1504 	}
1505 
1506 	if ((mode == SOFT_GEN_KEY) && (keytype == (CK_KEY_TYPE)~0UL)) {
1507 		keytype = key_type;
1508 	}
1509 
1510 	if ((mode == SOFT_GEN_KEY) && (keytype != key_type)) {
1511 		/*
1512 		 * The key type specified in the template does not
1513 		 * match the implied key type based on the mechanism.
1514 		 */
1515 		rv = CKR_TEMPLATE_INCONSISTENT;
1516 		goto fail_cleanup;
1517 	}
1518 
1519 	new_object->key_type = keytype;
1520 
1521 	/* Supported key types of the Public Key Object */
1522 	switch (keytype) {
1523 
1524 	case CKK_RSA:
1525 		if (mode == SOFT_CREATE_OBJ) {
1526 			if (isModulusBits || isPrime || isSubprime ||
1527 			    isBase || isValue) {
1528 				rv = CKR_TEMPLATE_INCONSISTENT;
1529 				goto fail_cleanup;
1530 			}
1531 
1532 			if (isModulus && isPubExpo) {
1533 				/*
1534 				 * Copy big integer attribute value to the
1535 				 * designated place in the public key object.
1536 				 */
1537 				copy_bigint_attr(&modulus,
1538 				    KEY_PUB_RSA_MOD(pbk));
1539 
1540 				copy_bigint_attr(&pubexpo,
1541 				    KEY_PUB_RSA_PUBEXPO(pbk));
1542 			} else {
1543 				rv = CKR_TEMPLATE_INCOMPLETE;
1544 				goto fail_cleanup;
1545 			}
1546 		} else {
1547 			if (isModulus || isPrime || isSubprime ||
1548 			    isBase || isValue) {
1549 				rv = CKR_TEMPLATE_INCONSISTENT;
1550 				goto fail_cleanup;
1551 			}
1552 
1553 			if (isModulusBits && isPubExpo) {
1554 				/*
1555 				 * Copy big integer attribute value to the
1556 				 * designated place in the public key object.
1557 				 */
1558 				copy_bigint_attr(&pubexpo,
1559 				    KEY_PUB_RSA_PUBEXPO(pbk));
1560 				KEY_PUB_RSA_MOD_BITS(pbk) = modulus_bits;
1561 			} else {
1562 				rv = CKR_TEMPLATE_INCOMPLETE;
1563 				goto fail_cleanup;
1564 			}
1565 		}
1566 
1567 		break;
1568 
1569 	case CKK_DSA:
1570 		if (mode == SOFT_CREATE_OBJ) {
1571 			if (isModulusBits || isModulus || isPubExpo) {
1572 				rv = CKR_TEMPLATE_INCONSISTENT;
1573 				goto fail_cleanup;
1574 			}
1575 
1576 			if (isPrime && isSubprime && isBase && isValue) {
1577 				copy_bigint_attr(&value,
1578 				    KEY_PUB_DSA_VALUE(pbk));
1579 			} else {
1580 				rv = CKR_TEMPLATE_INCOMPLETE;
1581 				goto fail_cleanup;
1582 			}
1583 		} else {
1584 			if (isModulusBits || isModulus || isPubExpo ||
1585 			    isValue) {
1586 				rv = CKR_TEMPLATE_INCONSISTENT;
1587 				goto fail_cleanup;
1588 			}
1589 
1590 			if (!(isPrime && isSubprime && isBase)) {
1591 				rv = CKR_TEMPLATE_INCOMPLETE;
1592 				goto fail_cleanup;
1593 			}
1594 		}
1595 
1596 		copy_bigint_attr(&prime, KEY_PUB_DSA_PRIME(pbk));
1597 
1598 		copy_bigint_attr(&subprime, KEY_PUB_DSA_SUBPRIME(pbk));
1599 
1600 		copy_bigint_attr(&base, KEY_PUB_DSA_BASE(pbk));
1601 
1602 		break;
1603 
1604 	case CKK_DH:
1605 		if (mode == SOFT_CREATE_OBJ) {
1606 			if (isModulusBits || isModulus || isPubExpo ||
1607 			    isSubprime) {
1608 				rv = CKR_TEMPLATE_INCONSISTENT;
1609 				goto fail_cleanup;
1610 			}
1611 
1612 			if (isPrime && isBase && isValue) {
1613 				copy_bigint_attr(&value,
1614 				    KEY_PUB_DH_VALUE(pbk));
1615 			} else {
1616 				rv = CKR_TEMPLATE_INCOMPLETE;
1617 				goto fail_cleanup;
1618 			}
1619 		} else {
1620 			if (isModulusBits || isModulus || isPubExpo ||
1621 			    isSubprime || isValue) {
1622 				rv = CKR_TEMPLATE_INCONSISTENT;
1623 				goto fail_cleanup;
1624 			}
1625 
1626 			if (!(isPrime && isBase)) {
1627 				rv = CKR_TEMPLATE_INCOMPLETE;
1628 				goto fail_cleanup;
1629 			}
1630 		}
1631 
1632 		copy_bigint_attr(&prime, KEY_PUB_DH_PRIME(pbk));
1633 
1634 		copy_bigint_attr(&base, KEY_PUB_DH_BASE(pbk));
1635 
1636 		break;
1637 
1638 	case CKK_X9_42_DH:
1639 		if (mode == SOFT_CREATE_OBJ) {
1640 			if (isModulusBits || isModulus || isPubExpo) {
1641 				rv = CKR_TEMPLATE_INCONSISTENT;
1642 				goto fail_cleanup;
1643 			}
1644 
1645 			if (isPrime && isSubprime && isBase && isValue) {
1646 				copy_bigint_attr(&value,
1647 				    KEY_PUB_DH942_VALUE(pbk));
1648 			} else {
1649 				rv = CKR_TEMPLATE_INCOMPLETE;
1650 				goto fail_cleanup;
1651 			}
1652 		} else {
1653 			if (isModulusBits || isModulus || isPubExpo ||
1654 			    isValue) {
1655 				rv = CKR_TEMPLATE_INCONSISTENT;
1656 				goto fail_cleanup;
1657 			}
1658 
1659 			if (!(isPrime && isSubprime && isBase)) {
1660 				rv = CKR_TEMPLATE_INCOMPLETE;
1661 				goto fail_cleanup;
1662 			}
1663 		}
1664 
1665 		copy_bigint_attr(&prime, KEY_PUB_DH942_PRIME(pbk));
1666 
1667 		copy_bigint_attr(&base, KEY_PUB_DH942_BASE(pbk));
1668 
1669 		copy_bigint_attr(&subprime, KEY_PUB_DH942_SUBPRIME(pbk));
1670 
1671 		break;
1672 
1673 	default:
1674 		rv = CKR_TEMPLATE_INCONSISTENT;
1675 		goto fail_cleanup;
1676 	}
1677 
1678 	/* Set up object. */
1679 	new_object->object_type = object_type;
1680 	new_object->bool_attr_mask = attr_mask;
1681 	if (isLabel) {
1682 		rv = soft_add_extra_attr(&string_tmp, new_object);
1683 		if (rv != CKR_OK)
1684 			goto fail_cleanup;
1685 		string_attr_cleanup(&string_tmp);
1686 	}
1687 
1688 	return (rv);
1689 
1690 fail_cleanup:
1691 	/*
1692 	 * cleanup the storage allocated to the local variables.
1693 	 */
1694 	bigint_attr_cleanup(&modulus);
1695 	bigint_attr_cleanup(&pubexpo);
1696 	bigint_attr_cleanup(&prime);
1697 	bigint_attr_cleanup(&subprime);
1698 	bigint_attr_cleanup(&base);
1699 	bigint_attr_cleanup(&value);
1700 	string_attr_cleanup(&string_tmp);
1701 
1702 	/*
1703 	 * cleanup the storage allocated inside the object itself.
1704 	 */
1705 	soft_cleanup_object(new_object);
1706 
1707 	return (rv);
1708 }
1709 
1710 
1711 /*
1712  * Build a Private Key Object.
1713  *
1714  * - Parse the object's template, and when an error is detected such as
1715  *   invalid attribute type, invalid attribute value, etc., return
1716  *   with appropriate return value.
1717  * - Set up attribute mask field in the object for the supplied common
1718  *   attributes that have boolean type.
1719  * - Build the attribute_info struct to hold the value of each supplied
1720  *   attribute that has byte array type. Link attribute_info structs
1721  *   together to form the extra attribute list of the object.
1722  * - Allocate storage for the Private Key object.
1723  * - Build the Private Key object according to the key type. Allocate
1724  *   storage to hold the big integer value for the supplied attributes
1725  *   that are required for a certain key type.
1726  *
1727  */
1728 CK_RV
1729 soft_build_private_key_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
1730 	soft_object_t *new_object, CK_ULONG mode, CK_KEY_TYPE key_type)
1731 {
1732 	ulong_t		i;
1733 	CK_KEY_TYPE	keytype = (CK_KEY_TYPE)~0UL;
1734 	uint64_t	attr_mask = PRIVATE_KEY_DEFAULT;
1735 	CK_RV 		rv = CKR_OK;
1736 	int		isLabel = 0;
1737 	/* Must set flags unless mode == SOFT_UNWRAP_KEY */
1738 	int		isModulus = 0;
1739 	int		isPriExpo = 0;
1740 	int		isPrime = 0;
1741 	int		isSubprime = 0;
1742 	int		isBase = 0;
1743 	/* Must set flags if mode == SOFT_GEN_KEY */
1744 	int		isValue = 0;
1745 	/* Must not set flags */
1746 	int		isValueBits = 0;
1747 	CK_ULONG	value_bits = 0;
1748 
1749 	/* Private Key RSA optional */
1750 	int		isPubExpo = 0;
1751 	int		isPrime1 = 0;
1752 	int		isPrime2 = 0;
1753 	int		isExpo1 = 0;
1754 	int		isExpo2 = 0;
1755 	int		isCoef = 0;
1756 
1757 	biginteger_t	modulus;
1758 	biginteger_t	priexpo;
1759 	biginteger_t	prime;
1760 	biginteger_t	subprime;
1761 	biginteger_t	base;
1762 	biginteger_t	value;
1763 
1764 	biginteger_t	pubexpo;
1765 	biginteger_t	prime1;
1766 	biginteger_t	prime2;
1767 	biginteger_t	expo1;
1768 	biginteger_t	expo2;
1769 	biginteger_t	coef;
1770 	CK_ATTRIBUTE	string_tmp;
1771 	BIGNUM	x, q;
1772 
1773 	private_key_obj_t *pvk;
1774 	uchar_t	object_type = 0;
1775 
1776 	/* prevent bigint_attr_cleanup from freeing invalid attr value */
1777 	(void) memset(&modulus, 0x0, sizeof (biginteger_t));
1778 	(void) memset(&priexpo, 0x0, sizeof (biginteger_t));
1779 	(void) memset(&prime, 0x0, sizeof (biginteger_t));
1780 	(void) memset(&subprime, 0x0, sizeof (biginteger_t));
1781 	(void) memset(&base, 0x0, sizeof (biginteger_t));
1782 	(void) memset(&value, 0x0, sizeof (biginteger_t));
1783 	(void) memset(&pubexpo, 0x0, sizeof (biginteger_t));
1784 	(void) memset(&prime1, 0x0, sizeof (biginteger_t));
1785 	(void) memset(&prime2, 0x0, sizeof (biginteger_t));
1786 	(void) memset(&expo1, 0x0, sizeof (biginteger_t));
1787 	(void) memset(&expo2, 0x0, sizeof (biginteger_t));
1788 	(void) memset(&coef, 0x0, sizeof (biginteger_t));
1789 	string_tmp.pValue = NULL;
1790 	x.malloced = 0;
1791 	q.malloced = 0;
1792 
1793 	for (i = 0; i < ulAttrNum; i++) {
1794 
1795 		/* Private Key Object Attributes */
1796 		switch (template[i].type) {
1797 
1798 		/* common key attributes */
1799 		case CKA_KEY_TYPE:
1800 			keytype = *((CK_KEY_TYPE*)template[i].pValue);
1801 			break;
1802 
1803 		case CKA_ID:
1804 		case CKA_START_DATE:
1805 		case CKA_END_DATE:
1806 
1807 		/* common private key attribute */
1808 		case CKA_SUBJECT:
1809 			/*
1810 			 * Allocate storage to hold the attribute
1811 			 * value with byte array type, and add it to
1812 			 * the extra attribute list of the object.
1813 			 */
1814 			rv = soft_add_extra_attr(&template[i],
1815 			    new_object);
1816 			if (rv != CKR_OK) {
1817 				goto fail_cleanup;
1818 			}
1819 			break;
1820 
1821 		/*
1822 		 * The following key related attribute types must
1823 		 * not be specified by C_CreateObject or C_GenerateKey(Pair).
1824 		 */
1825 		case CKA_LOCAL:
1826 		case CKA_KEY_GEN_MECHANISM:
1827 		case CKA_AUTH_PIN_FLAGS:
1828 		case CKA_ALWAYS_SENSITIVE:
1829 		case CKA_NEVER_EXTRACTABLE:
1830 			rv = CKR_TEMPLATE_INCONSISTENT;
1831 			goto fail_cleanup;
1832 
1833 		/* Key related boolean attributes */
1834 		case CKA_DERIVE:
1835 			if (*(CK_BBOOL *)template[i].pValue)
1836 				attr_mask |= DERIVE_BOOL_ON;
1837 			break;
1838 
1839 		case CKA_SENSITIVE:
1840 			if (*(CK_BBOOL *)template[i].pValue)
1841 				attr_mask |= SENSITIVE_BOOL_ON;
1842 			break;
1843 
1844 		case CKA_SECONDARY_AUTH:
1845 			if (*(CK_BBOOL *)template[i].pValue) {
1846 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
1847 				goto fail_cleanup;
1848 			}
1849 			break;
1850 
1851 		case CKA_DECRYPT:
1852 			if (*(CK_BBOOL *)template[i].pValue)
1853 				attr_mask |= DECRYPT_BOOL_ON;
1854 			else
1855 				attr_mask &= ~DECRYPT_BOOL_ON;
1856 			break;
1857 
1858 		case CKA_SIGN:
1859 			if (*(CK_BBOOL *)template[i].pValue)
1860 				attr_mask |= SIGN_BOOL_ON;
1861 			else
1862 				attr_mask &= ~SIGN_BOOL_ON;
1863 			break;
1864 
1865 		case CKA_SIGN_RECOVER:
1866 			if (*(CK_BBOOL *)template[i].pValue)
1867 				attr_mask |= SIGN_RECOVER_BOOL_ON;
1868 			else
1869 				attr_mask &= ~SIGN_RECOVER_BOOL_ON;
1870 			break;
1871 
1872 		case CKA_UNWRAP:
1873 			if (*(CK_BBOOL *)template[i].pValue)
1874 				attr_mask |= UNWRAP_BOOL_ON;
1875 			else
1876 				attr_mask &= ~UNWRAP_BOOL_ON;
1877 			break;
1878 
1879 		case CKA_EXTRACTABLE:
1880 			if (*(CK_BBOOL *)template[i].pValue)
1881 				attr_mask |= EXTRACTABLE_BOOL_ON;
1882 			else
1883 				attr_mask &= ~EXTRACTABLE_BOOL_ON;
1884 			break;
1885 
1886 		case CKA_MODIFIABLE:
1887 			if ((*(CK_BBOOL *)template[i].pValue) == B_FALSE)
1888 				attr_mask |= NOT_MODIFIABLE_BOOL_ON;
1889 			break;
1890 
1891 		/*
1892 		 * The following key related attribute types must
1893 		 * be specified according to the key type by
1894 		 * C_CreateObject.
1895 		 */
1896 		case CKA_MODULUS:
1897 
1898 			isModulus = 1;
1899 			/*
1900 			 * Copyin big integer attribute from template
1901 			 * to a local variable.
1902 			 */
1903 			rv = get_bigint_attr_from_template(&modulus,
1904 			    &template[i]);
1905 			if (rv != CKR_OK)
1906 				goto fail_cleanup;
1907 
1908 			/*
1909 			 * Modulus length needs to be between min key length and
1910 			 * max key length.
1911 			 */
1912 			if ((modulus.big_value_len <
1913 			    MIN_RSA_KEYLENGTH_IN_BYTES) ||
1914 			    (modulus.big_value_len >
1915 			    MAX_RSA_KEYLENGTH_IN_BYTES)) {
1916 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
1917 				goto fail_cleanup;
1918 			}
1919 			break;
1920 
1921 		case CKA_PUBLIC_EXPONENT:
1922 
1923 			isPubExpo = 1;
1924 			rv = get_bigint_attr_from_template(&pubexpo,
1925 			    &template[i]);
1926 			if (rv != CKR_OK)
1927 				goto fail_cleanup;
1928 			break;
1929 
1930 		case CKA_PRIVATE_EXPONENT:
1931 
1932 			isPriExpo = 1;
1933 			rv = get_bigint_attr_from_template(&priexpo,
1934 			    &template[i]);
1935 			if (rv != CKR_OK)
1936 				goto fail_cleanup;
1937 			break;
1938 
1939 		case CKA_PRIME_1:
1940 			isPrime1 = 1;
1941 			rv = get_bigint_attr_from_template(&prime1,
1942 			    &template[i]);
1943 			if (rv != CKR_OK)
1944 				goto fail_cleanup;
1945 			break;
1946 
1947 		case CKA_PRIME_2:
1948 			isPrime2 = 1;
1949 			rv = get_bigint_attr_from_template(&prime2,
1950 			    &template[i]);
1951 			if (rv != CKR_OK)
1952 				goto fail_cleanup;
1953 			break;
1954 
1955 		case CKA_EXPONENT_1:
1956 			isExpo1 = 1;
1957 			rv = get_bigint_attr_from_template(&expo1,
1958 			    &template[i]);
1959 			if (rv != CKR_OK)
1960 				goto fail_cleanup;
1961 			break;
1962 
1963 		case CKA_EXPONENT_2:
1964 			isExpo2 = 1;
1965 			rv = get_bigint_attr_from_template(&expo2,
1966 			    &template[i]);
1967 			if (rv != CKR_OK)
1968 				goto fail_cleanup;
1969 			break;
1970 
1971 		case CKA_COEFFICIENT:
1972 			isCoef = 1;
1973 			rv = get_bigint_attr_from_template(&coef,
1974 			    &template[i]);
1975 			if (rv != CKR_OK)
1976 				goto fail_cleanup;
1977 			break;
1978 
1979 		case CKA_PRIME:
1980 			isPrime = 1;
1981 			rv = get_bigint_attr_from_template(&prime,
1982 			    &template[i]);
1983 			if (rv != CKR_OK)
1984 				goto fail_cleanup;
1985 			break;
1986 
1987 		case CKA_SUBPRIME:
1988 			isSubprime = 1;
1989 			rv = get_bigint_attr_from_template(&subprime,
1990 			    &template[i]);
1991 			if (rv != CKR_OK)
1992 				goto fail_cleanup;
1993 			break;
1994 
1995 		case CKA_BASE:
1996 			isBase = 1;
1997 			rv = get_bigint_attr_from_template(&base,
1998 			    &template[i]);
1999 			if (rv != CKR_OK)
2000 				goto fail_cleanup;
2001 			break;
2002 
2003 		case CKA_VALUE:
2004 			isValue = 1;
2005 			if (mode == SOFT_CREATE_OBJ) {
2006 				if ((template[i].ulValueLen == 0) ||
2007 				    (template[i].pValue == NULL)) {
2008 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
2009 					goto fail_cleanup;
2010 				}
2011 			}
2012 
2013 			rv = get_bigint_attr_from_template(&value,
2014 			    &template[i]);
2015 			if (rv != CKR_OK)
2016 				goto fail_cleanup;
2017 			break;
2018 
2019 		case CKA_VALUE_BITS:
2020 			isValueBits = 1;
2021 			get_ulong_attr_from_template(&value_bits,
2022 			    &template[i]);
2023 			break;
2024 
2025 		case CKA_LABEL:
2026 			isLabel = 1;
2027 			rv = get_string_from_template(&string_tmp,
2028 			    &template[i]);
2029 			if (rv != CKR_OK)
2030 				goto fail_cleanup;
2031 			break;
2032 
2033 		default:
2034 			rv = soft_parse_common_attrs(&template[i],
2035 			    &object_type);
2036 			if (rv != CKR_OK)
2037 				goto fail_cleanup;
2038 			break;
2039 
2040 		}
2041 	} /* For */
2042 
2043 	/* Allocate storage for Private Key Object. */
2044 	pvk = calloc(1, sizeof (private_key_obj_t));
2045 	if (pvk == NULL) {
2046 		rv = CKR_HOST_MEMORY;
2047 		goto fail_cleanup;
2048 	}
2049 
2050 	new_object->object_class_u.private_key = pvk;
2051 	new_object->class = CKO_PRIVATE_KEY;
2052 
2053 	if ((mode == SOFT_CREATE_OBJ) && (keytype == (CK_KEY_TYPE)~0UL)) {
2054 		rv = CKR_TEMPLATE_INCOMPLETE;
2055 		goto fail_cleanup;
2056 	}
2057 
2058 	if (mode == SOFT_GEN_KEY) {
2059 		/*
2060 		 * The key type is not specified in the application's
2061 		 * template, so we use the implied key type based on
2062 		 * the mechanism.
2063 		 */
2064 		if (keytype == (CK_KEY_TYPE)~0UL) {
2065 			keytype = key_type;
2066 		}
2067 
2068 		/* If still unspecified, template is incomplete */
2069 		if (keytype == (CK_KEY_TYPE)~0UL) {
2070 			rv = CKR_TEMPLATE_INCOMPLETE;
2071 			goto fail_cleanup;
2072 		}
2073 
2074 		/*
2075 		 * The key type specified in the template does not
2076 		 * match the implied key type based on the mechanism.
2077 		 */
2078 		if (keytype != key_type) {
2079 			rv = CKR_TEMPLATE_INCONSISTENT;
2080 			goto fail_cleanup;
2081 		}
2082 	}
2083 
2084 	if (mode == SOFT_UNWRAP_KEY) {
2085 		/*
2086 		 * Note that, for mode SOFT_UNWRAP_KEY, key type is not
2087 		 * implied by the mechanism (key_type), so if it is not
2088 		 * specified from the attribute template (keytype), it is
2089 		 * incomplete.
2090 		 */
2091 		if (keytype == (CK_KEY_TYPE)~0UL) {
2092 			rv = CKR_TEMPLATE_INCOMPLETE;
2093 			goto fail_cleanup;
2094 		}
2095 	}
2096 
2097 	new_object->key_type = keytype;
2098 
2099 	/* Supported key types of the Private Key Object */
2100 	switch (keytype) {
2101 	case CKK_RSA:
2102 		if (isPrime || isSubprime || isBase || isValue ||
2103 		    isValueBits) {
2104 			rv = CKR_TEMPLATE_INCONSISTENT;
2105 			goto fail_cleanup;
2106 		}
2107 
2108 		if (mode == SOFT_GEN_KEY || mode == SOFT_UNWRAP_KEY) {
2109 			if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
2110 			    isPrime2 || isExpo1 || isExpo2 || isCoef) {
2111 				rv = CKR_TEMPLATE_INCONSISTENT;
2112 				goto fail_cleanup;
2113 			} else
2114 				break;
2115 		}
2116 
2117 		if (isModulus && isPriExpo) {
2118 			/*
2119 			 * Copy big integer attribute value to the
2120 			 * designated place in the Private Key object.
2121 			 */
2122 			copy_bigint_attr(&modulus, KEY_PRI_RSA_MOD(pvk));
2123 
2124 			copy_bigint_attr(&priexpo, KEY_PRI_RSA_PRIEXPO(pvk));
2125 		} else {
2126 			rv = CKR_TEMPLATE_INCOMPLETE;
2127 			goto fail_cleanup;
2128 		}
2129 
2130 		/* The following attributes are optional. */
2131 		if (isPubExpo) {
2132 			copy_bigint_attr(&pubexpo, KEY_PRI_RSA_PUBEXPO(pvk));
2133 		}
2134 
2135 		if (isPrime1) {
2136 			copy_bigint_attr(&prime1, KEY_PRI_RSA_PRIME1(pvk));
2137 		}
2138 
2139 		if (isPrime2) {
2140 			copy_bigint_attr(&prime2, KEY_PRI_RSA_PRIME2(pvk));
2141 		}
2142 
2143 		if (isExpo1) {
2144 			copy_bigint_attr(&expo1, KEY_PRI_RSA_EXPO1(pvk));
2145 		}
2146 
2147 		if (isExpo2) {
2148 			copy_bigint_attr(&expo2, KEY_PRI_RSA_EXPO2(pvk));
2149 		}
2150 
2151 		if (isCoef) {
2152 			copy_bigint_attr(&coef, KEY_PRI_RSA_COEF(pvk));
2153 		}
2154 		break;
2155 
2156 	case CKK_DSA:
2157 		if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
2158 		    isPrime2 || isExpo1 || isExpo2 || isCoef ||
2159 		    isValueBits) {
2160 			rv = CKR_TEMPLATE_INCONSISTENT;
2161 			goto fail_cleanup;
2162 		}
2163 
2164 		if (mode == SOFT_GEN_KEY || mode == SOFT_UNWRAP_KEY) {
2165 			if (isPrime || isSubprime || isBase || isValue) {
2166 				rv = CKR_TEMPLATE_INCONSISTENT;
2167 				goto fail_cleanup;
2168 			} else
2169 				break;
2170 		}
2171 
2172 		if (isPrime && isSubprime && isBase && isValue) {
2173 			/*
2174 			 * The private value x must be less than subprime q.
2175 			 * Size for big_init is in (32-bit) words.
2176 			 */
2177 #ifdef	__sparcv9
2178 			/* LINTED */
2179 			if (big_init(&x, ((int)value.big_value_len +
2180 #else	/* !__sparcv9 */
2181 			if (big_init(&x, (value.big_value_len +
2182 #endif	/* __sparcv9 */
2183 			    (int)sizeof (uint32_t) - 1) /
2184 			    (int)sizeof (uint32_t)) != BIG_OK) {
2185 				rv = CKR_HOST_MEMORY;
2186 				goto fail_cleanup;
2187 			}
2188 #ifdef	__sparcv9
2189 			/* LINTED */
2190 			if (big_init(&q, ((int)subprime.big_value_len +
2191 #else	/* !__sparcv9 */
2192 			if (big_init(&q, (subprime.big_value_len +
2193 #endif	/* __sparcv9 */
2194 			    (int)sizeof (uint32_t) - 1) /
2195 			    (int)sizeof (uint32_t)) != BIG_OK) {
2196 				rv = CKR_HOST_MEMORY;
2197 				goto fail_cleanup;
2198 			}
2199 			bytestring2bignum(&x, value.big_value,
2200 			    value.big_value_len);
2201 			bytestring2bignum(&q, subprime.big_value,
2202 			    subprime.big_value_len);
2203 
2204 			if (big_cmp_abs(&x, &q) > 0) {
2205 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2206 				goto fail_cleanup;
2207 			}
2208 
2209 			copy_bigint_attr(&prime, KEY_PRI_DSA_PRIME(pvk));
2210 
2211 			copy_bigint_attr(&subprime, KEY_PRI_DSA_SUBPRIME(pvk));
2212 
2213 			copy_bigint_attr(&base, KEY_PRI_DSA_BASE(pvk));
2214 
2215 			copy_bigint_attr(&value, KEY_PRI_DSA_VALUE(pvk));
2216 		} else {
2217 			rv = CKR_TEMPLATE_INCOMPLETE;
2218 			goto fail_cleanup;
2219 		}
2220 		break;
2221 
2222 	case CKK_DH:
2223 		if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
2224 		    isPrime2 || isExpo1 || isExpo2 || isCoef ||
2225 		    isSubprime) {
2226 			rv = CKR_TEMPLATE_INCONSISTENT;
2227 			goto fail_cleanup;
2228 		}
2229 
2230 		/* CKA_VALUE_BITS is for key gen but not unwrap */
2231 		if (mode == SOFT_GEN_KEY)
2232 			KEY_PRI_DH_VAL_BITS(pvk) = (isValueBits) ?
2233 			    value_bits : 0;
2234 		else if (mode == SOFT_UNWRAP_KEY) {
2235 			if (isValueBits) {
2236 				rv = CKR_TEMPLATE_INCONSISTENT;
2237 				goto fail_cleanup;
2238 			}
2239 		}
2240 
2241 		if (mode == SOFT_GEN_KEY || mode == SOFT_UNWRAP_KEY) {
2242 			if (isPrime || isBase || isValue) {
2243 				rv = CKR_TEMPLATE_INCONSISTENT;
2244 				goto fail_cleanup;
2245 			} else
2246 				break;
2247 		}
2248 
2249 		if (isValueBits) {
2250 			rv = CKR_TEMPLATE_INCONSISTENT;
2251 			goto fail_cleanup;
2252 		}
2253 
2254 		if (isPrime && isBase && isValue) {
2255 			copy_bigint_attr(&prime, KEY_PRI_DH_PRIME(pvk));
2256 
2257 			copy_bigint_attr(&base, KEY_PRI_DH_BASE(pvk));
2258 
2259 			copy_bigint_attr(&value, KEY_PRI_DH_VALUE(pvk));
2260 		} else {
2261 			rv = CKR_TEMPLATE_INCOMPLETE;
2262 			goto fail_cleanup;
2263 		}
2264 		break;
2265 
2266 	case CKK_X9_42_DH:
2267 		if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
2268 		    isPrime2 || isExpo1 || isExpo2 || isCoef ||
2269 		    isValueBits) {
2270 			rv = CKR_TEMPLATE_INCONSISTENT;
2271 			goto fail_cleanup;
2272 		}
2273 
2274 		if (mode == SOFT_GEN_KEY || mode == SOFT_UNWRAP_KEY) {
2275 			if (isPrime || isSubprime || isBase || isValue) {
2276 				rv = CKR_TEMPLATE_INCONSISTENT;
2277 				goto fail_cleanup;
2278 			} else
2279 				break;
2280 		}
2281 
2282 		if (isPrime && isSubprime && isBase && isValue) {
2283 			copy_bigint_attr(&prime, KEY_PRI_DH942_PRIME(pvk));
2284 
2285 			copy_bigint_attr(&base, KEY_PRI_DH942_BASE(pvk));
2286 
2287 			copy_bigint_attr(&subprime,
2288 				KEY_PRI_DH942_SUBPRIME(pvk));
2289 
2290 			copy_bigint_attr(&value, KEY_PRI_DH942_VALUE(pvk));
2291 		} else {
2292 			rv = CKR_TEMPLATE_INCOMPLETE;
2293 			goto fail_cleanup;
2294 		}
2295 		break;
2296 
2297 	default:
2298 		rv = CKR_TEMPLATE_INCONSISTENT;
2299 		goto fail_cleanup;
2300 	}
2301 
2302 	/* Set up object. */
2303 	new_object->object_type = object_type;
2304 	new_object->bool_attr_mask = attr_mask;
2305 	if (isLabel) {
2306 		rv = soft_add_extra_attr(&string_tmp, new_object);
2307 		if (rv != CKR_OK)
2308 			goto fail_cleanup;
2309 		string_attr_cleanup(&string_tmp);
2310 	}
2311 	big_finish(&x);
2312 	big_finish(&q);
2313 
2314 	return (rv);
2315 
2316 fail_cleanup:
2317 	/*
2318 	 * cleanup the storage allocated to the local variables.
2319 	 */
2320 	bigint_attr_cleanup(&modulus);
2321 	bigint_attr_cleanup(&priexpo);
2322 	bigint_attr_cleanup(&prime);
2323 	bigint_attr_cleanup(&subprime);
2324 	bigint_attr_cleanup(&base);
2325 	bigint_attr_cleanup(&value);
2326 	bigint_attr_cleanup(&pubexpo);
2327 	bigint_attr_cleanup(&prime1);
2328 	bigint_attr_cleanup(&prime2);
2329 	bigint_attr_cleanup(&expo1);
2330 	bigint_attr_cleanup(&expo2);
2331 	bigint_attr_cleanup(&coef);
2332 	string_attr_cleanup(&string_tmp);
2333 	big_finish(&x);
2334 	big_finish(&q);
2335 
2336 	/*
2337 	 * cleanup the storage allocated inside the object itself.
2338 	 */
2339 	soft_cleanup_object(new_object);
2340 
2341 	return (rv);
2342 }
2343 
2344 
2345 /*
2346  * Build a Secret Key Object.
2347  *
2348  * - Parse the object's template, and when an error is detected such as
2349  *   invalid attribute type, invalid attribute value, etc., return
2350  *   with appropriate return value.
2351  * - Set up attribute mask field in the object for the supplied common
2352  *   attributes that have boolean type.
2353  * - Build the attribute_info struct to hold the value of each supplied
2354  *   attribute that has byte array type. Link attribute_info structs
2355  *   together to form the extra attribute list of the object.
2356  * - Allocate storage for the Secret Key object.
2357  * - Build the Secret Key object. Allocate storage to hold the big integer
2358  *   value for the attribute CKA_VALUE that is required for all the key
2359  *   types supported by secret key object.
2360  * This function is called internally with mode = SOFT_CREATE_OBJ_INT.
2361  *
2362  */
2363 CK_RV
2364 soft_build_secret_key_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
2365 	soft_object_t *new_object, CK_ULONG mode, CK_ULONG key_len,
2366 	CK_KEY_TYPE key_type)
2367 {
2368 
2369 	ulong_t		i;
2370 	CK_KEY_TYPE	keytype = (CK_KEY_TYPE)~0UL;
2371 	uint64_t	attr_mask = SECRET_KEY_DEFAULT;
2372 	CK_RV 		rv = CKR_OK;
2373 	int		isLabel = 0;
2374 	/* Must set flags if mode != SOFT_UNWRAP_KEY, else must not set */
2375 	int		isValue = 0;
2376 	/* Must not set flags if mode != SOFT_UNWRAP_KEY, else optional */
2377 	int		isValueLen = 0;
2378 
2379 	CK_ATTRIBUTE	string_tmp;
2380 
2381 	secret_key_obj_t  *sck;
2382 	uchar_t	object_type = 0;
2383 
2384 	string_tmp.pValue = NULL;
2385 
2386 	/* Allocate storage for Secret Key Object. */
2387 	sck = calloc(1, sizeof (secret_key_obj_t));
2388 	if (sck == NULL) {
2389 		rv = CKR_HOST_MEMORY;
2390 		goto fail_cleanup;
2391 	}
2392 
2393 	new_object->object_class_u.secret_key = sck;
2394 	new_object->class = CKO_SECRET_KEY;
2395 
2396 	for (i = 0; i < ulAttrNum; i++) {
2397 
2398 		/* Secret Key Object Attributes */
2399 		switch (template[i].type) {
2400 
2401 		/* common key attributes */
2402 		case CKA_KEY_TYPE:
2403 			keytype = *((CK_KEY_TYPE*)template[i].pValue);
2404 			break;
2405 
2406 		case CKA_ID:
2407 		case CKA_START_DATE:
2408 		case CKA_END_DATE:
2409 			/*
2410 			 * Allocate storage to hold the attribute
2411 			 * value with byte array type, and add it to
2412 			 * the extra attribute list of the object.
2413 			 */
2414 			rv = soft_add_extra_attr(&template[i],
2415 			    new_object);
2416 			if (rv != CKR_OK) {
2417 				goto fail_cleanup;
2418 			}
2419 			break;
2420 
2421 		/*
2422 		 * The following key related attribute types must
2423 		 * not be specified by C_CreateObject and C_GenerateKey.
2424 		 */
2425 		case CKA_LOCAL:
2426 		case CKA_KEY_GEN_MECHANISM:
2427 		case CKA_ALWAYS_SENSITIVE:
2428 		case CKA_NEVER_EXTRACTABLE:
2429 			rv = CKR_TEMPLATE_INCONSISTENT;
2430 			goto fail_cleanup;
2431 
2432 		/* Key related boolean attributes */
2433 		case CKA_DERIVE:
2434 			if (*(CK_BBOOL *)template[i].pValue)
2435 				attr_mask |= DERIVE_BOOL_ON;
2436 			break;
2437 
2438 		case CKA_SENSITIVE:
2439 			if (*(CK_BBOOL *)template[i].pValue)
2440 				attr_mask |= SENSITIVE_BOOL_ON;
2441 			break;
2442 
2443 		case CKA_ENCRYPT:
2444 			if (*(CK_BBOOL *)template[i].pValue)
2445 				attr_mask |= ENCRYPT_BOOL_ON;
2446 			else
2447 				attr_mask &= ~ENCRYPT_BOOL_ON;
2448 			break;
2449 
2450 		case CKA_DECRYPT:
2451 			if (*(CK_BBOOL *)template[i].pValue)
2452 				attr_mask |= DECRYPT_BOOL_ON;
2453 			else
2454 				attr_mask &= ~DECRYPT_BOOL_ON;
2455 			break;
2456 
2457 		case CKA_SIGN:
2458 			if (*(CK_BBOOL *)template[i].pValue)
2459 				attr_mask |= SIGN_BOOL_ON;
2460 			else
2461 				attr_mask &= ~SIGN_BOOL_ON;
2462 			break;
2463 
2464 		case CKA_VERIFY:
2465 			if (*(CK_BBOOL *)template[i].pValue)
2466 				attr_mask |= VERIFY_BOOL_ON;
2467 			else
2468 				attr_mask &= ~VERIFY_BOOL_ON;
2469 			break;
2470 
2471 		case CKA_WRAP:
2472 			if (*(CK_BBOOL *)template[i].pValue)
2473 				attr_mask |= WRAP_BOOL_ON;
2474 			else
2475 				attr_mask &= ~WRAP_BOOL_ON;
2476 			break;
2477 
2478 		case CKA_UNWRAP:
2479 			if (*(CK_BBOOL *)template[i].pValue)
2480 				attr_mask |= UNWRAP_BOOL_ON;
2481 			else
2482 				attr_mask &= ~UNWRAP_BOOL_ON;
2483 			break;
2484 
2485 		case CKA_EXTRACTABLE:
2486 			if (*(CK_BBOOL *)template[i].pValue)
2487 				attr_mask |= EXTRACTABLE_BOOL_ON;
2488 			else
2489 				attr_mask &= ~EXTRACTABLE_BOOL_ON;
2490 			break;
2491 
2492 		case CKA_MODIFIABLE:
2493 			if ((*(CK_BBOOL *)template[i].pValue) == B_FALSE)
2494 				attr_mask |= NOT_MODIFIABLE_BOOL_ON;
2495 			break;
2496 
2497 		case CKA_VALUE:
2498 			isValue = 1;
2499 			if (mode == SOFT_CREATE_OBJ) {
2500 				if ((template[i].ulValueLen == 0) ||
2501 				    (template[i].pValue == NULL)) {
2502 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
2503 					goto fail_cleanup;
2504 				}
2505 			}
2506 
2507 			/*
2508 			 * Copyin attribute from template
2509 			 * to a local variable.
2510 			 */
2511 			rv = get_bigint_attr_from_template((biginteger_t *)sck,
2512 			    &template[i]);
2513 			if (rv != CKR_OK)
2514 				goto fail_cleanup;
2515 			break;
2516 
2517 		case CKA_VALUE_LEN:
2518 			isValueLen = 1;
2519 			get_ulong_attr_from_template(&sck->sk_value_len,
2520 			    &template[i]);
2521 			break;
2522 
2523 		case CKA_LABEL:
2524 			isLabel = 1;
2525 			rv = get_string_from_template(&string_tmp,
2526 			    &template[i]);
2527 			if (rv != CKR_OK)
2528 				goto fail_cleanup;
2529 			break;
2530 
2531 		default:
2532 			rv = soft_parse_common_attrs(&template[i],
2533 			    &object_type);
2534 			if (rv != CKR_OK)
2535 				goto fail_cleanup;
2536 			break;
2537 
2538 		}
2539 	} /* For */
2540 
2541 	switch (mode) {
2542 	case SOFT_CREATE_OBJ:
2543 	case SOFT_CREATE_OBJ_INT:
2544 	case SOFT_DERIVE_KEY_DH:
2545 		/*
2546 		 * The key type must be specified in the application's
2547 		 * template. Otherwise, returns error.
2548 		 */
2549 		if (keytype == (CK_KEY_TYPE)~0UL) {
2550 			rv = CKR_TEMPLATE_INCOMPLETE;
2551 			goto fail_cleanup;
2552 		}
2553 		break;
2554 
2555 	case SOFT_GEN_KEY:
2556 		if (keytype == (CK_KEY_TYPE)~0UL) {
2557 			/*
2558 			 * The key type is not specified in the application's
2559 			 * template, so we use the implied key type based on
2560 			 * the mechanism.
2561 			 */
2562 			keytype = key_type;
2563 		} else {
2564 			if (keytype != key_type) {
2565 				/*
2566 				 * The key type specified in the template
2567 				 * does not match the implied key type based
2568 				 * on the mechanism.
2569 				 */
2570 				rv = CKR_TEMPLATE_INCONSISTENT;
2571 				goto fail_cleanup;
2572 			}
2573 		}
2574 
2575 		/*
2576 		 * If a key_len is passed as a parameter, it has to
2577 		 * match the one found in the template.
2578 		 */
2579 		if (key_len > 0) {
2580 			if (isValueLen && sck->sk_value_len != key_len) {
2581 				rv = CKR_TEMPLATE_INCONSISTENT;
2582 				goto fail_cleanup;
2583 			}
2584 			isValueLen = 1;
2585 			sck->sk_value_len = key_len;
2586 		}
2587 		break;
2588 
2589 	case SOFT_UNWRAP_KEY:
2590 		/*
2591 		 * Note that, for mode SOFT_UNWRAP_KEY, key type is not
2592 		 * implied by the mechanism (key_type), so if it is not
2593 		 * specified from the attribute template (keytype), it is
2594 		 * incomplete.
2595 		 */
2596 		if (keytype == (CK_KEY_TYPE)~0UL) {
2597 			rv = CKR_TEMPLATE_INCOMPLETE;
2598 			goto fail_cleanup;
2599 		}
2600 		break;
2601 
2602 	case SOFT_DERIVE_KEY_OTHER:
2603 		/*
2604 		 * For CKM_MD5_KEY_DERIVATION & CKM_SHA1_KEY_DERIVATION, the
2605 		 * key type is optional.
2606 		 */
2607 		if (keytype == (CK_KEY_TYPE)~0UL) {
2608 			keytype = key_type;
2609 		}
2610 		break;
2611 	}
2612 
2613 	switch (mode) {
2614 	case SOFT_CREATE_OBJ:
2615 	case SOFT_CREATE_OBJ_INT:
2616 		switch (keytype) {
2617 		case CKK_RC4:
2618 			if (!isValue) {
2619 				rv = CKR_TEMPLATE_INCOMPLETE;
2620 				goto fail_cleanup;
2621 			}
2622 			if ((sck->sk_value_len < ARCFOUR_MIN_KEY_BYTES) ||
2623 			    (sck->sk_value_len > ARCFOUR_MAX_KEY_BYTES)) {
2624 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2625 				goto fail_cleanup;
2626 			}
2627 			break;
2628 
2629 		case CKK_GENERIC_SECRET:
2630 			if (!isValue) {
2631 				rv = CKR_TEMPLATE_INCOMPLETE;
2632 				goto fail_cleanup;
2633 			}
2634 			break;
2635 
2636 		case CKK_AES:
2637 			if (!isValue) {
2638 				rv = CKR_TEMPLATE_INCOMPLETE;
2639 				goto fail_cleanup;
2640 			}
2641 #ifdef	CRYPTO_UNLIMITED
2642 			if ((sck->sk_value_len != AES_MIN_KEY_BYTES) &&
2643 			    (sck->sk_value_len != AES_192_KEY_BYTES) &&
2644 			    (sck->sk_value_len != AES_MAX_KEY_BYTES)) {
2645 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2646 				goto fail_cleanup;
2647 			}
2648 #else
2649 			if (sck->sk_value_len != AES_MIN_KEY_BYTES) {
2650 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2651 				goto fail_cleanup;
2652 			}
2653 #endif /* CRYPTO_UNLIMITED */
2654 			break;
2655 
2656 		case CKK_DES:
2657 			if (!isValue) {
2658 				rv = CKR_TEMPLATE_INCOMPLETE;
2659 				goto fail_cleanup;
2660 			}
2661 			if (sck->sk_value_len != DES_KEYSIZE) {
2662 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2663 				goto fail_cleanup;
2664 			}
2665 			break;
2666 
2667 		case CKK_DES2:
2668 			if (!isValue) {
2669 				rv = CKR_TEMPLATE_INCOMPLETE;
2670 				goto fail_cleanup;
2671 			}
2672 			if (sck->sk_value_len != DES2_KEYSIZE) {
2673 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2674 				goto fail_cleanup;
2675 			}
2676 			break;
2677 
2678 		case CKK_DES3:
2679 			if (!isValue) {
2680 				rv = CKR_TEMPLATE_INCOMPLETE;
2681 				goto fail_cleanup;
2682 			}
2683 			if (sck->sk_value_len != DES3_KEYSIZE) {
2684 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2685 				goto fail_cleanup;
2686 			}
2687 			break;
2688 
2689 		default:
2690 			rv = CKR_TEMPLATE_INCONSISTENT;
2691 			goto fail_cleanup;
2692 		}
2693 
2694 		if (isValueLen) {
2695 			/*
2696 			 * Templates for internal object creation come from
2697 			 * applications calls to C_DeriveKey(), for which it
2698 			 * is OKey to pass a CKA_VALUE_LEN attribute, as
2699 			 * long as it does not conflict with the length of the
2700 			 * CKA_VALUE attribute.
2701 			 */
2702 			if ((mode != SOFT_CREATE_OBJ_INT) ||
2703 			    ((key_len > 0) && sck->sk_value_len != key_len)) {
2704 				rv = CKR_TEMPLATE_INCONSISTENT;
2705 				goto fail_cleanup;
2706 			}
2707 		}
2708 		break;
2709 
2710 	case SOFT_GEN_KEY:
2711 		/* CKA_VALUE must not be specified */
2712 		if (isValue) {
2713 			rv = CKR_TEMPLATE_INCONSISTENT;
2714 			goto fail_cleanup;
2715 		}
2716 
2717 		switch (keytype) {
2718 		/*
2719 		 * CKA_VALUE_LEN must be specified by C_GenerateKey
2720 		 * if mech is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET.
2721 		 */
2722 		case CKK_RC4:
2723 			if (!isValueLen) {
2724 				rv = CKR_TEMPLATE_INCONSISTENT;
2725 				goto fail_cleanup;
2726 			}
2727 
2728 			if ((sck->sk_value_len < ARCFOUR_MIN_KEY_BYTES) ||
2729 				(sck->sk_value_len > ARCFOUR_MAX_KEY_BYTES)) {
2730 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2731 				goto fail_cleanup;
2732 			}
2733 			break;
2734 
2735 		case CKK_GENERIC_SECRET:
2736 			/* arbitrary key length - no length checking */
2737 			if (!isValueLen) {
2738 				rv = CKR_TEMPLATE_INCONSISTENT;
2739 				goto fail_cleanup;
2740 			}
2741 			break;
2742 
2743 		case CKK_AES:
2744 			if (!isValueLen) {
2745 				rv = CKR_TEMPLATE_INCONSISTENT;
2746 				goto fail_cleanup;
2747 			}
2748 
2749 #ifdef	CRYPTO_UNLIMITED
2750 			if ((sck->sk_value_len != AES_MIN_KEY_BYTES) &&
2751 			    (sck->sk_value_len != AES_192_KEY_BYTES) &&
2752 			    (sck->sk_value_len != AES_MAX_KEY_BYTES)) {
2753 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2754 				goto fail_cleanup;
2755 			}
2756 #else
2757 			if (sck->sk_value_len != AES_MIN_KEY_BYTES) {
2758 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2759 				goto fail_cleanup;
2760 			}
2761 #endif /* CRYPTO_UNLIMITED */
2762 
2763 			break;
2764 
2765 		case CKK_DES:
2766 		case CKK_DES2:
2767 		case CKK_DES3:
2768 			/* CKA_VALUE_LEN attribute does not apply to DES<n> */
2769 			if (isValueLen) {
2770 				rv = CKR_TEMPLATE_INCONSISTENT;
2771 				goto fail_cleanup;
2772 			}
2773 			break;
2774 
2775 		default:
2776 			rv = CKR_TEMPLATE_INCONSISTENT;
2777 			goto fail_cleanup;
2778 		}
2779 		break;
2780 
2781 	case SOFT_UNWRAP_KEY:
2782 		/*
2783 		 * According to v2.11 of PKCS#11 spec, neither CKA_VALUE nor
2784 		 * CKA_VALUE_LEN can be be specified; however v2.20 has this
2785 		 * restriction removed, perhaps because it makes it hard to
2786 		 * determine variable-length key sizes.  This case statement
2787 		 * complied with v2.20.
2788 		 */
2789 		if (isValue) {
2790 			rv = CKR_TEMPLATE_INCONSISTENT;
2791 			goto fail_cleanup;
2792 		}
2793 
2794 		switch (keytype) {
2795 		/*
2796 		 * CKA_VALUE_LEN is optional
2797 		 * if key is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET
2798 		 * and the unwrapping mech is *_CBC_PAD.
2799 		 *
2800 		 * CKA_VALUE_LEN is required
2801 		 * if key is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET
2802 		 * and the unwrapping mech is *_ECB or *_CBC.
2803 		 *
2804 		 * since mech is not known at this point, CKA_VALUE_LEN is
2805 		 * treated as optional and the caller needs to enforce it.
2806 		 */
2807 		case CKK_RC4:
2808 			if (isValueLen) {
2809 				if ((sck->sk_value_len <
2810 				    ARCFOUR_MIN_KEY_BYTES) ||
2811 				    (sck->sk_value_len >
2812 				    ARCFOUR_MAX_KEY_BYTES)) {
2813 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
2814 					goto fail_cleanup;
2815 				}
2816 			}
2817 			break;
2818 
2819 		case CKK_GENERIC_SECRET:
2820 			/* arbitrary key length - no length checking */
2821 			break;
2822 
2823 		case CKK_AES:
2824 			if (isValueLen) {
2825 #ifdef	CRYPTO_UNLIMITED
2826 				if ((sck->sk_value_len != AES_MIN_KEY_BYTES) &&
2827 				    (sck->sk_value_len != AES_192_KEY_BYTES) &&
2828 				    (sck->sk_value_len != AES_MAX_KEY_BYTES)) {
2829 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
2830 					goto fail_cleanup;
2831 				}
2832 #else
2833 				if (sck->sk_value_len != AES_MIN_KEY_BYTES) {
2834 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
2835 					goto fail_cleanup;
2836 				}
2837 #endif /* CRYPTO_UNLIMITED */
2838 			}
2839 			break;
2840 
2841 		case CKK_DES:
2842 		case CKK_DES2:
2843 		case CKK_DES3:
2844 			/* CKA_VALUE_LEN attribute does not apply to DES<n> */
2845 			if (isValueLen) {
2846 				rv = CKR_TEMPLATE_INCONSISTENT;
2847 				goto fail_cleanup;
2848 			}
2849 			break;
2850 
2851 		default:
2852 			rv = CKR_TEMPLATE_INCONSISTENT;
2853 			goto fail_cleanup;
2854 		}
2855 		break;
2856 
2857 	case SOFT_DERIVE_KEY_DH:
2858 		/* CKA_VALUE must not be specified */
2859 		if (isValue) {
2860 			rv = CKR_TEMPLATE_INCONSISTENT;
2861 			goto fail_cleanup;
2862 		}
2863 
2864 		switch (keytype) {
2865 		/*
2866 		 * CKA_VALUE_LEN is optional
2867 		 * if mech is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET.
2868 		 */
2869 		case CKK_RC4:
2870 			if (isValueLen) {
2871 				if ((sck->sk_value_len <
2872 				    ARCFOUR_MIN_KEY_BYTES) ||
2873 				    (sck->sk_value_len >
2874 				    ARCFOUR_MAX_KEY_BYTES)) {
2875 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
2876 					goto fail_cleanup;
2877 				}
2878 			}
2879 			break;
2880 
2881 		case CKK_GENERIC_SECRET:
2882 			/* arbitrary key length - no length checking */
2883 			break;
2884 
2885 		case CKK_AES:
2886 			if (isValueLen) {
2887 #ifdef	CRYPTO_UNLIMITED
2888 				if ((sck->sk_value_len != AES_MIN_KEY_BYTES) &&
2889 				    (sck->sk_value_len != AES_192_KEY_BYTES) &&
2890 				    (sck->sk_value_len != AES_MAX_KEY_BYTES)) {
2891 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
2892 					goto fail_cleanup;
2893 				}
2894 #else
2895 				if (sck->sk_value_len != AES_MIN_KEY_BYTES) {
2896 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
2897 					goto fail_cleanup;
2898 				}
2899 #endif /* CRYPTO_UNLIMITED */
2900 			}
2901 
2902 			break;
2903 
2904 		case CKK_DES:
2905 		case CKK_DES2:
2906 		case CKK_DES3:
2907 			/* CKA_VALUE_LEN attribute does not apply to DES<n> */
2908 			if (isValueLen) {
2909 				rv = CKR_TEMPLATE_INCONSISTENT;
2910 				goto fail_cleanup;
2911 			}
2912 			break;
2913 
2914 		default:
2915 			rv = CKR_TEMPLATE_INCONSISTENT;
2916 			goto fail_cleanup;
2917 		}
2918 		break;
2919 
2920 	case SOFT_DERIVE_KEY_OTHER:
2921 		/* CKA_VALUE must not be specified */
2922 		if (isValue) {
2923 			rv = CKR_TEMPLATE_INCONSISTENT;
2924 			goto fail_cleanup;
2925 		}
2926 
2927 		switch (keytype) {
2928 		/*
2929 		 * CKA_VALUE_LEN is an optional attribute for
2930 		 * CKM_SHA1_KEY_DERIVATION and CKM_MD5_KEY_DERIVATION
2931 		 * if mech is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET.
2932 		 */
2933 		case CKK_RC4:
2934 		case CKK_GENERIC_SECRET:
2935 		case CKK_AES:
2936 			/*
2937 			 * No need to check key length value here, it will be
2938 			 * validated later in soft_key_derive_check_length().
2939 			 */
2940 			break;
2941 
2942 		case CKK_DES:
2943 		case CKK_DES2:
2944 		case CKK_DES3:
2945 			/* CKA_VALUE_LEN attribute does not apply to DES<n> */
2946 			if (isValueLen) {
2947 				rv = CKR_TEMPLATE_INCONSISTENT;
2948 				goto fail_cleanup;
2949 			}
2950 			break;
2951 
2952 		default:
2953 			rv = CKR_TEMPLATE_INCONSISTENT;
2954 			goto fail_cleanup;
2955 		}
2956 		break;
2957 	}
2958 
2959 	/* Set up object. */
2960 	new_object->key_type = keytype;
2961 	new_object->object_type = object_type;
2962 	new_object->bool_attr_mask = attr_mask;
2963 	if (isLabel) {
2964 		rv = soft_add_extra_attr(&string_tmp, new_object);
2965 		if (rv != CKR_OK)
2966 			goto fail_cleanup;
2967 		string_attr_cleanup(&string_tmp);
2968 	}
2969 	return (rv);
2970 
2971 fail_cleanup:
2972 	/*
2973 	 * cleanup the storage allocated to the local variables.
2974 	 */
2975 	bigint_attr_cleanup((biginteger_t *)sck);
2976 	string_attr_cleanup(&string_tmp);
2977 
2978 	/*
2979 	 * cleanup the storage allocated inside the object itself.
2980 	 */
2981 	soft_cleanup_object(new_object);
2982 
2983 	return (rv);
2984 }
2985 
2986 
2987 /*
2988  * Build a Domain Parameter Object.
2989  *
2990  * - Parse the object's template, and when an error is detected such as
2991  *   invalid attribute type, invalid attribute value, etc., return
2992  *   with appropriate return value.
2993  * - Allocate storage for the Domain Parameter object.
2994  * - Build the Domain Parameter object according to the key type. Allocate
2995  *   storage to hold the big integer value for the supplied attributes
2996  *   that are required for a certain key type.
2997  *
2998  */
2999 CK_RV
3000 soft_build_domain_parameters_object(CK_ATTRIBUTE_PTR template,
3001 	CK_ULONG ulAttrNum, soft_object_t *new_object)
3002 {
3003 
3004 	ulong_t		i;
3005 	CK_KEY_TYPE	keytype = (CK_KEY_TYPE)~0UL;
3006 	CK_RV 		rv = CKR_OK;
3007 	int		isLabel = 0;
3008 	/* Must set flags */
3009 	int		isPrime = 0;
3010 	int		isSubprime = 0;
3011 	int		isBase = 0;
3012 	/* Must not set flags */
3013 	int		isPrimeBits = 0;
3014 	int		isSubPrimeBits = 0;
3015 
3016 	biginteger_t	prime;
3017 	biginteger_t	subprime;
3018 	biginteger_t	base;
3019 	CK_ATTRIBUTE	string_tmp;
3020 
3021 	domain_obj_t	*dom;
3022 	uchar_t	object_type = 0;
3023 
3024 	/* prevent bigint_attr_cleanup from freeing invalid attr value */
3025 	(void) memset(&prime, 0x0, sizeof (biginteger_t));
3026 	(void) memset(&subprime, 0x0, sizeof (biginteger_t));
3027 	(void) memset(&base, 0x0, sizeof (biginteger_t));
3028 	string_tmp.pValue = NULL;
3029 
3030 	for (i = 0; i < ulAttrNum; i++) {
3031 
3032 		/* Domain Parameters Object Attributes */
3033 		switch (template[i].type) {
3034 
3035 		/* common domain parameter attribute */
3036 		case CKA_KEY_TYPE:
3037 			keytype = *((CK_KEY_TYPE*)template[i].pValue);
3038 			break;
3039 
3040 		/*
3041 		 * The following common domain parameter attribute
3042 		 * must not be specified by C_CreateObject.
3043 		 */
3044 		case CKA_LOCAL:
3045 			rv = CKR_TEMPLATE_INCONSISTENT;
3046 			goto fail_cleanup;
3047 
3048 		/*
3049 		 * The following domain parameter attributes must be
3050 		 * specified according to the key type by
3051 		 * C_CreateObject.
3052 		 */
3053 		case CKA_PRIME:
3054 			isPrime = 1;
3055 			/*
3056 			 * Copyin big integer attribute from template
3057 			 * to a local variable.
3058 			 */
3059 			rv = get_bigint_attr_from_template(&prime,
3060 			    &template[i]);
3061 			if (rv != CKR_OK)
3062 				goto fail_cleanup;
3063 			break;
3064 
3065 		case CKA_SUBPRIME:
3066 			isSubprime = 1;
3067 			rv = get_bigint_attr_from_template(&subprime,
3068 			    &template[i]);
3069 			if (rv != CKR_OK)
3070 				goto fail_cleanup;
3071 			break;
3072 
3073 		case CKA_BASE:
3074 			isBase = 1;
3075 			rv = get_bigint_attr_from_template(&base,
3076 			    &template[i]);
3077 			if (rv != CKR_OK)
3078 				goto fail_cleanup;
3079 			break;
3080 
3081 		case CKA_PRIME_BITS:
3082 			isPrimeBits = 1;
3083 			break;
3084 
3085 		case CKA_SUB_PRIME_BITS:
3086 			isSubPrimeBits = 1;
3087 			break;
3088 
3089 		case CKA_LABEL:
3090 			isLabel = 1;
3091 			rv = get_string_from_template(&string_tmp,
3092 			    &template[i]);
3093 			if (rv != CKR_OK)
3094 				goto fail_cleanup;
3095 			break;
3096 
3097 		default:
3098 			rv = soft_parse_common_attrs(&template[i],
3099 			    &object_type);
3100 			if (rv != CKR_OK)
3101 				goto fail_cleanup;
3102 			break;
3103 
3104 		}
3105 	} /* For */
3106 
3107 	/* Allocate storage for Domain Parameters Object. */
3108 	dom = calloc(1, sizeof (domain_obj_t));
3109 	if (dom == NULL) {
3110 		rv = CKR_HOST_MEMORY;
3111 		goto fail_cleanup;
3112 	}
3113 
3114 	new_object->object_class_u.domain = dom;
3115 	new_object->class = CKO_DOMAIN_PARAMETERS;
3116 
3117 	if (keytype == (CK_KEY_TYPE)~0UL) {
3118 		rv = CKR_TEMPLATE_INCOMPLETE;
3119 		goto fail_cleanup;
3120 	}
3121 
3122 	new_object->key_type = keytype;
3123 
3124 	/* Supported key types of the Domain Parameters Object */
3125 	switch (keytype) {
3126 	case CKK_DSA:
3127 		if (isPrimeBits || isSubPrimeBits) {
3128 			rv = CKR_TEMPLATE_INCONSISTENT;
3129 			goto fail_cleanup;
3130 		}
3131 
3132 		if (isPrime && isSubprime && isBase) {
3133 			/*
3134 			 * Copy big integer attribute value to the
3135 			 * designated place in the domain parameter
3136 			 * object.
3137 			 */
3138 			copy_bigint_attr(&prime, KEY_DOM_DSA_PRIME(dom));
3139 
3140 			copy_bigint_attr(&subprime, KEY_DOM_DSA_SUBPRIME(dom));
3141 
3142 			copy_bigint_attr(&base, KEY_DOM_DSA_BASE(dom));
3143 		} else {
3144 			rv = CKR_TEMPLATE_INCOMPLETE;
3145 			goto fail_cleanup;
3146 		}
3147 		break;
3148 
3149 	case CKK_DH:
3150 		if (isPrimeBits || isSubprime || isSubPrimeBits) {
3151 			rv = CKR_TEMPLATE_INCONSISTENT;
3152 			goto fail_cleanup;
3153 		}
3154 
3155 		if (isPrime && isBase) {
3156 			copy_bigint_attr(&prime, KEY_DOM_DH_PRIME(dom));
3157 
3158 			copy_bigint_attr(&base, KEY_DOM_DH_BASE(dom));
3159 		} else {
3160 			rv = CKR_TEMPLATE_INCOMPLETE;
3161 			goto fail_cleanup;
3162 		}
3163 		break;
3164 
3165 	case CKK_X9_42_DH:
3166 		if (isPrimeBits || isSubPrimeBits) {
3167 			rv = CKR_TEMPLATE_INCONSISTENT;
3168 			goto fail_cleanup;
3169 		}
3170 
3171 		if (isPrime && isSubprime && isBase) {
3172 			copy_bigint_attr(&prime, KEY_DOM_DH942_PRIME(dom));
3173 
3174 			copy_bigint_attr(&base, KEY_DOM_DH942_BASE(dom));
3175 
3176 			copy_bigint_attr(&subprime,
3177 				KEY_DOM_DH942_SUBPRIME(dom));
3178 		} else {
3179 			rv = CKR_TEMPLATE_INCOMPLETE;
3180 			goto fail_cleanup;
3181 		}
3182 		break;
3183 
3184 	default:
3185 		rv = CKR_TEMPLATE_INCONSISTENT;
3186 		goto fail_cleanup;
3187 	}
3188 
3189 	new_object->object_type = object_type;
3190 
3191 	if (isLabel) {
3192 		rv = soft_add_extra_attr(&string_tmp, new_object);
3193 		if (rv != CKR_OK)
3194 			goto fail_cleanup;
3195 		string_attr_cleanup(&string_tmp);
3196 	}
3197 
3198 	return (rv);
3199 
3200 fail_cleanup:
3201 	/*
3202 	 * cleanup the storage allocated to the local variables.
3203 	 */
3204 	bigint_attr_cleanup(&prime);
3205 	bigint_attr_cleanup(&subprime);
3206 	bigint_attr_cleanup(&base);
3207 	string_attr_cleanup(&string_tmp);
3208 
3209 	/*
3210 	 * cleanup the storage allocated inside the object itself.
3211 	 */
3212 	soft_cleanup_object(new_object);
3213 
3214 	return (rv);
3215 }
3216 
3217 /*
3218  * Build a Certificate Object
3219  *
3220  * - Parse the object's template, and when an error is detected such as
3221  *   invalid attribute type, invalid attribute value, etc., return
3222  *   with appropriate return value.
3223  * - Allocate storage for the Certificate object
3224  */
3225 static CK_RV
3226 soft_build_certificate_object(CK_ATTRIBUTE_PTR template,
3227 	CK_ULONG ulAttrNum, soft_object_t *new_object,
3228 	CK_CERTIFICATE_TYPE cert_type)
3229 {
3230 	uint64_t	attr_mask = 0;
3231 	CK_RV 		rv = CKR_OK;
3232 	CK_ULONG	i;
3233 	int		owner_set = 0;
3234 	int		value_set = 0;
3235 	int		subject_set = 0;
3236 	certificate_obj_t *cert;
3237 	/* certificate type defaults to the value given as a parameter */
3238 	CK_CERTIFICATE_TYPE certtype = cert_type;
3239 	CK_ATTRIBUTE	string_tmp;
3240 	int		isLabel = 0;
3241 	uchar_t		object_type = 0;
3242 
3243 	/*
3244 	 * Look for the certificate type attribute and do some
3245 	 * sanity checking before creating the structures.
3246 	 */
3247 	for (i = 0; i < ulAttrNum; i++) {
3248 		/* Certificate Object Attributes */
3249 		switch (template[i].type) {
3250 			case CKA_CERTIFICATE_TYPE:
3251 				certtype =
3252 				    *((CK_CERTIFICATE_TYPE*)template[i].pValue);
3253 				break;
3254 			case CKA_SUBJECT:
3255 				subject_set = 1;
3256 				break;
3257 			case CKA_OWNER:
3258 				owner_set = 1;
3259 				break;
3260 			case CKA_VALUE:
3261 				value_set = 1;
3262 				break;
3263 		}
3264 	}
3265 
3266 	/* The certificate type MUST be specified */
3267 	if (certtype != CKC_X_509 && certtype != CKC_X_509_ATTR_CERT)
3268 		return (CKR_TEMPLATE_INCOMPLETE);
3269 
3270 	/*
3271 	 * For X.509 certs, the CKA_SUBJECT and CKA_VALUE
3272 	 * must be present at creation time.
3273 	 */
3274 	if (certtype == CKC_X_509 &&
3275 	    (!subject_set || !value_set))
3276 		return (CKR_TEMPLATE_INCOMPLETE);
3277 
3278 	/*
3279 	 * For X.509 Attribute certs, the CKA_OWNER and CKA_VALUE
3280 	 * must be present at creation time.
3281 	 */
3282 	if (certtype == CKC_X_509_ATTR_CERT &&
3283 	    (!owner_set || !value_set))
3284 		return (CKR_TEMPLATE_INCOMPLETE);
3285 
3286 	string_tmp.pValue = NULL;
3287 	cert = calloc(1, sizeof (certificate_obj_t));
3288 	if (cert == NULL) {
3289 		return (CKR_HOST_MEMORY);
3290 	}
3291 	cert->certificate_type = certtype;
3292 
3293 	for (i = 0; i < ulAttrNum; i++) {
3294 		/* Certificate Object Attributes */
3295 		switch (certtype) {
3296 			case CKC_X_509:
3297 			switch (template[i].type) {
3298 				case CKA_SUBJECT:
3299 					rv = get_cert_attr_from_template(
3300 						&cert->cert_type_u.x509.subject,
3301 						&template[i]);
3302 					break;
3303 				case CKA_VALUE:
3304 					rv = get_cert_attr_from_template(
3305 						&cert->cert_type_u.x509.value,
3306 						&template[i]);
3307 					break;
3308 				case CKA_LABEL:
3309 					isLabel = 1;
3310 					rv = get_string_from_template(
3311 							&string_tmp,
3312 							&template[i]);
3313 					if (rv != CKR_OK)
3314 						goto fail_cleanup;
3315 					break;
3316 				case CKA_ID:
3317 				case CKA_ISSUER:
3318 				case CKA_SERIAL_NUMBER:
3319 					rv = soft_add_extra_attr(&template[i],
3320 						new_object);
3321 					break;
3322 				case CKA_MODIFIABLE:
3323 					if ((*(CK_BBOOL *)template[i].pValue) ==
3324 					    B_FALSE)
3325 						attr_mask |=
3326 						    NOT_MODIFIABLE_BOOL_ON;
3327 					break;
3328 				case CKA_CERTIFICATE_TYPE:
3329 					break;
3330 				default:
3331 				    rv = soft_parse_common_attrs(&template[i],
3332 					&object_type);
3333 				    if (rv != CKR_OK)
3334 					goto fail_cleanup;
3335 			}
3336 			break;
3337 			case CKC_X_509_ATTR_CERT:
3338 			switch (template[i].type) {
3339 				case CKA_OWNER:
3340 					rv = get_cert_attr_from_template(
3341 					    &cert->cert_type_u.x509_attr.owner,
3342 					    &template[i]);
3343 					break;
3344 				case CKA_VALUE:
3345 					rv = get_cert_attr_from_template(
3346 					    &cert->cert_type_u.x509_attr.value,
3347 					    &template[i]);
3348 					break;
3349 				case CKA_LABEL:
3350 					isLabel = 1;
3351 					rv = get_string_from_template(
3352 						&string_tmp, &template[i]);
3353 					if (rv != CKR_OK)
3354 						goto fail_cleanup;
3355 					break;
3356 				case CKA_SERIAL_NUMBER:
3357 				case CKA_AC_ISSUER:
3358 				case CKA_ATTR_TYPES:
3359 					rv = soft_add_extra_attr(&template[i],
3360 						new_object);
3361 					break;
3362 
3363 				case CKA_MODIFIABLE:
3364 					if ((*(CK_BBOOL *)template[i].pValue) ==
3365 					    B_FALSE)
3366 						attr_mask |=
3367 						    NOT_MODIFIABLE_BOOL_ON;
3368 					break;
3369 				case CKA_CERTIFICATE_TYPE:
3370 					break;
3371 				default:
3372 				    rv = soft_parse_common_attrs(&template[i],
3373 					&object_type);
3374 				    if (rv != CKR_OK)
3375 					goto fail_cleanup;
3376 				    break;
3377 			}
3378 			break;
3379 			default:
3380 				rv = CKR_TEMPLATE_INCOMPLETE;
3381 				break;
3382 		}
3383 	}
3384 
3385 	if (rv == CKR_OK) {
3386 		new_object->object_class_u.certificate = cert;
3387 		new_object->class = CKO_CERTIFICATE;
3388 		new_object->object_type = object_type;
3389 		new_object->cert_type = certtype;
3390 		new_object->bool_attr_mask = attr_mask;
3391 		if (isLabel) {
3392 			rv = soft_add_extra_attr(&string_tmp, new_object);
3393 			if (rv != CKR_OK)
3394 				goto fail_cleanup;
3395 			string_attr_cleanup(&string_tmp);
3396 		}
3397 	}
3398 
3399 fail_cleanup:
3400 	if (rv != CKR_OK) {
3401 		soft_cleanup_cert_object(new_object);
3402 	}
3403 	return (rv);
3404 }
3405 
3406 
3407 /*
3408  * Validate the attribute types in the object's template. Then,
3409  * call the appropriate build function according to the class of
3410  * the object specified in the template.
3411  *
3412  * Note: The following classes of objects are supported:
3413  * - CKO_PUBLIC_KEY
3414  * - CKO_PRIVATE_KEY
3415  * - CKO_SECRET_KEY
3416  * - CKO_DOMAIN_PARAMETERS
3417  * - CKO_CERTIFICATE
3418  *
3419  */
3420 CK_RV
3421 soft_build_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
3422 	soft_object_t *new_object)
3423 {
3424 
3425 	CK_OBJECT_CLASS class = (CK_OBJECT_CLASS)~0UL;
3426 	CK_RV 		rv = CKR_OK;
3427 
3428 	if (template == NULL) {
3429 		return (CKR_ARGUMENTS_BAD);
3430 	}
3431 
3432 	/* Validate the attribute type in the template. */
3433 	rv = soft_validate_attr(template, ulAttrNum, &class);
3434 	if (rv != CKR_OK)
3435 		return (rv);
3436 	/*
3437 	 * CKA_CLASS is a mandatory attribute for C_CreateObject
3438 	 */
3439 	if (class == (CK_OBJECT_CLASS)~0UL)
3440 		return (CKR_TEMPLATE_INCOMPLETE);
3441 
3442 	/*
3443 	 * Call the appropriate function based on the supported class
3444 	 * of the object.
3445 	 */
3446 	switch (class) {
3447 	case CKO_PUBLIC_KEY:
3448 		rv = soft_build_public_key_object(template, ulAttrNum,
3449 		    new_object, SOFT_CREATE_OBJ, (CK_KEY_TYPE)~0UL);
3450 		break;
3451 
3452 	case CKO_PRIVATE_KEY:
3453 		rv = soft_build_private_key_object(template, ulAttrNum,
3454 		    new_object, SOFT_CREATE_OBJ, (CK_KEY_TYPE)~0UL);
3455 		break;
3456 
3457 	case CKO_SECRET_KEY:
3458 		rv = soft_build_secret_key_object(template, ulAttrNum,
3459 		    new_object, SOFT_CREATE_OBJ, 0, (CK_KEY_TYPE)~0UL);
3460 		break;
3461 
3462 	case CKO_DOMAIN_PARAMETERS:
3463 		rv = soft_build_domain_parameters_object(template, ulAttrNum,
3464 		    new_object);
3465 		break;
3466 
3467 	case CKO_CERTIFICATE:
3468 		rv = soft_build_certificate_object(template, ulAttrNum,
3469 			new_object, (CK_CERTIFICATE_TYPE)~0UL);
3470 		break;
3471 
3472 	case CKO_DATA:
3473 	case CKO_HW_FEATURE:
3474 	case CKO_VENDOR_DEFINED:
3475 	default:
3476 		return (CKR_ATTRIBUTE_VALUE_INVALID);
3477 	}
3478 
3479 	return (rv);
3480 }
3481 
3482 /*
3483  * Validate the attribute types in the object's template. Then,
3484  * call the appropriate build function according to the class of
3485  * the object specified in the template.
3486  *
3487  */
3488 CK_RV
3489 soft_build_key(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
3490 	soft_object_t *new_object, CK_OBJECT_CLASS class, CK_KEY_TYPE key_type,
3491 	CK_ULONG key_len, CK_ULONG mode)
3492 {
3493 
3494 	CK_RV 		rv = CKR_OK;
3495 	CK_OBJECT_CLASS temp_class = (CK_OBJECT_CLASS)~0UL;
3496 
3497 	/* Validate the attribute type in the template. */
3498 	if ((template != NULL) && (ulAttrNum != 0)) {
3499 		rv = soft_validate_attr(template, ulAttrNum, &temp_class);
3500 		if (rv != CKR_OK)
3501 			return (rv);
3502 	}
3503 
3504 	/*
3505 	 * If either the class from the parameter list ("class") or
3506 	 * the class from the template ("temp_class") is not specified,
3507 	 * try to use the other one.
3508 	 */
3509 	if (temp_class == (CK_OBJECT_CLASS)~0UL) {
3510 		temp_class = class;
3511 	} else if (class == (CK_OBJECT_CLASS)~0UL) {
3512 		class = temp_class;
3513 	}
3514 
3515 	/* If object class is still not specified, template is incomplete. */
3516 	if (class == (CK_OBJECT_CLASS)~0UL)
3517 		return (CKR_TEMPLATE_INCOMPLETE);
3518 
3519 	/* Class should match if specified in both parameters and template. */
3520 	if (class != temp_class)
3521 		return (CKR_TEMPLATE_INCONSISTENT);
3522 
3523 	/*
3524 	 * Call the appropriate function based on the supported class
3525 	 * of the object.
3526 	 */
3527 	switch (class) {
3528 	case CKO_PUBLIC_KEY:
3529 
3530 		/* Unwrapping public keys is not supported. */
3531 		if (mode == SOFT_UNWRAP_KEY) {
3532 			rv = CKR_ATTRIBUTE_VALUE_INVALID;
3533 			break;
3534 		}
3535 
3536 		rv = soft_build_public_key_object(template, ulAttrNum,
3537 		    new_object, mode, key_type);
3538 		break;
3539 
3540 	case CKO_PRIVATE_KEY:
3541 
3542 		rv = soft_build_private_key_object(template, ulAttrNum,
3543 		    new_object, mode, key_type);
3544 		break;
3545 
3546 	case CKO_SECRET_KEY:
3547 
3548 		rv = soft_build_secret_key_object(template, ulAttrNum,
3549 		    new_object, mode, key_len, key_type);
3550 		break;
3551 
3552 	case CKO_DOMAIN_PARAMETERS:
3553 
3554 		/* Unwrapping domain parameters is not supported. */
3555 		if (mode == SOFT_UNWRAP_KEY) {
3556 			rv = CKR_ATTRIBUTE_VALUE_INVALID;
3557 			break;
3558 		}
3559 
3560 		rv = soft_build_domain_parameters_object(template, ulAttrNum,
3561 		    new_object);
3562 		break;
3563 
3564 	case CKO_DATA:
3565 	case CKO_CERTIFICATE:
3566 	case CKO_HW_FEATURE:
3567 	case CKO_VENDOR_DEFINED:
3568 	default:
3569 		return (CKR_ATTRIBUTE_VALUE_INVALID);
3570 	}
3571 
3572 	return (rv);
3573 }
3574 
3575 
3576 /*
3577  * Get the value of a requested attribute that is common to all supported
3578  * classes (i.e. public key, private key, secret key, domain parameters,
3579  * and certificate classes).
3580  */
3581 CK_RV
3582 soft_get_common_attrs(soft_object_t *object_p, CK_ATTRIBUTE_PTR template,
3583     uchar_t object_type)
3584 {
3585 
3586 	CK_RV rv = CKR_OK;
3587 
3588 	switch (template->type) {
3589 
3590 	case CKA_CLASS:
3591 		return (get_ulong_attr_from_object(object_p->class,
3592 		    template));
3593 
3594 	/* default boolean attributes */
3595 	case CKA_TOKEN:
3596 		template->ulValueLen = sizeof (CK_BBOOL);
3597 		if (template->pValue == NULL) {
3598 			return (CKR_OK);
3599 		}
3600 		if (object_type & TOKEN_OBJECT)
3601 			*((CK_BBOOL *)template->pValue) = B_TRUE;
3602 		else
3603 			*((CK_BBOOL *)template->pValue) = B_FALSE;
3604 		break;
3605 
3606 	case CKA_PRIVATE:
3607 
3608 		template->ulValueLen = sizeof (CK_BBOOL);
3609 		if (template->pValue == NULL) {
3610 			return (CKR_OK);
3611 		}
3612 		if (object_type & PRIVATE_OBJECT)
3613 			*((CK_BBOOL *)template->pValue) = B_TRUE;
3614 		else
3615 			*((CK_BBOOL *)template->pValue) = B_FALSE;
3616 		break;
3617 
3618 	case CKA_MODIFIABLE:
3619 		template->ulValueLen = sizeof (CK_BBOOL);
3620 		if (template->pValue == NULL) {
3621 			return (CKR_OK);
3622 		}
3623 		if ((object_p->bool_attr_mask) & NOT_MODIFIABLE_BOOL_ON)
3624 			*((CK_BBOOL *)template->pValue) = B_FALSE;
3625 		else
3626 			*((CK_BBOOL *)template->pValue) = B_TRUE;
3627 		break;
3628 
3629 	case CKA_LABEL:
3630 		return (get_extra_attr_from_object(object_p,
3631 		    template));
3632 
3633 	default:
3634 		/*
3635 		 * The specified attribute for the object is invalid.
3636 		 * (the object does not possess such an attribute.)
3637 		 */
3638 		template->ulValueLen = (CK_ULONG)-1;
3639 		return (CKR_ATTRIBUTE_TYPE_INVALID);
3640 	}
3641 
3642 	return (rv);
3643 }
3644 
3645 /*
3646  * Get the value of a requested attribute that is common to all key objects
3647  * (i.e. public key, private key and secret key).
3648  */
3649 CK_RV
3650 soft_get_common_key_attrs(soft_object_t *object_p, CK_ATTRIBUTE_PTR template)
3651 {
3652 
3653 	switch (template->type) {
3654 
3655 	case CKA_KEY_TYPE:
3656 		return (get_ulong_attr_from_object(object_p->key_type,
3657 		    template));
3658 
3659 	case CKA_ID:
3660 	case CKA_START_DATE:
3661 	case CKA_END_DATE:
3662 		/*
3663 		 * The above extra attributes have byte array type.
3664 		 */
3665 		return (get_extra_attr_from_object(object_p,
3666 		    template));
3667 
3668 	/* Key related boolean attributes */
3669 	case CKA_LOCAL:
3670 		return (get_bool_attr_from_object(object_p,
3671 		    LOCAL_BOOL_ON, template));
3672 
3673 	case CKA_DERIVE:
3674 		return (get_bool_attr_from_object(object_p,
3675 		    DERIVE_BOOL_ON, template));
3676 
3677 	case CKA_KEY_GEN_MECHANISM:
3678 		return (get_ulong_attr_from_object(object_p->mechanism,
3679 		    template));
3680 
3681 	default:
3682 		return (CKR_ATTRIBUTE_TYPE_INVALID);
3683 	}
3684 }
3685 
3686 /*
3687  * Get the value of a requested attribute of a Public Key Object.
3688  *
3689  * Rule: All the attributes in the public key object can be revealed.
3690  */
3691 CK_RV
3692 soft_get_public_key_attribute(soft_object_t *object_p,
3693 	CK_ATTRIBUTE_PTR template)
3694 {
3695 
3696 	CK_RV		rv = CKR_OK;
3697 	CK_KEY_TYPE	keytype = object_p->key_type;
3698 
3699 	switch (template->type) {
3700 
3701 	case CKA_SUBJECT:
3702 		/*
3703 		 * The above extra attributes have byte array type.
3704 		 */
3705 		return (get_extra_attr_from_object(object_p,
3706 		    template));
3707 
3708 	/* Key related boolean attributes */
3709 	case CKA_ENCRYPT:
3710 		return (get_bool_attr_from_object(object_p,
3711 		    ENCRYPT_BOOL_ON, template));
3712 
3713 	case CKA_VERIFY:
3714 		return (get_bool_attr_from_object(object_p,
3715 		    VERIFY_BOOL_ON, template));
3716 
3717 	case CKA_VERIFY_RECOVER:
3718 		return (get_bool_attr_from_object(object_p,
3719 		    VERIFY_RECOVER_BOOL_ON, template));
3720 
3721 	case CKA_WRAP:
3722 		return (get_bool_attr_from_object(object_p,
3723 		    WRAP_BOOL_ON, template));
3724 
3725 	case CKA_TRUSTED:
3726 		return (get_bool_attr_from_object(object_p,
3727 		    TRUSTED_BOOL_ON, template));
3728 
3729 	case CKA_MODULUS:
3730 		/*
3731 		 * This attribute is valid only for RSA public key
3732 		 * object.
3733 		 */
3734 		if (keytype == CKK_RSA) {
3735 			return (get_bigint_attr_from_object(
3736 			    OBJ_PUB_RSA_MOD(object_p), template));
3737 		} else {
3738 			template->ulValueLen = (CK_ULONG)-1;
3739 			return (CKR_ATTRIBUTE_TYPE_INVALID);
3740 		}
3741 
3742 	case CKA_PUBLIC_EXPONENT:
3743 		if (keytype == CKK_RSA) {
3744 			return (get_bigint_attr_from_object(
3745 			    OBJ_PUB_RSA_PUBEXPO(object_p), template));
3746 		} else {
3747 			template->ulValueLen = (CK_ULONG)-1;
3748 			return (CKR_ATTRIBUTE_TYPE_INVALID);
3749 		}
3750 
3751 	case CKA_MODULUS_BITS:
3752 		if (keytype == CKK_RSA) {
3753 			return (get_ulong_attr_from_object(
3754 			    OBJ_PUB_RSA_MOD_BITS(object_p), template));
3755 		} else {
3756 			template->ulValueLen = (CK_ULONG)-1;
3757 			return (CKR_ATTRIBUTE_TYPE_INVALID);
3758 		}
3759 
3760 	case CKA_PRIME:
3761 		switch (keytype) {
3762 		case CKK_DSA:
3763 			return (get_bigint_attr_from_object(
3764 			    OBJ_PUB_DSA_PRIME(object_p), template));
3765 
3766 		case CKK_DH:
3767 			return (get_bigint_attr_from_object(
3768 			    OBJ_PUB_DH_PRIME(object_p), template));
3769 
3770 		case CKK_X9_42_DH:
3771 			return (get_bigint_attr_from_object(
3772 			    OBJ_PUB_DH942_PRIME(object_p), template));
3773 
3774 		default:
3775 			template->ulValueLen = (CK_ULONG)-1;
3776 			return (CKR_ATTRIBUTE_TYPE_INVALID);
3777 		}
3778 
3779 	case CKA_SUBPRIME:
3780 		switch (keytype) {
3781 		case CKK_DSA:
3782 			return (get_bigint_attr_from_object(
3783 			    OBJ_PUB_DSA_SUBPRIME(object_p), template));
3784 
3785 		case CKK_X9_42_DH:
3786 			return (get_bigint_attr_from_object(
3787 			    OBJ_PUB_DH942_SUBPRIME(object_p), template));
3788 
3789 		default:
3790 			template->ulValueLen = (CK_ULONG)-1;
3791 			return (CKR_ATTRIBUTE_TYPE_INVALID);
3792 		}
3793 
3794 	case CKA_BASE:
3795 		switch (keytype) {
3796 		case CKK_DSA:
3797 			return (get_bigint_attr_from_object(
3798 			    OBJ_PUB_DSA_BASE(object_p), template));
3799 
3800 		case CKK_DH:
3801 			return (get_bigint_attr_from_object(
3802 			    OBJ_PUB_DH_BASE(object_p), template));
3803 
3804 		case CKK_X9_42_DH:
3805 			return (get_bigint_attr_from_object(
3806 			    OBJ_PUB_DH942_BASE(object_p), template));
3807 
3808 		default:
3809 			template->ulValueLen = (CK_ULONG)-1;
3810 			return (CKR_ATTRIBUTE_TYPE_INVALID);
3811 		}
3812 
3813 	case CKA_VALUE:
3814 		switch (keytype) {
3815 		case CKK_DSA:
3816 			return (get_bigint_attr_from_object(
3817 			    OBJ_PUB_DSA_VALUE(object_p), template));
3818 
3819 		case CKK_DH:
3820 			return (get_bigint_attr_from_object(
3821 			    OBJ_PUB_DH_VALUE(object_p), template));
3822 
3823 		case CKK_X9_42_DH:
3824 			return (get_bigint_attr_from_object(
3825 			    OBJ_PUB_DH942_VALUE(object_p), template));
3826 
3827 		default:
3828 			template->ulValueLen = (CK_ULONG)-1;
3829 			return (CKR_ATTRIBUTE_TYPE_INVALID);
3830 		}
3831 
3832 	default:
3833 		/*
3834 		 * First, get the value of the request attribute defined
3835 		 * in the list of common key attributes. If the request
3836 		 * attribute is not found in that list, then get the
3837 		 * attribute from the list of common attributes.
3838 		 */
3839 		rv = soft_get_common_key_attrs(object_p, template);
3840 		if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
3841 			rv = soft_get_common_attrs(object_p, template,
3842 			    object_p->object_type);
3843 		}
3844 		break;
3845 	}
3846 
3847 	return (rv);
3848 }
3849 
3850 
3851 /*
3852  * Get the value of a requested attribute of a Private Key Object.
3853  *
3854  * Rule: All the attributes in the private key object can be revealed
3855  *       except those marked with footnote number "7" when the object
3856  *       has its CKA_SENSITIVE attribute set to TRUE or its
3857  *       CKA_EXTRACTABLE attribute set to FALSE (p.88 in PKCS11 spec.).
3858  */
3859 CK_RV
3860 soft_get_private_key_attribute(soft_object_t *object_p,
3861 	CK_ATTRIBUTE_PTR template)
3862 {
3863 
3864 	CK_RV		rv = CKR_OK;
3865 	CK_KEY_TYPE	keytype = object_p->key_type;
3866 
3867 
3868 	/*
3869 	 * If the following specified attributes for the private key
3870 	 * object cannot be revealed because the object is sensitive
3871 	 * or unextractable, then the ulValueLen is set to -1.
3872 	 */
3873 	if ((object_p->bool_attr_mask & SENSITIVE_BOOL_ON) ||
3874 	    !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
3875 
3876 		switch (template->type) {
3877 		case CKA_PRIVATE_EXPONENT:
3878 		case CKA_PRIME_1:
3879 		case CKA_PRIME_2:
3880 		case CKA_EXPONENT_1:
3881 		case CKA_EXPONENT_2:
3882 		case CKA_COEFFICIENT:
3883 		case CKA_VALUE:
3884 			template->ulValueLen = (CK_ULONG)-1;
3885 			return (CKR_ATTRIBUTE_SENSITIVE);
3886 		}
3887 	}
3888 
3889 	switch (template->type) {
3890 
3891 	case CKA_SUBJECT:
3892 		/*
3893 		 * The above extra attributes have byte array type.
3894 		 */
3895 		return (get_extra_attr_from_object(object_p,
3896 		    template));
3897 
3898 	/* Key related boolean attributes */
3899 	case CKA_SENSITIVE:
3900 		return (get_bool_attr_from_object(object_p,
3901 		    SENSITIVE_BOOL_ON, template));
3902 
3903 	case CKA_SECONDARY_AUTH:
3904 		return (get_bool_attr_from_object(object_p,
3905 		    SECONDARY_AUTH_BOOL_ON, template));
3906 
3907 	case CKA_DECRYPT:
3908 		return (get_bool_attr_from_object(object_p,
3909 		    DECRYPT_BOOL_ON, template));
3910 
3911 	case CKA_SIGN:
3912 		return (get_bool_attr_from_object(object_p,
3913 		    SIGN_BOOL_ON, template));
3914 
3915 	case CKA_SIGN_RECOVER:
3916 		return (get_bool_attr_from_object(object_p,
3917 		    SIGN_RECOVER_BOOL_ON, template));
3918 
3919 	case CKA_UNWRAP:
3920 		return (get_bool_attr_from_object(object_p,
3921 		    UNWRAP_BOOL_ON, template));
3922 
3923 	case CKA_EXTRACTABLE:
3924 		return (get_bool_attr_from_object(object_p,
3925 		    EXTRACTABLE_BOOL_ON, template));
3926 
3927 	case CKA_ALWAYS_SENSITIVE:
3928 		return (get_bool_attr_from_object(object_p,
3929 		    ALWAYS_SENSITIVE_BOOL_ON, template));
3930 
3931 	case CKA_NEVER_EXTRACTABLE:
3932 		return (get_bool_attr_from_object(object_p,
3933 		    NEVER_EXTRACTABLE_BOOL_ON, template));
3934 
3935 	case CKA_MODULUS:
3936 		if (keytype == CKK_RSA) {
3937 			return (get_bigint_attr_from_object(
3938 			    OBJ_PRI_RSA_MOD(object_p), template));
3939 		} else {
3940 			template->ulValueLen = (CK_ULONG)-1;
3941 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
3942 			break;
3943 		}
3944 
3945 	case CKA_PUBLIC_EXPONENT:
3946 		if (keytype == CKK_RSA) {
3947 			return (get_bigint_attr_from_object(
3948 			    OBJ_PRI_RSA_PUBEXPO(object_p), template));
3949 		} else {
3950 			template->ulValueLen = (CK_ULONG)-1;
3951 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
3952 			break;
3953 		}
3954 
3955 	case CKA_PRIVATE_EXPONENT:
3956 		if (keytype == CKK_RSA) {
3957 			return (get_bigint_attr_from_object(
3958 			    OBJ_PRI_RSA_PRIEXPO(object_p), template));
3959 		} else {
3960 			template->ulValueLen = (CK_ULONG)-1;
3961 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
3962 			break;
3963 		}
3964 
3965 	case CKA_PRIME_1:
3966 		if (keytype == CKK_RSA) {
3967 			return (get_bigint_attr_from_object(
3968 			    OBJ_PRI_RSA_PRIME1(object_p), template));
3969 		} else {
3970 			template->ulValueLen = (CK_ULONG)-1;
3971 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
3972 			break;
3973 		}
3974 
3975 	case CKA_PRIME_2:
3976 		if (keytype == CKK_RSA) {
3977 			return (get_bigint_attr_from_object(
3978 			    OBJ_PRI_RSA_PRIME2(object_p), template));
3979 		} else {
3980 			template->ulValueLen = (CK_ULONG)-1;
3981 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
3982 			break;
3983 		}
3984 
3985 	case CKA_EXPONENT_1:
3986 		if (keytype == CKK_RSA) {
3987 			return (get_bigint_attr_from_object(
3988 			    OBJ_PRI_RSA_EXPO1(object_p), template));
3989 		} else {
3990 			template->ulValueLen = (CK_ULONG)-1;
3991 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
3992 			break;
3993 		}
3994 
3995 	case CKA_EXPONENT_2:
3996 		if (keytype == CKK_RSA) {
3997 			return (get_bigint_attr_from_object(
3998 			    OBJ_PRI_RSA_EXPO2(object_p), template));
3999 		} else {
4000 			template->ulValueLen = (CK_ULONG)-1;
4001 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
4002 			break;
4003 		}
4004 
4005 	case CKA_COEFFICIENT:
4006 		if (keytype == CKK_RSA) {
4007 			return (get_bigint_attr_from_object(
4008 			    OBJ_PRI_RSA_COEF(object_p), template));
4009 		} else {
4010 			template->ulValueLen = (CK_ULONG)-1;
4011 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
4012 			break;
4013 		}
4014 
4015 	case CKA_VALUE_BITS:
4016 		if (keytype == CKK_DH) {
4017 			return (get_ulong_attr_from_object(
4018 			    OBJ_PRI_DH_VAL_BITS(object_p), template));
4019 		} else {
4020 			template->ulValueLen = (CK_ULONG)-1;
4021 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
4022 			break;
4023 		}
4024 
4025 	case CKA_PRIME:
4026 		switch (keytype) {
4027 		case CKK_DSA:
4028 			return (get_bigint_attr_from_object(
4029 			    OBJ_PRI_DSA_PRIME(object_p), template));
4030 
4031 		case CKK_DH:
4032 			return (get_bigint_attr_from_object(
4033 			    OBJ_PRI_DH_PRIME(object_p), template));
4034 
4035 		case CKK_X9_42_DH:
4036 			return (get_bigint_attr_from_object(
4037 			    OBJ_PRI_DH942_PRIME(object_p), template));
4038 
4039 		default:
4040 			template->ulValueLen = (CK_ULONG)-1;
4041 			return (CKR_ATTRIBUTE_TYPE_INVALID);
4042 		}
4043 
4044 	case CKA_SUBPRIME:
4045 		switch (keytype) {
4046 		case CKK_DSA:
4047 			return (get_bigint_attr_from_object(
4048 			    OBJ_PRI_DSA_SUBPRIME(object_p), template));
4049 
4050 		case CKK_X9_42_DH:
4051 			return (get_bigint_attr_from_object(
4052 			    OBJ_PRI_DH942_SUBPRIME(object_p), template));
4053 
4054 		default:
4055 			template->ulValueLen = (CK_ULONG)-1;
4056 			return (CKR_ATTRIBUTE_TYPE_INVALID);
4057 		}
4058 
4059 	case CKA_BASE:
4060 		switch (keytype) {
4061 		case CKK_DSA:
4062 			return (get_bigint_attr_from_object(
4063 			    OBJ_PRI_DSA_BASE(object_p), template));
4064 
4065 		case CKK_DH:
4066 			return (get_bigint_attr_from_object(
4067 			    OBJ_PRI_DH_BASE(object_p), template));
4068 
4069 		case CKK_X9_42_DH:
4070 			return (get_bigint_attr_from_object(
4071 			    OBJ_PRI_DH942_BASE(object_p), template));
4072 
4073 		default:
4074 			template->ulValueLen = (CK_ULONG)-1;
4075 			return (CKR_ATTRIBUTE_TYPE_INVALID);
4076 		}
4077 
4078 	case CKA_VALUE:
4079 		switch (keytype) {
4080 		case CKK_DSA:
4081 			return (get_bigint_attr_from_object(
4082 			    OBJ_PRI_DSA_VALUE(object_p), template));
4083 
4084 		case CKK_DH:
4085 			return (get_bigint_attr_from_object(
4086 			    OBJ_PRI_DH_VALUE(object_p), template));
4087 
4088 		case CKK_X9_42_DH:
4089 			return (get_bigint_attr_from_object(
4090 			    OBJ_PRI_DH942_VALUE(object_p), template));
4091 
4092 		default:
4093 			template->ulValueLen = (CK_ULONG)-1;
4094 			return (CKR_ATTRIBUTE_TYPE_INVALID);
4095 		}
4096 
4097 	default:
4098 		/*
4099 		 * First, get the value of the request attribute defined
4100 		 * in the list of common key attributes. If the request
4101 		 * attribute is not found in that list, then get the
4102 		 * attribute from the list of common attributes.
4103 		 */
4104 		rv = soft_get_common_key_attrs(object_p, template);
4105 		if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
4106 			rv = soft_get_common_attrs(object_p, template,
4107 			    object_p->object_type);
4108 		}
4109 		break;
4110 	}
4111 
4112 	return (rv);
4113 }
4114 
4115 
4116 /*
4117  * Get the value of a requested attribute of a Secret Key Object.
4118  *
4119  * Rule: All the attributes in the secret key object can be revealed
4120  *       except those marked with footnote number "7" when the object
4121  *       has its CKA_SENSITIVE attribute set to TRUE or its
4122  *       CKA_EXTRACTABLE attribute set to FALSE (p.88 in PKCS11 spec.).
4123  */
4124 CK_RV
4125 soft_get_secret_key_attribute(soft_object_t *object_p,
4126 	CK_ATTRIBUTE_PTR template)
4127 {
4128 
4129 	CK_RV		rv = CKR_OK;
4130 	CK_KEY_TYPE	keytype = object_p->key_type;
4131 
4132 	switch (template->type) {
4133 
4134 	/* Key related boolean attributes */
4135 	case CKA_SENSITIVE:
4136 		return (get_bool_attr_from_object(object_p,
4137 		    SENSITIVE_BOOL_ON, template));
4138 
4139 	case CKA_ENCRYPT:
4140 		return (get_bool_attr_from_object(object_p,
4141 		    ENCRYPT_BOOL_ON, template));
4142 
4143 	case CKA_DECRYPT:
4144 		return (get_bool_attr_from_object(object_p,
4145 		    DECRYPT_BOOL_ON, template));
4146 
4147 	case CKA_SIGN:
4148 		return (get_bool_attr_from_object(object_p,
4149 		    SIGN_BOOL_ON, template));
4150 
4151 	case CKA_VERIFY:
4152 		return (get_bool_attr_from_object(object_p,
4153 		    VERIFY_BOOL_ON, template));
4154 
4155 	case CKA_WRAP:
4156 		return (get_bool_attr_from_object(object_p,
4157 		    WRAP_BOOL_ON, template));
4158 
4159 	case CKA_UNWRAP:
4160 		return (get_bool_attr_from_object(object_p,
4161 		    UNWRAP_BOOL_ON, template));
4162 
4163 	case CKA_EXTRACTABLE:
4164 		return (get_bool_attr_from_object(object_p,
4165 		    EXTRACTABLE_BOOL_ON, template));
4166 
4167 	case CKA_ALWAYS_SENSITIVE:
4168 		return (get_bool_attr_from_object(object_p,
4169 		    ALWAYS_SENSITIVE_BOOL_ON, template));
4170 
4171 	case CKA_NEVER_EXTRACTABLE:
4172 		return (get_bool_attr_from_object(object_p,
4173 		    NEVER_EXTRACTABLE_BOOL_ON, template));
4174 
4175 	case CKA_VALUE:
4176 	case CKA_VALUE_LEN:
4177 		/*
4178 		 * If the specified attribute for the secret key object
4179 		 * cannot be revealed because the object is sensitive
4180 		 * or unextractable, then the ulValueLen is set to -1.
4181 		 */
4182 		if ((object_p->bool_attr_mask & SENSITIVE_BOOL_ON) ||
4183 		    !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
4184 			template->ulValueLen = (CK_ULONG)-1;
4185 			return (CKR_ATTRIBUTE_SENSITIVE);
4186 		}
4187 
4188 		switch (keytype) {
4189 		case CKK_RC4:
4190 		case CKK_GENERIC_SECRET:
4191 		case CKK_RC5:
4192 		case CKK_DES:
4193 		case CKK_DES2:
4194 		case CKK_DES3:
4195 		case CKK_CDMF:
4196 		case CKK_AES:
4197 			if (template->type == CKA_VALUE_LEN) {
4198 				return (get_ulong_attr_from_object(
4199 				    OBJ_SEC_VALUE_LEN(object_p),
4200 				    template));
4201 			} else {
4202 				return (get_bigint_attr_from_object(
4203 				    (biginteger_t *)OBJ_SEC(object_p),
4204 				    template));
4205 			}
4206 		default:
4207 			template->ulValueLen = (CK_ULONG)-1;
4208 			rv = CKR_ATTRIBUTE_TYPE_INVALID;
4209 			break;
4210 		}
4211 		break;
4212 
4213 	default:
4214 		/*
4215 		 * First, get the value of the request attribute defined
4216 		 * in the list of common key attributes. If the request
4217 		 * attribute is not found in that list, then get the
4218 		 * attribute from the list of common attributes.
4219 		 */
4220 		rv = soft_get_common_key_attrs(object_p, template);
4221 		if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
4222 			rv = soft_get_common_attrs(object_p, template,
4223 			    object_p->object_type);
4224 		}
4225 		break;
4226 	}
4227 
4228 	return (rv);
4229 }
4230 
4231 
4232 /*
4233  * Get the value of a requested attribute of a Domain Parameters Object.
4234  *
4235  * Rule: All the attributes in the domain parameters object can be revealed.
4236  */
4237 CK_RV
4238 soft_get_domain_parameters_attribute(soft_object_t *object_p,
4239 	CK_ATTRIBUTE_PTR template)
4240 {
4241 
4242 	CK_RV		rv = CKR_OK;
4243 	CK_KEY_TYPE	keytype = object_p->key_type;
4244 
4245 	switch (template->type) {
4246 
4247 	case CKA_KEY_TYPE:
4248 		return (get_ulong_attr_from_object(keytype,
4249 		    template));
4250 
4251 	case CKA_LOCAL:
4252 		return (get_bool_attr_from_object(object_p,
4253 		    LOCAL_BOOL_ON, template));
4254 
4255 	case CKA_PRIME:
4256 		switch (keytype) {
4257 		case CKK_DSA:
4258 			return (get_bigint_attr_from_object(
4259 			    OBJ_DOM_DSA_PRIME(object_p), template));
4260 
4261 		case CKK_DH:
4262 			return (get_bigint_attr_from_object(
4263 			    OBJ_DOM_DH_PRIME(object_p), template));
4264 
4265 		case CKK_X9_42_DH:
4266 			return (get_bigint_attr_from_object(
4267 			    OBJ_DOM_DH942_PRIME(object_p), template));
4268 
4269 		default:
4270 			template->ulValueLen = (CK_ULONG)-1;
4271 			return (CKR_ATTRIBUTE_TYPE_INVALID);
4272 		}
4273 
4274 	case CKA_SUBPRIME:
4275 		switch (keytype) {
4276 		case CKK_DSA:
4277 			return (get_bigint_attr_from_object(
4278 			    OBJ_DOM_DSA_SUBPRIME(object_p), template));
4279 
4280 		case CKK_X9_42_DH:
4281 			return (get_bigint_attr_from_object(
4282 			    OBJ_DOM_DH942_SUBPRIME(object_p), template));
4283 
4284 		default:
4285 			template->ulValueLen = (CK_ULONG)-1;
4286 			return (CKR_ATTRIBUTE_TYPE_INVALID);
4287 		}
4288 
4289 	case CKA_BASE:
4290 		switch (keytype) {
4291 		case CKK_DSA:
4292 			return (get_bigint_attr_from_object(
4293 			    OBJ_DOM_DSA_BASE(object_p), template));
4294 
4295 		case CKK_DH:
4296 			return (get_bigint_attr_from_object(
4297 			    OBJ_DOM_DH_BASE(object_p), template));
4298 
4299 		case CKK_X9_42_DH:
4300 			return (get_bigint_attr_from_object(
4301 			    OBJ_DOM_DH942_BASE(object_p), template));
4302 
4303 		default:
4304 			template->ulValueLen = (CK_ULONG)-1;
4305 			return (CKR_ATTRIBUTE_TYPE_INVALID);
4306 		}
4307 
4308 	case CKA_PRIME_BITS:
4309 		switch (keytype) {
4310 		case CKK_DSA:
4311 			return (get_ulong_attr_from_object(
4312 			    OBJ_DOM_DSA_PRIME_BITS(object_p), template));
4313 
4314 		case CKK_DH:
4315 			return (get_ulong_attr_from_object(
4316 			    OBJ_DOM_DH_PRIME_BITS(object_p), template));
4317 
4318 		case CKK_X9_42_DH:
4319 			return (get_ulong_attr_from_object(
4320 			    OBJ_DOM_DH942_PRIME_BITS(object_p), template));
4321 
4322 		default:
4323 			template->ulValueLen = (CK_ULONG)-1;
4324 			return (CKR_ATTRIBUTE_TYPE_INVALID);
4325 		}
4326 
4327 	case CKA_SUB_PRIME_BITS:
4328 		switch (keytype) {
4329 		case CKK_X9_42_DH:
4330 			return (get_ulong_attr_from_object(
4331 			    OBJ_DOM_DH942_SUBPRIME_BITS(object_p), template));
4332 
4333 		default:
4334 			template->ulValueLen = (CK_ULONG)-1;
4335 			return (CKR_ATTRIBUTE_TYPE_INVALID);
4336 		}
4337 
4338 	default:
4339 		/*
4340 		 * Get the value of a common attribute.
4341 		 */
4342 		rv = soft_get_common_attrs(object_p, template,
4343 		    object_p->object_type);
4344 		break;
4345 	}
4346 
4347 	return (rv);
4348 }
4349 
4350 /*
4351  * Get certificate attributes from an object.
4352  * return CKR_ATTRIBUTE_TYPE_INVALID if the requested type
4353  * does not exist in the certificate.
4354  */
4355 CK_RV
4356 soft_get_certificate_attribute(soft_object_t *object_p,
4357 	CK_ATTRIBUTE_PTR template)
4358 {
4359 	CK_CERTIFICATE_TYPE certtype = object_p->cert_type;
4360 	cert_attr_t src;
4361 
4362 	switch (template->type) {
4363 		case CKA_SUBJECT:
4364 			if (certtype == CKC_X_509) {
4365 				return (get_cert_attr_from_object(
4366 					X509_CERT_SUBJECT(object_p), template));
4367 			}
4368 			break;
4369 		case CKA_VALUE:
4370 			if (certtype == CKC_X_509) {
4371 			    return (get_cert_attr_from_object(
4372 				X509_CERT_VALUE(object_p), template));
4373 			} else if (certtype == CKC_X_509_ATTR_CERT) {
4374 			    return (get_cert_attr_from_object(
4375 				X509_ATTR_CERT_VALUE(object_p),
4376 				template));
4377 			}
4378 			break;
4379 		case CKA_OWNER:
4380 			if (certtype == CKC_X_509_ATTR_CERT) {
4381 				return (get_cert_attr_from_object(
4382 					X509_ATTR_CERT_OWNER(object_p),
4383 					template));
4384 			}
4385 			break;
4386 		case CKA_CERTIFICATE_TYPE:
4387 			src.value = (CK_BYTE *)&certtype;
4388 			src.length = sizeof (certtype);
4389 			return (get_cert_attr_from_object(&src, template));
4390 			break;
4391 		case CKA_TRUSTED:
4392 			return (get_bool_attr_from_object(object_p,
4393 				TRUSTED_BOOL_ON, template));
4394 		case CKA_ID:
4395 		case CKA_ISSUER:
4396 		case CKA_SERIAL_NUMBER:
4397 		case CKA_AC_ISSUER:
4398 		case CKA_ATTR_TYPES:
4399 			return (get_extra_attr_from_object(object_p,
4400 				template));
4401 			break;
4402 		default:
4403 			return (soft_get_common_attrs(object_p, template,
4404 				object_p->object_type));
4405 			break;
4406 	}
4407 
4408 	/*
4409 	 * If we got this far, then the combination of certificate type
4410 	 * and requested attribute is invalid.
4411 	 */
4412 	return (CKR_ATTRIBUTE_TYPE_INVALID);
4413 }
4414 
4415 CK_RV
4416 soft_set_certificate_attribute(soft_object_t *object_p,
4417 	CK_ATTRIBUTE_PTR template, boolean_t copy)
4418 {
4419 	CK_CERTIFICATE_TYPE certtype = object_p->cert_type;
4420 
4421 	switch (template->type) {
4422 		case CKA_SUBJECT:
4423 			if (certtype == CKC_X_509) {
4424 				/* SUBJECT attr cannot be modified. */
4425 				return (CKR_ATTRIBUTE_READ_ONLY);
4426 			}
4427 			break;
4428 		case CKA_OWNER:
4429 			if (certtype == CKC_X_509_ATTR_CERT) {
4430 				/* OWNER attr cannot be modified. */
4431 				return (CKR_ATTRIBUTE_READ_ONLY);
4432 			}
4433 			break;
4434 		case CKA_VALUE:
4435 			/* VALUE attr cannot be modified. */
4436 			return (CKR_ATTRIBUTE_READ_ONLY);
4437 			break;
4438 		case CKA_ID:
4439 		case CKA_ISSUER:
4440 			if (certtype == CKC_X_509) {
4441 				return (set_extra_attr_to_object(object_p,
4442 					template->type, template));
4443 			}
4444 			break;
4445 		case CKA_AC_ISSUER:
4446 		case CKA_ATTR_TYPES:
4447 			if (certtype == CKC_X_509_ATTR_CERT) {
4448 				return (set_extra_attr_to_object(object_p,
4449 					template->type, template));
4450 			}
4451 			break;
4452 		case CKA_SERIAL_NUMBER:
4453 		case CKA_LABEL:
4454 			return (set_extra_attr_to_object(object_p,
4455 				template->type, template));
4456 			break;
4457 		default:
4458 			return (soft_set_common_storage_attribute(
4459 			    object_p, template, copy));
4460 			break;
4461 	}
4462 
4463 	/*
4464 	 * If we got this far, then the combination of certificate type
4465 	 * and requested attribute is invalid.
4466 	 */
4467 	return (CKR_ATTRIBUTE_TYPE_INVALID);
4468 }
4469 
4470 /*
4471  * Call the appropriate get attribute function according to the class
4472  * of object.
4473  *
4474  * The caller of this function holds the lock on the object.
4475  */
4476 CK_RV
4477 soft_get_attribute(soft_object_t *object_p, CK_ATTRIBUTE_PTR template)
4478 {
4479 
4480 	CK_RV		rv = CKR_OK;
4481 	CK_OBJECT_CLASS class = object_p->class;
4482 
4483 	switch (class) {
4484 	case CKO_PUBLIC_KEY:
4485 		rv = soft_get_public_key_attribute(object_p, template);
4486 		break;
4487 
4488 	case CKO_PRIVATE_KEY:
4489 		rv = soft_get_private_key_attribute(object_p, template);
4490 		break;
4491 
4492 	case CKO_SECRET_KEY:
4493 		rv = soft_get_secret_key_attribute(object_p, template);
4494 		break;
4495 
4496 	case CKO_DOMAIN_PARAMETERS:
4497 		rv = soft_get_domain_parameters_attribute(object_p, template);
4498 		break;
4499 
4500 	case CKO_CERTIFICATE:
4501 		rv = soft_get_certificate_attribute(object_p, template);
4502 		break;
4503 
4504 	default:
4505 		/*
4506 		 * If the specified attribute for the object is invalid
4507 		 * (the object does not possess such as attribute), then
4508 		 * the ulValueLen is modified to hold the value -1.
4509 		 */
4510 		template->ulValueLen = (CK_ULONG)-1;
4511 		return (CKR_ATTRIBUTE_TYPE_INVALID);
4512 	}
4513 
4514 	return (rv);
4515 
4516 }
4517 
4518 CK_RV
4519 soft_set_common_storage_attribute(soft_object_t *object_p,
4520 	CK_ATTRIBUTE_PTR template, boolean_t copy)
4521 {
4522 
4523 	CK_RV rv = CKR_OK;
4524 
4525 	switch (template->type) {
4526 
4527 	case CKA_TOKEN:
4528 		if (copy) {
4529 			if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
4530 				if (!soft_token_present)
4531 					return (CKR_DEVICE_REMOVED);
4532 				object_p->object_type |= TOKEN_OBJECT;
4533 			}
4534 		} else {
4535 			rv = CKR_ATTRIBUTE_READ_ONLY;
4536 		}
4537 
4538 		break;
4539 
4540 	case CKA_PRIVATE:
4541 		if (copy) {
4542 			if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
4543 				(void) pthread_mutex_lock(&soft_giant_mutex);
4544 				if (!soft_slot.authenticated) {
4545 					/*
4546 					 * Check if this is the special case
4547 					 * when the PIN is never initialized
4548 					 * in the keystore. If true, we will
4549 					 * let it pass here and let it fail
4550 					 * with CKR_PIN_EXPIRED later on.
4551 					 */
4552 					if (!soft_slot.userpin_change_needed) {
4553 						(void) pthread_mutex_unlock(
4554 						    &soft_giant_mutex);
4555 						return (CKR_USER_NOT_LOGGED_IN);
4556 					}
4557 				}
4558 				(void) pthread_mutex_unlock(&soft_giant_mutex);
4559 				object_p->object_type |= PRIVATE_OBJECT;
4560 			}
4561 		} else {
4562 			rv = CKR_ATTRIBUTE_READ_ONLY;
4563 		}
4564 		break;
4565 
4566 	case CKA_MODIFIABLE:
4567 		if (copy) {
4568 			if ((*(CK_BBOOL *)template->pValue) == TRUE)
4569 				object_p->bool_attr_mask &=
4570 				    ~NOT_MODIFIABLE_BOOL_ON;
4571 			else
4572 				object_p->bool_attr_mask |=
4573 				    NOT_MODIFIABLE_BOOL_ON;
4574 		} else {
4575 			rv = CKR_ATTRIBUTE_READ_ONLY;
4576 		}
4577 		break;
4578 
4579 	case CKA_CLASS:
4580 		rv = CKR_ATTRIBUTE_READ_ONLY;
4581 		break;
4582 
4583 	default:
4584 		rv = CKR_TEMPLATE_INCONSISTENT;
4585 	}
4586 
4587 	return (rv);
4588 }
4589 
4590 /*
4591  * Set the value of an attribute that is common to all key objects
4592  * (i.e. public key, private key and secret key).
4593  */
4594 CK_RV
4595 soft_set_common_key_attribute(soft_object_t *object_p,
4596 	CK_ATTRIBUTE_PTR template, boolean_t copy)
4597 {
4598 
4599 	switch (template->type) {
4600 
4601 	case CKA_LABEL:
4602 		/*
4603 		 * Only the LABEL can be modified in the common storage
4604 		 * object attributes after the object is created.
4605 		 */
4606 		return (set_extra_attr_to_object(object_p,
4607 		    CKA_LABEL, template));
4608 
4609 	case CKA_ID:
4610 		return (set_extra_attr_to_object(object_p,
4611 		    CKA_ID, template));
4612 
4613 	case CKA_START_DATE:
4614 		return (set_extra_attr_to_object(object_p,
4615 		    CKA_START_DATE, template));
4616 
4617 	case CKA_END_DATE:
4618 		return (set_extra_attr_to_object(object_p,
4619 		    CKA_END_DATE, template));
4620 
4621 	case CKA_DERIVE:
4622 		return (set_bool_attr_to_object(object_p,
4623 		    DERIVE_BOOL_ON, template));
4624 
4625 	case CKA_KEY_TYPE:
4626 	case CKA_LOCAL:
4627 	case CKA_KEY_GEN_MECHANISM:
4628 		return (CKR_ATTRIBUTE_READ_ONLY);
4629 
4630 	default:
4631 		return (soft_set_common_storage_attribute(object_p,
4632 		    template, copy));
4633 
4634 	}
4635 
4636 }
4637 
4638 
4639 /*
4640  * Set the value of an attribute of a Public Key Object.
4641  *
4642  * Rule: The attributes marked with footnote number "8" in the PKCS11
4643  *       spec may be modified (p.88 in PKCS11 spec.).
4644  */
4645 CK_RV
4646 soft_set_public_key_attribute(soft_object_t *object_p,
4647 	CK_ATTRIBUTE_PTR template, boolean_t copy)
4648 {
4649 	CK_KEY_TYPE	keytype = object_p->key_type;
4650 
4651 	switch (template->type) {
4652 
4653 	case CKA_SUBJECT:
4654 		return (set_extra_attr_to_object(object_p,
4655 		    CKA_SUBJECT, template));
4656 
4657 	case CKA_ENCRYPT:
4658 		return (set_bool_attr_to_object(object_p,
4659 		    ENCRYPT_BOOL_ON, template));
4660 
4661 	case CKA_VERIFY:
4662 		return (set_bool_attr_to_object(object_p,
4663 		    VERIFY_BOOL_ON, template));
4664 
4665 	case CKA_VERIFY_RECOVER:
4666 		return (set_bool_attr_to_object(object_p,
4667 		    VERIFY_RECOVER_BOOL_ON, template));
4668 
4669 	case CKA_WRAP:
4670 		return (set_bool_attr_to_object(object_p,
4671 		    WRAP_BOOL_ON, template));
4672 
4673 	case CKA_MODULUS:
4674 	case CKA_MODULUS_BITS:
4675 	case CKA_PUBLIC_EXPONENT:
4676 		if (keytype == CKK_RSA)
4677 			return (CKR_ATTRIBUTE_READ_ONLY);
4678 		break;
4679 
4680 	case CKA_SUBPRIME:
4681 		if ((keytype == CKK_DSA) ||
4682 		    (keytype == CKK_X9_42_DH))
4683 			return (CKR_ATTRIBUTE_READ_ONLY);
4684 		break;
4685 
4686 	case CKA_PRIME:
4687 	case CKA_BASE:
4688 	case CKA_VALUE:
4689 		if ((keytype == CKK_DSA) ||
4690 		    (keytype == CKK_DH) ||
4691 		    (keytype == CKK_X9_42_DH))
4692 			return (CKR_ATTRIBUTE_READ_ONLY);
4693 		break;
4694 
4695 	default:
4696 		/*
4697 		 * Set the value of a common key attribute.
4698 		 */
4699 		return (soft_set_common_key_attribute(object_p,
4700 		    template, copy));
4701 
4702 	}
4703 	/*
4704 	 * If we got this far, then the combination of key type
4705 	 * and requested attribute is invalid.
4706 	 */
4707 	return (CKR_ATTRIBUTE_TYPE_INVALID);
4708 }
4709 
4710 
4711 /*
4712  * Set the value of an attribute of a Private Key Object.
4713  *
4714  * Rule: The attributes marked with footnote number "8" in the PKCS11
4715  *       spec may be modified (p.88 in PKCS11 spec.).
4716  */
4717 CK_RV
4718 soft_set_private_key_attribute(soft_object_t *object_p,
4719 	CK_ATTRIBUTE_PTR template, boolean_t copy)
4720 {
4721 	CK_KEY_TYPE	keytype = object_p->key_type;
4722 
4723 	switch (template->type) {
4724 
4725 	case CKA_SUBJECT:
4726 		return (set_extra_attr_to_object(object_p,
4727 		    CKA_SUBJECT, template));
4728 
4729 	case CKA_SENSITIVE:
4730 		/*
4731 		 * Cannot set SENSITIVE to FALSE if it is already ON.
4732 		 */
4733 		if (((*(CK_BBOOL *)template->pValue) == B_FALSE) &&
4734 		    (object_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
4735 			return (CKR_ATTRIBUTE_READ_ONLY);
4736 		}
4737 
4738 		if (*(CK_BBOOL *)template->pValue)
4739 			object_p->bool_attr_mask |= SENSITIVE_BOOL_ON;
4740 		return (CKR_OK);
4741 
4742 	case CKA_DECRYPT:
4743 		return (set_bool_attr_to_object(object_p,
4744 		    DECRYPT_BOOL_ON, template));
4745 
4746 	case CKA_SIGN:
4747 		return (set_bool_attr_to_object(object_p,
4748 		    SIGN_BOOL_ON, template));
4749 
4750 	case CKA_SIGN_RECOVER:
4751 		return (set_bool_attr_to_object(object_p,
4752 		    SIGN_RECOVER_BOOL_ON, template));
4753 
4754 	case CKA_UNWRAP:
4755 		return (set_bool_attr_to_object(object_p,
4756 		    UNWRAP_BOOL_ON, template));
4757 
4758 	case CKA_EXTRACTABLE:
4759 		/*
4760 		 * Cannot set EXTRACTABLE to TRUE if it is already OFF.
4761 		 */
4762 		if ((*(CK_BBOOL *)template->pValue) &&
4763 		    !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
4764 			return (CKR_ATTRIBUTE_READ_ONLY);
4765 		}
4766 
4767 		if ((*(CK_BBOOL *)template->pValue) == B_FALSE)
4768 			object_p->bool_attr_mask &= ~EXTRACTABLE_BOOL_ON;
4769 		return (CKR_OK);
4770 
4771 	case CKA_MODULUS:
4772 	case CKA_PUBLIC_EXPONENT:
4773 	case CKA_PRIVATE_EXPONENT:
4774 	case CKA_PRIME_1:
4775 	case CKA_PRIME_2:
4776 	case CKA_EXPONENT_1:
4777 	case CKA_EXPONENT_2:
4778 	case CKA_COEFFICIENT:
4779 		if (keytype == CKK_RSA) {
4780 			return (CKR_ATTRIBUTE_READ_ONLY);
4781 		}
4782 		break;
4783 
4784 	case CKA_SUBPRIME:
4785 		if ((keytype == CKK_DSA) ||
4786 		    (keytype == CKK_X9_42_DH))
4787 			return (CKR_ATTRIBUTE_READ_ONLY);
4788 		break;
4789 
4790 	case CKA_PRIME:
4791 	case CKA_BASE:
4792 	case CKA_VALUE:
4793 		if ((keytype == CKK_DSA) ||
4794 		    (keytype == CKK_DH) ||
4795 		    (keytype == CKK_X9_42_DH))
4796 			return (CKR_ATTRIBUTE_READ_ONLY);
4797 		break;
4798 
4799 	case CKA_VALUE_BITS:
4800 		if (keytype == CKK_DH)
4801 			return (CKR_ATTRIBUTE_READ_ONLY);
4802 		break;
4803 
4804 	default:
4805 		/*
4806 		 * Set the value of a common key attribute.
4807 		 */
4808 		return (soft_set_common_key_attribute(object_p,
4809 		    template, copy));
4810 	}
4811 
4812 	/*
4813 	 * If we got this far, then the combination of key type
4814 	 * and requested attribute is invalid.
4815 	 */
4816 	return (CKR_ATTRIBUTE_TYPE_INVALID);
4817 }
4818 
4819 /*
4820  * Set the value of an attribute of a Secret Key Object.
4821  *
4822  * Rule: The attributes marked with footnote number "8" in the PKCS11
4823  *       spec may be modified (p.88 in PKCS11 spec.).
4824  */
4825 CK_RV
4826 soft_set_secret_key_attribute(soft_object_t *object_p,
4827 	CK_ATTRIBUTE_PTR template, boolean_t copy)
4828 {
4829 	CK_KEY_TYPE	keytype = object_p->key_type;
4830 
4831 	switch (template->type) {
4832 
4833 	case CKA_SENSITIVE:
4834 		/*
4835 		 * Cannot set SENSITIVE to FALSE if it is already ON.
4836 		 */
4837 		if (((*(CK_BBOOL *)template->pValue) == B_FALSE) &&
4838 		    (object_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
4839 			return (CKR_ATTRIBUTE_READ_ONLY);
4840 		}
4841 
4842 		if (*(CK_BBOOL *)template->pValue)
4843 			object_p->bool_attr_mask |= SENSITIVE_BOOL_ON;
4844 		return (CKR_OK);
4845 
4846 	case CKA_ENCRYPT:
4847 		return (set_bool_attr_to_object(object_p,
4848 		    ENCRYPT_BOOL_ON, template));
4849 
4850 	case CKA_DECRYPT:
4851 		return (set_bool_attr_to_object(object_p,
4852 		    DECRYPT_BOOL_ON, template));
4853 
4854 	case CKA_SIGN:
4855 		return (set_bool_attr_to_object(object_p,
4856 		    SIGN_BOOL_ON, template));
4857 
4858 	case CKA_VERIFY:
4859 		return (set_bool_attr_to_object(object_p,
4860 		    VERIFY_BOOL_ON, template));
4861 
4862 	case CKA_WRAP:
4863 		return (set_bool_attr_to_object(object_p,
4864 		    WRAP_BOOL_ON, template));
4865 
4866 	case CKA_UNWRAP:
4867 		return (set_bool_attr_to_object(object_p,
4868 		    UNWRAP_BOOL_ON, template));
4869 
4870 	case CKA_EXTRACTABLE:
4871 		/*
4872 		 * Cannot set EXTRACTABLE to TRUE if it is already OFF.
4873 		 */
4874 		if ((*(CK_BBOOL *)template->pValue) &&
4875 		    !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
4876 			return (CKR_ATTRIBUTE_READ_ONLY);
4877 		}
4878 
4879 		if ((*(CK_BBOOL *)template->pValue) == B_FALSE)
4880 			object_p->bool_attr_mask &= ~EXTRACTABLE_BOOL_ON;
4881 		return (CKR_OK);
4882 
4883 	case CKA_VALUE:
4884 		return (CKR_ATTRIBUTE_READ_ONLY);
4885 
4886 	case CKA_VALUE_LEN:
4887 		if ((keytype == CKK_RC4) ||
4888 		    (keytype == CKK_GENERIC_SECRET) ||
4889 		    (keytype == CKK_AES))
4890 			return (CKR_ATTRIBUTE_READ_ONLY);
4891 		break;
4892 
4893 	default:
4894 		/*
4895 		 * Set the value of a common key attribute.
4896 		 */
4897 		return (soft_set_common_key_attribute(object_p,
4898 		    template, copy));
4899 
4900 	}
4901 	/*
4902 	 * If we got this far, then the combination of key type
4903 	 * and requested attribute is invalid.
4904 	 */
4905 	return (CKR_ATTRIBUTE_TYPE_INVALID);
4906 }
4907 
4908 
4909 /*
4910  * Call the appropriate set attribute function according to the class
4911  * of object.
4912  *
4913  * The caller of this function does not hold the lock on the original
4914  * object, since this function is setting the attribute on the new object
4915  * that is being modified.
4916  *
4917  * Argument copy: TRUE when called by C_CopyObject,
4918  *		  FALSE when called by C_SetAttributeValue.
4919  */
4920 CK_RV
4921 soft_set_attribute(soft_object_t *object_p, CK_ATTRIBUTE_PTR template,
4922     boolean_t copy)
4923 {
4924 
4925 	CK_RV		rv = CKR_OK;
4926 	CK_OBJECT_CLASS	class = object_p->class;
4927 
4928 	switch (class) {
4929 
4930 	case CKO_PUBLIC_KEY:
4931 		rv = soft_set_public_key_attribute(object_p, template, copy);
4932 		break;
4933 
4934 	case CKO_PRIVATE_KEY:
4935 		rv = soft_set_private_key_attribute(object_p, template, copy);
4936 		break;
4937 
4938 	case CKO_SECRET_KEY:
4939 		rv = soft_set_secret_key_attribute(object_p, template, copy);
4940 		break;
4941 
4942 	case CKO_DOMAIN_PARAMETERS:
4943 		switch (template->type) {
4944 		case CKA_LABEL:
4945 			/*
4946 			 * Only the LABEL can be modified in the common
4947 			 * storage object attributes after the object is
4948 			 * created.
4949 			 */
4950 			return (set_extra_attr_to_object(object_p,
4951 			    CKA_LABEL, template));
4952 		default:
4953 			return (CKR_TEMPLATE_INCONSISTENT);
4954 		}
4955 	case CKO_CERTIFICATE:
4956 		rv = soft_set_certificate_attribute(object_p, template, copy);
4957 		break;
4958 
4959 	default:
4960 		/*
4961 		 * If the template specifies a value of an attribute
4962 		 * which is incompatible with other existing attributes
4963 		 * of the object, then fails with return code
4964 		 * CKR_TEMPLATE_INCONSISTENT.
4965 		 */
4966 		rv = CKR_TEMPLATE_INCONSISTENT;
4967 		break;
4968 	}
4969 
4970 	return (rv);
4971 }
4972 
4973 CK_RV
4974 soft_get_public_attr(soft_object_t *key, CK_ATTRIBUTE_TYPE type,
4975     uchar_t *value, uint32_t *value_len)
4976 {
4977 	uint32_t len = 0;
4978 	switch (type) {
4979 
4980 	/* The following attributes belong to RSA */
4981 	case CKA_MODULUS:
4982 #ifdef	__sparcv9
4983 		len =
4984 		    /* LINTED */
4985 		    (uint32_t)
4986 		    ((biginteger_t *)OBJ_PUB_RSA_MOD(key))->big_value_len;
4987 #else	/* !__sparcv9 */
4988 		len =
4989 		    ((biginteger_t *)OBJ_PUB_RSA_MOD(key))->big_value_len;
4990 #endif	/* __sparcv9 */
4991 
4992 		/* This attribute MUST BE set */
4993 		if (len == 0 || len > *value_len) {
4994 			return (CKR_ATTRIBUTE_VALUE_INVALID);
4995 		}
4996 		*value_len = len;
4997 
4998 		(void) memcpy(value,
4999 		    ((biginteger_t *)OBJ_PUB_RSA_MOD(key))->big_value,
5000 		    *value_len);
5001 
5002 		break;
5003 
5004 	case CKA_PUBLIC_EXPONENT:
5005 #ifdef	__sparcv9
5006 		len =
5007 		    /* LINTED */
5008 		    (uint32_t)
5009 		    ((biginteger_t *)OBJ_PUB_RSA_PUBEXPO(key))->big_value_len;
5010 #else	/* !__sparcv9 */
5011 		len =
5012 		    ((biginteger_t *)OBJ_PUB_RSA_PUBEXPO(key))->big_value_len;
5013 #endif	/* __sparcv9 */
5014 
5015 		/* This attribute MUST BE set */
5016 		if (len == 0 || len > *value_len) {
5017 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5018 		}
5019 		*value_len = len;
5020 
5021 		(void) memcpy(value,
5022 		    ((biginteger_t *)OBJ_PUB_RSA_PUBEXPO(key))->big_value,
5023 		    *value_len);
5024 
5025 		break;
5026 
5027 	/* The following attributes belong to DSA and DH */
5028 	case CKA_PRIME:
5029 
5030 		if (key->key_type == CKK_DSA)
5031 #ifdef	__sparcv9
5032 			len =
5033 			    /* LINTED */
5034 			    (uint32_t)
5035 			    ((biginteger_t *)OBJ_PUB_DSA_PRIME(key))->
5036 			    big_value_len;
5037 #else	/* !__sparcv9 */
5038 			len =
5039 			    ((biginteger_t *)OBJ_PUB_DSA_PRIME(key))->
5040 			    big_value_len;
5041 #endif	/* __sparcv9 */
5042 		else
5043 #ifdef	__sparcv9
5044 			len =
5045 			    /* LINTED */
5046 			    (uint32_t)
5047 			    ((biginteger_t *)OBJ_PUB_DH_PRIME(key))->
5048 			    big_value_len;
5049 #else	/* !__sparcv9 */
5050 			len =
5051 			    ((biginteger_t *)OBJ_PUB_DH_PRIME(key))->
5052 			    big_value_len;
5053 #endif	/* __sparcv9 */
5054 
5055 		/* This attribute MUST BE set */
5056 		if (len == 0 || len > *value_len) {
5057 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5058 		}
5059 		*value_len = len;
5060 
5061 		if (key->key_type == CKK_DSA)
5062 			(void) memcpy(value,
5063 			    ((biginteger_t *)OBJ_PUB_DSA_PRIME(key))->big_value,
5064 			    *value_len);
5065 		else
5066 			(void) memcpy(value,
5067 			    ((biginteger_t *)OBJ_PUB_DH_PRIME(key))->big_value,
5068 			    *value_len);
5069 
5070 		break;
5071 
5072 	case CKA_SUBPRIME:
5073 #ifdef	__sparcv9
5074 		len =
5075 		    /* LINTED */
5076 		    (uint32_t)
5077 		    ((biginteger_t *)OBJ_PUB_DSA_SUBPRIME(key))->big_value_len;
5078 #else	/* !__sparcv9 */
5079 		len =
5080 		    ((biginteger_t *)OBJ_PUB_DSA_SUBPRIME(key))->big_value_len;
5081 #endif	/* __sparcv9 */
5082 
5083 		/* This attribute MUST BE set */
5084 		if (len == 0 || len > *value_len) {
5085 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5086 		}
5087 		*value_len = len;
5088 
5089 		(void) memcpy(value,
5090 		    ((biginteger_t *)OBJ_PUB_DSA_SUBPRIME(key))->big_value,
5091 		    *value_len);
5092 
5093 		break;
5094 
5095 	case CKA_BASE:
5096 
5097 		if (key->key_type == CKK_DSA)
5098 #ifdef	__sparcv9
5099 			len =
5100 			    /* LINTED */
5101 			    (uint32_t)
5102 			    ((biginteger_t *)OBJ_PUB_DSA_BASE(key))->
5103 			    big_value_len;
5104 #else	/* !__sparcv9 */
5105 			len =
5106 			    ((biginteger_t *)OBJ_PUB_DSA_BASE(key))->
5107 			    big_value_len;
5108 #endif	/* __sparcv9 */
5109 		else
5110 #ifdef	__sparcv9
5111 			len =
5112 			    /* LINTED */
5113 			    (uint32_t)
5114 			    ((biginteger_t *)OBJ_PUB_DH_BASE(key))->
5115 			    big_value_len;
5116 #else	/* !__sparcv9 */
5117 			len =
5118 			    ((biginteger_t *)OBJ_PUB_DH_BASE(key))->
5119 			    big_value_len;
5120 #endif	/* __sparcv9 */
5121 
5122 		/* This attribute MUST BE set */
5123 		if (len == 0 || len > *value_len) {
5124 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5125 		}
5126 		*value_len = len;
5127 
5128 		if (key->key_type == CKK_DSA)
5129 			(void) memcpy(value,
5130 			    ((biginteger_t *)OBJ_PUB_DSA_BASE(key))->big_value,
5131 			    *value_len);
5132 		else
5133 			(void) memcpy(value,
5134 			    ((biginteger_t *)OBJ_PUB_DH_BASE(key))->big_value,
5135 			    *value_len);
5136 		break;
5137 
5138 	case CKA_VALUE:
5139 
5140 		if (key->key_type == CKK_DSA)
5141 #ifdef	__sparcv9
5142 			len =
5143 			    /* LINTED */
5144 			    (uint32_t)
5145 			    ((biginteger_t *)OBJ_PUB_DSA_VALUE(key))->
5146 			    big_value_len;
5147 #else	/* !__sparcv9 */
5148 			len =
5149 			    ((biginteger_t *)OBJ_PUB_DSA_VALUE(key))->
5150 			    big_value_len;
5151 #endif	/* __sparcv9 */
5152 		else
5153 #ifdef	__sparcv9
5154 			len =
5155 			    /* LINTED */
5156 			    (uint32_t)
5157 			    ((biginteger_t *)OBJ_PUB_DH_VALUE(key))->
5158 			    big_value_len;
5159 #else	/* !__sparcv9 */
5160 			len =
5161 			    ((biginteger_t *)OBJ_PUB_DH_VALUE(key))->
5162 			    big_value_len;
5163 #endif	/* __sparcv9 */
5164 
5165 		/* This attribute MUST BE set */
5166 		if (len == 0 || len > *value_len) {
5167 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5168 		}
5169 		*value_len = len;
5170 
5171 		if (key->key_type == CKK_DSA)
5172 			(void) memcpy(value,
5173 			    ((biginteger_t *)OBJ_PUB_DSA_VALUE(key))->big_value,
5174 			    *value_len);
5175 		else
5176 			(void) memcpy(value,
5177 			    ((biginteger_t *)OBJ_PUB_DH_VALUE(key))->big_value,
5178 			    *value_len);
5179 
5180 		break;
5181 	}
5182 
5183 	return (CKR_OK);
5184 }
5185 
5186 
5187 CK_RV
5188 soft_get_private_attr(soft_object_t *key, CK_ATTRIBUTE_TYPE type,
5189     uchar_t *value, uint32_t *value_len)
5190 {
5191 
5192 	uint32_t len = 0;
5193 
5194 	switch (type) {
5195 
5196 	/* The following attributes belong to RSA */
5197 	case CKA_MODULUS:
5198 #ifdef	__sparcv9
5199 		len =
5200 		    /* LINTED */
5201 		    (uint32_t)
5202 		    ((biginteger_t *)OBJ_PRI_RSA_MOD(key))->big_value_len;
5203 #else	/* !__sparcv9 */
5204 		len =
5205 		    ((biginteger_t *)OBJ_PRI_RSA_MOD(key))->big_value_len;
5206 #endif	/* __sparcv9 */
5207 
5208 		/* This attribute MUST BE set */
5209 		if (len == 0 || len > *value_len) {
5210 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5211 		}
5212 		*value_len = len;
5213 
5214 		(void) memcpy(value,
5215 		    ((biginteger_t *)OBJ_PRI_RSA_MOD(key))->big_value,
5216 		    *value_len);
5217 
5218 		break;
5219 
5220 	case CKA_PRIVATE_EXPONENT:
5221 #ifdef	__sparcv9
5222 		len =
5223 		    /* LINTED */
5224 		    (uint32_t)
5225 		    ((biginteger_t *)OBJ_PRI_RSA_PRIEXPO(key))->big_value_len;
5226 #else	/* !__sparcv9 */
5227 		len =
5228 		    ((biginteger_t *)OBJ_PRI_RSA_PRIEXPO(key))->big_value_len;
5229 #endif	/* __sparcv9 */
5230 
5231 		/* This attribute MUST BE set */
5232 		if (len == 0 || len > *value_len) {
5233 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5234 		}
5235 		*value_len = len;
5236 
5237 		(void) memcpy(value,
5238 		    ((biginteger_t *)OBJ_PRI_RSA_PRIEXPO(key))->big_value,
5239 		    *value_len);
5240 
5241 		break;
5242 
5243 	case CKA_PRIME_1:
5244 #ifdef	__sparcv9
5245 		len =
5246 		    /* LINTED */
5247 		    (uint32_t)
5248 		    ((biginteger_t *)OBJ_PRI_RSA_PRIME1(key))->big_value_len;
5249 #else	/* !__sparcv9 */
5250 		len =
5251 		    ((biginteger_t *)OBJ_PRI_RSA_PRIME1(key))->big_value_len;
5252 #endif	/* __sparcv9 */
5253 
5254 		if (len > *value_len) {
5255 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5256 		}
5257 		*value_len = len;
5258 
5259 		if (*value_len == 0) {
5260 			return (CKR_OK);
5261 		}
5262 
5263 		(void) memcpy(value,
5264 		    ((biginteger_t *)OBJ_PRI_RSA_PRIME1(key))->big_value,
5265 		    *value_len);
5266 
5267 		break;
5268 
5269 	case CKA_PRIME_2:
5270 #ifdef	__sparcv9
5271 		len =
5272 		    /* LINTED */
5273 		    (uint32_t)
5274 		    ((biginteger_t *)OBJ_PRI_RSA_PRIME2(key))->big_value_len;
5275 #else	/* !__sparcv9 */
5276 		len =
5277 		    ((biginteger_t *)OBJ_PRI_RSA_PRIME2(key))->big_value_len;
5278 #endif	/* __sparcv9 */
5279 
5280 		if (len > *value_len) {
5281 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5282 		}
5283 		*value_len = len;
5284 
5285 		if (*value_len == 0) {
5286 			return (CKR_OK);
5287 		}
5288 
5289 		(void) memcpy(value,
5290 		    ((biginteger_t *)OBJ_PRI_RSA_PRIME2(key))->big_value,
5291 		    *value_len);
5292 
5293 		break;
5294 
5295 	case CKA_EXPONENT_1:
5296 #ifdef	__sparcv9
5297 		len =
5298 		    /* LINTED */
5299 		    (uint32_t)
5300 		    ((biginteger_t *)OBJ_PRI_RSA_EXPO1(key))->big_value_len;
5301 #else	/* !__sparcv9 */
5302 		len =
5303 		    ((biginteger_t *)OBJ_PRI_RSA_EXPO1(key))->big_value_len;
5304 #endif	/* __sparcv9 */
5305 
5306 		if (len > *value_len) {
5307 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5308 		}
5309 		*value_len = len;
5310 
5311 		if (*value_len == 0) {
5312 			return (CKR_OK);
5313 		}
5314 
5315 		(void) memcpy(value,
5316 		    ((biginteger_t *)OBJ_PRI_RSA_EXPO1(key))->big_value,
5317 		    *value_len);
5318 
5319 		break;
5320 
5321 	case CKA_EXPONENT_2:
5322 #ifdef	__sparcv9
5323 		len =
5324 		    /* LINTED */
5325 		    (uint32_t)
5326 		    ((biginteger_t *)OBJ_PRI_RSA_EXPO2(key))->big_value_len;
5327 #else	/* !__sparcv9 */
5328 		len =
5329 		    ((biginteger_t *)OBJ_PRI_RSA_EXPO2(key))->big_value_len;
5330 #endif	/* __sparcv9 */
5331 
5332 		if (len > *value_len) {
5333 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5334 		}
5335 		*value_len = len;
5336 
5337 		if (*value_len == 0) {
5338 			return (CKR_OK);
5339 		}
5340 
5341 		(void) memcpy(value,
5342 		    ((biginteger_t *)OBJ_PRI_RSA_EXPO2(key))->big_value,
5343 		    *value_len);
5344 
5345 		break;
5346 
5347 	case CKA_COEFFICIENT:
5348 #ifdef	__sparcv9
5349 		len =
5350 		    /* LINTED */
5351 		    (uint32_t)
5352 		    ((biginteger_t *)OBJ_PRI_RSA_COEF(key))->big_value_len;
5353 #else	/* !__sparcv9 */
5354 		len =
5355 		    ((biginteger_t *)OBJ_PRI_RSA_COEF(key))->big_value_len;
5356 #endif	/* __sparcv9 */
5357 
5358 		if (len > *value_len) {
5359 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5360 		}
5361 		*value_len = len;
5362 
5363 		if (*value_len == 0) {
5364 			return (CKR_OK);
5365 		}
5366 
5367 		(void) memcpy(value,
5368 		    ((biginteger_t *)OBJ_PRI_RSA_COEF(key))->big_value,
5369 		    *value_len);
5370 
5371 		break;
5372 
5373 	/* The following attributes belong to DSA and DH */
5374 	case CKA_PRIME:
5375 
5376 		if (key->key_type == CKK_DSA)
5377 #ifdef	__sparcv9
5378 			len =
5379 			    /* LINTED */
5380 			    (uint32_t)
5381 			    ((biginteger_t *)OBJ_PRI_DSA_PRIME(key))->
5382 			    big_value_len;
5383 #else	/* !__sparcv9 */
5384 			len =
5385 			    ((biginteger_t *)OBJ_PRI_DSA_PRIME(key))->
5386 			    big_value_len;
5387 #endif	/* __sparcv9 */
5388 		else
5389 #ifdef	__sparcv9
5390 			len =
5391 			    /* LINTED */
5392 			    (uint32_t)
5393 			    ((biginteger_t *)OBJ_PRI_DH_PRIME(key))->
5394 			    big_value_len;
5395 #else	/* !__sparcv9 */
5396 			len =
5397 			    ((biginteger_t *)OBJ_PRI_DH_PRIME(key))->
5398 			    big_value_len;
5399 #endif	/* __sparcv9 */
5400 
5401 		/* This attribute MUST BE set */
5402 		if (len == 0 || len > *value_len) {
5403 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5404 		}
5405 		*value_len = len;
5406 
5407 		if (key->key_type == CKK_DSA)
5408 			(void) memcpy(value,
5409 			    ((biginteger_t *)OBJ_PRI_DSA_PRIME(key))->big_value,
5410 			    *value_len);
5411 		else
5412 			(void) memcpy(value,
5413 			    ((biginteger_t *)OBJ_PRI_DH_PRIME(key))->big_value,
5414 			    *value_len);
5415 
5416 		break;
5417 
5418 	case CKA_SUBPRIME:
5419 #ifdef	__sparcv9
5420 		len =
5421 		    /* LINTED */
5422 		    (uint32_t)
5423 		    ((biginteger_t *)OBJ_PRI_DSA_SUBPRIME(key))->big_value_len;
5424 #else	/* !__sparcv9 */
5425 		len =
5426 		    ((biginteger_t *)OBJ_PRI_DSA_SUBPRIME(key))->big_value_len;
5427 #endif	/* __sparcv9 */
5428 
5429 		/* This attribute MUST BE set */
5430 		if (len == 0 || len > *value_len) {
5431 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5432 		}
5433 		*value_len = len;
5434 
5435 		(void) memcpy(value,
5436 		    ((biginteger_t *)OBJ_PRI_DSA_SUBPRIME(key))->big_value,
5437 		    *value_len);
5438 
5439 		break;
5440 
5441 	case CKA_BASE:
5442 
5443 		if (key->key_type == CKK_DSA)
5444 #ifdef	__sparcv9
5445 			len =
5446 			    /* LINTED */
5447 			    (uint32_t)
5448 			    ((biginteger_t *)OBJ_PRI_DSA_BASE(key))->
5449 			    big_value_len;
5450 #else	/* !__sparcv9 */
5451 			len =
5452 			    ((biginteger_t *)OBJ_PRI_DSA_BASE(key))->
5453 			    big_value_len;
5454 #endif	/* __sparcv9 */
5455 		else
5456 #ifdef	__sparcv9
5457 			len =
5458 			    /* LINTED */
5459 			    (uint32_t)
5460 			    ((biginteger_t *)OBJ_PRI_DH_BASE(key))->
5461 			    big_value_len;
5462 #else	/* !__sparcv9 */
5463 			len =
5464 			    ((biginteger_t *)OBJ_PRI_DH_BASE(key))->
5465 			    big_value_len;
5466 #endif	/* __sparcv9 */
5467 
5468 		/* This attribute MUST BE set */
5469 		if (len == 0 || len > *value_len) {
5470 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5471 		}
5472 		*value_len = len;
5473 
5474 		if (key->key_type == CKK_DSA)
5475 			(void) memcpy(value,
5476 			    ((biginteger_t *)OBJ_PRI_DSA_BASE(key))->big_value,
5477 			    *value_len);
5478 		else
5479 			(void) memcpy(value,
5480 			    ((biginteger_t *)OBJ_PRI_DH_BASE(key))->big_value,
5481 			    *value_len);
5482 		break;
5483 
5484 	case CKA_VALUE:
5485 
5486 		if (key->key_type == CKK_DSA)
5487 #ifdef	__sparcv9
5488 			len =
5489 			    /* LINTED */
5490 			    (uint32_t)
5491 			    ((biginteger_t *)OBJ_PRI_DSA_VALUE(key))->
5492 			    big_value_len;
5493 #else	/* !__sparcv9 */
5494 			len =
5495 			    ((biginteger_t *)OBJ_PRI_DSA_VALUE(key))->
5496 			    big_value_len;
5497 #endif	/* __sparcv9 */
5498 		else
5499 #ifdef	__sparcv9
5500 			len =
5501 			    /* LINTED */
5502 			    (uint32_t)
5503 			    ((biginteger_t *)OBJ_PRI_DH_VALUE(key))->
5504 			    big_value_len;
5505 #else	/* !__sparcv9 */
5506 			len =
5507 			    ((biginteger_t *)OBJ_PRI_DH_VALUE(key))->
5508 			    big_value_len;
5509 #endif	/* __sparcv9 */
5510 
5511 		/* This attribute MUST BE set */
5512 		if (len == 0 || len > *value_len) {
5513 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5514 		}
5515 		*value_len = len;
5516 
5517 		if (key->key_type == CKK_DSA)
5518 			(void) memcpy(value,
5519 			    ((biginteger_t *)OBJ_PRI_DSA_VALUE(key))->big_value,
5520 			    *value_len);
5521 		else
5522 			(void) memcpy(value,
5523 			    ((biginteger_t *)OBJ_PRI_DH_VALUE(key))->big_value,
5524 			    *value_len);
5525 
5526 		break;
5527 	}
5528 
5529 	return (CKR_OK);
5530 
5531 }
5532 
5533 static CK_RV
5534 copy_bigint(biginteger_t *new_bigint, biginteger_t *old_bigint)
5535 {
5536 	new_bigint->big_value =
5537 	    malloc((sizeof (CK_BYTE) * new_bigint->big_value_len));
5538 
5539 	if (new_bigint->big_value == NULL) {
5540 		return (CKR_HOST_MEMORY);
5541 	}
5542 
5543 	(void) memcpy(new_bigint->big_value, old_bigint->big_value,
5544 	    (sizeof (CK_BYTE) * new_bigint->big_value_len));
5545 
5546 	return (CKR_OK);
5547 }
5548 
5549 static void
5550 free_public_key_attr(public_key_obj_t *pbk, CK_KEY_TYPE key_type)
5551 {
5552 	if (pbk == NULL) {
5553 		return;
5554 	}
5555 
5556 	switch (key_type) {
5557 		case CKK_RSA:
5558 			bigint_attr_cleanup(KEY_PUB_RSA_MOD(pbk));
5559 			bigint_attr_cleanup(KEY_PUB_RSA_PUBEXPO(pbk));
5560 			break;
5561 		case CKK_DSA:
5562 			bigint_attr_cleanup(KEY_PUB_DSA_PRIME(pbk));
5563 			bigint_attr_cleanup(KEY_PUB_DSA_SUBPRIME(pbk));
5564 			bigint_attr_cleanup(KEY_PUB_DSA_BASE(pbk));
5565 			bigint_attr_cleanup(KEY_PUB_DSA_VALUE(pbk));
5566 			break;
5567 		case CKK_DH:
5568 			bigint_attr_cleanup(KEY_PUB_DH_PRIME(pbk));
5569 			bigint_attr_cleanup(KEY_PUB_DH_BASE(pbk));
5570 			bigint_attr_cleanup(KEY_PUB_DH_VALUE(pbk));
5571 			break;
5572 		case CKK_X9_42_DH:
5573 			bigint_attr_cleanup(KEY_PUB_DH942_PRIME(pbk));
5574 			bigint_attr_cleanup(KEY_PUB_DH942_SUBPRIME(pbk));
5575 			bigint_attr_cleanup(KEY_PUB_DH942_BASE(pbk));
5576 			bigint_attr_cleanup(KEY_PUB_DH942_VALUE(pbk));
5577 			break;
5578 		default:
5579 			break;
5580 	}
5581 	free(pbk);
5582 }
5583 
5584 CK_RV
5585 soft_copy_public_key_attr(public_key_obj_t *old_pub_key_obj_p,
5586     public_key_obj_t **new_pub_key_obj_p, CK_KEY_TYPE key_type)
5587 {
5588 
5589 	public_key_obj_t *pbk;
5590 	CK_RV rv = CKR_OK;
5591 
5592 	pbk = calloc(1, sizeof (public_key_obj_t));
5593 	if (pbk == NULL) {
5594 		return (CKR_HOST_MEMORY);
5595 	}
5596 
5597 	switch (key_type) {
5598 		case CKK_RSA:
5599 			(void) memcpy(KEY_PUB_RSA(pbk),
5600 				KEY_PUB_RSA(old_pub_key_obj_p),
5601 			    sizeof (rsa_pub_key_t));
5602 			/* copy modulus */
5603 			rv = copy_bigint(KEY_PUB_RSA_MOD(pbk),
5604 			    KEY_PUB_RSA_MOD(old_pub_key_obj_p));
5605 			if (rv != CKR_OK) {
5606 				free_public_key_attr(pbk, key_type);
5607 				return (rv);
5608 			}
5609 			/* copy public exponent */
5610 			rv = copy_bigint(KEY_PUB_RSA_PUBEXPO(pbk),
5611 			    KEY_PUB_RSA_PUBEXPO(old_pub_key_obj_p));
5612 			if (rv != CKR_OK) {
5613 				free_public_key_attr(pbk, key_type);
5614 				return (rv);
5615 			}
5616 			break;
5617 		case CKK_DSA:
5618 			(void) memcpy(KEY_PUB_DSA(pbk),
5619 			    KEY_PUB_DSA(old_pub_key_obj_p),
5620 			    sizeof (dsa_pub_key_t));
5621 
5622 			/* copy prime */
5623 			rv = copy_bigint(KEY_PUB_DSA_PRIME(pbk),
5624 			    KEY_PUB_DSA_PRIME(old_pub_key_obj_p));
5625 			if (rv != CKR_OK) {
5626 				free_public_key_attr(pbk, key_type);
5627 				return (rv);
5628 			}
5629 
5630 			/* copy subprime */
5631 			rv = copy_bigint(KEY_PUB_DSA_SUBPRIME(pbk),
5632 			    KEY_PUB_DSA_SUBPRIME(old_pub_key_obj_p));
5633 			if (rv != CKR_OK) {
5634 				free_public_key_attr(pbk, key_type);
5635 				return (rv);
5636 			}
5637 
5638 			/* copy base */
5639 			rv = copy_bigint(KEY_PUB_DSA_BASE(pbk),
5640 			    KEY_PUB_DSA_BASE(old_pub_key_obj_p));
5641 			if (rv != CKR_OK) {
5642 				free_public_key_attr(pbk, key_type);
5643 				return (rv);
5644 			}
5645 
5646 			/* copy value */
5647 			rv = copy_bigint(KEY_PUB_DSA_VALUE(pbk),
5648 			    KEY_PUB_DSA_VALUE(old_pub_key_obj_p));
5649 			if (rv != CKR_OK) {
5650 				free_public_key_attr(pbk, key_type);
5651 				return (rv);
5652 			}
5653 			break;
5654 		case CKK_DH:
5655 			(void) memcpy(KEY_PUB_DH(pbk),
5656 			    KEY_PUB_DH(old_pub_key_obj_p),
5657 			    sizeof (dh_pub_key_t));
5658 
5659 			/* copy prime */
5660 			rv = copy_bigint(KEY_PUB_DH_PRIME(pbk),
5661 			    KEY_PUB_DH_PRIME(old_pub_key_obj_p));
5662 			if (rv != CKR_OK) {
5663 				free_public_key_attr(pbk, key_type);
5664 				return (rv);
5665 			}
5666 
5667 			/* copy base */
5668 			rv = copy_bigint(KEY_PUB_DH_BASE(pbk),
5669 			    KEY_PUB_DH_BASE(old_pub_key_obj_p));
5670 			if (rv != CKR_OK) {
5671 				free_public_key_attr(pbk, key_type);
5672 				return (rv);
5673 			}
5674 
5675 			/* copy value */
5676 			rv = copy_bigint(KEY_PUB_DH_VALUE(pbk),
5677 			    KEY_PUB_DH_VALUE(old_pub_key_obj_p));
5678 			if (rv != CKR_OK) {
5679 				free_public_key_attr(pbk, key_type);
5680 				return (rv);
5681 			}
5682 			break;
5683 		case CKK_X9_42_DH:
5684 			(void) memcpy(KEY_PUB_DH942(pbk),
5685 			    KEY_PUB_DH942(old_pub_key_obj_p),
5686 			    sizeof (dh942_pub_key_t));
5687 
5688 			/* copy prime */
5689 			rv = copy_bigint(KEY_PUB_DH942_PRIME(pbk),
5690 			    KEY_PUB_DH942_PRIME(old_pub_key_obj_p));
5691 			if (rv != CKR_OK) {
5692 				free_public_key_attr(pbk, key_type);
5693 				return (rv);
5694 			}
5695 
5696 			/* copy subprime */
5697 			rv = copy_bigint(KEY_PUB_DH942_SUBPRIME(pbk),
5698 			    KEY_PUB_DH942_SUBPRIME(old_pub_key_obj_p));
5699 			if (rv != CKR_OK) {
5700 				free_public_key_attr(pbk, key_type);
5701 				return (rv);
5702 			}
5703 
5704 			/* copy base */
5705 			rv = copy_bigint(KEY_PUB_DH942_BASE(pbk),
5706 			    KEY_PUB_DH942_BASE(old_pub_key_obj_p));
5707 			if (rv != CKR_OK) {
5708 				free_public_key_attr(pbk, key_type);
5709 				return (rv);
5710 			}
5711 
5712 			/* copy value */
5713 			rv = copy_bigint(KEY_PUB_DH942_VALUE(pbk),
5714 			    KEY_PUB_DH942_VALUE(old_pub_key_obj_p));
5715 			if (rv != CKR_OK) {
5716 				free_public_key_attr(pbk, key_type);
5717 				return (rv);
5718 			}
5719 			break;
5720 		default:
5721 			break;
5722 	}
5723 	*new_pub_key_obj_p = pbk;
5724 	return (rv);
5725 }
5726 
5727 static void
5728 free_private_key_attr(private_key_obj_t *pbk, CK_KEY_TYPE key_type)
5729 {
5730 	if (pbk == NULL) {
5731 		return;
5732 	}
5733 
5734 	switch (key_type) {
5735 		case CKK_RSA:
5736 			bigint_attr_cleanup(KEY_PRI_RSA_MOD(pbk));
5737 			bigint_attr_cleanup(KEY_PRI_RSA_PUBEXPO(pbk));
5738 			bigint_attr_cleanup(KEY_PRI_RSA_PRIEXPO(pbk));
5739 			bigint_attr_cleanup(KEY_PRI_RSA_PRIME1(pbk));
5740 			bigint_attr_cleanup(KEY_PRI_RSA_PRIME2(pbk));
5741 			bigint_attr_cleanup(KEY_PRI_RSA_EXPO1(pbk));
5742 			bigint_attr_cleanup(KEY_PRI_RSA_EXPO2(pbk));
5743 			bigint_attr_cleanup(KEY_PRI_RSA_COEF(pbk));
5744 			break;
5745 		case CKK_DSA:
5746 			bigint_attr_cleanup(KEY_PRI_DSA_PRIME(pbk));
5747 			bigint_attr_cleanup(KEY_PRI_DSA_SUBPRIME(pbk));
5748 			bigint_attr_cleanup(KEY_PRI_DSA_BASE(pbk));
5749 			bigint_attr_cleanup(KEY_PRI_DSA_VALUE(pbk));
5750 			break;
5751 		case CKK_DH:
5752 			bigint_attr_cleanup(KEY_PRI_DH_PRIME(pbk));
5753 			bigint_attr_cleanup(KEY_PRI_DH_BASE(pbk));
5754 			bigint_attr_cleanup(KEY_PRI_DH_VALUE(pbk));
5755 			break;
5756 		case CKK_X9_42_DH:
5757 			bigint_attr_cleanup(KEY_PRI_DH942_PRIME(pbk));
5758 			bigint_attr_cleanup(KEY_PRI_DH942_SUBPRIME(pbk));
5759 			bigint_attr_cleanup(KEY_PRI_DH942_BASE(pbk));
5760 			bigint_attr_cleanup(KEY_PRI_DH942_VALUE(pbk));
5761 			break;
5762 		default:
5763 			break;
5764 	}
5765 	free(pbk);
5766 }
5767 
5768 CK_RV
5769 soft_copy_private_key_attr(private_key_obj_t *old_pri_key_obj_p,
5770     private_key_obj_t **new_pri_key_obj_p, CK_KEY_TYPE key_type)
5771 {
5772 	CK_RV rv = CKR_OK;
5773 	private_key_obj_t *pbk;
5774 
5775 	pbk = calloc(1, sizeof (private_key_obj_t));
5776 	if (pbk == NULL) {
5777 		return (CKR_HOST_MEMORY);
5778 	}
5779 
5780 	switch (key_type) {
5781 		case CKK_RSA:
5782 			(void) memcpy(KEY_PRI_RSA(pbk),
5783 			    KEY_PRI_RSA(old_pri_key_obj_p),
5784 			    sizeof (rsa_pri_key_t));
5785 			/* copy modulus */
5786 			rv = copy_bigint(KEY_PRI_RSA_MOD(pbk),
5787 			    KEY_PRI_RSA_MOD(old_pri_key_obj_p));
5788 			if (rv != CKR_OK) {
5789 				free_private_key_attr(pbk, key_type);
5790 				return (rv);
5791 			}
5792 			/* copy public exponent */
5793 			rv = copy_bigint(KEY_PRI_RSA_PUBEXPO(pbk),
5794 			    KEY_PRI_RSA_PUBEXPO(old_pri_key_obj_p));
5795 			if (rv != CKR_OK) {
5796 				free_private_key_attr(pbk, key_type);
5797 				return (rv);
5798 			}
5799 			/* copy private exponent */
5800 			rv = copy_bigint(KEY_PRI_RSA_PRIEXPO(pbk),
5801 			    KEY_PRI_RSA_PRIEXPO(old_pri_key_obj_p));
5802 			if (rv != CKR_OK) {
5803 				free_private_key_attr(pbk, key_type);
5804 				return (rv);
5805 			}
5806 			/* copy prime_1 */
5807 			rv = copy_bigint(KEY_PRI_RSA_PRIME1(pbk),
5808 			    KEY_PRI_RSA_PRIME1(old_pri_key_obj_p));
5809 			if (rv != CKR_OK) {
5810 				free_private_key_attr(pbk, key_type);
5811 				return (rv);
5812 			}
5813 			/* copy prime_2 */
5814 			rv = copy_bigint(KEY_PRI_RSA_PRIME2(pbk),
5815 			    KEY_PRI_RSA_PRIME2(old_pri_key_obj_p));
5816 			if (rv != CKR_OK) {
5817 				free_private_key_attr(pbk, key_type);
5818 				return (rv);
5819 			}
5820 			/* copy exponent_1 */
5821 			rv = copy_bigint(KEY_PRI_RSA_EXPO1(pbk),
5822 			    KEY_PRI_RSA_EXPO1(old_pri_key_obj_p));
5823 			if (rv != CKR_OK) {
5824 				free_private_key_attr(pbk, key_type);
5825 				return (rv);
5826 			}
5827 			/* copy exponent_2 */
5828 			rv = copy_bigint(KEY_PRI_RSA_EXPO2(pbk),
5829 			    KEY_PRI_RSA_EXPO2(old_pri_key_obj_p));
5830 			if (rv != CKR_OK) {
5831 				free_private_key_attr(pbk, key_type);
5832 				return (rv);
5833 			}
5834 			/* copy coefficient */
5835 			rv = copy_bigint(KEY_PRI_RSA_COEF(pbk),
5836 			    KEY_PRI_RSA_COEF(old_pri_key_obj_p));
5837 			if (rv != CKR_OK) {
5838 				free_private_key_attr(pbk, key_type);
5839 				return (rv);
5840 			}
5841 			break;
5842 		case CKK_DSA:
5843 			(void) memcpy(KEY_PRI_DSA(pbk),
5844 			    KEY_PRI_DSA(old_pri_key_obj_p),
5845 			    sizeof (dsa_pri_key_t));
5846 
5847 			/* copy prime */
5848 			rv = copy_bigint(KEY_PRI_DSA_PRIME(pbk),
5849 			    KEY_PRI_DSA_PRIME(old_pri_key_obj_p));
5850 			if (rv != CKR_OK) {
5851 				free_private_key_attr(pbk, key_type);
5852 				return (rv);
5853 			}
5854 
5855 			/* copy subprime */
5856 			rv = copy_bigint(KEY_PRI_DSA_SUBPRIME(pbk),
5857 			    KEY_PRI_DSA_SUBPRIME(old_pri_key_obj_p));
5858 			if (rv != CKR_OK) {
5859 				free_private_key_attr(pbk, key_type);
5860 				return (rv);
5861 			}
5862 
5863 			/* copy base */
5864 			rv = copy_bigint(KEY_PRI_DSA_BASE(pbk),
5865 			    KEY_PRI_DSA_BASE(old_pri_key_obj_p));
5866 			if (rv != CKR_OK) {
5867 				free_private_key_attr(pbk, key_type);
5868 				return (rv);
5869 			}
5870 
5871 			/* copy value */
5872 			rv = copy_bigint(KEY_PRI_DSA_VALUE(pbk),
5873 			    KEY_PRI_DSA_VALUE(old_pri_key_obj_p));
5874 			if (rv != CKR_OK) {
5875 				free_private_key_attr(pbk, key_type);
5876 				return (rv);
5877 			}
5878 			break;
5879 		case CKK_DH:
5880 			(void) memcpy(KEY_PRI_DH(pbk),
5881 			    KEY_PRI_DH(old_pri_key_obj_p),
5882 			    sizeof (dh_pri_key_t));
5883 
5884 			/* copy prime */
5885 			rv = copy_bigint(KEY_PRI_DH_PRIME(pbk),
5886 			    KEY_PRI_DH_PRIME(old_pri_key_obj_p));
5887 			if (rv != CKR_OK) {
5888 				free_private_key_attr(pbk, key_type);
5889 				return (rv);
5890 			}
5891 
5892 			/* copy base */
5893 			rv = copy_bigint(KEY_PRI_DH_BASE(pbk),
5894 			    KEY_PRI_DH_BASE(old_pri_key_obj_p));
5895 			if (rv != CKR_OK) {
5896 				free_private_key_attr(pbk, key_type);
5897 				return (rv);
5898 			}
5899 
5900 			/* copy value */
5901 			rv = copy_bigint(KEY_PRI_DH_VALUE(pbk),
5902 			    KEY_PRI_DH_VALUE(old_pri_key_obj_p));
5903 			if (rv != CKR_OK) {
5904 				free_private_key_attr(pbk, key_type);
5905 				return (rv);
5906 			}
5907 			break;
5908 		case CKK_X9_42_DH:
5909 			(void) memcpy(KEY_PRI_DH942(pbk),
5910 			    KEY_PRI_DH942(old_pri_key_obj_p),
5911 			    sizeof (dh942_pri_key_t));
5912 
5913 			/* copy prime */
5914 			rv = copy_bigint(KEY_PRI_DH942_PRIME(pbk),
5915 			    KEY_PRI_DH942_PRIME(old_pri_key_obj_p));
5916 			if (rv != CKR_OK) {
5917 				free_private_key_attr(pbk, key_type);
5918 				return (rv);
5919 			}
5920 
5921 			/* copy subprime */
5922 			rv = copy_bigint(KEY_PRI_DH942_SUBPRIME(pbk),
5923 			    KEY_PRI_DH942_SUBPRIME(old_pri_key_obj_p));
5924 			if (rv != CKR_OK) {
5925 				free_private_key_attr(pbk, key_type);
5926 				return (rv);
5927 			}
5928 
5929 			/* copy base */
5930 			rv = copy_bigint(KEY_PRI_DH942_BASE(pbk),
5931 			    KEY_PRI_DH942_BASE(old_pri_key_obj_p));
5932 			if (rv != CKR_OK) {
5933 				free_private_key_attr(pbk, key_type);
5934 				return (rv);
5935 			}
5936 
5937 			/* copy value */
5938 			rv = copy_bigint(KEY_PRI_DH942_VALUE(pbk),
5939 			    KEY_PRI_DH942_VALUE(old_pri_key_obj_p));
5940 			if (rv != CKR_OK) {
5941 				free_private_key_attr(pbk, key_type);
5942 				return (rv);
5943 			}
5944 			break;
5945 		default:
5946 			break;
5947 	}
5948 	*new_pri_key_obj_p = pbk;
5949 	return (rv);
5950 }
5951 
5952 static void
5953 free_domain_attr(domain_obj_t *domain, CK_KEY_TYPE key_type)
5954 {
5955 	if (domain == NULL) {
5956 		return;
5957 	}
5958 
5959 	switch (key_type) {
5960 		case CKK_DSA:
5961 			bigint_attr_cleanup(KEY_DOM_DSA_PRIME(domain));
5962 			bigint_attr_cleanup(KEY_DOM_DSA_SUBPRIME(domain));
5963 			bigint_attr_cleanup(KEY_DOM_DSA_BASE(domain));
5964 			break;
5965 		case CKK_DH:
5966 			bigint_attr_cleanup(KEY_DOM_DH_PRIME(domain));
5967 			bigint_attr_cleanup(KEY_DOM_DH_BASE(domain));
5968 			break;
5969 		case CKK_X9_42_DH:
5970 			bigint_attr_cleanup(KEY_DOM_DH942_PRIME(domain));
5971 			bigint_attr_cleanup(KEY_DOM_DH942_SUBPRIME(domain));
5972 			bigint_attr_cleanup(KEY_DOM_DH942_BASE(domain));
5973 			break;
5974 		default:
5975 			break;
5976 	}
5977 	free(domain);
5978 }
5979 
5980 CK_RV
5981 soft_copy_domain_attr(domain_obj_t *old_domain_obj_p,
5982     domain_obj_t **new_domain_obj_p, CK_KEY_TYPE key_type)
5983 {
5984 	CK_RV rv = CKR_OK;
5985 	domain_obj_t *domain;
5986 
5987 	domain = calloc(1, sizeof (domain_obj_t));
5988 	if (domain == NULL) {
5989 		return (CKR_HOST_MEMORY);
5990 	}
5991 
5992 	switch (key_type) {
5993 		case CKK_DSA:
5994 			(void) memcpy(KEY_DOM_DSA(domain),
5995 			    KEY_DOM_DSA(old_domain_obj_p),
5996 			    sizeof (dsa_dom_key_t));
5997 
5998 			/* copy prime */
5999 			rv = copy_bigint(KEY_DOM_DSA_PRIME(domain),
6000 			    KEY_DOM_DSA_PRIME(old_domain_obj_p));
6001 			if (rv != CKR_OK) {
6002 				free_domain_attr(domain, key_type);
6003 				return (rv);
6004 			}
6005 
6006 			/* copy subprime */
6007 			rv = copy_bigint(KEY_DOM_DSA_SUBPRIME(domain),
6008 			    KEY_DOM_DSA_SUBPRIME(old_domain_obj_p));
6009 			if (rv != CKR_OK) {
6010 				free_domain_attr(domain, key_type);
6011 				return (rv);
6012 			}
6013 
6014 			/* copy base */
6015 			rv = copy_bigint(KEY_DOM_DSA_BASE(domain),
6016 			    KEY_DOM_DSA_BASE(old_domain_obj_p));
6017 			if (rv != CKR_OK) {
6018 				free_domain_attr(domain, key_type);
6019 				return (rv);
6020 			}
6021 
6022 			break;
6023 		case CKK_DH:
6024 			(void) memcpy(KEY_DOM_DH(domain),
6025 			    KEY_DOM_DH(old_domain_obj_p),
6026 			    sizeof (dh_dom_key_t));
6027 
6028 			/* copy prime */
6029 			rv = copy_bigint(KEY_DOM_DH_PRIME(domain),
6030 			    KEY_DOM_DH_PRIME(old_domain_obj_p));
6031 			if (rv != CKR_OK) {
6032 				free_domain_attr(domain, key_type);
6033 				return (rv);
6034 			}
6035 
6036 			/* copy base */
6037 			rv = copy_bigint(KEY_DOM_DH_BASE(domain),
6038 			    KEY_DOM_DH_BASE(old_domain_obj_p));
6039 			if (rv != CKR_OK) {
6040 				free_domain_attr(domain, key_type);
6041 				return (rv);
6042 			}
6043 
6044 			break;
6045 		case CKK_X9_42_DH:
6046 			(void) memcpy(KEY_DOM_DH942(domain),
6047 			    KEY_DOM_DH942(old_domain_obj_p),
6048 			    sizeof (dh942_dom_key_t));
6049 
6050 			/* copy prime */
6051 			rv = copy_bigint(KEY_DOM_DH942_PRIME(domain),
6052 			    KEY_DOM_DH942_PRIME(old_domain_obj_p));
6053 			if (rv != CKR_OK) {
6054 				free_domain_attr(domain, key_type);
6055 				return (rv);
6056 			}
6057 
6058 			/* copy subprime */
6059 			rv = copy_bigint(KEY_DOM_DH942_SUBPRIME(domain),
6060 			    KEY_DOM_DH942_SUBPRIME(old_domain_obj_p));
6061 			if (rv != CKR_OK) {
6062 				free_domain_attr(domain, key_type);
6063 				return (rv);
6064 			}
6065 
6066 			/* copy base */
6067 			rv = copy_bigint(KEY_DOM_DH942_BASE(domain),
6068 			    KEY_DOM_DH942_BASE(old_domain_obj_p));
6069 			if (rv != CKR_OK) {
6070 				free_domain_attr(domain, key_type);
6071 				return (rv);
6072 			}
6073 
6074 			break;
6075 		default:
6076 			break;
6077 	}
6078 	*new_domain_obj_p = domain;
6079 	return (rv);
6080 }
6081 
6082 CK_RV
6083 soft_copy_secret_key_attr(secret_key_obj_t *old_secret_key_obj_p,
6084     secret_key_obj_t **new_secret_key_obj_p)
6085 {
6086 	secret_key_obj_t *sk;
6087 
6088 	sk = malloc(sizeof (secret_key_obj_t));
6089 	if (sk == NULL) {
6090 		return (CKR_HOST_MEMORY);
6091 	}
6092 	(void) memcpy(sk, old_secret_key_obj_p, sizeof (secret_key_obj_t));
6093 
6094 	/* copy the secret key value */
6095 	sk->sk_value = malloc((sizeof (CK_BYTE) * sk->sk_value_len));
6096 	if (sk->sk_value == NULL) {
6097 		free(sk);
6098 		return (CKR_HOST_MEMORY);
6099 	}
6100 	(void) memcpy(sk->sk_value, old_secret_key_obj_p->sk_value,
6101 	    (sizeof (CK_BYTE) * sk->sk_value_len));
6102 
6103 	/*
6104 	 * Copy the pre-expanded key schedule.
6105 	 */
6106 	if (old_secret_key_obj_p->key_sched != NULL &&
6107 	    old_secret_key_obj_p->keysched_len > 0) {
6108 		sk->key_sched = malloc(old_secret_key_obj_p->keysched_len);
6109 		if (sk->key_sched == NULL) {
6110 			free(sk);
6111 			return (CKR_HOST_MEMORY);
6112 		}
6113 		sk->keysched_len = old_secret_key_obj_p->keysched_len;
6114 		(void) memcpy(sk->key_sched, old_secret_key_obj_p->key_sched,
6115 			sk->keysched_len);
6116 	}
6117 
6118 	*new_secret_key_obj_p = sk;
6119 
6120 	return (CKR_OK);
6121 }
6122 
6123 /*
6124  * If CKA_CLASS not given, guess CKA_CLASS using
6125  * attributes on template .
6126  *
6127  * Some attributes are specific to an object class.  If one or more
6128  * of these attributes are in the template, make a list of classes
6129  * that can have these attributes.  This would speed up the search later,
6130  * because we can immediately skip an object if the class of that
6131  * object can not possiblely contain one of the attributes.
6132  *
6133  */
6134 void
6135 soft_process_find_attr(CK_OBJECT_CLASS *pclasses,
6136     CK_ULONG *num_result_pclasses, CK_ATTRIBUTE_PTR pTemplate,
6137     CK_ULONG ulCount)
6138 {
6139 	ulong_t i;
6140 	int j;
6141 	boolean_t pub_found = B_FALSE,
6142 	    priv_found = B_FALSE,
6143 	    secret_found = B_FALSE,
6144 	    domain_found = B_FALSE,
6145 	    hardware_found = B_FALSE,
6146 	    cert_found = B_FALSE;
6147 	int num_pub_key_attrs, num_priv_key_attrs,
6148 	    num_secret_key_attrs, num_domain_attrs,
6149 	    num_hardware_attrs, num_cert_attrs;
6150 	int num_pclasses = 0;
6151 
6152 	for (i = 0; i < ulCount; i++) {
6153 		if (pTemplate[i].type == CKA_CLASS) {
6154 			/*
6155 			 * don't need to guess the class, it is specified.
6156 			 * Just record the class, and return.
6157 			 */
6158 			pclasses[0] =
6159 			    (*((CK_OBJECT_CLASS *)pTemplate[i].pValue));
6160 			*num_result_pclasses = 1;
6161 			return;
6162 		}
6163 	}
6164 
6165 	num_pub_key_attrs =
6166 	    sizeof (PUB_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6167 	num_priv_key_attrs =
6168 	    sizeof (PRIV_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6169 	num_secret_key_attrs =
6170 	    sizeof (SECRET_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6171 	num_domain_attrs =
6172 	    sizeof (DOMAIN_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6173 	num_hardware_attrs =
6174 	    sizeof (HARDWARE_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6175 	num_cert_attrs =
6176 	    sizeof (CERT_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6177 
6178 	/*
6179 	 * Get the list of objects class that might contain
6180 	 * some attributes.
6181 	 */
6182 	for (i = 0; i < ulCount; i++) {
6183 		/*
6184 		 * only check if this attribute can belong to public key object
6185 		 * class if public key object isn't already in the list
6186 		 */
6187 		if (!pub_found) {
6188 			for (j = 0; j < num_pub_key_attrs; j++) {
6189 				if (pTemplate[i].type == PUB_KEY_ATTRS[j]) {
6190 					pub_found = B_TRUE;
6191 					pclasses[num_pclasses++] =
6192 					    CKO_PUBLIC_KEY;
6193 					break;
6194 				}
6195 			}
6196 		}
6197 
6198 		if (!priv_found) {
6199 			for (j = 0; j < num_priv_key_attrs; j++) {
6200 				if (pTemplate[i].type == PRIV_KEY_ATTRS[j]) {
6201 					priv_found = B_TRUE;
6202 					pclasses[num_pclasses++] =
6203 					    CKO_PRIVATE_KEY;
6204 					break;
6205 				}
6206 			}
6207 		}
6208 
6209 		if (!secret_found) {
6210 			for (j = 0; j < num_secret_key_attrs; j++) {
6211 				if (pTemplate[i].type == SECRET_KEY_ATTRS[j]) {
6212 					secret_found = B_TRUE;
6213 					pclasses[num_pclasses++] =
6214 					    CKO_SECRET_KEY;
6215 					break;
6216 				}
6217 			}
6218 		}
6219 
6220 		if (!domain_found) {
6221 			for (j = 0; j < num_domain_attrs; j++) {
6222 				if (pTemplate[i].type == DOMAIN_ATTRS[j]) {
6223 					domain_found = B_TRUE;
6224 					pclasses[num_pclasses++] =
6225 					    CKO_DOMAIN_PARAMETERS;
6226 					break;
6227 				}
6228 			}
6229 		}
6230 
6231 		if (!hardware_found) {
6232 			for (j = 0; j < num_hardware_attrs; j++) {
6233 				if (pTemplate[i].type == HARDWARE_ATTRS[j]) {
6234 					hardware_found = B_TRUE;
6235 					pclasses[num_pclasses++] =
6236 					    CKO_HW_FEATURE;
6237 					break;
6238 				}
6239 			}
6240 		}
6241 
6242 		if (!cert_found) {
6243 			for (j = 0; j < num_cert_attrs; j++) {
6244 				if (pTemplate[i].type == CERT_ATTRS[j]) {
6245 					cert_found = B_TRUE;
6246 					pclasses[num_pclasses++] =
6247 					    CKO_CERTIFICATE;
6248 					break;
6249 				}
6250 			}
6251 		}
6252 	}
6253 	*num_result_pclasses = num_pclasses;
6254 }
6255 
6256 boolean_t
6257 soft_find_match_attrs(soft_object_t *obj, CK_OBJECT_CLASS *pclasses,
6258     CK_ULONG num_pclasses, CK_ATTRIBUTE *template, CK_ULONG num_attr)
6259 {
6260 	ulong_t i;
6261 	CK_ATTRIBUTE *tmpl_attr, *obj_attr;
6262 	cert_attr_t *cert_attr;
6263 	uint64_t attr_mask;
6264 	biginteger_t *bigint;
6265 	boolean_t compare_attr, compare_bigint, compare_boolean;
6266 	boolean_t compare_cert_val, compare_cert_type;
6267 
6268 	/*
6269 	 * Check if the class of this object match with any
6270 	 * of object classes that can possiblely contain the
6271 	 * requested attributes.
6272 	 */
6273 	if (num_pclasses > 0) {
6274 		for (i = 0; i < num_pclasses; i++) {
6275 			if (obj->class == pclasses[i]) {
6276 				break;
6277 			}
6278 		}
6279 		if (i == num_pclasses) {
6280 			/*
6281 			 * this object can't possiblely contain one or
6282 			 * more attributes, don't need to check this object
6283 			 */
6284 			return (B_FALSE);
6285 		}
6286 	}
6287 
6288 	/* need to examine everything */
6289 	for (i = 0; i < num_attr; i++) {
6290 		tmpl_attr = &(template[i]);
6291 		compare_attr = B_FALSE;
6292 		compare_bigint = B_FALSE;
6293 		compare_boolean = B_FALSE;
6294 		compare_cert_val = B_FALSE;
6295 		compare_cert_type = B_FALSE;
6296 		switch (tmpl_attr->type) {
6297 		/* First, check the most common attributes */
6298 		case CKA_CLASS:
6299 			if (*((CK_OBJECT_CLASS *)tmpl_attr->pValue) !=
6300 			    obj->class) {
6301 				return (B_FALSE);
6302 			}
6303 			break;
6304 		case CKA_KEY_TYPE:
6305 			if (*((CK_KEY_TYPE *)tmpl_attr->pValue) !=
6306 			    obj->key_type) {
6307 				return (B_FALSE);
6308 			}
6309 			break;
6310 		case CKA_ENCRYPT:
6311 			attr_mask = (obj->bool_attr_mask) & ENCRYPT_BOOL_ON;
6312 			compare_boolean = B_TRUE;
6313 			break;
6314 		case CKA_DECRYPT:
6315 			attr_mask = (obj->bool_attr_mask) & DECRYPT_BOOL_ON;
6316 			compare_boolean = B_TRUE;
6317 			break;
6318 		case CKA_WRAP:
6319 			attr_mask = (obj->bool_attr_mask) & WRAP_BOOL_ON;
6320 			compare_boolean = B_TRUE;
6321 			break;
6322 		case CKA_UNWRAP:
6323 			attr_mask = (obj->bool_attr_mask) & UNWRAP_BOOL_ON;
6324 			compare_boolean = B_TRUE;
6325 			break;
6326 		case CKA_SIGN:
6327 			attr_mask = (obj->bool_attr_mask) & SIGN_BOOL_ON;
6328 			compare_boolean = B_TRUE;
6329 			break;
6330 		case CKA_SIGN_RECOVER:
6331 			attr_mask = (obj->bool_attr_mask) &
6332 			    SIGN_RECOVER_BOOL_ON;
6333 			compare_boolean = B_TRUE;
6334 			break;
6335 		case CKA_VERIFY:
6336 			attr_mask = (obj->bool_attr_mask) & VERIFY_BOOL_ON;
6337 			compare_boolean = B_TRUE;
6338 			break;
6339 		case CKA_VERIFY_RECOVER:
6340 			attr_mask = (obj->bool_attr_mask) &
6341 			    VERIFY_RECOVER_BOOL_ON;
6342 			compare_boolean = B_TRUE;
6343 			break;
6344 		case CKA_DERIVE:
6345 			attr_mask = (obj->bool_attr_mask) & DERIVE_BOOL_ON;
6346 			compare_boolean = B_TRUE;
6347 			break;
6348 		case CKA_LOCAL:
6349 			attr_mask = (obj->bool_attr_mask) & LOCAL_BOOL_ON;
6350 			compare_boolean = B_TRUE;
6351 			break;
6352 		case CKA_SENSITIVE:
6353 			attr_mask = (obj->bool_attr_mask) & SENSITIVE_BOOL_ON;
6354 			compare_boolean = B_TRUE;
6355 			break;
6356 		case CKA_SECONDARY_AUTH:
6357 			attr_mask = (obj->bool_attr_mask) &
6358 			    SECONDARY_AUTH_BOOL_ON;
6359 			compare_boolean = B_TRUE;
6360 			break;
6361 		case CKA_TRUSTED:
6362 			attr_mask = (obj->bool_attr_mask) & TRUSTED_BOOL_ON;
6363 			compare_boolean = B_TRUE;
6364 			break;
6365 		case CKA_EXTRACTABLE:
6366 			attr_mask = (obj->bool_attr_mask) &
6367 			    EXTRACTABLE_BOOL_ON;
6368 			compare_boolean = B_TRUE;
6369 			break;
6370 		case CKA_ALWAYS_SENSITIVE:
6371 			attr_mask = (obj->bool_attr_mask) &
6372 			    ALWAYS_SENSITIVE_BOOL_ON;
6373 			compare_boolean = B_TRUE;
6374 			break;
6375 		case CKA_NEVER_EXTRACTABLE:
6376 			attr_mask = (obj->bool_attr_mask) &
6377 			    NEVER_EXTRACTABLE_BOOL_ON;
6378 			compare_boolean = B_TRUE;
6379 			break;
6380 		case CKA_TOKEN:
6381 			attr_mask = (obj->object_type) & TOKEN_OBJECT;
6382 			compare_boolean = B_TRUE;
6383 			break;
6384 		case CKA_PRIVATE:
6385 			attr_mask = (obj->object_type) & PRIVATE_OBJECT;
6386 			compare_boolean = B_TRUE;
6387 			break;
6388 		case CKA_MODIFIABLE:
6389 		{
6390 			CK_BBOOL bval;
6391 			attr_mask = (obj->bool_attr_mask) &
6392 			    NOT_MODIFIABLE_BOOL_ON;
6393 
6394 			if (attr_mask) {
6395 				bval = FALSE;
6396 			} else {
6397 				bval = TRUE;
6398 			}
6399 			if (bval != *((CK_BBOOL *)tmpl_attr->pValue)) {
6400 				return (B_FALSE);
6401 			}
6402 			break;
6403 		}
6404 		case CKA_OWNER:
6405 			/*
6406 			 * For X.509 attribute certificate object, get its
6407 			 * CKA_OWNER attribute from the x509_attr_cert_t struct.
6408 			 */
6409 			if ((obj->class == CKO_CERTIFICATE) &&
6410 			    (obj->cert_type == CKC_X_509_ATTR_CERT)) {
6411 				cert_attr = X509_ATTR_CERT_OWNER(obj);
6412 				compare_cert_val = B_TRUE;
6413 			}
6414 			break;
6415 		case CKA_SUBJECT:
6416 			/*
6417 			 * For X.509 certificate object, get its CKA_SUBJECT
6418 			 * attribute from the x509_cert_t struct (not from
6419 			 * the extra_attrlistp).
6420 			 */
6421 			if ((obj->class == CKO_CERTIFICATE) &&
6422 			    (obj->cert_type == CKC_X_509)) {
6423 				cert_attr = X509_CERT_SUBJECT(obj);
6424 				compare_cert_val = B_TRUE;
6425 				break;
6426 			}
6427 			/*FALLTHRU*/
6428 		case CKA_ID:
6429 		case CKA_START_DATE:
6430 		case CKA_END_DATE:
6431 		case CKA_KEY_GEN_MECHANISM:
6432 		case CKA_LABEL:
6433 		case CKA_ISSUER:
6434 		case CKA_SERIAL_NUMBER:
6435 		case CKA_AC_ISSUER:
6436 		case CKA_ATTR_TYPES:
6437 			/* find these attributes from extra_attrlistp */
6438 			obj_attr = get_extra_attr(tmpl_attr->type, obj);
6439 			compare_attr = B_TRUE;
6440 			break;
6441 		case CKA_CERTIFICATE_TYPE:
6442 			compare_cert_type = B_TRUE;
6443 			break;
6444 		case CKA_VALUE_LEN:
6445 			/* only secret key has this attribute */
6446 			if (obj->class == CKO_SECRET_KEY) {
6447 				if (*((CK_ULONG *)tmpl_attr->pValue) !=
6448 				    OBJ_SEC_VALUE_LEN(obj)) {
6449 					return (B_FALSE);
6450 				}
6451 			} else {
6452 				return (B_FALSE);
6453 			}
6454 			break;
6455 		case CKA_VALUE:
6456 			switch (obj->class) {
6457 			case CKO_SECRET_KEY:
6458 				/*
6459 				 * secret_key_obj_t is the same as
6460 				 * biginteger_t
6461 				 */
6462 				bigint = (biginteger_t *)OBJ_SEC(obj);
6463 				compare_bigint = B_TRUE;
6464 				break;
6465 			case CKO_PRIVATE_KEY:
6466 				if (obj->key_type == CKK_DSA) {
6467 					bigint = OBJ_PRI_DSA_VALUE(obj);
6468 				} else if (obj->key_type == CKK_DH) {
6469 					bigint = OBJ_PRI_DH_VALUE(obj);
6470 				} else if (obj->key_type == CKK_X9_42_DH) {
6471 					bigint = OBJ_PRI_DH942_VALUE(obj);
6472 				} else {
6473 					return (B_FALSE);
6474 				}
6475 				compare_bigint = B_TRUE;
6476 				break;
6477 			case CKO_PUBLIC_KEY:
6478 				if (obj->key_type == CKK_DSA) {
6479 					bigint = OBJ_PUB_DSA_VALUE(obj);
6480 				} else if (obj->key_type == CKK_DH) {
6481 					bigint = OBJ_PUB_DH_VALUE(obj);
6482 				} else if (obj->key_type == CKK_X9_42_DH) {
6483 					bigint = OBJ_PUB_DH942_VALUE(obj);
6484 				} else {
6485 					return (B_FALSE);
6486 				}
6487 				compare_bigint = B_TRUE;
6488 				break;
6489 			case CKO_CERTIFICATE:
6490 				if (obj->cert_type == CKC_X_509) {
6491 					cert_attr = X509_CERT_VALUE(obj);
6492 				} else if (obj->cert_type ==
6493 				    CKC_X_509_ATTR_CERT) {
6494 					cert_attr = X509_ATTR_CERT_VALUE(obj);
6495 				}
6496 				compare_cert_val = B_TRUE;
6497 				break;
6498 			default:
6499 				return (B_FALSE);
6500 			}
6501 			break;
6502 		case CKA_MODULUS:
6503 			/* only RSA public and private key have this attr */
6504 			if (obj->key_type == CKK_RSA) {
6505 				if (obj->class == CKO_PUBLIC_KEY) {
6506 					bigint = OBJ_PUB_RSA_MOD(obj);
6507 				} else if (obj->class == CKO_PRIVATE_KEY) {
6508 					bigint = OBJ_PRI_RSA_MOD(obj);
6509 				} else {
6510 					return (B_FALSE);
6511 				}
6512 				compare_bigint = B_TRUE;
6513 			} else {
6514 				return (B_FALSE);
6515 			}
6516 			break;
6517 		case CKA_MODULUS_BITS:
6518 			/* only RSA public key has this attribute */
6519 			if ((obj->key_type == CKK_RSA) &&
6520 			    (obj->class == CKO_PUBLIC_KEY)) {
6521 				CK_ULONG mod_bits = OBJ_PUB_RSA_MOD_BITS(obj);
6522 				if (mod_bits !=
6523 				    *((CK_ULONG *)tmpl_attr->pValue)) {
6524 					return (B_FALSE);
6525 				}
6526 			} else {
6527 				return (B_FALSE);
6528 			}
6529 			break;
6530 		case CKA_PUBLIC_EXPONENT:
6531 			/* only RSA public and private key have this attr */
6532 			if (obj->key_type == CKK_RSA) {
6533 				if (obj->class == CKO_PUBLIC_KEY) {
6534 					bigint = OBJ_PUB_RSA_PUBEXPO(obj);
6535 				} else if (obj->class == CKO_PRIVATE_KEY) {
6536 					bigint = OBJ_PRI_RSA_PUBEXPO(obj);
6537 				} else {
6538 					return (B_FALSE);
6539 				}
6540 				compare_bigint = B_TRUE;
6541 			} else {
6542 				return (B_FALSE);
6543 			}
6544 			break;
6545 		case CKA_PRIVATE_EXPONENT:
6546 			/* only RSA private key has this attribute */
6547 			if ((obj->key_type == CKK_RSA) &&
6548 			    (obj->class == CKO_PRIVATE_KEY)) {
6549 				bigint = OBJ_PRI_RSA_PRIEXPO(obj);
6550 				compare_bigint = B_TRUE;
6551 			} else {
6552 				return (B_FALSE);
6553 			}
6554 			break;
6555 		case CKA_PRIME_1:
6556 			/* only RSA private key has this attribute */
6557 			if ((obj->key_type == CKK_RSA) &&
6558 			    (obj->class == CKO_PRIVATE_KEY)) {
6559 				bigint = OBJ_PRI_RSA_PRIME1(obj);
6560 				compare_bigint = B_TRUE;
6561 			} else {
6562 				return (B_FALSE);
6563 			}
6564 			break;
6565 		case CKA_PRIME_2:
6566 			/* only RSA private key has this attribute */
6567 			if ((obj->key_type == CKK_RSA) &&
6568 			    (obj->class == CKO_PRIVATE_KEY)) {
6569 				bigint = OBJ_PRI_RSA_PRIME2(obj);
6570 				compare_bigint = B_TRUE;
6571 			} else {
6572 				return (B_FALSE);
6573 			}
6574 			break;
6575 		case CKA_EXPONENT_1:
6576 			/* only RSA private key has this attribute */
6577 			if ((obj->key_type == CKK_RSA) &&
6578 			    (obj->class == CKO_PRIVATE_KEY)) {
6579 				bigint = OBJ_PRI_RSA_EXPO1(obj);
6580 				compare_bigint = B_TRUE;
6581 			} else {
6582 				return (B_FALSE);
6583 			}
6584 			break;
6585 		case CKA_EXPONENT_2:
6586 			/* only RSA private key has this attribute */
6587 			if ((obj->key_type == CKK_RSA) &&
6588 			    (obj->class == CKO_PRIVATE_KEY)) {
6589 				bigint = OBJ_PRI_RSA_EXPO2(obj);
6590 				compare_bigint = B_TRUE;
6591 			} else {
6592 				return (B_FALSE);
6593 			}
6594 			break;
6595 		case CKA_COEFFICIENT:
6596 			/* only RSA private key has this attribute */
6597 			if ((obj->key_type == CKK_RSA) &&
6598 			    (obj->class == CKO_PRIVATE_KEY)) {
6599 				bigint = OBJ_PRI_RSA_COEF(obj);
6600 				compare_bigint = B_TRUE;
6601 			} else {
6602 				return (B_FALSE);
6603 			}
6604 			break;
6605 		case CKA_VALUE_BITS:
6606 			/* only Diffie-Hellman private key has this attr */
6607 			if ((obj->key_type == CKK_DH) &&
6608 			    (obj->class == CKO_PRIVATE_KEY)) {
6609 				CK_ULONG val_bits = OBJ_PRI_DH_VAL_BITS(obj);
6610 				if (val_bits !=
6611 				    *((CK_ULONG *)tmpl_attr->pValue)) {
6612 					return (B_FALSE);
6613 				}
6614 			} else {
6615 				return (B_FALSE);
6616 			}
6617 			break;
6618 		case CKA_PRIME:
6619 			if (obj->class == CKO_PUBLIC_KEY) {
6620 				switch (obj->key_type) {
6621 				case CKK_DSA:
6622 					bigint = OBJ_PUB_DSA_PRIME(obj);
6623 					break;
6624 				case CKK_DH:
6625 					bigint = OBJ_PUB_DH_PRIME(obj);
6626 					break;
6627 				case CKK_X9_42_DH:
6628 					bigint = OBJ_PUB_DH942_PRIME(obj);
6629 					break;
6630 				default:
6631 					return (B_FALSE);
6632 				}
6633 			} else if (obj->class == CKO_PRIVATE_KEY) {
6634 				switch (obj->key_type) {
6635 				case CKK_DSA:
6636 					bigint = OBJ_PRI_DSA_PRIME(obj);
6637 					break;
6638 				case CKK_DH:
6639 					bigint = OBJ_PRI_DH_PRIME(obj);
6640 					break;
6641 				case CKK_X9_42_DH:
6642 					bigint = OBJ_PRI_DH942_PRIME(obj);
6643 					break;
6644 				default:
6645 					return (B_FALSE);
6646 				}
6647 			} else if (obj->class == CKO_DOMAIN_PARAMETERS) {
6648 				switch (obj->key_type) {
6649 				case CKK_DSA:
6650 					bigint = OBJ_DOM_DSA_PRIME(obj);
6651 					break;
6652 				case CKK_DH:
6653 					bigint = OBJ_DOM_DH_PRIME(obj);
6654 					break;
6655 				case CKK_X9_42_DH:
6656 					bigint = OBJ_DOM_DH942_PRIME(obj);
6657 					break;
6658 				default:
6659 					return (B_FALSE);
6660 				}
6661 			} else {
6662 				return (B_FALSE);
6663 			}
6664 			compare_bigint = B_TRUE;
6665 			break;
6666 		case CKA_SUBPRIME:
6667 			if (obj->class == CKO_PUBLIC_KEY) {
6668 				switch (obj->key_type) {
6669 				case CKK_DSA:
6670 					bigint = OBJ_PUB_DSA_SUBPRIME(obj);
6671 					break;
6672 				case CKK_X9_42_DH:
6673 					bigint = OBJ_PUB_DH942_SUBPRIME(obj);
6674 					break;
6675 				default:
6676 					return (B_FALSE);
6677 				}
6678 			} else if (obj->class == CKO_PRIVATE_KEY) {
6679 				switch (obj->key_type) {
6680 				case CKK_DSA:
6681 					bigint = OBJ_PRI_DSA_SUBPRIME(obj);
6682 					break;
6683 				case CKK_X9_42_DH:
6684 					bigint = OBJ_PRI_DH942_SUBPRIME(obj);
6685 					break;
6686 				default:
6687 					return (B_FALSE);
6688 				}
6689 			} else if (obj->class == CKO_DOMAIN_PARAMETERS) {
6690 				switch (obj->key_type) {
6691 				case CKK_DSA:
6692 					bigint = OBJ_DOM_DSA_SUBPRIME(obj);
6693 					break;
6694 				case CKK_X9_42_DH:
6695 					bigint = OBJ_DOM_DH942_SUBPRIME(obj);
6696 					break;
6697 				default:
6698 					return (B_FALSE);
6699 				}
6700 			} else {
6701 				return (B_FALSE);
6702 			}
6703 			compare_bigint = B_TRUE;
6704 			break;
6705 		case CKA_BASE:
6706 			if (obj->class == CKO_PUBLIC_KEY) {
6707 				switch (obj->key_type) {
6708 				case CKK_DSA:
6709 					bigint = OBJ_PUB_DSA_BASE(obj);
6710 					break;
6711 				case CKK_DH:
6712 					bigint = OBJ_PUB_DH_BASE(obj);
6713 					break;
6714 				case CKK_X9_42_DH:
6715 					bigint = OBJ_PUB_DH942_BASE(obj);
6716 					break;
6717 				default:
6718 					return (B_FALSE);
6719 				}
6720 			} else if (obj->class == CKO_PRIVATE_KEY) {
6721 				switch (obj->key_type) {
6722 				case CKK_DSA:
6723 					bigint = OBJ_PRI_DSA_BASE(obj);
6724 					break;
6725 				case CKK_DH:
6726 					bigint = OBJ_PRI_DH_BASE(obj);
6727 					break;
6728 				case CKK_X9_42_DH:
6729 					bigint = OBJ_PRI_DH942_BASE(obj);
6730 					break;
6731 				default:
6732 					return (B_FALSE);
6733 				}
6734 			} else if (obj->class == CKO_DOMAIN_PARAMETERS) {
6735 				switch (obj->key_type) {
6736 				case CKK_DSA:
6737 					bigint = OBJ_DOM_DSA_BASE(obj);
6738 					break;
6739 				case CKK_DH:
6740 					bigint = OBJ_DOM_DH_BASE(obj);
6741 					break;
6742 				case CKK_X9_42_DH:
6743 					bigint = OBJ_DOM_DH942_BASE(obj);
6744 					break;
6745 				default:
6746 					return (B_FALSE);
6747 				}
6748 			} else {
6749 				return (B_FALSE);
6750 			}
6751 			compare_bigint = B_TRUE;
6752 			break;
6753 		case CKA_PRIME_BITS:
6754 			if (obj->class == CKO_DOMAIN_PARAMETERS) {
6755 				CK_ULONG prime_bits;
6756 				if (obj->key_type == CKK_DSA) {
6757 					prime_bits =
6758 					    OBJ_DOM_DSA_PRIME_BITS(obj);
6759 				} else if (obj->key_type == CKK_DH) {
6760 					prime_bits =
6761 					    OBJ_DOM_DH_PRIME_BITS(obj);
6762 				} else if (obj->key_type == CKK_X9_42_DH) {
6763 					prime_bits =
6764 					    OBJ_DOM_DH942_PRIME_BITS(obj);
6765 				} else {
6766 					return (B_FALSE);
6767 				}
6768 				if (prime_bits !=
6769 				    *((CK_ULONG *)tmpl_attr->pValue)) {
6770 					return (B_FALSE);
6771 				}
6772 			} else {
6773 				return (B_FALSE);
6774 			}
6775 			break;
6776 		case CKA_SUBPRIME_BITS:
6777 			if ((obj->class == CKO_DOMAIN_PARAMETERS) &&
6778 			    (obj->key_type == CKK_X9_42_DH)) {
6779 				CK_ULONG subprime_bits =
6780 				    OBJ_DOM_DH942_SUBPRIME_BITS(obj);
6781 				if (subprime_bits !=
6782 				    *((CK_ULONG *)tmpl_attr->pValue)) {
6783 					return (B_FALSE);
6784 				}
6785 			} else {
6786 				return (B_FALSE);
6787 			}
6788 			break;
6789 		default:
6790 			/*
6791 			 * any other attributes are currently not supported.
6792 			 * so, it's not possible for them to be in the
6793 			 * object
6794 			 */
6795 			return (B_FALSE);
6796 		}
6797 		if (compare_boolean) {
6798 			CK_BBOOL bval;
6799 
6800 			if (attr_mask) {
6801 				bval = TRUE;
6802 			} else {
6803 				bval = FALSE;
6804 			}
6805 			if (bval != *((CK_BBOOL *)tmpl_attr->pValue)) {
6806 				return (B_FALSE);
6807 			}
6808 		} else if (compare_bigint) {
6809 			if (bigint == NULL) {
6810 				return (B_FALSE);
6811 			}
6812 			if (tmpl_attr->ulValueLen != bigint->big_value_len) {
6813 				return (B_FALSE);
6814 			}
6815 			if (memcmp(tmpl_attr->pValue, bigint->big_value,
6816 			    tmpl_attr->ulValueLen) != 0) {
6817 				return (B_FALSE);
6818 			}
6819 		} else if (compare_attr) {
6820 			if (obj_attr == NULL) {
6821 				/*
6822 				 * The attribute type is valid, and its value
6823 				 * has not been initialized in the object. In
6824 				 * this case, it only matches the template's
6825 				 * attribute if the template's value length
6826 				 * is 0.
6827 				 */
6828 				if (tmpl_attr->ulValueLen != 0)
6829 					return (B_FALSE);
6830 			} else {
6831 				if (tmpl_attr->ulValueLen !=
6832 				    obj_attr->ulValueLen) {
6833 					return (B_FALSE);
6834 				}
6835 				if (memcmp(tmpl_attr->pValue, obj_attr->pValue,
6836 				    tmpl_attr->ulValueLen) != 0) {
6837 					return (B_FALSE);
6838 				}
6839 			}
6840 		} else if (compare_cert_val) {
6841 			if (cert_attr == NULL) {
6842 				/* specific attribute not found */
6843 				return (B_FALSE);
6844 			}
6845 			if (tmpl_attr->ulValueLen != cert_attr->length) {
6846 				return (B_FALSE);
6847 			}
6848 			if (memcmp(tmpl_attr->pValue, cert_attr->value,
6849 			    tmpl_attr->ulValueLen) != 0) {
6850 				return (B_FALSE);
6851 			}
6852 		} else if (compare_cert_type) {
6853 			if (memcmp(tmpl_attr->pValue, &(obj->cert_type),
6854 			    tmpl_attr->ulValueLen) != 0) {
6855 				return (B_FALSE);
6856 			}
6857 		}
6858 	}
6859 	return (B_TRUE);
6860 }
6861 
6862 CK_ATTRIBUTE_PTR
6863 get_extra_attr(CK_ATTRIBUTE_TYPE type, soft_object_t *obj)
6864 {
6865 	CK_ATTRIBUTE_INFO_PTR tmp;
6866 
6867 	tmp = obj->extra_attrlistp;
6868 	while (tmp != NULL) {
6869 		if (tmp->attr.type == type) {
6870 			return (&(tmp->attr));
6871 		}
6872 		tmp = tmp->next;
6873 	}
6874 	/* if get there, the specified attribute is not found */
6875 	return (NULL);
6876 }
6877