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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 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 37 CK_RV 38 C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 39 CK_OBJECT_HANDLE hKey) 40 { 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 /* free the memory allocated for sign_init.si_key */ 140 if (key_p->is_lib_obj) { 141 if (key_p->class == CKO_SECRET_KEY) { 142 free(verify_init.vi_key.ck_data); 143 } else if (key_p->key_type == CKK_RSA) { 144 free_key_attributes(&verify_init.vi_key); 145 } 146 } 147 148 if (rv != CKR_OK) { 149 (void) pthread_mutex_lock(&session_p->session_mutex); 150 session_p->verify.flags &= ~CRYPTO_OPERATION_ACTIVE; 151 ses_lock_held = B_TRUE; 152 } 153 154 clean_exit: 155 OBJ_REFRELE(key_p); 156 REFRELE(session_p, ses_lock_held); 157 return (rv); 158 } 159 160 161 CK_RV 162 C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, 163 CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) 164 { 165 166 CK_RV rv; 167 kernel_session_t *session_p; 168 boolean_t ses_lock_held = B_FALSE; 169 crypto_verify_t verify; 170 int r; 171 172 if (!kernel_initialized) 173 return (CKR_CRYPTOKI_NOT_INITIALIZED); 174 175 /* Obatin the session pointer */ 176 rv = handle2session(hSession, &session_p); 177 if (rv != CKR_OK) 178 return (rv); 179 180 (void) pthread_mutex_lock(&session_p->session_mutex); 181 ses_lock_held = B_TRUE; 182 183 /* Application must call C_VerifyInit before calling C_Verify. */ 184 if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) { 185 REFRELE(session_p, ses_lock_held); 186 return (CKR_OPERATION_NOT_INITIALIZED); 187 } 188 189 /* 190 * C_Verify must be called without intervening C_VerifyUpdate 191 * calls. 192 */ 193 if (session_p->verify.flags & CRYPTO_OPERATION_UPDATE) { 194 /* 195 * C_Verify can not be used to terminate a multi-part 196 * operation, so we'll leave the active verify operation 197 * flag on and let the application continue with the 198 * verify update operation. 199 */ 200 REFRELE(session_p, ses_lock_held); 201 return (CKR_FUNCTION_FAILED); 202 } 203 204 verify.cv_session = session_p->k_session; 205 (void) pthread_mutex_unlock(&session_p->session_mutex); 206 ses_lock_held = B_FALSE; 207 verify.cv_datalen = ulDataLen; 208 verify.cv_databuf = (char *)pData; 209 verify.cv_signlen = ulSignatureLen; 210 verify.cv_signbuf = (char *)pSignature; 211 212 while ((r = ioctl(kernel_fd, CRYPTO_VERIFY, &verify)) < 0) { 213 if (errno != EINTR) 214 break; 215 } 216 if (r < 0) { 217 rv = CKR_FUNCTION_FAILED; 218 } else { 219 rv = crypto2pkcs11_error_number(verify.cv_return_value); 220 } 221 222 clean_exit: 223 /* 224 * Always terminate the active verify operation. 225 * Application needs to call C_VerifyInit again for next 226 * verify operation. 227 */ 228 (void) pthread_mutex_lock(&session_p->session_mutex); 229 session_p->verify.flags = 0; 230 ses_lock_held = B_TRUE; 231 REFRELE(session_p, ses_lock_held); 232 233 return (rv); 234 } 235 236 237 CK_RV 238 C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, 239 CK_ULONG ulPartLen) 240 { 241 242 CK_RV rv; 243 kernel_session_t *session_p; 244 boolean_t ses_lock_held = B_FALSE; 245 crypto_verify_update_t verify_update; 246 int r; 247 248 if (!kernel_initialized) 249 return (CKR_CRYPTOKI_NOT_INITIALIZED); 250 251 /* Obtain the session pointer */ 252 rv = handle2session(hSession, &session_p); 253 if (rv != CKR_OK) 254 return (rv); 255 256 if (pPart == NULL) { 257 rv = CKR_ARGUMENTS_BAD; 258 goto clean_exit; 259 } 260 261 (void) pthread_mutex_lock(&session_p->session_mutex); 262 ses_lock_held = B_TRUE; 263 264 /* 265 * Application must call C_VerifyInit before calling 266 * C_VerifyUpdate. 267 */ 268 if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) { 269 REFRELE(session_p, ses_lock_held); 270 return (CKR_OPERATION_NOT_INITIALIZED); 271 } 272 273 session_p->verify.flags |= CRYPTO_OPERATION_UPDATE; 274 275 verify_update.vu_session = session_p->k_session; 276 (void) pthread_mutex_unlock(&session_p->session_mutex); 277 ses_lock_held = B_FALSE; 278 279 verify_update.vu_datalen = ulPartLen; 280 verify_update.vu_databuf = (char *)pPart; 281 282 while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_UPDATE, 283 &verify_update)) < 0) { 284 if (errno != EINTR) 285 break; 286 } 287 if (r < 0) { 288 rv = CKR_FUNCTION_FAILED; 289 } else { 290 rv = crypto2pkcs11_error_number(verify_update.vu_return_value); 291 } 292 293 if (rv == CKR_OK) { 294 REFRELE(session_p, ses_lock_held); 295 return (rv); 296 } 297 298 clean_exit: 299 /* 300 * After an error occurred, terminate the current verify 301 * operation by resetting the active and update flags. 302 */ 303 (void) pthread_mutex_lock(&session_p->session_mutex); 304 session_p->verify.flags = 0; 305 ses_lock_held = B_TRUE; 306 REFRELE(session_p, ses_lock_held); 307 308 return (rv); 309 } 310 311 312 CK_RV 313 C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, 314 CK_ULONG ulSignatureLen) 315 { 316 317 CK_RV rv; 318 kernel_session_t *session_p; 319 boolean_t ses_lock_held = B_FALSE; 320 crypto_verify_final_t verify_final; 321 int r; 322 323 if (!kernel_initialized) 324 return (CKR_CRYPTOKI_NOT_INITIALIZED); 325 326 /* Obtain the session pointer */ 327 rv = handle2session(hSession, &session_p); 328 if (rv != CKR_OK) 329 return (rv); 330 331 (void) pthread_mutex_lock(&session_p->session_mutex); 332 ses_lock_held = B_TRUE; 333 334 /* 335 * Application must call C_VerifyInit before calling 336 * C_VerifyFinal. 337 */ 338 if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) { 339 REFRELE(session_p, ses_lock_held); 340 return (CKR_OPERATION_NOT_INITIALIZED); 341 } 342 343 verify_final.vf_session = session_p->k_session; 344 (void) pthread_mutex_unlock(&session_p->session_mutex); 345 ses_lock_held = B_FALSE; 346 347 verify_final.vf_signlen = ulSignatureLen; 348 verify_final.vf_signbuf = (char *)pSignature; 349 350 while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_FINAL, &verify_final)) < 0) { 351 if (errno != EINTR) 352 break; 353 } 354 if (r < 0) { 355 rv = CKR_FUNCTION_FAILED; 356 } else { 357 rv = crypto2pkcs11_error_number(verify_final.vf_return_value); 358 } 359 360 clean_exit: 361 /* Always terminate the active verify operation */ 362 (void) pthread_mutex_lock(&session_p->session_mutex); 363 session_p->verify.flags = 0; 364 ses_lock_held = B_TRUE; 365 REFRELE(session_p, ses_lock_held); 366 367 return (rv); 368 } 369 370 371 CK_RV 372 C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 373 CK_OBJECT_HANDLE hKey) 374 { 375 376 CK_RV rv; 377 kernel_session_t *session_p; 378 kernel_object_t *key_p; 379 boolean_t ses_lock_held = B_FALSE; 380 crypto_verify_recover_init_t vr_init; 381 crypto_mech_type_t k_mech_type; 382 int r; 383 384 if (!kernel_initialized) 385 return (CKR_CRYPTOKI_NOT_INITIALIZED); 386 387 if (pMechanism == NULL) { 388 return (CKR_ARGUMENTS_BAD); 389 } 390 391 /* Get the kernel's internal mechanism number. */ 392 rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 393 if (rv != CKR_OK) 394 return (rv); 395 396 /* Obtain the session pointer. */ 397 rv = handle2session(hSession, &session_p); 398 if (rv != CKR_OK) 399 return (rv); 400 401 /* Obtain the object pointer. */ 402 HANDLE2OBJECT(hKey, key_p, rv); 403 if (rv != CKR_OK) { 404 REFRELE(session_p, ses_lock_held); 405 return (rv); 406 } 407 408 /* 409 * Check to see if key object is a RSA key and if it supports 410 * verify_recover. 411 */ 412 if (key_p->is_lib_obj && !((key_p->key_type == CKK_RSA) && 413 (key_p->bool_attr_mask & VERIFY_RECOVER_BOOL_ON))) { 414 rv = CKR_KEY_TYPE_INCONSISTENT; 415 goto clean_exit; 416 } 417 418 (void) pthread_mutex_lock(&session_p->session_mutex); 419 ses_lock_held = B_TRUE; 420 421 /* 422 * This active flag will remain ON until application calls 423 * C_VerifyRecover to verify a signature on data. 424 */ 425 session_p->verify.flags = CRYPTO_OPERATION_ACTIVE; 426 427 /* Set up the key data */ 428 if (!key_p->is_lib_obj) { 429 vr_init.ri_key.ck_format = CRYPTO_KEY_REFERENCE; 430 vr_init.ri_key.ck_obj_id = key_p->k_handle; 431 } else { 432 if (key_p->key_type == CKK_RSA) { 433 if (get_rsa_public_key(key_p, &vr_init.ri_key) != 434 CKR_OK) { 435 rv = CKR_HOST_MEMORY; 436 goto clean_exit; 437 } 438 } else { 439 rv = CKR_KEY_TYPE_INCONSISTENT; 440 goto clean_exit; 441 } 442 } 443 444 vr_init.ri_session = session_p->k_session; 445 (void) pthread_mutex_unlock(&session_p->session_mutex); 446 ses_lock_held = B_FALSE; 447 vr_init.ri_mech.cm_type = k_mech_type; 448 vr_init.ri_mech.cm_param = pMechanism->pParameter; 449 vr_init.ri_mech.cm_param_len = pMechanism->ulParameterLen; 450 451 while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_RECOVER_INIT, 452 &vr_init)) < 0) { 453 if (errno != EINTR) 454 break; 455 } 456 if (r < 0) { 457 rv = CKR_FUNCTION_FAILED; 458 } else { 459 rv = crypto2pkcs11_error_number(vr_init.ri_return_value); 460 } 461 462 /* free the memory allocated for vr_init.ri_key */ 463 if (key_p->is_lib_obj) { 464 free_key_attributes(&vr_init.ri_key); 465 } 466 467 if (rv != CKR_OK) { 468 (void) pthread_mutex_lock(&session_p->session_mutex); 469 session_p->verify.flags &= ~CRYPTO_OPERATION_ACTIVE; 470 ses_lock_held = B_TRUE; 471 } 472 473 clean_exit: 474 OBJ_REFRELE(key_p); 475 REFRELE(session_p, ses_lock_held); 476 return (rv); 477 } 478 479 480 CK_RV 481 C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, 482 CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) 483 { 484 485 CK_RV rv; 486 kernel_session_t *session_p; 487 boolean_t ses_lock_held = B_FALSE; 488 crypto_verify_recover_t verify_recover; 489 int r; 490 491 if (!kernel_initialized) 492 return (CKR_CRYPTOKI_NOT_INITIALIZED); 493 494 /* Obtain the session pointer */ 495 rv = handle2session(hSession, &session_p); 496 if (rv != CKR_OK) 497 return (rv); 498 499 if (pSignature == NULL || pulDataLen == NULL) { 500 rv = CKR_ARGUMENTS_BAD; 501 goto clean_exit; 502 } 503 504 (void) pthread_mutex_lock(&session_p->session_mutex); 505 ses_lock_held = B_TRUE; 506 507 /* 508 * Application must call C_VerifyRecoverInit before calling 509 * C_Verify. 510 */ 511 if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) { 512 REFRELE(session_p, ses_lock_held); 513 return (CKR_OPERATION_NOT_INITIALIZED); 514 } 515 516 verify_recover.vr_session = session_p->k_session; 517 (void) pthread_mutex_unlock(&session_p->session_mutex); 518 ses_lock_held = B_FALSE; 519 verify_recover.vr_signlen = ulSignatureLen; 520 verify_recover.vr_signbuf = (char *)pSignature; 521 verify_recover.vr_datalen = *pulDataLen; 522 verify_recover.vr_databuf = (char *)pData; 523 524 while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_RECOVER, 525 &verify_recover)) < 0) { 526 if (errno != EINTR) 527 break; 528 } 529 if (r < 0) { 530 rv = CKR_FUNCTION_FAILED; 531 } else { 532 rv = crypto2pkcs11_error_number( 533 verify_recover.vr_return_value); 534 } 535 536 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 537 *pulDataLen = verify_recover.vr_datalen; 538 539 if ((rv == CKR_BUFFER_TOO_SMALL) || 540 (rv == CKR_OK && pData == NULL)) { 541 /* 542 * We will not terminate the active verify operation flag, 543 * when the application-supplied buffer is too small, or 544 * the application asks for the length of buffer to hold 545 * the recovered data. 546 */ 547 REFRELE(session_p, ses_lock_held); 548 return (rv); 549 } 550 551 clean_exit: 552 /* 553 * Always terminate the active verify operation. 554 * Application needs to call C_VerifyInit again for next 555 * verify operation. 556 */ 557 (void) pthread_mutex_lock(&session_p->session_mutex); 558 session_p->verify.flags = 0; 559 ses_lock_held = B_TRUE; 560 REFRELE(session_p, ses_lock_held); 561 562 return (rv); 563 } 564