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 <strings.h> 29 #include <errno.h> 30 #include <security/cryptoki.h> 31 #include <sys/crypto/ioctl.h> 32 #include "kernelGlobal.h" 33 #include "kernelSession.h" 34 #include "kernelObject.h" 35 36 static boolean_t 37 attribute_in_template(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE_PTR t, CK_ULONG cnt) 38 { 39 int i; 40 41 for (i = 0; i < cnt; i++) { 42 if (t[i].type == type) 43 return (B_TRUE); 44 } 45 return (B_FALSE); 46 } 47 48 /* 49 * This routine returns modulus bytes rounded up to the nearest 8 byte 50 * chunk. This is so we don't have to pass in max sized buffers for 51 * returned attributes. Every unnecessary byte that we pass in results 52 * in a kernel allocation. 53 */ 54 static ulong_t 55 get_modulus_bytes(CK_ATTRIBUTE_PTR t, CK_ULONG cnt) 56 { 57 CK_ULONG modulus_len; 58 int i; 59 60 for (i = 0; i < cnt; i++) { 61 if (t[i].type == CKA_MODULUS_BITS) { 62 get_ulong_attr_from_template(&modulus_len, &t[i]); 63 /* convert from bit length to byte length */ 64 modulus_len = (modulus_len - 1) / 64 + 1; 65 return (modulus_len * 8); 66 } 67 } 68 return (0); 69 } 70 71 /* 72 * Remove specified attribute from array. Storage for the attribute's 73 * value is freed if 'free_attr' is TRUE. Attributes are shifted so they are 74 * contiguous within the array, i.e. the next attribute is shifted into 75 * the position of the removed attribute. Returns TRUE if specified 76 * attribute is removed. 77 */ 78 static boolean_t 79 remove_one_attribute(CK_ATTRIBUTE_PTR t, CK_ULONG type, uint_t count, 80 boolean_t free_attr) 81 { 82 int i, j; 83 84 for (i = 0, j = 0; i < count; i++) { 85 if (t[i].type == type) { 86 if (free_attr) { 87 free(t[i].pValue); 88 } 89 continue; 90 } 91 if (i != j) { 92 t[j].type = t[i].type; 93 t[j].pValue = t[i].pValue; 94 t[j].ulValueLen = t[i].ulValueLen; 95 } 96 j++; 97 } 98 if (j == count) 99 return (B_FALSE); 100 101 /* safety */ 102 t[j].pValue = NULL; 103 t[j].ulValueLen = 0; 104 return (B_TRUE); 105 } 106 107 static boolean_t 108 is_secret_key_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount) 109 { 110 int i; 111 for (i = 0; i < ulAttributeCount; i++) { 112 if (pTemplate[i].type == CKA_CLASS && 113 *(CK_OBJECT_CLASS *)(pTemplate[i].pValue) == 114 CKO_SECRET_KEY) 115 return (B_TRUE); 116 } 117 return (B_FALSE); 118 } 119 120 /* 121 * Allocate a template with space for new_count entries and copy the 122 * specified template into the new template. 123 */ 124 static CK_ATTRIBUTE_PTR 125 grow_template(CK_ATTRIBUTE_PTR old_template, CK_ULONG old_count, 126 CK_ULONG new_count) 127 { 128 CK_ATTRIBUTE_PTR new_template; 129 130 new_template = malloc(new_count * sizeof (CK_ATTRIBUTE)); 131 if (new_template != NULL) 132 bcopy(old_template, new_template, 133 old_count * sizeof (CK_ATTRIBUTE)); 134 return (new_template); 135 } 136 137 /* 138 * For fixed length keys such as DES, return the length based on 139 * the key type. For variable length keys such as AES, take the 140 * length from the CKA_VALUE_LEN attribute. 141 */ 142 static int 143 get_key_len_from_template(CK_MECHANISM_PTR pMechanism, 144 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, 145 kernel_object_t *basekey_p, ulong_t *key_len) 146 { 147 boolean_t fixed_len_key = B_FALSE; 148 ulong_t key_type; 149 int i; 150 151 for (i = 0; i < ulAttributeCount; i++) { 152 if (pTemplate[i].type == CKA_KEY_TYPE) { 153 get_ulong_attr_from_template(&key_type, &pTemplate[i]); 154 break; 155 } 156 } 157 /* CKA_KEY_TYPE must be present */ 158 if (i == ulAttributeCount) 159 return (CKR_TEMPLATE_INCOMPLETE); 160 161 switch (key_type) { 162 case CKK_DES: 163 *key_len = 8; 164 fixed_len_key = B_TRUE; 165 break; 166 case CKK_DES3: 167 *key_len = 24; 168 fixed_len_key = B_TRUE; 169 break; 170 case CKK_AES: 171 case CKK_BLOWFISH: 172 for (i = 0; i < ulAttributeCount; i++) { 173 if (pTemplate[i].type == CKA_VALUE_LEN) { 174 get_ulong_attr_from_template(key_len, 175 &pTemplate[i]); 176 break; 177 } 178 } 179 /* CKA_VALUE_LEN must be present */ 180 if (i == ulAttributeCount) 181 return (CKR_TEMPLATE_INCOMPLETE); 182 break; 183 case CKK_GENERIC_SECRET: 184 /* 185 * The key will not be truncated, so we need to 186 * get the max length for the mechanism. 187 */ 188 if (pMechanism->mechanism == CKM_DH_PKCS_DERIVE) { 189 CK_ATTRIBUTE tmp; 190 191 tmp.type = CKA_PRIME; 192 tmp.pValue = NULL; 193 194 /* get size of attribute */ 195 if (kernel_get_attribute(basekey_p, &tmp) != CKR_OK) { 196 return (CKR_ARGUMENTS_BAD); 197 } 198 *key_len = tmp.ulValueLen; 199 } else { 200 return (CKR_ARGUMENTS_BAD); 201 } 202 break; 203 default: 204 return (CKR_ATTRIBUTE_VALUE_INVALID); 205 } 206 207 if (fixed_len_key && attribute_in_template(CKA_VALUE_LEN, 208 pTemplate, ulAttributeCount)) 209 return (CKR_TEMPLATE_INCONSISTENT); 210 211 return (CKR_OK); 212 } 213 214 /* find specified attribute src template and copy to dest */ 215 static int 216 copy_attribute(CK_ULONG type, CK_ATTRIBUTE_PTR src, CK_ULONG src_cnt, 217 CK_ATTRIBUTE_PTR dst) 218 { 219 int rv, i; 220 221 for (i = 0; i < src_cnt; i++) { 222 if (src[i].type == type) { 223 rv = get_string_from_template(dst, &src[i]); 224 break; 225 } 226 } 227 /* 228 * The public template didn't have attribute. 229 */ 230 if (i == src_cnt) { 231 rv = CKR_TEMPLATE_INCOMPLETE; 232 } 233 return (rv); 234 } 235 236 static void 237 free_attributes(caddr_t p, uint_t *countp) 238 { 239 if (*countp > 0) { 240 free_object_attributes(p, *countp); 241 *countp = 0; 242 } 243 } 244 245 CK_RV 246 key_gen_by_value(CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, 247 CK_ULONG ulCount, kernel_session_t *session_p, 248 crypto_mech_type_t k_mech_type, kernel_object_t *new_objp) 249 { 250 crypto_nostore_generate_key_t obj_ngk; 251 char *key_buf = NULL; 252 CK_ATTRIBUTE_PTR newTemplate = NULL; 253 CK_BBOOL is_token_obj = FALSE; 254 CK_RV rv = CKR_OK; 255 ulong_t key_len = 0; 256 uint_t attr_count; 257 int r; 258 259 obj_ngk.ngk_in_count = 0; 260 obj_ngk.ngk_out_count = 0; 261 262 rv = get_key_len_from_template(pMechanism, pTemplate, ulCount, 263 NULL, &key_len); 264 if (rv != CRYPTO_SUCCESS) 265 goto failed_exit; 266 267 if ((key_buf = malloc(key_len)) == NULL) { 268 rv = CKR_HOST_MEMORY; 269 goto failed_exit; 270 } 271 272 attr_count = ulCount + 1; 273 newTemplate = grow_template(pTemplate, ulCount, attr_count); 274 if (newTemplate == NULL) { 275 rv = CKR_HOST_MEMORY; 276 goto failed_exit; 277 } 278 279 /* Now add the CKA_VALUE attribute to template */ 280 newTemplate[ulCount].type = CKA_VALUE; 281 newTemplate[ulCount].pValue = (caddr_t)key_buf; 282 newTemplate[ulCount].ulValueLen = key_len; 283 284 rv = process_object_attributes(newTemplate, attr_count - 1, 285 &obj_ngk.ngk_in_attributes, &is_token_obj); 286 if (rv != CKR_OK) { 287 goto failed_exit; 288 } 289 rv = process_object_attributes(&newTemplate[ulCount], 290 1, &obj_ngk.ngk_out_attributes, &is_token_obj); 291 if (rv != CKR_OK) { 292 goto failed_exit; 293 } 294 295 /* Cannot create a token object with a READ-ONLY session. */ 296 if (is_token_obj && session_p->ses_RO) { 297 rv = CKR_SESSION_READ_ONLY; 298 goto failed_exit; 299 } 300 301 /* Call the CRYPTO_NOSTORE_GENERATE_KEY ioctl */ 302 obj_ngk.ngk_session = session_p->k_session; 303 obj_ngk.ngk_in_count = attr_count - 1; 304 obj_ngk.ngk_out_count = 1; 305 obj_ngk.ngk_mechanism.cm_type = k_mech_type; 306 obj_ngk.ngk_mechanism.cm_param = pMechanism->pParameter; 307 obj_ngk.ngk_mechanism.cm_param_len = pMechanism->ulParameterLen; 308 309 while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY, 310 &obj_ngk)) < 0) { 311 if (errno != EINTR) 312 break; 313 } 314 if (r < 0) { 315 rv = CKR_FUNCTION_FAILED; 316 } else { 317 rv = crypto2pkcs11_error_number(obj_ngk.ngk_return_value); 318 } 319 free_attributes(obj_ngk.ngk_in_attributes, &obj_ngk.ngk_in_count); 320 if (rv != CKR_OK) { 321 goto failed_exit; 322 } 323 324 rv = get_object_attributes(&newTemplate[ulCount], 1, 325 obj_ngk.ngk_out_attributes); 326 free_attributes(obj_ngk.ngk_out_attributes, &obj_ngk.ngk_out_count); 327 if (rv != CRYPTO_SUCCESS) { 328 goto failed_exit; 329 } 330 331 /* 332 * CKA_VALUE_LEN is not stored with the secret key object, 333 * so we remove it by shifting attributes down one. 334 */ 335 (void) remove_one_attribute(newTemplate, CKA_VALUE_LEN, 336 attr_count, B_FALSE); 337 338 rv = kernel_build_object(newTemplate, attr_count - 1, 339 new_objp, session_p, KERNEL_GEN_KEY); 340 if (rv != CRYPTO_SUCCESS) { 341 goto failed_exit; 342 } 343 new_objp->is_lib_obj = B_TRUE; 344 new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 345 (void) free(newTemplate); 346 bzero(key_buf, key_len); 347 (void) free(key_buf); 348 return (CKR_OK); 349 350 failed_exit: 351 free_attributes(obj_ngk.ngk_in_attributes, &obj_ngk.ngk_in_count); 352 free_attributes(obj_ngk.ngk_out_attributes, &obj_ngk.ngk_out_count); 353 if (key_buf != NULL) { 354 bzero(key_buf, key_len); 355 (void) free(key_buf); 356 } 357 if (newTemplate != NULL) { 358 (void) free(newTemplate); 359 } 360 return (rv); 361 } 362 363 CK_RV 364 C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 365 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) 366 { 367 CK_RV rv = CKR_OK; 368 kernel_session_t *session_p; 369 kernel_object_t *new_objp = NULL; 370 kernel_slot_t *pslot; 371 boolean_t ses_lock_held = B_FALSE; 372 CK_BBOOL is_pri_obj; 373 CK_BBOOL is_token_obj = FALSE; 374 crypto_mech_type_t k_mech_type; 375 int r; 376 377 if (!kernel_initialized) 378 return (CKR_CRYPTOKI_NOT_INITIALIZED); 379 380 /* Obtain the session pointer */ 381 rv = handle2session(hSession, &session_p); 382 if (rv != CKR_OK) 383 return (rv); 384 385 if ((pMechanism == NULL) || (phKey == NULL)) { 386 rv = CKR_ARGUMENTS_BAD; 387 goto failed_exit; 388 } 389 390 if ((pTemplate == NULL) && (ulCount != 0)) { 391 rv = CKR_ARGUMENTS_BAD; 392 goto failed_exit; 393 } 394 395 /* Get the kernel's internal mechanism number. */ 396 rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 397 if (rv != CKR_OK) { 398 goto failed_exit; 399 } 400 401 /* Create an object wrapper in the library first */ 402 new_objp = calloc(1, sizeof (kernel_object_t)); 403 if (new_objp == NULL) { 404 rv = CKR_HOST_MEMORY; 405 goto failed_exit; 406 } 407 408 /* 409 * Special Case: if token does not support object creation, 410 * but does support key generation by value, then create a session 411 * object and initialize with value returned by token. 412 */ 413 pslot = slot_table[session_p->ses_slotid]; 414 if (!pslot->sl_func_list.fl_object_create) { 415 rv = key_gen_by_value(pMechanism, pTemplate, ulCount, session_p, 416 k_mech_type, new_objp); 417 if (rv != CKR_OK) 418 goto failed_exit; 419 } else { 420 crypto_object_generate_key_t obj_gk; 421 422 /* Process the attributes */ 423 rv = process_object_attributes(pTemplate, ulCount, 424 &obj_gk.gk_attributes, &is_token_obj); 425 if (rv != CKR_OK) { 426 goto failed_exit; 427 } 428 /* Cannot create a token object with a READ-ONLY session. */ 429 if (is_token_obj && session_p->ses_RO) { 430 free_object_attributes(obj_gk.gk_attributes, ulCount); 431 rv = CKR_SESSION_READ_ONLY; 432 goto failed_exit; 433 } 434 435 /* Call the CRYPTO_GENERATE_KEY ioctl */ 436 obj_gk.gk_session = session_p->k_session; 437 obj_gk.gk_count = ulCount; 438 obj_gk.gk_mechanism.cm_type = k_mech_type; 439 obj_gk.gk_mechanism.cm_param = pMechanism->pParameter; 440 obj_gk.gk_mechanism.cm_param_len = pMechanism->ulParameterLen; 441 442 while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY, 443 &obj_gk)) < 0) { 444 if (errno != EINTR) 445 break; 446 } 447 if (r < 0) { 448 rv = CKR_FUNCTION_FAILED; 449 } else { 450 rv = crypto2pkcs11_error_number(obj_gk.gk_return_value); 451 } 452 453 free_object_attributes(obj_gk.gk_attributes, ulCount); 454 455 if (rv != CKR_OK) { 456 goto failed_exit; 457 } 458 459 /* Get the value of the CKA_PRIVATE attribute. */ 460 rv = get_cka_private_value(session_p, obj_gk.gk_handle, 461 &is_pri_obj); 462 if (rv != CKR_OK) { 463 goto failed_exit; 464 } 465 466 /* 467 * Store the kernel object handle in the object wrapper and 468 * initialize the library object. 469 */ 470 new_objp->k_handle = obj_gk.gk_handle; 471 new_objp->is_lib_obj = B_FALSE; 472 new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 473 new_objp->extra_attrlistp = NULL; 474 475 if (is_pri_obj) 476 new_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 477 else 478 new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 479 480 if (is_token_obj) 481 new_objp->bool_attr_mask |= TOKEN_BOOL_ON; 482 else 483 new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 484 } 485 486 (void) pthread_mutex_init(&new_objp->object_mutex, NULL); 487 new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 488 489 /* 490 * Add the new object to the slot's token object list if it is a 491 * a token object. Otherwise, add it to the session's object list. 492 */ 493 if (is_token_obj) { 494 pslot = slot_table[session_p->ses_slotid]; 495 kernel_add_token_object_to_slot(new_objp, pslot); 496 } else { 497 kernel_add_object_to_session(new_objp, session_p); 498 } 499 500 *phKey = (CK_OBJECT_HANDLE)new_objp; 501 REFRELE(session_p, ses_lock_held); 502 return (rv); 503 504 failed_exit: 505 if (new_objp != NULL) { 506 (void) free(new_objp); 507 } 508 509 REFRELE(session_p, ses_lock_held); 510 return (rv); 511 } 512 513 CK_RV 514 key_gen_rsa_by_value(CK_MECHANISM_PTR pMechanism, 515 CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, 516 CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, 517 kernel_session_t *session_p, crypto_mech_type_t k_mech_type, 518 kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp) 519 { 520 crypto_nostore_generate_key_pair_t obj_nkp; 521 CK_ATTRIBUTE_PTR pubTemplate = NULL; 522 CK_ATTRIBUTE_PTR priTemplate = NULL; 523 CK_RV rv = CKR_OK; 524 CK_BBOOL is_token_obj1 = FALSE; 525 CK_BBOOL is_token_obj2 = FALSE; 526 uint_t pub_attr_count, pri_attr_count; 527 uint_t pub_out_attr_count = 0, pri_out_attr_count = 0; 528 char public_modulus[512]; 529 char public_exponent[8]; 530 char private_exponent[512]; 531 char private_modulus[512]; 532 char prime_1[512]; 533 char prime_2[512]; 534 char exponent_1[512]; 535 char exponent_2[512]; 536 char coefficient[512]; 537 CK_ULONG pub_class = CKO_PUBLIC_KEY; 538 CK_ULONG pri_class = CKO_PRIVATE_KEY; 539 CK_ULONG key_type; 540 CK_ULONG modulus_bytes; 541 boolean_t has_class, has_key_type, has_pub_exponent; 542 int n, r; 543 544 obj_nkp.nkp_in_public_count = 0; 545 obj_nkp.nkp_out_public_count = 0; 546 obj_nkp.nkp_in_private_count = 0; 547 obj_nkp.nkp_out_private_count = 0; 548 549 /* modulus bits must be present when generating a RSA key pair */ 550 if (!attribute_in_template(CKA_MODULUS_BITS, pPublicKeyTemplate, 551 ulPublicKeyAttributeCount)) { 552 rv = CKR_TEMPLATE_INCOMPLETE; 553 goto failed_exit; 554 } 555 556 modulus_bytes = get_modulus_bytes(pPublicKeyTemplate, 557 ulPublicKeyAttributeCount); 558 559 /* 560 * Add CKA_MODULUS to the public template. 561 * This attribute must not be in the template. 562 */ 563 if (attribute_in_template(CKA_MODULUS, pPublicKeyTemplate, 564 ulPublicKeyAttributeCount)) { 565 rv = CKR_TEMPLATE_INCONSISTENT; 566 goto failed_exit; 567 } 568 has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate, 569 ulPublicKeyAttributeCount); 570 has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate, 571 ulPublicKeyAttributeCount); 572 has_pub_exponent = attribute_in_template(CKA_PUBLIC_EXPONENT, 573 pPublicKeyTemplate, ulPublicKeyAttributeCount); 574 575 pub_attr_count = ulPublicKeyAttributeCount + 1; 576 if (!has_class) 577 pub_attr_count++; 578 if (!has_key_type) 579 pub_attr_count++; 580 if (!has_pub_exponent) 581 pub_attr_count++; 582 pubTemplate = grow_template(pPublicKeyTemplate, 583 ulPublicKeyAttributeCount, pub_attr_count); 584 if (pubTemplate == NULL) { 585 rv = CKR_HOST_MEMORY; 586 goto failed_exit; 587 } 588 589 n = ulPublicKeyAttributeCount; 590 if (!has_class) { 591 pubTemplate[n].type = CKA_CLASS; 592 pubTemplate[n].pValue = (caddr_t)&pub_class; 593 pubTemplate[n].ulValueLen = sizeof (pub_class); 594 n++; 595 } 596 if (!has_key_type) { 597 pubTemplate[n].type = CKA_KEY_TYPE; 598 key_type = CKK_RSA; 599 pubTemplate[n].pValue = (caddr_t)&key_type; 600 pubTemplate[n].ulValueLen = sizeof (key_type); 601 n++; 602 } 603 if (!has_pub_exponent) { 604 pubTemplate[n].type = CKA_PUBLIC_EXPONENT; 605 pubTemplate[n].pValue = (caddr_t)public_exponent; 606 pubTemplate[n].ulValueLen = modulus_bytes; 607 n++; 608 pub_out_attr_count++; 609 } 610 pubTemplate[n].type = CKA_MODULUS; 611 pubTemplate[n].pValue = (caddr_t)public_modulus; 612 pubTemplate[n].ulValueLen = modulus_bytes; 613 pub_out_attr_count++; 614 615 rv = process_object_attributes(pubTemplate, 616 pub_attr_count - pub_out_attr_count, 617 &obj_nkp.nkp_in_public_attributes, &is_token_obj1); 618 if (rv != CKR_OK) { 619 goto failed_exit; 620 } 621 obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count; 622 623 rv = process_object_attributes( 624 &pubTemplate[pub_attr_count - pub_out_attr_count], 625 pub_out_attr_count, &obj_nkp.nkp_out_public_attributes, 626 &is_token_obj1); 627 if (rv != CKR_OK) { 628 goto failed_exit; 629 } 630 obj_nkp.nkp_out_public_count = pub_out_attr_count; 631 632 /* 633 * Cannot create a token object with a READ-ONLY 634 * session. 635 */ 636 if (is_token_obj1 && session_p->ses_RO) { 637 rv = CKR_SESSION_READ_ONLY; 638 goto failed_exit; 639 } 640 641 /* 642 * Add CKA_MODULUS and CKA_PRIVATE_EXPONENT 643 * to the private template. These attributes 644 * must not be in the template. 645 */ 646 if (attribute_in_template(CKA_PRIVATE_EXPONENT, 647 pPrivateKeyTemplate, ulPrivateKeyAttributeCount) || 648 attribute_in_template(CKA_MODULUS, 649 pPrivateKeyTemplate, ulPrivateKeyAttributeCount)) { 650 rv = CKR_TEMPLATE_INCONSISTENT; 651 goto failed_exit; 652 } 653 has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate, 654 ulPrivateKeyAttributeCount); 655 has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate, 656 ulPrivateKeyAttributeCount); 657 658 pri_attr_count = ulPrivateKeyAttributeCount + 7; 659 if (!has_class) 660 pri_attr_count++; 661 if (!has_key_type) 662 pri_attr_count++; 663 664 /* allocate space for CKA_PUBLIC_EXPONENT */ 665 priTemplate = grow_template(pPrivateKeyTemplate, 666 ulPrivateKeyAttributeCount, pri_attr_count + 1); 667 if (priTemplate == NULL) { 668 rv = CKR_HOST_MEMORY; 669 goto failed_exit; 670 } 671 n = ulPrivateKeyAttributeCount; 672 if (!has_class) { 673 priTemplate[n].type = CKA_CLASS; 674 priTemplate[n].pValue = (caddr_t)&pri_class; 675 priTemplate[n].ulValueLen = sizeof (pri_class); 676 n++; 677 } 678 if (!has_key_type) { 679 priTemplate[n].type = CKA_KEY_TYPE; 680 key_type = CKK_RSA; 681 priTemplate[n].pValue = (caddr_t)&key_type; 682 priTemplate[n].ulValueLen = sizeof (key_type); 683 n++; 684 } 685 priTemplate[n].type = CKA_MODULUS; 686 priTemplate[n].pValue = (caddr_t)private_modulus; 687 priTemplate[n].ulValueLen = modulus_bytes; 688 pri_out_attr_count++; 689 690 n++; 691 priTemplate[n].type = CKA_PRIVATE_EXPONENT; 692 priTemplate[n].pValue = (caddr_t)private_exponent; 693 priTemplate[n].ulValueLen = modulus_bytes; 694 pri_out_attr_count++; 695 696 n++; 697 priTemplate[n].type = CKA_PRIME_1; 698 priTemplate[n].pValue = (caddr_t)prime_1; 699 priTemplate[n].ulValueLen = modulus_bytes/2; 700 pri_out_attr_count++; 701 702 n++; 703 priTemplate[n].type = CKA_PRIME_2; 704 priTemplate[n].pValue = (caddr_t)prime_2; 705 priTemplate[n].ulValueLen = modulus_bytes/2; 706 pri_out_attr_count++; 707 708 n++; 709 priTemplate[n].type = CKA_EXPONENT_1; 710 priTemplate[n].pValue = (caddr_t)exponent_1; 711 priTemplate[n].ulValueLen = modulus_bytes/2; 712 pri_out_attr_count++; 713 714 n++; 715 priTemplate[n].type = CKA_EXPONENT_2; 716 priTemplate[n].pValue = (caddr_t)exponent_2; 717 priTemplate[n].ulValueLen = modulus_bytes/2; 718 pri_out_attr_count++; 719 720 n++; 721 priTemplate[n].type = CKA_COEFFICIENT; 722 priTemplate[n].pValue = (caddr_t)coefficient; 723 priTemplate[n].ulValueLen = modulus_bytes/2; 724 pri_out_attr_count++; 725 726 rv = process_object_attributes(priTemplate, 727 pri_attr_count - pri_out_attr_count, 728 &obj_nkp.nkp_in_private_attributes, &is_token_obj2); 729 if (rv != CKR_OK) { 730 goto failed_exit; 731 } 732 obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count; 733 734 rv = process_object_attributes( 735 &priTemplate[pri_attr_count - pri_out_attr_count], 736 pri_out_attr_count, &obj_nkp.nkp_out_private_attributes, 737 &is_token_obj2); 738 if (rv != CKR_OK) { 739 goto failed_exit; 740 } 741 obj_nkp.nkp_out_private_count = pri_out_attr_count; 742 743 /* 744 * The public key and the private key need to contain the same 745 * attribute values for CKA_TOKEN. 746 */ 747 if (is_token_obj1 != is_token_obj2) { 748 rv = CKR_ATTRIBUTE_VALUE_INVALID; 749 goto failed_exit; 750 } 751 752 /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */ 753 obj_nkp.nkp_session = session_p-> k_session; 754 obj_nkp.nkp_mechanism.cm_type = k_mech_type; 755 obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter; 756 obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen; 757 758 while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR, 759 &obj_nkp)) < 0) { 760 if (errno != EINTR) 761 break; 762 } 763 if (r < 0) { 764 rv = CKR_FUNCTION_FAILED; 765 } else { 766 rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value); 767 } 768 free_attributes(obj_nkp.nkp_in_public_attributes, 769 &obj_nkp.nkp_in_public_count); 770 free_attributes(obj_nkp.nkp_in_private_attributes, 771 &obj_nkp.nkp_in_private_count); 772 773 if (rv != CKR_OK) { 774 goto failed_exit; 775 } 776 777 rv = get_object_attributes( 778 &pubTemplate[pub_attr_count - pub_out_attr_count], 779 pub_out_attr_count, obj_nkp.nkp_out_public_attributes); 780 if (rv == CRYPTO_SUCCESS) { 781 rv = get_object_attributes( 782 &priTemplate[pri_attr_count - pri_out_attr_count], 783 pri_out_attr_count, obj_nkp.nkp_out_private_attributes); 784 } 785 free_attributes(obj_nkp.nkp_out_public_attributes, 786 &obj_nkp.nkp_out_public_count); 787 free_attributes(obj_nkp.nkp_out_private_attributes, 788 &obj_nkp.nkp_out_private_count); 789 if (rv != CRYPTO_SUCCESS) { 790 goto failed_exit; 791 } 792 793 /* store generated modulus and public exponent */ 794 rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp, 795 session_p, KERNEL_GEN_KEY); 796 if (rv != CRYPTO_SUCCESS) { 797 goto failed_exit; 798 } 799 800 /* 801 * Copy CKA_PUBLIC_EXPONENT from the public template 802 * to the private template. 803 */ 804 rv = copy_attribute(CKA_PUBLIC_EXPONENT, pubTemplate, 805 pub_attr_count, &priTemplate[pri_attr_count]); 806 if (rv != CRYPTO_SUCCESS) { 807 goto failed_exit; 808 } 809 810 rv = kernel_build_object(priTemplate, pri_attr_count + 1, new_pri_objp, 811 session_p, KERNEL_GEN_KEY); 812 (void) free(priTemplate[pri_attr_count].pValue); 813 if (rv != CRYPTO_SUCCESS) { 814 goto failed_exit; 815 } 816 (void) free(pubTemplate); 817 (void) free(priTemplate); 818 819 new_pub_objp->is_lib_obj = B_TRUE; 820 new_pri_objp->is_lib_obj = B_TRUE; 821 new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p; 822 new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p; 823 (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL); 824 new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 825 (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL); 826 new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 827 return (CKR_OK); 828 829 failed_exit: 830 free_attributes(obj_nkp.nkp_in_public_attributes, 831 &obj_nkp.nkp_in_public_count); 832 free_attributes(obj_nkp.nkp_out_public_attributes, 833 &obj_nkp.nkp_out_public_count); 834 free_attributes(obj_nkp.nkp_in_private_attributes, 835 &obj_nkp.nkp_in_private_count); 836 free_attributes(obj_nkp.nkp_out_private_attributes, 837 &obj_nkp.nkp_out_private_count); 838 if (pubTemplate != NULL) { 839 (void) free(pubTemplate); 840 } 841 if (priTemplate != NULL) { 842 (void) free(priTemplate); 843 } 844 return (rv); 845 } 846 847 CK_RV 848 key_gen_dh_by_value(CK_MECHANISM_PTR pMechanism, 849 CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, 850 CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, 851 kernel_session_t *session_p, crypto_mech_type_t k_mech_type, 852 kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp) 853 { 854 crypto_nostore_generate_key_pair_t obj_nkp; 855 CK_ATTRIBUTE_PTR pubTemplate = NULL; 856 CK_ATTRIBUTE_PTR priTemplate = NULL; 857 CK_RV rv = CKR_OK; 858 CK_BBOOL is_token_obj1 = FALSE; 859 CK_BBOOL is_token_obj2 = FALSE; 860 uint_t pub_attr_count, pri_attr_count; 861 uint_t pub_out_attr_count = 0, pri_out_attr_count = 0; 862 char public_value[256]; 863 char private_value[256]; 864 CK_ULONG pub_class = CKO_PUBLIC_KEY; 865 CK_ULONG pri_class = CKO_PRIVATE_KEY; 866 CK_ULONG key_type; 867 boolean_t has_class, has_key_type; 868 int n, r; 869 870 obj_nkp.nkp_in_public_count = 0; 871 obj_nkp.nkp_out_public_count = 0; 872 obj_nkp.nkp_in_private_count = 0; 873 obj_nkp.nkp_out_private_count = 0; 874 875 /* 876 * Add CKA_VALUE to the public template. 877 * This attribute must not be in the template. 878 */ 879 if (attribute_in_template(CKA_VALUE, pPublicKeyTemplate, 880 ulPublicKeyAttributeCount)) { 881 rv = CKR_TEMPLATE_INCONSISTENT; 882 goto failed_exit; 883 } 884 has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate, 885 ulPublicKeyAttributeCount); 886 has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate, 887 ulPublicKeyAttributeCount); 888 889 pub_attr_count = ulPublicKeyAttributeCount + 1; 890 if (!has_class) 891 pub_attr_count++; 892 if (!has_key_type) 893 pub_attr_count++; 894 pubTemplate = grow_template(pPublicKeyTemplate, 895 ulPublicKeyAttributeCount, pub_attr_count); 896 if (pubTemplate == NULL) { 897 rv = CKR_HOST_MEMORY; 898 goto failed_exit; 899 } 900 901 n = ulPublicKeyAttributeCount; 902 if (!has_class) { 903 pubTemplate[n].type = CKA_CLASS; 904 pubTemplate[n].pValue = (caddr_t)&pub_class; 905 pubTemplate[n].ulValueLen = sizeof (pub_class); 906 n++; 907 } 908 if (!has_key_type) { 909 pubTemplate[n].type = CKA_KEY_TYPE; 910 key_type = CKK_DH; 911 pubTemplate[n].pValue = (caddr_t)&key_type; 912 pubTemplate[n].ulValueLen = sizeof (key_type); 913 n++; 914 } 915 pubTemplate[n].type = CKA_VALUE; 916 pubTemplate[n].pValue = (caddr_t)public_value; 917 pubTemplate[n].ulValueLen = sizeof (public_value); 918 pub_out_attr_count++; 919 920 rv = process_object_attributes(pubTemplate, 921 pub_attr_count - pub_out_attr_count, 922 &obj_nkp.nkp_in_public_attributes, &is_token_obj1); 923 if (rv != CKR_OK) { 924 goto failed_exit; 925 } 926 obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count; 927 928 rv = process_object_attributes( 929 &pubTemplate[pub_attr_count - pub_out_attr_count], 930 pub_out_attr_count, &obj_nkp.nkp_out_public_attributes, 931 &is_token_obj1); 932 if (rv != CKR_OK) { 933 goto failed_exit; 934 } 935 obj_nkp.nkp_out_public_count = pub_out_attr_count; 936 937 /* 938 * Cannot create a token object with a READ-ONLY 939 * session. 940 */ 941 if (is_token_obj1 && session_p->ses_RO) { 942 rv = CKR_SESSION_READ_ONLY; 943 goto failed_exit; 944 } 945 946 /* 947 * CKA_BASE, CKA_PRIME, and CKA_VALUE must not appear 948 * in private template. 949 */ 950 if (attribute_in_template(CKA_BASE, pPrivateKeyTemplate, 951 ulPrivateKeyAttributeCount) || 952 attribute_in_template(CKA_PRIME, pPrivateKeyTemplate, 953 ulPrivateKeyAttributeCount) || 954 attribute_in_template(CKA_VALUE, pPrivateKeyTemplate, 955 ulPrivateKeyAttributeCount)) { 956 rv = CKR_TEMPLATE_INCONSISTENT; 957 goto failed_exit; 958 } 959 960 if (attribute_in_template(CKA_VALUE, pPrivateKeyTemplate, 961 ulPrivateKeyAttributeCount)) { 962 rv = CKR_TEMPLATE_INCONSISTENT; 963 goto failed_exit; 964 } 965 has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate, 966 ulPrivateKeyAttributeCount); 967 has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate, 968 ulPrivateKeyAttributeCount); 969 970 pri_attr_count = ulPrivateKeyAttributeCount + 1; 971 if (!has_class) 972 pri_attr_count++; 973 if (!has_key_type) 974 pri_attr_count++; 975 976 /* allocate space for CKA_BASE and CKA_PRIME */ 977 priTemplate = grow_template(pPrivateKeyTemplate, 978 ulPrivateKeyAttributeCount, pri_attr_count + 2); 979 if (priTemplate == NULL) { 980 rv = CKR_HOST_MEMORY; 981 goto failed_exit; 982 } 983 n = ulPrivateKeyAttributeCount; 984 if (!has_class) { 985 priTemplate[n].type = CKA_CLASS; 986 priTemplate[n].pValue = (caddr_t)&pri_class; 987 priTemplate[n].ulValueLen = sizeof (pri_class); 988 n++; 989 } 990 if (!has_key_type) { 991 priTemplate[n].type = CKA_KEY_TYPE; 992 key_type = CKK_DH; 993 priTemplate[n].pValue = (caddr_t)&key_type; 994 priTemplate[n].ulValueLen = sizeof (key_type); 995 n++; 996 } 997 priTemplate[n].type = CKA_VALUE; 998 priTemplate[n].pValue = (caddr_t)private_value; 999 priTemplate[n].ulValueLen = sizeof (private_value); 1000 pri_out_attr_count++; 1001 1002 rv = process_object_attributes(priTemplate, 1003 pri_attr_count - pri_out_attr_count, 1004 &obj_nkp.nkp_in_private_attributes, &is_token_obj2); 1005 if (rv != CKR_OK) { 1006 goto failed_exit; 1007 } 1008 obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count; 1009 1010 rv = process_object_attributes( 1011 &priTemplate[pri_attr_count - pri_out_attr_count], 1012 pri_out_attr_count, &obj_nkp.nkp_out_private_attributes, 1013 &is_token_obj2); 1014 if (rv != CKR_OK) { 1015 goto failed_exit; 1016 } 1017 obj_nkp.nkp_out_private_count = pri_out_attr_count; 1018 1019 /* 1020 * The public key and the private key need to contain the same 1021 * attribute values for CKA_TOKEN. 1022 */ 1023 if (is_token_obj1 != is_token_obj2) { 1024 rv = CKR_ATTRIBUTE_VALUE_INVALID; 1025 goto failed_exit; 1026 } 1027 1028 /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */ 1029 obj_nkp.nkp_session = session_p-> k_session; 1030 obj_nkp.nkp_mechanism.cm_type = k_mech_type; 1031 obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter; 1032 obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen; 1033 1034 while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR, 1035 &obj_nkp)) < 0) { 1036 if (errno != EINTR) 1037 break; 1038 } 1039 if (r < 0) { 1040 rv = CKR_FUNCTION_FAILED; 1041 } else { 1042 rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value); 1043 } 1044 free_attributes(obj_nkp.nkp_in_public_attributes, 1045 &obj_nkp.nkp_in_public_count); 1046 free_attributes(obj_nkp.nkp_in_private_attributes, 1047 &obj_nkp.nkp_in_private_count); 1048 1049 if (rv != CKR_OK) { 1050 goto failed_exit; 1051 } 1052 1053 rv = get_object_attributes( 1054 &pubTemplate[pub_attr_count - pub_out_attr_count], 1055 pub_out_attr_count, obj_nkp.nkp_out_public_attributes); 1056 if (rv == CRYPTO_SUCCESS) { 1057 rv = get_object_attributes( 1058 &priTemplate[pri_attr_count - pri_out_attr_count], 1059 pri_out_attr_count, obj_nkp.nkp_out_private_attributes); 1060 } 1061 free_attributes(obj_nkp.nkp_out_public_attributes, 1062 &obj_nkp.nkp_out_public_count); 1063 free_attributes(obj_nkp.nkp_out_private_attributes, 1064 &obj_nkp.nkp_out_private_count); 1065 1066 if (rv != CRYPTO_SUCCESS) { 1067 goto failed_exit; 1068 } 1069 1070 rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp, 1071 session_p, KERNEL_GEN_KEY); 1072 if (rv != CRYPTO_SUCCESS) { 1073 goto failed_exit; 1074 } 1075 1076 /* 1077 * Copy CKA_BASE and CKA_PRIME from the public template 1078 * to the private template. 1079 */ 1080 rv = copy_attribute(CKA_BASE, pubTemplate, pub_attr_count, 1081 &priTemplate[pri_attr_count]); 1082 if (rv != CRYPTO_SUCCESS) { 1083 goto failed_exit; 1084 } 1085 rv = copy_attribute(CKA_PRIME, pubTemplate, pub_attr_count, 1086 &priTemplate[pri_attr_count + 1]); 1087 if (rv != CRYPTO_SUCCESS) { 1088 (void) free(priTemplate[pri_attr_count].pValue); 1089 goto failed_exit; 1090 } 1091 1092 /* +2 to account for CKA_BASE and CKA_PRIME */ 1093 rv = kernel_build_object(priTemplate, pri_attr_count + 2, 1094 new_pri_objp, session_p, KERNEL_GEN_KEY); 1095 (void) free(priTemplate[pri_attr_count].pValue); 1096 (void) free(priTemplate[pri_attr_count + 1].pValue); 1097 if (rv != CRYPTO_SUCCESS) { 1098 goto failed_exit; 1099 } 1100 (void) free(pubTemplate); 1101 (void) free(priTemplate); 1102 1103 new_pub_objp->is_lib_obj = B_TRUE; 1104 new_pri_objp->is_lib_obj = B_TRUE; 1105 new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1106 new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1107 (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL); 1108 new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 1109 (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL); 1110 new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 1111 return (CKR_OK); 1112 1113 failed_exit: 1114 free_attributes(obj_nkp.nkp_in_public_attributes, 1115 &obj_nkp.nkp_in_public_count); 1116 free_attributes(obj_nkp.nkp_out_public_attributes, 1117 &obj_nkp.nkp_out_public_count); 1118 free_attributes(obj_nkp.nkp_in_private_attributes, 1119 &obj_nkp.nkp_in_private_count); 1120 free_attributes(obj_nkp.nkp_out_private_attributes, 1121 &obj_nkp.nkp_out_private_count); 1122 if (pubTemplate != NULL) { 1123 (void) free(pubTemplate); 1124 } 1125 if (priTemplate != NULL) { 1126 (void) free(priTemplate); 1127 } 1128 return (rv); 1129 } 1130 1131 CK_RV 1132 key_gen_ec_by_value(CK_MECHANISM_PTR pMechanism, 1133 CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, 1134 CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, 1135 kernel_session_t *session_p, crypto_mech_type_t k_mech_type, 1136 kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp) 1137 { 1138 crypto_nostore_generate_key_pair_t obj_nkp; 1139 CK_ATTRIBUTE_PTR pubTemplate = NULL; 1140 CK_ATTRIBUTE_PTR priTemplate = NULL; 1141 CK_RV rv = CKR_OK; 1142 CK_BBOOL is_token_obj1 = FALSE; 1143 CK_BBOOL is_token_obj2 = FALSE; 1144 uint_t pub_attr_count, pri_attr_count; 1145 uint_t pub_out_attr_count = 0, pri_out_attr_count = 0; 1146 char value[32]; 1147 char point[128]; 1148 CK_ULONG pub_class = CKO_PUBLIC_KEY; 1149 CK_ULONG pri_class = CKO_PRIVATE_KEY; 1150 CK_ULONG key_type; 1151 boolean_t has_class, has_key_type; 1152 int n, r; 1153 1154 obj_nkp.nkp_in_public_count = 0; 1155 obj_nkp.nkp_out_public_count = 0; 1156 obj_nkp.nkp_in_private_count = 0; 1157 obj_nkp.nkp_out_private_count = 0; 1158 1159 /* 1160 * Add CKA_EC_POINT to the public template. 1161 * This is the generated value Q. This attribute 1162 * must not be in the template. 1163 */ 1164 if (attribute_in_template(CKA_EC_POINT, pPublicKeyTemplate, 1165 ulPublicKeyAttributeCount)) { 1166 rv = CKR_TEMPLATE_INCONSISTENT; 1167 goto failed_exit; 1168 } 1169 has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate, 1170 ulPublicKeyAttributeCount); 1171 has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate, 1172 ulPublicKeyAttributeCount); 1173 1174 pub_attr_count = ulPublicKeyAttributeCount + 1; 1175 if (!has_class) 1176 pub_attr_count++; 1177 if (!has_key_type) 1178 pub_attr_count++; 1179 pubTemplate = grow_template(pPublicKeyTemplate, 1180 ulPublicKeyAttributeCount, pub_attr_count); 1181 if (pubTemplate == NULL) { 1182 rv = CKR_HOST_MEMORY; 1183 goto failed_exit; 1184 } 1185 1186 n = ulPublicKeyAttributeCount; 1187 if (!has_class) { 1188 pubTemplate[n].type = CKA_CLASS; 1189 pubTemplate[n].pValue = (caddr_t)&pub_class; 1190 pubTemplate[n].ulValueLen = sizeof (pub_class); 1191 n++; 1192 } 1193 if (!has_key_type) { 1194 pubTemplate[n].type = CKA_KEY_TYPE; 1195 key_type = CKK_EC; 1196 pubTemplate[n].pValue = (caddr_t)&key_type; 1197 pubTemplate[n].ulValueLen = sizeof (key_type); 1198 n++; 1199 } 1200 pubTemplate[n].type = CKA_EC_POINT; 1201 pubTemplate[n].pValue = (caddr_t)point; 1202 pubTemplate[n].ulValueLen = sizeof (point); 1203 pub_out_attr_count++; 1204 1205 rv = process_object_attributes(pubTemplate, 1206 pub_attr_count - pub_out_attr_count, 1207 &obj_nkp.nkp_in_public_attributes, &is_token_obj1); 1208 if (rv != CKR_OK) { 1209 goto failed_exit; 1210 } 1211 obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count; 1212 1213 rv = process_object_attributes( 1214 &pubTemplate[pub_attr_count - pub_out_attr_count], 1215 pub_out_attr_count, &obj_nkp.nkp_out_public_attributes, 1216 &is_token_obj1); 1217 if (rv != CKR_OK) { 1218 goto failed_exit; 1219 } 1220 obj_nkp.nkp_out_public_count = pub_out_attr_count; 1221 1222 /* 1223 * Cannot create a token object with a READ-ONLY 1224 * session. 1225 */ 1226 if (is_token_obj1 && session_p->ses_RO) { 1227 rv = CKR_SESSION_READ_ONLY; 1228 goto failed_exit; 1229 } 1230 1231 /* 1232 * CKA_EC_PARAMS and CKA_VALUE must not appear in 1233 * private template. 1234 */ 1235 if (attribute_in_template(CKA_EC_PARAMS, pPrivateKeyTemplate, 1236 ulPrivateKeyAttributeCount) || 1237 attribute_in_template(CKA_VALUE, pPrivateKeyTemplate, 1238 ulPrivateKeyAttributeCount)) { 1239 rv = CKR_TEMPLATE_INCONSISTENT; 1240 goto failed_exit; 1241 } 1242 has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate, 1243 ulPrivateKeyAttributeCount); 1244 has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate, 1245 ulPrivateKeyAttributeCount); 1246 1247 pri_attr_count = ulPrivateKeyAttributeCount + 1; 1248 if (!has_class) 1249 pri_attr_count++; 1250 if (!has_key_type) 1251 pri_attr_count++; 1252 1253 /* allocate space for CKA_EC_PARAMS */ 1254 priTemplate = grow_template(pPrivateKeyTemplate, 1255 ulPrivateKeyAttributeCount, pri_attr_count + 1); 1256 if (priTemplate == NULL) { 1257 rv = CKR_HOST_MEMORY; 1258 goto failed_exit; 1259 } 1260 n = ulPrivateKeyAttributeCount; 1261 if (!has_class) { 1262 priTemplate[n].type = CKA_CLASS; 1263 priTemplate[n].pValue = (caddr_t)&pri_class; 1264 priTemplate[n].ulValueLen = sizeof (pri_class); 1265 n++; 1266 } 1267 if (!has_key_type) { 1268 priTemplate[n].type = CKA_KEY_TYPE; 1269 key_type = CKK_EC; 1270 priTemplate[n].pValue = (caddr_t)&key_type; 1271 priTemplate[n].ulValueLen = sizeof (key_type); 1272 n++; 1273 } 1274 priTemplate[n].type = CKA_VALUE; 1275 priTemplate[n].pValue = (caddr_t)value; 1276 priTemplate[n].ulValueLen = sizeof (value); 1277 pri_out_attr_count++; 1278 1279 rv = process_object_attributes(priTemplate, 1280 pri_attr_count - pri_out_attr_count, 1281 &obj_nkp.nkp_in_private_attributes, &is_token_obj2); 1282 if (rv != CKR_OK) { 1283 goto failed_exit; 1284 } 1285 obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count; 1286 1287 rv = process_object_attributes( 1288 &priTemplate[pri_attr_count - pri_out_attr_count], 1289 pri_out_attr_count, &obj_nkp.nkp_out_private_attributes, 1290 &is_token_obj2); 1291 if (rv != CKR_OK) { 1292 goto failed_exit; 1293 } 1294 obj_nkp.nkp_out_private_count = pri_out_attr_count; 1295 1296 /* 1297 * The public key and the private key need to contain the same 1298 * attribute values for CKA_TOKEN. 1299 */ 1300 if (is_token_obj1 != is_token_obj2) { 1301 rv = CKR_ATTRIBUTE_VALUE_INVALID; 1302 goto failed_exit; 1303 } 1304 1305 /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */ 1306 obj_nkp.nkp_session = session_p-> k_session; 1307 obj_nkp.nkp_mechanism.cm_type = k_mech_type; 1308 obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter; 1309 obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen; 1310 1311 while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR, 1312 &obj_nkp)) < 0) { 1313 if (errno != EINTR) 1314 break; 1315 } 1316 if (r < 0) { 1317 rv = CKR_FUNCTION_FAILED; 1318 } else { 1319 rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value); 1320 } 1321 free_attributes(obj_nkp.nkp_in_public_attributes, 1322 &obj_nkp.nkp_in_public_count); 1323 free_attributes(obj_nkp.nkp_in_private_attributes, 1324 &obj_nkp.nkp_in_private_count); 1325 1326 if (rv != CKR_OK) { 1327 goto failed_exit; 1328 } 1329 1330 rv = get_object_attributes( 1331 &pubTemplate[pub_attr_count - pub_out_attr_count], 1332 pub_out_attr_count, obj_nkp.nkp_out_public_attributes); 1333 if (rv == CRYPTO_SUCCESS) { 1334 rv = get_object_attributes( 1335 &priTemplate[pri_attr_count - pri_out_attr_count], 1336 pri_out_attr_count, obj_nkp.nkp_out_private_attributes); 1337 } 1338 free_attributes(obj_nkp.nkp_out_public_attributes, 1339 &obj_nkp.nkp_out_public_count); 1340 free_attributes(obj_nkp.nkp_out_private_attributes, 1341 &obj_nkp.nkp_out_private_count); 1342 if (rv != CRYPTO_SUCCESS) { 1343 goto failed_exit; 1344 } 1345 1346 rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp, 1347 session_p, KERNEL_GEN_KEY); 1348 if (rv != CRYPTO_SUCCESS) { 1349 goto failed_exit; 1350 } 1351 1352 /* 1353 * Copy CKA_EC_PARAMS from the public template to the 1354 * private template. 1355 */ 1356 rv = copy_attribute(CKA_EC_PARAMS, pubTemplate, pub_attr_count, 1357 &priTemplate[pri_attr_count]); 1358 if (rv != CRYPTO_SUCCESS) { 1359 goto failed_exit; 1360 } 1361 1362 /* +1 to account for CKA_EC_PARAMS */ 1363 rv = kernel_build_object(priTemplate, pri_attr_count + 1, 1364 new_pri_objp, session_p, KERNEL_GEN_KEY); 1365 (void) free(priTemplate[pri_attr_count].pValue); 1366 if (rv != CRYPTO_SUCCESS) { 1367 goto failed_exit; 1368 } 1369 (void) free(pubTemplate); 1370 (void) free(priTemplate); 1371 1372 new_pub_objp->is_lib_obj = B_TRUE; 1373 new_pri_objp->is_lib_obj = B_TRUE; 1374 new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1375 new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1376 (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL); 1377 new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 1378 (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL); 1379 new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 1380 return (CKR_OK); 1381 1382 failed_exit: 1383 free_attributes(obj_nkp.nkp_in_public_attributes, 1384 &obj_nkp.nkp_in_public_count); 1385 free_attributes(obj_nkp.nkp_out_public_attributes, 1386 &obj_nkp.nkp_out_public_count); 1387 free_attributes(obj_nkp.nkp_in_private_attributes, 1388 &obj_nkp.nkp_in_private_count); 1389 free_attributes(obj_nkp.nkp_out_private_attributes, 1390 &obj_nkp.nkp_out_private_count); 1391 if (pubTemplate != NULL) { 1392 (void) free(pubTemplate); 1393 } 1394 if (priTemplate != NULL) { 1395 (void) free(priTemplate); 1396 } 1397 return (rv); 1398 } 1399 1400 CK_RV 1401 C_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 1402 CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, 1403 CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, 1404 CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey) 1405 { 1406 CK_RV rv = CKR_OK; 1407 kernel_session_t *session_p; 1408 kernel_object_t *new_pub_objp = NULL; 1409 kernel_object_t *new_pri_objp = NULL; 1410 kernel_slot_t *pslot; 1411 boolean_t ses_lock_held = B_FALSE; 1412 CK_BBOOL is_pri_obj1; 1413 CK_BBOOL is_pri_obj2; 1414 CK_BBOOL is_token_obj1 = FALSE; 1415 CK_BBOOL is_token_obj2 = FALSE; 1416 crypto_mech_type_t k_mech_type; 1417 int r; 1418 CK_RV (*func)(CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, CK_ULONG, 1419 CK_ATTRIBUTE_PTR, CK_ULONG, kernel_session_t *, crypto_mech_type_t, 1420 kernel_object_t *, kernel_object_t *); 1421 1422 if (!kernel_initialized) 1423 return (CKR_CRYPTOKI_NOT_INITIALIZED); 1424 1425 /* Obtain the session pointer. */ 1426 rv = handle2session(hSession, &session_p); 1427 if (rv != CKR_OK) 1428 return (rv); 1429 1430 if ((pMechanism == NULL) || (phPublicKey == NULL) || 1431 (phPrivateKey == NULL)) { 1432 rv = CKR_ARGUMENTS_BAD; 1433 goto failed_exit; 1434 } 1435 1436 if ((pPublicKeyTemplate == NULL) && (ulPublicKeyAttributeCount != 0)) { 1437 rv = CKR_ARGUMENTS_BAD; 1438 goto failed_exit; 1439 } 1440 1441 if ((pPrivateKeyTemplate == NULL) && 1442 (ulPrivateKeyAttributeCount != 0)) { 1443 rv = CKR_ARGUMENTS_BAD; 1444 goto failed_exit; 1445 } 1446 1447 /* Get the kernel's internal mechanism number. */ 1448 rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 1449 if (rv != CKR_OK) { 1450 goto failed_exit; 1451 } 1452 1453 /* Create an object wrapper for the public key */ 1454 new_pub_objp = calloc(1, sizeof (kernel_object_t)); 1455 if (new_pub_objp == NULL) { 1456 rv = CKR_HOST_MEMORY; 1457 goto failed_exit; 1458 } 1459 1460 /* Create an object wrapper for the private key. */ 1461 new_pri_objp = calloc(1, sizeof (kernel_object_t)); 1462 if (new_pri_objp == NULL) { 1463 rv = CKR_HOST_MEMORY; 1464 goto failed_exit; 1465 } 1466 1467 /* 1468 * Special Case: if token does not support object creation, 1469 * but does support key generation by value, then create a session 1470 * object and initialize with values returned by token. 1471 */ 1472 pslot = slot_table[session_p->ses_slotid]; 1473 if (!pslot->sl_func_list.fl_object_create) { 1474 switch (pMechanism->mechanism) { 1475 case CKM_RSA_PKCS_KEY_PAIR_GEN: 1476 func = key_gen_rsa_by_value; 1477 break; 1478 1479 case CKM_DH_PKCS_KEY_PAIR_GEN: 1480 func = key_gen_dh_by_value; 1481 break; 1482 1483 case CKM_EC_KEY_PAIR_GEN: 1484 func = key_gen_ec_by_value; 1485 break; 1486 1487 default: 1488 rv = CKR_MECHANISM_INVALID; 1489 goto failed_exit; 1490 } 1491 rv = (*func)(pMechanism, pPublicKeyTemplate, 1492 ulPublicKeyAttributeCount, pPrivateKeyTemplate, 1493 ulPrivateKeyAttributeCount, session_p, k_mech_type, 1494 new_pub_objp, new_pri_objp); 1495 if (rv != CKR_OK) 1496 goto failed_exit; 1497 } else { 1498 crypto_object_generate_key_pair_t obj_kp; 1499 1500 /* Process the public key attributes. */ 1501 rv = process_object_attributes(pPublicKeyTemplate, 1502 ulPublicKeyAttributeCount, &obj_kp.kp_public_attributes, 1503 &is_token_obj1); 1504 if (rv != CKR_OK) { 1505 goto failed_exit; 1506 } 1507 1508 /* Cannot create a token object with a READ-ONLY session. */ 1509 if (is_token_obj1 && session_p->ses_RO) { 1510 free_object_attributes(obj_kp.kp_public_attributes, 1511 ulPublicKeyAttributeCount); 1512 rv = CKR_SESSION_READ_ONLY; 1513 goto failed_exit; 1514 } 1515 1516 /* Process the private key attributes. */ 1517 rv = process_object_attributes(pPrivateKeyTemplate, 1518 ulPrivateKeyAttributeCount, &obj_kp.kp_private_attributes, 1519 &is_token_obj2); 1520 if (rv != CKR_OK) { 1521 free_object_attributes(obj_kp.kp_public_attributes, 1522 ulPublicKeyAttributeCount); 1523 goto failed_exit; 1524 } 1525 1526 /* 1527 * The public key and the private key need to contain the same 1528 * attribute values for CKA_TOKEN. 1529 */ 1530 if (is_token_obj1 != is_token_obj2) { 1531 free_object_attributes(obj_kp.kp_public_attributes, 1532 ulPublicKeyAttributeCount); 1533 free_object_attributes(obj_kp.kp_private_attributes, 1534 ulPrivateKeyAttributeCount); 1535 rv = CKR_ATTRIBUTE_VALUE_INVALID; 1536 goto failed_exit; 1537 } 1538 1539 /* Call the CRYPTO_GENERATE_KEY_PAIR ioctl. */ 1540 obj_kp.kp_session = session_p-> k_session; 1541 obj_kp.kp_mechanism.cm_type = k_mech_type; 1542 obj_kp.kp_mechanism.cm_param = pMechanism->pParameter; 1543 obj_kp.kp_mechanism.cm_param_len = pMechanism->ulParameterLen; 1544 obj_kp.kp_public_count = ulPublicKeyAttributeCount; 1545 obj_kp.kp_private_count = ulPrivateKeyAttributeCount; 1546 1547 while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY_PAIR, 1548 &obj_kp)) < 0) { 1549 if (errno != EINTR) 1550 break; 1551 } 1552 if (r < 0) { 1553 rv = CKR_FUNCTION_FAILED; 1554 } else { 1555 rv = crypto2pkcs11_error_number(obj_kp.kp_return_value); 1556 } 1557 free_object_attributes(obj_kp.kp_public_attributes, 1558 ulPublicKeyAttributeCount); 1559 free_object_attributes(obj_kp.kp_private_attributes, 1560 ulPrivateKeyAttributeCount); 1561 1562 if (rv != CKR_OK) 1563 goto failed_exit; 1564 1565 /* Get the CKA_PRIVATE value for the key pair. */ 1566 rv = get_cka_private_value(session_p, obj_kp.kp_public_handle, 1567 &is_pri_obj1); 1568 if (rv != CKR_OK) { 1569 goto failed_exit; 1570 } 1571 1572 rv = get_cka_private_value(session_p, obj_kp.kp_private_handle, 1573 &is_pri_obj2); 1574 if (rv != CKR_OK) { 1575 goto failed_exit; 1576 } 1577 1578 /* 1579 * Store the kernel public key handle into the public key 1580 * object and finish the public key object initialization. 1581 */ 1582 new_pub_objp->is_lib_obj = B_FALSE; 1583 new_pub_objp->k_handle = obj_kp.kp_public_handle; 1584 new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1585 new_pub_objp->extra_attrlistp = NULL; 1586 1587 if (is_pri_obj1) 1588 new_pub_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 1589 else 1590 new_pub_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 1591 1592 if (is_token_obj1) 1593 new_pub_objp->bool_attr_mask |= TOKEN_BOOL_ON; 1594 else 1595 new_pub_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 1596 1597 (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL); 1598 new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 1599 1600 /* 1601 * Store the kernel private key handle into the private key 1602 * object and finish the private key object initialization. 1603 */ 1604 new_pri_objp->is_lib_obj = B_FALSE; 1605 new_pri_objp->k_handle = obj_kp.kp_private_handle; 1606 new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1607 new_pri_objp->extra_attrlistp = NULL; 1608 1609 if (is_pri_obj2) 1610 new_pri_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 1611 else 1612 new_pri_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 1613 1614 if (is_token_obj2) 1615 new_pri_objp->bool_attr_mask |= TOKEN_BOOL_ON; 1616 else 1617 new_pri_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 1618 1619 } 1620 (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL); 1621 new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 1622 1623 /* 1624 * Add the new pub/pri objects to the slot's token list if they are 1625 * token objects. Otherwise, add them to the session's object list. 1626 */ 1627 if (is_token_obj1) { /* is_token_obj1 == is_token_obj2 */ 1628 pslot = slot_table[session_p->ses_slotid]; 1629 kernel_add_token_object_to_slot(new_pub_objp, pslot); 1630 kernel_add_token_object_to_slot(new_pri_objp, pslot); 1631 } else { 1632 kernel_add_object_to_session(new_pub_objp, session_p); 1633 kernel_add_object_to_session(new_pri_objp, session_p); 1634 } 1635 1636 *phPublicKey = (CK_OBJECT_HANDLE)new_pub_objp; 1637 *phPrivateKey = (CK_OBJECT_HANDLE)new_pri_objp; 1638 REFRELE(session_p, ses_lock_held); 1639 return (rv); 1640 1641 failed_exit: 1642 if (new_pub_objp != NULL) { 1643 (void) free(new_pub_objp); 1644 } 1645 if (new_pri_objp != NULL) { 1646 (void) free(new_pri_objp); 1647 } 1648 REFRELE(session_p, ses_lock_held); 1649 return (rv); 1650 } 1651 1652 1653 CK_RV 1654 C_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 1655 CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, 1656 CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen) 1657 { 1658 CK_RV rv = CKR_OK; 1659 kernel_session_t *session_p; 1660 boolean_t ses_lock_held = B_FALSE; 1661 kernel_object_t *wrappingkey_p; 1662 kernel_object_t *key_p; 1663 crypto_mech_type_t k_mech_type; 1664 crypto_object_wrap_key_t obj_wrapkey; 1665 int r; 1666 1667 if (!kernel_initialized) 1668 return (CKR_CRYPTOKI_NOT_INITIALIZED); 1669 1670 if (pulWrappedKeyLen == NULL || pMechanism == NULL) { 1671 return (CKR_ARGUMENTS_BAD); 1672 } 1673 1674 /* 1675 * Obtain the session pointer. Also, increment the session 1676 * reference count. 1677 */ 1678 rv = handle2session(hSession, &session_p); 1679 if (rv != CKR_OK) 1680 return (rv); 1681 1682 /* Get the kernel's internal mechanism number. */ 1683 rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 1684 if (rv != CKR_OK) { 1685 REFRELE(session_p, ses_lock_held); 1686 return (rv); 1687 } 1688 1689 /* Obtain the wrapping key object pointer. */ 1690 HANDLE2OBJECT(hWrappingKey, wrappingkey_p, rv); 1691 if (rv != CKR_OK) { 1692 REFRELE(session_p, ses_lock_held); 1693 return (rv); 1694 } 1695 1696 /* Obtain the to_be_wrapped key object pointer. */ 1697 HANDLE2OBJECT(hKey, key_p, rv); 1698 if (rv != CKR_OK) { 1699 OBJ_REFRELE(wrappingkey_p); 1700 REFRELE(session_p, ses_lock_held); 1701 return (rv); 1702 } 1703 1704 /* Make the CRYPTO_OBJECT_WRAP_KEY ioctl call. */ 1705 obj_wrapkey.wk_session = session_p->k_session; 1706 obj_wrapkey.wk_mechanism.cm_type = k_mech_type; 1707 obj_wrapkey.wk_mechanism.cm_param = pMechanism->pParameter; 1708 obj_wrapkey.wk_mechanism.cm_param_len = pMechanism->ulParameterLen; 1709 obj_wrapkey.wk_wrapping_key.ck_format = CRYPTO_KEY_REFERENCE; 1710 obj_wrapkey.wk_wrapping_key.ck_obj_id = wrappingkey_p->k_handle; 1711 obj_wrapkey.wk_object_handle = key_p->k_handle; 1712 obj_wrapkey.wk_wrapped_key_len = *pulWrappedKeyLen; 1713 obj_wrapkey.wk_wrapped_key = (char *)pWrappedKey; 1714 1715 while ((r = ioctl(kernel_fd, CRYPTO_WRAP_KEY, &obj_wrapkey)) < 0) { 1716 if (errno != EINTR) 1717 break; 1718 } 1719 if (r < 0) { 1720 rv = CKR_FUNCTION_FAILED; 1721 } else { 1722 rv = crypto2pkcs11_error_number(obj_wrapkey.wk_return_value); 1723 } 1724 1725 /* 1726 * Besides rv == CKR_OK, we will set the value of pulWrappedKeyLen 1727 * when the applciation-supplied wrapped key buffer is too small. 1728 * The situation that the application only asks for the length of 1729 * the wrapped key is covered in rv == CKR_OK. 1730 */ 1731 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) { 1732 *pulWrappedKeyLen = obj_wrapkey.wk_wrapped_key_len; 1733 } 1734 1735 OBJ_REFRELE(key_p); 1736 OBJ_REFRELE(wrappingkey_p); 1737 REFRELE(session_p, ses_lock_held); 1738 return (rv); 1739 } 1740 1741 1742 CK_RV 1743 C_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 1744 CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, 1745 CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, 1746 CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) 1747 { 1748 CK_RV rv = CKR_OK; 1749 kernel_session_t *session_p; 1750 kernel_object_t *unwrappingkey_p; 1751 kernel_object_t *new_objp = NULL; 1752 kernel_slot_t *pslot; 1753 boolean_t ses_lock_held = B_FALSE; 1754 CK_BBOOL is_pri_obj; 1755 CK_BBOOL is_token_obj = FALSE; 1756 CK_MECHANISM_INFO info; 1757 uint32_t k_mi_flags; 1758 CK_BYTE *clear_key_val = NULL; 1759 CK_ULONG ulDataLen; 1760 CK_ATTRIBUTE_PTR newTemplate = NULL; 1761 crypto_mech_type_t k_mech_type; 1762 crypto_object_unwrap_key_t obj_unwrapkey; 1763 int r; 1764 1765 if (!kernel_initialized) 1766 return (CKR_CRYPTOKI_NOT_INITIALIZED); 1767 1768 if (pMechanism == NULL || pWrappedKey == NULL || phKey == NULL) { 1769 return (CKR_ARGUMENTS_BAD); 1770 } 1771 1772 if ((pTemplate == NULL) && (ulAttributeCount != 0)) { 1773 return (CKR_ARGUMENTS_BAD); 1774 } 1775 1776 /* Obtain the session pointer. */ 1777 rv = handle2session(hSession, &session_p); 1778 if (rv != CKR_OK) 1779 return (rv); 1780 1781 /* Obtain the wrapping key object pointer. */ 1782 HANDLE2OBJECT(hUnwrappingKey, unwrappingkey_p, rv); 1783 if (rv != CKR_OK) { 1784 REFRELE(session_p, ses_lock_held); 1785 return (rv); 1786 } 1787 1788 /* 1789 * If the HW provider doesn't support C_UnwrapKey, we will try 1790 * to emulate it in the library. 1791 */ 1792 pslot = slot_table[session_p->ses_slotid]; 1793 if ((!pslot->sl_func_list.fl_object_create) && 1794 (!pslot->sl_func_list.fl_key_unwrap)) { 1795 rv = get_mechanism_info(pslot, pMechanism->mechanism, &info, 1796 &k_mi_flags); 1797 if (rv != CKR_OK) { 1798 goto failed_exit; 1799 } 1800 1801 /* 1802 * If the mechanism flag doesn't have CKF_UNWRAP, and it's 1803 * an unwrapping of a secret key object, then help this 1804 * out with a decryption followed by an object creation. 1805 */ 1806 if (!(k_mi_flags & CRYPTO_FG_UNWRAP) && 1807 (k_mi_flags & CRYPTO_FG_DECRYPT) && 1808 (is_secret_key_template(pTemplate, ulAttributeCount))) { 1809 1810 /* First allocate space for the recovered key value */ 1811 clear_key_val = malloc(ulWrappedKeyLen); 1812 if (clear_key_val == NULL) { 1813 rv = CKR_HOST_MEMORY; 1814 goto failed_exit; 1815 } 1816 1817 rv = kernel_decrypt_init(session_p, unwrappingkey_p, 1818 pMechanism); 1819 if (rv != CKR_OK) { 1820 goto failed_exit; 1821 } 1822 1823 ulDataLen = ulWrappedKeyLen; 1824 rv = kernel_decrypt(session_p, pWrappedKey, 1825 ulWrappedKeyLen, clear_key_val, &ulDataLen); 1826 if (rv != CKR_OK) { 1827 goto failed_exit; 1828 } 1829 1830 newTemplate = grow_template(pTemplate, ulAttributeCount, 1831 ulAttributeCount + 1); 1832 if (newTemplate == NULL) { 1833 rv = CKR_HOST_MEMORY; 1834 goto failed_exit; 1835 } 1836 /* Now add the CKA_VALUE attribute to template */ 1837 newTemplate[ulAttributeCount].type = CKA_VALUE; 1838 newTemplate[ulAttributeCount].pValue = clear_key_val; 1839 newTemplate[ulAttributeCount].ulValueLen = ulDataLen; 1840 1841 /* Finally create the key, based on the new template */ 1842 rv = kernel_add_object(newTemplate, 1843 ulAttributeCount + 1, phKey, session_p); 1844 (void) free(clear_key_val); 1845 (void) free(newTemplate); 1846 OBJ_REFRELE(unwrappingkey_p); 1847 REFRELE(session_p, ses_lock_held); 1848 return (rv); 1849 } else { 1850 rv = CKR_FUNCTION_FAILED; 1851 goto failed_exit; 1852 } 1853 } 1854 1855 /* 1856 * If we come here, the HW provider must have registered the unwrapkey 1857 * entry. Therefore, the unwrap key will be performed in the HW 1858 * provider. 1859 */ 1860 rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 1861 if (rv != CKR_OK) { 1862 goto failed_exit; 1863 } 1864 1865 /* Create an object wrapper for the new key in the library first */ 1866 new_objp = calloc(1, sizeof (kernel_object_t)); 1867 if (new_objp == NULL) { 1868 rv = CKR_HOST_MEMORY; 1869 goto failed_exit; 1870 } 1871 1872 /* Process the attributes */ 1873 rv = process_object_attributes(pTemplate, ulAttributeCount, 1874 &obj_unwrapkey.uk_attributes, &is_token_obj); 1875 if (rv != CKR_OK) { 1876 goto failed_exit; 1877 } 1878 1879 /* Cannot create a token object with a READ-ONLY session. */ 1880 if (is_token_obj && session_p->ses_RO) { 1881 free_object_attributes(obj_unwrapkey.uk_attributes, 1882 ulAttributeCount); 1883 rv = CKR_SESSION_READ_ONLY; 1884 goto failed_exit; 1885 } 1886 1887 /* Make the CRYPTO_UNWRAP_KEY ioctl call. */ 1888 obj_unwrapkey.uk_session = session_p->k_session; 1889 obj_unwrapkey.uk_mechanism.cm_type = k_mech_type; 1890 obj_unwrapkey.uk_mechanism.cm_param = pMechanism->pParameter; 1891 obj_unwrapkey.uk_mechanism.cm_param_len = pMechanism->ulParameterLen; 1892 obj_unwrapkey.uk_unwrapping_key.ck_format = CRYPTO_KEY_REFERENCE; 1893 obj_unwrapkey.uk_unwrapping_key.ck_obj_id = unwrappingkey_p->k_handle; 1894 obj_unwrapkey.uk_wrapped_key = (char *)pWrappedKey; 1895 obj_unwrapkey.uk_wrapped_key_len = ulWrappedKeyLen; 1896 obj_unwrapkey.uk_count = ulAttributeCount; 1897 1898 while ((r = ioctl(kernel_fd, CRYPTO_UNWRAP_KEY, &obj_unwrapkey)) < 0) { 1899 if (errno != EINTR) 1900 break; 1901 } 1902 if (r < 0) { 1903 rv = CKR_FUNCTION_FAILED; 1904 } else { 1905 rv = crypto2pkcs11_error_number(obj_unwrapkey.uk_return_value); 1906 } 1907 1908 free_object_attributes(obj_unwrapkey.uk_attributes, ulAttributeCount); 1909 if (rv != CKR_OK) { 1910 goto failed_exit; 1911 } 1912 1913 /* Get the CKA_PRIVATE value for the unwrapped key. */ 1914 rv = get_cka_private_value(session_p, obj_unwrapkey.uk_object_handle, 1915 &is_pri_obj); 1916 if (rv != CKR_OK) { 1917 goto failed_exit; 1918 } 1919 1920 /* 1921 * Store the kernel object handle in the new key object wrapper and 1922 * initialize it. 1923 */ 1924 new_objp->k_handle = obj_unwrapkey.uk_object_handle; 1925 new_objp->is_lib_obj = B_FALSE; 1926 new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1927 new_objp->extra_attrlistp = NULL; 1928 1929 if (is_pri_obj) 1930 new_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 1931 else 1932 new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 1933 1934 if (is_token_obj) 1935 new_objp->bool_attr_mask |= TOKEN_BOOL_ON; 1936 else 1937 new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 1938 1939 (void) pthread_mutex_init(&new_objp->object_mutex, NULL); 1940 new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 1941 1942 /* 1943 * Add the new object to the slot's token object list if it is a 1944 * a token object. Otherwise, add it to the session's object list. 1945 */ 1946 if (is_token_obj) { 1947 pslot = slot_table[session_p->ses_slotid]; 1948 kernel_add_token_object_to_slot(new_objp, pslot); 1949 } else { 1950 kernel_add_object_to_session(new_objp, session_p); 1951 } 1952 1953 *phKey = (CK_OBJECT_HANDLE)new_objp; 1954 OBJ_REFRELE(unwrappingkey_p); 1955 REFRELE(session_p, ses_lock_held); 1956 return (rv); 1957 1958 failed_exit: 1959 OBJ_REFRELE(unwrappingkey_p); 1960 if (new_objp != NULL) 1961 (void) free(new_objp); 1962 1963 if (clear_key_val != NULL) 1964 (void) free(clear_key_val); 1965 1966 if (newTemplate != NULL) 1967 (void) free(newTemplate); 1968 1969 REFRELE(session_p, ses_lock_held); 1970 return (rv); 1971 } 1972 1973 /* 1974 * Get sufficient attributes from a base key to pass by value in a 1975 * crypto_key structure. Storage for attributes is allocated. 1976 * For EC public keys, it is CKA_EC_PARAMS and CKA_EC_POINT. 1977 * For EC private keys, it is CKA_EC_PARAMS and CKA_VALUE. 1978 */ 1979 static int 1980 get_base_key_attributes(kernel_object_t *base_key, crypto_key_t *key_by_value) 1981 { 1982 CK_ATTRIBUTE tmp; 1983 crypto_object_attribute_t *attrs; 1984 biginteger_t *big; 1985 int rv; 1986 1987 switch (base_key->key_type) { 1988 case CKK_EC: 1989 attrs = malloc(2 * sizeof (crypto_object_attribute_t)); 1990 if (attrs == NULL) { 1991 rv = CKR_HOST_MEMORY; 1992 goto out; 1993 } 1994 bzero(attrs, 2 * sizeof (crypto_object_attribute_t)); 1995 1996 (void) pthread_mutex_lock(&base_key->object_mutex); 1997 1998 if (!base_key->is_lib_obj) { 1999 rv = CRYPTO_ARGUMENTS_BAD; 2000 goto out; 2001 } 2002 2003 if (base_key->class != CKO_PUBLIC_KEY && 2004 base_key->class != CKO_PRIVATE_KEY) { 2005 rv = CRYPTO_ARGUMENTS_BAD; 2006 goto out; 2007 } 2008 2009 /* 2010 * Both public and private EC keys should have 2011 * a CKA_EC_PARAMS attribute. 2012 */ 2013 tmp.type = CKA_EC_PARAMS; 2014 tmp.pValue = NULL; 2015 2016 /* get size of attribute */ 2017 rv = kernel_get_attribute(base_key, &tmp); 2018 if (rv != CKR_OK) { 2019 goto out; 2020 } 2021 2022 tmp.pValue = malloc(tmp.ulValueLen); 2023 if (tmp.pValue == NULL) { 2024 rv = CKR_HOST_MEMORY; 2025 goto out; 2026 } 2027 rv = kernel_get_attribute(base_key, &tmp); 2028 if (rv != CKR_OK) { 2029 goto out; 2030 } 2031 attrs[0].oa_type = tmp.type; 2032 attrs[0].oa_value = tmp.pValue; 2033 attrs[0].oa_value_len = tmp.ulValueLen; 2034 2035 switch (base_key->class) { 2036 case CKO_PUBLIC_KEY: 2037 big = OBJ_PUB_EC_POINT(base_key); 2038 tmp.type = CKA_EC_POINT; 2039 break; 2040 2041 case CKO_PRIVATE_KEY: 2042 big = OBJ_PRI_EC_VALUE(base_key); 2043 tmp.type = CKA_VALUE; 2044 break; 2045 2046 default: 2047 rv = CKR_ATTRIBUTE_TYPE_INVALID; 2048 goto out; 2049 } 2050 tmp.ulValueLen = big->big_value_len; 2051 tmp.pValue = malloc(tmp.ulValueLen); 2052 if (tmp.pValue == NULL) { 2053 rv = CKR_HOST_MEMORY; 2054 goto out; 2055 } 2056 rv = kernel_get_attribute(base_key, &tmp); 2057 if (rv != CKR_OK) { 2058 goto out; 2059 } 2060 attrs[1].oa_type = tmp.type; 2061 attrs[1].oa_value = tmp.pValue; 2062 attrs[1].oa_value_len = tmp.ulValueLen; 2063 key_by_value->ck_attrs = attrs; 2064 key_by_value->ck_count = 2; 2065 break; 2066 2067 case CKK_DH: 2068 attrs = malloc(3 * sizeof (crypto_object_attribute_t)); 2069 if (attrs == NULL) { 2070 rv = CKR_HOST_MEMORY; 2071 goto out; 2072 } 2073 bzero(attrs, 3 * sizeof (crypto_object_attribute_t)); 2074 2075 (void) pthread_mutex_lock(&base_key->object_mutex); 2076 2077 if (!base_key->is_lib_obj) { 2078 rv = CRYPTO_ARGUMENTS_BAD; 2079 goto out; 2080 } 2081 2082 if (base_key->class != CKO_PRIVATE_KEY) { 2083 rv = CRYPTO_ARGUMENTS_BAD; 2084 goto out; 2085 } 2086 tmp.type = CKA_BASE; 2087 tmp.pValue = NULL; 2088 2089 /* get size of attribute */ 2090 rv = kernel_get_attribute(base_key, &tmp); 2091 if (rv != CKR_OK) { 2092 goto out; 2093 } 2094 2095 tmp.pValue = malloc(tmp.ulValueLen); 2096 if (tmp.pValue == NULL) { 2097 rv = CKR_HOST_MEMORY; 2098 goto out; 2099 } 2100 rv = kernel_get_attribute(base_key, &tmp); 2101 if (rv != CKR_OK) { 2102 goto out; 2103 } 2104 attrs[0].oa_type = tmp.type; 2105 attrs[0].oa_value = tmp.pValue; 2106 attrs[0].oa_value_len = tmp.ulValueLen; 2107 2108 tmp.type = CKA_PRIME; 2109 tmp.pValue = NULL; 2110 2111 /* get size of attribute */ 2112 rv = kernel_get_attribute(base_key, &tmp); 2113 if (rv != CKR_OK) { 2114 goto out; 2115 } 2116 2117 tmp.pValue = malloc(tmp.ulValueLen); 2118 if (tmp.pValue == NULL) { 2119 rv = CKR_HOST_MEMORY; 2120 goto out; 2121 } 2122 rv = kernel_get_attribute(base_key, &tmp); 2123 if (rv != CKR_OK) { 2124 goto out; 2125 } 2126 attrs[1].oa_type = tmp.type; 2127 attrs[1].oa_value = tmp.pValue; 2128 attrs[1].oa_value_len = tmp.ulValueLen; 2129 2130 big = OBJ_PRI_EC_VALUE(base_key); 2131 tmp.type = CKA_VALUE; 2132 2133 tmp.ulValueLen = big->big_value_len; 2134 tmp.pValue = malloc(tmp.ulValueLen); 2135 if (tmp.pValue == NULL) { 2136 rv = CKR_HOST_MEMORY; 2137 goto out; 2138 } 2139 rv = kernel_get_attribute(base_key, &tmp); 2140 if (rv != CKR_OK) { 2141 goto out; 2142 } 2143 attrs[2].oa_type = tmp.type; 2144 attrs[2].oa_value = tmp.pValue; 2145 attrs[2].oa_value_len = tmp.ulValueLen; 2146 key_by_value->ck_attrs = attrs; 2147 key_by_value->ck_count = 3; 2148 break; 2149 2150 default: 2151 rv = CKR_ATTRIBUTE_TYPE_INVALID; 2152 goto out; 2153 } 2154 (void) pthread_mutex_unlock(&base_key->object_mutex); 2155 return (CKR_OK); 2156 2157 out: 2158 (void) pthread_mutex_unlock(&base_key->object_mutex); 2159 return (rv); 2160 } 2161 2162 CK_RV 2163 derive_key_by_value(CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, 2164 CK_ULONG ulAttributeCount, kernel_session_t *session_p, 2165 crypto_mech_type_t k_mech_type, kernel_object_t *basekey_p, 2166 kernel_object_t *new_objp) 2167 { 2168 crypto_nostore_derive_key_t obj_ndk; 2169 char *key_buf = NULL; 2170 CK_ATTRIBUTE_PTR newTemplate = NULL; 2171 CK_BBOOL is_token_obj = FALSE; 2172 CK_RV rv = CKR_OK; 2173 CK_ULONG secret_class = CKO_SECRET_KEY; 2174 ulong_t key_len = 0; 2175 uint_t attr_count = 0; 2176 boolean_t removed; 2177 boolean_t has_class; 2178 int r, n; 2179 2180 obj_ndk.ndk_in_count = 0; 2181 obj_ndk.ndk_out_count = 0; 2182 obj_ndk.ndk_base_key.ck_count = 0; 2183 2184 rv = get_key_len_from_template(pMechanism, pTemplate, ulAttributeCount, 2185 basekey_p, &key_len); 2186 if (rv != CKR_OK) { 2187 goto failed_exit; 2188 } 2189 2190 if ((key_buf = malloc(key_len)) == NULL) { 2191 rv = CKR_HOST_MEMORY; 2192 goto failed_exit; 2193 } 2194 2195 has_class = attribute_in_template(CKA_CLASS, pTemplate, 2196 ulAttributeCount); 2197 2198 attr_count = ulAttributeCount + 1; 2199 if (!has_class) 2200 attr_count++; 2201 2202 newTemplate = grow_template(pTemplate, ulAttributeCount, attr_count); 2203 if (newTemplate == NULL) { 2204 rv = CKR_HOST_MEMORY; 2205 goto failed_exit; 2206 } 2207 2208 n = ulAttributeCount; 2209 if (!has_class) { 2210 newTemplate[n].type = CKA_CLASS; 2211 newTemplate[n].pValue = (caddr_t)&secret_class; 2212 newTemplate[n].ulValueLen = sizeof (secret_class); 2213 n++; 2214 } 2215 2216 /* Add CKA_VALUE to the template */ 2217 newTemplate[n].type = CKA_VALUE; 2218 newTemplate[n].pValue = (caddr_t)key_buf; 2219 newTemplate[n].ulValueLen = key_len; 2220 2221 rv = process_object_attributes(newTemplate, attr_count - 1, 2222 &obj_ndk.ndk_in_attributes, &is_token_obj); 2223 if (rv != CKR_OK) { 2224 goto failed_exit; 2225 } 2226 2227 rv = process_object_attributes(&newTemplate[attr_count - 1], 2228 1, &obj_ndk.ndk_out_attributes, &is_token_obj); 2229 if (rv != CKR_OK) { 2230 goto failed_exit; 2231 } 2232 2233 /* Cannot create a token object with a READ-ONLY session. */ 2234 if (is_token_obj && session_p->ses_RO) { 2235 rv = CKR_SESSION_READ_ONLY; 2236 goto failed_exit; 2237 } 2238 2239 obj_ndk.ndk_session = session_p->k_session; 2240 obj_ndk.ndk_mechanism.cm_type = k_mech_type; 2241 obj_ndk.ndk_mechanism.cm_param = pMechanism->pParameter; 2242 obj_ndk.ndk_mechanism.cm_param_len = pMechanism->ulParameterLen; 2243 2244 /* 2245 * Obtain the attributes of base key and pass them by value. 2246 */ 2247 rv = get_base_key_attributes(basekey_p, &obj_ndk.ndk_base_key); 2248 if (rv != CKR_OK) { 2249 goto failed_exit; 2250 } 2251 2252 obj_ndk.ndk_base_key.ck_format = CRYPTO_KEY_ATTR_LIST; 2253 obj_ndk.ndk_in_count = attr_count - 1; 2254 obj_ndk.ndk_out_count = 1; 2255 2256 while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_DERIVE_KEY, 2257 &obj_ndk)) < 0) { 2258 if (errno != EINTR) 2259 break; 2260 } 2261 if (r < 0) { 2262 rv = CKR_FUNCTION_FAILED; 2263 } else { 2264 rv = crypto2pkcs11_error_number(obj_ndk.ndk_return_value); 2265 } 2266 free_attributes(obj_ndk.ndk_in_attributes, &obj_ndk.ndk_in_count); 2267 free_attributes((caddr_t)obj_ndk.ndk_base_key.ck_attrs, 2268 &obj_ndk.ndk_base_key.ck_count); 2269 if (rv != CKR_OK) { 2270 goto failed_exit; 2271 } 2272 2273 rv = get_object_attributes(&newTemplate[attr_count - 1], 2274 1, obj_ndk.ndk_out_attributes); 2275 free_attributes(obj_ndk.ndk_out_attributes, &obj_ndk.ndk_out_count); 2276 if (rv != CRYPTO_SUCCESS) { 2277 goto failed_exit; 2278 } 2279 2280 removed = remove_one_attribute(newTemplate, CKA_VALUE_LEN, 2281 attr_count, B_FALSE); 2282 2283 rv = kernel_build_object(newTemplate, removed ? attr_count - 1 : 2284 attr_count, new_objp, session_p, KERNEL_GEN_KEY); 2285 if (rv != CRYPTO_SUCCESS) { 2286 goto failed_exit; 2287 } 2288 2289 free(key_buf); 2290 free(newTemplate); 2291 new_objp->is_lib_obj = B_TRUE; 2292 new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 2293 return (CKR_OK); 2294 2295 failed_exit: 2296 if (key_buf != NULL) 2297 free(key_buf); 2298 if (newTemplate != NULL) 2299 free(newTemplate); 2300 free_attributes(obj_ndk.ndk_in_attributes, &obj_ndk.ndk_in_count); 2301 free_attributes(obj_ndk.ndk_out_attributes, &obj_ndk.ndk_out_count); 2302 free_attributes((caddr_t)obj_ndk.ndk_base_key.ck_attrs, 2303 &obj_ndk.ndk_base_key.ck_count); 2304 return (rv); 2305 } 2306 2307 CK_RV 2308 C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 2309 CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, 2310 CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) 2311 { 2312 CK_RV rv = CKR_OK; 2313 kernel_session_t *session_p; 2314 kernel_object_t *basekey_p; 2315 kernel_object_t *new_objp; 2316 kernel_slot_t *pslot; 2317 boolean_t ses_lock_held = B_FALSE; 2318 CK_BBOOL is_pri_obj; 2319 CK_BBOOL is_token_obj = FALSE; 2320 crypto_mech_type_t k_mech_type; 2321 int r; 2322 2323 if (!kernel_initialized) 2324 return (CKR_CRYPTOKI_NOT_INITIALIZED); 2325 2326 /* Obtain the session pointer. */ 2327 rv = handle2session(hSession, &session_p); 2328 if (rv != CKR_OK) 2329 return (rv); 2330 2331 if (pMechanism == NULL) { 2332 REFRELE(session_p, ses_lock_held); 2333 return (CKR_ARGUMENTS_BAD); 2334 } 2335 2336 if ((pTemplate == NULL && ulAttributeCount != 0) || 2337 (pTemplate != NULL && ulAttributeCount == 0)) { 2338 REFRELE(session_p, ses_lock_held); 2339 return (CKR_ARGUMENTS_BAD); 2340 } 2341 2342 /* Obtain the base key object pointer. */ 2343 HANDLE2OBJECT(hBaseKey, basekey_p, rv); 2344 if (rv != CKR_OK) { 2345 REFRELE(session_p, ses_lock_held); 2346 return (rv); 2347 } 2348 2349 /* Get the kernel's internal mechanism number. */ 2350 rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 2351 if (rv != CKR_OK) { 2352 goto failed_exit; 2353 } 2354 2355 /* Create an object wrapper in the library for the generated key. */ 2356 new_objp = calloc(1, sizeof (kernel_object_t)); 2357 if (new_objp == NULL) { 2358 rv = CKR_HOST_MEMORY; 2359 goto failed_exit; 2360 } 2361 2362 /* 2363 * Special Case: if token does not support object creation, 2364 * but does support key derivation by value, then create a session 2365 * object and initialize with values returned by token. 2366 */ 2367 pslot = slot_table[session_p->ses_slotid]; 2368 if (!pslot->sl_func_list.fl_object_create) { 2369 rv = derive_key_by_value(pMechanism, pTemplate, 2370 ulAttributeCount, session_p, k_mech_type, basekey_p, 2371 new_objp); 2372 if (rv != CKR_OK) 2373 goto failed_exit; 2374 } else { 2375 crypto_derive_key_t obj_dk; 2376 2377 rv = process_object_attributes(pTemplate, ulAttributeCount, 2378 &obj_dk.dk_attributes, &is_token_obj); 2379 if (rv != CKR_OK) { 2380 goto failed_exit; 2381 } 2382 2383 /* Cannot create a token object with a READ-ONLY session. */ 2384 if (is_token_obj && session_p->ses_RO) { 2385 free_object_attributes(obj_dk.dk_attributes, 2386 ulAttributeCount); 2387 rv = CKR_SESSION_READ_ONLY; 2388 goto failed_exit; 2389 } 2390 2391 obj_dk.dk_session = session_p->k_session; 2392 obj_dk.dk_mechanism.cm_type = k_mech_type; 2393 obj_dk.dk_mechanism.cm_param = pMechanism->pParameter; 2394 obj_dk.dk_mechanism.cm_param_len = pMechanism->ulParameterLen; 2395 obj_dk.dk_base_key.ck_format = CRYPTO_KEY_REFERENCE; 2396 obj_dk.dk_base_key.ck_obj_id = basekey_p->k_handle; 2397 obj_dk.dk_count = ulAttributeCount; 2398 2399 while ((r = ioctl(kernel_fd, CRYPTO_DERIVE_KEY, &obj_dk)) < 0) { 2400 if (errno != EINTR) 2401 break; 2402 } 2403 if (r < 0) { 2404 rv = CKR_FUNCTION_FAILED; 2405 } else { 2406 rv = crypto2pkcs11_error_number(obj_dk.dk_return_value); 2407 } 2408 2409 free_object_attributes(obj_dk.dk_attributes, ulAttributeCount); 2410 if (rv != CKR_OK) { 2411 goto failed_exit; 2412 } 2413 2414 /* Get the CKA_PRIVATE value for the derived key. */ 2415 rv = get_cka_private_value(session_p, obj_dk.dk_object_handle, 2416 &is_pri_obj); 2417 if (rv != CKR_OK) { 2418 goto failed_exit; 2419 } 2420 2421 /* 2422 * Store the kernel object handle into the new derived key 2423 * object and finish the object initialization. 2424 */ 2425 new_objp->is_lib_obj = B_FALSE; 2426 new_objp->k_handle = obj_dk.dk_object_handle; 2427 new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 2428 new_objp->extra_attrlistp = NULL; 2429 2430 if (is_pri_obj) 2431 new_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 2432 else 2433 new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 2434 2435 if (is_token_obj) 2436 new_objp->bool_attr_mask |= TOKEN_BOOL_ON; 2437 else 2438 new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 2439 } 2440 (void) pthread_mutex_init(&new_objp->object_mutex, NULL); 2441 new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 2442 2443 /* 2444 * Add the new derived object to the slot's token list if it is a 2445 * token object. Otherwise, add it to the session's object list. 2446 */ 2447 if (is_token_obj) { 2448 pslot = slot_table[session_p->ses_slotid]; 2449 kernel_add_token_object_to_slot(new_objp, pslot); 2450 } else { 2451 kernel_add_object_to_session(new_objp, session_p); 2452 } 2453 2454 *phKey = (CK_OBJECT_HANDLE)new_objp; 2455 OBJ_REFRELE(basekey_p); 2456 REFRELE(session_p, ses_lock_held); 2457 return (rv); 2458 2459 failed_exit: 2460 OBJ_REFRELE(basekey_p); 2461 if (new_objp != NULL) { 2462 (void) free(new_objp); 2463 } 2464 2465 REFRELE(session_p, ses_lock_held); 2466 return (rv); 2467 } 2468