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