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