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