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