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