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