xref: /onnv-gate/usr/src/lib/pkcs11/pkcs11_kms/common/kmsAttributeUtil.c (revision 12720:3db6e0082404)
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  */
37 CK_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  */
85 CK_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  */
103 CK_RV
kms_lookup_attr(CK_ATTRIBUTE_TYPE type)104 kms_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  */
149 CK_RV
kms_validate_attr(CK_ATTRIBUTE_PTR template,CK_ULONG ulAttrNum,CK_OBJECT_CLASS * class)150 kms_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  */
212 void
kms_cleanup_extra_attr(kms_object_t * object_p)213 kms_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  */
246 CK_RV
kms_add_extra_attr(CK_ATTRIBUTE_PTR template,kms_object_t * object_p)247 kms_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  */
294 CK_RV
kms_copy_extra_attr(CK_ATTRIBUTE_INFO_PTR old_attrp,kms_object_t * object_p)295 kms_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  */
342 CK_RV
get_extra_attr_from_object(kms_object_t * object_p,CK_ATTRIBUTE_PTR template)343 get_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  */
398 CK_RV
set_extra_attr_to_object(kms_object_t * object_p,CK_ATTRIBUTE_TYPE type,CK_ATTRIBUTE_PTR template)399 set_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  */
455 CK_RV
get_bool_attr_from_object(kms_object_t * object_p,CK_ULONG bool_flag,CK_ATTRIBUTE_PTR template)456 get_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  */
491 CK_RV
set_bool_attr_to_object(kms_object_t * object_p,CK_ULONG bool_flag,CK_ATTRIBUTE_PTR template)492 set_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  */
509 CK_RV
get_ulong_attr_from_object(CK_ULONG value,CK_ATTRIBUTE_PTR template)510 get_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 
536 CK_RV
get_string_from_template(CK_ATTRIBUTE_PTR dest,CK_ATTRIBUTE_PTR src)537 get_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 
561 void
string_attr_cleanup(CK_ATTRIBUTE_PTR template)562 string_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  */
577 static CK_RV
kms_parse_common_attrs(CK_ATTRIBUTE_PTR template,uint64_t * attr_mask_p)578 kms_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  */
638 CK_RV
kms_build_secret_key_object(CK_ATTRIBUTE_PTR template,CK_ULONG ulAttrNum,kms_object_t * new_object)639 kms_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 
859 fail_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  */
881 CK_RV
kms_build_object(CK_ATTRIBUTE_PTR template,CK_ULONG ulAttrNum,kms_object_t * new_object)882 kms_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  */
930 CK_RV
kms_get_common_attrs(kms_object_t * object_p,CK_ATTRIBUTE_PTR template)931 kms_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  */
997 CK_RV
kms_get_common_key_attrs(kms_object_t * object_p,CK_ATTRIBUTE_PTR template)998 kms_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  */
1043 CK_RV
kms_get_secret_key_attribute(kms_object_t * object_p,CK_ATTRIBUTE_PTR template)1044 kms_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  */
1178 CK_RV
kms_get_attribute(kms_object_t * object_p,CK_ATTRIBUTE_PTR template)1179 kms_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  */
1210 static CK_RV
kms_set_common_key_attribute(kms_object_t * object_p,CK_ATTRIBUTE_PTR template,boolean_t copy)1211 kms_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  */
1295 static CK_RV
kms_set_secret_key_attribute(kms_object_t * object_p,CK_ATTRIBUTE_PTR template,boolean_t copy)1296 kms_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  */
1388 CK_RV
kms_set_attribute(kms_object_t * object_p,CK_ATTRIBUTE_PTR template,boolean_t copy)1389 kms_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 
1419 CK_RV
kms_copy_secret_key_attr(secret_key_obj_t * old_secret_key_obj_p,secret_key_obj_t ** new_secret_key_obj_p)1420 kms_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  */
1458 void
kms_process_find_attr(CK_OBJECT_CLASS * pclasses,CK_ULONG * num_result_pclasses,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)1459 kms_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 
1505 boolean_t
kms_find_match_attrs(kms_object_t * obj,CK_OBJECT_CLASS * pclasses,CK_ULONG num_pclasses,CK_ATTRIBUTE * template,CK_ULONG num_attr)1506 kms_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 
1712 CK_ATTRIBUTE_PTR
get_extra_attr(CK_ATTRIBUTE_TYPE type,kms_object_t * obj)1713 get_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