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 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  * Copyright 2012 Milan Jurik. All rights reserved.
25  * Copyright (c) 2018, Joyent, Inc.
26  */
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
soft_lookup_attr(CK_ATTRIBUTE_TYPE type)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
soft_validate_attr(CK_ATTRIBUTE_PTR template,CK_ULONG ulAttrNum,CK_OBJECT_CLASS * class)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
cleanup_cert_attr(cert_attr_t * attr)324 cleanup_cert_attr(cert_attr_t *attr)
325 {
326 	if (attr != NULL) {
327 		freezero(attr->value, attr->length);
328 		attr->value = NULL;
329 		attr->length = 0;
330 	}
331 }
332 
333 static CK_RV
copy_cert_attr(cert_attr_t * src_attr,cert_attr_t ** dest_attr)334 copy_cert_attr(cert_attr_t *src_attr, cert_attr_t **dest_attr)
335 {
336 	CK_RV rv = CKR_OK;
337 
338 	if (src_attr == NULL || dest_attr == NULL)
339 		return (CKR_HOST_MEMORY);
340 
341 	if (src_attr->value == NULL)
342 		return (CKR_HOST_MEMORY);
343 
344 	/* free memory if its already allocated */
345 	if (*dest_attr != NULL) {
346 		cleanup_cert_attr(*dest_attr);
347 	} else {
348 		*dest_attr = malloc(sizeof (cert_attr_t));
349 		if (*dest_attr == NULL)
350 			return (CKR_HOST_MEMORY);
351 	}
352 
353 	(*dest_attr)->value = NULL;
354 	(*dest_attr)->length = 0;
355 
356 	if (src_attr->length) {
357 		(*dest_attr)->value = malloc(src_attr->length);
358 		if ((*dest_attr)->value == NULL) {
359 			free(*dest_attr);
360 			return (CKR_HOST_MEMORY);
361 		}
362 
363 		(void) memcpy((*dest_attr)->value, src_attr->value,
364 		    src_attr->length);
365 		(*dest_attr)->length = src_attr->length;
366 	}
367 
368 	return (rv);
369 }
370 
371 void
soft_cleanup_cert_object(soft_object_t * object_p)372 soft_cleanup_cert_object(soft_object_t *object_p)
373 {
374 	CK_CERTIFICATE_TYPE certtype = object_p->cert_type;
375 
376 	if (object_p->class != CKO_CERTIFICATE ||
377 	    OBJ_CERT(object_p) == NULL)
378 		return;
379 
380 	if (certtype == CKC_X_509) {
381 		if (X509_CERT_SUBJECT(object_p) != NULL) {
382 			cleanup_cert_attr(X509_CERT_SUBJECT(object_p));
383 			free(X509_CERT_SUBJECT(object_p));
384 			X509_CERT_SUBJECT(object_p) = NULL;
385 		}
386 		if (X509_CERT_VALUE(object_p) != NULL) {
387 			cleanup_cert_attr(X509_CERT_VALUE(object_p));
388 			free(X509_CERT_VALUE(object_p));
389 			X509_CERT_VALUE(object_p) = NULL;
390 		}
391 		free(OBJ_CERT(object_p));
392 	} else if (certtype == CKC_X_509_ATTR_CERT) {
393 		if (X509_ATTR_CERT_VALUE(object_p) != NULL) {
394 			cleanup_cert_attr(X509_ATTR_CERT_VALUE(object_p));
395 			free(X509_ATTR_CERT_VALUE(object_p));
396 			X509_ATTR_CERT_VALUE(object_p) = NULL;
397 		}
398 		if (X509_ATTR_CERT_OWNER(object_p) != NULL) {
399 			cleanup_cert_attr(X509_ATTR_CERT_OWNER(object_p));
400 			free(X509_ATTR_CERT_OWNER(object_p));
401 			X509_ATTR_CERT_OWNER(object_p) = NULL;
402 		}
403 		free(OBJ_CERT(object_p));
404 	}
405 }
406 
407 /*
408  * Clean up and release all the storage in the extra attribute list
409  * of an object.
410  */
411 void
soft_cleanup_extra_attr(soft_object_t * object_p)412 soft_cleanup_extra_attr(soft_object_t *object_p)
413 {
414 
415 	CK_ATTRIBUTE_INFO_PTR extra_attr;
416 	CK_ATTRIBUTE_INFO_PTR tmp;
417 
418 	extra_attr = object_p->extra_attrlistp;
419 	while (extra_attr) {
420 		tmp = extra_attr->next;
421 		if (extra_attr->attr.pValue != NULL) {
422 			/*
423 			 * All extra attributes in the extra attribute
424 			 * list have pValue points to the value of the
425 			 * attribute (with simple byte array type).
426 			 * Free the storage for the value of the attribute.
427 			 */
428 			freezero(extra_attr->attr.pValue,
429 			    extra_attr->attr.ulValueLen);
430 		}
431 
432 		/* Free the storage for the attribute_info struct. */
433 		free(extra_attr);
434 		extra_attr = tmp;
435 	}
436 
437 	object_p->extra_attrlistp = NULL;
438 }
439 
440 
441 /*
442  * Create the attribute_info struct to hold the object's attribute,
443  * and add it to the extra attribute list of an object.
444  */
445 CK_RV
soft_add_extra_attr(CK_ATTRIBUTE_PTR template,soft_object_t * object_p)446 soft_add_extra_attr(CK_ATTRIBUTE_PTR template, soft_object_t *object_p)
447 {
448 
449 	CK_ATTRIBUTE_INFO_PTR attrp;
450 
451 	/* Allocate the storage for the attribute_info struct. */
452 	attrp = calloc(1, sizeof (attribute_info_t));
453 	if (attrp == NULL) {
454 		return (CKR_HOST_MEMORY);
455 	}
456 
457 	/* Set up attribute_info struct. */
458 	attrp->attr.type = template->type;
459 	attrp->attr.ulValueLen = template->ulValueLen;
460 
461 	if ((template->pValue != NULL) &&
462 	    (template->ulValueLen > 0)) {
463 		/* Allocate storage for the value of the attribute. */
464 		attrp->attr.pValue = malloc(template->ulValueLen);
465 		if (attrp->attr.pValue == NULL) {
466 			free(attrp);
467 			return (CKR_HOST_MEMORY);
468 		}
469 
470 		(void) memcpy(attrp->attr.pValue, template->pValue,
471 		    template->ulValueLen);
472 	} else {
473 		attrp->attr.pValue = NULL;
474 	}
475 
476 	/* Insert the new attribute in front of extra attribute list. */
477 	if (object_p->extra_attrlistp == NULL) {
478 		object_p->extra_attrlistp = attrp;
479 		attrp->next = NULL;
480 	} else {
481 		attrp->next = object_p->extra_attrlistp;
482 		object_p->extra_attrlistp = attrp;
483 	}
484 
485 	return (CKR_OK);
486 }
487 
488 CK_RV
soft_copy_certificate(certificate_obj_t * oldcert,certificate_obj_t ** newcert,CK_CERTIFICATE_TYPE type)489 soft_copy_certificate(certificate_obj_t *oldcert, certificate_obj_t **newcert,
490     CK_CERTIFICATE_TYPE type)
491 {
492 	CK_RV rv = CKR_OK;
493 	certificate_obj_t	*cert;
494 	x509_cert_t		x509;
495 	x509_attr_cert_t	x509_attr;
496 
497 	cert = calloc(1, sizeof (certificate_obj_t));
498 	if (cert == NULL) {
499 		return (CKR_HOST_MEMORY);
500 	}
501 
502 	if (type == CKC_X_509) {
503 		x509 = oldcert->cert_type_u.x509;
504 		if (x509.subject)
505 			if ((rv = copy_cert_attr(x509.subject,
506 			    &cert->cert_type_u.x509.subject)))
507 				return (rv);
508 		if (x509.value)
509 			if ((rv = copy_cert_attr(x509.value,
510 			    &cert->cert_type_u.x509.value)))
511 				return (rv);
512 	} else if (type == CKC_X_509_ATTR_CERT) {
513 		x509_attr = oldcert->cert_type_u.x509_attr;
514 		if (x509_attr.owner)
515 			if ((rv = copy_cert_attr(x509_attr.owner,
516 			    &cert->cert_type_u.x509_attr.owner)))
517 				return (rv);
518 		if (x509_attr.value)
519 			if ((rv = copy_cert_attr(x509_attr.value,
520 			    &cert->cert_type_u.x509_attr.value)))
521 				return (rv);
522 	} else {
523 		/* wrong certificate type */
524 		rv = CKR_ATTRIBUTE_TYPE_INVALID;
525 	}
526 	if (rv == CKR_OK)
527 		*newcert = cert;
528 	return (rv);
529 }
530 
531 /*
532  * Copy the attribute_info struct from the old object to a new attribute_info
533  * struct, and add that new struct to the extra attribute list of the new
534  * object.
535  */
536 CK_RV
soft_copy_extra_attr(CK_ATTRIBUTE_INFO_PTR old_attrp,soft_object_t * object_p)537 soft_copy_extra_attr(CK_ATTRIBUTE_INFO_PTR old_attrp, soft_object_t *object_p)
538 {
539 	CK_ATTRIBUTE_INFO_PTR attrp;
540 
541 	/* Allocate attribute_info struct. */
542 	attrp = calloc(1, sizeof (attribute_info_t));
543 	if (attrp == NULL) {
544 		return (CKR_HOST_MEMORY);
545 	}
546 
547 	attrp->attr.type = old_attrp->attr.type;
548 	attrp->attr.ulValueLen = old_attrp->attr.ulValueLen;
549 
550 	if ((old_attrp->attr.pValue != NULL) &&
551 	    (old_attrp->attr.ulValueLen > 0)) {
552 		attrp->attr.pValue = malloc(old_attrp->attr.ulValueLen);
553 		if (attrp->attr.pValue == NULL) {
554 			free(attrp);
555 			return (CKR_HOST_MEMORY);
556 		}
557 
558 		(void) memcpy(attrp->attr.pValue, old_attrp->attr.pValue,
559 		    old_attrp->attr.ulValueLen);
560 	} else {
561 		attrp->attr.pValue = NULL;
562 	}
563 
564 	/* Insert the new attribute in front of extra attribute list */
565 	if (object_p->extra_attrlistp == NULL) {
566 		object_p->extra_attrlistp = attrp;
567 		attrp->next = NULL;
568 	} else {
569 		attrp->next = object_p->extra_attrlistp;
570 		object_p->extra_attrlistp = attrp;
571 	}
572 
573 	return (CKR_OK);
574 }
575 
576 
577 /*
578  * Get the attribute triple from the extra attribute list in the object
579  * (if the specified attribute type is found), and copy it to a template.
580  * Note the type of the attribute to be copied is specified by the template,
581  * and the storage is pre-allocated for the atrribute value in the template
582  * for doing the copy.
583  */
584 CK_RV
get_extra_attr_from_object(soft_object_t * object_p,CK_ATTRIBUTE_PTR template)585 get_extra_attr_from_object(soft_object_t *object_p, CK_ATTRIBUTE_PTR template)
586 {
587 
588 	CK_ATTRIBUTE_INFO_PTR extra_attr;
589 	CK_ATTRIBUTE_TYPE type = template->type;
590 
591 	extra_attr = object_p->extra_attrlistp;
592 
593 	while (extra_attr) {
594 		if (type == extra_attr->attr.type) {
595 			/* Found it. */
596 			break;
597 		} else {
598 			/* Does not match, try next one. */
599 			extra_attr = extra_attr->next;
600 		}
601 	}
602 
603 	if (extra_attr == NULL) {
604 		/* A valid but un-initialized attribute. */
605 		template->ulValueLen = 0;
606 		return (CKR_OK);
607 	}
608 
609 	/*
610 	 * We found the attribute in the extra attribute list.
611 	 */
612 	if (template->pValue == NULL) {
613 		template->ulValueLen = extra_attr->attr.ulValueLen;
614 		return (CKR_OK);
615 	}
616 
617 	if (template->ulValueLen >= extra_attr->attr.ulValueLen) {
618 		/*
619 		 * The buffer provided by the application is large
620 		 * enough to hold the value of the attribute.
621 		 */
622 		(void) memcpy(template->pValue, extra_attr->attr.pValue,
623 		    extra_attr->attr.ulValueLen);
624 		template->ulValueLen = extra_attr->attr.ulValueLen;
625 		return (CKR_OK);
626 	} else {
627 		/*
628 		 * The buffer provided by the application does
629 		 * not have enough space to hold the value.
630 		 */
631 		template->ulValueLen = (CK_ULONG)-1;
632 		return (CKR_BUFFER_TOO_SMALL);
633 	}
634 }
635 
636 
637 /*
638  * Modify the attribute triple in the extra attribute list of the object
639  * if the specified attribute type is found. Otherwise, just add it to
640  * list.
641  */
642 CK_RV
set_extra_attr_to_object(soft_object_t * object_p,CK_ATTRIBUTE_TYPE type,CK_ATTRIBUTE_PTR template)643 set_extra_attr_to_object(soft_object_t *object_p, CK_ATTRIBUTE_TYPE type,
644     CK_ATTRIBUTE_PTR template)
645 {
646 
647 	CK_ATTRIBUTE_INFO_PTR extra_attr;
648 
649 	extra_attr = object_p->extra_attrlistp;
650 
651 	while (extra_attr) {
652 		if (type == extra_attr->attr.type) {
653 			/* Found it. */
654 			break;
655 		} else {
656 			/* Does not match, try next one. */
657 			extra_attr = extra_attr->next;
658 		}
659 	}
660 
661 	if (extra_attr == NULL) {
662 		/*
663 		 * This attribute is a new one, go ahead adding it to
664 		 * the extra attribute list.
665 		 */
666 		return (soft_add_extra_attr(template, object_p));
667 	}
668 
669 	/* We found the attribute in the extra attribute list. */
670 	if ((template->pValue != NULL) &&
671 	    (template->ulValueLen > 0)) {
672 		if (template->ulValueLen > extra_attr->attr.ulValueLen) {
673 			/* The old buffer is too small to hold the new value. */
674 			if (extra_attr->attr.pValue != NULL) {
675 				/* Free storage for the old attribute value. */
676 				freezero(extra_attr->attr.pValue,
677 				    extra_attr->attr.ulValueLen);
678 			}
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
get_bigint_attr_from_template(biginteger_t * big,CK_ATTRIBUTE_PTR template)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
get_bigint_attr_from_object(biginteger_t * big,CK_ATTRIBUTE_PTR template)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
get_bool_attr_from_object(soft_object_t * object_p,CK_ULONG bool_flag,CK_ATTRIBUTE_PTR template)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
set_bool_attr_to_object(soft_object_t * object_p,CK_ULONG bool_flag,CK_ATTRIBUTE_PTR template)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
get_ulong_attr_from_object(CK_ULONG value,CK_ATTRIBUTE_PTR template)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 static CK_RV
get_ulong_attr_from_template(CK_ULONG * value,CK_ATTRIBUTE_PTR template)856 get_ulong_attr_from_template(CK_ULONG *value, CK_ATTRIBUTE_PTR template)
857 {
858 
859 	if (template->ulValueLen < sizeof (CK_ULONG))
860 		return (CKR_ATTRIBUTE_VALUE_INVALID);
861 
862 	if (template->pValue != NULL) {
863 		*value = *(CK_ULONG_PTR)template->pValue;
864 	} else {
865 		*value = 0;
866 	}
867 
868 	return (CKR_OK);
869 }
870 
871 /*
872  * Copy the big integer attribute value from source's biginteger_t to
873  * destination's biginteger_t.
874  */
875 void
copy_bigint_attr(biginteger_t * src,biginteger_t * dst)876 copy_bigint_attr(biginteger_t *src, biginteger_t *dst)
877 {
878 
879 	if ((src->big_value != NULL) &&
880 	    (src->big_value_len > 0)) {
881 		/*
882 		 * To do the copy, just have dst's big_value points
883 		 * to src's.
884 		 */
885 		dst->big_value = src->big_value;
886 		dst->big_value_len = src->big_value_len;
887 
888 		/*
889 		 * After the copy, nullify the src's big_value pointer.
890 		 * It prevents any double freeing the value.
891 		 */
892 		src->big_value = NULL;
893 		src->big_value_len = 0;
894 	} else {
895 		dst->big_value = NULL;
896 		dst->big_value_len = 0;
897 	}
898 }
899 
900 CK_RV
get_string_from_template(CK_ATTRIBUTE_PTR dest,CK_ATTRIBUTE_PTR src)901 get_string_from_template(CK_ATTRIBUTE_PTR dest, CK_ATTRIBUTE_PTR src)
902 {
903 	if ((src->pValue != NULL) &&
904 	    (src->ulValueLen > 0)) {
905 		/* Allocate storage for the value of the attribute. */
906 		dest->pValue = malloc(src->ulValueLen);
907 		if (dest->pValue == NULL) {
908 			return (CKR_HOST_MEMORY);
909 		}
910 
911 		(void) memcpy(dest->pValue, src->pValue,
912 		    src->ulValueLen);
913 		dest->ulValueLen = src->ulValueLen;
914 		dest->type = src->type;
915 	} else {
916 		dest->pValue = NULL;
917 		dest->ulValueLen = 0;
918 		dest->type = src->type;
919 	}
920 
921 	return (CKR_OK);
922 
923 }
924 
925 CK_RV
get_cert_attr_from_template(cert_attr_t ** dest,CK_ATTRIBUTE_PTR src)926 get_cert_attr_from_template(cert_attr_t **dest, CK_ATTRIBUTE_PTR src)
927 {
928 	if (src->pValue != NULL && src->ulValueLen > 0) {
929 		/*
930 		 * If the attribute was already set, clear out the
931 		 * existing value and release the memory.
932 		 */
933 		if (*dest != NULL) {
934 			cleanup_cert_attr(*dest);
935 		} else {
936 			*dest = malloc(sizeof (cert_attr_t));
937 			if (*dest == NULL) {
938 				return (CKR_HOST_MEMORY);
939 			}
940 			(void) memset(*dest, 0, sizeof (cert_attr_t));
941 		}
942 		(*dest)->value = malloc(src->ulValueLen);
943 		if ((*dest)->value == NULL) {
944 			free(*dest);
945 			*dest = NULL;
946 			return (CKR_HOST_MEMORY);
947 		}
948 		(void) memcpy((*dest)->value, src->pValue, src->ulValueLen);
949 		(*dest)->length = src->ulValueLen;
950 	}
951 
952 	return (CKR_OK);
953 }
954 
955 /*
956  * Copy the certificate attribute information to the template.
957  * If the template attribute is not big enough, set the ulValueLen=-1
958  * and return CKR_BUFFER_TOO_SMALL.
959  */
960 static CK_RV
get_cert_attr_from_object(cert_attr_t * src,CK_ATTRIBUTE_PTR template)961 get_cert_attr_from_object(cert_attr_t *src, CK_ATTRIBUTE_PTR template)
962 {
963 	if (template->pValue == NULL) {
964 		template->ulValueLen = src->length;
965 		return (CKR_OK);
966 	} else if (template->ulValueLen >= src->length) {
967 		/*
968 		 * The buffer provided by the application is large
969 		 * enough to hold the value of the attribute.
970 		 */
971 		(void) memcpy(template->pValue, src->value, src->length);
972 		template->ulValueLen = src->length;
973 		return (CKR_OK);
974 	} else {
975 		/*
976 		 * The buffer provided by the application does
977 		 * not have enough space to hold the value.
978 		 */
979 		template->ulValueLen = (CK_ULONG)-1;
980 		return (CKR_BUFFER_TOO_SMALL);
981 	}
982 }
983 
984 void
string_attr_cleanup(CK_ATTRIBUTE_PTR template)985 string_attr_cleanup(CK_ATTRIBUTE_PTR template)
986 {
987 	freezero(template->pValue, template->ulValueLen);
988 	template->pValue = NULL;
989 	template->ulValueLen = 0;
990 }
991 
992 /*
993  * Release the storage allocated for object attribute with big integer
994  * value.
995  */
996 void
bigint_attr_cleanup(biginteger_t * big)997 bigint_attr_cleanup(biginteger_t *big)
998 {
999 
1000 	if (big == NULL)
1001 		return;
1002 
1003 	freezero(big->big_value, big->big_value_len);
1004 	big->big_value = NULL;
1005 	big->big_value_len = 0;
1006 }
1007 
1008 
1009 /*
1010  * Clean up and release all the storage allocated to hold the big integer
1011  * attributes associated with the type (i.e. class) of the object. Also,
1012  * release the storage allocated to the type of the object.
1013  */
1014 void
soft_cleanup_object_bigint_attrs(soft_object_t * object_p)1015 soft_cleanup_object_bigint_attrs(soft_object_t *object_p)
1016 {
1017 
1018 	CK_OBJECT_CLASS class = object_p->class;
1019 	CK_KEY_TYPE	keytype = object_p->key_type;
1020 
1021 
1022 	switch (class) {
1023 	case CKO_PUBLIC_KEY:
1024 		if (OBJ_PUB(object_p)) {
1025 			switch (keytype) {
1026 			case CKK_RSA:
1027 				bigint_attr_cleanup(OBJ_PUB_RSA_MOD(
1028 				    object_p));
1029 				bigint_attr_cleanup(OBJ_PUB_RSA_PUBEXPO(
1030 				    object_p));
1031 				break;
1032 
1033 			case CKK_DSA:
1034 				bigint_attr_cleanup(OBJ_PUB_DSA_PRIME(
1035 				    object_p));
1036 				bigint_attr_cleanup(OBJ_PUB_DSA_SUBPRIME(
1037 				    object_p));
1038 				bigint_attr_cleanup(OBJ_PUB_DSA_BASE(
1039 				    object_p));
1040 				bigint_attr_cleanup(OBJ_PUB_DSA_VALUE(
1041 				    object_p));
1042 				break;
1043 
1044 			case CKK_DH:
1045 				bigint_attr_cleanup(OBJ_PUB_DH_PRIME(
1046 				    object_p));
1047 				bigint_attr_cleanup(OBJ_PUB_DH_BASE(
1048 				    object_p));
1049 				bigint_attr_cleanup(OBJ_PUB_DH_VALUE(
1050 				    object_p));
1051 				break;
1052 
1053 			case CKK_X9_42_DH:
1054 				bigint_attr_cleanup(OBJ_PUB_DH942_PRIME(
1055 				    object_p));
1056 				bigint_attr_cleanup(OBJ_PUB_DH942_BASE(
1057 				    object_p));
1058 				bigint_attr_cleanup(OBJ_PUB_DH942_SUBPRIME(
1059 				    object_p));
1060 				bigint_attr_cleanup(OBJ_PUB_DH942_VALUE(
1061 				    object_p));
1062 				break;
1063 			case CKK_EC:
1064 				bigint_attr_cleanup(OBJ_PUB_EC_POINT(
1065 				    object_p));
1066 				break;
1067 			}
1068 
1069 			/* Release Public Key Object struct */
1070 			free(OBJ_PUB(object_p));
1071 			OBJ_PUB(object_p) = NULL;
1072 		}
1073 		break;
1074 
1075 	case CKO_PRIVATE_KEY:
1076 		if (OBJ_PRI(object_p)) {
1077 			switch (keytype) {
1078 			case CKK_RSA:
1079 				bigint_attr_cleanup(OBJ_PRI_RSA_MOD(
1080 				    object_p));
1081 				bigint_attr_cleanup(OBJ_PRI_RSA_PUBEXPO(
1082 				    object_p));
1083 				bigint_attr_cleanup(OBJ_PRI_RSA_PRIEXPO(
1084 				    object_p));
1085 				bigint_attr_cleanup(OBJ_PRI_RSA_PRIME1(
1086 				    object_p));
1087 				bigint_attr_cleanup(OBJ_PRI_RSA_PRIME2(
1088 				    object_p));
1089 				bigint_attr_cleanup(OBJ_PRI_RSA_EXPO1(
1090 				    object_p));
1091 				bigint_attr_cleanup(OBJ_PRI_RSA_EXPO2(
1092 				    object_p));
1093 				bigint_attr_cleanup(OBJ_PRI_RSA_COEF(
1094 				    object_p));
1095 				break;
1096 
1097 			case CKK_DSA:
1098 				bigint_attr_cleanup(OBJ_PRI_DSA_PRIME(
1099 				    object_p));
1100 				bigint_attr_cleanup(OBJ_PRI_DSA_SUBPRIME(
1101 				    object_p));
1102 				bigint_attr_cleanup(OBJ_PRI_DSA_BASE(
1103 				    object_p));
1104 				bigint_attr_cleanup(OBJ_PRI_DSA_VALUE(
1105 				    object_p));
1106 				break;
1107 
1108 			case CKK_DH:
1109 				bigint_attr_cleanup(OBJ_PRI_DH_PRIME(
1110 				    object_p));
1111 				bigint_attr_cleanup(OBJ_PRI_DH_BASE(
1112 				    object_p));
1113 				bigint_attr_cleanup(OBJ_PRI_DH_VALUE(
1114 				    object_p));
1115 				break;
1116 
1117 			case CKK_X9_42_DH:
1118 				bigint_attr_cleanup(OBJ_PRI_DH942_PRIME(
1119 				    object_p));
1120 				bigint_attr_cleanup(OBJ_PRI_DH942_BASE(
1121 				    object_p));
1122 				bigint_attr_cleanup(OBJ_PRI_DH942_SUBPRIME(
1123 				    object_p));
1124 				bigint_attr_cleanup(OBJ_PRI_DH942_VALUE(
1125 				    object_p));
1126 				break;
1127 
1128 			case CKK_EC:
1129 				bigint_attr_cleanup(OBJ_PRI_EC_VALUE(
1130 				    object_p));
1131 				break;
1132 			}
1133 
1134 			/* Release Private Key Object struct. */
1135 			free(OBJ_PRI(object_p));
1136 			OBJ_PRI(object_p) = NULL;
1137 		}
1138 		break;
1139 
1140 	case CKO_SECRET_KEY:
1141 		if (OBJ_SEC(object_p)) {
1142 			/* cleanup key data area */
1143 			if (OBJ_SEC_VALUE(object_p) != NULL &&
1144 			    OBJ_SEC_VALUE_LEN(object_p) > 0) {
1145 				freezero(OBJ_SEC_VALUE(object_p),
1146 				    OBJ_SEC_VALUE_LEN(object_p));
1147 			}
1148 			/* cleanup key schedule data area */
1149 			if (OBJ_KEY_SCHED(object_p) != NULL &&
1150 			    OBJ_KEY_SCHED_LEN(object_p) > 0) {
1151 				freezero(OBJ_KEY_SCHED(object_p),
1152 				    OBJ_KEY_SCHED_LEN(object_p));
1153 			}
1154 
1155 			/* Release Secret Key Object struct. */
1156 			free(OBJ_SEC(object_p));
1157 			OBJ_SEC(object_p) = NULL;
1158 		}
1159 		break;
1160 
1161 	case CKO_DOMAIN_PARAMETERS:
1162 		if (OBJ_DOM(object_p)) {
1163 			switch (keytype) {
1164 			case CKK_DSA:
1165 				bigint_attr_cleanup(OBJ_DOM_DSA_PRIME(
1166 				    object_p));
1167 				bigint_attr_cleanup(OBJ_DOM_DSA_SUBPRIME(
1168 				    object_p));
1169 				bigint_attr_cleanup(OBJ_DOM_DSA_BASE(
1170 				    object_p));
1171 				break;
1172 
1173 			case CKK_DH:
1174 				bigint_attr_cleanup(OBJ_DOM_DH_PRIME(
1175 				    object_p));
1176 				bigint_attr_cleanup(OBJ_DOM_DH_BASE(
1177 				    object_p));
1178 				break;
1179 
1180 			case CKK_X9_42_DH:
1181 				bigint_attr_cleanup(OBJ_DOM_DH942_PRIME(
1182 				    object_p));
1183 				bigint_attr_cleanup(OBJ_DOM_DH942_BASE(
1184 				    object_p));
1185 				bigint_attr_cleanup(OBJ_DOM_DH942_SUBPRIME(
1186 				    object_p));
1187 				break;
1188 			}
1189 
1190 			/* Release Domain Parameters Object struct. */
1191 			free(OBJ_DOM(object_p));
1192 			OBJ_DOM(object_p) = NULL;
1193 		}
1194 		break;
1195 	}
1196 }
1197 
1198 
1199 /*
1200  * Parse the common attributes. Return to caller with appropriate return
1201  * value to indicate if the supplied template specifies a valid attribute
1202  * with a valid value.
1203  */
1204 CK_RV
soft_parse_common_attrs(CK_ATTRIBUTE_PTR template,uchar_t * object_type)1205 soft_parse_common_attrs(CK_ATTRIBUTE_PTR template, uchar_t *object_type)
1206 {
1207 
1208 	CK_RV rv = CKR_OK;
1209 
1210 	switch (template->type) {
1211 	case CKA_CLASS:
1212 		break;
1213 
1214 	/* default boolean attributes */
1215 	case CKA_TOKEN:
1216 		if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
1217 			if (!soft_keystore_status(KEYSTORE_INITIALIZED))
1218 				return (CKR_DEVICE_REMOVED);
1219 			*object_type |= TOKEN_OBJECT;
1220 		}
1221 		break;
1222 
1223 	case CKA_PRIVATE:
1224 		if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
1225 			(void) pthread_mutex_lock(&soft_giant_mutex);
1226 			if (!soft_slot.authenticated) {
1227 				/*
1228 				 * Check if this is the special case when
1229 				 * the PIN is never initialized in the keystore.
1230 				 * If true, we will let it pass here and let
1231 				 * it fail with CKR_PIN_EXPIRED later on.
1232 				 */
1233 				if (!soft_slot.userpin_change_needed) {
1234 					(void) pthread_mutex_unlock(
1235 					    &soft_giant_mutex);
1236 					return (CKR_USER_NOT_LOGGED_IN);
1237 				}
1238 			}
1239 			(void) pthread_mutex_unlock(&soft_giant_mutex);
1240 			*object_type |= PRIVATE_OBJECT;
1241 		}
1242 		break;
1243 
1244 	case CKA_LABEL:
1245 		break;
1246 
1247 	default:
1248 		rv = CKR_TEMPLATE_INCONSISTENT;
1249 	}
1250 
1251 	return (rv);
1252 }
1253 
1254 
1255 /*
1256  * Build a Public Key Object.
1257  *
1258  * - Parse the object's template, and when an error is detected such as
1259  *   invalid attribute type, invalid attribute value, etc., return
1260  *   with appropriate return value.
1261  * - Set up attribute mask field in the object for the supplied common
1262  *   attributes that have boolean type.
1263  * - Build the attribute_info struct to hold the value of each supplied
1264  *   attribute that has byte array type. Link attribute_info structs
1265  *   together to form the extra attribute list of the object.
1266  * - Allocate storage for the Public Key object.
1267  * - Build the Public Key object according to the key type. Allocate
1268  *   storage to hold the big integer value for the supplied attributes
1269  *   that are required for a certain key type.
1270  *
1271  */
1272 CK_RV
soft_build_public_key_object(CK_ATTRIBUTE_PTR template,CK_ULONG ulAttrNum,soft_object_t * new_object,CK_ULONG mode,CK_KEY_TYPE key_type)1273 soft_build_public_key_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
1274     soft_object_t *new_object, CK_ULONG mode, CK_KEY_TYPE key_type)
1275 {
1276 
1277 	ulong_t		i;
1278 	CK_KEY_TYPE	keytype = (CK_KEY_TYPE)~0UL;
1279 	uint64_t	attr_mask = PUBLIC_KEY_DEFAULT;
1280 	CK_RV		rv = CKR_OK;
1281 	int		isLabel = 0;
1282 	/* Must set flags */
1283 	int		isModulus = 0;
1284 	int		isPubExpo = 0;
1285 	int		isPrime = 0;
1286 	int		isSubprime = 0;
1287 	int		isBase = 0;
1288 	int		isValue = 0;
1289 	int		isECParam = 0;
1290 	int		isECPoint = 0;
1291 	/* Must not set flags */
1292 	int		isModulusBits = 0;
1293 	CK_ULONG	modulus_bits = 0;
1294 
1295 	biginteger_t	modulus;
1296 	biginteger_t	pubexpo;
1297 	biginteger_t	prime;
1298 	biginteger_t	subprime;
1299 	biginteger_t	base;
1300 	biginteger_t	value;
1301 	biginteger_t	point;
1302 	CK_ATTRIBUTE	string_tmp;
1303 	CK_ATTRIBUTE	param_tmp;
1304 
1305 	public_key_obj_t  *pbk;
1306 	uchar_t	object_type = 0;
1307 
1308 	CK_ATTRIBUTE	defpubexpo = { CKA_PUBLIC_EXPONENT,
1309 	    (CK_BYTE_PTR)DEFAULT_PUB_EXPO, DEFAULT_PUB_EXPO_Len };
1310 
1311 	BIGNUM		n;
1312 
1313 	/* prevent bigint_attr_cleanup from freeing invalid attr value */
1314 	(void) memset(&modulus, 0x0, sizeof (biginteger_t));
1315 	(void) memset(&pubexpo, 0x0, sizeof (biginteger_t));
1316 	(void) memset(&prime, 0x0, sizeof (biginteger_t));
1317 	(void) memset(&subprime, 0x0, sizeof (biginteger_t));
1318 	(void) memset(&base, 0x0, sizeof (biginteger_t));
1319 	(void) memset(&value, 0x0, sizeof (biginteger_t));
1320 	(void) memset(&point, 0x0, sizeof (biginteger_t));
1321 	string_tmp.pValue = NULL;
1322 	param_tmp.pValue = NULL;
1323 
1324 	for (i = 0; i < ulAttrNum; i++) {
1325 
1326 		/* Public Key Object Attributes */
1327 		switch (template[i].type) {
1328 
1329 		/* common key attributes */
1330 		case CKA_KEY_TYPE:
1331 			keytype = *((CK_KEY_TYPE*)template[i].pValue);
1332 			break;
1333 
1334 		case CKA_ID:
1335 		case CKA_START_DATE:
1336 		case CKA_END_DATE:
1337 
1338 		/* common public key attribute */
1339 		case CKA_SUBJECT:
1340 			/*
1341 			 * Allocate storage to hold the attribute
1342 			 * value with byte array type, and add it to
1343 			 * the extra attribute list of the object.
1344 			 */
1345 			rv = soft_add_extra_attr(&template[i],
1346 			    new_object);
1347 			if (rv != CKR_OK) {
1348 				goto fail_cleanup;
1349 			}
1350 			break;
1351 
1352 		/*
1353 		 * The following key related attribute types must
1354 		 * not be specified by C_CreateObject, C_GenerateKey(Pair).
1355 		 */
1356 		case CKA_LOCAL:
1357 		case CKA_KEY_GEN_MECHANISM:
1358 			rv = CKR_TEMPLATE_INCONSISTENT;
1359 			goto fail_cleanup;
1360 
1361 		/* Key related boolean attributes */
1362 		case CKA_DERIVE:
1363 			if (*(CK_BBOOL *)template[i].pValue)
1364 				attr_mask |= DERIVE_BOOL_ON;
1365 			break;
1366 
1367 		case CKA_ENCRYPT:
1368 			if (*(CK_BBOOL *)template[i].pValue)
1369 				attr_mask |= ENCRYPT_BOOL_ON;
1370 			else
1371 				attr_mask &= ~ENCRYPT_BOOL_ON;
1372 			break;
1373 
1374 		case CKA_VERIFY:
1375 			if (*(CK_BBOOL *)template[i].pValue)
1376 				attr_mask |= VERIFY_BOOL_ON;
1377 			else
1378 				attr_mask &= ~VERIFY_BOOL_ON;
1379 			break;
1380 
1381 		case CKA_VERIFY_RECOVER:
1382 			if (*(CK_BBOOL *)template[i].pValue)
1383 				attr_mask |= VERIFY_RECOVER_BOOL_ON;
1384 			else
1385 				attr_mask &= ~VERIFY_RECOVER_BOOL_ON;
1386 			break;
1387 
1388 		case CKA_WRAP:
1389 			if (*(CK_BBOOL *)template[i].pValue)
1390 				attr_mask |= WRAP_BOOL_ON;
1391 			else
1392 				attr_mask &= ~WRAP_BOOL_ON;
1393 			break;
1394 
1395 		case CKA_TRUSTED:
1396 			if (*(CK_BBOOL *)template[i].pValue)
1397 				attr_mask |= TRUSTED_BOOL_ON;
1398 			break;
1399 
1400 		case CKA_MODIFIABLE:
1401 			if ((*(CK_BBOOL *)template[i].pValue) == B_FALSE)
1402 				attr_mask |= NOT_MODIFIABLE_BOOL_ON;
1403 			break;
1404 
1405 		/*
1406 		 * The following key related attribute types must
1407 		 * be specified according to the key type by
1408 		 * C_CreateObject.
1409 		 */
1410 		case CKA_MODULUS:
1411 
1412 			isModulus = 1;
1413 			/*
1414 			 * Copyin big integer attribute from template
1415 			 * to a local variable.
1416 			 */
1417 			rv = get_bigint_attr_from_template(&modulus,
1418 			    &template[i]);
1419 			if (rv != CKR_OK)
1420 				goto fail_cleanup;
1421 
1422 			/*
1423 			 * Modulus length needs to be between min key length and
1424 			 * max key length.
1425 			 */
1426 			if ((modulus.big_value_len <
1427 			    MIN_RSA_KEYLENGTH_IN_BYTES) ||
1428 			    (modulus.big_value_len >
1429 			    MAX_RSA_KEYLENGTH_IN_BYTES)) {
1430 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
1431 				goto fail_cleanup;
1432 			}
1433 			break;
1434 
1435 		case CKA_PUBLIC_EXPONENT:
1436 			isPubExpo = 1;
1437 			rv = get_bigint_attr_from_template(&pubexpo,
1438 			    &template[i]);
1439 			if (rv != CKR_OK)
1440 				goto fail_cleanup;
1441 			break;
1442 
1443 		case CKA_PRIME:
1444 			isPrime = 1;
1445 			rv = get_bigint_attr_from_template(&prime,
1446 			    &template[i]);
1447 			if (rv != CKR_OK)
1448 				goto fail_cleanup;
1449 			break;
1450 
1451 		case CKA_SUBPRIME:
1452 			isSubprime = 1;
1453 			rv = get_bigint_attr_from_template(&subprime,
1454 			    &template[i]);
1455 			if (rv != CKR_OK)
1456 				goto fail_cleanup;
1457 			break;
1458 
1459 		case CKA_BASE:
1460 			isBase = 1;
1461 			rv = get_bigint_attr_from_template(&base,
1462 			    &template[i]);
1463 			if (rv != CKR_OK)
1464 				goto fail_cleanup;
1465 			break;
1466 
1467 		case CKA_VALUE:
1468 			isValue = 1;
1469 			if (mode == SOFT_CREATE_OBJ) {
1470 				if ((template[i].ulValueLen == 0) ||
1471 				    (template[i].pValue == NULL)) {
1472 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
1473 					goto fail_cleanup;
1474 				}
1475 			}
1476 
1477 			rv = get_bigint_attr_from_template(&value,
1478 			    &template[i]);
1479 			if (rv != CKR_OK)
1480 				goto fail_cleanup;
1481 			break;
1482 
1483 		case CKA_MODULUS_BITS:
1484 			isModulusBits = 1;
1485 			rv = get_ulong_attr_from_template(&modulus_bits,
1486 			    &template[i]);
1487 			if (rv != CKR_OK)
1488 				goto fail_cleanup;
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 				 * Derive modulus_bits attribute from modulus.
1567 				 * Save modulus_bits integer value to the
1568 				 * designated place in the public key object.
1569 				 */
1570 				n.malloced = 0;
1571 #ifdef  __sparcv9
1572 				if (big_init(&n, (int)CHARLEN2BIGNUMLEN(
1573 				    modulus.big_value_len)) != BIG_OK) {
1574 #else   /* !__sparcv9 */
1575 				if (big_init(&n, CHARLEN2BIGNUMLEN(
1576 				    modulus.big_value_len)) != BIG_OK) {
1577 #endif  /* __sparcv9 */
1578 					rv = CKR_HOST_MEMORY;
1579 					big_finish(&n);
1580 					goto fail_cleanup;
1581 				}
1582 				bytestring2bignum(&n, modulus.big_value,
1583 				    modulus.big_value_len);
1584 
1585 				modulus_bits = big_bitlength(&n);
1586 				KEY_PUB_RSA_MOD_BITS(pbk) = modulus_bits;
1587 				big_finish(&n);
1588 
1589 				/*
1590 				 * After modulus_bits has been computed,
1591 				 * it is safe to move modulus and pubexpo
1592 				 * big integer attribute value to the
1593 				 * designated place in the public key object.
1594 				 */
1595 				copy_bigint_attr(&modulus,
1596 				    KEY_PUB_RSA_MOD(pbk));
1597 
1598 				copy_bigint_attr(&pubexpo,
1599 				    KEY_PUB_RSA_PUBEXPO(pbk));
1600 			} else {
1601 				rv = CKR_TEMPLATE_INCOMPLETE;
1602 				goto fail_cleanup;
1603 			}
1604 		} else {
1605 			/* mode is SOFT_GEN_KEY */
1606 
1607 			if (isModulus || isPrime || isSubprime ||
1608 			    isBase || isValue) {
1609 				rv = CKR_TEMPLATE_INCONSISTENT;
1610 				goto fail_cleanup;
1611 			}
1612 
1613 
1614 			if (isModulusBits) {
1615 				/*
1616 				 * Copy big integer attribute value to the
1617 				 * designated place in the public key object.
1618 				 */
1619 				KEY_PUB_RSA_MOD_BITS(pbk) = modulus_bits;
1620 			} else {
1621 				rv = CKR_TEMPLATE_INCOMPLETE;
1622 				goto fail_cleanup;
1623 			}
1624 
1625 			/*
1626 			 * Use PKCS#11 default 0x010001 for public exponent
1627 			 * if not not specified in attribute template.
1628 			 */
1629 			if (!isPubExpo) {
1630 				isPubExpo = 1;
1631 				rv = get_bigint_attr_from_template(&pubexpo,
1632 				    &defpubexpo);
1633 				if (rv != CKR_OK)
1634 					goto fail_cleanup;
1635 			}
1636 			/*
1637 			 * Copy big integer attribute value to the
1638 			 * designated place in the public key object.
1639 			 */
1640 			copy_bigint_attr(&pubexpo, KEY_PUB_RSA_PUBEXPO(pbk));
1641 		}
1642 
1643 		break;
1644 
1645 	case CKK_DSA:
1646 		if (mode == SOFT_CREATE_OBJ) {
1647 			if (isModulusBits || isModulus || isPubExpo) {
1648 				rv = CKR_TEMPLATE_INCONSISTENT;
1649 				goto fail_cleanup;
1650 			}
1651 
1652 			if (isPrime && isSubprime && isBase && isValue) {
1653 				copy_bigint_attr(&value,
1654 				    KEY_PUB_DSA_VALUE(pbk));
1655 			} else {
1656 				rv = CKR_TEMPLATE_INCOMPLETE;
1657 				goto fail_cleanup;
1658 			}
1659 		} else {
1660 			if (isModulusBits || isModulus || isPubExpo ||
1661 			    isValue) {
1662 				rv = CKR_TEMPLATE_INCONSISTENT;
1663 				goto fail_cleanup;
1664 			}
1665 
1666 			if (!(isPrime && isSubprime && isBase)) {
1667 				rv = CKR_TEMPLATE_INCOMPLETE;
1668 				goto fail_cleanup;
1669 			}
1670 		}
1671 
1672 		copy_bigint_attr(&prime, KEY_PUB_DSA_PRIME(pbk));
1673 
1674 		copy_bigint_attr(&subprime, KEY_PUB_DSA_SUBPRIME(pbk));
1675 
1676 		copy_bigint_attr(&base, KEY_PUB_DSA_BASE(pbk));
1677 
1678 		break;
1679 
1680 	case CKK_DH:
1681 		if (mode == SOFT_CREATE_OBJ) {
1682 			if (isModulusBits || isModulus || isPubExpo ||
1683 			    isSubprime) {
1684 				rv = CKR_TEMPLATE_INCONSISTENT;
1685 				goto fail_cleanup;
1686 			}
1687 
1688 			if (isPrime && isBase && isValue) {
1689 				copy_bigint_attr(&value,
1690 				    KEY_PUB_DH_VALUE(pbk));
1691 			} else {
1692 				rv = CKR_TEMPLATE_INCOMPLETE;
1693 				goto fail_cleanup;
1694 			}
1695 		} else {
1696 			if (isModulusBits || isModulus || isPubExpo ||
1697 			    isSubprime || isValue) {
1698 				rv = CKR_TEMPLATE_INCONSISTENT;
1699 				goto fail_cleanup;
1700 			}
1701 
1702 			if (!(isPrime && isBase)) {
1703 				rv = CKR_TEMPLATE_INCOMPLETE;
1704 				goto fail_cleanup;
1705 			}
1706 		}
1707 
1708 		copy_bigint_attr(&prime, KEY_PUB_DH_PRIME(pbk));
1709 
1710 		copy_bigint_attr(&base, KEY_PUB_DH_BASE(pbk));
1711 
1712 		break;
1713 
1714 	case CKK_X9_42_DH:
1715 		if (mode == SOFT_CREATE_OBJ) {
1716 			if (isModulusBits || isModulus || isPubExpo) {
1717 				rv = CKR_TEMPLATE_INCONSISTENT;
1718 				goto fail_cleanup;
1719 			}
1720 
1721 			if (isPrime && isSubprime && isBase && isValue) {
1722 				copy_bigint_attr(&value,
1723 				    KEY_PUB_DH942_VALUE(pbk));
1724 			} else {
1725 				rv = CKR_TEMPLATE_INCOMPLETE;
1726 				goto fail_cleanup;
1727 			}
1728 		} else {
1729 			if (isModulusBits || isModulus || isPubExpo ||
1730 			    isValue) {
1731 				rv = CKR_TEMPLATE_INCONSISTENT;
1732 				goto fail_cleanup;
1733 			}
1734 
1735 			if (!(isPrime && isSubprime && isBase)) {
1736 				rv = CKR_TEMPLATE_INCOMPLETE;
1737 				goto fail_cleanup;
1738 			}
1739 		}
1740 
1741 		copy_bigint_attr(&prime, KEY_PUB_DH942_PRIME(pbk));
1742 
1743 		copy_bigint_attr(&base, KEY_PUB_DH942_BASE(pbk));
1744 
1745 		copy_bigint_attr(&subprime, KEY_PUB_DH942_SUBPRIME(pbk));
1746 
1747 		break;
1748 
1749 	case CKK_EC:
1750 		if (mode == SOFT_CREATE_OBJ) {
1751 			if (isModulusBits || isModulus || isPubExpo ||
1752 			    isPrime || isSubprime || isBase || isValue) {
1753 				rv = CKR_TEMPLATE_INCONSISTENT;
1754 				goto fail_cleanup;
1755 
1756 			} else if (!isECParam || !isECPoint) {
1757 				rv = CKR_TEMPLATE_INCOMPLETE;
1758 				goto fail_cleanup;
1759 			}
1760 		} else {
1761 			if (isModulusBits || isModulus || isPubExpo ||
1762 			    isPrime || isSubprime || isBase || isValue) {
1763 				rv = CKR_TEMPLATE_INCONSISTENT;
1764 				goto fail_cleanup;
1765 
1766 			} else if (!isECParam) {
1767 				rv = CKR_TEMPLATE_INCOMPLETE;
1768 				goto fail_cleanup;
1769 			}
1770 		}
1771 
1772 		if (isECPoint) {
1773 			copy_bigint_attr(&point, KEY_PUB_EC_POINT(pbk));
1774 		}
1775 		rv = soft_add_extra_attr(&param_tmp, new_object);
1776 		if (rv != CKR_OK)
1777 			goto fail_cleanup;
1778 		string_attr_cleanup(&param_tmp);
1779 		break;
1780 
1781 	default:
1782 		rv = CKR_TEMPLATE_INCONSISTENT;
1783 		goto fail_cleanup;
1784 	}
1785 
1786 	/* Set up object. */
1787 	new_object->object_type = object_type;
1788 	new_object->bool_attr_mask = attr_mask;
1789 	if (isLabel) {
1790 		rv = soft_add_extra_attr(&string_tmp, new_object);
1791 		if (rv != CKR_OK)
1792 			goto fail_cleanup;
1793 		string_attr_cleanup(&string_tmp);
1794 	}
1795 
1796 	return (rv);
1797 
1798 fail_cleanup:
1799 	/*
1800 	 * cleanup the storage allocated to the local variables.
1801 	 */
1802 	bigint_attr_cleanup(&modulus);
1803 	bigint_attr_cleanup(&pubexpo);
1804 	bigint_attr_cleanup(&prime);
1805 	bigint_attr_cleanup(&subprime);
1806 	bigint_attr_cleanup(&base);
1807 	bigint_attr_cleanup(&value);
1808 	bigint_attr_cleanup(&point);
1809 	string_attr_cleanup(&string_tmp);
1810 	string_attr_cleanup(&param_tmp);
1811 
1812 	/*
1813 	 * cleanup the storage allocated inside the object itself.
1814 	 */
1815 	soft_cleanup_object(new_object);
1816 
1817 	return (rv);
1818 }
1819 
1820 
1821 /*
1822  * Build a Private Key Object.
1823  *
1824  * - Parse the object's template, and when an error is detected such as
1825  *   invalid attribute type, invalid attribute value, etc., return
1826  *   with appropriate return value.
1827  * - Set up attribute mask field in the object for the supplied common
1828  *   attributes that have boolean type.
1829  * - Build the attribute_info struct to hold the value of each supplied
1830  *   attribute that has byte array type. Link attribute_info structs
1831  *   together to form the extra attribute list of the object.
1832  * - Allocate storage for the Private Key object.
1833  * - Build the Private Key object according to the key type. Allocate
1834  *   storage to hold the big integer value for the supplied attributes
1835  *   that are required for a certain key type.
1836  *
1837  */
1838 CK_RV
1839 soft_build_private_key_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
1840     soft_object_t *new_object, CK_ULONG mode, CK_KEY_TYPE key_type)
1841 {
1842 	ulong_t		i;
1843 	CK_KEY_TYPE	keytype = (CK_KEY_TYPE)~0UL;
1844 	uint64_t	attr_mask = PRIVATE_KEY_DEFAULT;
1845 	CK_RV		rv = CKR_OK;
1846 	int		isLabel = 0;
1847 	int		isECParam = 0;
1848 	/* Must set flags unless mode == SOFT_UNWRAP_KEY */
1849 	int		isModulus = 0;
1850 	int		isPriExpo = 0;
1851 	int		isPrime = 0;
1852 	int		isSubprime = 0;
1853 	int		isBase = 0;
1854 	/* Must set flags if mode == SOFT_GEN_KEY */
1855 	int		isValue = 0;
1856 	/* Must not set flags */
1857 	int		isValueBits = 0;
1858 	CK_ULONG	value_bits = 0;
1859 
1860 	/* Private Key RSA optional */
1861 	int		isPubExpo = 0;
1862 	int		isPrime1 = 0;
1863 	int		isPrime2 = 0;
1864 	int		isExpo1 = 0;
1865 	int		isExpo2 = 0;
1866 	int		isCoef = 0;
1867 
1868 	biginteger_t	modulus;
1869 	biginteger_t	priexpo;
1870 	biginteger_t	prime;
1871 	biginteger_t	subprime;
1872 	biginteger_t	base;
1873 	biginteger_t	value;
1874 
1875 	biginteger_t	pubexpo;
1876 	biginteger_t	prime1;
1877 	biginteger_t	prime2;
1878 	biginteger_t	expo1;
1879 	biginteger_t	expo2;
1880 	biginteger_t	coef;
1881 	CK_ATTRIBUTE	string_tmp;
1882 	CK_ATTRIBUTE	param_tmp;
1883 	BIGNUM	x, q;
1884 
1885 	private_key_obj_t *pvk;
1886 	uchar_t	object_type = 0;
1887 
1888 	/* prevent bigint_attr_cleanup from freeing invalid attr value */
1889 	(void) memset(&modulus, 0x0, sizeof (biginteger_t));
1890 	(void) memset(&priexpo, 0x0, sizeof (biginteger_t));
1891 	(void) memset(&prime, 0x0, sizeof (biginteger_t));
1892 	(void) memset(&subprime, 0x0, sizeof (biginteger_t));
1893 	(void) memset(&base, 0x0, sizeof (biginteger_t));
1894 	(void) memset(&value, 0x0, sizeof (biginteger_t));
1895 	(void) memset(&pubexpo, 0x0, sizeof (biginteger_t));
1896 	(void) memset(&prime1, 0x0, sizeof (biginteger_t));
1897 	(void) memset(&prime2, 0x0, sizeof (biginteger_t));
1898 	(void) memset(&expo1, 0x0, sizeof (biginteger_t));
1899 	(void) memset(&expo2, 0x0, sizeof (biginteger_t));
1900 	(void) memset(&coef, 0x0, sizeof (biginteger_t));
1901 	string_tmp.pValue = NULL;
1902 	param_tmp.pValue = NULL;
1903 	x.malloced = 0;
1904 	q.malloced = 0;
1905 
1906 	for (i = 0; i < ulAttrNum; i++) {
1907 
1908 		/* Private Key Object Attributes */
1909 		switch (template[i].type) {
1910 		/* common key attributes */
1911 		case CKA_KEY_TYPE:
1912 			keytype = *((CK_KEY_TYPE*)template[i].pValue);
1913 			break;
1914 
1915 		case CKA_ID:
1916 		case CKA_START_DATE:
1917 		case CKA_END_DATE:
1918 
1919 		/* common private key attribute */
1920 		case CKA_SUBJECT:
1921 			/*
1922 			 * Allocate storage to hold the attribute
1923 			 * value with byte array type, and add it to
1924 			 * the extra attribute list of the object.
1925 			 */
1926 			rv = soft_add_extra_attr(&template[i],
1927 			    new_object);
1928 			if (rv != CKR_OK) {
1929 				goto fail_cleanup;
1930 			}
1931 			break;
1932 
1933 		/*
1934 		 * The following key related attribute types must
1935 		 * not be specified by C_CreateObject or C_GenerateKey(Pair).
1936 		 */
1937 		case CKA_LOCAL:
1938 		case CKA_KEY_GEN_MECHANISM:
1939 		case CKA_AUTH_PIN_FLAGS:
1940 		case CKA_ALWAYS_SENSITIVE:
1941 		case CKA_NEVER_EXTRACTABLE:
1942 			rv = CKR_TEMPLATE_INCONSISTENT;
1943 			goto fail_cleanup;
1944 
1945 		/* Key related boolean attributes */
1946 		case CKA_DERIVE:
1947 			if (*(CK_BBOOL *)template[i].pValue)
1948 				attr_mask |= DERIVE_BOOL_ON;
1949 			break;
1950 
1951 		case CKA_SENSITIVE:
1952 			if (*(CK_BBOOL *)template[i].pValue)
1953 				attr_mask |= SENSITIVE_BOOL_ON;
1954 			break;
1955 
1956 		case CKA_SECONDARY_AUTH:
1957 			if (*(CK_BBOOL *)template[i].pValue) {
1958 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
1959 				goto fail_cleanup;
1960 			}
1961 			break;
1962 
1963 		case CKA_DECRYPT:
1964 			if (*(CK_BBOOL *)template[i].pValue)
1965 				attr_mask |= DECRYPT_BOOL_ON;
1966 			else
1967 				attr_mask &= ~DECRYPT_BOOL_ON;
1968 			break;
1969 
1970 		case CKA_SIGN:
1971 			if (*(CK_BBOOL *)template[i].pValue)
1972 				attr_mask |= SIGN_BOOL_ON;
1973 			else
1974 				attr_mask &= ~SIGN_BOOL_ON;
1975 			break;
1976 
1977 		case CKA_SIGN_RECOVER:
1978 			if (*(CK_BBOOL *)template[i].pValue)
1979 				attr_mask |= SIGN_RECOVER_BOOL_ON;
1980 			else
1981 				attr_mask &= ~SIGN_RECOVER_BOOL_ON;
1982 			break;
1983 
1984 		case CKA_UNWRAP:
1985 			if (*(CK_BBOOL *)template[i].pValue)
1986 				attr_mask |= UNWRAP_BOOL_ON;
1987 			else
1988 				attr_mask &= ~UNWRAP_BOOL_ON;
1989 			break;
1990 
1991 		case CKA_EXTRACTABLE:
1992 			if (*(CK_BBOOL *)template[i].pValue)
1993 				attr_mask |= EXTRACTABLE_BOOL_ON;
1994 			else
1995 				attr_mask &= ~EXTRACTABLE_BOOL_ON;
1996 			break;
1997 
1998 		case CKA_MODIFIABLE:
1999 			if ((*(CK_BBOOL *)template[i].pValue) == B_FALSE)
2000 				attr_mask |= NOT_MODIFIABLE_BOOL_ON;
2001 			break;
2002 
2003 		/*
2004 		 * The following key related attribute types must
2005 		 * be specified according to the key type by
2006 		 * C_CreateObject.
2007 		 */
2008 		case CKA_MODULUS:
2009 
2010 			isModulus = 1;
2011 			/*
2012 			 * Copyin big integer attribute from template
2013 			 * to a local variable.
2014 			 */
2015 			rv = get_bigint_attr_from_template(&modulus,
2016 			    &template[i]);
2017 			if (rv != CKR_OK)
2018 				goto fail_cleanup;
2019 
2020 			/*
2021 			 * Modulus length needs to be between min key length and
2022 			 * max key length.
2023 			 */
2024 			if ((modulus.big_value_len <
2025 			    MIN_RSA_KEYLENGTH_IN_BYTES) ||
2026 			    (modulus.big_value_len >
2027 			    MAX_RSA_KEYLENGTH_IN_BYTES)) {
2028 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2029 				goto fail_cleanup;
2030 			}
2031 			break;
2032 
2033 		case CKA_PUBLIC_EXPONENT:
2034 
2035 			isPubExpo = 1;
2036 			rv = get_bigint_attr_from_template(&pubexpo,
2037 			    &template[i]);
2038 			if (rv != CKR_OK)
2039 				goto fail_cleanup;
2040 			break;
2041 
2042 		case CKA_PRIVATE_EXPONENT:
2043 
2044 			isPriExpo = 1;
2045 			rv = get_bigint_attr_from_template(&priexpo,
2046 			    &template[i]);
2047 			if (rv != CKR_OK)
2048 				goto fail_cleanup;
2049 			break;
2050 
2051 		case CKA_PRIME_1:
2052 			isPrime1 = 1;
2053 			rv = get_bigint_attr_from_template(&prime1,
2054 			    &template[i]);
2055 			if (rv != CKR_OK)
2056 				goto fail_cleanup;
2057 			break;
2058 
2059 		case CKA_PRIME_2:
2060 			isPrime2 = 1;
2061 			rv = get_bigint_attr_from_template(&prime2,
2062 			    &template[i]);
2063 			if (rv != CKR_OK)
2064 				goto fail_cleanup;
2065 			break;
2066 
2067 		case CKA_EXPONENT_1:
2068 			isExpo1 = 1;
2069 			rv = get_bigint_attr_from_template(&expo1,
2070 			    &template[i]);
2071 			if (rv != CKR_OK)
2072 				goto fail_cleanup;
2073 			break;
2074 
2075 		case CKA_EXPONENT_2:
2076 			isExpo2 = 1;
2077 			rv = get_bigint_attr_from_template(&expo2,
2078 			    &template[i]);
2079 			if (rv != CKR_OK)
2080 				goto fail_cleanup;
2081 			break;
2082 
2083 		case CKA_COEFFICIENT:
2084 			isCoef = 1;
2085 			rv = get_bigint_attr_from_template(&coef,
2086 			    &template[i]);
2087 			if (rv != CKR_OK)
2088 				goto fail_cleanup;
2089 			break;
2090 
2091 		case CKA_PRIME:
2092 			isPrime = 1;
2093 			rv = get_bigint_attr_from_template(&prime,
2094 			    &template[i]);
2095 			if (rv != CKR_OK)
2096 				goto fail_cleanup;
2097 			break;
2098 
2099 		case CKA_SUBPRIME:
2100 			isSubprime = 1;
2101 			rv = get_bigint_attr_from_template(&subprime,
2102 			    &template[i]);
2103 			if (rv != CKR_OK)
2104 				goto fail_cleanup;
2105 			break;
2106 
2107 		case CKA_BASE:
2108 			isBase = 1;
2109 			rv = get_bigint_attr_from_template(&base,
2110 			    &template[i]);
2111 			if (rv != CKR_OK)
2112 				goto fail_cleanup;
2113 			break;
2114 
2115 		case CKA_VALUE:
2116 			isValue = 1;
2117 			if (mode == SOFT_CREATE_OBJ) {
2118 				if ((template[i].ulValueLen == 0) ||
2119 				    (template[i].pValue == NULL)) {
2120 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
2121 					goto fail_cleanup;
2122 				}
2123 			}
2124 
2125 			rv = get_bigint_attr_from_template(&value,
2126 			    &template[i]);
2127 			if (rv != CKR_OK)
2128 				goto fail_cleanup;
2129 			break;
2130 
2131 		case CKA_VALUE_BITS:
2132 			isValueBits = 1;
2133 			rv = get_ulong_attr_from_template(&value_bits,
2134 			    &template[i]);
2135 			if (rv != CKR_OK)
2136 				goto fail_cleanup;
2137 			break;
2138 
2139 		case CKA_LABEL:
2140 			isLabel = 1;
2141 			rv = get_string_from_template(&string_tmp,
2142 			    &template[i]);
2143 			if (rv != CKR_OK)
2144 				goto fail_cleanup;
2145 			break;
2146 
2147 		case CKA_EC_PARAMS:
2148 			isECParam = 1;
2149 			rv = get_string_from_template(&param_tmp,
2150 			    &template[i]);
2151 			if (rv != CKR_OK)
2152 				goto fail_cleanup;
2153 			break;
2154 
2155 		default:
2156 			rv = soft_parse_common_attrs(&template[i],
2157 			    &object_type);
2158 			if (rv != CKR_OK)
2159 				goto fail_cleanup;
2160 			break;
2161 
2162 		}
2163 	} /* For */
2164 
2165 	/* Allocate storage for Private Key Object. */
2166 	pvk = calloc(1, sizeof (private_key_obj_t));
2167 	if (pvk == NULL) {
2168 		rv = CKR_HOST_MEMORY;
2169 		goto fail_cleanup;
2170 	}
2171 
2172 	new_object->object_class_u.private_key = pvk;
2173 	new_object->class = CKO_PRIVATE_KEY;
2174 
2175 	if ((mode == SOFT_CREATE_OBJ) && (keytype == (CK_KEY_TYPE)~0UL)) {
2176 		rv = CKR_TEMPLATE_INCOMPLETE;
2177 		goto fail_cleanup;
2178 	}
2179 
2180 	if (mode == SOFT_GEN_KEY) {
2181 		/*
2182 		 * The key type is not specified in the application's
2183 		 * template, so we use the implied key type based on
2184 		 * the mechanism.
2185 		 */
2186 		if (keytype == (CK_KEY_TYPE)~0UL) {
2187 			keytype = key_type;
2188 		}
2189 
2190 		/* If still unspecified, template is incomplete */
2191 		if (keytype == (CK_KEY_TYPE)~0UL) {
2192 			rv = CKR_TEMPLATE_INCOMPLETE;
2193 			goto fail_cleanup;
2194 		}
2195 
2196 		/*
2197 		 * The key type specified in the template does not
2198 		 * match the implied key type based on the mechanism.
2199 		 */
2200 		if (keytype != key_type) {
2201 			rv = CKR_TEMPLATE_INCONSISTENT;
2202 			goto fail_cleanup;
2203 		}
2204 	}
2205 
2206 	if (mode == SOFT_UNWRAP_KEY) {
2207 		/*
2208 		 * Note that, for mode SOFT_UNWRAP_KEY, key type is not
2209 		 * implied by the mechanism (key_type), so if it is not
2210 		 * specified from the attribute template (keytype), it is
2211 		 * incomplete.
2212 		 */
2213 		if (keytype == (CK_KEY_TYPE)~0UL) {
2214 			rv = CKR_TEMPLATE_INCOMPLETE;
2215 			goto fail_cleanup;
2216 		}
2217 	}
2218 
2219 	new_object->key_type = keytype;
2220 
2221 	/* Supported key types of the Private Key Object */
2222 	switch (keytype) {
2223 	case CKK_RSA:
2224 		if (isPrime || isSubprime || isBase || isValue ||
2225 		    isValueBits) {
2226 			rv = CKR_TEMPLATE_INCONSISTENT;
2227 			goto fail_cleanup;
2228 		}
2229 
2230 		if (mode == SOFT_GEN_KEY || mode == SOFT_UNWRAP_KEY) {
2231 			if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
2232 			    isPrime2 || isExpo1 || isExpo2 || isCoef) {
2233 				rv = CKR_TEMPLATE_INCONSISTENT;
2234 				goto fail_cleanup;
2235 			} else
2236 				break;
2237 		}
2238 
2239 		if (isModulus && isPriExpo) {
2240 			/*
2241 			 * Copy big integer attribute value to the
2242 			 * designated place in the Private Key object.
2243 			 */
2244 			copy_bigint_attr(&modulus, KEY_PRI_RSA_MOD(pvk));
2245 
2246 			copy_bigint_attr(&priexpo, KEY_PRI_RSA_PRIEXPO(pvk));
2247 		} else {
2248 			rv = CKR_TEMPLATE_INCOMPLETE;
2249 			goto fail_cleanup;
2250 		}
2251 
2252 		/* The following attributes are optional. */
2253 		if (isPubExpo) {
2254 			copy_bigint_attr(&pubexpo, KEY_PRI_RSA_PUBEXPO(pvk));
2255 		}
2256 
2257 		if (isPrime1) {
2258 			copy_bigint_attr(&prime1, KEY_PRI_RSA_PRIME1(pvk));
2259 		}
2260 
2261 		if (isPrime2) {
2262 			copy_bigint_attr(&prime2, KEY_PRI_RSA_PRIME2(pvk));
2263 		}
2264 
2265 		if (isExpo1) {
2266 			copy_bigint_attr(&expo1, KEY_PRI_RSA_EXPO1(pvk));
2267 		}
2268 
2269 		if (isExpo2) {
2270 			copy_bigint_attr(&expo2, KEY_PRI_RSA_EXPO2(pvk));
2271 		}
2272 
2273 		if (isCoef) {
2274 			copy_bigint_attr(&coef, KEY_PRI_RSA_COEF(pvk));
2275 		}
2276 		break;
2277 
2278 	case CKK_DSA:
2279 		if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
2280 		    isPrime2 || isExpo1 || isExpo2 || isCoef ||
2281 		    isValueBits) {
2282 			rv = CKR_TEMPLATE_INCONSISTENT;
2283 			goto fail_cleanup;
2284 		}
2285 
2286 		if (mode == SOFT_GEN_KEY || mode == SOFT_UNWRAP_KEY) {
2287 			if (isPrime || isSubprime || isBase || isValue) {
2288 				rv = CKR_TEMPLATE_INCONSISTENT;
2289 				goto fail_cleanup;
2290 			} else
2291 				break;
2292 		}
2293 
2294 		if (isPrime && isSubprime && isBase && isValue) {
2295 			/*
2296 			 * The private value x must be less than subprime q.
2297 			 * Size for big_init is in BIG_CHUNK_TYPE words.
2298 			 */
2299 #ifdef	__sparcv9
2300 			if (big_init(&x,
2301 			    (int)CHARLEN2BIGNUMLEN(value.big_value_len))
2302 			    != BIG_OK) {
2303 #else	/* !__sparcv9 */
2304 			if (big_init(&x,
2305 			    CHARLEN2BIGNUMLEN(value.big_value_len))
2306 			    != BIG_OK) {
2307 #endif	/* __sparcv9 */
2308 				rv = CKR_HOST_MEMORY;
2309 				goto fail_cleanup;
2310 			}
2311 #ifdef	__sparcv9
2312 			if (big_init(&q,
2313 			    (int)CHARLEN2BIGNUMLEN(subprime.big_value_len))
2314 			    != BIG_OK) {
2315 #else	/* !__sparcv9 */
2316 			if (big_init(&q,
2317 			    CHARLEN2BIGNUMLEN(subprime.big_value_len))
2318 			    != BIG_OK) {
2319 #endif	/* __sparcv9 */
2320 				rv = CKR_HOST_MEMORY;
2321 				goto fail_cleanup;
2322 			}
2323 			bytestring2bignum(&x, value.big_value,
2324 			    value.big_value_len);
2325 			bytestring2bignum(&q, subprime.big_value,
2326 			    subprime.big_value_len);
2327 
2328 			if (big_cmp_abs(&x, &q) > 0) {
2329 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2330 				goto fail_cleanup;
2331 			}
2332 
2333 			copy_bigint_attr(&prime, KEY_PRI_DSA_PRIME(pvk));
2334 
2335 			copy_bigint_attr(&subprime, KEY_PRI_DSA_SUBPRIME(pvk));
2336 
2337 			copy_bigint_attr(&base, KEY_PRI_DSA_BASE(pvk));
2338 
2339 			copy_bigint_attr(&value, KEY_PRI_DSA_VALUE(pvk));
2340 		} else {
2341 			rv = CKR_TEMPLATE_INCOMPLETE;
2342 			goto fail_cleanup;
2343 		}
2344 		break;
2345 
2346 	case CKK_DH:
2347 		if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
2348 		    isPrime2 || isExpo1 || isExpo2 || isCoef ||
2349 		    isSubprime) {
2350 			rv = CKR_TEMPLATE_INCONSISTENT;
2351 			goto fail_cleanup;
2352 		}
2353 
2354 		/* CKA_VALUE_BITS is for key gen but not unwrap */
2355 		if (mode == SOFT_GEN_KEY)
2356 			KEY_PRI_DH_VAL_BITS(pvk) = (isValueBits) ?
2357 			    value_bits : 0;
2358 		else if (mode == SOFT_UNWRAP_KEY) {
2359 			if (isValueBits) {
2360 				rv = CKR_TEMPLATE_INCONSISTENT;
2361 				goto fail_cleanup;
2362 			}
2363 		}
2364 
2365 		if (mode == SOFT_GEN_KEY || mode == SOFT_UNWRAP_KEY) {
2366 			if (isPrime || isBase || isValue) {
2367 				rv = CKR_TEMPLATE_INCONSISTENT;
2368 				goto fail_cleanup;
2369 			} else
2370 				break;
2371 		}
2372 
2373 		if (isValueBits) {
2374 			rv = CKR_TEMPLATE_INCONSISTENT;
2375 			goto fail_cleanup;
2376 		}
2377 
2378 		if (isPrime && isBase && isValue) {
2379 			copy_bigint_attr(&prime, KEY_PRI_DH_PRIME(pvk));
2380 
2381 			copy_bigint_attr(&base, KEY_PRI_DH_BASE(pvk));
2382 
2383 			copy_bigint_attr(&value, KEY_PRI_DH_VALUE(pvk));
2384 		} else {
2385 			rv = CKR_TEMPLATE_INCOMPLETE;
2386 			goto fail_cleanup;
2387 		}
2388 		break;
2389 
2390 	case CKK_X9_42_DH:
2391 		if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
2392 		    isPrime2 || isExpo1 || isExpo2 || isCoef ||
2393 		    isValueBits) {
2394 			rv = CKR_TEMPLATE_INCONSISTENT;
2395 			goto fail_cleanup;
2396 		}
2397 
2398 		if (mode == SOFT_GEN_KEY || mode == SOFT_UNWRAP_KEY) {
2399 			if (isPrime || isSubprime || isBase || isValue) {
2400 				rv = CKR_TEMPLATE_INCONSISTENT;
2401 				goto fail_cleanup;
2402 			} else
2403 				break;
2404 		}
2405 
2406 		if (isPrime && isSubprime && isBase && isValue) {
2407 			copy_bigint_attr(&prime, KEY_PRI_DH942_PRIME(pvk));
2408 
2409 			copy_bigint_attr(&base, KEY_PRI_DH942_BASE(pvk));
2410 
2411 			copy_bigint_attr(&subprime,
2412 			    KEY_PRI_DH942_SUBPRIME(pvk));
2413 
2414 			copy_bigint_attr(&value, KEY_PRI_DH942_VALUE(pvk));
2415 		} else {
2416 			rv = CKR_TEMPLATE_INCOMPLETE;
2417 			goto fail_cleanup;
2418 		}
2419 		break;
2420 
2421 	case CKK_EC:
2422 		if (isModulus || isPubExpo || isPrime ||
2423 		    isPrime1 || isPrime2 || isExpo1 || isExpo2 || isCoef ||
2424 		    isValueBits || isBase) {
2425 			rv = CKR_TEMPLATE_INCONSISTENT;
2426 			goto fail_cleanup;
2427 
2428 		} else if (isECParam) {
2429 			rv = soft_add_extra_attr(&param_tmp, new_object);
2430 			if (rv != CKR_OK)
2431 				goto fail_cleanup;
2432 			string_attr_cleanup(&param_tmp);
2433 		}
2434 		if (isValue) {
2435 			copy_bigint_attr(&value, KEY_PRI_EC_VALUE(pvk));
2436 		}
2437 		break;
2438 
2439 	default:
2440 		rv = CKR_TEMPLATE_INCONSISTENT;
2441 		goto fail_cleanup;
2442 	}
2443 
2444 	/* Set up object. */
2445 	new_object->object_type = object_type;
2446 	new_object->bool_attr_mask = attr_mask;
2447 	if (isLabel) {
2448 		rv = soft_add_extra_attr(&string_tmp, new_object);
2449 		if (rv != CKR_OK)
2450 			goto fail_cleanup;
2451 		string_attr_cleanup(&string_tmp);
2452 	}
2453 	big_finish(&x);
2454 	big_finish(&q);
2455 
2456 	return (rv);
2457 
2458 fail_cleanup:
2459 	/*
2460 	 * cleanup the storage allocated to the local variables.
2461 	 */
2462 	bigint_attr_cleanup(&modulus);
2463 	bigint_attr_cleanup(&priexpo);
2464 	bigint_attr_cleanup(&prime);
2465 	bigint_attr_cleanup(&subprime);
2466 	bigint_attr_cleanup(&base);
2467 	bigint_attr_cleanup(&value);
2468 	bigint_attr_cleanup(&pubexpo);
2469 	bigint_attr_cleanup(&prime1);
2470 	bigint_attr_cleanup(&prime2);
2471 	bigint_attr_cleanup(&expo1);
2472 	bigint_attr_cleanup(&expo2);
2473 	bigint_attr_cleanup(&coef);
2474 	string_attr_cleanup(&string_tmp);
2475 	string_attr_cleanup(&param_tmp);
2476 	big_finish(&x);
2477 	big_finish(&q);
2478 
2479 	/*
2480 	 * cleanup the storage allocated inside the object itself.
2481 	 */
2482 	soft_cleanup_object(new_object);
2483 
2484 	return (rv);
2485 }
2486 
2487 
2488 /*
2489  * Build a Secret Key Object.
2490  *
2491  * - Parse the object's template, and when an error is detected such as
2492  *   invalid attribute type, invalid attribute value, etc., return
2493  *   with appropriate return value.
2494  * - Set up attribute mask field in the object for the supplied common
2495  *   attributes that have boolean type.
2496  * - Build the attribute_info struct to hold the value of each supplied
2497  *   attribute that has byte array type. Link attribute_info structs
2498  *   together to form the extra attribute list of the object.
2499  * - Allocate storage for the Secret Key object.
2500  * - Build the Secret Key object. Allocate storage to hold the big integer
2501  *   value for the attribute CKA_VALUE that is required for all the key
2502  *   types supported by secret key object.
2503  * This function is called internally with mode = SOFT_CREATE_OBJ_INT.
2504  *
2505  */
2506 CK_RV
2507 soft_build_secret_key_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
2508     soft_object_t *new_object, CK_ULONG mode, CK_ULONG key_len,
2509     CK_KEY_TYPE key_type)
2510 {
2511 
2512 	ulong_t		i;
2513 	CK_KEY_TYPE	keytype = (CK_KEY_TYPE)~0UL;
2514 	uint64_t	attr_mask = SECRET_KEY_DEFAULT;
2515 	CK_RV		rv = CKR_OK;
2516 	int		isLabel = 0;
2517 	/* Must set flags if mode != SOFT_UNWRAP_KEY, else must not set */
2518 	int		isValue = 0;
2519 	/* Must not set flags if mode != SOFT_UNWRAP_KEY, else optional */
2520 	int		isValueLen = 0;
2521 
2522 	CK_ATTRIBUTE	string_tmp;
2523 
2524 	secret_key_obj_t  *sck;
2525 	uchar_t	object_type = 0;
2526 
2527 	string_tmp.pValue = NULL;
2528 
2529 	/* Allocate storage for Secret Key Object. */
2530 	sck = calloc(1, sizeof (secret_key_obj_t));
2531 	if (sck == NULL) {
2532 		rv = CKR_HOST_MEMORY;
2533 		goto fail_cleanup;
2534 	}
2535 
2536 	new_object->object_class_u.secret_key = sck;
2537 	new_object->class = CKO_SECRET_KEY;
2538 
2539 	for (i = 0; i < ulAttrNum; i++) {
2540 
2541 		/* Secret Key Object Attributes */
2542 		switch (template[i].type) {
2543 
2544 		/* common key attributes */
2545 		case CKA_KEY_TYPE:
2546 			keytype = *((CK_KEY_TYPE*)template[i].pValue);
2547 			break;
2548 
2549 		case CKA_ID:
2550 		case CKA_START_DATE:
2551 		case CKA_END_DATE:
2552 			/*
2553 			 * Allocate storage to hold the attribute
2554 			 * value with byte array type, and add it to
2555 			 * the extra attribute list of the object.
2556 			 */
2557 			rv = soft_add_extra_attr(&template[i],
2558 			    new_object);
2559 			if (rv != CKR_OK) {
2560 				goto fail_cleanup;
2561 			}
2562 			break;
2563 
2564 		/*
2565 		 * The following key related attribute types must
2566 		 * not be specified by C_CreateObject and C_GenerateKey.
2567 		 */
2568 		case CKA_LOCAL:
2569 		case CKA_KEY_GEN_MECHANISM:
2570 		case CKA_ALWAYS_SENSITIVE:
2571 		case CKA_NEVER_EXTRACTABLE:
2572 			rv = CKR_TEMPLATE_INCONSISTENT;
2573 			goto fail_cleanup;
2574 
2575 		/* Key related boolean attributes */
2576 		case CKA_DERIVE:
2577 			if (*(CK_BBOOL *)template[i].pValue)
2578 				attr_mask |= DERIVE_BOOL_ON;
2579 			break;
2580 
2581 		case CKA_SENSITIVE:
2582 			if (*(CK_BBOOL *)template[i].pValue)
2583 				attr_mask |= SENSITIVE_BOOL_ON;
2584 			break;
2585 
2586 		case CKA_ENCRYPT:
2587 			if (*(CK_BBOOL *)template[i].pValue)
2588 				attr_mask |= ENCRYPT_BOOL_ON;
2589 			else
2590 				attr_mask &= ~ENCRYPT_BOOL_ON;
2591 			break;
2592 
2593 		case CKA_DECRYPT:
2594 			if (*(CK_BBOOL *)template[i].pValue)
2595 				attr_mask |= DECRYPT_BOOL_ON;
2596 			else
2597 				attr_mask &= ~DECRYPT_BOOL_ON;
2598 			break;
2599 
2600 		case CKA_SIGN:
2601 			if (*(CK_BBOOL *)template[i].pValue)
2602 				attr_mask |= SIGN_BOOL_ON;
2603 			else
2604 				attr_mask &= ~SIGN_BOOL_ON;
2605 			break;
2606 
2607 		case CKA_VERIFY:
2608 			if (*(CK_BBOOL *)template[i].pValue)
2609 				attr_mask |= VERIFY_BOOL_ON;
2610 			else
2611 				attr_mask &= ~VERIFY_BOOL_ON;
2612 			break;
2613 
2614 		case CKA_WRAP:
2615 			if (*(CK_BBOOL *)template[i].pValue)
2616 				attr_mask |= WRAP_BOOL_ON;
2617 			else
2618 				attr_mask &= ~WRAP_BOOL_ON;
2619 			break;
2620 
2621 		case CKA_UNWRAP:
2622 			if (*(CK_BBOOL *)template[i].pValue)
2623 				attr_mask |= UNWRAP_BOOL_ON;
2624 			else
2625 				attr_mask &= ~UNWRAP_BOOL_ON;
2626 			break;
2627 
2628 		case CKA_EXTRACTABLE:
2629 			if (*(CK_BBOOL *)template[i].pValue)
2630 				attr_mask |= EXTRACTABLE_BOOL_ON;
2631 			else
2632 				attr_mask &= ~EXTRACTABLE_BOOL_ON;
2633 			break;
2634 
2635 		case CKA_MODIFIABLE:
2636 			if ((*(CK_BBOOL *)template[i].pValue) == B_FALSE)
2637 				attr_mask |= NOT_MODIFIABLE_BOOL_ON;
2638 			break;
2639 
2640 		case CKA_VALUE:
2641 			isValue = 1;
2642 			if (mode == SOFT_CREATE_OBJ) {
2643 				if ((template[i].ulValueLen == 0) ||
2644 				    (template[i].pValue == NULL)) {
2645 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
2646 					goto fail_cleanup;
2647 				}
2648 			}
2649 
2650 			/*
2651 			 * Copyin attribute from template
2652 			 * to a local variable.
2653 			 */
2654 			rv = get_bigint_attr_from_template((biginteger_t *)sck,
2655 			    &template[i]);
2656 			if (rv != CKR_OK)
2657 				goto fail_cleanup;
2658 			break;
2659 
2660 		case CKA_VALUE_LEN:
2661 			isValueLen = 1;
2662 			rv = get_ulong_attr_from_template(&sck->sk_value_len,
2663 			    &template[i]);
2664 			if (rv != CKR_OK)
2665 				goto fail_cleanup;
2666 			break;
2667 
2668 		case CKA_LABEL:
2669 			isLabel = 1;
2670 			rv = get_string_from_template(&string_tmp,
2671 			    &template[i]);
2672 			if (rv != CKR_OK)
2673 				goto fail_cleanup;
2674 			break;
2675 
2676 		default:
2677 			rv = soft_parse_common_attrs(&template[i],
2678 			    &object_type);
2679 			if (rv != CKR_OK)
2680 				goto fail_cleanup;
2681 			break;
2682 
2683 		}
2684 	} /* For */
2685 
2686 	switch (mode) {
2687 	case SOFT_CREATE_OBJ:
2688 	case SOFT_CREATE_OBJ_INT:
2689 	case SOFT_DERIVE_KEY_DH:
2690 		/*
2691 		 * The key type must be specified in the application's
2692 		 * template. Otherwise, returns error.
2693 		 */
2694 		if (keytype == (CK_KEY_TYPE)~0UL) {
2695 			rv = CKR_TEMPLATE_INCOMPLETE;
2696 			goto fail_cleanup;
2697 		}
2698 		break;
2699 
2700 	case SOFT_GEN_KEY:
2701 		if (keytype == (CK_KEY_TYPE)~0UL) {
2702 			/*
2703 			 * The key type is not specified in the application's
2704 			 * template, so we use the implied key type based on
2705 			 * the mechanism.
2706 			 */
2707 			keytype = key_type;
2708 		} else {
2709 			if (keytype != key_type) {
2710 				/*
2711 				 * The key type specified in the template
2712 				 * does not match the implied key type based
2713 				 * on the mechanism.
2714 				 */
2715 				rv = CKR_TEMPLATE_INCONSISTENT;
2716 				goto fail_cleanup;
2717 			}
2718 		}
2719 
2720 		/*
2721 		 * If a key_len is passed as a parameter, it has to
2722 		 * match the one found in the template.
2723 		 */
2724 		if (key_len > 0) {
2725 			if (isValueLen && sck->sk_value_len != key_len) {
2726 				rv = CKR_TEMPLATE_INCONSISTENT;
2727 				goto fail_cleanup;
2728 			}
2729 			isValueLen = 1;
2730 			sck->sk_value_len = key_len;
2731 		}
2732 		break;
2733 
2734 	case SOFT_UNWRAP_KEY:
2735 		/*
2736 		 * Note that, for mode SOFT_UNWRAP_KEY, key type is not
2737 		 * implied by the mechanism (key_type), so if it is not
2738 		 * specified from the attribute template (keytype), it is
2739 		 * incomplete.
2740 		 */
2741 		if (keytype == (CK_KEY_TYPE)~0UL) {
2742 			rv = CKR_TEMPLATE_INCOMPLETE;
2743 			goto fail_cleanup;
2744 		}
2745 		break;
2746 
2747 	case SOFT_DERIVE_KEY_OTHER:
2748 		/*
2749 		 * For CKM_MD5_KEY_DERIVATION & CKM_SHA1_KEY_DERIVATION, the
2750 		 * key type is optional.
2751 		 */
2752 		if (keytype == (CK_KEY_TYPE)~0UL) {
2753 			keytype = key_type;
2754 		}
2755 		break;
2756 	}
2757 
2758 	switch (mode) {
2759 	case SOFT_CREATE_OBJ:
2760 	case SOFT_CREATE_OBJ_INT:
2761 		switch (keytype) {
2762 		case CKK_RC4:
2763 			if (!isValue) {
2764 				rv = CKR_TEMPLATE_INCOMPLETE;
2765 				goto fail_cleanup;
2766 			}
2767 			if ((sck->sk_value_len < ARCFOUR_MIN_KEY_BYTES) ||
2768 			    (sck->sk_value_len > ARCFOUR_MAX_KEY_BYTES)) {
2769 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2770 				goto fail_cleanup;
2771 			}
2772 			break;
2773 
2774 		case CKK_GENERIC_SECRET:
2775 			if (!isValue) {
2776 				rv = CKR_TEMPLATE_INCOMPLETE;
2777 				goto fail_cleanup;
2778 			}
2779 			break;
2780 
2781 		case CKK_AES:
2782 			if (!isValue) {
2783 				rv = CKR_TEMPLATE_INCOMPLETE;
2784 				goto fail_cleanup;
2785 			}
2786 			if ((sck->sk_value_len != AES_MIN_KEY_BYTES) &&
2787 			    (sck->sk_value_len != AES_192_KEY_BYTES) &&
2788 			    (sck->sk_value_len != AES_MAX_KEY_BYTES)) {
2789 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2790 				goto fail_cleanup;
2791 			}
2792 			break;
2793 
2794 		case CKK_BLOWFISH:
2795 			if (!isValue) {
2796 				rv = CKR_TEMPLATE_INCOMPLETE;
2797 				goto fail_cleanup;
2798 			}
2799 			if ((sck->sk_value_len < BLOWFISH_MINBYTES) ||
2800 			    (sck->sk_value_len > BLOWFISH_MAXBYTES)) {
2801 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2802 				goto fail_cleanup;
2803 			}
2804 
2805 			break;
2806 
2807 		case CKK_DES:
2808 			if (!isValue) {
2809 				rv = CKR_TEMPLATE_INCOMPLETE;
2810 				goto fail_cleanup;
2811 			}
2812 			if (sck->sk_value_len != DES_KEYSIZE) {
2813 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2814 				goto fail_cleanup;
2815 			}
2816 			break;
2817 
2818 		case CKK_DES2:
2819 			if (!isValue) {
2820 				rv = CKR_TEMPLATE_INCOMPLETE;
2821 				goto fail_cleanup;
2822 			}
2823 			if (sck->sk_value_len != DES2_KEYSIZE) {
2824 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2825 				goto fail_cleanup;
2826 			}
2827 			break;
2828 
2829 		case CKK_DES3:
2830 			if (!isValue) {
2831 				rv = CKR_TEMPLATE_INCOMPLETE;
2832 				goto fail_cleanup;
2833 			}
2834 			if (sck->sk_value_len != DES3_KEYSIZE) {
2835 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2836 				goto fail_cleanup;
2837 			}
2838 			break;
2839 
2840 		default:
2841 			rv = CKR_TEMPLATE_INCONSISTENT;
2842 			goto fail_cleanup;
2843 		}
2844 
2845 		if (isValueLen) {
2846 			/*
2847 			 * Templates for internal object creation come from
2848 			 * applications calls to C_DeriveKey(), for which it
2849 			 * is OKey to pass a CKA_VALUE_LEN attribute, as
2850 			 * long as it does not conflict with the length of the
2851 			 * CKA_VALUE attribute.
2852 			 */
2853 			if ((mode != SOFT_CREATE_OBJ_INT) ||
2854 			    ((key_len > 0) && sck->sk_value_len != key_len)) {
2855 				rv = CKR_TEMPLATE_INCONSISTENT;
2856 				goto fail_cleanup;
2857 			}
2858 		}
2859 		break;
2860 
2861 	case SOFT_GEN_KEY:
2862 		/* CKA_VALUE must not be specified */
2863 		if (isValue) {
2864 			rv = CKR_TEMPLATE_INCONSISTENT;
2865 			goto fail_cleanup;
2866 		}
2867 
2868 		switch (keytype) {
2869 		/*
2870 		 * CKA_VALUE_LEN must be specified by C_GenerateKey
2871 		 * if mech is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET.
2872 		 */
2873 		case CKK_RC4:
2874 			if (!isValueLen) {
2875 				rv = CKR_TEMPLATE_INCOMPLETE;
2876 				goto fail_cleanup;
2877 			}
2878 			;
2879 			if ((sck->sk_value_len < ARCFOUR_MIN_KEY_BYTES) ||
2880 			    (sck->sk_value_len > ARCFOUR_MAX_KEY_BYTES)) {
2881 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2882 				goto fail_cleanup;
2883 			}
2884 			break;
2885 
2886 		case CKK_GENERIC_SECRET:
2887 			/* arbitrary key length - no length checking */
2888 			if (!isValueLen) {
2889 				rv = CKR_TEMPLATE_INCOMPLETE;
2890 				goto fail_cleanup;
2891 			}
2892 			break;
2893 
2894 		case CKK_AES:
2895 			if (!isValueLen) {
2896 				rv = CKR_TEMPLATE_INCOMPLETE;
2897 				goto fail_cleanup;
2898 			}
2899 
2900 			if ((sck->sk_value_len != AES_MIN_KEY_BYTES) &&
2901 			    (sck->sk_value_len != AES_192_KEY_BYTES) &&
2902 			    (sck->sk_value_len != AES_MAX_KEY_BYTES)) {
2903 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2904 				goto fail_cleanup;
2905 			}
2906 
2907 			break;
2908 
2909 		case CKK_BLOWFISH:
2910 			if (!isValueLen) {
2911 				rv = CKR_TEMPLATE_INCOMPLETE;
2912 				goto fail_cleanup;
2913 			}
2914 			if ((sck->sk_value_len < BLOWFISH_MINBYTES) ||
2915 			    (sck->sk_value_len > BLOWFISH_MAXBYTES)) {
2916 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2917 				goto fail_cleanup;
2918 			}
2919 
2920 			break;
2921 
2922 		case CKK_DES:
2923 		case CKK_DES2:
2924 		case CKK_DES3:
2925 			/* CKA_VALUE_LEN attribute does not apply to DES<n> */
2926 			if (isValueLen) {
2927 				rv = CKR_TEMPLATE_INCONSISTENT;
2928 				goto fail_cleanup;
2929 			}
2930 			break;
2931 
2932 		default:
2933 			rv = CKR_TEMPLATE_INCONSISTENT;
2934 			goto fail_cleanup;
2935 		}
2936 		break;
2937 
2938 	case SOFT_UNWRAP_KEY:
2939 		/*
2940 		 * According to v2.11 of PKCS#11 spec, neither CKA_VALUE nor
2941 		 * CKA_VALUE_LEN can be be specified; however v2.20 has this
2942 		 * restriction removed, perhaps because it makes it hard to
2943 		 * determine variable-length key sizes.  This case statement
2944 		 * complied with v2.20.
2945 		 */
2946 		if (isValue) {
2947 			rv = CKR_TEMPLATE_INCONSISTENT;
2948 			goto fail_cleanup;
2949 		}
2950 
2951 		switch (keytype) {
2952 		/*
2953 		 * CKA_VALUE_LEN is optional
2954 		 * if key is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET
2955 		 * and the unwrapping mech is *_CBC_PAD.
2956 		 *
2957 		 * CKA_VALUE_LEN is required
2958 		 * if key is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET
2959 		 * and the unwrapping mech is *_ECB or *_CBC.
2960 		 *
2961 		 * since mech is not known at this point, CKA_VALUE_LEN is
2962 		 * treated as optional and the caller needs to enforce it.
2963 		 */
2964 		case CKK_RC4:
2965 			if (isValueLen) {
2966 				if ((sck->sk_value_len <
2967 				    ARCFOUR_MIN_KEY_BYTES) ||
2968 				    (sck->sk_value_len >
2969 				    ARCFOUR_MAX_KEY_BYTES)) {
2970 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
2971 					goto fail_cleanup;
2972 				}
2973 			}
2974 			break;
2975 
2976 		case CKK_GENERIC_SECRET:
2977 			/* arbitrary key length - no length checking */
2978 			break;
2979 
2980 		case CKK_AES:
2981 			if (isValueLen) {
2982 				if ((sck->sk_value_len != AES_MIN_KEY_BYTES) &&
2983 				    (sck->sk_value_len != AES_192_KEY_BYTES) &&
2984 				    (sck->sk_value_len != AES_MAX_KEY_BYTES)) {
2985 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
2986 					goto fail_cleanup;
2987 				}
2988 			}
2989 			break;
2990 
2991 		case CKK_BLOWFISH:
2992 			if (isValueLen &&
2993 			    ((sck->sk_value_len < BLOWFISH_MINBYTES) ||
2994 			    (sck->sk_value_len > BLOWFISH_MAXBYTES))) {
2995 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
2996 				goto fail_cleanup;
2997 			}
2998 			break;
2999 
3000 		case CKK_DES:
3001 		case CKK_DES2:
3002 		case CKK_DES3:
3003 			/* CKA_VALUE_LEN attribute does not apply to DES<n> */
3004 			if (isValueLen) {
3005 				rv = CKR_TEMPLATE_INCONSISTENT;
3006 				goto fail_cleanup;
3007 			}
3008 			break;
3009 
3010 		default:
3011 			rv = CKR_TEMPLATE_INCONSISTENT;
3012 			goto fail_cleanup;
3013 		}
3014 		break;
3015 
3016 	case SOFT_DERIVE_KEY_DH:
3017 		/* CKA_VALUE must not be specified */
3018 		if (isValue) {
3019 			rv = CKR_TEMPLATE_INCONSISTENT;
3020 			goto fail_cleanup;
3021 		}
3022 
3023 		switch (keytype) {
3024 		/*
3025 		 * CKA_VALUE_LEN is optional
3026 		 * if mech is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET.
3027 		 */
3028 		case CKK_RC4:
3029 			if (isValueLen) {
3030 				if ((sck->sk_value_len <
3031 				    ARCFOUR_MIN_KEY_BYTES) ||
3032 				    (sck->sk_value_len >
3033 				    ARCFOUR_MAX_KEY_BYTES)) {
3034 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
3035 					goto fail_cleanup;
3036 				}
3037 			}
3038 			break;
3039 
3040 		case CKK_GENERIC_SECRET:
3041 			/* arbitrary key length - no length checking */
3042 			break;
3043 
3044 		case CKK_AES:
3045 			if (isValueLen) {
3046 				if ((sck->sk_value_len != AES_MIN_KEY_BYTES) &&
3047 				    (sck->sk_value_len != AES_192_KEY_BYTES) &&
3048 				    (sck->sk_value_len != AES_MAX_KEY_BYTES)) {
3049 					rv = CKR_ATTRIBUTE_VALUE_INVALID;
3050 					goto fail_cleanup;
3051 				}
3052 			}
3053 
3054 			break;
3055 
3056 		case CKK_BLOWFISH:
3057 			if (isValueLen &&
3058 			    ((sck->sk_value_len < BLOWFISH_MINBYTES) ||
3059 			    (sck->sk_value_len > BLOWFISH_MAXBYTES))) {
3060 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
3061 				goto fail_cleanup;
3062 			}
3063 			break;
3064 
3065 		case CKK_DES:
3066 		case CKK_DES2:
3067 		case CKK_DES3:
3068 			/* CKA_VALUE_LEN attribute does not apply to DES<n> */
3069 			if (isValueLen) {
3070 				rv = CKR_TEMPLATE_INCONSISTENT;
3071 				goto fail_cleanup;
3072 			}
3073 			break;
3074 
3075 		default:
3076 			rv = CKR_TEMPLATE_INCONSISTENT;
3077 			goto fail_cleanup;
3078 		}
3079 		break;
3080 
3081 	case SOFT_DERIVE_KEY_OTHER:
3082 		/* CKA_VALUE must not be specified */
3083 		if (isValue) {
3084 			rv = CKR_TEMPLATE_INCONSISTENT;
3085 			goto fail_cleanup;
3086 		}
3087 
3088 		switch (keytype) {
3089 		/*
3090 		 * CKA_VALUE_LEN is an optional attribute for
3091 		 * CKM_SHA1_KEY_DERIVATION and CKM_MD5_KEY_DERIVATION
3092 		 * if mech is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET.
3093 		 */
3094 		case CKK_RC4:
3095 		case CKK_GENERIC_SECRET:
3096 		case CKK_AES:
3097 		case CKK_BLOWFISH:
3098 			/*
3099 			 * No need to check key length value here, it will be
3100 			 * validated later in soft_key_derive_check_length().
3101 			 */
3102 			break;
3103 
3104 		case CKK_DES:
3105 		case CKK_DES2:
3106 		case CKK_DES3:
3107 			/* CKA_VALUE_LEN attribute does not apply to DES<n> */
3108 			if (isValueLen) {
3109 				rv = CKR_TEMPLATE_INCONSISTENT;
3110 				goto fail_cleanup;
3111 			}
3112 			break;
3113 
3114 		default:
3115 			rv = CKR_TEMPLATE_INCONSISTENT;
3116 			goto fail_cleanup;
3117 		}
3118 		break;
3119 	}
3120 
3121 	/* Set up object. */
3122 	new_object->key_type = keytype;
3123 	new_object->object_type = object_type;
3124 	new_object->bool_attr_mask = attr_mask;
3125 	if (isLabel) {
3126 		rv = soft_add_extra_attr(&string_tmp, new_object);
3127 		if (rv != CKR_OK)
3128 			goto fail_cleanup;
3129 		string_attr_cleanup(&string_tmp);
3130 	}
3131 	return (rv);
3132 
3133 fail_cleanup:
3134 	/*
3135 	 * cleanup the storage allocated to the local variables.
3136 	 */
3137 	bigint_attr_cleanup((biginteger_t *)sck);
3138 	string_attr_cleanup(&string_tmp);
3139 
3140 	/*
3141 	 * cleanup the storage allocated inside the object itself.
3142 	 */
3143 	soft_cleanup_object(new_object);
3144 
3145 	return (rv);
3146 }
3147 
3148 
3149 /*
3150  * Build a Domain Parameter Object.
3151  *
3152  * - Parse the object's template, and when an error is detected such as
3153  *   invalid attribute type, invalid attribute value, etc., return
3154  *   with appropriate return value.
3155  * - Allocate storage for the Domain Parameter object.
3156  * - Build the Domain Parameter object according to the key type. Allocate
3157  *   storage to hold the big integer value for the supplied attributes
3158  *   that are required for a certain key type.
3159  *
3160  */
3161 CK_RV
3162 soft_build_domain_parameters_object(CK_ATTRIBUTE_PTR template,
3163     CK_ULONG ulAttrNum, soft_object_t *new_object)
3164 {
3165 
3166 	ulong_t		i;
3167 	CK_KEY_TYPE	keytype = (CK_KEY_TYPE)~0UL;
3168 	CK_RV		rv = CKR_OK;
3169 	int		isLabel = 0;
3170 	/* Must set flags */
3171 	int		isPrime = 0;
3172 	int		isSubprime = 0;
3173 	int		isBase = 0;
3174 	/* Must not set flags */
3175 	int		isPrimeBits = 0;
3176 	int		isSubPrimeBits = 0;
3177 
3178 	biginteger_t	prime;
3179 	biginteger_t	subprime;
3180 	biginteger_t	base;
3181 	CK_ATTRIBUTE	string_tmp;
3182 
3183 	domain_obj_t	*dom;
3184 	uchar_t	object_type = 0;
3185 
3186 	/* prevent bigint_attr_cleanup from freeing invalid attr value */
3187 	(void) memset(&prime, 0x0, sizeof (biginteger_t));
3188 	(void) memset(&subprime, 0x0, sizeof (biginteger_t));
3189 	(void) memset(&base, 0x0, sizeof (biginteger_t));
3190 	string_tmp.pValue = NULL;
3191 
3192 	for (i = 0; i < ulAttrNum; i++) {
3193 
3194 		/* Domain Parameters Object Attributes */
3195 		switch (template[i].type) {
3196 
3197 		/* common domain parameter attribute */
3198 		case CKA_KEY_TYPE:
3199 			keytype = *((CK_KEY_TYPE*)template[i].pValue);
3200 			break;
3201 
3202 		/*
3203 		 * The following common domain parameter attribute
3204 		 * must not be specified by C_CreateObject.
3205 		 */
3206 		case CKA_LOCAL:
3207 			rv = CKR_TEMPLATE_INCONSISTENT;
3208 			goto fail_cleanup;
3209 
3210 		/*
3211 		 * The following domain parameter attributes must be
3212 		 * specified according to the key type by
3213 		 * C_CreateObject.
3214 		 */
3215 		case CKA_PRIME:
3216 			isPrime = 1;
3217 			/*
3218 			 * Copyin big integer attribute from template
3219 			 * to a local variable.
3220 			 */
3221 			rv = get_bigint_attr_from_template(&prime,
3222 			    &template[i]);
3223 			if (rv != CKR_OK)
3224 				goto fail_cleanup;
3225 			break;
3226 
3227 		case CKA_SUBPRIME:
3228 			isSubprime = 1;
3229 			rv = get_bigint_attr_from_template(&subprime,
3230 			    &template[i]);
3231 			if (rv != CKR_OK)
3232 				goto fail_cleanup;
3233 			break;
3234 
3235 		case CKA_BASE:
3236 			isBase = 1;
3237 			rv = get_bigint_attr_from_template(&base,
3238 			    &template[i]);
3239 			if (rv != CKR_OK)
3240 				goto fail_cleanup;
3241 			break;
3242 
3243 		case CKA_PRIME_BITS:
3244 			isPrimeBits = 1;
3245 			break;
3246 
3247 		case CKA_SUB_PRIME_BITS:
3248 			isSubPrimeBits = 1;
3249 			break;
3250 
3251 		case CKA_LABEL:
3252 			isLabel = 1;
3253 			rv = get_string_from_template(&string_tmp,
3254 			    &template[i]);
3255 			if (rv != CKR_OK)
3256 				goto fail_cleanup;
3257 			break;
3258 
3259 		default:
3260 			rv = soft_parse_common_attrs(&template[i],
3261 			    &object_type);
3262 			if (rv != CKR_OK)
3263 				goto fail_cleanup;
3264 			break;
3265 
3266 		}
3267 	} /* For */
3268 
3269 	/* Allocate storage for Domain Parameters Object. */
3270 	dom = calloc(1, sizeof (domain_obj_t));
3271 	if (dom == NULL) {
3272 		rv = CKR_HOST_MEMORY;
3273 		goto fail_cleanup;
3274 	}
3275 
3276 	new_object->object_class_u.domain = dom;
3277 	new_object->class = CKO_DOMAIN_PARAMETERS;
3278 
3279 	if (keytype == (CK_KEY_TYPE)~0UL) {
3280 		rv = CKR_TEMPLATE_INCOMPLETE;
3281 		goto fail_cleanup;
3282 	}
3283 
3284 	new_object->key_type = keytype;
3285 
3286 	/* Supported key types of the Domain Parameters Object */
3287 	switch (keytype) {
3288 	case CKK_DSA:
3289 		if (isPrimeBits || isSubPrimeBits) {
3290 			rv = CKR_TEMPLATE_INCONSISTENT;
3291 			goto fail_cleanup;
3292 		}
3293 
3294 		if (isPrime && isSubprime && isBase) {
3295 			/*
3296 			 * Copy big integer attribute value to the
3297 			 * designated place in the domain parameter
3298 			 * object.
3299 			 */
3300 			copy_bigint_attr(&prime, KEY_DOM_DSA_PRIME(dom));
3301 
3302 			copy_bigint_attr(&subprime, KEY_DOM_DSA_SUBPRIME(dom));
3303 
3304 			copy_bigint_attr(&base, KEY_DOM_DSA_BASE(dom));
3305 		} else {
3306 			rv = CKR_TEMPLATE_INCOMPLETE;
3307 			goto fail_cleanup;
3308 		}
3309 		break;
3310 
3311 	case CKK_DH:
3312 		if (isPrimeBits || isSubprime || isSubPrimeBits) {
3313 			rv = CKR_TEMPLATE_INCONSISTENT;
3314 			goto fail_cleanup;
3315 		}
3316 
3317 		if (isPrime && isBase) {
3318 			copy_bigint_attr(&prime, KEY_DOM_DH_PRIME(dom));
3319 
3320 			copy_bigint_attr(&base, KEY_DOM_DH_BASE(dom));
3321 		} else {
3322 			rv = CKR_TEMPLATE_INCOMPLETE;
3323 			goto fail_cleanup;
3324 		}
3325 		break;
3326 
3327 	case CKK_X9_42_DH:
3328 		if (isPrimeBits || isSubPrimeBits) {
3329 			rv = CKR_TEMPLATE_INCONSISTENT;
3330 			goto fail_cleanup;
3331 		}
3332 
3333 		if (isPrime && isSubprime && isBase) {
3334 			copy_bigint_attr(&prime, KEY_DOM_DH942_PRIME(dom));
3335 
3336 			copy_bigint_attr(&base, KEY_DOM_DH942_BASE(dom));
3337 
3338 			copy_bigint_attr(&subprime,
3339 			    KEY_DOM_DH942_SUBPRIME(dom));
3340 		} else {
3341 			rv = CKR_TEMPLATE_INCOMPLETE;
3342 			goto fail_cleanup;
3343 		}
3344 		break;
3345 
3346 	default:
3347 		rv = CKR_TEMPLATE_INCONSISTENT;
3348 		goto fail_cleanup;
3349 	}
3350 
3351 	new_object->object_type = object_type;
3352 
3353 	if (isLabel) {
3354 		rv = soft_add_extra_attr(&string_tmp, new_object);
3355 		if (rv != CKR_OK)
3356 			goto fail_cleanup;
3357 		string_attr_cleanup(&string_tmp);
3358 	}
3359 
3360 	return (rv);
3361 
3362 fail_cleanup:
3363 	/*
3364 	 * cleanup the storage allocated to the local variables.
3365 	 */
3366 	bigint_attr_cleanup(&prime);
3367 	bigint_attr_cleanup(&subprime);
3368 	bigint_attr_cleanup(&base);
3369 	string_attr_cleanup(&string_tmp);
3370 
3371 	/*
3372 	 * cleanup the storage allocated inside the object itself.
3373 	 */
3374 	soft_cleanup_object(new_object);
3375 
3376 	return (rv);
3377 }
3378 
3379 /*
3380  * Build a Certificate Object
3381  *
3382  * - Parse the object's template, and when an error is detected such as
3383  *   invalid attribute type, invalid attribute value, etc., return
3384  *   with appropriate return value.
3385  * - Allocate storage for the Certificate object
3386  */
3387 static CK_RV
3388 soft_build_certificate_object(CK_ATTRIBUTE_PTR template,
3389     CK_ULONG ulAttrNum, soft_object_t *new_object,
3390     CK_CERTIFICATE_TYPE cert_type)
3391 {
3392 	uint64_t	attr_mask = 0;
3393 	CK_RV		rv = CKR_OK;
3394 	CK_ULONG	i;
3395 	int		owner_set = 0;
3396 	int		value_set = 0;
3397 	int		subject_set = 0;
3398 	certificate_obj_t *cert;
3399 	/* certificate type defaults to the value given as a parameter */
3400 	CK_CERTIFICATE_TYPE certtype = cert_type;
3401 	CK_ATTRIBUTE	string_tmp;
3402 	int		isLabel = 0;
3403 	uchar_t		object_type = 0;
3404 
3405 	/*
3406 	 * Look for the certificate type attribute and do some
3407 	 * sanity checking before creating the structures.
3408 	 */
3409 	for (i = 0; i < ulAttrNum; i++) {
3410 		/* Certificate Object Attributes */
3411 		switch (template[i].type) {
3412 			case CKA_CERTIFICATE_TYPE:
3413 				certtype =
3414 				    *((CK_CERTIFICATE_TYPE*)template[i].pValue);
3415 				break;
3416 			case CKA_SUBJECT:
3417 				subject_set = 1;
3418 				break;
3419 			case CKA_OWNER:
3420 				owner_set = 1;
3421 				break;
3422 			case CKA_VALUE:
3423 				value_set = 1;
3424 				break;
3425 		}
3426 	}
3427 
3428 	/* The certificate type MUST be specified */
3429 	if (certtype != CKC_X_509 && certtype != CKC_X_509_ATTR_CERT)
3430 		return (CKR_TEMPLATE_INCOMPLETE);
3431 
3432 	/*
3433 	 * For X.509 certs, the CKA_SUBJECT and CKA_VALUE
3434 	 * must be present at creation time.
3435 	 */
3436 	if (certtype == CKC_X_509 &&
3437 	    (!subject_set || !value_set))
3438 		return (CKR_TEMPLATE_INCOMPLETE);
3439 
3440 	/*
3441 	 * For X.509 Attribute certs, the CKA_OWNER and CKA_VALUE
3442 	 * must be present at creation time.
3443 	 */
3444 	if (certtype == CKC_X_509_ATTR_CERT &&
3445 	    (!owner_set || !value_set))
3446 		return (CKR_TEMPLATE_INCOMPLETE);
3447 
3448 	string_tmp.pValue = NULL;
3449 	cert = calloc(1, sizeof (certificate_obj_t));
3450 	if (cert == NULL) {
3451 		return (CKR_HOST_MEMORY);
3452 	}
3453 	cert->certificate_type = certtype;
3454 
3455 	for (i = 0; i < ulAttrNum; i++) {
3456 		/* Certificate Object Attributes */
3457 		switch (certtype) {
3458 			case CKC_X_509:
3459 			switch (template[i].type) {
3460 				case CKA_SUBJECT:
3461 					rv = get_cert_attr_from_template(
3462 					    &cert->cert_type_u.x509.subject,
3463 					    &template[i]);
3464 					break;
3465 				case CKA_VALUE:
3466 					rv = get_cert_attr_from_template(
3467 					    &cert->cert_type_u.x509.value,
3468 					    &template[i]);
3469 					break;
3470 				case CKA_LABEL:
3471 					isLabel = 1;
3472 					rv = get_string_from_template(
3473 					    &string_tmp,
3474 					    &template[i]);
3475 					if (rv != CKR_OK)
3476 						goto fail_cleanup;
3477 					break;
3478 				case CKA_ID:
3479 				case CKA_ISSUER:
3480 				case CKA_SERIAL_NUMBER:
3481 					rv = soft_add_extra_attr(&template[i],
3482 					    new_object);
3483 					break;
3484 				case CKA_MODIFIABLE:
3485 					if ((*(CK_BBOOL *)template[i].pValue) ==
3486 					    B_FALSE)
3487 						attr_mask |=
3488 						    NOT_MODIFIABLE_BOOL_ON;
3489 					break;
3490 				case CKA_CERTIFICATE_TYPE:
3491 					break;
3492 				default:
3493 					rv = soft_parse_common_attrs(
3494 					    &template[i], &object_type);
3495 					if (rv != CKR_OK)
3496 						goto fail_cleanup;
3497 			}
3498 			break;
3499 			case CKC_X_509_ATTR_CERT:
3500 			switch (template[i].type) {
3501 				case CKA_OWNER:
3502 					rv = get_cert_attr_from_template(
3503 					    &cert->cert_type_u.x509_attr.owner,
3504 					    &template[i]);
3505 					break;
3506 				case CKA_VALUE:
3507 					rv = get_cert_attr_from_template(
3508 					    &cert->cert_type_u.x509_attr.value,
3509 					    &template[i]);
3510 					break;
3511 				case CKA_LABEL:
3512 					isLabel = 1;
3513 					rv = get_string_from_template(
3514 					    &string_tmp, &template[i]);
3515 					if (rv != CKR_OK)
3516 						goto fail_cleanup;
3517 					break;
3518 				case CKA_SERIAL_NUMBER:
3519 				case CKA_AC_ISSUER:
3520 				case CKA_ATTR_TYPES:
3521 					rv = soft_add_extra_attr(&template[i],
3522 					    new_object);
3523 					break;
3524 
3525 				case CKA_MODIFIABLE:
3526 					if ((*(CK_BBOOL *)template[i].pValue) ==
3527 					    B_FALSE)
3528 						attr_mask |=
3529 						    NOT_MODIFIABLE_BOOL_ON;
3530 					break;
3531 				case CKA_CERTIFICATE_TYPE:
3532 					break;
3533 				default:
3534 					rv = soft_parse_common_attrs(
3535 					    &template[i], &object_type);
3536 					if (rv != CKR_OK)
3537 						goto fail_cleanup;
3538 					break;
3539 			}
3540 			break;
3541 			default:
3542 				rv = CKR_TEMPLATE_INCOMPLETE;
3543 				break;
3544 		}
3545 	}
3546 
3547 	if (rv == CKR_OK) {
3548 		new_object->object_class_u.certificate = cert;
3549 		new_object->class = CKO_CERTIFICATE;
3550 		new_object->object_type = object_type;
3551 		new_object->cert_type = certtype;
3552 		new_object->bool_attr_mask = attr_mask;
3553 		if (isLabel) {
3554 			rv = soft_add_extra_attr(&string_tmp, new_object);
3555 			if (rv != CKR_OK)
3556 				goto fail_cleanup;
3557 			string_attr_cleanup(&string_tmp);
3558 		}
3559 	}
3560 
3561 fail_cleanup:
3562 	if (rv != CKR_OK) {
3563 		soft_cleanup_cert_object(new_object);
3564 	}
3565 	return (rv);
3566 }
3567 
3568 
3569 /*
3570  * Validate the attribute types in the object's template. Then,
3571  * call the appropriate build function according to the class of
3572  * the object specified in the template.
3573  *
3574  * Note: The following classes of objects are supported:
3575  * - CKO_PUBLIC_KEY
3576  * - CKO_PRIVATE_KEY
3577  * - CKO_SECRET_KEY
3578  * - CKO_DOMAIN_PARAMETERS
3579  * - CKO_CERTIFICATE
3580  *
3581  */
3582 CK_RV
3583 soft_build_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
3584     soft_object_t *new_object)
3585 {
3586 
3587 	CK_OBJECT_CLASS class = (CK_OBJECT_CLASS)~0UL;
3588 	CK_RV		rv = CKR_OK;
3589 
3590 	if (template == NULL) {
3591 		return (CKR_ARGUMENTS_BAD);
3592 	}
3593 
3594 	/* Validate the attribute type in the template. */
3595 	rv = soft_validate_attr(template, ulAttrNum, &class);
3596 	if (rv != CKR_OK)
3597 		return (rv);
3598 	/*
3599 	 * CKA_CLASS is a mandatory attribute for C_CreateObject
3600 	 */
3601 	if (class == (CK_OBJECT_CLASS)~0UL)
3602 		return (CKR_TEMPLATE_INCOMPLETE);
3603 
3604 	/*
3605 	 * Call the appropriate function based on the supported class
3606 	 * of the object.
3607 	 */
3608 	switch (class) {
3609 	case CKO_PUBLIC_KEY:
3610 		rv = soft_build_public_key_object(template, ulAttrNum,
3611 		    new_object, SOFT_CREATE_OBJ, (CK_KEY_TYPE)~0UL);
3612 		break;
3613 
3614 	case CKO_PRIVATE_KEY:
3615 		rv = soft_build_private_key_object(template, ulAttrNum,
3616 		    new_object, SOFT_CREATE_OBJ, (CK_KEY_TYPE)~0UL);
3617 		break;
3618 
3619 	case CKO_SECRET_KEY:
3620 		rv = soft_build_secret_key_object(template, ulAttrNum,
3621 		    new_object, SOFT_CREATE_OBJ, 0, (CK_KEY_TYPE)~0UL);
3622 		break;
3623 
3624 	case CKO_DOMAIN_PARAMETERS:
3625 		rv = soft_build_domain_parameters_object(template, ulAttrNum,
3626 		    new_object);
3627 		break;
3628 
3629 	case CKO_CERTIFICATE:
3630 		rv = soft_build_certificate_object(template, ulAttrNum,
3631 		    new_object, (CK_CERTIFICATE_TYPE)~0UL);
3632 		break;
3633 
3634 	case CKO_DATA:
3635 	case CKO_HW_FEATURE:
3636 	case CKO_VENDOR_DEFINED:
3637 	default:
3638 		return (CKR_ATTRIBUTE_VALUE_INVALID);
3639 	}
3640 
3641 	return (rv);
3642 }
3643 
3644 /*
3645  * Validate the attribute types in the object's template. Then,
3646  * call the appropriate build function according to the class of
3647  * the object specified in the template.
3648  *
3649  */
3650 CK_RV
3651 soft_build_key(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
3652     soft_object_t *new_object, CK_OBJECT_CLASS class, CK_KEY_TYPE key_type,
3653     CK_ULONG key_len, CK_ULONG mode)
3654 {
3655 
3656 	CK_RV		rv = CKR_OK;
3657 	CK_OBJECT_CLASS temp_class = (CK_OBJECT_CLASS)~0UL;
3658 
3659 	/* Validate the attribute type in the template. */
3660 	if ((template != NULL) && (ulAttrNum != 0)) {
3661 		rv = soft_validate_attr(template, ulAttrNum, &temp_class);
3662 		if (rv != CKR_OK)
3663 			return (rv);
3664 	}
3665 
3666 	/*
3667 	 * If either the class from the parameter list ("class") or
3668 	 * the class from the template ("temp_class") is not specified,
3669 	 * try to use the other one.
3670 	 */
3671 	if (temp_class == (CK_OBJECT_CLASS)~0UL) {
3672 		temp_class = class;
3673 	} else if (class == (CK_OBJECT_CLASS)~0UL) {
3674 		class = temp_class;
3675 	}
3676 
3677 	/* If object class is still not specified, template is incomplete. */
3678 	if (class == (CK_OBJECT_CLASS)~0UL)
3679 		return (CKR_TEMPLATE_INCOMPLETE);
3680 
3681 	/* Class should match if specified in both parameters and template. */
3682 	if (class != temp_class)
3683 		return (CKR_TEMPLATE_INCONSISTENT);
3684 
3685 	/*
3686 	 * Call the appropriate function based on the supported class
3687 	 * of the object.
3688 	 */
3689 	switch (class) {
3690 	case CKO_PUBLIC_KEY:
3691 
3692 		/* Unwrapping public keys is not supported. */
3693 		if (mode == SOFT_UNWRAP_KEY) {
3694 			rv = CKR_ATTRIBUTE_VALUE_INVALID;
3695 			break;
3696 		}
3697 
3698 		rv = soft_build_public_key_object(template, ulAttrNum,
3699 		    new_object, mode, key_type);
3700 		break;
3701 
3702 	case CKO_PRIVATE_KEY:
3703 
3704 		rv = soft_build_private_key_object(template, ulAttrNum,
3705 		    new_object, mode, key_type);
3706 		break;
3707 
3708 	case CKO_SECRET_KEY:
3709 
3710 		rv = soft_build_secret_key_object(template, ulAttrNum,
3711 		    new_object, mode, key_len, key_type);
3712 		break;
3713 
3714 	case CKO_DOMAIN_PARAMETERS:
3715 
3716 		/* Unwrapping domain parameters is not supported. */
3717 		if (mode == SOFT_UNWRAP_KEY) {
3718 			rv = CKR_ATTRIBUTE_VALUE_INVALID;
3719 			break;
3720 		}
3721 
3722 		rv = soft_build_domain_parameters_object(template, ulAttrNum,
3723 		    new_object);
3724 		break;
3725 
3726 	case CKO_DATA:
3727 	case CKO_CERTIFICATE:
3728 	case CKO_HW_FEATURE:
3729 	case CKO_VENDOR_DEFINED:
3730 	default:
3731 		return (CKR_ATTRIBUTE_VALUE_INVALID);
3732 	}
3733 
3734 	return (rv);
3735 }
3736 
3737 
3738 /*
3739  * Get the value of a requested attribute that is common to all supported
3740  * classes (i.e. public key, private key, secret key, domain parameters,
3741  * and certificate classes).
3742  */
3743 CK_RV
3744 soft_get_common_attrs(soft_object_t *object_p, CK_ATTRIBUTE_PTR template,
3745     uchar_t object_type)
3746 {
3747 
3748 	CK_RV rv = CKR_OK;
3749 
3750 	switch (template->type) {
3751 
3752 	case CKA_CLASS:
3753 		return (get_ulong_attr_from_object(object_p->class,
3754 		    template));
3755 
3756 	/* default boolean attributes */
3757 	case CKA_TOKEN:
3758 		template->ulValueLen = sizeof (CK_BBOOL);
3759 		if (template->pValue == NULL) {
3760 			return (CKR_OK);
3761 		}
3762 		if (object_type & TOKEN_OBJECT)
3763 			*((CK_BBOOL *)template->pValue) = B_TRUE;
3764 		else
3765 			*((CK_BBOOL *)template->pValue) = B_FALSE;
3766 		break;
3767 
3768 	case CKA_PRIVATE:
3769 
3770 		template->ulValueLen = sizeof (CK_BBOOL);
3771 		if (template->pValue == NULL) {
3772 			return (CKR_OK);
3773 		}
3774 		if (object_type & PRIVATE_OBJECT)
3775 			*((CK_BBOOL *)template->pValue) = B_TRUE;
3776 		else
3777 			*((CK_BBOOL *)template->pValue) = B_FALSE;
3778 		break;
3779 
3780 	case CKA_MODIFIABLE:
3781 		template->ulValueLen = sizeof (CK_BBOOL);
3782 		if (template->pValue == NULL) {
3783 			return (CKR_OK);
3784 		}
3785 		if ((object_p->bool_attr_mask) & NOT_MODIFIABLE_BOOL_ON)
3786 			*((CK_BBOOL *)template->pValue) = B_FALSE;
3787 		else
3788 			*((CK_BBOOL *)template->pValue) = B_TRUE;
3789 		break;
3790 
3791 	case CKA_LABEL:
3792 		return (get_extra_attr_from_object(object_p,
3793 		    template));
3794 
3795 	default:
3796 		/*
3797 		 * The specified attribute for the object is invalid.
3798 		 * (the object does not possess such an attribute.)
3799 		 */
3800 		template->ulValueLen = (CK_ULONG)-1;
3801 		return (CKR_ATTRIBUTE_TYPE_INVALID);
3802 	}
3803 
3804 	return (rv);
3805 }
3806 
3807 /*
3808  * Get the value of a requested attribute that is common to all key objects
3809  * (i.e. public key, private key and secret key).
3810  */
3811 CK_RV
3812 soft_get_common_key_attrs(soft_object_t *object_p, CK_ATTRIBUTE_PTR template)
3813 {
3814 
3815 	switch (template->type) {
3816 
3817 	case CKA_KEY_TYPE:
3818 		return (get_ulong_attr_from_object(object_p->key_type,
3819 		    template));
3820 
3821 	case CKA_ID:
3822 	case CKA_START_DATE:
3823 	case CKA_END_DATE:
3824 		/*
3825 		 * The above extra attributes have byte array type.
3826 		 */
3827 		return (get_extra_attr_from_object(object_p,
3828 		    template));
3829 
3830 	/* Key related boolean attributes */
3831 	case CKA_LOCAL:
3832 		return (get_bool_attr_from_object(object_p,
3833 		    LOCAL_BOOL_ON, template));
3834 
3835 	case CKA_DERIVE:
3836 		return (get_bool_attr_from_object(object_p,
3837 		    DERIVE_BOOL_ON, template));
3838 
3839 	case CKA_KEY_GEN_MECHANISM:
3840 		return (get_ulong_attr_from_object(object_p->mechanism,
3841 		    template));
3842 
3843 	default:
3844 		return (CKR_ATTRIBUTE_TYPE_INVALID);
3845 	}
3846 }
3847 
3848 /*
3849  * Get the value of a requested attribute of a Public Key Object.
3850  *
3851  * Rule: All the attributes in the public key object can be revealed.
3852  */
3853 CK_RV
3854 soft_get_public_key_attribute(soft_object_t *object_p,
3855     CK_ATTRIBUTE_PTR template)
3856 {
3857 
3858 	CK_RV		rv = CKR_OK;
3859 	CK_KEY_TYPE	keytype = object_p->key_type;
3860 
3861 	switch (template->type) {
3862 
3863 	case CKA_SUBJECT:
3864 	case CKA_EC_PARAMS:
3865 		/*
3866 		 * The above extra attributes have byte array type.
3867 		 */
3868 		return (get_extra_attr_from_object(object_p,
3869 		    template));
3870 
3871 	/* Key related boolean attributes */
3872 	case CKA_ENCRYPT:
3873 		return (get_bool_attr_from_object(object_p,
3874 		    ENCRYPT_BOOL_ON, template));
3875 
3876 	case CKA_VERIFY:
3877 		return (get_bool_attr_from_object(object_p,
3878 		    VERIFY_BOOL_ON, template));
3879 
3880 	case CKA_VERIFY_RECOVER:
3881 		return (get_bool_attr_from_object(object_p,
3882 		    VERIFY_RECOVER_BOOL_ON, template));
3883 
3884 	case CKA_WRAP:
3885 		return (get_bool_attr_from_object(object_p,
3886 		    WRAP_BOOL_ON, template));
3887 
3888 	case CKA_TRUSTED:
3889 		return (get_bool_attr_from_object(object_p,
3890 		    TRUSTED_BOOL_ON, template));
3891 
3892 	case CKA_MODULUS:
3893 		/*
3894 		 * This attribute is valid only for RSA public key
3895 		 * object.
3896 		 */
3897 		if (keytype == CKK_RSA) {
3898 			return (get_bigint_attr_from_object(
3899 			    OBJ_PUB_RSA_MOD(object_p), template));
3900 		} else {
3901 			template->ulValueLen = (CK_ULONG)-1;
3902 			return (CKR_ATTRIBUTE_TYPE_INVALID);
3903 		}
3904 
3905 	case CKA_PUBLIC_EXPONENT:
3906 		if (keytype == CKK_RSA) {
3907 			return (get_bigint_attr_from_object(
3908 			    OBJ_PUB_RSA_PUBEXPO(object_p), template));
3909 		} else {
3910 			template->ulValueLen = (CK_ULONG)-1;
3911 			return (CKR_ATTRIBUTE_TYPE_INVALID);
3912 		}
3913 
3914 	case CKA_MODULUS_BITS:
3915 		if (keytype == CKK_RSA) {
3916 			return (get_ulong_attr_from_object(
3917 			    OBJ_PUB_RSA_MOD_BITS(object_p), template));
3918 		} else {
3919 			template->ulValueLen = (CK_ULONG)-1;
3920 			return (CKR_ATTRIBUTE_TYPE_INVALID);
3921 		}
3922 
3923 	case CKA_PRIME:
3924 		switch (keytype) {
3925 		case CKK_DSA:
3926 			return (get_bigint_attr_from_object(
3927 			    OBJ_PUB_DSA_PRIME(object_p), template));
3928 
3929 		case CKK_DH:
3930 			return (get_bigint_attr_from_object(
3931 			    OBJ_PUB_DH_PRIME(object_p), template));
3932 
3933 		case CKK_X9_42_DH:
3934 			return (get_bigint_attr_from_object(
3935 			    OBJ_PUB_DH942_PRIME(object_p), template));
3936 
3937 		default:
3938 			template->ulValueLen = (CK_ULONG)-1;
3939 			return (CKR_ATTRIBUTE_TYPE_INVALID);
3940 		}
3941 
3942 	case CKA_SUBPRIME:
3943 		switch (keytype) {
3944 		case CKK_DSA:
3945 			return (get_bigint_attr_from_object(
3946 			    OBJ_PUB_DSA_SUBPRIME(object_p), template));
3947 
3948 		case CKK_X9_42_DH:
3949 			return (get_bigint_attr_from_object(
3950 			    OBJ_PUB_DH942_SUBPRIME(object_p), template));
3951 
3952 		default:
3953 			template->ulValueLen = (CK_ULONG)-1;
3954 			return (CKR_ATTRIBUTE_TYPE_INVALID);
3955 		}
3956 
3957 	case CKA_BASE:
3958 		switch (keytype) {
3959 		case CKK_DSA:
3960 			return (get_bigint_attr_from_object(
3961 			    OBJ_PUB_DSA_BASE(object_p), template));
3962 
3963 		case CKK_DH:
3964 			return (get_bigint_attr_from_object(
3965 			    OBJ_PUB_DH_BASE(object_p), template));
3966 
3967 		case CKK_X9_42_DH:
3968 			return (get_bigint_attr_from_object(
3969 			    OBJ_PUB_DH942_BASE(object_p), template));
3970 
3971 		default:
3972 			template->ulValueLen = (CK_ULONG)-1;
3973 			return (CKR_ATTRIBUTE_TYPE_INVALID);
3974 		}
3975 
3976 	case CKA_EC_POINT:
3977 		return (get_bigint_attr_from_object(
3978 		    OBJ_PUB_EC_POINT(object_p), template));
3979 
3980 	case CKA_VALUE:
3981 		switch (keytype) {
3982 		case CKK_DSA:
3983 			return (get_bigint_attr_from_object(
3984 			    OBJ_PUB_DSA_VALUE(object_p), template));
3985 
3986 		case CKK_DH:
3987 			return (get_bigint_attr_from_object(
3988 			    OBJ_PUB_DH_VALUE(object_p), template));
3989 
3990 		case CKK_X9_42_DH:
3991 			return (get_bigint_attr_from_object(
3992 			    OBJ_PUB_DH942_VALUE(object_p), template));
3993 
3994 		default:
3995 			template->ulValueLen = (CK_ULONG)-1;
3996 			return (CKR_ATTRIBUTE_TYPE_INVALID);
3997 		}
3998 
3999 	default:
4000 		/*
4001 		 * First, get the value of the request attribute defined
4002 		 * in the list of common key attributes. If the request
4003 		 * attribute is not found in that list, then get the
4004 		 * attribute from the list of common attributes.
4005 		 */
4006 		rv = soft_get_common_key_attrs(object_p, template);
4007 		if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
4008 			rv = soft_get_common_attrs(object_p, template,
4009 			    object_p->object_type);
4010 <