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 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <errno.h> 30 #include <security/cryptoki.h> 31 #include <sys/crypto/ioctl.h> 32 #include "kernelGlobal.h" 33 #include "kernelObject.h" 34 #include "kernelSession.h" 35 #include "kernelEmulate.h" 36 37 CK_RV 38 C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 39 CK_OBJECT_HANDLE hKey) 40 { 41 CK_RV rv; 42 kernel_session_t *session_p; 43 kernel_object_t *key_p; 44 boolean_t ses_lock_held = B_FALSE; 45 crypto_sign_init_t sign_init; 46 crypto_mech_type_t k_mech_type; 47 int r; 48 49 if (!kernel_initialized) 50 return (CKR_CRYPTOKI_NOT_INITIALIZED); 51 52 if (pMechanism == NULL) { 53 return (CKR_ARGUMENTS_BAD); 54 } 55 56 /* Get the kernel's internal mechanism number. */ 57 rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 58 if (rv != CKR_OK) { 59 return (rv); 60 } 61 62 /* Obtain the session pointer. */ 63 rv = handle2session(hSession, &session_p); 64 if (rv != CKR_OK) 65 return (rv); 66 67 /* Obtain the object pointer. */ 68 HANDLE2OBJECT(hKey, key_p, rv); 69 if (rv != CKR_OK) { 70 REFRELE(session_p, ses_lock_held); 71 return (rv); 72 } 73 74 /* Check to see if key object supports signature. */ 75 if (key_p->is_lib_obj && !(key_p->bool_attr_mask & SIGN_BOOL_ON)) { 76 rv = CKR_KEY_TYPE_INCONSISTENT; 77 goto clean_exit; 78 } 79 80 (void) pthread_mutex_lock(&session_p->session_mutex); 81 ses_lock_held = B_TRUE; 82 83 /* 84 * This active flag will remain ON until application calls either 85 * C_Sign or C_SignFinal to actually obtain the signature. 86 */ 87 session_p->sign.flags = CRYPTO_OPERATION_ACTIVE; 88 sign_init.si_session = session_p->k_session; 89 (void) pthread_mutex_unlock(&session_p->session_mutex); 90 ses_lock_held = B_FALSE; 91 92 if (!key_p->is_lib_obj) { 93 sign_init.si_key.ck_format = CRYPTO_KEY_REFERENCE; 94 sign_init.si_key.ck_obj_id = key_p->k_handle; 95 } else { 96 if (key_p->class == CKO_SECRET_KEY) { 97 sign_init.si_key.ck_format = CRYPTO_KEY_RAW; 98 sign_init.si_key.ck_data = 99 get_symmetric_key_value(key_p); 100 if (sign_init.si_key.ck_data == NULL) { 101 rv = CKR_HOST_MEMORY; 102 goto clean_exit; 103 } 104 sign_init.si_key.ck_length = 105 OBJ_SEC(key_p)->sk_value_len << 3; 106 107 } else if (key_p->key_type == CKK_RSA) { 108 rv = get_rsa_private_key(key_p, &sign_init.si_key); 109 if (rv != CKR_OK) { 110 goto clean_exit; 111 } 112 } else if (key_p->key_type == CKK_DSA) { 113 rv = get_dsa_private_key(key_p, &sign_init.si_key); 114 if (rv != CKR_OK) { 115 goto clean_exit; 116 } 117 } else { 118 rv = CKR_KEY_TYPE_INCONSISTENT; 119 goto clean_exit; 120 } 121 } 122 123 sign_init.si_mech.cm_type = k_mech_type; 124 sign_init.si_mech.cm_param = pMechanism->pParameter; 125 sign_init.si_mech.cm_param_len = pMechanism->ulParameterLen; 126 127 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_INIT, &sign_init)) < 0) { 128 if (errno != EINTR) 129 break; 130 } 131 if (r < 0) { 132 rv = CKR_FUNCTION_FAILED; 133 } else { 134 rv = crypto2pkcs11_error_number(sign_init.si_return_value); 135 } 136 137 if (rv == CKR_OK && SLOT_HAS_LIMITED_HASH(session_p) && 138 is_hmac(pMechanism->mechanism)) { 139 if (key_p->is_lib_obj && key_p->class == CKO_SECRET_KEY) { 140 (void) pthread_mutex_lock(&session_p->session_mutex); 141 session_p->sign.flags |= CRYPTO_EMULATE; 142 (void) pthread_mutex_unlock(&session_p->session_mutex); 143 rv = emulate_init(session_p, pMechanism, 144 &(sign_init.si_key), OP_SIGN); 145 } else { 146 rv = CKR_ARGUMENTS_BAD; 147 } 148 } 149 150 if (key_p->is_lib_obj) { 151 if (key_p->class == CKO_SECRET_KEY) { 152 free(sign_init.si_key.ck_data); 153 } else { 154 free_key_attributes(&sign_init.si_key); 155 } 156 } 157 158 if (rv != CKR_OK) { 159 (void) pthread_mutex_lock(&session_p->session_mutex); 160 session_p->sign.flags &= ~CRYPTO_OPERATION_ACTIVE; 161 ses_lock_held = B_TRUE; 162 } 163 164 clean_exit: 165 OBJ_REFRELE(key_p); 166 REFRELE(session_p, ses_lock_held); 167 return (rv); 168 } 169 170 171 CK_RV 172 C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, 173 CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) 174 { 175 176 CK_RV rv; 177 kernel_session_t *session_p; 178 boolean_t ses_lock_held = B_FALSE; 179 crypto_sign_t sign; 180 int r; 181 182 if (!kernel_initialized) 183 return (CKR_CRYPTOKI_NOT_INITIALIZED); 184 185 /* Obtain the session pointer */ 186 rv = handle2session(hSession, &session_p); 187 if (rv != CKR_OK) 188 return (rv); 189 190 if (pulSignatureLen == NULL) { 191 rv = CKR_ARGUMENTS_BAD; 192 goto clean_exit; 193 } 194 195 (void) pthread_mutex_lock(&session_p->session_mutex); 196 ses_lock_held = B_TRUE; 197 198 /* Application must call C_SignInit before calling C_Sign. */ 199 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { 200 REFRELE(session_p, ses_lock_held); 201 return (CKR_OPERATION_NOT_INITIALIZED); 202 } 203 204 /* 205 * C_Sign must be called without intervening C_SignUpdate 206 * calls. 207 */ 208 if (session_p->sign.flags & CRYPTO_OPERATION_UPDATE) { 209 /* 210 * C_Sign can not be used to terminate a multi-part 211 * operation, so we'll leave the active sign operation 212 * flag on and let the application continue with the 213 * sign update operation. 214 */ 215 REFRELE(session_p, ses_lock_held); 216 return (CKR_FUNCTION_FAILED); 217 } 218 219 if (session_p->sign.flags & CRYPTO_EMULATE) { 220 if ((ulDataLen < SLOT_THRESHOLD(session_p)) || 221 (ulDataLen > SLOT_MAX_INDATA_LEN(session_p))) { 222 session_p->sign.flags |= CRYPTO_EMULATE_USING_SW; 223 (void) pthread_mutex_unlock(&session_p->session_mutex); 224 225 rv = do_soft_hmac_sign(get_spp(&session_p->sign), 226 pData, ulDataLen, 227 pSignature, pulSignatureLen, OP_SINGLE); 228 goto done; 229 } else { 230 free_soft_ctx(get_sp(&session_p->sign), OP_SIGN); 231 } 232 } 233 234 sign.cs_session = session_p->k_session; 235 (void) pthread_mutex_unlock(&session_p->session_mutex); 236 ses_lock_held = B_FALSE; 237 238 sign.cs_datalen = ulDataLen; 239 sign.cs_databuf = (char *)pData; 240 sign.cs_signlen = *pulSignatureLen; 241 sign.cs_signbuf = (char *)pSignature; 242 243 while ((r = ioctl(kernel_fd, CRYPTO_SIGN, &sign)) < 0) { 244 if (errno != EINTR) 245 break; 246 } 247 if (r < 0) { 248 rv = CKR_FUNCTION_FAILED; 249 } else { 250 rv = crypto2pkcs11_error_number(sign.cs_return_value); 251 } 252 253 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 254 *pulSignatureLen = sign.cs_signlen; 255 256 done: 257 if ((rv == CKR_BUFFER_TOO_SMALL) || 258 (rv == CKR_OK && pSignature == NULL)) { 259 /* 260 * We will not terminate the active sign operation flag, 261 * when the application-supplied buffer is too small, or 262 * the application asks for the length of buffer to hold 263 * the signature. 264 */ 265 REFRELE(session_p, ses_lock_held); 266 return (rv); 267 } 268 269 clean_exit: 270 /* 271 * Terminates the active sign operation. 272 * Application needs to call C_SignInit again for next 273 * sign operation. 274 */ 275 (void) pthread_mutex_lock(&session_p->session_mutex); 276 277 REINIT_OPBUF(&session_p->sign); 278 session_p->sign.flags = 0; 279 ses_lock_held = B_TRUE; 280 REFRELE(session_p, ses_lock_held); 281 282 return (rv); 283 } 284 285 286 CK_RV 287 C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, 288 CK_ULONG ulPartLen) 289 { 290 291 CK_RV rv; 292 kernel_session_t *session_p; 293 boolean_t ses_lock_held = B_FALSE; 294 crypto_sign_update_t sign_update; 295 int r; 296 297 if (!kernel_initialized) 298 return (CKR_CRYPTOKI_NOT_INITIALIZED); 299 300 /* Obtain the session pointer */ 301 rv = handle2session(hSession, &session_p); 302 if (rv != CKR_OK) 303 return (rv); 304 305 if (pPart == NULL) { 306 rv = CKR_ARGUMENTS_BAD; 307 goto clean_exit; 308 } 309 310 (void) pthread_mutex_lock(&session_p->session_mutex); 311 ses_lock_held = B_TRUE; 312 313 /* 314 * Application must call C_SignInit before calling 315 * C_SignUpdate. 316 */ 317 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { 318 REFRELE(session_p, ses_lock_held); 319 return (CKR_OPERATION_NOT_INITIALIZED); 320 } 321 322 session_p->sign.flags |= CRYPTO_OPERATION_UPDATE; 323 324 if (session_p->sign.flags & CRYPTO_EMULATE) { 325 (void) pthread_mutex_unlock(&session_p->session_mutex); 326 rv = emulate_update(session_p, pPart, ulPartLen, OP_SIGN); 327 goto done; 328 } 329 330 sign_update.su_session = session_p->k_session; 331 (void) pthread_mutex_unlock(&session_p->session_mutex); 332 ses_lock_held = B_FALSE; 333 334 sign_update.su_datalen = ulPartLen; 335 sign_update.su_databuf = (char *)pPart; 336 337 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_UPDATE, &sign_update)) < 0) { 338 if (errno != EINTR) 339 break; 340 } 341 if (r < 0) { 342 rv = CKR_FUNCTION_FAILED; 343 } else { 344 rv = crypto2pkcs11_error_number(sign_update.su_return_value); 345 } 346 347 done: 348 if (rv == CKR_OK) { 349 REFRELE(session_p, ses_lock_held); 350 return (rv); 351 } 352 353 clean_exit: 354 /* 355 * After an error occurred, terminate the current sign 356 * operation by resetting the active and update flags. 357 */ 358 (void) pthread_mutex_lock(&session_p->session_mutex); 359 REINIT_OPBUF(&session_p->sign); 360 session_p->sign.flags = 0; 361 ses_lock_held = B_TRUE; 362 REFRELE(session_p, ses_lock_held); 363 364 return (rv); 365 } 366 367 368 CK_RV 369 C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, 370 CK_ULONG_PTR pulSignatureLen) 371 { 372 373 CK_RV rv; 374 kernel_session_t *session_p; 375 boolean_t ses_lock_held = B_FALSE; 376 crypto_sign_final_t sign_final; 377 int r; 378 379 if (!kernel_initialized) 380 return (CKR_CRYPTOKI_NOT_INITIALIZED); 381 382 /* Obtain the session pointer */ 383 rv = handle2session(hSession, &session_p); 384 if (rv != CKR_OK) 385 return (rv); 386 387 if (pulSignatureLen == NULL) { 388 rv = CKR_ARGUMENTS_BAD; 389 goto clean_exit; 390 } 391 392 (void) pthread_mutex_lock(&session_p->session_mutex); 393 ses_lock_held = B_TRUE; 394 395 /* 396 * Application must call C_SignInit before calling 397 * C_SignFinal. 398 */ 399 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { 400 REFRELE(session_p, ses_lock_held); 401 return (CKR_OPERATION_NOT_INITIALIZED); 402 } 403 404 /* The order of checks is important here */ 405 if (session_p->sign.flags & CRYPTO_EMULATE_USING_SW) { 406 if (session_p->sign.flags & CRYPTO_EMULATE_UPDATE_DONE) { 407 (void) pthread_mutex_unlock(&session_p->session_mutex); 408 rv = do_soft_hmac_sign(get_spp(&session_p->sign), 409 NULL, 0, pSignature, pulSignatureLen, OP_FINAL); 410 } else { 411 /* 412 * We end up here if an earlier C_SignFinal() call 413 * took the C_Sign() path and it had returned 414 * CKR_BUFFER_TOO_SMALL. 415 */ 416 digest_buf_t *bufp = session_p->sign.context; 417 (void) pthread_mutex_unlock(&session_p->session_mutex); 418 if (bufp == NULL || bufp->buf == NULL) { 419 rv = CKR_ARGUMENTS_BAD; 420 goto clean_exit; 421 } 422 rv = do_soft_hmac_sign(get_spp(&session_p->sign), 423 bufp->buf, bufp->indata_len, 424 pSignature, pulSignatureLen, OP_SINGLE); 425 } 426 goto done; 427 } else if (session_p->sign.flags & CRYPTO_EMULATE) { 428 digest_buf_t *bufp = session_p->sign.context; 429 430 /* 431 * We are emulating a single-part operation now. 432 * So, clear the flag. 433 */ 434 session_p->sign.flags &= ~CRYPTO_OPERATION_UPDATE; 435 if (bufp == NULL || bufp->buf == NULL) { 436 rv = CKR_ARGUMENTS_BAD; 437 goto clean_exit; 438 } 439 REFRELE(session_p, ses_lock_held); 440 rv = C_Sign(hSession, bufp->buf, bufp->indata_len, 441 pSignature, pulSignatureLen); 442 return (rv); 443 } 444 445 sign_final.sf_session = session_p->k_session; 446 (void) pthread_mutex_unlock(&session_p->session_mutex); 447 ses_lock_held = B_FALSE; 448 449 sign_final.sf_signlen = *pulSignatureLen; 450 sign_final.sf_signbuf = (char *)pSignature; 451 452 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_FINAL, &sign_final)) < 0) { 453 if (errno != EINTR) 454 break; 455 } 456 if (r < 0) { 457 rv = CKR_FUNCTION_FAILED; 458 } else { 459 rv = crypto2pkcs11_error_number(sign_final.sf_return_value); 460 } 461 462 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 463 *pulSignatureLen = sign_final.sf_signlen; 464 465 done: 466 if ((rv == CKR_BUFFER_TOO_SMALL) || 467 (rv == CKR_OK && pSignature == NULL)) { 468 /* 469 * We will not terminate the active sign operation flag, 470 * when the application-supplied buffer is too small, or 471 * the application asks for the length of buffer to hold 472 * the signature. 473 */ 474 REFRELE(session_p, ses_lock_held); 475 return (rv); 476 } 477 478 clean_exit: 479 /* Terminates the active sign operation */ 480 (void) pthread_mutex_lock(&session_p->session_mutex); 481 REINIT_OPBUF(&session_p->sign); 482 session_p->sign.flags = 0; 483 ses_lock_held = B_TRUE; 484 REFRELE(session_p, ses_lock_held); 485 486 return (rv); 487 } 488 489 490 CK_RV 491 C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 492 CK_OBJECT_HANDLE hKey) 493 { 494 495 CK_RV rv; 496 kernel_session_t *session_p; 497 kernel_object_t *key_p; 498 boolean_t ses_lock_held = B_FALSE; 499 crypto_sign_recover_init_t sr_init; 500 crypto_mech_type_t k_mech_type; 501 int r; 502 503 if (!kernel_initialized) 504 return (CKR_CRYPTOKI_NOT_INITIALIZED); 505 506 if (pMechanism == NULL) { 507 return (CKR_ARGUMENTS_BAD); 508 } 509 510 /* Get the kernel's internal mechanism number. */ 511 rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 512 if (rv != CKR_OK) 513 return (rv); 514 515 /* Obtain the session pointer. */ 516 rv = handle2session(hSession, &session_p); 517 if (rv != CKR_OK) 518 return (rv); 519 520 /* Obtain the object pointer. */ 521 HANDLE2OBJECT(hKey, key_p, rv); 522 if (rv != CKR_OK) { 523 REFRELE(session_p, ses_lock_held); 524 return (rv); 525 } 526 527 /* 528 * Check to see if key object is a RSA key and if it supports 529 * sign_recover. 530 */ 531 if (key_p->is_lib_obj && !((key_p->key_type == CKK_RSA) && 532 (key_p->bool_attr_mask & SIGN_RECOVER_BOOL_ON))) { 533 rv = CKR_KEY_TYPE_INCONSISTENT; 534 goto clean_exit; 535 } 536 537 (void) pthread_mutex_lock(&session_p->session_mutex); 538 ses_lock_held = B_TRUE; 539 540 /* 541 * This active flag will remain ON until application calls 542 * C_SignRecover to actually obtain the signature. 543 */ 544 session_p->sign.flags = CRYPTO_OPERATION_ACTIVE; 545 546 /* Set up the key data */ 547 if (!key_p->is_lib_obj) { 548 sr_init.ri_key.ck_format = CRYPTO_KEY_REFERENCE; 549 sr_init.ri_key.ck_obj_id = key_p->k_handle; 550 } else { 551 if (key_p->key_type == CKK_RSA) { 552 if (get_rsa_private_key(key_p, &sr_init.ri_key) != 553 CKR_OK) { 554 rv = CKR_HOST_MEMORY; 555 goto clean_exit; 556 } 557 } else { 558 rv = CKR_KEY_TYPE_INCONSISTENT; 559 goto clean_exit; 560 } 561 } 562 563 sr_init.ri_session = session_p->k_session; 564 (void) pthread_mutex_unlock(&session_p->session_mutex); 565 ses_lock_held = B_FALSE; 566 sr_init.ri_mech.cm_type = k_mech_type; 567 sr_init.ri_mech.cm_param = pMechanism->pParameter; 568 sr_init.ri_mech.cm_param_len = pMechanism->ulParameterLen; 569 570 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_RECOVER_INIT, &sr_init)) < 0) { 571 if (errno != EINTR) 572 break; 573 } 574 if (r < 0) { 575 rv = CKR_FUNCTION_FAILED; 576 } else { 577 rv = crypto2pkcs11_error_number(sr_init.ri_return_value); 578 } 579 580 if (key_p->is_lib_obj) { 581 free_key_attributes(&sr_init.ri_key); 582 } 583 584 if (rv != CKR_OK) { 585 (void) pthread_mutex_lock(&session_p->session_mutex); 586 session_p->sign.flags &= ~CRYPTO_OPERATION_ACTIVE; 587 ses_lock_held = B_TRUE; 588 } 589 590 clean_exit: 591 OBJ_REFRELE(key_p); 592 REFRELE(session_p, ses_lock_held); 593 return (rv); 594 } 595 596 597 CK_RV 598 C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, 599 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) 600 { 601 602 CK_RV rv; 603 kernel_session_t *session_p; 604 boolean_t ses_lock_held = B_FALSE; 605 crypto_sign_recover_t sign_recover; 606 int r; 607 608 if (!kernel_initialized) 609 return (CKR_CRYPTOKI_NOT_INITIALIZED); 610 611 /* Obatin the session pointer */ 612 rv = handle2session(hSession, &session_p); 613 if (rv != CKR_OK) 614 return (rv); 615 616 if (pulSignatureLen == NULL) { 617 rv = CKR_ARGUMENTS_BAD; 618 goto clean_exit; 619 } 620 621 (void) pthread_mutex_lock(&session_p->session_mutex); 622 ses_lock_held = B_TRUE; 623 624 /* Application must call C_SignInit before calling C_Sign. */ 625 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { 626 REFRELE(session_p, ses_lock_held); 627 return (CKR_OPERATION_NOT_INITIALIZED); 628 } 629 630 sign_recover.sr_session = session_p->k_session; 631 (void) pthread_mutex_unlock(&session_p->session_mutex); 632 ses_lock_held = B_FALSE; 633 634 sign_recover.sr_datalen = ulDataLen; 635 sign_recover.sr_databuf = (char *)pData; 636 sign_recover.sr_signlen = *pulSignatureLen; 637 sign_recover.sr_signbuf = (char *)pSignature; 638 639 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_RECOVER, &sign_recover)) < 0) { 640 if (errno != EINTR) 641 break; 642 } 643 if (r < 0) { 644 rv = CKR_FUNCTION_FAILED; 645 } else { 646 rv = crypto2pkcs11_error_number(sign_recover.sr_return_value); 647 } 648 649 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 650 *pulSignatureLen = sign_recover.sr_signlen; 651 652 if ((rv == CKR_BUFFER_TOO_SMALL) || 653 (rv == CKR_OK && pSignature == NULL)) { 654 /* 655 * We will not terminate the active sign operation flag, 656 * when the application-supplied buffer is too small, or 657 * the application asks for the length of buffer to hold 658 * the signature. 659 */ 660 REFRELE(session_p, ses_lock_held); 661 return (rv); 662 } 663 664 clean_exit: 665 /* 666 * Terminates the active sign operation. 667 * Application needs to call C_SignInit again for next 668 * sign operation. 669 */ 670 (void) pthread_mutex_lock(&session_p->session_mutex); 671 session_p->sign.flags = 0; 672 ses_lock_held = B_TRUE; 673 REFRELE(session_p, ses_lock_held); 674 675 return (rv); 676 } 677