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