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