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