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 goto clean_exit; 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 if (key_p->key_type == CKK_RSA) { 140 free_key_attributes(&sign_init.si_key); 141 } else if (key_p->key_type == CKK_DSA) { 142 free_key_attributes(&sign_init.si_key); 143 } 144 } 145 146 if (rv != CKR_OK) { 147 (void) pthread_mutex_lock(&session_p->session_mutex); 148 session_p->sign.flags &= ~CRYPTO_OPERATION_ACTIVE; 149 ses_lock_held = B_TRUE; 150 } 151 152 clean_exit: 153 REFRELE(session_p, ses_lock_held); 154 return (rv); 155 } 156 157 158 CK_RV 159 C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, 160 CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) 161 { 162 163 CK_RV rv; 164 kernel_session_t *session_p; 165 boolean_t ses_lock_held = B_FALSE; 166 crypto_sign_t sign; 167 int r; 168 169 if (!kernel_initialized) 170 return (CKR_CRYPTOKI_NOT_INITIALIZED); 171 172 /* Obtain the session pointer */ 173 rv = handle2session(hSession, &session_p); 174 if (rv != CKR_OK) 175 return (rv); 176 177 if (pulSignatureLen == NULL) { 178 rv = CKR_ARGUMENTS_BAD; 179 goto clean_exit; 180 } 181 182 (void) pthread_mutex_lock(&session_p->session_mutex); 183 ses_lock_held = B_TRUE; 184 185 /* Application must call C_SignInit before calling C_Sign. */ 186 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { 187 REFRELE(session_p, ses_lock_held); 188 return (CKR_OPERATION_NOT_INITIALIZED); 189 } 190 191 /* 192 * C_Sign must be called without intervening C_SignUpdate 193 * calls. 194 */ 195 if (session_p->sign.flags & CRYPTO_OPERATION_UPDATE) { 196 /* 197 * C_Sign can not be used to terminate a multi-part 198 * operation, so we'll leave the active sign operation 199 * flag on and let the application continue with the 200 * sign update operation. 201 */ 202 REFRELE(session_p, ses_lock_held); 203 return (CKR_FUNCTION_FAILED); 204 } 205 206 sign.cs_session = session_p->k_session; 207 (void) pthread_mutex_unlock(&session_p->session_mutex); 208 ses_lock_held = B_FALSE; 209 210 sign.cs_datalen = ulDataLen; 211 sign.cs_databuf = (char *)pData; 212 sign.cs_signlen = *pulSignatureLen; 213 sign.cs_signbuf = (char *)pSignature; 214 215 while ((r = ioctl(kernel_fd, CRYPTO_SIGN, &sign)) < 0) { 216 if (errno != EINTR) 217 break; 218 } 219 if (r < 0) { 220 rv = CKR_FUNCTION_FAILED; 221 } else { 222 rv = crypto2pkcs11_error_number(sign.cs_return_value); 223 } 224 225 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 226 *pulSignatureLen = sign.cs_signlen; 227 228 if ((rv == CKR_BUFFER_TOO_SMALL) || 229 (rv == CKR_OK && pSignature == NULL)) { 230 /* 231 * We will not terminate the active sign operation flag, 232 * when the application-supplied buffer is too small, or 233 * the application asks for the length of buffer to hold 234 * the signature. 235 */ 236 REFRELE(session_p, ses_lock_held); 237 return (rv); 238 } 239 240 clean_exit: 241 /* 242 * Terminates the active sign operation. 243 * Application needs to call C_SignInit again for next 244 * sign operation. 245 */ 246 (void) pthread_mutex_lock(&session_p->session_mutex); 247 session_p->sign.flags = 0; 248 ses_lock_held = B_TRUE; 249 REFRELE(session_p, ses_lock_held); 250 251 return (rv); 252 } 253 254 255 CK_RV 256 C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, 257 CK_ULONG ulPartLen) 258 { 259 260 CK_RV rv; 261 kernel_session_t *session_p; 262 boolean_t ses_lock_held = B_FALSE; 263 crypto_sign_update_t sign_update; 264 int r; 265 266 if (!kernel_initialized) 267 return (CKR_CRYPTOKI_NOT_INITIALIZED); 268 269 /* Obtain the session pointer */ 270 rv = handle2session(hSession, &session_p); 271 if (rv != CKR_OK) 272 return (rv); 273 274 if (pPart == NULL) { 275 rv = CKR_ARGUMENTS_BAD; 276 goto clean_exit; 277 } 278 279 (void) pthread_mutex_lock(&session_p->session_mutex); 280 ses_lock_held = B_TRUE; 281 282 /* 283 * Application must call C_SignInit before calling 284 * C_SignUpdate. 285 */ 286 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { 287 REFRELE(session_p, ses_lock_held); 288 return (CKR_OPERATION_NOT_INITIALIZED); 289 } 290 291 session_p->sign.flags |= CRYPTO_OPERATION_UPDATE; 292 293 sign_update.su_session = session_p->k_session; 294 (void) pthread_mutex_unlock(&session_p->session_mutex); 295 ses_lock_held = B_FALSE; 296 297 sign_update.su_datalen = ulPartLen; 298 sign_update.su_databuf = (char *)pPart; 299 300 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_UPDATE, &sign_update)) < 0) { 301 if (errno != EINTR) 302 break; 303 } 304 if (r < 0) { 305 rv = CKR_FUNCTION_FAILED; 306 } else { 307 rv = crypto2pkcs11_error_number(sign_update.su_return_value); 308 } 309 310 if (rv == CKR_OK) { 311 REFRELE(session_p, ses_lock_held); 312 return (rv); 313 } 314 315 clean_exit: 316 /* 317 * After an error occurred, terminate the current sign 318 * operation by resetting the active and update flags. 319 */ 320 (void) pthread_mutex_lock(&session_p->session_mutex); 321 session_p->sign.flags = 0; 322 ses_lock_held = B_TRUE; 323 REFRELE(session_p, ses_lock_held); 324 325 return (rv); 326 } 327 328 329 CK_RV 330 C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, 331 CK_ULONG_PTR pulSignatureLen) 332 { 333 334 CK_RV rv; 335 kernel_session_t *session_p; 336 boolean_t ses_lock_held = B_FALSE; 337 crypto_sign_final_t sign_final; 338 int r; 339 340 if (!kernel_initialized) 341 return (CKR_CRYPTOKI_NOT_INITIALIZED); 342 343 /* Obtain the session pointer */ 344 rv = handle2session(hSession, &session_p); 345 if (rv != CKR_OK) 346 return (rv); 347 348 if (pulSignatureLen == NULL) { 349 rv = CKR_ARGUMENTS_BAD; 350 goto clean_exit; 351 } 352 353 (void) pthread_mutex_lock(&session_p->session_mutex); 354 ses_lock_held = B_TRUE; 355 356 /* 357 * Application must call C_SignInit before calling 358 * C_SignFinal. 359 */ 360 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { 361 REFRELE(session_p, ses_lock_held); 362 return (CKR_OPERATION_NOT_INITIALIZED); 363 } 364 365 sign_final.sf_session = session_p->k_session; 366 (void) pthread_mutex_unlock(&session_p->session_mutex); 367 ses_lock_held = B_FALSE; 368 369 sign_final.sf_signlen = *pulSignatureLen; 370 sign_final.sf_signbuf = (char *)pSignature; 371 372 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_FINAL, &sign_final)) < 0) { 373 if (errno != EINTR) 374 break; 375 } 376 if (r < 0) { 377 rv = CKR_FUNCTION_FAILED; 378 } else { 379 rv = crypto2pkcs11_error_number(sign_final.sf_return_value); 380 } 381 382 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 383 *pulSignatureLen = sign_final.sf_signlen; 384 385 if ((rv == CKR_BUFFER_TOO_SMALL) || 386 (rv == CKR_OK && pSignature == NULL)) { 387 /* 388 * We will not terminate the active sign operation flag, 389 * when the application-supplied buffer is too small, or 390 * the application asks for the length of buffer to hold 391 * the signature. 392 */ 393 REFRELE(session_p, ses_lock_held); 394 return (rv); 395 } 396 397 clean_exit: 398 /* Terminates the active sign operation */ 399 (void) pthread_mutex_lock(&session_p->session_mutex); 400 session_p->sign.flags = 0; 401 ses_lock_held = B_TRUE; 402 REFRELE(session_p, ses_lock_held); 403 404 return (rv); 405 } 406 407 408 CK_RV 409 C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 410 CK_OBJECT_HANDLE hKey) 411 { 412 413 CK_RV rv; 414 kernel_session_t *session_p; 415 kernel_object_t *key_p; 416 boolean_t ses_lock_held = B_FALSE; 417 crypto_sign_recover_init_t sr_init; 418 crypto_mech_type_t k_mech_type; 419 int r; 420 421 if (!kernel_initialized) 422 return (CKR_CRYPTOKI_NOT_INITIALIZED); 423 424 if (pMechanism == NULL) { 425 return (CKR_ARGUMENTS_BAD); 426 } 427 428 /* Get the kernel's internal mechanism number. */ 429 rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 430 if (rv != CKR_OK) 431 return (rv); 432 433 /* Obtain the session pointer. */ 434 rv = handle2session(hSession, &session_p); 435 if (rv != CKR_OK) 436 return (rv); 437 438 /* Obtain the object pointer. */ 439 HANDLE2OBJECT(hKey, key_p, rv); 440 if (rv != CKR_OK) { 441 goto clean_exit; 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 REFRELE(session_p, ses_lock_held); 509 return (rv); 510 } 511 512 513 CK_RV 514 C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, 515 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) 516 { 517 518 CK_RV rv; 519 kernel_session_t *session_p; 520 boolean_t ses_lock_held = B_FALSE; 521 crypto_sign_recover_t sign_recover; 522 int r; 523 524 if (!kernel_initialized) 525 return (CKR_CRYPTOKI_NOT_INITIALIZED); 526 527 /* Obatin the session pointer */ 528 rv = handle2session(hSession, &session_p); 529 if (rv != CKR_OK) 530 return (rv); 531 532 if (pulSignatureLen == NULL) { 533 rv = CKR_ARGUMENTS_BAD; 534 goto clean_exit; 535 } 536 537 (void) pthread_mutex_lock(&session_p->session_mutex); 538 ses_lock_held = B_TRUE; 539 540 /* Application must call C_SignInit before calling C_Sign. */ 541 if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { 542 REFRELE(session_p, ses_lock_held); 543 return (CKR_OPERATION_NOT_INITIALIZED); 544 } 545 546 sign_recover.sr_session = session_p->k_session; 547 (void) pthread_mutex_unlock(&session_p->session_mutex); 548 ses_lock_held = B_FALSE; 549 550 sign_recover.sr_datalen = ulDataLen; 551 sign_recover.sr_databuf = (char *)pData; 552 sign_recover.sr_signlen = *pulSignatureLen; 553 sign_recover.sr_signbuf = (char *)pSignature; 554 555 while ((r = ioctl(kernel_fd, CRYPTO_SIGN_RECOVER, &sign_recover)) < 0) { 556 if (errno != EINTR) 557 break; 558 } 559 if (r < 0) { 560 rv = CKR_FUNCTION_FAILED; 561 } else { 562 rv = crypto2pkcs11_error_number(sign_recover.sr_return_value); 563 } 564 565 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 566 *pulSignatureLen = sign_recover.sr_signlen; 567 568 if ((rv == CKR_BUFFER_TOO_SMALL) || 569 (rv == CKR_OK && pSignature == NULL)) { 570 /* 571 * We will not terminate the active sign operation flag, 572 * when the application-supplied buffer is too small, or 573 * the application asks for the length of buffer to hold 574 * the signature. 575 */ 576 REFRELE(session_p, ses_lock_held); 577 return (rv); 578 } 579 580 clean_exit: 581 /* 582 * Terminates the active sign operation. 583 * Application needs to call C_SignInit again for next 584 * sign operation. 585 */ 586 (void) pthread_mutex_lock(&session_p->session_mutex); 587 session_p->sign.flags = 0; 588 ses_lock_held = B_TRUE; 589 REFRELE(session_p, ses_lock_held); 590 591 return (rv); 592 } 593