comparison usr/src/lib/pkcs11/pkcs11_kms/common/kmsAttributeUtil.c @ 12720:3db6e0082404

PSARC 2010/195 PKCS11 KMS Provider 6944296 Solaris needs a PKCS#11 provider to allow access to KMS keystore functionality
author Wyllys Ingersoll <Wyllys.Ingersoll@Sun.COM>
date Mon, 28 Jun 2010 16:04:11 -0700
parents
children e5889df1eaac
comparison
equal deleted inserted replaced
12719:bd9fb35d09c2 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }