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