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