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