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