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