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