1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <string.h> 29 #include <stdlib.h> 30 #include <strings.h> 31 #include "metaGlobal.h" 32 #include "metaAttrMasters.h" 33 34 static void 35 find_attribute(CK_ATTRIBUTE_TYPE attrtype, generic_attr_t *attributes, 36 size_t num_attributes, generic_attr_t **found_attribute); 37 38 /* 39 * get_master_attributes_by_object 40 * 41 * Returns an (statically allocated) set of object attributes, as determined by 42 * class and keytype of the supplied object. The attributes are only 43 * initialized to default values. 44 */ 45 CK_RV 46 get_master_attributes_by_object(slot_session_t *session, 47 slot_object_t *slot_object, generic_attr_t **attributes, 48 size_t *num_attributes) 49 { 50 CK_RV rv; 51 CK_ATTRIBUTE attr; 52 CK_OBJECT_CLASS class; 53 CK_ULONG subtype = CK_UNAVAILABLE_INFORMATION; 54 55 /* first get the class */ 56 attr.type = CKA_CLASS; 57 attr.pValue = &class; 58 attr.ulValueLen = sizeof (class); 59 rv = FUNCLIST(session->fw_st_id)->C_GetAttributeValue( 60 session->hSession, slot_object->hObject, &attr, 1); 61 if (rv != CKR_OK) { 62 return (rv); 63 } 64 65 attr.pValue = &subtype; 66 attr.ulValueLen = sizeof (subtype); 67 switch (class) { 68 case CKO_CERTIFICATE: 69 attr.type = CKA_CERTIFICATE_TYPE; 70 break; 71 case CKO_HW_FEATURE: 72 attr.type = CKA_HW_FEATURE_TYPE; 73 break; 74 case CKO_PUBLIC_KEY: 75 case CKO_PRIVATE_KEY: 76 case CKO_SECRET_KEY: 77 case CKO_DOMAIN_PARAMETERS: 78 attr.type = CKA_KEY_TYPE; 79 break; 80 case CKO_DATA: 81 goto get_attr; 82 break; 83 default: 84 /* should never be here */ 85 return (CKR_ATTRIBUTE_VALUE_INVALID); 86 } 87 rv = FUNCLIST(session->fw_st_id)->C_GetAttributeValue( 88 session->hSession, slot_object->hObject, &attr, 1); 89 if (rv != CKR_OK) { 90 return (rv); 91 } 92 93 get_attr: 94 rv = get_master_attributes_by_type(class, subtype, 95 attributes, num_attributes); 96 97 return (rv); 98 } 99 100 /* 101 * get_master_attributes_by_template 102 * 103 * Returns an (statically allocated) set of object attributes, as determined by 104 * the supplied object template. The template is only used to determine the 105 * class/subclass of the object. The attributes are only initialized to 106 * default values. 107 */ 108 CK_RV 109 get_master_attributes_by_template( 110 CK_ATTRIBUTE *template, CK_ULONG template_size, 111 generic_attr_t **attributes, size_t *num_attributes) 112 { 113 CK_OBJECT_CLASS class; 114 CK_ULONG subtype = CK_UNAVAILABLE_INFORMATION; 115 boolean_t found; 116 117 found = get_template_ulong(CKA_CLASS, template, template_size, &class); 118 if (!found) { 119 return (CKR_TEMPLATE_INCOMPLETE); 120 } 121 122 switch (class) { 123 case CKO_CERTIFICATE: 124 found = get_template_ulong(CKA_CERTIFICATE_TYPE, 125 template, template_size, &subtype); 126 break; 127 case CKO_HW_FEATURE: 128 found = get_template_ulong(CKA_HW_FEATURE_TYPE, 129 template, template_size, &subtype); 130 break; 131 case CKO_PUBLIC_KEY: 132 case CKO_PRIVATE_KEY: 133 case CKO_SECRET_KEY: 134 case CKO_DOMAIN_PARAMETERS: 135 found = get_template_ulong(CKA_KEY_TYPE, 136 template, template_size, &subtype); 137 break; 138 case CKO_DATA: 139 /* CKO_DATA has no subtype, just pretend it is found */ 140 found = B_TRUE; 141 default: 142 /* unknown object class */ 143 return (CKR_ATTRIBUTE_VALUE_INVALID); 144 } 145 146 if (!found) { 147 return (CKR_TEMPLATE_INCOMPLETE); 148 } 149 150 return (get_master_attributes_by_type(class, subtype, 151 attributes, num_attributes)); 152 } 153 154 /* 155 * get_master_template_by_type 156 * 157 * Returns an (statically allocated) set of object attributes, as determined 158 * by the specified class and subtype. The attributes are initialized to default 159 * values. 160 */ 161 CK_RV 162 get_master_template_by_type(CK_OBJECT_CLASS class, CK_ULONG subtype, 163 generic_attr_t **attributes, size_t *num_attributes) 164 { 165 generic_attr_t *master_template = NULL; 166 size_t master_template_size = 0; 167 168 switch (class) { 169 case CKO_HW_FEATURE: 170 switch (subtype) { 171 case CKO_HW_FEATURE: 172 master_template = (generic_attr_t *)OBJ_HW_CLOCK; 173 master_template_size = sizeof (OBJ_HW_CLOCK); 174 break; 175 176 case CKH_MONOTONIC_COUNTER: 177 master_template = (generic_attr_t *)OBJ_HW_MONOTONIC; 178 master_template_size = sizeof (OBJ_HW_MONOTONIC); 179 break; 180 181 default: 182 /* Unsupported. */ 183 break; 184 } 185 break; 186 187 case CKO_DATA: 188 /* Objects of this class have no subtype. */ 189 master_template = (generic_attr_t *)OBJ_DATA; 190 master_template_size = sizeof (OBJ_DATA); 191 break; 192 193 case CKO_CERTIFICATE: 194 switch (subtype) { 195 case CKC_X_509: 196 master_template = (generic_attr_t *)OBJ_CERT_X509; 197 master_template_size = sizeof (OBJ_CERT_X509); 198 break; 199 200 case CKC_X_509_ATTR_CERT: 201 master_template = (generic_attr_t *)OBJ_CERT_X509ATTR; 202 master_template_size = sizeof (OBJ_CERT_X509ATTR); 203 break; 204 205 default: 206 /* Unsupported. */ 207 break; 208 } 209 break; 210 211 case CKO_PUBLIC_KEY: 212 switch (subtype) { 213 case CKK_RSA: 214 master_template = (generic_attr_t *)OBJ_PUBKEY_RSA; 215 master_template_size = sizeof (OBJ_PUBKEY_RSA); 216 break; 217 218 case CKK_DSA: 219 master_template = (generic_attr_t *)OBJ_PUBKEY_DSA; 220 master_template_size = sizeof (OBJ_PUBKEY_DSA); 221 break; 222 223 case CKK_EC: 224 master_template = (generic_attr_t *)OBJ_PUBKEY_EC; 225 master_template_size = sizeof (OBJ_PUBKEY_EC); 226 break; 227 228 case CKK_DH: 229 master_template = (generic_attr_t *)OBJ_PUBKEY_DH; 230 master_template_size = sizeof (OBJ_PUBKEY_DH); 231 break; 232 233 case CKK_X9_42_DH: 234 master_template = (generic_attr_t *)OBJ_PUBKEY_X942DH; 235 master_template_size = sizeof (OBJ_PUBKEY_X942DH); 236 break; 237 238 case CKK_KEA: 239 master_template = (generic_attr_t *)OBJ_PUBKEY_KEA; 240 master_template_size = sizeof (OBJ_PUBKEY_KEA); 241 break; 242 243 default: 244 /* Unsupported. */ 245 break; 246 } 247 break; 248 249 case CKO_PRIVATE_KEY: 250 switch (subtype) { 251 case CKK_RSA: 252 master_template = (generic_attr_t *)OBJ_PRIVKEY_RSA; 253 master_template_size = sizeof (OBJ_PRIVKEY_RSA); 254 break; 255 256 case CKK_DSA: 257 master_template = (generic_attr_t *)OBJ_PRIVKEY_DSA; 258 master_template_size = sizeof (OBJ_PRIVKEY_DSA); 259 break; 260 261 case CKK_EC: 262 master_template = (generic_attr_t *)OBJ_PRIVKEY_EC; 263 master_template_size = sizeof (OBJ_PRIVKEY_EC); 264 break; 265 266 case CKK_DH: 267 master_template = (generic_attr_t *)OBJ_PRIVKEY_DH; 268 master_template_size = sizeof (OBJ_PRIVKEY_DH); 269 break; 270 271 case CKK_X9_42_DH: 272 master_template = (generic_attr_t *)OBJ_PRIVKEY_X942DH; 273 master_template_size = sizeof (OBJ_PRIVKEY_X942DH); 274 break; 275 276 case CKK_KEA: 277 master_template = (generic_attr_t *)OBJ_PRIVKEY_KEA; 278 master_template_size = sizeof (OBJ_PRIVKEY_KEA); 279 break; 280 281 default: 282 /* Unsupported. */ 283 break; 284 } 285 break; 286 287 case CKO_SECRET_KEY: 288 /* 289 * The only difference between secret keys is that some 290 * are valiable length (eg CKK_AES), while others are not 291 * (eg CKK_DES) -- and do not have a CKA_VALUE_LEN attribute. 292 * 293 * FUTURE(?): Consider using obj_seckey_withlen for unknown 294 * keytypes. This is the most likely choice, as new algorithms 295 * seem to support variable length keys. That's not the default 296 * now, because if people have implemented new key types with 297 * different attribute sets (like the mess of public/private 298 * key types), then incorrect behaviour would result. It's 299 * easier to relax this restriction than to tighten it (which 300 * would introduce a regression to anyone relying on this 301 * working for unknown key types). 302 * 303 */ 304 switch (subtype) { 305 case CKK_DES: 306 case CKK_DES2: 307 case CKK_DES3: 308 case CKK_IDEA: 309 case CKK_CDMF: 310 case CKK_SKIPJACK: 311 case CKK_BATON: 312 case CKK_JUNIPER: 313 master_template = (generic_attr_t *)OBJ_SECKEY; 314 master_template_size = sizeof (OBJ_SECKEY); 315 break; 316 317 case CKK_GENERIC_SECRET: 318 case CKK_RC2: 319 case CKK_RC4: 320 case CKK_RC5: 321 case CKK_AES: 322 case CKK_BLOWFISH: 323 case CKK_CAST: 324 case CKK_CAST3: 325 case CKK_CAST128: 326 master_template = (generic_attr_t *)OBJ_SECKEY_WITHLEN; 327 master_template_size = sizeof (OBJ_SECKEY_WITHLEN); 328 break; 329 330 default: 331 /* Unsupported. */ 332 break; 333 } 334 break; 335 336 case CKO_DOMAIN_PARAMETERS: 337 switch (subtype) { 338 case CKK_DSA: 339 master_template = (generic_attr_t *)OBJ_DOM_DSA; 340 master_template_size = sizeof (OBJ_DOM_DSA); 341 break; 342 343 case CKK_DH: 344 master_template = (generic_attr_t *)OBJ_DOM_DH; 345 master_template_size = sizeof (OBJ_DOM_DH); 346 break; 347 348 case CKK_X9_42_DH: 349 master_template = (generic_attr_t *)OBJ_DOM_X942DH; 350 master_template_size = sizeof (OBJ_DOM_X942DH); 351 break; 352 353 default: 354 /* Unsupported. */ 355 break; 356 } 357 break; 358 359 default: 360 /* Unsupported. */ 361 break; 362 } 363 364 /* Requested object is unknown or invalid. */ 365 if (master_template == NULL) 366 return (CKR_ATTRIBUTE_VALUE_INVALID); 367 else { 368 *attributes = master_template; 369 *num_attributes = master_template_size; 370 return (CKR_OK); 371 } 372 } 373 374 375 /* 376 * get_master_attributes_by_type 377 * 378 * Returns an (statically allocated) set of object attributes, as determined by 379 * the specified class and subtype. The attributes are initialized to default 380 * values. 381 */ 382 CK_RV 383 get_master_attributes_by_type(CK_OBJECT_CLASS class, CK_ULONG subtype, 384 generic_attr_t **attributes, size_t *num_attributes) 385 { 386 CK_RV rv; 387 generic_attr_t *master_template = NULL; 388 generic_attr_t *new_attributes; 389 size_t i, num_new_attributes, master_template_size = 0; 390 391 /* Determine the appropriate master template needed. */ 392 rv = get_master_template_by_type(class, subtype, 393 &master_template, &master_template_size); 394 if (rv != CKR_OK) 395 return (rv); 396 397 /* Duplicate the master template. */ 398 new_attributes = malloc(master_template_size); 399 if (new_attributes == NULL) 400 return (CKR_HOST_MEMORY); 401 402 (void) memcpy(new_attributes, master_template, master_template_size); 403 num_new_attributes = master_template_size / sizeof (generic_attr_t); 404 405 /* Set the pointer in the appropriate storage area. */ 406 for (i = 0; i < num_new_attributes; i++) { 407 generic_attr_t *attr; 408 409 attr = new_attributes + i; 410 411 switch (attr->attribute.ulValueLen) { 412 case (sizeof (CK_ULONG)): 413 attr->attribute.pValue = &attr->generic_ulong; 414 break; 415 case (sizeof (CK_BBOOL)): 416 attr->attribute.pValue = &attr->generic_bbool; 417 break; 418 default: 419 attr->attribute.pValue = attr->generic_data; 420 break; 421 } 422 423 } 424 425 /* Secret keys share a common template, so set the key type here. */ 426 if (class == CKO_SECRET_KEY) { 427 /* Keytype / subtype is always the second attribute. */ 428 new_attributes[1].generic_ulong = subtype; 429 } 430 431 *attributes = new_attributes; 432 *num_attributes = num_new_attributes; 433 434 return (CKR_OK); 435 } 436 437 438 /* 439 * get_master_attributes_by_duplication 440 * 441 * Returns an (statically allocated) set of object attributes, as copied from an 442 * existing set of attributes. The new attributes inherit the values from 443 * the old attributes. 444 */ 445 CK_RV 446 get_master_attributes_by_duplication( 447 generic_attr_t *src_attrs, size_t num_src_attrs, 448 generic_attr_t **dst_attrs, size_t *num_dst_attrs) 449 { 450 CK_RV rv = CKR_OK; 451 generic_attr_t *new_attrs, *src, *dst; 452 size_t i; 453 454 new_attrs = malloc(sizeof (generic_attr_t) * num_src_attrs); 455 if (new_attrs == NULL) 456 return (CKR_HOST_MEMORY); 457 458 for (i = 0; i < num_src_attrs; i++) { 459 src = src_attrs + i; 460 dst = new_attrs + i; 461 462 *dst = *src; 463 464 /* Adjust pointers in dst so that they don't point to src. */ 465 466 if (src->isMalloced) { 467 dst->attribute.pValue = 468 malloc(src->attribute.ulValueLen); 469 470 if (dst->attribute.pValue == NULL) { 471 /* 472 * Continue on error, so that the cleanup 473 * routine doesn't see pointers to src_attrs. 474 */ 475 dst->attribute.ulValueLen = 0; 476 rv = CKR_HOST_MEMORY; 477 continue; 478 } 479 } else if (src->attribute.pValue == &src->generic_bbool) { 480 dst->attribute.pValue = &dst->generic_bbool; 481 } else if (src->attribute.pValue == &src->generic_ulong) { 482 dst->attribute.pValue = &dst->generic_ulong; 483 } else if (src->attribute.pValue == &src->generic_data) { 484 dst->attribute.pValue = &dst->generic_data; 485 } else { 486 /* This shouldn't happen. */ 487 dst->attribute.pValue = NULL; 488 dst->attribute.ulValueLen = 0; 489 rv = CKR_GENERAL_ERROR; 490 num_src_attrs = i + 1; 491 break; 492 } 493 494 (void) memcpy(dst->attribute.pValue, src->attribute.pValue, 495 src->attribute.ulValueLen); 496 } 497 498 if (rv != CKR_OK) { 499 dealloc_attributes(new_attrs, num_src_attrs); 500 } else { 501 *dst_attrs = new_attrs; 502 *num_dst_attrs = num_src_attrs; 503 } 504 505 return (rv); 506 } 507 508 509 /* 510 * dealloc_attributes 511 * 512 * Deallocates the storage used for a set of attributes. The attribute 513 * values are zeroed out before being free'd. 514 */ 515 void 516 dealloc_attributes(generic_attr_t *attributes, size_t num_attributes) 517 { 518 size_t i; 519 generic_attr_t *attr; 520 521 for (i = 0; i < num_attributes; i++) { 522 attr = attributes + i; 523 524 /* 525 * Zero-out any attribute values. We could do this just for 526 * attributes with isSensitive == True, but it's not much 527 * extra work to just do them all. [Most attributes are just 528 * 1 or 4 bytes] 529 */ 530 bzero(attr->attribute.pValue, attr->attribute.ulValueLen); 531 532 if (attr->isMalloced) 533 free(attr->attribute.pValue); 534 } 535 536 free(attributes); 537 } 538 539 540 /* 541 * attribute_set_value 542 * 543 * Sets the value of the specified attribute. Any portion of the old value 544 * which will not be overwritten by the new value is zeroed out. 545 */ 546 CK_RV 547 attribute_set_value(CK_ATTRIBUTE *new_attr, 548 generic_attr_t *attributes, size_t num_attributes) 549 { 550 generic_attr_t *attr = NULL; 551 552 if (new_attr == NULL) 553 return (CKR_TEMPLATE_INCOMPLETE); 554 else if (new_attr->pValue == NULL) { 555 return (CKR_ATTRIBUTE_VALUE_INVALID); 556 } 557 558 find_attribute(new_attr->type, attributes, num_attributes, &attr); 559 if (attr == NULL) { 560 return (CKR_ATTRIBUTE_TYPE_INVALID); 561 } 562 563 /* Store the new value. */ 564 if (attr->attribute.ulValueLen >= new_attr->ulValueLen) { 565 /* Existing storage is sufficient to store new value. */ 566 567 /* bzero() out any data that won't be overwritten. */ 568 bzero((char *)attr->attribute.pValue + new_attr->ulValueLen, 569 attr->attribute.ulValueLen - new_attr->ulValueLen); 570 571 } else if (new_attr->ulValueLen <= sizeof (attr->generic_data)) { 572 /* Use generic storage to avoid a malloc. */ 573 574 bzero(attr->attribute.pValue, attr->attribute.ulValueLen); 575 if (attr->isMalloced) { 576 /* 577 * If app sets a large value (triggering a malloc), 578 * then sets a tiny value, and finally again sets 579 * a large value (phew!) we could end up here. 580 * 581 * FUTURE?: Store the original malloc size, so that 582 * we can regrow the value up to the original size. 583 * This might avoid some heap churn for pathalogic 584 * applications. 585 */ 586 free(attr->attribute.pValue); 587 attr->isMalloced = B_FALSE; 588 } 589 590 attr->attribute.pValue = attr->generic_data; 591 592 } else { 593 /* Need to allocate storage for the new value. */ 594 void *newStorage; 595 596 newStorage = malloc(new_attr->ulValueLen); 597 if (newStorage == NULL) 598 return (CKR_HOST_MEMORY); 599 bzero(attr->attribute.pValue, attr->attribute.ulValueLen); 600 attr->attribute.pValue = newStorage; 601 attr->isMalloced = B_TRUE; 602 } 603 604 (void) memcpy(attr->attribute.pValue, new_attr->pValue, 605 new_attr->ulValueLen); 606 attr->attribute.ulValueLen = new_attr->ulValueLen; 607 attr->hasValueForClone = B_TRUE; 608 609 return (CKR_OK); 610 } 611 612 613 /* 614 * find_attribute 615 * 616 * Passes a pointer to the requested attribute, or NULL if not found. 617 */ 618 static void 619 find_attribute(CK_ATTRIBUTE_TYPE attrtype, generic_attr_t *attributes, 620 size_t num_attributes, generic_attr_t **found_attribute) 621 { 622 generic_attr_t *attr; 623 boolean_t found = B_FALSE; 624 size_t i; 625 626 /* Find the requested attribute. */ 627 for (i = 0, attr = attributes; i < num_attributes; i++, attr++) { 628 if (attr->attribute.type == attrtype) { 629 found = B_TRUE; 630 break; 631 } 632 } 633 634 *found_attribute = found ? attr : NULL; 635 } 636 637 638 /* 639 * get_template_ulong 640 * 641 * Look for the specified ulong-size attribute, and retrieve its value. The 642 * return value specifies if the attribute was found (or not). 643 */ 644 boolean_t 645 get_template_ulong(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE *attributes, 646 CK_ULONG num_attributes, CK_ULONG *result) 647 { 648 boolean_t found = B_FALSE; 649 CK_ULONG i; 650 651 for (i = 0; i < num_attributes; i++) { 652 if (attributes[i].type == type) { 653 CK_ULONG *value = attributes[i].pValue; 654 655 *result = *value; 656 found = B_TRUE; 657 break; 658 } 659 } 660 661 return (found); 662 } 663 664 665 /* 666 * get_template_boolean 667 * 668 * Look for the specified boolean attribute, and retrieve its value. The 669 * return value specifies if the attribute was found (or not). 670 */ 671 boolean_t 672 get_template_boolean(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE *attributes, 673 CK_ULONG num_attributes, boolean_t *result) 674 { 675 boolean_t found = B_FALSE; 676 CK_ULONG i; 677 678 for (i = 0; i < num_attributes; i++) { 679 if (attributes[i].type == type) { 680 CK_BBOOL *value = attributes[i].pValue; 681 682 if (*value == CK_FALSE) 683 *result = B_FALSE; 684 else 685 *result = B_TRUE; 686 687 found = B_TRUE; 688 break; 689 } 690 } 691 692 return (found); 693 } 694 695 /* 696 * set_template_boolean 697 * 698 * Look for the specified boolean attribute, and set its value. 699 * 700 * if 'local' is true, it sets the pointer to the value in the template a new 701 * location. There should be no memory leak created by this because we are 702 * only doing this to booleans which should not be malloc'ed. 703 * 704 * if 'local' is false, it sets its value. 705 * 706 * The return value specifies if the attribute was found (or not). 707 */ 708 int 709 set_template_boolean(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE *attributes, 710 CK_ULONG num_attributes, boolean_t local, CK_BBOOL *value) 711 { 712 int i; 713 714 for (i = 0; i < num_attributes; i++) { 715 if (attributes[i].type == type) { 716 if (local) 717 attributes[i].pValue = value; 718 else 719 *((CK_BBOOL *)attributes[i].pValue) = *value; 720 721 return (i); 722 } 723 } 724 725 return (-1); 726 } 727