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