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