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