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