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