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