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