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 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
22 */
23#include <stdlib.h>
24#include <string.h>
25#include <security/cryptoki.h>
26#include <sys/crypto/common.h>
27#include <aes_impl.h>
28#include "kmsGlobal.h"
29#include "kmsObject.h"
30#include "kmsSession.h"
31#include "kmsSlot.h"
32
33/*
34 * This attribute table is used by the kms_lookup_attr()
35 * to validate the attributes.
36 */
37CK_ATTRIBUTE_TYPE attr_map[] = {
38	CKA_PRIVATE,
39	CKA_LABEL,
40	CKA_APPLICATION,
41	CKA_OBJECT_ID,
42	CKA_CERTIFICATE_TYPE,
43	CKA_ISSUER,
44	CKA_SERIAL_NUMBER,
45	CKA_AC_ISSUER,
46	CKA_OWNER,
47	CKA_ATTR_TYPES,
48	CKA_SUBJECT,
49	CKA_ID,
50	CKA_SENSITIVE,
51	CKA_START_DATE,
52	CKA_END_DATE,
53	CKA_MODULUS,
54	CKA_MODULUS_BITS,
55	CKA_PUBLIC_EXPONENT,
56	CKA_PRIVATE_EXPONENT,
57	CKA_PRIME_1,
58	CKA_PRIME_2,
59	CKA_EXPONENT_1,
60	CKA_EXPONENT_2,
61	CKA_COEFFICIENT,
62	CKA_PRIME,
63	CKA_SUBPRIME,
64	CKA_BASE,
65	CKA_EXTRACTABLE,
66	CKA_LOCAL,
67	CKA_NEVER_EXTRACTABLE,
68	CKA_ALWAYS_SENSITIVE,
69	CKA_MODIFIABLE,
70	CKA_ECDSA_PARAMS,
71	CKA_EC_POINT,
72	CKA_SECONDARY_AUTH,
73	CKA_AUTH_PIN_FLAGS,
74	CKA_HW_FEATURE_TYPE,
75	CKA_RESET_ON_INIT,
76	CKA_HAS_RESET
77};
78
79/*
80 * attributes that exists only in secret key objects
81 * Note: some attributes may also exist in one or two
82 *       other object classes, but they are also listed
83 *       because not all object have them.
84 */
85CK_ATTRIBUTE_TYPE SECRET_KEY_ATTRS[] =
86{
87	CKA_VALUE_LEN,
88	CKA_ENCRYPT,
89	CKA_DECRYPT,
90	CKA_WRAP,
91	CKA_UNWRAP,
92	CKA_SIGN,
93	CKA_VERIFY,
94	CKA_SENSITIVE,
95	CKA_EXTRACTABLE,
96	CKA_NEVER_EXTRACTABLE,
97	CKA_ALWAYS_SENSITIVE
98};
99
100/*
101 * Validate the attribute by using binary search algorithm.
102 */
103CK_RV
104kms_lookup_attr(CK_ATTRIBUTE_TYPE type)
105{
106	size_t lower, middle, upper;
107
108	lower = 0;
109	upper = (sizeof (attr_map) / sizeof (CK_ATTRIBUTE_TYPE)) - 1;
110
111	while (lower <= upper) {
112		/* Always starts from middle. */
113		middle = (lower + upper) / 2;
114
115		if (type > attr_map[middle]) {
116			/* Adjust the lower bound to upper half. */
117			lower = middle + 1;
118			continue;
119		}
120
121		if (type == attr_map[middle]) {
122			/* Found it. */
123			return (CKR_OK);
124		}
125
126		if (type < attr_map[middle]) {
127			/* Adjust the upper bound to lower half. */
128			upper = middle - 1;
129			continue;
130		}
131	}
132
133	/* Failed to find the matching attribute from the attribute table. */
134	return (CKR_ATTRIBUTE_TYPE_INVALID);
135}
136
137
138/*
139 * Validate the attribute by using the following search algorithm:
140 *
141 * 1) Search for the most frequently used attributes first.
142 * 2) If not found, search for the usage-purpose attributes - these
143 *    attributes have dense set of values, therefore compiler will
144 *    optimize it with a branch table and branch to the appropriate
145 *    case.
146 * 3) If still not found, use binary search for the rest of the
147 *    attributes in the attr_map[] table.
148 */
149CK_RV
150kms_validate_attr(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
151	CK_OBJECT_CLASS *class)
152{
153
154	CK_ULONG i;
155	CK_RV rv = CKR_OK;
156
157	for (i = 0; i < ulAttrNum; i++) {
158		/* First tier search */
159		switch (template[i].type) {
160		case CKA_CLASS:
161			*class = *((CK_OBJECT_CLASS*)template[i].pValue);
162			break;
163		case CKA_TOKEN:
164			break;
165		case CKA_KEY_TYPE:
166			break;
167		case CKA_VALUE:
168			break;
169		case CKA_VALUE_LEN:
170			break;
171		case CKA_VALUE_BITS:
172			break;
173		default:
174			/* Second tier search */
175			switch (template[i].type) {
176			case CKA_ENCRYPT:
177				break;
178			case CKA_DECRYPT:
179				break;
180			case CKA_WRAP:
181				break;
182			case CKA_UNWRAP:
183				break;
184			case CKA_SIGN:
185				break;
186			case CKA_SIGN_RECOVER:
187				break;
188			case CKA_VERIFY:
189				break;
190			case CKA_VERIFY_RECOVER:
191				break;
192			case CKA_DERIVE:
193				break;
194			default:
195				/* Third tier search */
196				rv = kms_lookup_attr(template[i].type);
197				if (rv != CKR_OK)
198					return (rv);
199				break;
200			}
201			break;
202		}
203	}
204	return (rv);
205}
206
207
208/*
209 * Clean up and release all the storage in the extra attribute list
210 * of an object.
211 */
212void
213kms_cleanup_extra_attr(kms_object_t *object_p)
214{
215
216	CK_ATTRIBUTE_INFO_PTR extra_attr;
217	CK_ATTRIBUTE_INFO_PTR tmp;
218
219	if (object_p == NULL)
220		return;
221
222	extra_attr = object_p->extra_attrlistp;
223	while (extra_attr) {
224		tmp = extra_attr->next;
225		if (extra_attr->attr.pValue)
226			/*
227			 * All extra attributes in the extra attribute
228			 * list have pValue points to the value of the
229			 * attribute (with simple byte array type).
230			 * Free the storage for the value of the attribute.
231			 */
232			free(extra_attr->attr.pValue);
233
234		/* Free the storage for the attribute_info struct. */
235		free(extra_attr);
236		extra_attr = tmp;
237	}
238
239	object_p->extra_attrlistp = NULL;
240}
241
242/*
243 * Create the attribute_info struct to hold the object's attribute,
244 * and add it to the extra attribute list of an object.
245 */
246CK_RV
247kms_add_extra_attr(CK_ATTRIBUTE_PTR template, kms_object_t *object_p)
248{
249
250	CK_ATTRIBUTE_INFO_PTR attrp;
251
252	/* Allocate the storage for the attribute_info struct. */
253	attrp = calloc(1, sizeof (attribute_info_t));
254	if (attrp == NULL) {
255		return (CKR_HOST_MEMORY);
256	}
257
258	/* Set up attribute_info struct. */
259	attrp->attr.type = template->type;
260	attrp->attr.ulValueLen = template->ulValueLen;
261
262	if ((template->pValue != NULL) &&
263	    (template->ulValueLen > 0)) {
264		/* Allocate storage for the value of the attribute. */
265		attrp->attr.pValue = malloc(template->ulValueLen);
266		if (attrp->attr.pValue == NULL) {
267			free(attrp);
268			return (CKR_HOST_MEMORY);
269		}
270
271		(void) memcpy(attrp->attr.pValue, template->pValue,
272		    template->ulValueLen);
273	} else {
274		attrp->attr.pValue = NULL;
275	}
276
277	/* Insert the new attribute in front of extra attribute list. */
278	if (object_p->extra_attrlistp == NULL) {
279		object_p->extra_attrlistp = attrp;
280		attrp->next = NULL;
281	} else {
282		attrp->next = object_p->extra_attrlistp;
283		object_p->extra_attrlistp = attrp;
284	}
285
286	return (CKR_OK);
287}
288
289/*
290 * Copy the attribute_info struct from the old object to a new attribute_info
291 * struct, and add that new struct to the extra attribute list of the new
292 * object.
293 */
294CK_RV
295kms_copy_extra_attr(CK_ATTRIBUTE_INFO_PTR old_attrp,
296    kms_object_t *object_p)
297{
298	CK_ATTRIBUTE_INFO_PTR attrp;
299
300	/* Allocate attribute_info struct. */
301	attrp = calloc(1, sizeof (attribute_info_t));
302	if (attrp == NULL) {
303		return (CKR_HOST_MEMORY);
304	}
305
306	attrp->attr.type = old_attrp->attr.type;
307	attrp->attr.ulValueLen = old_attrp->attr.ulValueLen;
308
309	if ((old_attrp->attr.pValue != NULL) &&
310	    (old_attrp->attr.ulValueLen > 0)) {
311		attrp->attr.pValue = malloc(old_attrp->attr.ulValueLen);
312		if (attrp->attr.pValue == NULL) {
313			free(attrp);
314			return (CKR_HOST_MEMORY);
315		}
316
317		(void) memcpy(attrp->attr.pValue, old_attrp->attr.pValue,
318		    old_attrp->attr.ulValueLen);
319	} else {
320		attrp->attr.pValue = NULL;
321	}
322
323	/* Insert the new attribute in front of extra attribute list */
324	if (object_p->extra_attrlistp == NULL) {
325		object_p->extra_attrlistp = attrp;
326		attrp->next = NULL;
327	} else {
328		attrp->next = object_p->extra_attrlistp;
329		object_p->extra_attrlistp = attrp;
330	}
331
332	return (CKR_OK);
333}
334
335/*
336 * Get the attribute triple from the extra attribute list in the object
337 * (if the specified attribute type is found), and copy it to a template.
338 * Note the type of the attribute to be copied is specified by the template,
339 * and the storage is pre-allocated for the atrribute value in the template
340 * for doing the copy.
341 */
342CK_RV
343get_extra_attr_from_object(kms_object_t *object_p, CK_ATTRIBUTE_PTR template)
344{
345	CK_ATTRIBUTE_INFO_PTR extra_attr;
346	CK_ATTRIBUTE_TYPE type = template->type;
347
348	extra_attr = object_p->extra_attrlistp;
349
350	while (extra_attr) {
351		if (type == extra_attr->attr.type) {
352			/* Found it. */
353			break;
354		} else {
355			/* Does not match, try next one. */
356			extra_attr = extra_attr->next;
357		}
358	}
359
360	if (extra_attr == NULL) {
361		/* A valid but un-initialized attribute. */
362		template->ulValueLen = 0;
363		return (CKR_OK);
364	}
365
366	/*
367	 * We found the attribute in the extra attribute list.
368	 */
369	if (template->pValue == NULL) {
370		template->ulValueLen = extra_attr->attr.ulValueLen;
371		return (CKR_OK);
372	}
373
374	if (template->ulValueLen >= extra_attr->attr.ulValueLen) {
375		/*
376		 * The buffer provided by the application is large
377		 * enough to hold the value of the attribute.
378		 */
379		(void) memcpy(template->pValue, extra_attr->attr.pValue,
380		    extra_attr->attr.ulValueLen);
381		template->ulValueLen = extra_attr->attr.ulValueLen;
382		return (CKR_OK);
383	} else {
384		/*
385		 * The buffer provided by the application does
386		 * not have enough space to hold the value.
387		 */
388		template->ulValueLen = (CK_ULONG)-1;
389		return (CKR_BUFFER_TOO_SMALL);
390	}
391}
392
393/*
394 * Modify the attribute triple in the extra attribute list of the object
395 * if the specified attribute type is found. Otherwise, just add it to
396 * list.
397 */
398CK_RV
399set_extra_attr_to_object(kms_object_t *object_p, CK_ATTRIBUTE_TYPE type,
400	CK_ATTRIBUTE_PTR template)
401{
402	CK_ATTRIBUTE_INFO_PTR extra_attr;
403
404	extra_attr = object_p->extra_attrlistp;
405
406	while (extra_attr) {
407		if (type == extra_attr->attr.type) {
408			/* Found it. */
409			break;
410		} else {
411			/* Does not match, try next one. */
412			extra_attr = extra_attr->next;
413		}
414	}
415
416	if (extra_attr == NULL) {
417		/*
418		 * This attribute is a new one, go ahead adding it to
419		 * the extra attribute list.
420		 */
421		return (kms_add_extra_attr(template, object_p));
422	}
423
424	/* We found the attribute in the extra attribute list. */
425	if ((template->pValue != NULL) &&
426	    (template->ulValueLen > 0)) {
427		if (template->ulValueLen > extra_attr->attr.ulValueLen) {
428			/* The old buffer is too small to hold the new value. */
429			if (extra_attr->attr.pValue != NULL)
430				/* Free storage for the old attribute value. */
431				free(extra_attr->attr.pValue);
432
433			/* Allocate storage for the new attribute value. */
434			extra_attr->attr.pValue = malloc(template->ulValueLen);
435			if (extra_attr->attr.pValue == NULL) {
436				return (CKR_HOST_MEMORY);
437			}
438		}
439
440		/* Replace the attribute with new value. */
441		extra_attr->attr.ulValueLen = template->ulValueLen;
442		(void) memcpy(extra_attr->attr.pValue, template->pValue,
443		    template->ulValueLen);
444	} else {
445		extra_attr->attr.pValue = NULL;
446	}
447
448	return (CKR_OK);
449}
450
451/*
452 * Copy the boolean data type attribute value from an object for the
453 * specified attribute to the template.
454 */
455CK_RV
456get_bool_attr_from_object(kms_object_t *object_p, CK_ULONG bool_flag,
457	CK_ATTRIBUTE_PTR template)
458{
459
460	if (template->pValue == NULL) {
461		template->ulValueLen = sizeof (CK_BBOOL);
462		return (CKR_OK);
463	}
464
465	if (template->ulValueLen >= sizeof (CK_BBOOL)) {
466		/*
467		 * The buffer provided by the application is large
468		 * enough to hold the value of the attribute.
469		 */
470		if (object_p->bool_attr_mask & bool_flag) {
471			*((CK_BBOOL *)template->pValue) = B_TRUE;
472		} else {
473			*((CK_BBOOL *)template->pValue) = B_FALSE;
474		}
475
476		template->ulValueLen = sizeof (CK_BBOOL);
477		return (CKR_OK);
478	} else {
479		/*
480		 * The buffer provided by the application does
481		 * not have enough space to hold the value.
482		 */
483		template->ulValueLen = (CK_ULONG)-1;
484		return (CKR_BUFFER_TOO_SMALL);
485	}
486}
487
488/*
489 * Set the boolean data type attribute value in the object.
490 */
491CK_RV
492set_bool_attr_to_object(kms_object_t *object_p, CK_ULONG bool_flag,
493	CK_ATTRIBUTE_PTR template)
494{
495
496	if (*(CK_BBOOL *)template->pValue)
497		object_p->bool_attr_mask |= bool_flag;
498	else
499		object_p->bool_attr_mask &= ~bool_flag;
500
501	return (CKR_OK);
502}
503
504
505/*
506 * Copy the CK_ULONG data type attribute value from an object to the
507 * template.
508 */
509CK_RV
510get_ulong_attr_from_object(CK_ULONG value, CK_ATTRIBUTE_PTR template)
511{
512
513	if (template->pValue == NULL) {
514		template->ulValueLen = sizeof (CK_ULONG);
515		return (CKR_OK);
516	}
517
518	if (template->ulValueLen >= sizeof (CK_ULONG)) {
519		/*
520		 * The buffer provided by the application is large
521		 * enough to hold the value of the attribute.
522		 */
523		*(CK_ULONG_PTR)template->pValue = value;
524		template->ulValueLen = sizeof (CK_ULONG);
525		return (CKR_OK);
526	} else {
527		/*
528		 * The buffer provided by the application does
529		 * not have enough space to hold the value.
530		 */
531		template->ulValueLen = (CK_ULONG)-1;
532		return (CKR_BUFFER_TOO_SMALL);
533	}
534}
535
536CK_RV
537get_string_from_template(CK_ATTRIBUTE_PTR dest, CK_ATTRIBUTE_PTR src)
538{
539	if ((src->pValue != NULL) &&
540	    (src->ulValueLen > 0)) {
541		/* Allocate storage for the value of the attribute. */
542		dest->pValue = malloc(src->ulValueLen);
543		if (dest->pValue == NULL) {
544			return (CKR_HOST_MEMORY);
545		}
546
547		(void) memcpy(dest->pValue, src->pValue,
548		    src->ulValueLen);
549		dest->ulValueLen = src->ulValueLen;
550		dest->type = src->type;
551	} else {
552		dest->pValue = NULL;
553		dest->ulValueLen = 0;
554		dest->type = src->type;
555	}
556
557	return (CKR_OK);
558
559}
560
561void
562string_attr_cleanup(CK_ATTRIBUTE_PTR template)
563{
564
565	if (template->pValue) {
566		free(template->pValue);
567		template->pValue = NULL;
568		template->ulValueLen = 0;
569	}
570}
571
572/*
573 * Parse the common attributes. Return to caller with appropriate return
574 * value to indicate if the supplied template specifies a valid attribute
575 * with a valid value.
576 */
577static CK_RV
578kms_parse_common_attrs(CK_ATTRIBUTE_PTR template, uint64_t *attr_mask_p)
579{
580	CK_RV rv = CKR_OK;
581	kms_slot_t *pslot = get_slotinfo();
582
583	switch (template->type) {
584	case CKA_CLASS:
585		break;
586	case CKA_TOKEN:
587		if ((*(CK_BBOOL *)template->pValue) == TRUE)
588			*attr_mask_p |= TOKEN_BOOL_ON;
589		break;
590
591	case CKA_PRIVATE:
592		if ((*(CK_BBOOL *)template->pValue) == TRUE) {
593			/*
594			 * Cannot create a private object if the token
595			 * has a keystore and the user isn't logged in.
596			 */
597			if (pslot->sl_state != CKU_USER) {
598				rv = CKR_ATTRIBUTE_VALUE_INVALID;
599			} else {
600				*attr_mask_p |= PRIVATE_BOOL_ON;
601			}
602		}
603		break;
604
605	case CKA_MODIFIABLE:
606		if ((*(CK_BBOOL *)template->pValue) == FALSE) {
607			*attr_mask_p &= ~MODIFIABLE_BOOL_ON;
608		}
609		break;
610
611	case CKA_LABEL:
612		break;
613
614	default:
615		rv = CKR_TEMPLATE_INCONSISTENT;
616	}
617
618	return (rv);
619}
620
621/*
622 * Build a Secret Key Object.
623 *
624 * - Parse the object's template, and when an error is detected such as
625 *   invalid attribute type, invalid attribute value, etc., return
626 *   with appropriate return value.
627 * - Set up attribute mask field in the object for the supplied common
628 *   attributes that have boolean type.
629 * - Build the attribute_info struct to hold the value of each supplied
630 *   attribute that has byte array type. Link attribute_info structs
631 *   together to form the extra attribute list of the object.
632 * - Allocate storage for the Secret Key object.
633 * - Build the Secret Key object. Allocate storage to hold the big integer
634 *   value for the attribute CKA_VALUE that is required for all the key
635 *   types supported by secret key object.
636 *
637 */
638CK_RV
639kms_build_secret_key_object(CK_ATTRIBUTE_PTR template,
640    CK_ULONG ulAttrNum,	kms_object_t *new_object)
641{
642	int		i;
643	CK_KEY_TYPE	keytype = (CK_KEY_TYPE)~0UL;
644	uint64_t	attr_mask;
645	CK_RV 		rv = CKR_OK;
646	int		isLabel = 0;
647	/* Must not set flags */
648	int		isValueLen = 0;
649	CK_ATTRIBUTE	string_tmp;
650	secret_key_obj_t  *sck;
651
652	string_tmp.pValue = NULL;
653
654	/*
655	 * If the object was pulled from the KMS, the
656	 * attributes are encoded in the object record
657	 * before this function is called, we don't
658	 * want to overwrite them unless the attribute
659	 * template says differently.
660	 */
661	if (new_object->bool_attr_mask != 0)
662		attr_mask = new_object->bool_attr_mask;
663	else
664		attr_mask = SECRET_KEY_DEFAULT;
665
666	/* Allocate storage for Secret Key Object. */
667	sck = calloc(1, sizeof (secret_key_obj_t));
668	if (sck == NULL) {
669		rv = CKR_HOST_MEMORY;
670		goto fail_cleanup;
671	}
672
673	new_object->object_class_u.secret_key = sck;
674	new_object->class = CKO_SECRET_KEY;
675
676	for (i = 0; i < ulAttrNum; i++) {
677
678		/* Secret Key Object Attributes */
679		switch (template[i].type) {
680
681		/* common key attributes */
682		case CKA_KEY_TYPE:
683		keytype = *((CK_KEY_TYPE*)template[i].pValue);
684			break;
685
686		case CKA_ID:
687		case CKA_START_DATE:
688		case CKA_END_DATE:
689			/*
690			 * Allocate storage to hold the attribute
691			 * value with byte array type, and add it to
692			 * the extra attribute list of the object.
693			 */
694			rv = kms_add_extra_attr(&template[i],
695			    new_object);
696			if (rv != CKR_OK) {
697				goto fail_cleanup;
698			}
699			break;
700
701		/*
702		 * The following key related attribute types must
703		 * not be specified by C_CreateObject.
704		 */
705		case CKA_LOCAL:
706		case CKA_KEY_GEN_MECHANISM:
707		case CKA_ALWAYS_SENSITIVE:
708		case CKA_NEVER_EXTRACTABLE:
709			rv = CKR_TEMPLATE_INCONSISTENT;
710			goto fail_cleanup;
711
712		/* Key related boolean attributes */
713		case CKA_DERIVE:
714			if (*(CK_BBOOL *)template[i].pValue)
715				attr_mask |= DERIVE_BOOL_ON;
716			break;
717
718		case CKA_SENSITIVE:
719			if (*(CK_BBOOL *)template[i].pValue)
720				attr_mask |= SENSITIVE_BOOL_ON;
721			break;
722
723		case CKA_ENCRYPT:
724			if (*(CK_BBOOL *)template[i].pValue)
725				attr_mask |= ENCRYPT_BOOL_ON;
726			else
727				attr_mask &= ~ENCRYPT_BOOL_ON;
728			break;
729
730		case CKA_DECRYPT:
731			if (*(CK_BBOOL *)template[i].pValue)
732				attr_mask |= DECRYPT_BOOL_ON;
733			else
734				attr_mask &= ~DECRYPT_BOOL_ON;
735			break;
736
737		case CKA_SIGN:
738			if (*(CK_BBOOL *)template[i].pValue)
739				attr_mask |= SIGN_BOOL_ON;
740			else
741				attr_mask &= ~SIGN_BOOL_ON;
742			break;
743
744		case CKA_VERIFY:
745			if (*(CK_BBOOL *)template[i].pValue)
746				attr_mask |= VERIFY_BOOL_ON;
747			else
748				attr_mask &= ~VERIFY_BOOL_ON;
749			break;
750
751		case CKA_WRAP:
752			if (*(CK_BBOOL *)template[i].pValue)
753				attr_mask |= WRAP_BOOL_ON;
754			break;
755
756		case CKA_UNWRAP:
757			if (*(CK_BBOOL *)template[i].pValue)
758				attr_mask |= UNWRAP_BOOL_ON;
759			break;
760
761		case CKA_EXTRACTABLE:
762			if (*(CK_BBOOL *)template[i].pValue)
763				attr_mask |= EXTRACTABLE_BOOL_ON;
764			else
765				attr_mask &= ~EXTRACTABLE_BOOL_ON;
766			break;
767
768		case CKA_VALUE:
769			if ((template[i].ulValueLen == 0) ||
770			    (template[i].pValue == NULL)) {
771				rv = CKR_ATTRIBUTE_VALUE_INVALID;
772				goto fail_cleanup;
773			}
774			/*
775			 * Copyin attribute from template
776			 * to a local variable.
777			 */
778			sck->sk_value = malloc(template[i].ulValueLen);
779			if (sck->sk_value == NULL) {
780				rv = CKR_HOST_MEMORY;
781				goto fail_cleanup;
782			}
783			(void) memcpy(sck->sk_value, template[i].pValue,
784			    template[i].ulValueLen);
785			sck->sk_value_len = template[i].ulValueLen;
786			break;
787
788		case CKA_VALUE_LEN:
789			isValueLen = 1;
790			if (template[i].pValue != NULL)
791				sck->sk_value_len =
792				    *(CK_ULONG_PTR)template[i].pValue;
793			else
794				sck->sk_value_len = 0;
795			break;
796
797		case CKA_LABEL:
798			isLabel = 1;
799			rv = get_string_from_template(&string_tmp,
800			    &template[i]);
801			if (rv != CKR_OK)
802				goto fail_cleanup;
803			break;
804
805		default:
806			rv = kms_parse_common_attrs(&template[i], &attr_mask);
807			if (rv != CKR_OK)
808				goto fail_cleanup;
809			break;
810
811		}
812	} /* For */
813
814	if (keytype == (CK_KEY_TYPE)~0UL) {
815		rv = CKR_TEMPLATE_INCOMPLETE;
816		goto fail_cleanup;
817	}
818
819	new_object->key_type = keytype;
820
821	/* Supported key types of the Secret Key Object */
822	switch (keytype) {
823
824	case CKK_AES:
825		if (!isValueLen) {
826			rv = CKR_TEMPLATE_INCOMPLETE;
827			goto fail_cleanup;
828		}
829		if (sck->sk_value_len != AES_MIN_KEY_BYTES &&
830		    sck->sk_value_len != AES_192_KEY_BYTES &&
831		    sck->sk_value_len != AES_MAX_KEY_BYTES) {
832			rv = CKR_ATTRIBUTE_VALUE_INVALID;
833			goto fail_cleanup;
834		}
835		break;
836
837	case CKK_RC4:
838	case CKK_GENERIC_SECRET:
839	case CKK_BLOWFISH:
840	case CKK_DES:
841	case CKK_DES2:
842	case CKK_DES3:
843	default:
844		rv = CKR_TEMPLATE_INCONSISTENT;
845		goto fail_cleanup;
846	}
847
848	/* Set up object. */
849	new_object->bool_attr_mask = attr_mask;
850	if (isLabel) {
851		rv = kms_add_extra_attr(&string_tmp, new_object);
852		if (rv != CKR_OK)
853			goto fail_cleanup;
854		string_attr_cleanup(&string_tmp);
855	}
856
857	return (rv);
858
859fail_cleanup:
860	/*
861	 * cleanup the storage allocated to the local variables.
862	 */
863	string_attr_cleanup(&string_tmp);
864
865	/*
866	 * cleanup the storage allocated inside the object itself.
867	 */
868	kms_cleanup_object(new_object);
869
870	return (rv);
871}
872
873/*
874 * Validate the attribute types in the object's template. Then,
875 * call the appropriate build function according to the class of
876 * the object specified in the template.
877 *
878 * Note: The following classes of objects are supported:
879 * - CKO_SECRET_KEY
880 */
881CK_RV
882kms_build_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
883    kms_object_t *new_object)
884{
885	CK_OBJECT_CLASS class = (CK_OBJECT_CLASS)~0UL;
886	CK_RV 		rv = CKR_OK;
887
888	if (template == NULL) {
889		return (CKR_ARGUMENTS_BAD);
890	}
891
892	/* Validate the attribute type in the template. */
893	rv = kms_validate_attr(template, ulAttrNum, &class);
894	if (rv != CKR_OK)
895		return (rv);
896
897	if (class == (CK_OBJECT_CLASS)~0UL)
898		return (CKR_TEMPLATE_INCOMPLETE);
899
900	/*
901	 * Call the appropriate function based on the supported class
902	 * of the object.
903	 */
904	switch (class) {
905
906	case CKO_SECRET_KEY:
907		rv = kms_build_secret_key_object(template, ulAttrNum,
908		    new_object);
909		break;
910
911	case CKO_DOMAIN_PARAMETERS:
912	case CKO_DATA:
913	case CKO_CERTIFICATE:
914	case CKO_HW_FEATURE:
915	case CKO_VENDOR_DEFINED:
916	case CKO_PUBLIC_KEY:
917	case CKO_PRIVATE_KEY:
918	default:
919		return (CKR_ATTRIBUTE_VALUE_INVALID);
920	}
921
922	return (rv);
923}
924
925
926/*
927 * Get the value of a requested attribute that is common to all supported
928 * classes (i.e. public key, private key, secret key classes).
929 */
930CK_RV
931kms_get_common_attrs(kms_object_t *object_p, CK_ATTRIBUTE_PTR template)
932{
933
934	CK_RV rv = CKR_OK;
935
936	switch (template->type) {
937
938	case CKA_CLASS:
939		return (get_ulong_attr_from_object(object_p->class,
940		    template));
941
942	/* default boolean attributes */
943	case CKA_TOKEN:
944		template->ulValueLen = sizeof (CK_BBOOL);
945		if (template->pValue == NULL) {
946			return (CKR_OK);
947		}
948
949		*((CK_BBOOL *)template->pValue) = B_FALSE;
950		break;
951
952	case CKA_PRIVATE:
953
954		template->ulValueLen = sizeof (CK_BBOOL);
955		if (template->pValue == NULL) {
956			return (CKR_OK);
957		}
958		if (object_p->bool_attr_mask & PRIVATE_BOOL_ON) {
959			*((CK_BBOOL *)template->pValue) = B_TRUE;
960		} else {
961			*((CK_BBOOL *)template->pValue) = B_FALSE;
962		}
963		break;
964
965	case CKA_MODIFIABLE:
966		template->ulValueLen = sizeof (CK_BBOOL);
967		if (template->pValue == NULL) {
968			return (CKR_OK);
969		}
970		if ((object_p->bool_attr_mask) & MODIFIABLE_BOOL_ON)
971			*((CK_BBOOL *)template->pValue) = B_TRUE;
972		else
973			*((CK_BBOOL *)template->pValue) = B_FALSE;
974		break;
975
976	case CKA_LABEL:
977		return (get_extra_attr_from_object(object_p,
978		    template));
979		break;
980
981	default:
982		/*
983		 * The specified attribute for the object is invalid.
984		 * (the object does not possess such an attribute.)
985		 */
986		template->ulValueLen = (CK_ULONG)-1;
987		return (CKR_ATTRIBUTE_TYPE_INVALID);
988	}
989
990	return (rv);
991}
992
993/*
994 * Get the value of a requested attribute that is common to all key objects
995 * (i.e. public key, private key and secret key).
996 */
997CK_RV
998kms_get_common_key_attrs(kms_object_t *object_p,
999    CK_ATTRIBUTE_PTR template)
1000{
1001
1002	switch (template->type) {
1003
1004	case CKA_KEY_TYPE:
1005		return (get_ulong_attr_from_object(object_p->key_type,
1006		    template));
1007
1008	case CKA_ID:
1009	case CKA_START_DATE:
1010	case CKA_END_DATE:
1011		/*
1012		 * The above extra attributes have byte array type.
1013		 */
1014		return (get_extra_attr_from_object(object_p,
1015		    template));
1016
1017	/* Key related boolean attributes */
1018	case CKA_LOCAL:
1019		return (get_bool_attr_from_object(object_p,
1020		    LOCAL_BOOL_ON, template));
1021
1022	case CKA_DERIVE:
1023		return (get_bool_attr_from_object(object_p,
1024		    DERIVE_BOOL_ON, template));
1025
1026	case CKA_KEY_GEN_MECHANISM:
1027		return (get_ulong_attr_from_object(object_p->mechanism,
1028		    template));
1029
1030	default:
1031		return (CKR_ATTRIBUTE_TYPE_INVALID);
1032	}
1033}
1034
1035/*
1036 * Get the value of a requested attribute of a Secret Key Object.
1037 *
1038 * Rule: All the attributes in the secret key object can be revealed
1039 *       except those marked with footnote number "7" when the object
1040 *       has its CKA_SENSITIVE attribute set to TRUE or its
1041 *       CKA_EXTRACTABLE attribute set to FALSE.
1042 */
1043CK_RV
1044kms_get_secret_key_attribute(kms_object_t *object_p,
1045    CK_ATTRIBUTE_PTR template)
1046{
1047
1048	CK_RV		rv = CKR_OK;
1049	CK_KEY_TYPE	keytype = object_p->key_type;
1050
1051	switch (template->type) {
1052
1053	/* Key related boolean attributes */
1054	case CKA_SENSITIVE:
1055		return (get_bool_attr_from_object(object_p,
1056		    SENSITIVE_BOOL_ON, template));
1057
1058	case CKA_ENCRYPT:
1059		return (get_bool_attr_from_object(object_p,
1060		    ENCRYPT_BOOL_ON, template));
1061
1062	case CKA_DECRYPT:
1063		return (get_bool_attr_from_object(object_p,
1064		    DECRYPT_BOOL_ON, template));
1065
1066	case CKA_SIGN:
1067		return (get_bool_attr_from_object(object_p,
1068		    SIGN_BOOL_ON, template));
1069
1070	case CKA_VERIFY:
1071		return (get_bool_attr_from_object(object_p,
1072		    VERIFY_BOOL_ON, template));
1073
1074	case CKA_WRAP:
1075		return (get_bool_attr_from_object(object_p,
1076		    WRAP_BOOL_ON, template));
1077
1078	case CKA_UNWRAP:
1079		return (get_bool_attr_from_object(object_p,
1080		    UNWRAP_BOOL_ON, template));
1081
1082	case CKA_EXTRACTABLE:
1083		return (get_bool_attr_from_object(object_p,
1084		    EXTRACTABLE_BOOL_ON, template));
1085
1086	case CKA_ALWAYS_SENSITIVE:
1087		return (get_bool_attr_from_object(object_p,
1088		    ALWAYS_SENSITIVE_BOOL_ON, template));
1089
1090	case CKA_NEVER_EXTRACTABLE:
1091		return (get_bool_attr_from_object(object_p,
1092		    NEVER_EXTRACTABLE_BOOL_ON, template));
1093
1094	case CKA_VALUE:
1095		/*
1096		 * If the specified attribute for the secret key object
1097		 * cannot be revealed because the object is sensitive
1098		 * or unextractable, then the ulValueLen is set to -1.
1099		 */
1100		if ((object_p->bool_attr_mask & SENSITIVE_BOOL_ON) ||
1101		    !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
1102			template->ulValueLen = (CK_ULONG)-1;
1103			return (CKR_ATTRIBUTE_SENSITIVE);
1104		}
1105
1106		switch (keytype) {
1107		case CKK_AES:
1108			/*
1109			 * Copy secret key object attributes to template.
1110			 */
1111			if (template->pValue == NULL) {
1112				template->ulValueLen =
1113				    OBJ_SEC_VALUE_LEN(object_p);
1114				return (CKR_OK);
1115			}
1116
1117			if (OBJ_SEC_VALUE(object_p) == NULL) {
1118				template->ulValueLen = 0;
1119				return (CKR_OK);
1120			}
1121
1122			if (template->ulValueLen >=
1123			    OBJ_SEC_VALUE_LEN(object_p)) {
1124				(void) memcpy(template->pValue,
1125				    OBJ_SEC_VALUE(object_p),
1126				    OBJ_SEC_VALUE_LEN(object_p));
1127				template->ulValueLen =
1128				    OBJ_SEC_VALUE_LEN(object_p);
1129				return (CKR_OK);
1130			} else {
1131				template->ulValueLen = (CK_ULONG)-1;
1132				return (CKR_BUFFER_TOO_SMALL);
1133			}
1134
1135		case CKK_RC4:
1136		case CKK_GENERIC_SECRET:
1137		case CKK_RC5:
1138		case CKK_DES:
1139		case CKK_DES2:
1140		case CKK_DES3:
1141		case CKK_CDMF:
1142		case CKK_BLOWFISH:
1143		default:
1144			template->ulValueLen = (CK_ULONG)-1;
1145			rv = CKR_ATTRIBUTE_TYPE_INVALID;
1146			break;
1147		}
1148		break;
1149
1150	case CKA_VALUE_LEN:
1151		return (get_ulong_attr_from_object(OBJ_SEC_VALUE_LEN(object_p),
1152		    template));
1153
1154	default:
1155		/*
1156		 * First, get the value of the request attribute defined
1157		 * in the list of common key attributes. If the request
1158		 * attribute is not found in that list, then get the
1159		 * attribute from the list of common attributes.
1160		 */
1161		rv = kms_get_common_key_attrs(object_p, template);
1162		if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
1163			rv = kms_get_common_attrs(object_p, template);
1164		}
1165		break;
1166	}
1167
1168	return (rv);
1169
1170}
1171
1172/*
1173 * Call the appropriate get attribute function according to the class
1174 * of object.
1175 *
1176 * The caller of this function holds the lock on the object.
1177 */
1178CK_RV
1179kms_get_attribute(kms_object_t *object_p, CK_ATTRIBUTE_PTR template)
1180{
1181
1182	CK_RV		rv = CKR_OK;
1183	CK_OBJECT_CLASS class = object_p->class;
1184
1185	switch (class) {
1186	case CKO_SECRET_KEY:
1187		rv = kms_get_secret_key_attribute(object_p, template);
1188		break;
1189
1190	case CKO_PRIVATE_KEY:
1191	case CKO_PUBLIC_KEY:
1192	default:
1193		/*
1194		 * If the specified attribute for the object is invalid
1195		 * (the object does not possess such as attribute), then
1196		 * the ulValueLen is modified to hold the value -1.
1197		 */
1198		template->ulValueLen = (CK_ULONG)-1;
1199		return (CKR_ATTRIBUTE_TYPE_INVALID);
1200	}
1201
1202	return (rv);
1203
1204}
1205
1206/*
1207 * Set the value of an attribute that is common to all key objects
1208 * (i.e. public key, private key and secret key).
1209 */
1210static CK_RV
1211kms_set_common_key_attribute(kms_object_t *object_p,
1212    CK_ATTRIBUTE_PTR template, boolean_t copy)
1213{
1214
1215	kms_slot_t *pslot = get_slotinfo();
1216	CK_RV rv = CKR_OK;
1217
1218	switch (template->type) {
1219
1220	case CKA_LABEL:
1221		/*
1222		 * Only the LABEL can be modified in the common storage
1223		 * object attributes after the object is created.
1224		 */
1225		return (set_extra_attr_to_object(object_p,
1226		    CKA_LABEL, template));
1227
1228	case CKA_ID:
1229		return (set_extra_attr_to_object(object_p,
1230		    CKA_ID, template));
1231
1232	case CKA_START_DATE:
1233		return (set_extra_attr_to_object(object_p,
1234		    CKA_START_DATE, template));
1235
1236	case CKA_END_DATE:
1237		return (set_extra_attr_to_object(object_p,
1238		    CKA_END_DATE, template));
1239
1240	case CKA_DERIVE:
1241		return (set_bool_attr_to_object(object_p,
1242		    DERIVE_BOOL_ON, template));
1243
1244	case CKA_CLASS:
1245	case CKA_KEY_TYPE:
1246	case CKA_LOCAL:
1247		return (CKR_ATTRIBUTE_READ_ONLY);
1248
1249	case CKA_PRIVATE:
1250		if (!copy) {
1251			/* called from C_SetAttributeValue() */
1252			return (CKR_ATTRIBUTE_READ_ONLY);
1253		}
1254
1255		/* called from C_CopyObject() */
1256		if ((*(CK_BBOOL *)template->pValue) != B_TRUE) {
1257			return (CKR_OK);
1258		}
1259
1260		(void) pthread_mutex_lock(&pslot->sl_mutex);
1261		/*
1262		 * Cannot create a private object if the token
1263		 * has a keystore and the user isn't logged in.
1264		 */
1265		if (pslot->sl_state != CKU_USER) {
1266			rv = CKR_USER_NOT_LOGGED_IN;
1267		} else {
1268			rv = set_bool_attr_to_object(object_p,
1269			    PRIVATE_BOOL_ON, template);
1270		}
1271		(void) pthread_mutex_unlock(&pslot->sl_mutex);
1272		return (rv);
1273
1274	case CKA_MODIFIABLE:
1275		if (copy) {
1276			rv = set_bool_attr_to_object(object_p,
1277			    MODIFIABLE_BOOL_ON, template);
1278		} else {
1279			rv = CKR_ATTRIBUTE_READ_ONLY;
1280		}
1281		return (rv);
1282
1283	default:
1284		return (CKR_TEMPLATE_INCONSISTENT);
1285	}
1286
1287}
1288
1289/*
1290 * Set the value of an attribute of a Secret Key Object.
1291 *
1292 * Rule: The attributes marked with footnote number "8" in the PKCS11
1293 *       spec may be modified (p.88 in PKCS11 spec.).
1294 */
1295static CK_RV
1296kms_set_secret_key_attribute(kms_object_t *object_p,
1297    CK_ATTRIBUTE_PTR template, boolean_t copy)
1298{
1299	CK_KEY_TYPE	keytype = object_p->key_type;
1300
1301	switch (template->type) {
1302
1303	case CKA_SENSITIVE:
1304		/*
1305		 * Cannot set SENSITIVE to FALSE if it is already ON.
1306		 */
1307		if (((*(CK_BBOOL *)template->pValue) == B_FALSE) &&
1308		    (object_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
1309			return (CKR_ATTRIBUTE_READ_ONLY);
1310		}
1311
1312		if (*(CK_BBOOL *)template->pValue)
1313			object_p->bool_attr_mask |= SENSITIVE_BOOL_ON;
1314		return (CKR_OK);
1315
1316	case CKA_ENCRYPT:
1317		return (set_bool_attr_to_object(object_p,
1318		    ENCRYPT_BOOL_ON, template));
1319
1320	case CKA_DECRYPT:
1321		return (set_bool_attr_to_object(object_p,
1322		    DECRYPT_BOOL_ON, template));
1323
1324	case CKA_SIGN:
1325		return (set_bool_attr_to_object(object_p,
1326		    SIGN_BOOL_ON, template));
1327
1328	case CKA_VERIFY:
1329		return (set_bool_attr_to_object(object_p,
1330		    VERIFY_BOOL_ON, template));
1331
1332	case CKA_WRAP:
1333		return (set_bool_attr_to_object(object_p,
1334		    WRAP_BOOL_ON, template));
1335
1336	case CKA_UNWRAP:
1337		return (set_bool_attr_to_object(object_p,
1338		    UNWRAP_BOOL_ON, template));
1339
1340	case CKA_EXTRACTABLE:
1341		/*
1342		 * Cannot set EXTRACTABLE to TRUE if it is already OFF.
1343		 */
1344		if ((*(CK_BBOOL *)template->pValue) &&
1345		    !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
1346			return (CKR_ATTRIBUTE_READ_ONLY);
1347		}
1348
1349		if ((*(CK_BBOOL *)template->pValue) == B_FALSE)
1350			object_p->bool_attr_mask &= ~EXTRACTABLE_BOOL_ON;
1351		return (CKR_OK);
1352
1353	case CKA_VALUE:
1354		return (CKR_ATTRIBUTE_READ_ONLY);
1355
1356	case CKA_VALUE_LEN:
1357		if ((keytype == CKK_RC4) ||
1358		    (keytype == CKK_GENERIC_SECRET) ||
1359		    (keytype == CKK_AES) ||
1360		    (keytype == CKK_BLOWFISH))
1361			return (CKR_ATTRIBUTE_READ_ONLY);
1362		break;
1363
1364	default:
1365		/*
1366		 * Set the value of a common key attribute.
1367		 */
1368		return (kms_set_common_key_attribute(object_p,
1369		    template, copy));
1370	}
1371
1372	/*
1373	 * If we got this far, then the combination of key type
1374	 * and requested attribute is invalid.
1375	 */
1376	return (CKR_ATTRIBUTE_TYPE_INVALID);
1377}
1378
1379/*
1380 * Call the appropriate set attribute function according to the class
1381 * of object.
1382 *
1383 * The caller of this function does not hold the lock on the original
1384 * object, since this function is setting the attribute on the new object
1385 * that is being modified.
1386 *
1387 */
1388CK_RV
1389kms_set_attribute(kms_object_t *object_p, CK_ATTRIBUTE_PTR template,
1390    boolean_t copy)
1391{
1392
1393	CK_RV		rv = CKR_OK;
1394	CK_OBJECT_CLASS	class = object_p->class;
1395
1396	switch (class) {
1397
1398	case CKO_SECRET_KEY:
1399		rv = kms_set_secret_key_attribute(object_p, template,
1400		    copy);
1401		break;
1402
1403	case CKO_PUBLIC_KEY:
1404	case CKO_PRIVATE_KEY:
1405	default:
1406		/*
1407		 * If the template specifies a value of an attribute
1408		 * which is incompatible with other existing attributes
1409		 * of the object, then fails with return code
1410		 * CKR_TEMPLATE_INCONSISTENT.
1411		 */
1412		rv = CKR_TEMPLATE_INCONSISTENT;
1413		break;
1414	}
1415
1416	return (rv);
1417}
1418
1419CK_RV
1420kms_copy_secret_key_attr(secret_key_obj_t *old_secret_key_obj_p,
1421    secret_key_obj_t **new_secret_key_obj_p)
1422{
1423	secret_key_obj_t *sk;
1424
1425	sk = malloc(sizeof (secret_key_obj_t));
1426	if (sk == NULL) {
1427		return (CKR_HOST_MEMORY);
1428	}
1429	(void) memcpy(sk, old_secret_key_obj_p, sizeof (secret_key_obj_t));
1430
1431	/* copy the secret key value */
1432	sk->sk_value = malloc((sizeof (CK_BYTE) * sk->sk_value_len));
1433	if (sk->sk_value == NULL) {
1434		free(sk);
1435		return (CKR_HOST_MEMORY);
1436	}
1437	(void) memcpy(sk->sk_value, old_secret_key_obj_p->sk_value,
1438	    (sizeof (CK_BYTE) * sk->sk_value_len));
1439
1440	*new_secret_key_obj_p = sk;
1441
1442	return (CKR_OK);
1443}
1444
1445
1446
1447/*
1448 * If CKA_CLASS not given, guess CKA_CLASS using
1449 * attributes on template.
1450 *
1451 * Some attributes are specific to an object class.  If one or more
1452 * of these attributes are in the template, make a list of classes
1453 * that can have these attributes.  This would speed up the search later,
1454 * because we can immediately skip an object if the class of that
1455 * object can not possibly contain one of the attributes.
1456 *
1457 */
1458void
1459kms_process_find_attr(CK_OBJECT_CLASS *pclasses,
1460    CK_ULONG *num_result_pclasses, CK_ATTRIBUTE_PTR pTemplate,
1461    CK_ULONG ulCount)
1462{
1463	ulong_t i;
1464	int j;
1465	boolean_t secret_found = B_FALSE;
1466	int num_secret_key_attrs;
1467	int num_pclasses = 0;
1468
1469	for (i = 0; i < ulCount; i++) {
1470		if (pTemplate[i].type == CKA_CLASS) {
1471			/*
1472			 * don't need to guess the class, it is specified.
1473			 * Just record the class, and return.
1474			 */
1475			pclasses[0] =
1476			    (*((CK_OBJECT_CLASS *)pTemplate[i].pValue));
1477			*num_result_pclasses = 1;
1478			return;
1479		}
1480	}
1481
1482	num_secret_key_attrs =
1483	    sizeof (SECRET_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
1484
1485	/*
1486	 * Get the list of objects class that might contain
1487	 * some attributes.
1488	 */
1489	for (i = 0; i < ulCount; i++) {
1490		if (!secret_found) {
1491			for (j = 0; j < num_secret_key_attrs; j++) {
1492				if (pTemplate[i].type == SECRET_KEY_ATTRS[j]) {
1493					secret_found = B_TRUE;
1494					pclasses[num_pclasses++] =
1495					    CKO_SECRET_KEY;
1496					break;
1497				}
1498			}
1499		}
1500	}
1501	*num_result_pclasses = num_pclasses;
1502}
1503
1504
1505boolean_t
1506kms_find_match_attrs(kms_object_t *obj, CK_OBJECT_CLASS *pclasses,
1507    CK_ULONG num_pclasses, CK_ATTRIBUTE *template, CK_ULONG num_attr)
1508{
1509	ulong_t i;
1510	CK_ATTRIBUTE *tmpl_attr, *obj_attr;
1511	uint64_t attr_mask;
1512	boolean_t compare_attr, compare_boolean;
1513
1514	/*
1515	 * Check if the class of this object match with any
1516	 * of object classes that can possibly contain the
1517	 * requested attributes.
1518	 */
1519	if (num_pclasses > 0) {
1520		for (i = 0; i < num_pclasses; i++) {
1521			if (obj->class == pclasses[i]) {
1522				break;
1523			}
1524		}
1525		if (i == num_pclasses) {
1526			/*
1527			 * this object can't possibly contain one or
1528			 * more attributes, don't need to check this object
1529			 */
1530			return (B_FALSE);
1531		}
1532	}
1533
1534	/* need to examine everything */
1535	for (i = 0; i < num_attr; i++) {
1536		tmpl_attr = &(template[i]);
1537		compare_attr = B_FALSE;
1538		compare_boolean = B_FALSE;
1539		switch (tmpl_attr->type) {
1540		/* First, check the most common attributes */
1541		case CKA_CLASS:
1542			if (*((CK_OBJECT_CLASS *)tmpl_attr->pValue) !=
1543			    obj->class) {
1544				return (B_FALSE);
1545			}
1546			break;
1547		case CKA_KEY_TYPE:
1548			if (*((CK_KEY_TYPE *)tmpl_attr->pValue) !=
1549			    obj->key_type) {
1550				return (B_FALSE);
1551			}
1552			break;
1553		case CKA_ENCRYPT:
1554			attr_mask = (obj->bool_attr_mask) & ENCRYPT_BOOL_ON;
1555			compare_boolean = B_TRUE;
1556			break;
1557		case CKA_DECRYPT:
1558			attr_mask = (obj->bool_attr_mask) & DECRYPT_BOOL_ON;
1559			compare_boolean = B_TRUE;
1560			break;
1561		case CKA_WRAP:
1562			attr_mask = (obj->bool_attr_mask) & WRAP_BOOL_ON;
1563			compare_boolean = B_TRUE;
1564			break;
1565		case CKA_UNWRAP:
1566			attr_mask = (obj->bool_attr_mask) & UNWRAP_BOOL_ON;
1567			compare_boolean = B_TRUE;
1568			break;
1569		case CKA_SIGN:
1570			attr_mask = (obj->bool_attr_mask) & SIGN_BOOL_ON;
1571			compare_boolean = B_TRUE;
1572			break;
1573		case CKA_SIGN_RECOVER:
1574			attr_mask = (obj->bool_attr_mask) &
1575			    SIGN_RECOVER_BOOL_ON;
1576			compare_boolean = B_TRUE;
1577			break;
1578		case CKA_VERIFY:
1579			attr_mask = (obj->bool_attr_mask) & VERIFY_BOOL_ON;
1580			compare_boolean = B_TRUE;
1581			break;
1582		case CKA_VERIFY_RECOVER:
1583			attr_mask = (obj->bool_attr_mask) &
1584			    VERIFY_RECOVER_BOOL_ON;
1585			compare_boolean = B_TRUE;
1586			break;
1587		case CKA_DERIVE:
1588			attr_mask = (obj->bool_attr_mask) & DERIVE_BOOL_ON;
1589			compare_boolean = B_TRUE;
1590			break;
1591		case CKA_LOCAL:
1592			attr_mask = (obj->bool_attr_mask) & LOCAL_BOOL_ON;
1593			compare_boolean = B_TRUE;
1594			break;
1595		case CKA_SENSITIVE:
1596			attr_mask = (obj->bool_attr_mask) & SENSITIVE_BOOL_ON;
1597			compare_boolean = B_TRUE;
1598			break;
1599		case CKA_SECONDARY_AUTH:
1600			attr_mask = (obj->bool_attr_mask) &
1601			    SECONDARY_AUTH_BOOL_ON;
1602			compare_boolean = B_TRUE;
1603			break;
1604		case CKA_TRUSTED:
1605			attr_mask = (obj->bool_attr_mask) & TRUSTED_BOOL_ON;
1606			compare_boolean = B_TRUE;
1607			break;
1608		case CKA_EXTRACTABLE:
1609			attr_mask = (obj->bool_attr_mask) &
1610			    EXTRACTABLE_BOOL_ON;
1611			compare_boolean = B_TRUE;
1612			break;
1613		case CKA_ALWAYS_SENSITIVE:
1614			attr_mask = (obj->bool_attr_mask) &
1615			    ALWAYS_SENSITIVE_BOOL_ON;
1616			compare_boolean = B_TRUE;
1617			break;
1618		case CKA_NEVER_EXTRACTABLE:
1619			attr_mask = (obj->bool_attr_mask) &
1620			    NEVER_EXTRACTABLE_BOOL_ON;
1621			compare_boolean = B_TRUE;
1622			break;
1623		case CKA_TOKEN:
1624			attr_mask = (obj->bool_attr_mask) & TOKEN_BOOL_ON;
1625			compare_boolean = B_TRUE;
1626			break;
1627		case CKA_PRIVATE:
1628			attr_mask = (obj->bool_attr_mask) & PRIVATE_BOOL_ON;
1629			compare_boolean = B_TRUE;
1630			break;
1631		case CKA_MODIFIABLE:
1632			attr_mask = (obj->bool_attr_mask) & MODIFIABLE_BOOL_ON;
1633			compare_boolean = B_TRUE;
1634			break;
1635		case CKA_SUBJECT:
1636		case CKA_ID:
1637		case CKA_START_DATE:
1638		case CKA_END_DATE:
1639		case CKA_KEY_GEN_MECHANISM:
1640		case CKA_LABEL:
1641			/* find these attributes from extra_attrlistp */
1642			obj_attr = get_extra_attr(tmpl_attr->type, obj);
1643			compare_attr = B_TRUE;
1644			break;
1645		case CKA_VALUE_LEN:
1646			/* only secret key has this attribute */
1647			if (obj->class == CKO_SECRET_KEY) {
1648				if (*((CK_ULONG *)tmpl_attr->pValue) !=
1649				    OBJ_SEC_VALUE_LEN(obj)) {
1650					return (B_FALSE);
1651				}
1652			} else {
1653				return (B_FALSE);
1654			}
1655			break;
1656		case CKA_VALUE:
1657			switch (obj->class) {
1658			case CKO_SECRET_KEY:
1659				break;
1660			default:
1661				return (B_FALSE);
1662			}
1663			break;
1664		case CKA_VALUE_BITS:
1665		case CKA_PRIME_BITS:
1666		case CKA_SUBPRIME_BITS:
1667		default:
1668			/*
1669			 * any other attributes are currently not supported.
1670			 * so, it's not possible for them to be in the
1671			 * object
1672			 */
1673			return (B_FALSE);
1674		}
1675		if (compare_boolean) {
1676			CK_BBOOL bval;
1677
1678			if (attr_mask) {
1679				bval = TRUE;
1680			} else {
1681				bval = FALSE;
1682			}
1683			if (bval != *((CK_BBOOL *)tmpl_attr->pValue)) {
1684				return (B_FALSE);
1685			}
1686		} else if (compare_attr) {
1687			if (obj_attr == NULL) {
1688				/*
1689				 * The attribute type is valid, and its value
1690				 * has not been initialized in the object. In
1691				 * this case, it only matches the template's
1692				 * attribute if the template's value length
1693				 * is 0.
1694				 */
1695				if (tmpl_attr->ulValueLen != 0)
1696					return (B_FALSE);
1697			} else {
1698				if (tmpl_attr->ulValueLen !=
1699				    obj_attr->ulValueLen) {
1700					return (B_FALSE);
1701				}
1702				if (memcmp(tmpl_attr->pValue, obj_attr->pValue,
1703				    tmpl_attr->ulValueLen) != 0) {
1704					return (B_FALSE);
1705				}
1706			}
1707		}
1708	}
1709	return (B_TRUE);
1710}
1711
1712CK_ATTRIBUTE_PTR
1713get_extra_attr(CK_ATTRIBUTE_TYPE type, kms_object_t *obj)
1714{
1715	CK_ATTRIBUTE_INFO_PTR tmp;
1716
1717	tmp = obj->extra_attrlistp;
1718	while (tmp != NULL) {
1719		if (tmp->attr.type == type) {
1720			return (&(tmp->attr));
1721		}
1722		tmp = tmp->next;
1723	}
1724	/* if get there, the specified attribute is not found */
1725	return (NULL);
1726}
1727