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