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