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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved. 26 * 27 * Copyright 2020 Joyent, Inc. 28 */ 29 30 #include <strings.h> 31 #include <errno.h> 32 #include <cryptoutil.h> 33 #include <unistd.h> /* for pid_t */ 34 #include <pthread.h> 35 #include <stddef.h> 36 #include <security/cryptoki.h> 37 #include <sys/debug.h> 38 #include "softGlobal.h" 39 #include "softSession.h" 40 #include "softObject.h" 41 #include "softKeystore.h" 42 #include "softKeystoreUtil.h" 43 44 #pragma init(softtoken_init) 45 #pragma fini(softtoken_fini) 46 47 extern soft_session_t token_session; /* for fork handler */ 48 49 static struct CK_FUNCTION_LIST functionList = { 50 { 2, 20 }, /* version */ 51 C_Initialize, 52 C_Finalize, 53 C_GetInfo, 54 C_GetFunctionList, 55 C_GetSlotList, 56 C_GetSlotInfo, 57 C_GetTokenInfo, 58 C_GetMechanismList, 59 C_GetMechanismInfo, 60 C_InitToken, 61 C_InitPIN, 62 C_SetPIN, 63 C_OpenSession, 64 C_CloseSession, 65 C_CloseAllSessions, 66 C_GetSessionInfo, 67 C_GetOperationState, 68 C_SetOperationState, 69 C_Login, 70 C_Logout, 71 C_CreateObject, 72 C_CopyObject, 73 C_DestroyObject, 74 C_GetObjectSize, 75 C_GetAttributeValue, 76 C_SetAttributeValue, 77 C_FindObjectsInit, 78 C_FindObjects, 79 C_FindObjectsFinal, 80 C_EncryptInit, 81 C_Encrypt, 82 C_EncryptUpdate, 83 C_EncryptFinal, 84 C_DecryptInit, 85 C_Decrypt, 86 C_DecryptUpdate, 87 C_DecryptFinal, 88 C_DigestInit, 89 C_Digest, 90 C_DigestUpdate, 91 C_DigestKey, 92 C_DigestFinal, 93 C_SignInit, 94 C_Sign, 95 C_SignUpdate, 96 C_SignFinal, 97 C_SignRecoverInit, 98 C_SignRecover, 99 C_VerifyInit, 100 C_Verify, 101 C_VerifyUpdate, 102 C_VerifyFinal, 103 C_VerifyRecoverInit, 104 C_VerifyRecover, 105 C_DigestEncryptUpdate, 106 C_DecryptDigestUpdate, 107 C_SignEncryptUpdate, 108 C_DecryptVerifyUpdate, 109 C_GenerateKey, 110 C_GenerateKeyPair, 111 C_WrapKey, 112 C_UnwrapKey, 113 C_DeriveKey, 114 C_SeedRandom, 115 C_GenerateRandom, 116 C_GetFunctionStatus, 117 C_CancelFunction, 118 C_WaitForSlotEvent 119 }; 120 121 boolean_t softtoken_initialized = B_FALSE; 122 123 static pid_t softtoken_pid = 0; 124 125 /* 126 * Lock ordering in pkcs11_softtoken is as follows: 127 * soft_giant_mutex 128 * soft_sessionlist_mutex 129 * soft_slot.slot_mutex 130 * soft_slot.keystore_mutex 131 * token session mutexes 132 * soft_session_t->session_mutex 133 * soft_object_mutex 134 * soft_object_t->object_mutex 135 * obj_delay_freed.obj_to_be_free_mutex 136 * ses_delay_freed.ses_to_br_free_mutex 137 */ 138 139 /* 140 * This mutex protects soft_session_list, all_sessions_closing, 141 * and soft_session_tree 142 */ 143 pthread_mutex_t soft_sessionlist_mutex; 144 soft_session_t *soft_session_list = NULL; 145 avl_tree_t soft_session_tree; 146 147 /* This protects soft_object_tree */ 148 pthread_mutex_t soft_object_mutex; 149 avl_tree_t soft_object_tree; 150 151 int all_sessions_closing = 0; 152 153 slot_t soft_slot; 154 obj_to_be_freed_list_t obj_delay_freed; 155 ses_to_be_freed_list_t ses_delay_freed; 156 157 /* protects softtoken_initialized and access to C_Initialize/C_Finalize */ 158 pthread_mutex_t soft_giant_mutex = PTHREAD_MUTEX_INITIALIZER; 159 160 static CK_RV finalize_common(boolean_t force, CK_VOID_PTR pReserved); 161 static void softtoken_init(void); 162 static void softtoken_fini(void); 163 static void softtoken_fork_prepare(void); 164 static void softtoken_fork_after(void); 165 static int session_compare(const void *a, const void *b); 166 static int object_compare(const void *a, const void *b); 167 168 CK_RV 169 C_Initialize(CK_VOID_PTR pInitArgs) 170 { 171 pthread_mutexattr_t attr = { 0 }; 172 int initialize_pid; 173 boolean_t supplied_ok; 174 CK_RV rv; 175 176 /* 177 * Get lock to insure only one thread enters this 178 * function at a time. 179 */ 180 (void) pthread_mutex_lock(&soft_giant_mutex); 181 182 initialize_pid = getpid(); 183 184 if (softtoken_initialized) { 185 if (initialize_pid == softtoken_pid) { 186 /* 187 * This process has called C_Initialize already 188 */ 189 (void) pthread_mutex_unlock(&soft_giant_mutex); 190 return (CKR_CRYPTOKI_ALREADY_INITIALIZED); 191 } else { 192 /* 193 * A fork has happened and the child is 194 * reinitializing. Do a finalize_common to close 195 * out any state from the parent, and then 196 * continue on. 197 */ 198 (void) finalize_common(B_TRUE, NULL); 199 } 200 } 201 202 if (pInitArgs != NULL) { 203 CK_C_INITIALIZE_ARGS *initargs1 = 204 (CK_C_INITIALIZE_ARGS *) pInitArgs; 205 206 /* pReserved must be NULL */ 207 if (initargs1->pReserved != NULL) { 208 (void) pthread_mutex_unlock(&soft_giant_mutex); 209 return (CKR_ARGUMENTS_BAD); 210 } 211 212 /* 213 * ALL supplied function pointers need to have the value 214 * either NULL or non-NULL. 215 */ 216 supplied_ok = (initargs1->CreateMutex == NULL && 217 initargs1->DestroyMutex == NULL && 218 initargs1->LockMutex == NULL && 219 initargs1->UnlockMutex == NULL) || 220 (initargs1->CreateMutex != NULL && 221 initargs1->DestroyMutex != NULL && 222 initargs1->LockMutex != NULL && 223 initargs1->UnlockMutex != NULL); 224 225 if (!supplied_ok) { 226 (void) pthread_mutex_unlock(&soft_giant_mutex); 227 return (CKR_ARGUMENTS_BAD); 228 } 229 230 /* 231 * When the CKF_OS_LOCKING_OK flag isn't set and mutex 232 * function pointers are supplied by an application, 233 * return an error. We must be able to use our own primitives. 234 */ 235 if (!(initargs1->flags & CKF_OS_LOCKING_OK) && 236 (initargs1->CreateMutex != NULL)) { 237 (void) pthread_mutex_unlock(&soft_giant_mutex); 238 return (CKR_CANT_LOCK); 239 } 240 } 241 242 if (pthread_mutexattr_init(&attr) != 0) { 243 (void) pthread_mutex_unlock(&soft_giant_mutex); 244 return (CKR_HOST_MEMORY); 245 } 246 247 VERIFY0(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK)); 248 249 /* Initialize the session list lock */ 250 if (pthread_mutex_init(&soft_sessionlist_mutex, &attr) != 0) { 251 (void) pthread_mutexattr_destroy(&attr); 252 (void) pthread_mutex_unlock(&soft_giant_mutex); 253 return (CKR_CANT_LOCK); 254 } 255 256 if (pthread_mutex_init(&soft_object_mutex, &attr) != 0) { 257 (void) pthread_mutexattr_destroy(&attr); 258 (void) pthread_mutex_unlock(&soft_giant_mutex); 259 return (CKR_CANT_LOCK); 260 } 261 262 VERIFY0(pthread_mutexattr_destroy(&attr)); 263 264 /* 265 * token object related initialization 266 */ 267 soft_slot.authenticated = 0; 268 soft_slot.userpin_change_needed = 0; 269 soft_slot.token_object_list = NULL; 270 soft_slot.keystore_load_status = KEYSTORE_UNINITIALIZED; 271 272 if ((rv = soft_init_token_session()) != CKR_OK) { 273 (void) pthread_mutex_destroy(&soft_sessionlist_mutex); 274 (void) pthread_mutex_unlock(&soft_giant_mutex); 275 return (rv); 276 } 277 278 /* Initialize the slot lock */ 279 if (pthread_mutex_init(&soft_slot.slot_mutex, NULL) != 0) { 280 (void) pthread_mutex_destroy(&soft_sessionlist_mutex); 281 (void) soft_destroy_token_session(); 282 (void) pthread_mutex_unlock(&soft_giant_mutex); 283 return (CKR_CANT_LOCK); 284 } 285 286 /* Initialize the keystore lock */ 287 if (pthread_mutex_init(&soft_slot.keystore_mutex, NULL) != 0) { 288 (void) pthread_mutex_destroy(&soft_slot.slot_mutex); 289 (void) pthread_mutex_destroy(&soft_sessionlist_mutex); 290 (void) soft_destroy_token_session(); 291 (void) pthread_mutex_unlock(&soft_giant_mutex); 292 return (CKR_CANT_LOCK); 293 } 294 295 /* Initialize the object_to_be_freed list */ 296 if (pthread_mutex_init(&obj_delay_freed.obj_to_be_free_mutex, NULL) 297 != 0) { 298 (void) pthread_mutex_destroy(&soft_slot.keystore_mutex); 299 (void) pthread_mutex_destroy(&soft_slot.slot_mutex); 300 (void) pthread_mutex_destroy(&soft_sessionlist_mutex); 301 (void) soft_destroy_token_session(); 302 (void) pthread_mutex_unlock(&soft_giant_mutex); 303 return (CKR_CANT_LOCK); 304 } 305 obj_delay_freed.count = 0; 306 obj_delay_freed.first = NULL; 307 obj_delay_freed.last = NULL; 308 309 if (pthread_mutex_init(&ses_delay_freed.ses_to_be_free_mutex, NULL) 310 != 0) { 311 (void) pthread_mutex_destroy( 312 &obj_delay_freed.obj_to_be_free_mutex); 313 (void) pthread_mutex_destroy(&soft_slot.keystore_mutex); 314 (void) pthread_mutex_destroy(&soft_slot.slot_mutex); 315 (void) pthread_mutex_destroy(&soft_sessionlist_mutex); 316 (void) soft_destroy_token_session(); 317 (void) pthread_mutex_unlock(&soft_giant_mutex); 318 return (CKR_CANT_LOCK); 319 } 320 ses_delay_freed.count = 0; 321 ses_delay_freed.first = NULL; 322 ses_delay_freed.last = NULL; 323 324 if (rv != CKR_OK) { 325 (void) pthread_mutex_destroy( 326 &ses_delay_freed.ses_to_be_free_mutex); 327 (void) pthread_mutex_destroy( 328 &obj_delay_freed.obj_to_be_free_mutex); 329 (void) pthread_mutex_destroy(&soft_slot.keystore_mutex); 330 (void) pthread_mutex_destroy(&soft_slot.slot_mutex); 331 (void) pthread_mutex_destroy(&soft_sessionlist_mutex); 332 (void) soft_destroy_token_session(); 333 (void) pthread_mutex_unlock(&soft_giant_mutex); 334 return (CKR_FUNCTION_FAILED); 335 } 336 337 softtoken_pid = initialize_pid; 338 softtoken_initialized = B_TRUE; 339 (void) pthread_mutex_unlock(&soft_giant_mutex); 340 341 return (CKR_OK); 342 } 343 344 /* 345 * C_Finalize is a wrapper around finalize_common. The 346 * soft_giant_mutex should be locked by C_Finalize(). 347 */ 348 CK_RV 349 C_Finalize(CK_VOID_PTR pReserved) 350 { 351 352 CK_RV rv; 353 354 (void) pthread_mutex_lock(&soft_giant_mutex); 355 356 rv = finalize_common(B_FALSE, pReserved); 357 358 (void) pthread_mutex_unlock(&soft_giant_mutex); 359 360 return (rv); 361 362 } 363 364 /* 365 * finalize_common() does the work for C_Finalize. soft_giant_mutex 366 * must be held before calling this function. 367 */ 368 static CK_RV 369 finalize_common(boolean_t force, CK_VOID_PTR pReserved) 370 { 371 CK_RV rv = CKR_OK; 372 struct object *delay_free_obj, *tmpo; 373 struct session *delay_free_ses, *tmps; 374 375 if (!softtoken_initialized) { 376 return (CKR_CRYPTOKI_NOT_INITIALIZED); 377 } 378 379 /* Check to see if pReseved is NULL */ 380 if (pReserved != NULL) { 381 return (CKR_ARGUMENTS_BAD); 382 } 383 384 (void) pthread_mutex_lock(&soft_sessionlist_mutex); 385 /* 386 * Set all_sessions_closing flag so any access to any 387 * existing sessions will be rejected. 388 */ 389 all_sessions_closing = 1; 390 (void) pthread_mutex_unlock(&soft_sessionlist_mutex); 391 392 /* Delete all the sessions and release the allocated resources */ 393 rv = soft_delete_all_sessions(force); 394 395 (void) pthread_mutex_lock(&soft_sessionlist_mutex); 396 /* Reset all_sessions_closing flag. */ 397 all_sessions_closing = 0; 398 (void) pthread_mutex_unlock(&soft_sessionlist_mutex); 399 400 softtoken_initialized = B_FALSE; 401 softtoken_pid = 0; 402 403 /* 404 * There used to be calls to cleanup libcryptoutil here. Given that 405 * libcryptoutil can be linked and invoked independently of PKCS#11, 406 * cleaning up libcryptoutil here makes no sense. Decoupling these 407 * two also prevent deadlocks and other artificial dependencies. 408 */ 409 410 (void) pthread_mutex_destroy(&soft_object_mutex); 411 412 /* Destroy the session list lock here */ 413 (void) pthread_mutex_destroy(&soft_sessionlist_mutex); 414 415 /* 416 * Destroy token object related stuffs 417 * 1. Clean up the token object list 418 * 2. Destroy slot mutex 419 * 3. Destroy mutex in token_session 420 */ 421 soft_delete_all_in_core_token_objects(ALL_TOKEN); 422 (void) pthread_mutex_destroy(&soft_slot.slot_mutex); 423 (void) pthread_mutex_destroy(&soft_slot.keystore_mutex); 424 (void) soft_destroy_token_session(); 425 426 /* 427 * free all entries in the delay_freed list 428 */ 429 delay_free_obj = obj_delay_freed.first; 430 while (delay_free_obj != NULL) { 431 tmpo = delay_free_obj->next; 432 free(delay_free_obj); 433 delay_free_obj = tmpo; 434 } 435 436 soft_slot.keystore_load_status = KEYSTORE_UNINITIALIZED; 437 (void) pthread_mutex_destroy(&obj_delay_freed.obj_to_be_free_mutex); 438 439 delay_free_ses = ses_delay_freed.first; 440 while (delay_free_ses != NULL) { 441 tmps = delay_free_ses->next; 442 free(delay_free_ses); 443 delay_free_ses = tmps; 444 } 445 (void) pthread_mutex_destroy(&ses_delay_freed.ses_to_be_free_mutex); 446 447 return (rv); 448 } 449 450 static void 451 softtoken_init() 452 { 453 avl_create(&soft_session_tree, session_compare, sizeof (soft_session_t), 454 offsetof(soft_session_t, node)); 455 456 avl_create(&soft_object_tree, object_compare, sizeof (soft_object_t), 457 offsetof(soft_object_t, node)); 458 459 /* Children inherit parent's atfork handlers */ 460 (void) pthread_atfork(softtoken_fork_prepare, 461 softtoken_fork_after, softtoken_fork_after); 462 } 463 464 /* 465 * softtoken_fini() function required to make sure complete cleanup 466 * is done if softtoken is ever unloaded without a C_Finalize() call. 467 */ 468 static void 469 softtoken_fini() 470 { 471 (void) pthread_mutex_lock(&soft_giant_mutex); 472 473 /* if we're not initilized, do not attempt to finalize */ 474 if (!softtoken_initialized) { 475 (void) pthread_mutex_unlock(&soft_giant_mutex); 476 return; 477 } 478 479 (void) finalize_common(B_TRUE, NULL_PTR); 480 481 avl_destroy(&soft_object_tree); 482 avl_destroy(&soft_session_tree); 483 484 (void) pthread_mutex_unlock(&soft_giant_mutex); 485 } 486 487 CK_RV 488 C_GetInfo(CK_INFO_PTR pInfo) 489 { 490 if (!softtoken_initialized) 491 return (CKR_CRYPTOKI_NOT_INITIALIZED); 492 493 if (pInfo == NULL) { 494 return (CKR_ARGUMENTS_BAD); 495 } 496 497 /* Provide general information in the provided buffer */ 498 pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR; 499 pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR; 500 (void) strncpy((char *)pInfo->manufacturerID, 501 SOFT_MANUFACTURER_ID, 32); 502 pInfo->flags = 0; 503 (void) strncpy((char *)pInfo->libraryDescription, 504 LIBRARY_DESCRIPTION, 32); 505 pInfo->libraryVersion.major = LIBRARY_VERSION_MAJOR; 506 pInfo->libraryVersion.minor = LIBRARY_VERSION_MINOR; 507 508 return (CKR_OK); 509 } 510 511 CK_RV 512 C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) 513 { 514 if (ppFunctionList == NULL) { 515 return (CKR_ARGUMENTS_BAD); 516 } 517 518 *ppFunctionList = &functionList; 519 520 return (CKR_OK); 521 } 522 523 /* 524 * PKCS#11 states that C_GetFunctionStatus should always return 525 * CKR_FUNCTION_NOT_PARALLEL 526 */ 527 /*ARGSUSED*/ 528 CK_RV 529 C_GetFunctionStatus(CK_SESSION_HANDLE hSession) 530 { 531 return (CKR_FUNCTION_NOT_PARALLEL); 532 } 533 534 /* 535 * PKCS#11 states that C_CancelFunction should always return 536 * CKR_FUNCTION_NOT_PARALLEL 537 */ 538 /*ARGSUSED*/ 539 CK_RV 540 C_CancelFunction(CK_SESSION_HANDLE hSession) 541 { 542 return (CKR_FUNCTION_NOT_PARALLEL); 543 } 544 545 /* 546 * Take out all mutexes before fork. 547 * 548 * Order: 549 * 1. soft_giant_mutex 550 * 2. soft_sessionlist_mutex 551 * 3. soft_slot.slot_mutex 552 * 4. soft_slot.keystore_mutex 553 * 5. token_session mutexes via soft_acquire_all_session_mutexes() 554 * 6. all soft_session_list mutexes via soft_acquire_all_session_mutexes() 555 * 7. obj_delay_freed.obj_to_be_free_mutex; 556 * 8. ses_delay_freed.ses_to_be_free_mutex 557 */ 558 void 559 softtoken_fork_prepare() 560 { 561 (void) pthread_mutex_lock(&soft_giant_mutex); 562 if (softtoken_initialized) { 563 (void) pthread_mutex_lock(&soft_sessionlist_mutex); 564 (void) pthread_mutex_lock(&soft_slot.slot_mutex); 565 (void) pthread_mutex_lock(&soft_slot.keystore_mutex); 566 soft_acquire_all_session_mutexes(&token_session); 567 soft_acquire_all_session_mutexes(soft_session_list); 568 VERIFY0(pthread_mutex_lock(&soft_object_mutex)); 569 (void) pthread_mutex_lock( 570 &obj_delay_freed.obj_to_be_free_mutex); 571 (void) pthread_mutex_lock( 572 &ses_delay_freed.ses_to_be_free_mutex); 573 } 574 } 575 576 /* 577 * Release in opposite order to softtoken_fork_prepare(). 578 * Function is used for parent and child. 579 */ 580 void 581 softtoken_fork_after() 582 { 583 if (softtoken_initialized) { 584 (void) pthread_mutex_unlock( 585 &ses_delay_freed.ses_to_be_free_mutex); 586 (void) pthread_mutex_unlock( 587 &obj_delay_freed.obj_to_be_free_mutex); 588 VERIFY0(pthread_mutex_unlock(&soft_object_mutex)); 589 soft_release_all_session_mutexes(soft_session_list); 590 soft_release_all_session_mutexes(&token_session); 591 (void) pthread_mutex_unlock(&soft_slot.keystore_mutex); 592 (void) pthread_mutex_unlock(&soft_slot.slot_mutex); 593 (void) pthread_mutex_unlock(&soft_sessionlist_mutex); 594 } 595 (void) pthread_mutex_unlock(&soft_giant_mutex); 596 } 597 598 static int 599 session_compare(const void *a, const void *b) 600 { 601 const soft_session_t *l = a; 602 const soft_session_t *r = b; 603 604 if (l->handle < r->handle) 605 return (-1); 606 if (l->handle > r->handle) 607 return (1); 608 return (0); 609 } 610 611 static int 612 object_compare(const void *a, const void *b) 613 { 614 const soft_object_t *l = a; 615 const soft_object_t *r = b; 616 617 if (l->handle < r->handle) 618 return (-1); 619 if (l->handle > r->handle) 620 return (1); 621 return (0); 622 } 623