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 <errno.h> 29 #include <security/cryptoki.h> 30 #include <sys/crypto/ioctl.h> 31 #include "kernelGlobal.h" 32 #include "kernelObject.h" 33 #include "kernelSession.h" 34 35 CK_RV 36 C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 37 CK_OBJECT_HANDLE hKey) 38 { 39 40 CK_RV rv; 41 kernel_session_t *session_p; 42 kernel_object_t *key_p; 43 boolean_t ses_lock_held = B_FALSE; 44 crypto_sign_init_t sign_init; 45 crypto_mech_type_t k_mech_type; 46 int r; 47 48 if (!kernel_initialized) 49 return (CKR_CRYPTOKI_NOT_INITIALIZED); 50 51 if (pMechanism == NULL) { 52 return (CKR_ARGUMENTS_BAD); 53 } 54 55 /* Get the kernel's internal mechanism number. */ 56 rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 57 if (rv != CKR_OK) { 58 return (rv); 59 } 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 signature. */ 74 if (key_p->is_lib_obj && !(key_p->bool_attr_mask & SIGN_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_Sign or C_SignFinal to actually obtain the signature. 85 */ 86 session_p->sign.flags = CRYPTO_OPERATION_ACTIVE; 87 sign_init.si_session = session_p->k_session; 88 (void) pthread_mutex_unlock(&session_p->session_mutex); 89 ses_lock_held = B_FALSE; 90 91 if (!key_p->is_lib_obj) { 92 sign_init.si_key.ck_format = CRYPTO_KEY_REFERENCE; 93 sign_init.si_key.ck_obj_id = key_p->k_handle; 94 } else { 95 if (key_p->class == CKO_SECRET_KEY) { 96 sign_init.si_key.ck_format = CRYPTO_KEY_RAW; 97 sign_init.si_key.ck_data = 98 get_symmetric_key_value(key_p); 99 if (sign_init.si_key.ck_data == NULL) { 100 rv = CKR_HOST_MEMORY; 101 goto clean_exit; 102 } 103 sign_init.si_key.ck_length = 104 OBJ_SEC(key_p)->sk_value_len << 3; 105 106 } else if (key_p->key_type == CKK_RSA) { 107 rv = get_rsa_private_key(key_p, &sign_init.si_key); 108 if (rv != CKR_OK) { 109 goto clean_exit; 110 } 111 } else if (key_p->key_type == CKK_DSA) { 112 rv = get_dsa_private_key(key_p, &sign_init.si_key); 113 if (rv != CKR_OK) { 114 goto clean_exit; 115 } 116 } else { 117 rv = CKR_KEY_TYPE_INCONSISTENT; 118 goto clean_exit; 119 } 120 } 121 122 sign_init.si_mech.cm_type = k_mech_type; 123 sign_init.si_mech.cm_param = pMechanism->pParameter; 124 sign_init.si_mech.cm_param_len = pMechanism->ulParameterLen; 125 126 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_INIT, &sign_init)) < 0) { 127 if (errno != EINTR) 128 break; 129 } 130 if (r < 0) { 131 rv = CKR_FUNCTION_FAILED; 132 } else { 133 rv = crypto2pkcs11_error_number(sign_init.si_return_value); 134 } 135 136 if (key_p->is_lib_obj) { 137 if (key_p->class == CKO_SECRET_KEY) { 138 free(sign_init.si_key.ck_data); 139 } else { 140 free_key_attributes(&sign_init.si_key); 141 } 142 } 143 144 if (rv != CKR_OK) { 145 (void) pthread_mutex_lock(&session_p->session_mutex); 146 session_p->sign.flags &= ~CRYPTO_OPERATION_ACTIVE; 147 ses_lock_held = B_TRUE; 148 } 149 150 clean_exit: 151 OBJ_REFRELE(key_p); 152 REFRELE(session_p, ses_lock_held); 153 return (rv); 154 } 155 156 157 CK_RV 158 C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, 159 CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) 160 { 161 162 CK_RV rv; 163 kernel_session_t *session_p; 164 boolean_t ses_lock_held = B_FALSE; 165 crypto_sign_t sign; 166 int r; 167 168 if (!kernel_initialized) 169 return (CKR_CRYPTOKI_NOT_INITIALIZED); 170 171 /* Obtain the session pointer */ 172 rv = handle2session(hSession, &session_p); 173 if (rv != CKR_OK) 174 return (rv); 175 176 if (pulSignatureLen == NULL) { 177 rv = CKR_ARGUMENTS_BAD; 178 goto clean_exit; 179 } 180 181 (void) pthread_mutex_lock(&session_p->session_mutex); 182 ses_lock_held = B_TRUE; 183 184 /* Application must call C_SignInit before calling C_Sign. */ 185 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { 186 REFRELE(session_p, ses_lock_held); 187 return (CKR_OPERATION_NOT_INITIALIZED); 188 } 189 190 /* 191 * C_Sign must be called without intervening C_SignUpdate 192 * calls. 193 */ 194 if (session_p->sign.flags & CRYPTO_OPERATION_UPDATE) { 195 /* 196 * C_Sign can not be used to terminate a multi-part 197 * operation, so we'll leave the active sign operation 198 * flag on and let the application continue with the 199 * sign update operation. 200 */ 201 REFRELE(session_p, ses_lock_held); 202 return (CKR_FUNCTION_FAILED); 203 } 204 205 sign.cs_session = session_p->k_session; 206 (void) pthread_mutex_unlock(&session_p->session_mutex); 207 ses_lock_held = B_FALSE; 208 209 sign.cs_datalen = ulDataLen; 210 sign.cs_databuf = (char *)pData; 211 sign.cs_signlen = *pulSignatureLen; 212 sign.cs_signbuf = (char *)pSignature; 213 214 while ((r = ioctl(kernel_fd, CRYPTO_SIGN, &sign)) < 0) { 215 if (errno != EINTR) 216 break; 217 } 218 if (r < 0) { 219 rv = CKR_FUNCTION_FAILED; 220 } else { 221 rv = crypto2pkcs11_error_number(sign.cs_return_value); 222 } 223 224 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 225 *pulSignatureLen = sign.cs_signlen; 226 227 if ((rv == CKR_BUFFER_TOO_SMALL) || 228 (rv == CKR_OK && pSignature == NULL)) { 229 /* 230 * We will not terminate the active sign operation flag, 231 * when the application-supplied buffer is too small, or 232 * the application asks for the length of buffer to hold 233 * the signature. 234 */ 235 REFRELE(session_p, ses_lock_held); 236 return (rv); 237 } 238 239 clean_exit: 240 /* 241 * Terminates the active sign operation. 242 * Application needs to call C_SignInit again for next 243 * sign operation. 244 */ 245 (void) pthread_mutex_lock(&session_p->session_mutex); 246 session_p->sign.flags = 0; 247 ses_lock_held = B_TRUE; 248 REFRELE(session_p, ses_lock_held); 249 250 return (rv); 251 } 252 253 254 CK_RV 255 C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, 256 CK_ULONG ulPartLen) 257 { 258 259 CK_RV rv; 260 kernel_session_t *session_p; 261 boolean_t ses_lock_held = B_FALSE; 262 crypto_sign_update_t sign_update; 263 int r; 264 265 if (!kernel_initialized) 266 return (CKR_CRYPTOKI_NOT_INITIALIZED); 267 268 /* Obtain the session pointer */ 269 rv = handle2session(hSession, &session_p); 270 if (rv != CKR_OK) 271 return (rv); 272 273 if (pPart == NULL) { 274 rv = CKR_ARGUMENTS_BAD; 275 goto clean_exit; 276 } 277 278 (void) pthread_mutex_lock(&session_p->session_mutex); 279 ses_lock_held = B_TRUE; 280 281 /* 282 * Application must call C_SignInit before calling 283 * C_SignUpdate. 284 */ 285 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { 286 REFRELE(session_p, ses_lock_held); 287 return (CKR_OPERATION_NOT_INITIALIZED); 288 } 289 290 session_p->sign.flags |= CRYPTO_OPERATION_UPDATE; 291 292 sign_update.su_session = session_p->k_session; 293 (void) pthread_mutex_unlock(&session_p->session_mutex); 294 ses_lock_held = B_FALSE; 295 296 sign_update.su_datalen = ulPartLen; 297 sign_update.su_databuf = (char *)pPart; 298 299 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_UPDATE, &sign_update)) < 0) { 300 if (errno != EINTR) 301 break; 302 } 303 if (r < 0) { 304 rv = CKR_FUNCTION_FAILED; 305 } else { 306 rv = crypto2pkcs11_error_number(sign_update.su_return_value); 307 } 308 309 if (rv == CKR_OK) { 310 REFRELE(session_p, ses_lock_held); 311 return (rv); 312 } 313 314 clean_exit: 315 /* 316 * After an error occurred, terminate the current sign 317 * operation by resetting the active and update flags. 318 */ 319 (void) pthread_mutex_lock(&session_p->session_mutex); 320 session_p->sign.flags = 0; 321 ses_lock_held = B_TRUE; 322 REFRELE(session_p, ses_lock_held); 323 324 return (rv); 325 } 326 327 328 CK_RV 329 C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, 330 CK_ULONG_PTR pulSignatureLen) 331 { 332 333 CK_RV rv; 334 kernel_session_t *session_p; 335 boolean_t ses_lock_held = B_FALSE; 336 crypto_sign_final_t sign_final; 337 int r; 338 339 if (!kernel_initialized) 340 return (CKR_CRYPTOKI_NOT_INITIALIZED); 341 342 /* Obtain the session pointer */ 343 rv = handle2session(hSession, &session_p); 344 if (rv != CKR_OK) 345 return (rv); 346 347 if (pulSignatureLen == NULL) { 348 rv = CKR_ARGUMENTS_BAD; 349 goto clean_exit; 350 } 351 352 (void) pthread_mutex_lock(&session_p->session_mutex); 353 ses_lock_held = B_TRUE; 354 355 /* 356 * Application must call C_SignInit before calling 357 * C_SignFinal. 358 */ 359 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { 360 REFRELE(session_p, ses_lock_held); 361 return (CKR_OPERATION_NOT_INITIALIZED); 362 } 363 364 sign_final.sf_session = session_p->k_session; 365 (void) pthread_mutex_unlock(&session_p->session_mutex); 366 ses_lock_held = B_FALSE; 367 368 sign_final.sf_signlen = *pulSignatureLen; 369 sign_final.sf_signbuf = (char *)pSignature; 370 371 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_FINAL, &sign_final)) < 0) { 372 if (errno != EINTR) 373 break; 374 } 375 if (r < 0) { 376 rv = CKR_FUNCTION_FAILED; 377 } else { 378 rv = crypto2pkcs11_error_number(sign_final.sf_return_value); 379 } 380 381 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 382 *pulSignatureLen = sign_final.sf_signlen; 383 384 if ((rv == CKR_BUFFER_TOO_SMALL) || 385 (rv == CKR_OK && pSignature == NULL)) { 386 /* 387 * We will not terminate the active sign operation flag, 388 * when the application-supplied buffer is too small, or 389 * the application asks for the length of buffer to hold 390 * the signature. 391 */ 392 REFRELE(session_p, ses_lock_held); 393 return (rv); 394 } 395 396 clean_exit: 397 /* Terminates the active sign operation */ 398 (void) pthread_mutex_lock(&session_p->session_mutex); 399 session_p->sign.flags = 0; 400 ses_lock_held = B_TRUE; 401 REFRELE(session_p, ses_lock_held); 402 403 return (rv); 404 } 405 406 407 CK_RV 408 C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 409 CK_OBJECT_HANDLE hKey) 410 { 411 412 CK_RV rv; 413 kernel_session_t *session_p; 414 kernel_object_t *key_p; 415 boolean_t ses_lock_held = B_FALSE; 416 crypto_sign_recover_init_t sr_init; 417 crypto_mech_type_t k_mech_type; 418 int r; 419 420 if (!kernel_initialized) 421 return (CKR_CRYPTOKI_NOT_INITIALIZED); 422 423 if (pMechanism == NULL) { 424 return (CKR_ARGUMENTS_BAD); 425 } 426 427 /* Get the kernel's internal mechanism number. */ 428 rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 429 if (rv != CKR_OK) 430 return (rv); 431 432 /* Obtain the session pointer. */ 433 rv = handle2session(hSession, &session_p); 434 if (rv != CKR_OK) 435 return (rv); 436 437 /* Obtain the object pointer. */ 438 HANDLE2OBJECT(hKey, key_p, rv); 439 if (rv != CKR_OK) { 440 REFRELE(session_p, ses_lock_held); 441 return (rv); 442 } 443 444 /* 445 * Check to see if key object is a RSA key and if it supports 446 * sign_recover. 447 */ 448 if (key_p->is_lib_obj && !((key_p->key_type == CKK_RSA) && 449 (key_p->bool_attr_mask & SIGN_RECOVER_BOOL_ON))) { 450 rv = CKR_KEY_TYPE_INCONSISTENT; 451 goto clean_exit; 452 } 453 454 (void) pthread_mutex_lock(&session_p->session_mutex); 455 ses_lock_held = B_TRUE; 456 457 /* 458 * This active flag will remain ON until application calls 459 * C_SignRecover to actually obtain the signature. 460 */ 461 session_p->sign.flags = CRYPTO_OPERATION_ACTIVE; 462 463 /* Set up the key data */ 464 if (!key_p->is_lib_obj) { 465 sr_init.ri_key.ck_format = CRYPTO_KEY_REFERENCE; 466 sr_init.ri_key.ck_obj_id = key_p->k_handle; 467 } else { 468 if (key_p->key_type == CKK_RSA) { 469 if (get_rsa_private_key(key_p, &sr_init.ri_key) != 470 CKR_OK) { 471 rv = CKR_HOST_MEMORY; 472 goto clean_exit; 473 } 474 } else { 475 rv = CKR_KEY_TYPE_INCONSISTENT; 476 goto clean_exit; 477 } 478 } 479 480 sr_init.ri_session = session_p->k_session; 481 (void) pthread_mutex_unlock(&session_p->session_mutex); 482 ses_lock_held = B_FALSE; 483 sr_init.ri_mech.cm_type = k_mech_type; 484 sr_init.ri_mech.cm_param = pMechanism->pParameter; 485 sr_init.ri_mech.cm_param_len = pMechanism->ulParameterLen; 486 487 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_RECOVER_INIT, &sr_init)) < 0) { 488 if (errno != EINTR) 489 break; 490 } 491 if (r < 0) { 492 rv = CKR_FUNCTION_FAILED; 493 } else { 494 rv = crypto2pkcs11_error_number(sr_init.ri_return_value); 495 } 496 497 if (key_p->is_lib_obj) { 498 free_key_attributes(&sr_init.ri_key); 499 } 500 501 if (rv != CKR_OK) { 502 (void) pthread_mutex_lock(&session_p->session_mutex); 503 session_p->sign.flags &= ~CRYPTO_OPERATION_ACTIVE; 504 ses_lock_held = B_TRUE; 505 } 506 507 clean_exit: 508 OBJ_REFRELE(key_p); 509 REFRELE(session_p, ses_lock_held); 510 return (rv); 511 } 512 513 514 CK_RV 515 C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, 516 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) 517 { 518 519 CK_RV rv; 520 kernel_session_t *session_p; 521 boolean_t ses_lock_held = B_FALSE; 522 crypto_sign_recover_t sign_recover; 523 int r; 524 525 if (!kernel_initialized) 526 return (CKR_CRYPTOKI_NOT_INITIALIZED); 527 528 /* Obatin the session pointer */ 529 rv = handle2session(hSession, &session_p); 530 if (rv != CKR_OK) 531 return (rv); 532 533 if (pulSignatureLen == NULL) { 534 rv = CKR_ARGUMENTS_BAD; 535 goto clean_exit; 536 } 537 538 (void) pthread_mutex_lock(&session_p->session_mutex); 539 ses_lock_held = B_TRUE; 540 541 /* Application must call C_SignInit before calling C_Sign. */ 542 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { 543 REFRELE(session_p, ses_lock_held); 544 return (CKR_OPERATION_NOT_INITIALIZED); 545 } 546 547 sign_recover.sr_session = session_p->k_session; 548 (void) pthread_mutex_unlock(&session_p->session_mutex); 549 ses_lock_held = B_FALSE; 550 551 sign_recover.sr_datalen = ulDataLen; 552 sign_recover.sr_databuf = (char *)pData; 553 sign_recover.sr_signlen = *pulSignatureLen; 554 sign_recover.sr_signbuf = (char *)pSignature; 555 556 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_RECOVER, &sign_recover)) < 0) { 557 if (errno != EINTR) 558 break; 559 } 560 if (r < 0) { 561 rv = CKR_FUNCTION_FAILED; 562 } else { 563 rv = crypto2pkcs11_error_number(sign_recover.sr_return_value); 564 } 565 566 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 567 *pulSignatureLen = sign_recover.sr_signlen; 568 569 if ((rv == CKR_BUFFER_TOO_SMALL) || 570 (rv == CKR_OK && pSignature == NULL)) { 571 /* 572 * We will not terminate the active sign operation flag, 573 * when the application-supplied buffer is too small, or 574 * the application asks for the length of buffer to hold 575 * the signature. 576 */ 577 REFRELE(session_p, ses_lock_held); 578 return (rv); 579 } 580 581 clean_exit: 582 /* 583 * Terminates the active sign operation. 584 * Application needs to call C_SignInit again for next 585 * sign operation. 586 */ 587 (void) pthread_mutex_lock(&session_p->session_mutex); 588 session_p->sign.flags = 0; 589 ses_lock_held = B_TRUE; 590 REFRELE(session_p, ses_lock_held); 591 592 return (rv); 593 } 594