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