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 }