xref: /titanic_50/usr/src/lib/pkcs11/pkcs11_softtoken/common/softAttributeUtil.c (revision 39b934fce0e8cf6fbca646adbc101efba60943f0)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <stdlib.h>
27 #include <string.h>
28 #include <security/cryptoki.h>
29 #include <sys/crypto/common.h>
30 #include <arcfour.h>
31 #include <aes_impl.h>
32 #include <blowfish_impl.h>
33 #include <bignum.h>
34 #include <des_impl.h>
35 #include <rsa_impl.h>
36 #include "softGlobal.h"
37 #include "softObject.h"
38 #include "softSession.h"
39 #include "softKeystore.h"
40 #include "softKeystoreUtil.h"
41 #include "softCrypt.h"
42 
43 
44 /*
45  * This attribute table is used by the soft_lookup_attr()
46  * to validate the attributes.
47  */
48 CK_ATTRIBUTE_TYPE attr_map[] = {
49 	CKA_PRIVATE,
50 	CKA_LABEL,
51 	CKA_APPLICATION,
52 	CKA_OBJECT_ID,
53 	CKA_CERTIFICATE_TYPE,
54 	CKA_ISSUER,
55 	CKA_SERIAL_NUMBER,
56 	CKA_AC_ISSUER,
57 	CKA_OWNER,
58 	CKA_ATTR_TYPES,
59 	CKA_SUBJECT,
60 	CKA_ID,
61 	CKA_SENSITIVE,
62 	CKA_START_DATE,
63 	CKA_END_DATE,
64 	CKA_MODULUS,
65 	CKA_MODULUS_BITS,
66 	CKA_PUBLIC_EXPONENT,
67 	CKA_PRIVATE_EXPONENT,
68 	CKA_PRIME_1,
69 	CKA_PRIME_2,
70 	CKA_EXPONENT_1,
71 	CKA_EXPONENT_2,
72 	CKA_COEFFICIENT,
73 	CKA_PRIME,
74 	CKA_SUBPRIME,
75 	CKA_BASE,
76 	CKA_EXTRACTABLE,
77 	CKA_LOCAL,
78 	CKA_NEVER_EXTRACTABLE,
79 	CKA_ALWAYS_SENSITIVE,
80 	CKA_MODIFIABLE,
81 	CKA_ECDSA_PARAMS,
82 	CKA_EC_PARAMS,
83 	CKA_EC_POINT,
84 	CKA_SECONDARY_AUTH,
85 	CKA_AUTH_PIN_FLAGS,
86 	CKA_HW_FEATURE_TYPE,
87 	CKA_RESET_ON_INIT,
88 	CKA_HAS_RESET
89 };
90 
91 /*
92  * attributes that exists only in public key objects
93  * Note: some attributes may also exist in one or two
94  *       other object classes, but they are also listed
95  *       because not all object have them.
96  */
97 CK_ATTRIBUTE_TYPE PUB_KEY_ATTRS[] =
98 {
99 	CKA_SUBJECT,
100 	CKA_ENCRYPT,
101 	CKA_WRAP,
102 	CKA_VERIFY,
103 	CKA_VERIFY_RECOVER,
104 	CKA_MODULUS,
105 	CKA_MODULUS_BITS,
106 	CKA_PUBLIC_EXPONENT,
107 	CKA_PRIME,
108 	CKA_SUBPRIME,
109 	CKA_BASE,
110 	CKA_TRUSTED,
111 	CKA_ECDSA_PARAMS,
112 	CKA_EC_PARAMS,
113 	CKA_EC_POINT
114 };
115 
116 /*
117  * attributes that exists only in private key objects
118  * Note: some attributes may also exist in one or two
119  *       other object classes, but they are also listed
120  *       because not all object have them.
121  */
122 CK_ATTRIBUTE_TYPE PRIV_KEY_ATTRS[] =
123 {
124 	CKA_DECRYPT,
125 	CKA_UNWRAP,
126 	CKA_SIGN,
127 	CKA_SIGN_RECOVER,
128 	CKA_MODULUS,
129 	CKA_PUBLIC_EXPONENT,
130 	CKA_PRIVATE_EXPONENT,
131 	CKA_PRIME,
132 	CKA_SUBPRIME,
133 	CKA_BASE,
134 	CKA_PRIME_1,
135 	CKA_PRIME_2,
136 	CKA_EXPONENT_1,
137 	CKA_EXPONENT_2,
138 	CKA_COEFFICIENT,
139 	CKA_VALUE_BITS,
140 	CKA_SUBJECT,
141 	CKA_SENSITIVE,
142 	CKA_EXTRACTABLE,
143 	CKA_NEVER_EXTRACTABLE,
144 	CKA_ALWAYS_SENSITIVE,
145 	CKA_EC_PARAMS
146 };
147 
148 /*
149  * attributes that exists only in secret key objects
150  * Note: some attributes may also exist in one or two
151  *       other object classes, but they are also listed
152  *       because not all object have them.
153  */
154 CK_ATTRIBUTE_TYPE SECRET_KEY_ATTRS[] =
155 {
156 	CKA_VALUE_LEN,
157 	CKA_ENCRYPT,
158 	CKA_DECRYPT,
159 	CKA_WRAP,
160 	CKA_UNWRAP,
161 	CKA_SIGN,
162 	CKA_VERIFY,
163 	CKA_SENSITIVE,
164 	CKA_EXTRACTABLE,
165 	CKA_NEVER_EXTRACTABLE,
166 	CKA_ALWAYS_SENSITIVE
167 };
168 
169 /*
170  * attributes that exists only in domain parameter objects
171  * Note: some attributes may also exist in one or two
172  *       other object classes, but they are also listed
173  *       because not all object have them.
174  */
175 CK_ATTRIBUTE_TYPE DOMAIN_ATTRS[] =
176 {
177 	CKA_PRIME,
178 	CKA_SUBPRIME,
179 	CKA_BASE,
180 	CKA_PRIME_BITS,
181 	CKA_SUBPRIME_BITS,
182 	CKA_SUB_PRIME_BITS
183 };
184 
185 /*
186  * attributes that exists only in hardware feature objects
187  *
188  */
189 CK_ATTRIBUTE_TYPE HARDWARE_ATTRS[] =
190 {
191 	CKA_HW_FEATURE_TYPE,
192 	CKA_RESET_ON_INIT,
193 	CKA_HAS_RESET
194 };
195 
196 /*
197  * attributes that exists only in certificate objects
198  */
199 CK_ATTRIBUTE_TYPE CERT_ATTRS[] =
200 {
201 	CKA_CERTIFICATE_TYPE,
202 	CKA_TRUSTED,
203 	CKA_SUBJECT,
204 	CKA_ID,
205 	CKA_ISSUER,
206 	CKA_AC_ISSUER,
207 	CKA_SERIAL_NUMBER,
208 	CKA_OWNER,
209 	CKA_ATTR_TYPES
210 };
211 
212 
213 /*
214  * Validate the attribute by using binary search algorithm.
215  */
216 CK_RV
217 soft_lookup_attr(CK_ATTRIBUTE_TYPE type)
218 {
219 
220 	size_t lower, middle, upper;
221 
222 	lower = 0;
223 	upper = (sizeof (attr_map) / sizeof (CK_ATTRIBUTE_TYPE)) - 1;
224 
225 	while (lower <= upper) {
226 		/* Always starts from middle. */
227 		middle = (lower + upper) / 2;
228 
229 		if (type > attr_map[middle]) {
230 			/* Adjust the lower bound to upper half. */
231 			lower = middle + 1;
232 			continue;
233 		}
234 
235 		if (type == attr_map[middle]) {
236 			/* Found it. */
237 			return (CKR_OK);
238 		}
239 
240 		if (type < attr_map[middle]) {
241 			/* Adjust the upper bound to lower half. */
242 			upper = middle - 1;
243 			continue;
244 		}
245 	}
246 
247 	/* Failed to find the matching attribute from the attribute table. */
248 	return (CKR_ATTRIBUTE_TYPE_INVALID);
249 }
250 
251 
252 /*
253  * Validate the attribute by using the following search algorithm:
254  *
255  * 1) Search for the most frequently used attributes first.
256  * 2) If not found, search for the usage-purpose attributes - these
257  *    attributes have dense set of values, therefore compiler will
258  *    optimize it with a branch table and branch to the appropriate
259  *    case.
260  * 3) If still not found, use binary search for the rest of the
261  *    attributes in the attr_map[] table.
262  */
263 CK_RV
264 soft_validate_attr(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
265 	CK_OBJECT_CLASS *class)
266 {
267 
268 	CK_ULONG i;
269 	CK_RV rv = CKR_OK;
270 
271 	for (i = 0; i < ulAttrNum; i++) {
272 		/* First tier search */
273 		switch (template[i].type) {
274 		case CKA_CLASS:
275 			*class = *((CK_OBJECT_CLASS*)template[i].pValue);
276 			break;
277 		case CKA_TOKEN:
278 			break;
279 		case CKA_KEY_TYPE:
280 			break;
281 		case CKA_VALUE:
282 			break;
283 		case CKA_VALUE_LEN:
284 			break;
285 		case CKA_VALUE_BITS:
286 			break;
287 		default:
288 			/* Second tier search */
289 			switch (template[i].type) {
290 			case CKA_ENCRYPT:
291 				break;
292 			case CKA_DECRYPT:
293 				break;
294 			case CKA_WRAP:
295 				break;
296 			case CKA_UNWRAP:
297 				break;
298 			case CKA_SIGN:
299 				break;
300 			case CKA_SIGN_RECOVER:
301 				break;
302 			case CKA_VERIFY:
303 				break;
304 			case CKA_VERIFY_RECOVER:
305 				break;
306 			case CKA_DERIVE:
307 				break;
308 			default:
309 				/* Third tier search */
310 				rv = soft_lookup_attr(template[i].type);
311 				if (rv != CKR_OK)
312 					return (rv);
313 				break;
314 			}
315 			break;
316 		}
317 	}
318 	return (rv);
319 }
320 
321 static void
322 cleanup_cert_attr(cert_attr_t *attr)
323 {
324 	if (attr) {
325 		if (attr->value) {
326 			(void) memset(attr->value, 0, attr->length);
327 			free(attr->value);
328 		}
329 		attr->value = NULL;
330 		attr->length = 0;
331 	}
332 }
333 
334 static CK_RV
335 copy_cert_attr(cert_attr_t *src_attr, cert_attr_t **dest_attr)
336 {
337 	CK_RV rv = CKR_OK;
338 
339 	if (src_attr == NULL || dest_attr == NULL)
340 		return (CKR_HOST_MEMORY);
341 
342 	if (src_attr->value == NULL)
343 		return (CKR_HOST_MEMORY);
344 
345 	/* free memory if its already allocated */
346 	if (*dest_attr != NULL) {
347 		if ((*dest_attr)->value != (CK_BYTE *)NULL)
348 			free((*dest_attr)->value);
349 	} else {
350 		*dest_attr = malloc(sizeof (cert_attr_t));
351 		if (*dest_attr == NULL)
352 			return (CKR_HOST_MEMORY);
353 	}
354 
355 	(*dest_attr)->value = NULL;
356 	(*dest_attr)->length = 0;
357 
358 	if (src_attr->length) {
359 		(*dest_attr)->value = malloc(src_attr->length);
360 		if ((*dest_attr)->value == NULL) {
361 			free(*dest_attr);
362 			return (CKR_HOST_MEMORY);
363 		}
364 
365 		(void) memcpy((*dest_attr)->value, src_attr->value,
366 		    src_attr->length);
367 		(*dest_attr)->length = src_attr->length;
368 	}
369 
370 	return (rv);
371 }
372 
373 void
374 soft_cleanup_cert_object(soft_object_t *object_p)
375 {
376 	CK_CERTIFICATE_TYPE certtype = object_p->cert_type;
377 
378 	if (object_p->class != CKO_CERTIFICATE ||
379 	    OBJ_CERT(object_p) == NULL)
380 		return;
381 
382 	if (certtype == CKC_X_509) {
383 		if (X509_CERT_SUBJECT(object_p) != NULL) {
384 			cleanup_cert_attr(X509_CERT_SUBJECT(object_p));
385 			free(X509_CERT_SUBJECT(object_p));
386 			X509_CERT_SUBJECT(object_p) = NULL;
387 		}
388 		if (X509_CERT_VALUE(object_p) != NULL) {
389 			cleanup_cert_attr(X509_CERT_VALUE(object_p));
390 			free(X509_CERT_VALUE(object_p));
391 			X509_CERT_VALUE(object_p) = NULL;
392 		}
393 		free(OBJ_CERT(object_p));
394 	} else if (certtype == CKC_X_509_ATTR_CERT) {
395 		if (X509_ATTR_CERT_VALUE(object_p) != NULL) {
396 			cleanup_cert_attr(X509_ATTR_CERT_VALUE(object_p));
397 			free(X509_ATTR_CERT_VALUE(object_p));
398 			X509_ATTR_CERT_VALUE(object_p) = NULL;
399 		}
400 		if (X509_ATTR_CERT_OWNER(object_p) != NULL) {
401 			cleanup_cert_attr(X509_ATTR_CERT_OWNER(object_p));
402 			free(X509_ATTR_CERT_OWNER(object_p));
403 			X509_ATTR_CERT_OWNER(object_p) = NULL;
404 		}
405 		free(OBJ_CERT(object_p));
406 	}
407 }
408 
409 /*
410  * Clean up and release all the storage in the extra attribute list
411  * of an object.
412  */
413 void
414 soft_cleanup_extra_attr(soft_object_t *object_p)
415 {
416 
417 	CK_ATTRIBUTE_INFO_PTR extra_attr;
418 	CK_ATTRIBUTE_INFO_PTR tmp;
419 
420 	extra_attr = object_p->extra_attrlistp;
421 	while (extra_attr) {
422 		tmp = extra_attr->next;
423 		if (extra_attr->attr.pValue)
424 			/*
425 			 * All extra attributes in the extra attribute
426 			 * list have pValue points to the value of the
427 			 * attribute (with simple byte array type).
428 			 * Free the storage for the value of the attribute.
429 			 */
430 			free(extra_attr->attr.pValue);
431 
432 		/* Free the storage for the attribute_info struct. */
433 		free(extra_attr);
434 		extra_attr = tmp;
435 	}
436 
437 	object_p->extra_attrlistp = NULL;
438 }
439 
440 
441 /*
442  * Create the attribute_info struct to hold the object's attribute,
443  * and add it to the extra attribute list of an object.
444  */
445 CK_RV
446 soft_add_extra_attr(CK_ATTRIBUTE_PTR template, soft_object_t *object_p)
447 {
448 
449 	CK_ATTRIBUTE_INFO_PTR attrp;
450 
451 	/* Allocate the storage for the attribute_info struct. */
452 	attrp = calloc(1, sizeof (attribute_info_t));
453 	if (attrp == NULL) {
454 		return (CKR_HOST_MEMORY);
455 	}
456 
457 	/* Set up attribute_info struct. */
458 	attrp->attr.type = template->type;
459 	attrp->attr.ulValueLen = template->ulValueLen;
460 
461 	if ((template->pValue != NULL) &&
462 	    (template->ulValueLen > 0)) {
463 		/* Allocate storage for the value of the attribute. */
464 		attrp->attr.pValue = malloc(template->ulValueLen);
465 		if (attrp->attr.pValue == NULL) {
466 			free(attrp);
467 			return (CKR_HOST_MEMORY);
468 		}
469 
470 		(void) memcpy(attrp->attr.pValue, template->pValue,
471 		    template->ulValueLen);
472 	} else {
473 		attrp->attr.pValue = NULL;
474 	}
475 
476 	/* Insert the new attribute in front of extra attribute list. */
477 	if (object_p->extra_attrlistp == NULL) {
478 		object_p->extra_attrlistp = attrp;
479 		attrp->next = NULL;
480 	} else {
481 		attrp->next = object_p->extra_attrlistp;
482 		object_p->extra_attrlistp = attrp;
483 	}
484 
485 	return (CKR_OK);
486 }
487 
488 CK_RV
489 soft_copy_certificate(certificate_obj_t *oldcert, certificate_obj_t **newcert,
490 		CK_CERTIFICATE_TYPE type)
491 {
492 	CK_RV rv = CKR_OK;
493 	certificate_obj_t	*cert;
494 	x509_cert_t		x509;
495 	x509_attr_cert_t	x509_attr;
496 
497 	cert = calloc(1, sizeof (certificate_obj_t));
498 	if (cert == NULL) {
499 		return (CKR_HOST_MEMORY);
500 	}
501 
502 	if (type == CKC_X_509) {
503 		x509 = oldcert->cert_type_u.x509;
504 		if (x509.subject)
505 			if ((rv = copy_cert_attr(x509.subject,
506 			    &cert->cert_type_u.x509.subject)))
507 				return (rv);
508 		if (x509.value)
509 			if ((rv = copy_cert_attr(x509.value,
510 			    &cert->cert_type_u.x509.value)))
511 				return (rv);
512 	} else if (type == CKC_X_509_ATTR_CERT) {
513 		x509_attr = oldcert->cert_type_u.x509_attr;
514 		if (x509_attr.owner)
515 			if ((rv = copy_cert_attr(x509_attr.owner,
516 			    &cert->cert_type_u.x509_attr.owner)))
517 				return (rv);
518 		if (x509_attr.value)
519 			if ((rv = copy_cert_attr(x509_attr.value,
520 			    &cert->cert_type_u.x509_attr.value)))
521 				return (rv);
522 	} else {
523 		/* wrong certificate type */
524 		rv = CKR_ATTRIBUTE_TYPE_INVALID;
525 	}
526 	if (rv == CKR_OK)
527 		*newcert = cert;
528 	return (rv);
529 }
530 
531 /*
532  * Copy the attribute_info struct from the old object to a new attribute_info
533  * struct, and add that new struct to the extra attribute list of the new
534  * object.
535  */
536 CK_RV
537 soft_copy_extra_attr(CK_ATTRIBUTE_INFO_PTR old_attrp, soft_object_t *object_p)
538 {
539 	CK_ATTRIBUTE_INFO_PTR attrp;
540 
541 	/* Allocate attribute_info struct. */
542 	attrp = calloc(1, sizeof (attribute_info_t));
543 	if (attrp == NULL) {
544 		return (CKR_HOST_MEMORY);
545 	}
546 
547 	attrp->attr.type = old_attrp->attr.type;
548 	attrp->attr.ulValueLen = old_attrp->attr.ulValueLen;
549 
550 	if ((old_attrp->attr.pValue != NULL) &&
551 	    (old_attrp->attr.ulValueLen > 0)) {
552 		attrp->attr.pValue = malloc(old_attrp->attr.ulValueLen);
553 		if (attrp->attr.pValue == NULL) {
554 			free(attrp);
555 			return (CKR_HOST_MEMORY);
556 		}
557 
558 		(void) memcpy(attrp->attr.pValue, old_attrp->attr.pValue,
559 		    old_attrp->attr.ulValueLen);
560 	} else {
561 		attrp->attr.pValue = NULL;
562 	}
563 
564 	/* Insert the new attribute in front of extra attribute list */
565 	if (object_p->extra_attrlistp == NULL) {
566 		object_p->extra_attrlistp = attrp;
567 		attrp->next = NULL;
568 	} else {
569 		attrp->next = object_p->extra_attrlistp;
570 		object_p->extra_attrlistp = attrp;
571 	}
572 
573 	return (CKR_OK);
574 }
575 
576 
577 /*
578  * Get the attribute triple from the extra attribute list in the object
579  * (if the specified attribute type is found), and copy it to a template.
580  * Note the type of the attribute to be copied is specified by the template,
581  * and the storage is pre-allocated for the atrribute value in the template
582  * for doing the copy.
583  */
584 CK_RV
585 get_extra_attr_from_object(soft_object_t *object_p, CK_ATTRIBUTE_PTR template)
586 {
587 
588 	CK_ATTRIBUTE_INFO_PTR extra_attr;
589 	CK_ATTRIBUTE_TYPE type = template->type;
590 
591 	extra_attr = object_p->extra_attrlistp;
592 
593 	while (extra_attr) {
594 		if (type == extra_attr->attr.type) {
595 			/* Found it. */
596 			break;
597 		} else {
598 			/* Does not match, try next one. */
599 			extra_attr = extra_attr->next;
600 		}
601 	}
602 
603 	if (extra_attr == NULL) {
604 		/* A valid but un-initialized attribute. */
605 		template->ulValueLen = 0;
606 		return (CKR_OK);
607 	}
608 
609 	/*
610 	 * We found the attribute in the extra attribute list.
611 	 */
612 	if (template->pValue == NULL) {
613 		template->ulValueLen = extra_attr->attr.ulValueLen;
614 		return (CKR_OK);
615 	}
616 
617 	if (template->ulValueLen >= extra_attr->attr.ulValueLen) {
618 		/*
619 		 * The buffer provided by the application is large
620 		 * enough to hold the value of the attribute.
621 		 */
622 		(void) memcpy(template->pValue, extra_attr->attr.pValue,
623 		    extra_attr->attr.ulValueLen);
624 		template->ulValueLen = extra_attr->attr.ulValueLen;
625 		return (CKR_OK);
626 	} else {
627 		/*
628 		 * The buffer provided by the application does
629 		 * not have enough space to hold the value.
630 		 */
631 		template->ulValueLen = (CK_ULONG)-1;
632 		return (CKR_BUFFER_TOO_SMALL);
633 	}
634 }
635 
636 
637 /*
638  * Modify the attribute triple in the extra attribute list of the object
639  * if the specified attribute type is found. Otherwise, just add it to
640  * list.
641  */
642 CK_RV
643 set_extra_attr_to_object(soft_object_t *object_p, CK_ATTRIBUTE_TYPE type,
644 	CK_ATTRIBUTE_PTR template)
645 {
646 
647 	CK_ATTRIBUTE_INFO_PTR extra_attr;
648 
649 	extra_attr = object_p->extra_attrlistp;
650 
651 	while (extra_attr) {
652 		if (type == extra_attr->attr.type) {
653 			/* Found it. */
654 			break;
655 		} else {
656 			/* Does not match, try next one. */
657 			extra_attr = extra_attr->next;
658 		}
659 	}
660 
661 	if (extra_attr == NULL) {
662 		/*
663 		 * This attribute is a new one, go ahead adding it to
664 		 * the extra attribute list.
665 		 */
666 		return (soft_add_extra_attr(template, object_p));
667 	}
668 
669 	/* We found the attribute in the extra attribute list. */
670 	if ((template->pValue != NULL) &&
671 	    (template->ulValueLen > 0)) {
672 		if (template->ulValueLen > extra_attr->attr.ulValueLen) {
673 			/* The old buffer is too small to hold the new value. */
674 			if (extra_attr->attr.pValue != NULL)
675 				/* Free storage for the old attribute value. */
676 				free(extra_attr->attr.pValue);
677 
678 			/* Allocate storage for the new attribute value. */
679 			extra_attr->attr.pValue = malloc(template->ulValueLen);
680 			if (extra_attr->attr.pValue == NULL) {
681 				return (CKR_HOST_MEMORY);
682 			}
683 		}
684 
685 		/* Replace the attribute with new value. */
686 		extra_attr->attr.ulValueLen = template->ulValueLen;
687 		(void) memcpy(extra_attr->attr.pValue, template->pValue,
688 		    template->ulValueLen);
689 	} else {
690 		extra_attr->attr.pValue = NULL;
691 	}
692 
693 	return (CKR_OK);
694 }
695 
696 
697 /*
698  * Copy the big integer attribute value from template to a biginteger_t struct.
699  */
700 CK_RV
701 get_bigint_attr_from_template(biginteger_t *big, CK_ATTRIBUTE_PTR template)
702 {
703 
704 	if ((template->pValue != NULL) &&
705 	    (template->ulValueLen > 0)) {
706 		/* Allocate storage for the value of the attribute. */
707 		big->big_value = malloc(template->ulValueLen);
708 		if (big->big_value == NULL) {
709 			return (CKR_HOST_MEMORY);
710 		}
711 
712 		(void) memcpy(big->big_value, template->pValue,
713 		    template->ulValueLen);
714 		big->big_value_len = template->ulValueLen;
715 	} else {
716 		big->big_value = NULL;
717 		big->big_value_len = 0;
718 	}
719 
720 	return (CKR_OK);
721 }
722 
723 
724 /*
725  * Copy the big integer attribute value from a biginteger_t struct in the
726  * object to a template.
727  */
728 CK_RV
729 get_bigint_attr_from_object(biginteger_t *big, CK_ATTRIBUTE_PTR template)
730 {
731 
732 	if (template->pValue == NULL) {
733 		template->ulValueLen = big->big_value_len;
734 		return (CKR_OK);
735 	}
736 
737 	if (big->big_value == NULL) {
738 		template->ulValueLen = 0;
739 		return (CKR_OK);
740 	}
741 
742 	if (template->ulValueLen >= big->big_value_len) {
743 		/*
744 		 * The buffer provided by the application is large
745 		 * enough to hold the value of the attribute.
746 		 */
747 		(void) memcpy(template->pValue, big->big_value,
748 		    big->big_value_len);
749 		template->ulValueLen = big->big_value_len;
750 		return (CKR_OK);
751 	} else {
752 		/*
753 		 * The buffer provided by the application does
754 		 * not have enough space to hold the value.
755 		 */
756 		template->ulValueLen = (CK_ULONG)-1;
757 		return (CKR_BUFFER_TOO_SMALL);
758 	}
759 }
760 
761 
762 /*
763  * Copy the boolean data type attribute value from an object for the
764  * specified attribute to the template.
765  */
766 CK_RV
767 get_bool_attr_from_object(soft_object_t *object_p, CK_ULONG bool_flag,
768 	CK_ATTRIBUTE_PTR template)
769 {
770 
771 	if (template->pValue == NULL) {
772 		template->ulValueLen = sizeof (CK_BBOOL);
773 		return (CKR_OK);
774 	}
775 
776 	if (template->ulValueLen >= sizeof (CK_BBOOL)) {
777 		/*
778 		 * The buffer provided by the application is large
779 		 * enough to hold the value of the attribute.
780 		 */
781 		if (object_p->bool_attr_mask & bool_flag) {
782 			*((CK_BBOOL *)template->pValue) = B_TRUE;
783 		} else {
784 			*((CK_BBOOL *)template->pValue) = B_FALSE;
785 		}
786 
787 		template->ulValueLen = sizeof (CK_BBOOL);
788 		return (CKR_OK);
789 	} else {
790 		/*
791 		 * The buffer provided by the application does
792 		 * not have enough space to hold the value.
793 		 */
794 		template->ulValueLen = (CK_ULONG)-1;
795 		return (CKR_BUFFER_TOO_SMALL);
796 	}
797 }
798 
799 /*
800  * Set the boolean data type attribute value in the object.
801  */
802 CK_RV
803 set_bool_attr_to_object(soft_object_t *object_p, CK_ULONG bool_flag,
804 	CK_ATTRIBUTE_PTR template)
805 {
806 
807 	if (*(CK_BBOOL *)template->pValue)
808 		object_p->bool_attr_mask |= bool_flag;
809 	else
810 		object_p->bool_attr_mask &= ~bool_flag;
811 
812 	return (CKR_OK);
813 }
814 
815 
816 /*
817  * Copy the CK_ULONG data type attribute value from an object to the
818  * template.
819  */
820 CK_RV
821 get_ulong_attr_from_object(CK_ULONG value, CK_ATTRIBUTE_PTR template)
822 {
823 
824 	if (template->pValue == NULL) {
825 		template->ulValueLen = sizeof (CK_ULONG);
826 		return (CKR_OK);
827 	}
828 
829 	if (template->ulValueLen >= sizeof (CK_ULONG)) {
830 		/*
831 		 * The buffer provided by the application is large
832 		 * enough to hold the value of the attribute.
833 		 * It is also assumed to be correctly aligned.
834 		 */
835 		*(CK_ULONG_PTR)template->pValue = value;
836 		template->ulValueLen = sizeof (CK_ULONG);
837 		return (CKR_OK);
838 	} else {
839 		/*
840 		 * The buffer provided by the application does
841 		 * not have enough space to hold the value.
842 		 */
843 		template->ulValueLen = (CK_ULONG)-1;
844 		return (CKR_BUFFER_TOO_SMALL);
845 	}
846 }
847 
848 
849 /*
850  * Copy the CK_ULONG data type attribute value from a template to the
851  * object.
852  */
853 static CK_RV
854 get_ulong_attr_from_template(CK_ULONG *value, CK_ATTRIBUTE_PTR template)
855 {
856 
857 	if (template->ulValueLen < sizeof (CK_ULONG))
858 		return (CKR_ATTRIBUTE_VALUE_INVALID);
859 
860 	if (template->pValue != NULL) {
861 		*value = *(CK_ULONG_PTR)template->pValue;
862 	} else {
863 		*value = 0;
864 	}
865 
866 	return (CKR_OK);
867 }
868 
869 /*
870  * Copy the big integer attribute value from source's biginteger_t to
871  * destination's biginteger_t.
872  */
873 void
874 copy_bigint_attr(biginteger_t *src, biginteger_t *dst)
875 {
876 
877 	if ((src->big_value != NULL) &&
878 	    (src->big_value_len > 0)) {
879 		/*
880 		 * To do the copy, just have dst's big_value points
881 		 * to src's.
882 		 */
883 		dst->big_value = src->big_value;
884 		dst->big_value_len = src->big_value_len;
885 
886 		/*
887 		 * After the copy, nullify the src's big_value pointer.
888 		 * It prevents any double freeing the value.
889 		 */
890 		src->big_value = NULL;
891 		src->big_value_len = 0;
892 	} else {
893 		dst->big_value = NULL;
894 		dst->big_value_len = 0;
895 	}
896 }
897 
898 CK_RV
899 get_string_from_template(CK_ATTRIBUTE_PTR dest, CK_ATTRIBUTE_PTR src)
900 {
901 	if ((src->pValue != NULL) &&
902 	    (src->ulValueLen > 0)) {
903 		/* Allocate storage for the value of the attribute. */
904 		dest->pValue = malloc(src->ulValueLen);
905 		if (dest->pValue == NULL) {
906 			return (CKR_HOST_MEMORY);
907 		}
908 
909 		(void) memcpy(dest->pValue, src->pValue,
910 		    src->ulValueLen);
911 		dest->ulValueLen = src->ulValueLen;
912 		dest->type = src->type;
913 	} else {
914 		dest->pValue = NULL;
915 		dest->ulValueLen = 0;
916 		dest->type = src->type;
917 	}
918 
919 	return (CKR_OK);
920 
921 }
922 
923 CK_RV
924 get_cert_attr_from_template(cert_attr_t **dest, CK_ATTRIBUTE_PTR src)
925 {
926 	if (src->pValue != NULL && src->ulValueLen > 0) {
927 		/*
928 		 * If the attribute was already set, clear out the
929 		 * existing value and release the memory.
930 		 */
931 		if (*dest != NULL) {
932 			if ((*dest)->value != NULL) {
933 				(void) memset((*dest)->value, 0,
934 				    (*dest)->length);
935 				free((*dest)->value);
936 			}
937 		} else {
938 			*dest = malloc(sizeof (cert_attr_t));
939 			if (*dest == NULL) {
940 				return (CKR_HOST_MEMORY);
941 			}
942 			(void) memset(*dest, 0, sizeof (cert_attr_t));
943 		}
944 		(*dest)->value = malloc(src->ulValueLen);
945 		if ((*dest)->value == NULL) {
946 			free(*dest);
947 			*dest = NULL;
948 			return (CKR_HOST_MEMORY);
949 		}
950 		(void) memcpy((*dest)->value, src->pValue, src->ulValueLen);
951 		(*dest)->length = src->ulValueLen;
952 	}
953 
954 	return (CKR_OK);
955 }
956 
957 /*
958  * Copy the certificate attribute information to the template.
959  * If the template attribute is not big enough, set the ulValueLen=-1
960  * and return CKR_BUFFER_TOO_SMALL.
961  */
962 static CK_RV
963 get_cert_attr_from_object(cert_attr_t *src, CK_ATTRIBUTE_PTR template)
964 {
965 	if (template->pValue == NULL) {
966 		template->ulValueLen = src->length;
967 		return (CKR_OK);
968 	} else if (template->ulValueLen >= src->length) {
969 		/*
970 		 * The buffer provided by the application is large
971 		 * enough to hold the value of the attribute.
972 		 */
973 		(void) memcpy(template->pValue, src->value, src->length);
974 		template->ulValueLen = src->length;
975 		return (CKR_OK);
976 	} else {
977 		/*
978 		 * The buffer provided by the application does
979 		 * not have enough space to hold the value.
980 		 */
981 		template->ulValueLen = (CK_ULONG)-1;
982 		return (CKR_BUFFER_TOO_SMALL);
983 	}
984 }
985 
986 void
987 string_attr_cleanup(CK_ATTRIBUTE_PTR template)
988 {
989 
990 	if (template->pValue) {
991 		free(template->pValue);
992 		template->pValue = NULL;
993 		template->ulValueLen = 0;
994 	}
995 }
996 
997 /*
998  * Release the storage allocated for object attribute with big integer
999  * value.
1000  */
1001 void
1002 bigint_attr_cleanup(biginteger_t *big)
1003 {
1004 
1005 	if (big == NULL)
1006 		return;
1007 
1008 	if (big->big_value) {
1009 		(void) memset(big->big_value, 0, big->big_value_len);
1010 		free(big->big_value);
1011 		big->big_value = NULL;
1012 		big->big_value_len = 0;
1013 	}
1014 }
1015 
1016 
1017 /*
1018  * Clean up and release all the storage allocated to hold the big integer
1019  * attributes associated with the type (i.e. class) of the object. Also,
1020  * release the storage allocated to the type of the object.
1021  */
1022 void
1023 soft_cleanup_object_bigint_attrs(soft_object_t *object_p)
1024 {
1025 
1026 	CK_OBJECT_CLASS class = object_p->class;
1027 	CK_KEY_TYPE	keytype = object_p->key_type;
1028 
1029 
1030 	switch (class) {
1031 	case CKO_PUBLIC_KEY:
1032 		if (OBJ_PUB(object_p)) {
1033 			switch (keytype) {
1034 			case CKK_RSA:
1035 				bigint_attr_cleanup(OBJ_PUB_RSA_MOD(
1036 				    object_p));
1037 				bigint_attr_cleanup(OBJ_PUB_RSA_PUBEXPO(
1038 				    object_p));
1039 				break;
1040 
1041 			case CKK_DSA:
1042 				bigint_attr_cleanup(OBJ_PUB_DSA_PRIME(
1043 				    object_p));
1044 				bigint_attr_cleanup(OBJ_PUB_DSA_SUBPRIME(
1045 				    object_p));
1046 				bigint_attr_cleanup(OBJ_PUB_DSA_BASE(
1047 				    object_p));
1048 				bigint_attr_cleanup(OBJ_PUB_DSA_VALUE(
1049 				    object_p));
1050 				break;
1051 
1052 			case CKK_DH:
1053 				bigint_attr_cleanup(OBJ_PUB_DH_PRIME(
1054 				    object_p));
1055 				bigint_attr_cleanup(OBJ_PUB_DH_BASE(
1056 				    object_p));
1057 				bigint_attr_cleanup(OBJ_PUB_DH_VALUE(
1058 				    object_p));
1059 				break;
1060 
1061 			case CKK_X9_42_DH:
1062 				bigint_attr_cleanup(OBJ_PUB_DH942_PRIME(
1063 				    object_p));
1064 				bigint_attr_cleanup(OBJ_PUB_DH942_BASE(
1065 				    object_p));
1066 				bigint_attr_cleanup(OBJ_PUB_DH942_SUBPRIME(
1067 				    object_p));
1068 				bigint_attr_cleanup(OBJ_PUB_DH942_VALUE(
1069 				    object_p));
1070 				break;
1071 			case CKK_EC:
1072 				bigint_attr_cleanup(OBJ_PUB_EC_POINT(
1073 				    object_p));
1074 				break;
1075 			}
1076 
1077 			/* Release Public Key Object struct */
1078 			free(OBJ_PUB(object_p));
1079 			OBJ_PUB(object_p) = NULL;
1080 		}
1081 		break;
1082 
1083 	case CKO_PRIVATE_KEY:
1084 		if (OBJ_PRI(object_p)) {
1085 			switch (keytype) {
1086 			case CKK_RSA:
1087 				bigint_attr_cleanup(OBJ_PRI_RSA_MOD(
1088 				    object_p));
1089 				bigint_attr_cleanup(OBJ_PRI_RSA_PUBEXPO(
1090 				    object_p));
1091 				bigint_attr_cleanup(OBJ_PRI_RSA_PRIEXPO(
1092 				    object_p));
1093 				bigint_attr_cleanup(OBJ_PRI_RSA_PRIME1(
1094 				    object_p));
1095 				bigint_attr_cleanup(OBJ_PRI_RSA_PRIME2(
1096 				    object_p));
1097 				bigint_attr_cleanup(OBJ_PRI_RSA_EXPO1(
1098 				    object_p));
1099 				bigint_attr_cleanup(OBJ_PRI_RSA_EXPO2(
1100 				    object_p));
1101 				bigint_attr_cleanup(OBJ_PRI_RSA_COEF(
1102 				    object_p));
1103 				break;
1104 
1105 			case CKK_DSA:
1106 				bigint_attr_cleanup(OBJ_PRI_DSA_PRIME(
1107 				    object_p));
1108 				bigint_attr_cleanup(OBJ_PRI_DSA_SUBPRIME(
1109 				    object_p));
1110 				bigint_attr_cleanup(OBJ_PRI_DSA_BASE(
1111 				    object_p));
1112 				bigint_attr_cleanup(OBJ_PRI_DSA_VALUE(
1113 				    object_p));
1114 				break;
1115 
1116 			case CKK_DH:
1117 				bigint_attr_cleanup(OBJ_PRI_DH_PRIME(
1118 				    object_p));
1119 				bigint_attr_cleanup(OBJ_PRI_DH_BASE(
1120 				    object_p));
1121 				bigint_attr_cleanup(OBJ_PRI_DH_VALUE(
1122 				    object_p));
1123 				break;
1124 
1125 			case CKK_X9_42_DH:
1126 				bigint_attr_cleanup(OBJ_PRI_DH942_PRIME(
1127 				    object_p));
1128 				bigint_attr_cleanup(OBJ_PRI_DH942_BASE(
1129 				    object_p));
1130 				bigint_attr_cleanup(OBJ_PRI_DH942_SUBPRIME(
1131 				    object_p));
1132 				bigint_attr_cleanup(OBJ_PRI_DH942_VALUE(
1133 				    object_p));
1134 				break;
1135 
1136 			case CKK_EC:
1137 				bigint_attr_cleanup(OBJ_PRI_EC_VALUE(
1138 				    object_p));
1139 				break;
1140 			}
1141 
1142 			/* Release Private Key Object struct. */
1143 			free(OBJ_PRI(object_p));
1144 			OBJ_PRI(object_p) = NULL;
1145 		}
1146 		break;
1147 
1148 	case CKO_SECRET_KEY:
1149 		if (OBJ_SEC(object_p)) {
1150 			/* cleanup key data area */
1151 			if (OBJ_SEC_VALUE(object_p) != NULL &&
1152 			    OBJ_SEC_VALUE_LEN(object_p) > 0) {
1153 				(void) memset(OBJ_SEC_VALUE(object_p), 0,
1154 				    OBJ_SEC_VALUE_LEN(object_p));
1155 				free(OBJ_SEC_VALUE(object_p));
1156 			}
1157 			/* cleanup key schedule data area */
1158 			if (OBJ_KEY_SCHED(object_p) != NULL &&
1159 			    OBJ_KEY_SCHED_LEN(object_p) > 0) {
1160 				(void) memset(OBJ_KEY_SCHED(object_p), 0,
1161 				    OBJ_KEY_SCHED_LEN(object_p));
1162 				free(OBJ_KEY_SCHED(object_p));
1163 			}
1164 
1165 			/* Release Secret Key Object struct. */
1166 			free(OBJ_SEC(object_p));
1167 			OBJ_SEC(object_p) = NULL;
1168 		}
1169 		break;
1170 
1171 	case CKO_DOMAIN_PARAMETERS:
1172 		if (OBJ_DOM(object_p)) {
1173 			switch (keytype) {
1174 			case CKK_DSA:
1175 				bigint_attr_cleanup(OBJ_DOM_DSA_PRIME(
1176 				    object_p));
1177 				bigint_attr_cleanup(OBJ_DOM_DSA_SUBPRIME(
1178 				    object_p));
1179 				bigint_attr_cleanup(OBJ_DOM_DSA_BASE(
1180 				    object_p));
1181 				break;
1182 
1183 			case CKK_DH:
1184 				bigint_attr_cleanup(OBJ_DOM_DH_PRIME(
1185 				    object_p));
1186 				bigint_attr_cleanup(OBJ_DOM_DH_BASE(
1187 				    object_p));
1188 				break;
1189 
1190 			case CKK_X9_42_DH:
1191 				bigint_attr_cleanup(OBJ_DOM_DH942_PRIME(
1192 				    object_p));
1193 				bigint_attr_cleanup(OBJ_DOM_DH942_BASE(
1194 				    object_p));
1195 				bigint_attr_cleanup(OBJ_DOM_DH942_SUBPRIME(
1196 				    object_p));
1197 				break;
1198 			}
1199 
1200 			/* Release Domain Parameters Object struct. */
1201 			free(OBJ_DOM(object_p));
1202 			OBJ_DOM(object_p) = NULL;
1203 		}
1204 		break;
1205 	}
1206 }
1207 
1208 
1209 /*
1210  * Parse the common attributes. Return to caller with appropriate return
1211  * value to indicate if the supplied template specifies a valid attribute
1212  * with a valid value.
1213  */
1214 CK_RV
1215 soft_parse_common_attrs(CK_ATTRIBUTE_PTR template, uchar_t *object_type)
1216 {
1217 
1218 	CK_RV rv = CKR_OK;
1219 
1220 	switch (template->type) {
1221 	case CKA_CLASS:
1222 		break;
1223 
1224 	/* default boolean attributes */
1225 	case CKA_TOKEN:
1226 		if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
1227 			if (!soft_keystore_status(KEYSTORE_INITIALIZED))
1228 				return (CKR_DEVICE_REMOVED);
1229 			*object_type |= TOKEN_OBJECT;
1230 		}
1231 		break;
1232 
1233 	case CKA_PRIVATE:
1234 		if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
1235 			(void) pthread_mutex_lock(&soft_giant_mutex);
1236 			if (!soft_slot.authenticated) {
1237 				/*
1238 				 * Check if this is the special case when
1239 				 * the PIN is never initialized in the keystore.
1240 				 * If true, we will let it pass here and let
1241 				 * it fail with CKR_PIN_EXPIRED later on.
1242 				 */
1243 				if (!soft_slot.userpin_change_needed) {
1244 					(void) pthread_mutex_unlock(
1245 					    &soft_giant_mutex);
1246 					return (CKR_USER_NOT_LOGGED_IN);
1247 				}
1248 			}
1249 			(void) pthread_mutex_unlock(&soft_giant_mutex);
1250 			*object_type |= PRIVATE_OBJECT;
1251 		}
1252 		break;
1253 
1254 	case CKA_LABEL:
1255 		break;
1256 
1257 	default:
1258 		rv = CKR_TEMPLATE_INCONSISTENT;
1259 	}
1260 
1261 	return (rv);
1262 }
1263 
1264 
1265 /*
1266  * Build a Public Key Object.
1267  *
1268  * - Parse the object's template, and when an error is detected such as
1269  *   invalid attribute type, invalid attribute value, etc., return
1270  *   with appropriate return value.
1271  * - Set up attribute mask field in the object for the supplied common
1272  *   attributes that have boolean type.
1273  * - Build the attribute_info struct to hold the value of each supplied
1274  *   attribute that has byte array type. Link attribute_info structs
1275  *   together to form the extra attribute list of the object.
1276  * - Allocate storage for the Public Key object.
1277  * - Build the Public Key object according to the key type. Allocate
1278  *   storage to hold the big integer value for the supplied attributes
1279  *   that are required for a certain key type.
1280  *
1281  */
1282 CK_RV
1283 soft_build_public_key_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
1284 	soft_object_t *new_object, CK_ULONG mode, CK_KEY_TYPE key_type)
1285 {
1286 
1287 	ulong_t		i;
1288 	CK_KEY_TYPE	keytype = (CK_KEY_TYPE)~0UL;
1289 	uint64_t	attr_mask = PUBLIC_KEY_DEFAULT;
1290 	CK_RV 		rv = CKR_OK;
1291 	int		isLabel = 0;
1292 	/* Must set flags */
1293 	int		isModulus = 0;
1294 	int		isPubExpo = 0;
1295 	int		isPrime = 0;
1296 	int		isSubprime = 0;
1297 	int		isBase = 0;
1298 	int		isValue = 0;
1299 	int		isECParam = 0;
1300 	int		isECPoint = 0;
1301 	/* Must not set flags */
1302 	int		isModulusBits = 0;
1303 	CK_ULONG	modulus_bits = 0;
1304 
1305 	biginteger_t	modulus;
1306 	biginteger_t	pubexpo;
1307 	biginteger_t	prime;
1308 	biginteger_t	subprime;
1309 	biginteger_t	base;
1310 	biginteger_t	value;
1311 	biginteger_t	point;
1312 	CK_ATTRIBUTE	string_tmp;
1313 	CK_ATTRIBUTE	param_tmp;
1314 
1315 	public_key_obj_t  *pbk;
1316 	uchar_t	object_type = 0;
1317 
1318 	CK_ATTRIBUTE	defpubexpo = { CKA_PUBLIC_EXPONENT,
1319 	    (CK_BYTE_PTR)DEFAULT_PUB_EXPO, DEFAULT_PUB_EXPO_Len };
1320 
1321 	BIGNUM		n;
1322 
1323 	/* prevent bigint_attr_cleanup from freeing invalid attr value */
1324 	(void) memset(&modulus, 0x0, sizeof (biginteger_t));
1325 	(void) memset(&pubexpo, 0x0, sizeof (biginteger_t));
1326 	(void) memset(&prime, 0x0, sizeof (biginteger_t));
1327 	(void) memset(&subprime, 0x0, sizeof (biginteger_t));
1328 	(void) memset(&base, 0x0, sizeof (biginteger_t));
1329 	(void) memset(&value, 0x0, sizeof (biginteger_t));
1330 	(void) memset(&point, 0x0, sizeof (biginteger_t));
1331 	string_tmp.pValue = NULL;
1332 	param_tmp.pValue = NULL;
1333 
1334 	for (i = 0; i < ulAttrNum; i++) {
1335 
1336 		/* Public Key Object Attributes */
1337 		switch (template[i].type) {
1338 
1339 		/* common key attributes */
1340 		case CKA_KEY_TYPE:
1341 			keytype = *((CK_KEY_TYPE*)template[i].pValue);
1342 			break;
1343 
1344 		case CKA_ID:
1345 		case CKA_START_DATE:
1346 		case CKA_END_DATE:
1347 
1348 		/* common public key attribute */
1349 		case CKA_SUBJECT:
1350 			/*
1351 			 * Allocate storage to hold the attribute
1352 			 * value with byte array type, and add it to
1353 			 * the extra attribute list of the object.
1354 			 */
1355 			rv = soft_add_extra_attr(&template[i],
1356 			    new_object);
1357 			if (rv != CKR_OK) {
1358 				goto fail_cleanup;
1359 			}
1360 			break;
1361 
1362 		/*
1363 		 * The following key related attribute types must
1364 		 * not be specified by C_CreateObject, C_GenerateKey(Pair).
1365 		 */
1366 		case CKA_LOCAL:
1367 		case CKA_KEY_GEN_MECHANISM:
1368 			rv = CKR_TEMPLATE_INCONSISTENT;
1369 			goto fail_cleanup;
1370 
1371 		/* Key related boolean attributes */
1372 		case CKA_DERIVE:
1373 			if (*(CK_BBOOL *)template[i].pValue)
1374 				attr_mask |= DERIVE_BOOL_ON;
1375 			break;
1376 
1377 		case CKA_ENCRYPT:
1378 			if (*(CK_BBOOL *)template[i].pValue)
1379 				attr_mask |= ENCRYPT_BOOL_ON;
1380 			else
1381 				attr_mask &= ~ENCRYPT_BOOL_ON;
1382 			break;
1383 
1384 		case CKA_VERIFY:
1385 			if (*(CK_BBOOL *)template[i].pValue)
1386 				attr_mask |= VERIFY_BOOL_ON;
1387 			else
1388 				attr_mask &= ~VERIFY_BOOL_ON;
1389 			break;
1390 
1391 		case CKA_VERIFY_RECOVER:
1392 			if (*(CK_BBOOL *)template[i].pValue)
1393 				attr_mask |= VERIFY_RECOVER_BOOL_ON;
1394 			else
1395 				attr_mask &= ~VERIFY_RECOVER_BOOL_ON;
1396 			break;
1397 
1398 		case CKA_WRAP:
1399 			if (*(CK_BBOOL *)template[i].pValue)
1400 				attr_mask |= WRAP_BOOL_ON;
1401 			else
1402 				attr_mask &= ~WRAP_BOOL_ON;
1403 			break;
1404 
1405 		case CKA_TRUSTED:
1406 			if (*(CK_BBOOL *)template[i].pValue)
1407 				attr_mask |= TRUSTED_BOOL_ON;
1408 			break;
1409 
1410 		case CKA_MODIFIABLE:
1411 			if ((*(CK_BBOOL *)template[i].pValue) == B_FALSE)
1412 				attr_mask |= NOT_MODIFIABLE_BOOL_ON;
1413 			break;
1414 
1415 		/*
1416 		 * The following key related attribute types must
1417 		 * be specified according to the key type by
1418 		 * C_CreateObject.
1419 		 */
1420 		case CKA_MODULUS:
1421 
1422 			isModulus = 1;
1423 			/*
1424 			 * Copyin big integer attribute from template
1425 			 * to a local variable.
1426 			 */
1427 			rv = get_bigint_attr_from_template(&modulus,
1428 			    &template[i]);
1429 			if (rv != CKR_OK)
1430 				goto fail_cleanup;
1431 
1432 			/*
1433 			 * Modulus length needs to be between min key length and
1434 			 * max key length.
1435 			 */
1436 			if ((modulus.big_value_len <
1437 			    MIN_RSA_KEYLENGTH_IN_BYTES) ||
1438 			    (modulus.big_value_len >
1439 			    MAX_RSA_KEYLENGTH_IN_BYTES)) {
1440 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
1441 				goto fail_cleanup;
1442 			}
1443 			break;
1444 
1445 		case CKA_PUBLIC_EXPONENT:
1446 			isPubExpo = 1;
1447 			rv = get_bigint_attr_from_template(&pubexpo,
1448 			    &template[i]);
1449 			if (rv != CKR_OK)
1450 				goto fail_cleanup;
1451 			break;
1452 
1453 		case CKA_PRIME:
1454 			isPrime = 1;
1455 			rv = get_bigint_attr_from_template(&prime,
1456 			    &template[i]);
1457 			if (rv != CKR_OK)
1458 				goto fail_cleanup;
1459 			break;
1460 
1461 		case CKA_SUBPRIME:
1462 			isSubprime = 1;
1463 			rv = get_bigint_attr_from_template(&subprime,
1464 			    &template[i]);
1465 			if (rv != CKR_OK)
1466 				goto fail_cleanup;
1467 			break;
1468 
1469 		case CKA_BASE:
1470 			isBase = 1;
1471 			rv = get_bigint_attr_from_template(&base,
1472 			    &template[i]);
1473 			if (rv != CKR_OK)
1474 				goto fail_cleanup;
1475 			break;
1476 
1477 		case CKA_VALUE:
1478 			isValue = 1;
1479 			if (mode == SOFT_CREATE_OBJ) {
1480 				if ((template[i].ulValueLen == 0) ||
1481 				    (template[i].pValue == NULL)) {
1482 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
1483 					goto fail_cleanup;
1484 				}
1485 			}
1486 
1487 			rv = get_bigint_attr_from_template(&value,
1488 			    &template[i]);
1489 			if (rv != CKR_OK)
1490 				goto fail_cleanup;
1491 			break;
1492 
1493 		case CKA_MODULUS_BITS:
1494 			isModulusBits = 1;
1495 			rv = get_ulong_attr_from_template(&modulus_bits,
1496 			    &template[i]);
1497 			if (rv != CKR_OK)
1498 				goto fail_cleanup;
1499 			break;
1500 
1501 		case CKA_LABEL:
1502 			isLabel = 1;
1503 			rv = get_string_from_template(&string_tmp,
1504 			    &template[i]);
1505 			if (rv != CKR_OK)
1506 				goto fail_cleanup;
1507 			break;
1508 
1509 		case CKA_EC_PARAMS:
1510 			isECParam = 1;
1511 			rv = get_string_from_template(&param_tmp, &template[i]);
1512 			if (rv != CKR_OK)
1513 				goto fail_cleanup;
1514 			break;
1515 
1516 		case CKA_EC_POINT:
1517 			isECPoint = 1;
1518 			rv = get_bigint_attr_from_template(&point,
1519 			    &template[i]);
1520 			if (rv != CKR_OK)
1521 				goto fail_cleanup;
1522 			break;
1523 
1524 		default:
1525 			rv = soft_parse_common_attrs(&template[i],
1526 			    &object_type);
1527 			if (rv != CKR_OK)
1528 				goto fail_cleanup;
1529 			break;
1530 		}
1531 	} /* For */
1532 
1533 	/* Allocate storage for Public Key Object. */
1534 	pbk = calloc(1, sizeof (public_key_obj_t));
1535 	if (pbk == NULL) {
1536 		rv = CKR_HOST_MEMORY;
1537 		goto fail_cleanup;
1538 	}
1539 
1540 	new_object->object_class_u.public_key = pbk;
1541 	new_object->class = CKO_PUBLIC_KEY;
1542 
1543 	if ((mode == SOFT_CREATE_OBJ) && (keytype == (CK_KEY_TYPE)~0UL)) {
1544 		rv = CKR_TEMPLATE_INCOMPLETE;
1545 		goto fail_cleanup;
1546 	}
1547 
1548 	if ((mode == SOFT_GEN_KEY) && (keytype == (CK_KEY_TYPE)~0UL)) {
1549 		keytype = key_type;
1550 	}
1551 
1552 	if ((mode == SOFT_GEN_KEY) && (keytype != key_type)) {
1553 		/*
1554 		 * The key type specified in the template does not
1555 		 * match the implied key type based on the mechanism.
1556 		 */
1557 		rv = CKR_TEMPLATE_INCONSISTENT;
1558 		goto fail_cleanup;
1559 	}
1560 
1561 	new_object->key_type = keytype;
1562 
1563 	/* Supported key types of the Public Key Object */
1564 	switch (keytype) {
1565 
1566 	case CKK_RSA:
1567 		if (mode == SOFT_CREATE_OBJ) {
1568 			if (isModulusBits || isPrime || isSubprime ||
1569 			    isBase || isValue) {
1570 				rv = CKR_TEMPLATE_INCONSISTENT;
1571 				goto fail_cleanup;
1572 			}
1573 
1574 			if (isModulus && isPubExpo) {
1575 				/*
1576 				 * Copy big integer attribute value to the
1577 				 * designated place in the public key object.
1578 				 */
1579 				copy_bigint_attr(&modulus,
1580 				    KEY_PUB_RSA_MOD(pbk));
1581 
1582 				copy_bigint_attr(&pubexpo,
1583 				    KEY_PUB_RSA_PUBEXPO(pbk));
1584 			} else {
1585 				rv = CKR_TEMPLATE_INCOMPLETE;
1586 				goto fail_cleanup;
1587 			}
1588 
1589 			/*
1590 			 * Derive modulus_bits attribute from modulus.
1591 			 * Copy big integer attribute value to the
1592 			 * designated place in the public key object.
1593 			 */
1594 			n.malloced = 0;
1595 #ifdef  __sparcv9
1596 			if (big_init(&n,
1597 			    (int)CHARLEN2BIGNUMLEN(modulus.big_value_len))
1598 			    != BIG_OK) {
1599 #else   /* !__sparcv9 */
1600 			if (big_init(&n,
1601 			    CHARLEN2BIGNUMLEN(modulus.big_value_len))
1602 			    != BIG_OK) {
1603 #endif  /* __sparcv9 */
1604 				rv = CKR_HOST_MEMORY;
1605 				big_finish(&n);
1606 				goto fail_cleanup;
1607 			}
1608 			bytestring2bignum(&n, modulus.big_value,
1609 			    modulus.big_value_len);
1610 
1611 			modulus_bits = big_bitlength(&n);
1612 			KEY_PUB_RSA_MOD_BITS(pbk) = modulus_bits;
1613 
1614 			big_finish(&n);
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 			break;
4573 		case CKA_TRUSTED:
4574 			return (get_bool_attr_from_object(object_p,
4575 			    TRUSTED_BOOL_ON, template));
4576 		case CKA_ID:
4577 		case CKA_ISSUER:
4578 		case CKA_SERIAL_NUMBER:
4579 		case CKA_AC_ISSUER:
4580 		case CKA_ATTR_TYPES:
4581 			return (get_extra_attr_from_object(object_p,
4582 			    template));
4583 			break;
4584 		default:
4585 			return (soft_get_common_attrs(object_p, template,
4586 			    object_p->object_type));
4587 			break;
4588 	}
4589 
4590 	/*
4591 	 * If we got this far, then the combination of certificate type
4592 	 * and requested attribute is invalid.
4593 	 */
4594 	return (CKR_ATTRIBUTE_TYPE_INVALID);
4595 }
4596 
4597 CK_RV
4598 soft_set_certificate_attribute(soft_object_t *object_p,
4599 	CK_ATTRIBUTE_PTR template, boolean_t copy)
4600 {
4601 	CK_CERTIFICATE_TYPE certtype = object_p->cert_type;
4602 
4603 	switch (template->type) {
4604 		case CKA_SUBJECT:
4605 			if (certtype == CKC_X_509) {
4606 				/* SUBJECT attr cannot be modified. */
4607 				return (CKR_ATTRIBUTE_READ_ONLY);
4608 			}
4609 			break;
4610 		case CKA_OWNER:
4611 			if (certtype == CKC_X_509_ATTR_CERT) {
4612 				/* OWNER attr cannot be modified. */
4613 				return (CKR_ATTRIBUTE_READ_ONLY);
4614 			}
4615 			break;
4616 		case CKA_VALUE:
4617 			/* VALUE attr cannot be modified. */
4618 			return (CKR_ATTRIBUTE_READ_ONLY);
4619 			break;
4620 		case CKA_ID:
4621 		case CKA_ISSUER:
4622 			if (certtype == CKC_X_509) {
4623 				return (set_extra_attr_to_object(object_p,
4624 				    template->type, template));
4625 			}
4626 			break;
4627 		case CKA_AC_ISSUER:
4628 		case CKA_ATTR_TYPES:
4629 			if (certtype == CKC_X_509_ATTR_CERT) {
4630 				return (set_extra_attr_to_object(object_p,
4631 				    template->type, template));
4632 			}
4633 			break;
4634 		case CKA_SERIAL_NUMBER:
4635 		case CKA_LABEL:
4636 			return (set_extra_attr_to_object(object_p,
4637 			    template->type, template));
4638 			break;
4639 		default:
4640 			return (soft_set_common_storage_attribute(
4641 			    object_p, template, copy));
4642 			break;
4643 	}
4644 
4645 	/*
4646 	 * If we got this far, then the combination of certificate type
4647 	 * and requested attribute is invalid.
4648 	 */
4649 	return (CKR_ATTRIBUTE_TYPE_INVALID);
4650 }
4651 
4652 /*
4653  * Call the appropriate get attribute function according to the class
4654  * of object.
4655  *
4656  * The caller of this function holds the lock on the object.
4657  */
4658 CK_RV
4659 soft_get_attribute(soft_object_t *object_p, CK_ATTRIBUTE_PTR template)
4660 {
4661 
4662 	CK_RV		rv = CKR_OK;
4663 	CK_OBJECT_CLASS class = object_p->class;
4664 
4665 	switch (class) {
4666 	case CKO_PUBLIC_KEY:
4667 		rv = soft_get_public_key_attribute(object_p, template);
4668 		break;
4669 
4670 	case CKO_PRIVATE_KEY:
4671 		rv = soft_get_private_key_attribute(object_p, template);
4672 		break;
4673 
4674 	case CKO_SECRET_KEY:
4675 		rv = soft_get_secret_key_attribute(object_p, template);
4676 		break;
4677 
4678 	case CKO_DOMAIN_PARAMETERS:
4679 		rv = soft_get_domain_parameters_attribute(object_p, template);
4680 		break;
4681 
4682 	case CKO_CERTIFICATE:
4683 		rv = soft_get_certificate_attribute(object_p, template);
4684 		break;
4685 
4686 	default:
4687 		/*
4688 		 * If the specified attribute for the object is invalid
4689 		 * (the object does not possess such as attribute), then
4690 		 * the ulValueLen is modified to hold the value -1.
4691 		 */
4692 		template->ulValueLen = (CK_ULONG)-1;
4693 		return (CKR_ATTRIBUTE_TYPE_INVALID);
4694 	}
4695 
4696 	return (rv);
4697 
4698 }
4699 
4700 CK_RV
4701 soft_set_common_storage_attribute(soft_object_t *object_p,
4702 	CK_ATTRIBUTE_PTR template, boolean_t copy)
4703 {
4704 
4705 	CK_RV rv = CKR_OK;
4706 
4707 	switch (template->type) {
4708 
4709 	case CKA_TOKEN:
4710 		if (copy) {
4711 			if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
4712 				if (!soft_keystore_status(KEYSTORE_INITIALIZED))
4713 					return (CKR_DEVICE_REMOVED);
4714 				object_p->object_type |= TOKEN_OBJECT;
4715 			}
4716 		} else {
4717 			rv = CKR_ATTRIBUTE_READ_ONLY;
4718 		}
4719 
4720 		break;
4721 
4722 	case CKA_PRIVATE:
4723 		if (copy) {
4724 			if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
4725 				(void) pthread_mutex_lock(&soft_giant_mutex);
4726 				if (!soft_slot.authenticated) {
4727 					/*
4728 					 * Check if this is the special case
4729 					 * when the PIN is never initialized
4730 					 * in the keystore. If true, we will
4731 					 * let it pass here and let it fail
4732 					 * with CKR_PIN_EXPIRED later on.
4733 					 */
4734 					if (!soft_slot.userpin_change_needed) {
4735 						(void) pthread_mutex_unlock(
4736 						    &soft_giant_mutex);
4737 						return (CKR_USER_NOT_LOGGED_IN);
4738 					}
4739 				}
4740 				(void) pthread_mutex_unlock(&soft_giant_mutex);
4741 				object_p->object_type |= PRIVATE_OBJECT;
4742 			}
4743 		} else {
4744 			rv = CKR_ATTRIBUTE_READ_ONLY;
4745 		}
4746 		break;
4747 
4748 	case CKA_MODIFIABLE:
4749 		if (copy) {
4750 			if ((*(CK_BBOOL *)template->pValue) == TRUE)
4751 				object_p->bool_attr_mask &=
4752 				    ~NOT_MODIFIABLE_BOOL_ON;
4753 			else
4754 				object_p->bool_attr_mask |=
4755 				    NOT_MODIFIABLE_BOOL_ON;
4756 		} else {
4757 			rv = CKR_ATTRIBUTE_READ_ONLY;
4758 		}
4759 		break;
4760 
4761 	case CKA_CLASS:
4762 		rv = CKR_ATTRIBUTE_READ_ONLY;
4763 		break;
4764 
4765 	default:
4766 		rv = CKR_TEMPLATE_INCONSISTENT;
4767 	}
4768 
4769 	return (rv);
4770 }
4771 
4772 /*
4773  * Set the value of an attribute that is common to all key objects
4774  * (i.e. public key, private key and secret key).
4775  */
4776 CK_RV
4777 soft_set_common_key_attribute(soft_object_t *object_p,
4778 	CK_ATTRIBUTE_PTR template, boolean_t copy)
4779 {
4780 
4781 	switch (template->type) {
4782 
4783 	case CKA_LABEL:
4784 		/*
4785 		 * Only the LABEL can be modified in the common storage
4786 		 * object attributes after the object is created.
4787 		 */
4788 		return (set_extra_attr_to_object(object_p,
4789 		    CKA_LABEL, template));
4790 
4791 	case CKA_ID:
4792 		return (set_extra_attr_to_object(object_p,
4793 		    CKA_ID, template));
4794 
4795 	case CKA_START_DATE:
4796 		return (set_extra_attr_to_object(object_p,
4797 		    CKA_START_DATE, template));
4798 
4799 	case CKA_END_DATE:
4800 		return (set_extra_attr_to_object(object_p,
4801 		    CKA_END_DATE, template));
4802 
4803 	case CKA_DERIVE:
4804 		return (set_bool_attr_to_object(object_p,
4805 		    DERIVE_BOOL_ON, template));
4806 
4807 	case CKA_KEY_TYPE:
4808 	case CKA_LOCAL:
4809 	case CKA_KEY_GEN_MECHANISM:
4810 		return (CKR_ATTRIBUTE_READ_ONLY);
4811 
4812 	default:
4813 		return (soft_set_common_storage_attribute(object_p,
4814 		    template, copy));
4815 
4816 	}
4817 
4818 }
4819 
4820 
4821 /*
4822  * Set the value of an attribute of a Public Key Object.
4823  *
4824  * Rule: The attributes marked with footnote number "8" in the PKCS11
4825  *       spec may be modified (p.88 in PKCS11 spec.).
4826  */
4827 CK_RV
4828 soft_set_public_key_attribute(soft_object_t *object_p,
4829 	CK_ATTRIBUTE_PTR template, boolean_t copy)
4830 {
4831 	CK_KEY_TYPE	keytype = object_p->key_type;
4832 
4833 	switch (template->type) {
4834 
4835 	case CKA_SUBJECT:
4836 		return (set_extra_attr_to_object(object_p,
4837 		    CKA_SUBJECT, template));
4838 
4839 	case CKA_ENCRYPT:
4840 		return (set_bool_attr_to_object(object_p,
4841 		    ENCRYPT_BOOL_ON, template));
4842 
4843 	case CKA_VERIFY:
4844 		return (set_bool_attr_to_object(object_p,
4845 		    VERIFY_BOOL_ON, template));
4846 
4847 	case CKA_VERIFY_RECOVER:
4848 		return (set_bool_attr_to_object(object_p,
4849 		    VERIFY_RECOVER_BOOL_ON, template));
4850 
4851 	case CKA_WRAP:
4852 		return (set_bool_attr_to_object(object_p,
4853 		    WRAP_BOOL_ON, template));
4854 
4855 	case CKA_MODULUS:
4856 	case CKA_MODULUS_BITS:
4857 	case CKA_PUBLIC_EXPONENT:
4858 		if (keytype == CKK_RSA)
4859 			return (CKR_ATTRIBUTE_READ_ONLY);
4860 		break;
4861 
4862 	case CKA_SUBPRIME:
4863 		if ((keytype == CKK_DSA) ||
4864 		    (keytype == CKK_X9_42_DH))
4865 			return (CKR_ATTRIBUTE_READ_ONLY);
4866 		break;
4867 
4868 	case CKA_PRIME:
4869 	case CKA_BASE:
4870 	case CKA_VALUE:
4871 		if ((keytype == CKK_DSA) ||
4872 		    (keytype == CKK_DH) ||
4873 		    (keytype == CKK_X9_42_DH))
4874 			return (CKR_ATTRIBUTE_READ_ONLY);
4875 		break;
4876 
4877 	default:
4878 		/*
4879 		 * Set the value of a common key attribute.
4880 		 */
4881 		return (soft_set_common_key_attribute(object_p,
4882 		    template, copy));
4883 
4884 	}
4885 	/*
4886 	 * If we got this far, then the combination of key type
4887 	 * and requested attribute is invalid.
4888 	 */
4889 	return (CKR_ATTRIBUTE_TYPE_INVALID);
4890 }
4891 
4892 
4893 /*
4894  * Set the value of an attribute of a Private Key Object.
4895  *
4896  * Rule: The attributes marked with footnote number "8" in the PKCS11
4897  *       spec may be modified (p.88 in PKCS11 spec.).
4898  */
4899 CK_RV
4900 soft_set_private_key_attribute(soft_object_t *object_p,
4901 	CK_ATTRIBUTE_PTR template, boolean_t copy)
4902 {
4903 	CK_KEY_TYPE	keytype = object_p->key_type;
4904 
4905 	switch (template->type) {
4906 
4907 	case CKA_SUBJECT:
4908 		return (set_extra_attr_to_object(object_p,
4909 		    CKA_SUBJECT, template));
4910 
4911 	case CKA_SENSITIVE:
4912 		/*
4913 		 * Cannot set SENSITIVE to FALSE if it is already ON.
4914 		 */
4915 		if (((*(CK_BBOOL *)template->pValue) == B_FALSE) &&
4916 		    (object_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
4917 			return (CKR_ATTRIBUTE_READ_ONLY);
4918 		}
4919 
4920 		if (*(CK_BBOOL *)template->pValue)
4921 			object_p->bool_attr_mask |= SENSITIVE_BOOL_ON;
4922 		return (CKR_OK);
4923 
4924 	case CKA_DECRYPT:
4925 		return (set_bool_attr_to_object(object_p,
4926 		    DECRYPT_BOOL_ON, template));
4927 
4928 	case CKA_SIGN:
4929 		return (set_bool_attr_to_object(object_p,
4930 		    SIGN_BOOL_ON, template));
4931 
4932 	case CKA_SIGN_RECOVER:
4933 		return (set_bool_attr_to_object(object_p,
4934 		    SIGN_RECOVER_BOOL_ON, template));
4935 
4936 	case CKA_UNWRAP:
4937 		return (set_bool_attr_to_object(object_p,
4938 		    UNWRAP_BOOL_ON, template));
4939 
4940 	case CKA_EXTRACTABLE:
4941 		/*
4942 		 * Cannot set EXTRACTABLE to TRUE if it is already OFF.
4943 		 */
4944 		if ((*(CK_BBOOL *)template->pValue) &&
4945 		    !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
4946 			return (CKR_ATTRIBUTE_READ_ONLY);
4947 		}
4948 
4949 		if ((*(CK_BBOOL *)template->pValue) == B_FALSE)
4950 			object_p->bool_attr_mask &= ~EXTRACTABLE_BOOL_ON;
4951 		return (CKR_OK);
4952 
4953 	case CKA_MODULUS:
4954 	case CKA_PUBLIC_EXPONENT:
4955 	case CKA_PRIVATE_EXPONENT:
4956 	case CKA_PRIME_1:
4957 	case CKA_PRIME_2:
4958 	case CKA_EXPONENT_1:
4959 	case CKA_EXPONENT_2:
4960 	case CKA_COEFFICIENT:
4961 		if (keytype == CKK_RSA) {
4962 			return (CKR_ATTRIBUTE_READ_ONLY);
4963 		}
4964 		break;
4965 
4966 	case CKA_SUBPRIME:
4967 		if ((keytype == CKK_DSA) ||
4968 		    (keytype == CKK_X9_42_DH))
4969 			return (CKR_ATTRIBUTE_READ_ONLY);
4970 		break;
4971 
4972 	case CKA_PRIME:
4973 	case CKA_BASE:
4974 	case CKA_VALUE:
4975 		if ((keytype == CKK_DSA) ||
4976 		    (keytype == CKK_DH) ||
4977 		    (keytype == CKK_X9_42_DH))
4978 			return (CKR_ATTRIBUTE_READ_ONLY);
4979 		break;
4980 
4981 	case CKA_VALUE_BITS:
4982 		if (keytype == CKK_DH)
4983 			return (CKR_ATTRIBUTE_READ_ONLY);
4984 		break;
4985 
4986 	default:
4987 		/*
4988 		 * Set the value of a common key attribute.
4989 		 */
4990 		return (soft_set_common_key_attribute(object_p,
4991 		    template, copy));
4992 	}
4993 
4994 	/*
4995 	 * If we got this far, then the combination of key type
4996 	 * and requested attribute is invalid.
4997 	 */
4998 	return (CKR_ATTRIBUTE_TYPE_INVALID);
4999 }
5000 
5001 /*
5002  * Set the value of an attribute of a Secret Key Object.
5003  *
5004  * Rule: The attributes marked with footnote number "8" in the PKCS11
5005  *       spec may be modified (p.88 in PKCS11 spec.).
5006  */
5007 CK_RV
5008 soft_set_secret_key_attribute(soft_object_t *object_p,
5009 	CK_ATTRIBUTE_PTR template, boolean_t copy)
5010 {
5011 	CK_KEY_TYPE	keytype = object_p->key_type;
5012 
5013 	switch (template->type) {
5014 
5015 	case CKA_SENSITIVE:
5016 		/*
5017 		 * Cannot set SENSITIVE to FALSE if it is already ON.
5018 		 */
5019 		if (((*(CK_BBOOL *)template->pValue) == B_FALSE) &&
5020 		    (object_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
5021 			return (CKR_ATTRIBUTE_READ_ONLY);
5022 		}
5023 
5024 		if (*(CK_BBOOL *)template->pValue)
5025 			object_p->bool_attr_mask |= SENSITIVE_BOOL_ON;
5026 		return (CKR_OK);
5027 
5028 	case CKA_ENCRYPT:
5029 		return (set_bool_attr_to_object(object_p,
5030 		    ENCRYPT_BOOL_ON, template));
5031 
5032 	case CKA_DECRYPT:
5033 		return (set_bool_attr_to_object(object_p,
5034 		    DECRYPT_BOOL_ON, template));
5035 
5036 	case CKA_SIGN:
5037 		return (set_bool_attr_to_object(object_p,
5038 		    SIGN_BOOL_ON, template));
5039 
5040 	case CKA_VERIFY:
5041 		return (set_bool_attr_to_object(object_p,
5042 		    VERIFY_BOOL_ON, template));
5043 
5044 	case CKA_WRAP:
5045 		return (set_bool_attr_to_object(object_p,
5046 		    WRAP_BOOL_ON, template));
5047 
5048 	case CKA_UNWRAP:
5049 		return (set_bool_attr_to_object(object_p,
5050 		    UNWRAP_BOOL_ON, template));
5051 
5052 	case CKA_EXTRACTABLE:
5053 		/*
5054 		 * Cannot set EXTRACTABLE to TRUE if it is already OFF.
5055 		 */
5056 		if ((*(CK_BBOOL *)template->pValue) &&
5057 		    !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
5058 			return (CKR_ATTRIBUTE_READ_ONLY);
5059 		}
5060 
5061 		if ((*(CK_BBOOL *)template->pValue) == B_FALSE)
5062 			object_p->bool_attr_mask &= ~EXTRACTABLE_BOOL_ON;
5063 		return (CKR_OK);
5064 
5065 	case CKA_VALUE:
5066 		return (CKR_ATTRIBUTE_READ_ONLY);
5067 
5068 	case CKA_VALUE_LEN:
5069 		if ((keytype == CKK_RC4) ||
5070 		    (keytype == CKK_GENERIC_SECRET) ||
5071 		    (keytype == CKK_AES) ||
5072 		    (keytype == CKK_BLOWFISH))
5073 			return (CKR_ATTRIBUTE_READ_ONLY);
5074 		break;
5075 
5076 	default:
5077 		/*
5078 		 * Set the value of a common key attribute.
5079 		 */
5080 		return (soft_set_common_key_attribute(object_p,
5081 		    template, copy));
5082 
5083 	}
5084 	/*
5085 	 * If we got this far, then the combination of key type
5086 	 * and requested attribute is invalid.
5087 	 */
5088 	return (CKR_ATTRIBUTE_TYPE_INVALID);
5089 }
5090 
5091 
5092 /*
5093  * Call the appropriate set attribute function according to the class
5094  * of object.
5095  *
5096  * The caller of this function does not hold the lock on the original
5097  * object, since this function is setting the attribute on the new object
5098  * that is being modified.
5099  *
5100  * Argument copy: TRUE when called by C_CopyObject,
5101  *		  FALSE when called by C_SetAttributeValue.
5102  */
5103 CK_RV
5104 soft_set_attribute(soft_object_t *object_p, CK_ATTRIBUTE_PTR template,
5105     boolean_t copy)
5106 {
5107 
5108 	CK_RV		rv = CKR_OK;
5109 	CK_OBJECT_CLASS	class = object_p->class;
5110 
5111 	switch (class) {
5112 
5113 	case CKO_PUBLIC_KEY:
5114 		rv = soft_set_public_key_attribute(object_p, template, copy);
5115 		break;
5116 
5117 	case CKO_PRIVATE_KEY:
5118 		rv = soft_set_private_key_attribute(object_p, template, copy);
5119 		break;
5120 
5121 	case CKO_SECRET_KEY:
5122 		rv = soft_set_secret_key_attribute(object_p, template, copy);
5123 		break;
5124 
5125 	case CKO_DOMAIN_PARAMETERS:
5126 		switch (template->type) {
5127 		case CKA_LABEL:
5128 			/*
5129 			 * Only the LABEL can be modified in the common
5130 			 * storage object attributes after the object is
5131 			 * created.
5132 			 */
5133 			return (set_extra_attr_to_object(object_p,
5134 			    CKA_LABEL, template));
5135 		default:
5136 			return (CKR_TEMPLATE_INCONSISTENT);
5137 		}
5138 	case CKO_CERTIFICATE:
5139 		rv = soft_set_certificate_attribute(object_p, template, copy);
5140 		break;
5141 
5142 	default:
5143 		/*
5144 		 * If the template specifies a value of an attribute
5145 		 * which is incompatible with other existing attributes
5146 		 * of the object, then fails with return code
5147 		 * CKR_TEMPLATE_INCONSISTENT.
5148 		 */
5149 		rv = CKR_TEMPLATE_INCONSISTENT;
5150 		break;
5151 	}
5152 
5153 	return (rv);
5154 }
5155 
5156 CK_RV
5157 soft_get_public_value(soft_object_t *key, CK_ATTRIBUTE_TYPE type,
5158     uchar_t *value, uint32_t *value_len)
5159 {
5160 	uint32_t len = 0;
5161 	switch (type) {
5162 
5163 	/* The following attributes belong to RSA */
5164 	case CKA_MODULUS:
5165 #ifdef	__sparcv9
5166 		len =
5167 		    /* LINTED */
5168 		    (uint32_t)
5169 		    ((biginteger_t *)OBJ_PUB_RSA_MOD(key))->big_value_len;
5170 #else	/* !__sparcv9 */
5171 		len =
5172 		    ((biginteger_t *)OBJ_PUB_RSA_MOD(key))->big_value_len;
5173 #endif	/* __sparcv9 */
5174 
5175 		/* This attribute MUST BE set */
5176 		if (len == 0 || len > *value_len) {
5177 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5178 		}
5179 		*value_len = len;
5180 
5181 		(void) memcpy(value,
5182 		    ((biginteger_t *)OBJ_PUB_RSA_MOD(key))->big_value,
5183 		    *value_len);
5184 
5185 		break;
5186 
5187 	case CKA_PUBLIC_EXPONENT:
5188 #ifdef	__sparcv9
5189 		len =
5190 		    /* LINTED */
5191 		    (uint32_t)
5192 		    ((biginteger_t *)OBJ_PUB_RSA_PUBEXPO(key))->big_value_len;
5193 #else	/* !__sparcv9 */
5194 		len =
5195 		    ((biginteger_t *)OBJ_PUB_RSA_PUBEXPO(key))->big_value_len;
5196 #endif	/* __sparcv9 */
5197 
5198 		/* This attribute MUST BE set */
5199 		if (len == 0 || len > *value_len) {
5200 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5201 		}
5202 		*value_len = len;
5203 
5204 		(void) memcpy(value,
5205 		    ((biginteger_t *)OBJ_PUB_RSA_PUBEXPO(key))->big_value,
5206 		    *value_len);
5207 
5208 		break;
5209 
5210 	/* The following attributes belong to DSA and DH */
5211 	case CKA_PRIME:
5212 
5213 		if (key->key_type == CKK_DSA)
5214 #ifdef	__sparcv9
5215 			len =
5216 			    /* LINTED */
5217 			    (uint32_t)
5218 			    ((biginteger_t *)OBJ_PUB_DSA_PRIME(key))->
5219 			    big_value_len;
5220 #else	/* !__sparcv9 */
5221 			len =
5222 			    ((biginteger_t *)OBJ_PUB_DSA_PRIME(key))->
5223 			    big_value_len;
5224 #endif	/* __sparcv9 */
5225 		else
5226 #ifdef	__sparcv9
5227 			len =
5228 			    /* LINTED */
5229 			    (uint32_t)
5230 			    ((biginteger_t *)OBJ_PUB_DH_PRIME(key))->
5231 			    big_value_len;
5232 #else	/* !__sparcv9 */
5233 			len =
5234 			    ((biginteger_t *)OBJ_PUB_DH_PRIME(key))->
5235 			    big_value_len;
5236 #endif	/* __sparcv9 */
5237 
5238 		/* This attribute MUST BE set */
5239 		if (len == 0 || len > *value_len) {
5240 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5241 		}
5242 		*value_len = len;
5243 
5244 		if (key->key_type == CKK_DSA)
5245 			(void) memcpy(value,
5246 			    ((biginteger_t *)OBJ_PUB_DSA_PRIME(key))->big_value,
5247 			    *value_len);
5248 		else
5249 			(void) memcpy(value,
5250 			    ((biginteger_t *)OBJ_PUB_DH_PRIME(key))->big_value,
5251 			    *value_len);
5252 
5253 		break;
5254 
5255 	case CKA_SUBPRIME:
5256 #ifdef	__sparcv9
5257 		len =
5258 		    /* LINTED */
5259 		    (uint32_t)
5260 		    ((biginteger_t *)OBJ_PUB_DSA_SUBPRIME(key))->big_value_len;
5261 #else	/* !__sparcv9 */
5262 		len =
5263 		    ((biginteger_t *)OBJ_PUB_DSA_SUBPRIME(key))->big_value_len;
5264 #endif	/* __sparcv9 */
5265 
5266 		/* This attribute MUST BE set */
5267 		if (len == 0 || len > *value_len) {
5268 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5269 		}
5270 		*value_len = len;
5271 
5272 		(void) memcpy(value,
5273 		    ((biginteger_t *)OBJ_PUB_DSA_SUBPRIME(key))->big_value,
5274 		    *value_len);
5275 
5276 		break;
5277 
5278 	case CKA_BASE:
5279 
5280 		if (key->key_type == CKK_DSA)
5281 #ifdef	__sparcv9
5282 			len =
5283 			    /* LINTED */
5284 			    (uint32_t)
5285 			    ((biginteger_t *)OBJ_PUB_DSA_BASE(key))->
5286 			    big_value_len;
5287 #else	/* !__sparcv9 */
5288 			len =
5289 			    ((biginteger_t *)OBJ_PUB_DSA_BASE(key))->
5290 			    big_value_len;
5291 #endif	/* __sparcv9 */
5292 		else
5293 #ifdef	__sparcv9
5294 			len =
5295 			    /* LINTED */
5296 			    (uint32_t)
5297 			    ((biginteger_t *)OBJ_PUB_DH_BASE(key))->
5298 			    big_value_len;
5299 #else	/* !__sparcv9 */
5300 			len =
5301 			    ((biginteger_t *)OBJ_PUB_DH_BASE(key))->
5302 			    big_value_len;
5303 #endif	/* __sparcv9 */
5304 
5305 		/* This attribute MUST BE set */
5306 		if (len == 0 || len > *value_len) {
5307 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5308 		}
5309 		*value_len = len;
5310 
5311 		if (key->key_type == CKK_DSA)
5312 			(void) memcpy(value,
5313 			    ((biginteger_t *)OBJ_PUB_DSA_BASE(key))->big_value,
5314 			    *value_len);
5315 		else
5316 			(void) memcpy(value,
5317 			    ((biginteger_t *)OBJ_PUB_DH_BASE(key))->big_value,
5318 			    *value_len);
5319 		break;
5320 
5321 	case CKA_VALUE:
5322 
5323 		if (key->key_type == CKK_DSA)
5324 #ifdef	__sparcv9
5325 			len =
5326 			    /* LINTED */
5327 			    (uint32_t)
5328 			    ((biginteger_t *)OBJ_PUB_DSA_VALUE(key))->
5329 			    big_value_len;
5330 #else	/* !__sparcv9 */
5331 			len =
5332 			    ((biginteger_t *)OBJ_PUB_DSA_VALUE(key))->
5333 			    big_value_len;
5334 #endif	/* __sparcv9 */
5335 		else
5336 #ifdef	__sparcv9
5337 			len =
5338 			    /* LINTED */
5339 			    (uint32_t)
5340 			    ((biginteger_t *)OBJ_PUB_DH_VALUE(key))->
5341 			    big_value_len;
5342 #else	/* !__sparcv9 */
5343 			len =
5344 			    ((biginteger_t *)OBJ_PUB_DH_VALUE(key))->
5345 			    big_value_len;
5346 #endif	/* __sparcv9 */
5347 
5348 		/* This attribute MUST BE set */
5349 		if (len == 0 || len > *value_len) {
5350 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5351 		}
5352 		*value_len = len;
5353 
5354 		if (key->key_type == CKK_DSA)
5355 			(void) memcpy(value,
5356 			    ((biginteger_t *)OBJ_PUB_DSA_VALUE(key))->big_value,
5357 			    *value_len);
5358 		else
5359 			(void) memcpy(value,
5360 			    ((biginteger_t *)OBJ_PUB_DH_VALUE(key))->big_value,
5361 			    *value_len);
5362 
5363 		break;
5364 	}
5365 
5366 	return (CKR_OK);
5367 }
5368 
5369 
5370 CK_RV
5371 soft_get_private_value(soft_object_t *key, CK_ATTRIBUTE_TYPE type,
5372     uchar_t *value, uint32_t *value_len)
5373 {
5374 
5375 	uint32_t len = 0;
5376 
5377 	switch (type) {
5378 
5379 	/* The following attributes belong to RSA */
5380 	case CKA_MODULUS:
5381 #ifdef	__sparcv9
5382 		len =
5383 		    /* LINTED */
5384 		    (uint32_t)
5385 		    ((biginteger_t *)OBJ_PRI_RSA_MOD(key))->big_value_len;
5386 #else	/* !__sparcv9 */
5387 		len =
5388 		    ((biginteger_t *)OBJ_PRI_RSA_MOD(key))->big_value_len;
5389 #endif	/* __sparcv9 */
5390 
5391 		/* This attribute MUST BE set */
5392 		if (len == 0 || len > *value_len) {
5393 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5394 		}
5395 		*value_len = len;
5396 
5397 		(void) memcpy(value,
5398 		    ((biginteger_t *)OBJ_PRI_RSA_MOD(key))->big_value,
5399 		    *value_len);
5400 
5401 		break;
5402 
5403 	case CKA_PRIVATE_EXPONENT:
5404 #ifdef	__sparcv9
5405 		len =
5406 		    /* LINTED */
5407 		    (uint32_t)
5408 		    ((biginteger_t *)OBJ_PRI_RSA_PRIEXPO(key))->big_value_len;
5409 #else	/* !__sparcv9 */
5410 		len =
5411 		    ((biginteger_t *)OBJ_PRI_RSA_PRIEXPO(key))->big_value_len;
5412 #endif	/* __sparcv9 */
5413 
5414 		/* This attribute MUST BE set */
5415 		if (len == 0 || len > *value_len) {
5416 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5417 		}
5418 		*value_len = len;
5419 
5420 		(void) memcpy(value,
5421 		    ((biginteger_t *)OBJ_PRI_RSA_PRIEXPO(key))->big_value,
5422 		    *value_len);
5423 
5424 		break;
5425 
5426 	case CKA_PRIME_1:
5427 #ifdef	__sparcv9
5428 		len =
5429 		    /* LINTED */
5430 		    (uint32_t)
5431 		    ((biginteger_t *)OBJ_PRI_RSA_PRIME1(key))->big_value_len;
5432 #else	/* !__sparcv9 */
5433 		len =
5434 		    ((biginteger_t *)OBJ_PRI_RSA_PRIME1(key))->big_value_len;
5435 #endif	/* __sparcv9 */
5436 
5437 		if (len > *value_len) {
5438 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5439 		}
5440 		*value_len = len;
5441 
5442 		if (*value_len == 0) {
5443 			return (CKR_OK);
5444 		}
5445 
5446 		(void) memcpy(value,
5447 		    ((biginteger_t *)OBJ_PRI_RSA_PRIME1(key))->big_value,
5448 		    *value_len);
5449 
5450 		break;
5451 
5452 	case CKA_PRIME_2:
5453 #ifdef	__sparcv9
5454 		len =
5455 		    /* LINTED */
5456 		    (uint32_t)
5457 		    ((biginteger_t *)OBJ_PRI_RSA_PRIME2(key))->big_value_len;
5458 #else	/* !__sparcv9 */
5459 		len =
5460 		    ((biginteger_t *)OBJ_PRI_RSA_PRIME2(key))->big_value_len;
5461 #endif	/* __sparcv9 */
5462 
5463 		if (len > *value_len) {
5464 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5465 		}
5466 		*value_len = len;
5467 
5468 		if (*value_len == 0) {
5469 			return (CKR_OK);
5470 		}
5471 
5472 		(void) memcpy(value,
5473 		    ((biginteger_t *)OBJ_PRI_RSA_PRIME2(key))->big_value,
5474 		    *value_len);
5475 
5476 		break;
5477 
5478 	case CKA_EXPONENT_1:
5479 #ifdef	__sparcv9
5480 		len =
5481 		    /* LINTED */
5482 		    (uint32_t)
5483 		    ((biginteger_t *)OBJ_PRI_RSA_EXPO1(key))->big_value_len;
5484 #else	/* !__sparcv9 */
5485 		len =
5486 		    ((biginteger_t *)OBJ_PRI_RSA_EXPO1(key))->big_value_len;
5487 #endif	/* __sparcv9 */
5488 
5489 		if (len > *value_len) {
5490 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5491 		}
5492 		*value_len = len;
5493 
5494 		if (*value_len == 0) {
5495 			return (CKR_OK);
5496 		}
5497 
5498 		(void) memcpy(value,
5499 		    ((biginteger_t *)OBJ_PRI_RSA_EXPO1(key))->big_value,
5500 		    *value_len);
5501 
5502 		break;
5503 
5504 	case CKA_EXPONENT_2:
5505 #ifdef	__sparcv9
5506 		len =
5507 		    /* LINTED */
5508 		    (uint32_t)
5509 		    ((biginteger_t *)OBJ_PRI_RSA_EXPO2(key))->big_value_len;
5510 #else	/* !__sparcv9 */
5511 		len =
5512 		    ((biginteger_t *)OBJ_PRI_RSA_EXPO2(key))->big_value_len;
5513 #endif	/* __sparcv9 */
5514 
5515 		if (len > *value_len) {
5516 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5517 		}
5518 		*value_len = len;
5519 
5520 		if (*value_len == 0) {
5521 			return (CKR_OK);
5522 		}
5523 
5524 		(void) memcpy(value,
5525 		    ((biginteger_t *)OBJ_PRI_RSA_EXPO2(key))->big_value,
5526 		    *value_len);
5527 
5528 		break;
5529 
5530 	case CKA_COEFFICIENT:
5531 #ifdef	__sparcv9
5532 		len =
5533 		    /* LINTED */
5534 		    (uint32_t)
5535 		    ((biginteger_t *)OBJ_PRI_RSA_COEF(key))->big_value_len;
5536 #else	/* !__sparcv9 */
5537 		len =
5538 		    ((biginteger_t *)OBJ_PRI_RSA_COEF(key))->big_value_len;
5539 #endif	/* __sparcv9 */
5540 
5541 		if (len > *value_len) {
5542 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5543 		}
5544 		*value_len = len;
5545 
5546 		if (*value_len == 0) {
5547 			return (CKR_OK);
5548 		}
5549 
5550 		(void) memcpy(value,
5551 		    ((biginteger_t *)OBJ_PRI_RSA_COEF(key))->big_value,
5552 		    *value_len);
5553 
5554 		break;
5555 
5556 	/* The following attributes belong to DSA and DH */
5557 	case CKA_PRIME:
5558 
5559 		if (key->key_type == CKK_DSA)
5560 #ifdef	__sparcv9
5561 			len =
5562 			    /* LINTED */
5563 			    (uint32_t)
5564 			    ((biginteger_t *)OBJ_PRI_DSA_PRIME(key))->
5565 			    big_value_len;
5566 #else	/* !__sparcv9 */
5567 			len =
5568 			    ((biginteger_t *)OBJ_PRI_DSA_PRIME(key))->
5569 			    big_value_len;
5570 #endif	/* __sparcv9 */
5571 		else
5572 #ifdef	__sparcv9
5573 			len =
5574 			    /* LINTED */
5575 			    (uint32_t)
5576 			    ((biginteger_t *)OBJ_PRI_DH_PRIME(key))->
5577 			    big_value_len;
5578 #else	/* !__sparcv9 */
5579 			len =
5580 			    ((biginteger_t *)OBJ_PRI_DH_PRIME(key))->
5581 			    big_value_len;
5582 #endif	/* __sparcv9 */
5583 
5584 		/* This attribute MUST BE set */
5585 		if (len == 0 || len > *value_len) {
5586 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5587 		}
5588 		*value_len = len;
5589 
5590 		if (key->key_type == CKK_DSA)
5591 			(void) memcpy(value,
5592 			    ((biginteger_t *)OBJ_PRI_DSA_PRIME(key))->big_value,
5593 			    *value_len);
5594 		else
5595 			(void) memcpy(value,
5596 			    ((biginteger_t *)OBJ_PRI_DH_PRIME(key))->big_value,
5597 			    *value_len);
5598 
5599 		break;
5600 
5601 	case CKA_SUBPRIME:
5602 #ifdef	__sparcv9
5603 		len =
5604 		    /* LINTED */
5605 		    (uint32_t)
5606 		    ((biginteger_t *)OBJ_PRI_DSA_SUBPRIME(key))->big_value_len;
5607 #else	/* !__sparcv9 */
5608 		len =
5609 		    ((biginteger_t *)OBJ_PRI_DSA_SUBPRIME(key))->big_value_len;
5610 #endif	/* __sparcv9 */
5611 
5612 		/* This attribute MUST BE set */
5613 		if (len == 0 || len > *value_len) {
5614 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5615 		}
5616 		*value_len = len;
5617 
5618 		(void) memcpy(value,
5619 		    ((biginteger_t *)OBJ_PRI_DSA_SUBPRIME(key))->big_value,
5620 		    *value_len);
5621 
5622 		break;
5623 
5624 	case CKA_BASE:
5625 
5626 		if (key->key_type == CKK_DSA)
5627 #ifdef	__sparcv9
5628 			len =
5629 			    /* LINTED */
5630 			    (uint32_t)
5631 			    ((biginteger_t *)OBJ_PRI_DSA_BASE(key))->
5632 			    big_value_len;
5633 #else	/* !__sparcv9 */
5634 			len =
5635 			    ((biginteger_t *)OBJ_PRI_DSA_BASE(key))->
5636 			    big_value_len;
5637 #endif	/* __sparcv9 */
5638 		else
5639 #ifdef	__sparcv9
5640 			len =
5641 			    /* LINTED */
5642 			    (uint32_t)
5643 			    ((biginteger_t *)OBJ_PRI_DH_BASE(key))->
5644 			    big_value_len;
5645 #else	/* !__sparcv9 */
5646 			len =
5647 			    ((biginteger_t *)OBJ_PRI_DH_BASE(key))->
5648 			    big_value_len;
5649 #endif	/* __sparcv9 */
5650 
5651 		/* This attribute MUST BE set */
5652 		if (len == 0 || len > *value_len) {
5653 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5654 		}
5655 		*value_len = len;
5656 
5657 		if (key->key_type == CKK_DSA)
5658 			(void) memcpy(value,
5659 			    ((biginteger_t *)OBJ_PRI_DSA_BASE(key))->big_value,
5660 			    *value_len);
5661 		else
5662 			(void) memcpy(value,
5663 			    ((biginteger_t *)OBJ_PRI_DH_BASE(key))->big_value,
5664 			    *value_len);
5665 		break;
5666 
5667 	case CKA_VALUE:
5668 
5669 		if (key->key_type == CKK_DSA) {
5670 #ifdef	__sparcv9
5671 			len =
5672 			    /* LINTED */
5673 			    (uint32_t)
5674 			    ((biginteger_t *)OBJ_PRI_DSA_VALUE(key))->
5675 			    big_value_len;
5676 #else	/* !__sparcv9 */
5677 			len =
5678 			    ((biginteger_t *)OBJ_PRI_DSA_VALUE(key))->
5679 			    big_value_len;
5680 #endif	/* __sparcv9 */
5681 		} else if (key->key_type == CKK_DH) {
5682 #ifdef	__sparcv9
5683 			len =
5684 			    /* LINTED */
5685 			    (uint32_t)
5686 			    ((biginteger_t *)OBJ_PRI_DH_VALUE(key))->
5687 			    big_value_len;
5688 #else	/* !__sparcv9 */
5689 			len =
5690 			    ((biginteger_t *)OBJ_PRI_DH_VALUE(key))->
5691 			    big_value_len;
5692 #endif	/* __sparcv9 */
5693 		} else {
5694 #ifdef	__sparcv9
5695 			len =
5696 			    /* LINTED */
5697 			    (uint32_t)
5698 			    ((biginteger_t *)OBJ_PRI_EC_VALUE(key))->
5699 			    big_value_len;
5700 #else	/* !__sparcv9 */
5701 			len =
5702 			    ((biginteger_t *)OBJ_PRI_EC_VALUE(key))->
5703 			    big_value_len;
5704 #endif	/* __sparcv9 */
5705 		}
5706 
5707 		/* This attribute MUST BE set */
5708 		if (len == 0 || len > *value_len) {
5709 			return (CKR_ATTRIBUTE_VALUE_INVALID);
5710 		}
5711 		*value_len = len;
5712 
5713 		if (key->key_type == CKK_DSA) {
5714 			(void) memcpy(value,
5715 			    ((biginteger_t *)OBJ_PRI_DSA_VALUE(key))->big_value,
5716 			    *value_len);
5717 		} else if (key->key_type == CKK_DH) {
5718 			(void) memcpy(value,
5719 			    ((biginteger_t *)OBJ_PRI_DH_VALUE(key))->big_value,
5720 			    *value_len);
5721 		} else {
5722 			(void) memcpy(value,
5723 			    ((biginteger_t *)OBJ_PRI_EC_VALUE(key))->big_value,
5724 			    *value_len);
5725 		}
5726 
5727 		break;
5728 	}
5729 
5730 	return (CKR_OK);
5731 
5732 }
5733 
5734 static CK_RV
5735 copy_bigint(biginteger_t *new_bigint, biginteger_t *old_bigint)
5736 {
5737 	new_bigint->big_value =
5738 	    malloc((sizeof (CK_BYTE) * new_bigint->big_value_len));
5739 
5740 	if (new_bigint->big_value == NULL) {
5741 		return (CKR_HOST_MEMORY);
5742 	}
5743 
5744 	(void) memcpy(new_bigint->big_value, old_bigint->big_value,
5745 	    (sizeof (CK_BYTE) * new_bigint->big_value_len));
5746 
5747 	return (CKR_OK);
5748 }
5749 
5750 static void
5751 free_public_key_attr(public_key_obj_t *pbk, CK_KEY_TYPE key_type)
5752 {
5753 	if (pbk == NULL) {
5754 		return;
5755 	}
5756 
5757 	switch (key_type) {
5758 		case CKK_RSA:
5759 			bigint_attr_cleanup(KEY_PUB_RSA_MOD(pbk));
5760 			bigint_attr_cleanup(KEY_PUB_RSA_PUBEXPO(pbk));
5761 			break;
5762 		case CKK_DSA:
5763 			bigint_attr_cleanup(KEY_PUB_DSA_PRIME(pbk));
5764 			bigint_attr_cleanup(KEY_PUB_DSA_SUBPRIME(pbk));
5765 			bigint_attr_cleanup(KEY_PUB_DSA_BASE(pbk));
5766 			bigint_attr_cleanup(KEY_PUB_DSA_VALUE(pbk));
5767 			break;
5768 		case CKK_DH:
5769 			bigint_attr_cleanup(KEY_PUB_DH_PRIME(pbk));
5770 			bigint_attr_cleanup(KEY_PUB_DH_BASE(pbk));
5771 			bigint_attr_cleanup(KEY_PUB_DH_VALUE(pbk));
5772 			break;
5773 		case CKK_EC:
5774 			bigint_attr_cleanup(KEY_PUB_EC_POINT(pbk));
5775 			break;
5776 		case CKK_X9_42_DH:
5777 			bigint_attr_cleanup(KEY_PUB_DH942_PRIME(pbk));
5778 			bigint_attr_cleanup(KEY_PUB_DH942_SUBPRIME(pbk));
5779 			bigint_attr_cleanup(KEY_PUB_DH942_BASE(pbk));
5780 			bigint_attr_cleanup(KEY_PUB_DH942_VALUE(pbk));
5781 			break;
5782 		default:
5783 			break;
5784 	}
5785 	free(pbk);
5786 }
5787 
5788 CK_RV
5789 soft_copy_public_key_attr(public_key_obj_t *old_pub_key_obj_p,
5790     public_key_obj_t **new_pub_key_obj_p, CK_KEY_TYPE key_type)
5791 {
5792 
5793 	public_key_obj_t *pbk;
5794 	CK_RV rv = CKR_OK;
5795 
5796 	pbk = calloc(1, sizeof (public_key_obj_t));
5797 	if (pbk == NULL) {
5798 		return (CKR_HOST_MEMORY);
5799 	}
5800 
5801 	switch (key_type) {
5802 		case CKK_RSA:
5803 			(void) memcpy(KEY_PUB_RSA(pbk),
5804 			    KEY_PUB_RSA(old_pub_key_obj_p),
5805 			    sizeof (rsa_pub_key_t));
5806 			/* copy modulus */
5807 			rv = copy_bigint(KEY_PUB_RSA_MOD(pbk),
5808 			    KEY_PUB_RSA_MOD(old_pub_key_obj_p));
5809 			if (rv != CKR_OK) {
5810 				free_public_key_attr(pbk, key_type);
5811 				return (rv);
5812 			}
5813 			/* copy public exponent */
5814 			rv = copy_bigint(KEY_PUB_RSA_PUBEXPO(pbk),
5815 			    KEY_PUB_RSA_PUBEXPO(old_pub_key_obj_p));
5816 			if (rv != CKR_OK) {
5817 				free_public_key_attr(pbk, key_type);
5818 				return (rv);
5819 			}
5820 			break;
5821 		case CKK_DSA:
5822 			(void) memcpy(KEY_PUB_DSA(pbk),
5823 			    KEY_PUB_DSA(old_pub_key_obj_p),
5824 			    sizeof (dsa_pub_key_t));
5825 
5826 			/* copy prime */
5827 			rv = copy_bigint(KEY_PUB_DSA_PRIME(pbk),
5828 			    KEY_PUB_DSA_PRIME(old_pub_key_obj_p));
5829 			if (rv != CKR_OK) {
5830 				free_public_key_attr(pbk, key_type);
5831 				return (rv);
5832 			}
5833 
5834 			/* copy subprime */
5835 			rv = copy_bigint(KEY_PUB_DSA_SUBPRIME(pbk),
5836 			    KEY_PUB_DSA_SUBPRIME(old_pub_key_obj_p));
5837 			if (rv != CKR_OK) {
5838 				free_public_key_attr(pbk, key_type);
5839 				return (rv);
5840 			}
5841 
5842 			/* copy base */
5843 			rv = copy_bigint(KEY_PUB_DSA_BASE(pbk),
5844 			    KEY_PUB_DSA_BASE(old_pub_key_obj_p));
5845 			if (rv != CKR_OK) {
5846 				free_public_key_attr(pbk, key_type);
5847 				return (rv);
5848 			}
5849 
5850 			/* copy value */
5851 			rv = copy_bigint(KEY_PUB_DSA_VALUE(pbk),
5852 			    KEY_PUB_DSA_VALUE(old_pub_key_obj_p));
5853 			if (rv != CKR_OK) {
5854 				free_public_key_attr(pbk, key_type);
5855 				return (rv);
5856 			}
5857 			break;
5858 		case CKK_DH:
5859 			(void) memcpy(KEY_PUB_DH(pbk),
5860 			    KEY_PUB_DH(old_pub_key_obj_p),
5861 			    sizeof (dh_pub_key_t));
5862 
5863 			/* copy prime */
5864 			rv = copy_bigint(KEY_PUB_DH_PRIME(pbk),
5865 			    KEY_PUB_DH_PRIME(old_pub_key_obj_p));
5866 			if (rv != CKR_OK) {
5867 				free_public_key_attr(pbk, key_type);
5868 				return (rv);
5869 			}
5870 
5871 			/* copy base */
5872 			rv = copy_bigint(KEY_PUB_DH_BASE(pbk),
5873 			    KEY_PUB_DH_BASE(old_pub_key_obj_p));
5874 			if (rv != CKR_OK) {
5875 				free_public_key_attr(pbk, key_type);
5876 				return (rv);
5877 			}
5878 
5879 			/* copy value */
5880 			rv = copy_bigint(KEY_PUB_DH_VALUE(pbk),
5881 			    KEY_PUB_DH_VALUE(old_pub_key_obj_p));
5882 			if (rv != CKR_OK) {
5883 				free_public_key_attr(pbk, key_type);
5884 				return (rv);
5885 			}
5886 			break;
5887 		case CKK_EC:
5888 			(void) memcpy(KEY_PUB_EC(pbk),
5889 			    KEY_PUB_EC(old_pub_key_obj_p),
5890 			    sizeof (ec_pub_key_t));
5891 
5892 			/* copy point */
5893 			rv = copy_bigint(KEY_PUB_EC_POINT(pbk),
5894 			    KEY_PUB_EC_POINT(old_pub_key_obj_p));
5895 			if (rv != CKR_OK) {
5896 				free_public_key_attr(pbk, key_type);
5897 				return (rv);
5898 			}
5899 			break;
5900 		case CKK_X9_42_DH:
5901 			(void) memcpy(KEY_PUB_DH942(pbk),
5902 			    KEY_PUB_DH942(old_pub_key_obj_p),
5903 			    sizeof (dh942_pub_key_t));
5904 
5905 			/* copy prime */
5906 			rv = copy_bigint(KEY_PUB_DH942_PRIME(pbk),
5907 			    KEY_PUB_DH942_PRIME(old_pub_key_obj_p));
5908 			if (rv != CKR_OK) {
5909 				free_public_key_attr(pbk, key_type);
5910 				return (rv);
5911 			}
5912 
5913 			/* copy subprime */
5914 			rv = copy_bigint(KEY_PUB_DH942_SUBPRIME(pbk),
5915 			    KEY_PUB_DH942_SUBPRIME(old_pub_key_obj_p));
5916 			if (rv != CKR_OK) {
5917 				free_public_key_attr(pbk, key_type);
5918 				return (rv);
5919 			}
5920 
5921 			/* copy base */
5922 			rv = copy_bigint(KEY_PUB_DH942_BASE(pbk),
5923 			    KEY_PUB_DH942_BASE(old_pub_key_obj_p));
5924 			if (rv != CKR_OK) {
5925 				free_public_key_attr(pbk, key_type);
5926 				return (rv);
5927 			}
5928 
5929 			/* copy value */
5930 			rv = copy_bigint(KEY_PUB_DH942_VALUE(pbk),
5931 			    KEY_PUB_DH942_VALUE(old_pub_key_obj_p));
5932 			if (rv != CKR_OK) {
5933 				free_public_key_attr(pbk, key_type);
5934 				return (rv);
5935 			}
5936 			break;
5937 		default:
5938 			break;
5939 	}
5940 	*new_pub_key_obj_p = pbk;
5941 	return (rv);
5942 }
5943 
5944 static void
5945 free_private_key_attr(private_key_obj_t *pbk, CK_KEY_TYPE key_type)
5946 {
5947 	if (pbk == NULL) {
5948 		return;
5949 	}
5950 
5951 	switch (key_type) {
5952 		case CKK_RSA:
5953 			bigint_attr_cleanup(KEY_PRI_RSA_MOD(pbk));
5954 			bigint_attr_cleanup(KEY_PRI_RSA_PUBEXPO(pbk));
5955 			bigint_attr_cleanup(KEY_PRI_RSA_PRIEXPO(pbk));
5956 			bigint_attr_cleanup(KEY_PRI_RSA_PRIME1(pbk));
5957 			bigint_attr_cleanup(KEY_PRI_RSA_PRIME2(pbk));
5958 			bigint_attr_cleanup(KEY_PRI_RSA_EXPO1(pbk));
5959 			bigint_attr_cleanup(KEY_PRI_RSA_EXPO2(pbk));
5960 			bigint_attr_cleanup(KEY_PRI_RSA_COEF(pbk));
5961 			break;
5962 		case CKK_DSA:
5963 			bigint_attr_cleanup(KEY_PRI_DSA_PRIME(pbk));
5964 			bigint_attr_cleanup(KEY_PRI_DSA_SUBPRIME(pbk));
5965 			bigint_attr_cleanup(KEY_PRI_DSA_BASE(pbk));
5966 			bigint_attr_cleanup(KEY_PRI_DSA_VALUE(pbk));
5967 			break;
5968 		case CKK_DH:
5969 			bigint_attr_cleanup(KEY_PRI_DH_PRIME(pbk));
5970 			bigint_attr_cleanup(KEY_PRI_DH_BASE(pbk));
5971 			bigint_attr_cleanup(KEY_PRI_DH_VALUE(pbk));
5972 			break;
5973 		case CKK_EC:
5974 			bigint_attr_cleanup(KEY_PRI_EC_VALUE(pbk));
5975 			break;
5976 		case CKK_X9_42_DH:
5977 			bigint_attr_cleanup(KEY_PRI_DH942_PRIME(pbk));
5978 			bigint_attr_cleanup(KEY_PRI_DH942_SUBPRIME(pbk));
5979 			bigint_attr_cleanup(KEY_PRI_DH942_BASE(pbk));
5980 			bigint_attr_cleanup(KEY_PRI_DH942_VALUE(pbk));
5981 			break;
5982 		default:
5983 			break;
5984 	}
5985 	free(pbk);
5986 }
5987 
5988 CK_RV
5989 soft_copy_private_key_attr(private_key_obj_t *old_pri_key_obj_p,
5990     private_key_obj_t **new_pri_key_obj_p, CK_KEY_TYPE key_type)
5991 {
5992 	CK_RV rv = CKR_OK;
5993 	private_key_obj_t *pbk;
5994 
5995 	pbk = calloc(1, sizeof (private_key_obj_t));
5996 	if (pbk == NULL) {
5997 		return (CKR_HOST_MEMORY);
5998 	}
5999 
6000 	switch (key_type) {
6001 		case CKK_RSA:
6002 			(void) memcpy(KEY_PRI_RSA(pbk),
6003 			    KEY_PRI_RSA(old_pri_key_obj_p),
6004 			    sizeof (rsa_pri_key_t));
6005 			/* copy modulus */
6006 			rv = copy_bigint(KEY_PRI_RSA_MOD(pbk),
6007 			    KEY_PRI_RSA_MOD(old_pri_key_obj_p));
6008 			if (rv != CKR_OK) {
6009 				free_private_key_attr(pbk, key_type);
6010 				return (rv);
6011 			}
6012 			/* copy public exponent */
6013 			rv = copy_bigint(KEY_PRI_RSA_PUBEXPO(pbk),
6014 			    KEY_PRI_RSA_PUBEXPO(old_pri_key_obj_p));
6015 			if (rv != CKR_OK) {
6016 				free_private_key_attr(pbk, key_type);
6017 				return (rv);
6018 			}
6019 			/* copy private exponent */
6020 			rv = copy_bigint(KEY_PRI_RSA_PRIEXPO(pbk),
6021 			    KEY_PRI_RSA_PRIEXPO(old_pri_key_obj_p));
6022 			if (rv != CKR_OK) {
6023 				free_private_key_attr(pbk, key_type);
6024 				return (rv);
6025 			}
6026 			/* copy prime_1 */
6027 			rv = copy_bigint(KEY_PRI_RSA_PRIME1(pbk),
6028 			    KEY_PRI_RSA_PRIME1(old_pri_key_obj_p));
6029 			if (rv != CKR_OK) {
6030 				free_private_key_attr(pbk, key_type);
6031 				return (rv);
6032 			}
6033 			/* copy prime_2 */
6034 			rv = copy_bigint(KEY_PRI_RSA_PRIME2(pbk),
6035 			    KEY_PRI_RSA_PRIME2(old_pri_key_obj_p));
6036 			if (rv != CKR_OK) {
6037 				free_private_key_attr(pbk, key_type);
6038 				return (rv);
6039 			}
6040 			/* copy exponent_1 */
6041 			rv = copy_bigint(KEY_PRI_RSA_EXPO1(pbk),
6042 			    KEY_PRI_RSA_EXPO1(old_pri_key_obj_p));
6043 			if (rv != CKR_OK) {
6044 				free_private_key_attr(pbk, key_type);
6045 				return (rv);
6046 			}
6047 			/* copy exponent_2 */
6048 			rv = copy_bigint(KEY_PRI_RSA_EXPO2(pbk),
6049 			    KEY_PRI_RSA_EXPO2(old_pri_key_obj_p));
6050 			if (rv != CKR_OK) {
6051 				free_private_key_attr(pbk, key_type);
6052 				return (rv);
6053 			}
6054 			/* copy coefficient */
6055 			rv = copy_bigint(KEY_PRI_RSA_COEF(pbk),
6056 			    KEY_PRI_RSA_COEF(old_pri_key_obj_p));
6057 			if (rv != CKR_OK) {
6058 				free_private_key_attr(pbk, key_type);
6059 				return (rv);
6060 			}
6061 			break;
6062 		case CKK_DSA:
6063 			(void) memcpy(KEY_PRI_DSA(pbk),
6064 			    KEY_PRI_DSA(old_pri_key_obj_p),
6065 			    sizeof (dsa_pri_key_t));
6066 
6067 			/* copy prime */
6068 			rv = copy_bigint(KEY_PRI_DSA_PRIME(pbk),
6069 			    KEY_PRI_DSA_PRIME(old_pri_key_obj_p));
6070 			if (rv != CKR_OK) {
6071 				free_private_key_attr(pbk, key_type);
6072 				return (rv);
6073 			}
6074 
6075 			/* copy subprime */
6076 			rv = copy_bigint(KEY_PRI_DSA_SUBPRIME(pbk),
6077 			    KEY_PRI_DSA_SUBPRIME(old_pri_key_obj_p));
6078 			if (rv != CKR_OK) {
6079 				free_private_key_attr(pbk, key_type);
6080 				return (rv);
6081 			}
6082 
6083 			/* copy base */
6084 			rv = copy_bigint(KEY_PRI_DSA_BASE(pbk),
6085 			    KEY_PRI_DSA_BASE(old_pri_key_obj_p));
6086 			if (rv != CKR_OK) {
6087 				free_private_key_attr(pbk, key_type);
6088 				return (rv);
6089 			}
6090 
6091 			/* copy value */
6092 			rv = copy_bigint(KEY_PRI_DSA_VALUE(pbk),
6093 			    KEY_PRI_DSA_VALUE(old_pri_key_obj_p));
6094 			if (rv != CKR_OK) {
6095 				free_private_key_attr(pbk, key_type);
6096 				return (rv);
6097 			}
6098 			break;
6099 		case CKK_DH:
6100 			(void) memcpy(KEY_PRI_DH(pbk),
6101 			    KEY_PRI_DH(old_pri_key_obj_p),
6102 			    sizeof (dh_pri_key_t));
6103 
6104 			/* copy prime */
6105 			rv = copy_bigint(KEY_PRI_DH_PRIME(pbk),
6106 			    KEY_PRI_DH_PRIME(old_pri_key_obj_p));
6107 			if (rv != CKR_OK) {
6108 				free_private_key_attr(pbk, key_type);
6109 				return (rv);
6110 			}
6111 
6112 			/* copy base */
6113 			rv = copy_bigint(KEY_PRI_DH_BASE(pbk),
6114 			    KEY_PRI_DH_BASE(old_pri_key_obj_p));
6115 			if (rv != CKR_OK) {
6116 				free_private_key_attr(pbk, key_type);
6117 				return (rv);
6118 			}
6119 
6120 			/* copy value */
6121 			rv = copy_bigint(KEY_PRI_DH_VALUE(pbk),
6122 			    KEY_PRI_DH_VALUE(old_pri_key_obj_p));
6123 			if (rv != CKR_OK) {
6124 				free_private_key_attr(pbk, key_type);
6125 				return (rv);
6126 			}
6127 			break;
6128 		case CKK_EC:
6129 			(void) memcpy(KEY_PRI_EC(pbk),
6130 			    KEY_PRI_EC(old_pri_key_obj_p),
6131 			    sizeof (ec_pri_key_t));
6132 
6133 			/* copy value */
6134 			rv = copy_bigint(KEY_PRI_EC_VALUE(pbk),
6135 			    KEY_PRI_EC_VALUE(old_pri_key_obj_p));
6136 			if (rv != CKR_OK) {
6137 				free_private_key_attr(pbk, key_type);
6138 				return (rv);
6139 			}
6140 			break;
6141 		case CKK_X9_42_DH:
6142 			(void) memcpy(KEY_PRI_DH942(pbk),
6143 			    KEY_PRI_DH942(old_pri_key_obj_p),
6144 			    sizeof (dh942_pri_key_t));
6145 
6146 			/* copy prime */
6147 			rv = copy_bigint(KEY_PRI_DH942_PRIME(pbk),
6148 			    KEY_PRI_DH942_PRIME(old_pri_key_obj_p));
6149 			if (rv != CKR_OK) {
6150 				free_private_key_attr(pbk, key_type);
6151 				return (rv);
6152 			}
6153 
6154 			/* copy subprime */
6155 			rv = copy_bigint(KEY_PRI_DH942_SUBPRIME(pbk),
6156 			    KEY_PRI_DH942_SUBPRIME(old_pri_key_obj_p));
6157 			if (rv != CKR_OK) {
6158 				free_private_key_attr(pbk, key_type);
6159 				return (rv);
6160 			}
6161 
6162 			/* copy base */
6163 			rv = copy_bigint(KEY_PRI_DH942_BASE(pbk),
6164 			    KEY_PRI_DH942_BASE(old_pri_key_obj_p));
6165 			if (rv != CKR_OK) {
6166 				free_private_key_attr(pbk, key_type);
6167 				return (rv);
6168 			}
6169 
6170 			/* copy value */
6171 			rv = copy_bigint(KEY_PRI_DH942_VALUE(pbk),
6172 			    KEY_PRI_DH942_VALUE(old_pri_key_obj_p));
6173 			if (rv != CKR_OK) {
6174 				free_private_key_attr(pbk, key_type);
6175 				return (rv);
6176 			}
6177 			break;
6178 		default:
6179 			break;
6180 	}
6181 	*new_pri_key_obj_p = pbk;
6182 	return (rv);
6183 }
6184 
6185 static void
6186 free_domain_attr(domain_obj_t *domain, CK_KEY_TYPE key_type)
6187 {
6188 	if (domain == NULL) {
6189 		return;
6190 	}
6191 
6192 	switch (key_type) {
6193 		case CKK_DSA:
6194 			bigint_attr_cleanup(KEY_DOM_DSA_PRIME(domain));
6195 			bigint_attr_cleanup(KEY_DOM_DSA_SUBPRIME(domain));
6196 			bigint_attr_cleanup(KEY_DOM_DSA_BASE(domain));
6197 			break;
6198 		case CKK_DH:
6199 			bigint_attr_cleanup(KEY_DOM_DH_PRIME(domain));
6200 			bigint_attr_cleanup(KEY_DOM_DH_BASE(domain));
6201 			break;
6202 		case CKK_X9_42_DH:
6203 			bigint_attr_cleanup(KEY_DOM_DH942_PRIME(domain));
6204 			bigint_attr_cleanup(KEY_DOM_DH942_SUBPRIME(domain));
6205 			bigint_attr_cleanup(KEY_DOM_DH942_BASE(domain));
6206 			break;
6207 		default:
6208 			break;
6209 	}
6210 	free(domain);
6211 }
6212 
6213 CK_RV
6214 soft_copy_domain_attr(domain_obj_t *old_domain_obj_p,
6215     domain_obj_t **new_domain_obj_p, CK_KEY_TYPE key_type)
6216 {
6217 	CK_RV rv = CKR_OK;
6218 	domain_obj_t *domain;
6219 
6220 	domain = calloc(1, sizeof (domain_obj_t));
6221 	if (domain == NULL) {
6222 		return (CKR_HOST_MEMORY);
6223 	}
6224 
6225 	switch (key_type) {
6226 		case CKK_DSA:
6227 			(void) memcpy(KEY_DOM_DSA(domain),
6228 			    KEY_DOM_DSA(old_domain_obj_p),
6229 			    sizeof (dsa_dom_key_t));
6230 
6231 			/* copy prime */
6232 			rv = copy_bigint(KEY_DOM_DSA_PRIME(domain),
6233 			    KEY_DOM_DSA_PRIME(old_domain_obj_p));
6234 			if (rv != CKR_OK) {
6235 				free_domain_attr(domain, key_type);
6236 				return (rv);
6237 			}
6238 
6239 			/* copy subprime */
6240 			rv = copy_bigint(KEY_DOM_DSA_SUBPRIME(domain),
6241 			    KEY_DOM_DSA_SUBPRIME(old_domain_obj_p));
6242 			if (rv != CKR_OK) {
6243 				free_domain_attr(domain, key_type);
6244 				return (rv);
6245 			}
6246 
6247 			/* copy base */
6248 			rv = copy_bigint(KEY_DOM_DSA_BASE(domain),
6249 			    KEY_DOM_DSA_BASE(old_domain_obj_p));
6250 			if (rv != CKR_OK) {
6251 				free_domain_attr(domain, key_type);
6252 				return (rv);
6253 			}
6254 
6255 			break;
6256 		case CKK_DH:
6257 			(void) memcpy(KEY_DOM_DH(domain),
6258 			    KEY_DOM_DH(old_domain_obj_p),
6259 			    sizeof (dh_dom_key_t));
6260 
6261 			/* copy prime */
6262 			rv = copy_bigint(KEY_DOM_DH_PRIME(domain),
6263 			    KEY_DOM_DH_PRIME(old_domain_obj_p));
6264 			if (rv != CKR_OK) {
6265 				free_domain_attr(domain, key_type);
6266 				return (rv);
6267 			}
6268 
6269 			/* copy base */
6270 			rv = copy_bigint(KEY_DOM_DH_BASE(domain),
6271 			    KEY_DOM_DH_BASE(old_domain_obj_p));
6272 			if (rv != CKR_OK) {
6273 				free_domain_attr(domain, key_type);
6274 				return (rv);
6275 			}
6276 
6277 			break;
6278 		case CKK_X9_42_DH:
6279 			(void) memcpy(KEY_DOM_DH942(domain),
6280 			    KEY_DOM_DH942(old_domain_obj_p),
6281 			    sizeof (dh942_dom_key_t));
6282 
6283 			/* copy prime */
6284 			rv = copy_bigint(KEY_DOM_DH942_PRIME(domain),
6285 			    KEY_DOM_DH942_PRIME(old_domain_obj_p));
6286 			if (rv != CKR_OK) {
6287 				free_domain_attr(domain, key_type);
6288 				return (rv);
6289 			}
6290 
6291 			/* copy subprime */
6292 			rv = copy_bigint(KEY_DOM_DH942_SUBPRIME(domain),
6293 			    KEY_DOM_DH942_SUBPRIME(old_domain_obj_p));
6294 			if (rv != CKR_OK) {
6295 				free_domain_attr(domain, key_type);
6296 				return (rv);
6297 			}
6298 
6299 			/* copy base */
6300 			rv = copy_bigint(KEY_DOM_DH942_BASE(domain),
6301 			    KEY_DOM_DH942_BASE(old_domain_obj_p));
6302 			if (rv != CKR_OK) {
6303 				free_domain_attr(domain, key_type);
6304 				return (rv);
6305 			}
6306 
6307 			break;
6308 		default:
6309 			break;
6310 	}
6311 	*new_domain_obj_p = domain;
6312 	return (rv);
6313 }
6314 
6315 CK_RV
6316 soft_copy_secret_key_attr(secret_key_obj_t *old_secret_key_obj_p,
6317     secret_key_obj_t **new_secret_key_obj_p)
6318 {
6319 	secret_key_obj_t *sk;
6320 
6321 	sk = malloc(sizeof (secret_key_obj_t));
6322 	if (sk == NULL) {
6323 		return (CKR_HOST_MEMORY);
6324 	}
6325 	(void) memcpy(sk, old_secret_key_obj_p, sizeof (secret_key_obj_t));
6326 
6327 	/* copy the secret key value */
6328 	sk->sk_value = malloc((sizeof (CK_BYTE) * sk->sk_value_len));
6329 	if (sk->sk_value == NULL) {
6330 		free(sk);
6331 		return (CKR_HOST_MEMORY);
6332 	}
6333 	(void) memcpy(sk->sk_value, old_secret_key_obj_p->sk_value,
6334 	    (sizeof (CK_BYTE) * sk->sk_value_len));
6335 
6336 	/*
6337 	 * Copy the pre-expanded key schedule.
6338 	 */
6339 	if (old_secret_key_obj_p->key_sched != NULL &&
6340 	    old_secret_key_obj_p->keysched_len > 0) {
6341 		sk->key_sched = malloc(old_secret_key_obj_p->keysched_len);
6342 		if (sk->key_sched == NULL) {
6343 			free(sk);
6344 			return (CKR_HOST_MEMORY);
6345 		}
6346 		sk->keysched_len = old_secret_key_obj_p->keysched_len;
6347 		(void) memcpy(sk->key_sched, old_secret_key_obj_p->key_sched,
6348 		    sk->keysched_len);
6349 	}
6350 
6351 	*new_secret_key_obj_p = sk;
6352 
6353 	return (CKR_OK);
6354 }
6355 
6356 /*
6357  * If CKA_CLASS not given, guess CKA_CLASS using
6358  * attributes on template .
6359  *
6360  * Some attributes are specific to an object class.  If one or more
6361  * of these attributes are in the template, make a list of classes
6362  * that can have these attributes.  This would speed up the search later,
6363  * because we can immediately skip an object if the class of that
6364  * object can not possibly contain one of the attributes.
6365  *
6366  */
6367 void
6368 soft_process_find_attr(CK_OBJECT_CLASS *pclasses,
6369     CK_ULONG *num_result_pclasses, CK_ATTRIBUTE_PTR pTemplate,
6370     CK_ULONG ulCount)
6371 {
6372 	ulong_t i;
6373 	int j;
6374 	boolean_t pub_found = B_FALSE,
6375 	    priv_found = B_FALSE,
6376 	    secret_found = B_FALSE,
6377 	    domain_found = B_FALSE,
6378 	    hardware_found = B_FALSE,
6379 	    cert_found = B_FALSE;
6380 	int num_pub_key_attrs, num_priv_key_attrs,
6381 	    num_secret_key_attrs, num_domain_attrs,
6382 	    num_hardware_attrs, num_cert_attrs;
6383 	int num_pclasses = 0;
6384 
6385 	for (i = 0; i < ulCount; i++) {
6386 		if (pTemplate[i].type == CKA_CLASS) {
6387 			/*
6388 			 * don't need to guess the class, it is specified.
6389 			 * Just record the class, and return.
6390 			 */
6391 			pclasses[0] =
6392 			    (*((CK_OBJECT_CLASS *)pTemplate[i].pValue));
6393 			*num_result_pclasses = 1;
6394 			return;
6395 		}
6396 	}
6397 
6398 	num_pub_key_attrs =
6399 	    sizeof (PUB_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6400 	num_priv_key_attrs =
6401 	    sizeof (PRIV_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6402 	num_secret_key_attrs =
6403 	    sizeof (SECRET_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6404 	num_domain_attrs =
6405 	    sizeof (DOMAIN_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6406 	num_hardware_attrs =
6407 	    sizeof (HARDWARE_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6408 	num_cert_attrs =
6409 	    sizeof (CERT_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6410 
6411 	/*
6412 	 * Get the list of objects class that might contain
6413 	 * some attributes.
6414 	 */
6415 	for (i = 0; i < ulCount; i++) {
6416 		/*
6417 		 * only check if this attribute can belong to public key object
6418 		 * class if public key object isn't already in the list
6419 		 */
6420 		if (!pub_found) {
6421 			for (j = 0; j < num_pub_key_attrs; j++) {
6422 				if (pTemplate[i].type == PUB_KEY_ATTRS[j]) {
6423 					pub_found = B_TRUE;
6424 					pclasses[num_pclasses++] =
6425 					    CKO_PUBLIC_KEY;
6426 					break;
6427 				}
6428 			}
6429 		}
6430 
6431 		if (!priv_found) {
6432 			for (j = 0; j < num_priv_key_attrs; j++) {
6433 				if (pTemplate[i].type == PRIV_KEY_ATTRS[j]) {
6434 					priv_found = B_TRUE;
6435 					pclasses[num_pclasses++] =
6436 					    CKO_PRIVATE_KEY;
6437 					break;
6438 				}
6439 			}
6440 		}
6441 
6442 		if (!secret_found) {
6443 			for (j = 0; j < num_secret_key_attrs; j++) {
6444 				if (pTemplate[i].type == SECRET_KEY_ATTRS[j]) {
6445 					secret_found = B_TRUE;
6446 					pclasses[num_pclasses++] =
6447 					    CKO_SECRET_KEY;
6448 					break;
6449 				}
6450 			}
6451 		}
6452 
6453 		if (!domain_found) {
6454 			for (j = 0; j < num_domain_attrs; j++) {
6455 				if (pTemplate[i].type == DOMAIN_ATTRS[j]) {
6456 					domain_found = B_TRUE;
6457 					pclasses[num_pclasses++] =
6458 					    CKO_DOMAIN_PARAMETERS;
6459 					break;
6460 				}
6461 			}
6462 		}
6463 
6464 		if (!hardware_found) {
6465 			for (j = 0; j < num_hardware_attrs; j++) {
6466 				if (pTemplate[i].type == HARDWARE_ATTRS[j]) {
6467 					hardware_found = B_TRUE;
6468 					pclasses[num_pclasses++] =
6469 					    CKO_HW_FEATURE;
6470 					break;
6471 				}
6472 			}
6473 		}
6474 
6475 		if (!cert_found) {
6476 			for (j = 0; j < num_cert_attrs; j++) {
6477 				if (pTemplate[i].type == CERT_ATTRS[j]) {
6478 					cert_found = B_TRUE;
6479 					pclasses[num_pclasses++] =
6480 					    CKO_CERTIFICATE;
6481 					break;
6482 				}
6483 			}
6484 		}
6485 	}
6486 	*num_result_pclasses = num_pclasses;
6487 }
6488 
6489 boolean_t
6490 soft_find_match_attrs(soft_object_t *obj, CK_OBJECT_CLASS *pclasses,
6491     CK_ULONG num_pclasses, CK_ATTRIBUTE *template, CK_ULONG num_attr)
6492 {
6493 	ulong_t i;
6494 	CK_ATTRIBUTE *tmpl_attr, *obj_attr;
6495 	cert_attr_t *cert_attr;
6496 	uint64_t attr_mask;
6497 	biginteger_t *bigint;
6498 	boolean_t compare_attr, compare_bigint, compare_boolean;
6499 	boolean_t compare_cert_val, compare_cert_type;
6500 
6501 	/*
6502 	 * Check if the class of this object match with any
6503 	 * of object classes that can possibly contain the
6504 	 * requested attributes.
6505 	 */
6506 	if (num_pclasses > 0) {
6507 		for (i = 0; i < num_pclasses; i++) {
6508 			if (obj->class == pclasses[i]) {
6509 				break;
6510 			}
6511 		}
6512 		if (i == num_pclasses) {
6513 			/*
6514 			 * this object can't possibly contain one or
6515 			 * more attributes, don't need to check this object
6516 			 */
6517 			return (B_FALSE);
6518 		}
6519 	}
6520 
6521 	/* need to examine everything */
6522 	for (i = 0; i < num_attr; i++) {
6523 		tmpl_attr = &(template[i]);
6524 		compare_attr = B_FALSE;
6525 		compare_bigint = B_FALSE;
6526 		compare_boolean = B_FALSE;
6527 		compare_cert_val = B_FALSE;
6528 		compare_cert_type = B_FALSE;
6529 		switch (tmpl_attr->type) {
6530 		/* First, check the most common attributes */
6531 		case CKA_CLASS:
6532 			if (*((CK_OBJECT_CLASS *)tmpl_attr->pValue) !=
6533 			    obj->class) {
6534 				return (B_FALSE);
6535 			}
6536 			break;
6537 		case CKA_KEY_TYPE:
6538 			if (*((CK_KEY_TYPE *)tmpl_attr->pValue) !=
6539 			    obj->key_type) {
6540 				return (B_FALSE);
6541 			}
6542 			break;
6543 		case CKA_ENCRYPT:
6544 			attr_mask = (obj->bool_attr_mask) & ENCRYPT_BOOL_ON;
6545 			compare_boolean = B_TRUE;
6546 			break;
6547 		case CKA_DECRYPT:
6548 			attr_mask = (obj->bool_attr_mask) & DECRYPT_BOOL_ON;
6549 			compare_boolean = B_TRUE;
6550 			break;
6551 		case CKA_WRAP:
6552 			attr_mask = (obj->bool_attr_mask) & WRAP_BOOL_ON;
6553 			compare_boolean = B_TRUE;
6554 			break;
6555 		case CKA_UNWRAP:
6556 			attr_mask = (obj->bool_attr_mask) & UNWRAP_BOOL_ON;
6557 			compare_boolean = B_TRUE;
6558 			break;
6559 		case CKA_SIGN:
6560 			attr_mask = (obj->bool_attr_mask) & SIGN_BOOL_ON;
6561 			compare_boolean = B_TRUE;
6562 			break;
6563 		case CKA_SIGN_RECOVER:
6564 			attr_mask = (obj->bool_attr_mask) &
6565 			    SIGN_RECOVER_BOOL_ON;
6566 			compare_boolean = B_TRUE;
6567 			break;
6568 		case CKA_VERIFY:
6569 			attr_mask = (obj->bool_attr_mask) & VERIFY_BOOL_ON;
6570 			compare_boolean = B_TRUE;
6571 			break;
6572 		case CKA_VERIFY_RECOVER:
6573 			attr_mask = (obj->bool_attr_mask) &
6574 			    VERIFY_RECOVER_BOOL_ON;
6575 			compare_boolean = B_TRUE;
6576 			break;
6577 		case CKA_DERIVE:
6578 			attr_mask = (obj->bool_attr_mask) & DERIVE_BOOL_ON;
6579 			compare_boolean = B_TRUE;
6580 			break;
6581 		case CKA_LOCAL:
6582 			attr_mask = (obj->bool_attr_mask) & LOCAL_BOOL_ON;
6583 			compare_boolean = B_TRUE;
6584 			break;
6585 		case CKA_SENSITIVE:
6586 			attr_mask = (obj->bool_attr_mask) & SENSITIVE_BOOL_ON;
6587 			compare_boolean = B_TRUE;
6588 			break;
6589 		case CKA_SECONDARY_AUTH:
6590 			attr_mask = (obj->bool_attr_mask) &
6591 			    SECONDARY_AUTH_BOOL_ON;
6592 			compare_boolean = B_TRUE;
6593 			break;
6594 		case CKA_TRUSTED:
6595 			attr_mask = (obj->bool_attr_mask) & TRUSTED_BOOL_ON;
6596 			compare_boolean = B_TRUE;
6597 			break;
6598 		case CKA_EXTRACTABLE:
6599 			attr_mask = (obj->bool_attr_mask) &
6600 			    EXTRACTABLE_BOOL_ON;
6601 			compare_boolean = B_TRUE;
6602 			break;
6603 		case CKA_ALWAYS_SENSITIVE:
6604 			attr_mask = (obj->bool_attr_mask) &
6605 			    ALWAYS_SENSITIVE_BOOL_ON;
6606 			compare_boolean = B_TRUE;
6607 			break;
6608 		case CKA_NEVER_EXTRACTABLE:
6609 			attr_mask = (obj->bool_attr_mask) &
6610 			    NEVER_EXTRACTABLE_BOOL_ON;
6611 			compare_boolean = B_TRUE;
6612 			break;
6613 		case CKA_TOKEN:
6614 			attr_mask = (obj->object_type) & TOKEN_OBJECT;
6615 			compare_boolean = B_TRUE;
6616 			break;
6617 		case CKA_PRIVATE:
6618 			attr_mask = (obj->object_type) & PRIVATE_OBJECT;
6619 			compare_boolean = B_TRUE;
6620 			break;
6621 		case CKA_MODIFIABLE:
6622 		{
6623 			CK_BBOOL bval;
6624 			attr_mask = (obj->bool_attr_mask) &
6625 			    NOT_MODIFIABLE_BOOL_ON;
6626 
6627 			if (attr_mask) {
6628 				bval = FALSE;
6629 			} else {
6630 				bval = TRUE;
6631 			}
6632 			if (bval != *((CK_BBOOL *)tmpl_attr->pValue)) {
6633 				return (B_FALSE);
6634 			}
6635 			break;
6636 		}
6637 		case CKA_OWNER:
6638 			/*
6639 			 * For X.509 attribute certificate object, get its
6640 			 * CKA_OWNER attribute from the x509_attr_cert_t struct.
6641 			 */
6642 			if ((obj->class == CKO_CERTIFICATE) &&
6643 			    (obj->cert_type == CKC_X_509_ATTR_CERT)) {
6644 				cert_attr = X509_ATTR_CERT_OWNER(obj);
6645 				compare_cert_val = B_TRUE;
6646 			}
6647 			break;
6648 		case CKA_SUBJECT:
6649 			/*
6650 			 * For X.509 certificate object, get its CKA_SUBJECT
6651 			 * attribute from the x509_cert_t struct (not from
6652 			 * the extra_attrlistp).
6653 			 */
6654 			if ((obj->class == CKO_CERTIFICATE) &&
6655 			    (obj->cert_type == CKC_X_509)) {
6656 				cert_attr = X509_CERT_SUBJECT(obj);
6657 				compare_cert_val = B_TRUE;
6658 				break;
6659 			}
6660 			/*FALLTHRU*/
6661 		case CKA_ID:
6662 		case CKA_START_DATE:
6663 		case CKA_END_DATE:
6664 		case CKA_KEY_GEN_MECHANISM:
6665 		case CKA_LABEL:
6666 		case CKA_ISSUER:
6667 		case CKA_SERIAL_NUMBER:
6668 		case CKA_AC_ISSUER:
6669 		case CKA_ATTR_TYPES:
6670 			/* find these attributes from extra_attrlistp */
6671 			obj_attr = get_extra_attr(tmpl_attr->type, obj);
6672 			compare_attr = B_TRUE;
6673 			break;
6674 		case CKA_CERTIFICATE_TYPE:
6675 			compare_cert_type = B_TRUE;
6676 			break;
6677 		case CKA_VALUE_LEN:
6678 			/* only secret key has this attribute */
6679 			if (obj->class == CKO_SECRET_KEY) {
6680 				if (*((CK_ULONG *)tmpl_attr->pValue) !=
6681 				    OBJ_SEC_VALUE_LEN(obj)) {
6682 					return (B_FALSE);
6683 				}
6684 			} else {
6685 				return (B_FALSE);
6686 			}
6687 			break;
6688 		case CKA_VALUE:
6689 			switch (obj->class) {
6690 			case CKO_SECRET_KEY:
6691 				/*
6692 				 * secret_key_obj_t is the same as
6693 				 * biginteger_t
6694 				 */
6695 				bigint = (biginteger_t *)OBJ_SEC(obj);
6696 				compare_bigint = B_TRUE;
6697 				break;
6698 			case CKO_PRIVATE_KEY:
6699 				if (obj->key_type == CKK_DSA) {
6700 					bigint = OBJ_PRI_DSA_VALUE(obj);
6701 				} else if (obj->key_type == CKK_DH) {
6702 					bigint = OBJ_PRI_DH_VALUE(obj);
6703 				} else if (obj->key_type == CKK_X9_42_DH) {
6704 					bigint = OBJ_PRI_DH942_VALUE(obj);
6705 				} else {
6706 					return (B_FALSE);
6707 				}
6708 				compare_bigint = B_TRUE;
6709 				break;
6710 			case CKO_PUBLIC_KEY:
6711 				if (obj->key_type == CKK_DSA) {
6712 					bigint = OBJ_PUB_DSA_VALUE(obj);
6713 				} else if (obj->key_type == CKK_DH) {
6714 					bigint = OBJ_PUB_DH_VALUE(obj);
6715 				} else if (obj->key_type == CKK_X9_42_DH) {
6716 					bigint = OBJ_PUB_DH942_VALUE(obj);
6717 				} else {
6718 					return (B_FALSE);
6719 				}
6720 				compare_bigint = B_TRUE;
6721 				break;
6722 			case CKO_CERTIFICATE:
6723 				if (obj->cert_type == CKC_X_509) {
6724 					cert_attr = X509_CERT_VALUE(obj);
6725 				} else if (obj->cert_type ==
6726 				    CKC_X_509_ATTR_CERT) {
6727 					cert_attr = X509_ATTR_CERT_VALUE(obj);
6728 				}
6729 				compare_cert_val = B_TRUE;
6730 				break;
6731 			default:
6732 				return (B_FALSE);
6733 			}
6734 			break;
6735 		case CKA_MODULUS:
6736 			/* only RSA public and private key have this attr */
6737 			if (obj->key_type == CKK_RSA) {
6738 				if (obj->class == CKO_PUBLIC_KEY) {
6739 					bigint = OBJ_PUB_RSA_MOD(obj);
6740 				} else if (obj->class == CKO_PRIVATE_KEY) {
6741 					bigint = OBJ_PRI_RSA_MOD(obj);
6742 				} else {
6743 					return (B_FALSE);
6744 				}
6745 				compare_bigint = B_TRUE;
6746 			} else {
6747 				return (B_FALSE);
6748 			}
6749 			break;
6750 		case CKA_MODULUS_BITS:
6751 			/* only RSA public key has this attribute */
6752 			if ((obj->key_type == CKK_RSA) &&
6753 			    (obj->class == CKO_PUBLIC_KEY)) {
6754 				CK_ULONG mod_bits = OBJ_PUB_RSA_MOD_BITS(obj);
6755 				if (mod_bits !=
6756 				    *((CK_ULONG *)tmpl_attr->pValue)) {
6757 					return (B_FALSE);
6758 				}
6759 			} else {
6760 				return (B_FALSE);
6761 			}
6762 			break;
6763 		case CKA_PUBLIC_EXPONENT:
6764 			/* only RSA public and private key have this attr */
6765 			if (obj->key_type == CKK_RSA) {
6766 				if (obj->class == CKO_PUBLIC_KEY) {
6767 					bigint = OBJ_PUB_RSA_PUBEXPO(obj);
6768 				} else if (obj->class == CKO_PRIVATE_KEY) {
6769 					bigint = OBJ_PRI_RSA_PUBEXPO(obj);
6770 				} else {
6771 					return (B_FALSE);
6772 				}
6773 				compare_bigint = B_TRUE;
6774 			} else {
6775 				return (B_FALSE);
6776 			}
6777 			break;
6778 		case CKA_PRIVATE_EXPONENT:
6779 			/* only RSA private key has this attribute */
6780 			if ((obj->key_type == CKK_RSA) &&
6781 			    (obj->class == CKO_PRIVATE_KEY)) {
6782 				bigint = OBJ_PRI_RSA_PRIEXPO(obj);
6783 				compare_bigint = B_TRUE;
6784 			} else {
6785 				return (B_FALSE);
6786 			}
6787 			break;
6788 		case CKA_PRIME_1:
6789 			/* only RSA private key has this attribute */
6790 			if ((obj->key_type == CKK_RSA) &&
6791 			    (obj->class == CKO_PRIVATE_KEY)) {
6792 				bigint = OBJ_PRI_RSA_PRIME1(obj);
6793 				compare_bigint = B_TRUE;
6794 			} else {
6795 				return (B_FALSE);
6796 			}
6797 			break;
6798 		case CKA_PRIME_2:
6799 			/* only RSA private key has this attribute */
6800 			if ((obj->key_type == CKK_RSA) &&
6801 			    (obj->class == CKO_PRIVATE_KEY)) {
6802 				bigint = OBJ_PRI_RSA_PRIME2(obj);
6803 				compare_bigint = B_TRUE;
6804 			} else {
6805 				return (B_FALSE);
6806 			}
6807 			break;
6808 		case CKA_EXPONENT_1:
6809 			/* only RSA private key has this attribute */
6810 			if ((obj->key_type == CKK_RSA) &&
6811 			    (obj->class == CKO_PRIVATE_KEY)) {
6812 				bigint = OBJ_PRI_RSA_EXPO1(obj);
6813 				compare_bigint = B_TRUE;
6814 			} else {
6815 				return (B_FALSE);
6816 			}
6817 			break;
6818 		case CKA_EXPONENT_2:
6819 			/* only RSA private key has this attribute */
6820 			if ((obj->key_type == CKK_RSA) &&
6821 			    (obj->class == CKO_PRIVATE_KEY)) {
6822 				bigint = OBJ_PRI_RSA_EXPO2(obj);
6823 				compare_bigint = B_TRUE;
6824 			} else {
6825 				return (B_FALSE);
6826 			}
6827 			break;
6828 		case CKA_COEFFICIENT:
6829 			/* only RSA private key has this attribute */
6830 			if ((obj->key_type == CKK_RSA) &&
6831 			    (obj->class == CKO_PRIVATE_KEY)) {
6832 				bigint = OBJ_PRI_RSA_COEF(obj);
6833 				compare_bigint = B_TRUE;
6834 			} else {
6835 				return (B_FALSE);
6836 			}
6837 			break;
6838 		case CKA_VALUE_BITS:
6839 			/* only Diffie-Hellman private key has this attr */
6840 			if ((obj->key_type == CKK_DH) &&
6841 			    (obj->class == CKO_PRIVATE_KEY)) {
6842 				CK_ULONG val_bits = OBJ_PRI_DH_VAL_BITS(obj);
6843 				if (val_bits !=
6844 				    *((CK_ULONG *)tmpl_attr->pValue)) {
6845 					return (B_FALSE);
6846 				}
6847 			} else {
6848 				return (B_FALSE);
6849 			}
6850 			break;
6851 		case CKA_PRIME:
6852 			if (obj->class == CKO_PUBLIC_KEY) {
6853 				switch (obj->key_type) {
6854 				case CKK_DSA:
6855 					bigint = OBJ_PUB_DSA_PRIME(obj);
6856 					break;
6857 				case CKK_DH:
6858 					bigint = OBJ_PUB_DH_PRIME(obj);
6859 					break;
6860 				case CKK_X9_42_DH:
6861 					bigint = OBJ_PUB_DH942_PRIME(obj);
6862 					break;
6863 				default:
6864 					return (B_FALSE);
6865 				}
6866 			} else if (obj->class == CKO_PRIVATE_KEY) {
6867 				switch (obj->key_type) {
6868 				case CKK_DSA:
6869 					bigint = OBJ_PRI_DSA_PRIME(obj);
6870 					break;
6871 				case CKK_DH:
6872 					bigint = OBJ_PRI_DH_PRIME(obj);
6873 					break;
6874 				case CKK_X9_42_DH:
6875 					bigint = OBJ_PRI_DH942_PRIME(obj);
6876 					break;
6877 				default:
6878 					return (B_FALSE);
6879 				}
6880 			} else if (obj->class == CKO_DOMAIN_PARAMETERS) {
6881 				switch (obj->key_type) {
6882 				case CKK_DSA:
6883 					bigint = OBJ_DOM_DSA_PRIME(obj);
6884 					break;
6885 				case CKK_DH:
6886 					bigint = OBJ_DOM_DH_PRIME(obj);
6887 					break;
6888 				case CKK_X9_42_DH:
6889 					bigint = OBJ_DOM_DH942_PRIME(obj);
6890 					break;
6891 				default:
6892 					return (B_FALSE);
6893 				}
6894 			} else {
6895 				return (B_FALSE);
6896 			}
6897 			compare_bigint = B_TRUE;
6898 			break;
6899 		case CKA_SUBPRIME:
6900 			if (obj->class == CKO_PUBLIC_KEY) {
6901 				switch (obj->key_type) {
6902 				case CKK_DSA:
6903 					bigint = OBJ_PUB_DSA_SUBPRIME(obj);
6904 					break;
6905 				case CKK_X9_42_DH:
6906 					bigint = OBJ_PUB_DH942_SUBPRIME(obj);
6907 					break;
6908 				default:
6909 					return (B_FALSE);
6910 				}
6911 			} else if (obj->class == CKO_PRIVATE_KEY) {
6912 				switch (obj->key_type) {
6913 				case CKK_DSA:
6914 					bigint = OBJ_PRI_DSA_SUBPRIME(obj);
6915 					break;
6916 				case CKK_X9_42_DH:
6917 					bigint = OBJ_PRI_DH942_SUBPRIME(obj);
6918 					break;
6919 				default:
6920 					return (B_FALSE);
6921 				}
6922 			} else if (obj->class == CKO_DOMAIN_PARAMETERS) {
6923 				switch (obj->key_type) {
6924 				case CKK_DSA:
6925 					bigint = OBJ_DOM_DSA_SUBPRIME(obj);
6926 					break;
6927 				case CKK_X9_42_DH:
6928 					bigint = OBJ_DOM_DH942_SUBPRIME(obj);
6929 					break;
6930 				default:
6931 					return (B_FALSE);
6932 				}
6933 			} else {
6934 				return (B_FALSE);
6935 			}
6936 			compare_bigint = B_TRUE;
6937 			break;
6938 		case CKA_BASE:
6939 			if (obj->class == CKO_PUBLIC_KEY) {
6940 				switch (obj->key_type) {
6941 				case CKK_DSA:
6942 					bigint = OBJ_PUB_DSA_BASE(obj);
6943 					break;
6944 				case CKK_DH:
6945 					bigint = OBJ_PUB_DH_BASE(obj);
6946 					break;
6947 				case CKK_X9_42_DH:
6948 					bigint = OBJ_PUB_DH942_BASE(obj);
6949 					break;
6950 				default:
6951 					return (B_FALSE);
6952 				}
6953 			} else if (obj->class == CKO_PRIVATE_KEY) {
6954 				switch (obj->key_type) {
6955 				case CKK_DSA:
6956 					bigint = OBJ_PRI_DSA_BASE(obj);
6957 					break;
6958 				case CKK_DH:
6959 					bigint = OBJ_PRI_DH_BASE(obj);
6960 					break;
6961 				case CKK_X9_42_DH:
6962 					bigint = OBJ_PRI_DH942_BASE(obj);
6963 					break;
6964 				default:
6965 					return (B_FALSE);
6966 				}
6967 			} else if (obj->class == CKO_DOMAIN_PARAMETERS) {
6968 				switch (obj->key_type) {
6969 				case CKK_DSA:
6970 					bigint = OBJ_DOM_DSA_BASE(obj);
6971 					break;
6972 				case CKK_DH:
6973 					bigint = OBJ_DOM_DH_BASE(obj);
6974 					break;
6975 				case CKK_X9_42_DH:
6976 					bigint = OBJ_DOM_DH942_BASE(obj);
6977 					break;
6978 				default:
6979 					return (B_FALSE);
6980 				}
6981 			} else {
6982 				return (B_FALSE);
6983 			}
6984 			compare_bigint = B_TRUE;
6985 			break;
6986 		case CKA_PRIME_BITS:
6987 			if (obj->class == CKO_DOMAIN_PARAMETERS) {
6988 				CK_ULONG prime_bits;
6989 				if (obj->key_type == CKK_DSA) {
6990 					prime_bits =
6991 					    OBJ_DOM_DSA_PRIME_BITS(obj);
6992 				} else if (obj->key_type == CKK_DH) {
6993 					prime_bits =
6994 					    OBJ_DOM_DH_PRIME_BITS(obj);
6995 				} else if (obj->key_type == CKK_X9_42_DH) {
6996 					prime_bits =
6997 					    OBJ_DOM_DH942_PRIME_BITS(obj);
6998 				} else {
6999 					return (B_FALSE);
7000 				}
7001 				if (prime_bits !=
7002 				    *((CK_ULONG *)tmpl_attr->pValue)) {
7003 					return (B_FALSE);
7004 				}
7005 			} else {
7006 				return (B_FALSE);
7007 			}
7008 			break;
7009 		case CKA_SUBPRIME_BITS:
7010 			if ((obj->class == CKO_DOMAIN_PARAMETERS) &&
7011 			    (obj->key_type == CKK_X9_42_DH)) {
7012 				CK_ULONG subprime_bits =
7013 				    OBJ_DOM_DH942_SUBPRIME_BITS(obj);
7014 				if (subprime_bits !=
7015 				    *((CK_ULONG *)tmpl_attr->pValue)) {
7016 					return (B_FALSE);
7017 				}
7018 			} else {
7019 				return (B_FALSE);
7020 			}
7021 			break;
7022 		default:
7023 			/*
7024 			 * any other attributes are currently not supported.
7025 			 * so, it's not possible for them to be in the
7026 			 * object
7027 			 */
7028 			return (B_FALSE);
7029 		}
7030 		if (compare_boolean) {
7031 			CK_BBOOL bval;
7032 
7033 			if (attr_mask) {
7034 				bval = TRUE;
7035 			} else {
7036 				bval = FALSE;
7037 			}
7038 			if (bval != *((CK_BBOOL *)tmpl_attr->pValue)) {
7039 				return (B_FALSE);
7040 			}
7041 		} else if (compare_bigint) {
7042 			if (bigint == NULL) {
7043 				return (B_FALSE);
7044 			}
7045 			if (tmpl_attr->ulValueLen != bigint->big_value_len) {
7046 				return (B_FALSE);
7047 			}
7048 			if (memcmp(tmpl_attr->pValue, bigint->big_value,
7049 			    tmpl_attr->ulValueLen) != 0) {
7050 				return (B_FALSE);
7051 			}
7052 		} else if (compare_attr) {
7053 			if (obj_attr == NULL) {
7054 				/*
7055 				 * The attribute type is valid, and its value
7056 				 * has not been initialized in the object. In
7057 				 * this case, it only matches the template's
7058 				 * attribute if the template's value length
7059 				 * is 0.
7060 				 */
7061 				if (tmpl_attr->ulValueLen != 0)
7062 					return (B_FALSE);
7063 			} else {
7064 				if (tmpl_attr->ulValueLen !=
7065 				    obj_attr->ulValueLen) {
7066 					return (B_FALSE);
7067 				}
7068 				if (memcmp(tmpl_attr->pValue, obj_attr->pValue,
7069 				    tmpl_attr->ulValueLen) != 0) {
7070 					return (B_FALSE);
7071 				}
7072 			}
7073 		} else if (compare_cert_val) {
7074 			if (cert_attr == NULL) {
7075 				/* specific attribute not found */
7076 				return (B_FALSE);
7077 			}
7078 			if (tmpl_attr->ulValueLen != cert_attr->length) {
7079 				return (B_FALSE);
7080 			}
7081 			if (memcmp(tmpl_attr->pValue, cert_attr->value,
7082 			    tmpl_attr->ulValueLen) != 0) {
7083 				return (B_FALSE);
7084 			}
7085 		} else if (compare_cert_type) {
7086 			if (memcmp(tmpl_attr->pValue, &(obj->cert_type),
7087 			    tmpl_attr->ulValueLen) != 0) {
7088 				return (B_FALSE);
7089 			}
7090 		}
7091 	}
7092 	return (B_TRUE);
7093 }
7094 
7095 CK_ATTRIBUTE_PTR
7096 get_extra_attr(CK_ATTRIBUTE_TYPE type, soft_object_t *obj)
7097 {
7098 	CK_ATTRIBUTE_INFO_PTR tmp;
7099 
7100 	tmp = obj->extra_attrlistp;
7101 	while (tmp != NULL) {
7102 		if (tmp->attr.type == type) {
7103 			return (&(tmp->attr));
7104 		}
7105 		tmp = tmp->next;
7106 	}
7107 	/* if get there, the specified attribute is not found */
7108 	return (NULL);
7109 }
7110