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 * Copyright (c) 2018, Joyent, Inc. 26 */ 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 default: 83 /* should never be here */ 84 return (CKR_ATTRIBUTE_VALUE_INVALID); 85 } 86 rv = FUNCLIST(session->fw_st_id)->C_GetAttributeValue( 87 session->hSession, slot_object->hObject, &attr, 1); 88 if (rv != CKR_OK) { 89 return (rv); 90 } 91 92 get_attr: 93 rv = get_master_attributes_by_type(class, subtype, 94 attributes, num_attributes); 95 96 return (rv); 97 } 98 99 /* 100 * get_master_attributes_by_template 101 * 102 * Returns an (statically allocated) set of object attributes, as determined by 103 * the supplied object template. The template is only used to determine the 104 * class/subclass of the object. The attributes are only initialized to 105 * default values. 106 */ 107 CK_RV 108 get_master_attributes_by_template( 109 CK_ATTRIBUTE *template, CK_ULONG template_size, 110 generic_attr_t **attributes, size_t *num_attributes) 111 { 112 CK_OBJECT_CLASS class; 113 CK_ULONG subtype = CK_UNAVAILABLE_INFORMATION; 114 boolean_t found; 115 116 found = get_template_ulong(CKA_CLASS, template, template_size, &class); 117 if (!found) { 118 return (CKR_TEMPLATE_INCOMPLETE); 119 } 120 121 switch (class) { 122 case CKO_CERTIFICATE: 123 found = get_template_ulong(CKA_CERTIFICATE_TYPE, 124 template, template_size, &subtype); 125 break; 126 case CKO_HW_FEATURE: 127 found = get_template_ulong(CKA_HW_FEATURE_TYPE, 128 template, template_size, &subtype); 129 break; 130 case CKO_PUBLIC_KEY: 131 case CKO_PRIVATE_KEY: 132 case CKO_SECRET_KEY: 133 case CKO_DOMAIN_PARAMETERS: 134 found = get_template_ulong(CKA_KEY_TYPE, 135 template, template_size, &subtype); 136 break; 137 case CKO_DATA: 138 /* CKO_DATA has no subtype, just pretend it is found */ 139 found = B_TRUE; 140 break; 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 explicit_bzero(attr->attribute.pValue, 531 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 explicit_bzero((char *)attr->attribute.pValue + 570 new_attr->ulValueLen, 571 attr->attribute.ulValueLen - new_attr->ulValueLen); 572 573 } else if (new_attr->ulValueLen <= sizeof (attr->generic_data)) { 574 /* Use generic storage to avoid a malloc. */ 575 576 explicit_bzero(attr->attribute.pValue, 577 attr->attribute.ulValueLen); 578 if (attr->isMalloced) { 579 /* 580 * If app sets a large value (triggering a malloc), 581 * then sets a tiny value, and finally again sets 582 * a large value (phew!) we could end up here. 583 * 584 * FUTURE?: Store the original malloc size, so that 585 * we can regrow the value up to the original size. 586 * This might avoid some heap churn for pathalogic 587 * applications. 588 */ 589 free(attr->attribute.pValue); 590 attr->isMalloced = B_FALSE; 591 } 592 593 attr->attribute.pValue = attr->generic_data; 594 595 } else { 596 /* Need to allocate storage for the new value. */ 597 void *newStorage; 598 599 newStorage = malloc(new_attr->ulValueLen); 600 if (newStorage == NULL) 601 return (CKR_HOST_MEMORY); 602 bzero(attr->attribute.pValue, attr->attribute.ulValueLen); 603 attr->attribute.pValue = newStorage; 604 attr->isMalloced = B_TRUE; 605 } 606 607 (void) memcpy(attr->attribute.pValue, new_attr->pValue, 608 new_attr->ulValueLen); 609 attr->attribute.ulValueLen = new_attr->ulValueLen; 610 attr->hasValueForClone = B_TRUE; 611 612 return (CKR_OK); 613 } 614 615 616 /* 617 * find_attribute 618 * 619 * Passes a pointer to the requested attribute, or NULL if not found. 620 */ 621 static void 622 find_attribute(CK_ATTRIBUTE_TYPE attrtype, generic_attr_t *attributes, 623 size_t num_attributes, generic_attr_t **found_attribute) 624 { 625 generic_attr_t *attr; 626 boolean_t found = B_FALSE; 627 size_t i; 628 629 /* Find the requested attribute. */ 630 for (i = 0, attr = attributes; i < num_attributes; i++, attr++) { 631 if (attr->attribute.type == attrtype) { 632 found = B_TRUE; 633 break; 634 } 635 } 636 637 *found_attribute = found ? attr : NULL; 638 } 639 640 641 /* 642 * get_template_ulong 643 * 644 * Look for the specified ulong-size attribute, and retrieve its value. The 645 * return value specifies if the attribute was found (or not). 646 */ 647 boolean_t 648 get_template_ulong(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE *attributes, 649 CK_ULONG num_attributes, CK_ULONG *result) 650 { 651 boolean_t found = B_FALSE; 652 CK_ULONG i; 653 654 for (i = 0; i < num_attributes; i++) { 655 if (attributes[i].type == type) { 656 CK_ULONG *value = attributes[i].pValue; 657 658 *result = *value; 659 found = B_TRUE; 660 break; 661 } 662 } 663 664 return (found); 665 } 666 667 668 /* 669 * get_template_boolean 670 * 671 * Look for the specified boolean attribute, and retrieve its value. The 672 * return value specifies if the attribute was found (or not). 673 */ 674 boolean_t 675 get_template_boolean(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE *attributes, 676 CK_ULONG num_attributes, boolean_t *result) 677 { 678 boolean_t found = B_FALSE; 679 CK_ULONG i; 680 681 for (i = 0; i < num_attributes; i++) { 682 if (attributes[i].type == type) { 683 CK_BBOOL *value = attributes[i].pValue; 684 685 if (*value == CK_FALSE) 686 *result = B_FALSE; 687 else 688 *result = B_TRUE; 689 690 found = B_TRUE; 691 break; 692 } 693 } 694 695 return (found); 696 } 697 698 /* 699 * set_template_boolean 700 * 701 * Look for the specified boolean attribute, and set its value. 702 * 703 * if 'local' is true, it sets the pointer to the value in the template a new 704 * location. There should be no memory leak created by this because we are 705 * only doing this to booleans which should not be malloc'ed. 706 * 707 * if 'local' is false, it sets its value. 708 * 709 * The return value specifies if the attribute was found (or not). 710 */ 711 int 712 set_template_boolean(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE *attributes, 713 CK_ULONG num_attributes, boolean_t local, CK_BBOOL *value) 714 { 715 int i; 716 717 for (i = 0; i < num_attributes; i++) { 718 if (attributes[i].type == type) { 719 if (local) 720 attributes[i].pValue = value; 721 else 722 *((CK_BBOOL *)attributes[i].pValue) = *value; 723 724 return (i); 725 } 726 } 727 728 return (-1); 729 } 730