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