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  * ONLY SET TO TRUE BY softtoken_fork_prepare().
 135  * ONLY SET TO FALSE BY softtoken_fork_after().
 136  */
 137 boolean_t fork_prepared = B_FALSE;
 138 
 139 static CK_RV finalize_common(boolean_t force, CK_VOID_PTR pReserved);
 140 static void softtoken_init();
 141 static void softtoken_fini();
 142 static void softtoken_fork_prepare();
 143 static void softtoken_fork_after();
 144 static void softtoken_fork_after_droplocks(void);
 145 
 146 CK_RV
 147 C_Initialize(CK_VOID_PTR pInitArgs)
 148 {
 149 
 150         int initialize_pid;
 151         boolean_t supplied_ok;
 152         CK_RV rv;
 153 
 154         /*
 155          * Get lock to insure only one thread enters this
 156          * function at a time.
 157          */
 158         (void) pthread_mutex_lock(&soft_giant_mutex);
 159 
 160         initialize_pid = getpid();
 161 
 162         if (softtoken_initialized) {
 163                 if (initialize_pid == softtoken_pid) {
 164                         /*
 165                          * This process has called C_Initialize already
 166                          */
 167                         (void) pthread_mutex_unlock(&soft_giant_mutex);
 168                         return (CKR_CRYPTOKI_ALREADY_INITIALIZED);
 169                 } else {
 170                         /*
 171                          * A fork has happened and the child is
 172                          * reinitializing.  Do a finalize_common to close
 173                          * out any state from the parent, and then
 174                          * continue on.
 175                          */
 176                         (void) finalize_common(B_TRUE, NULL);
 177                 }
 178         }
 179 
 180         if (pInitArgs != NULL) {
 181                 CK_C_INITIALIZE_ARGS *initargs1 =
 182                     (CK_C_INITIALIZE_ARGS *) pInitArgs;
 183 
 184                 /* pReserved must be NULL */
 185                 if (initargs1->pReserved != NULL) {
 186                         (void) pthread_mutex_unlock(&soft_giant_mutex);
 187                         return (CKR_ARGUMENTS_BAD);
 188                 }
 189 
 190                 /*
 191                  * ALL supplied function pointers need to have the value
 192                  * either NULL or non-NULL.
 193                  */
 194                 supplied_ok = (initargs1->CreateMutex == NULL &&
 195                     initargs1->DestroyMutex == NULL &&
 196                     initargs1->LockMutex == NULL &&
 197                     initargs1->UnlockMutex == NULL) ||
 198                     (initargs1->CreateMutex != NULL &&
 199                     initargs1->DestroyMutex != NULL &&
 200                     initargs1->LockMutex != NULL &&
 201                     initargs1->UnlockMutex != NULL);
 202 
 203                 if (!supplied_ok) {
 204                         (void) pthread_mutex_unlock(&soft_giant_mutex);
 205                         return (CKR_ARGUMENTS_BAD);
 206                 }
 207 
 208                 /*
 209                  * When the CKF_OS_LOCKING_OK flag isn't set and mutex
 210                  * function pointers are supplied by an application,
 211                  * return an error.  We must be able to use our own primitives.
 212                  */
 213                 if (!(initargs1->flags & CKF_OS_LOCKING_OK) &&
 214                     (initargs1->CreateMutex != NULL)) {
 215                         (void) pthread_mutex_unlock(&soft_giant_mutex);
 216                         return (CKR_CANT_LOCK);
 217                 }
 218         }
 219 
 220         /* Initialize the session list lock */
 221         if (pthread_mutex_init(&soft_sessionlist_mutex, NULL) != 0) {
 222                 (void) pthread_mutex_unlock(&soft_giant_mutex);
 223                 return (CKR_CANT_LOCK);
 224         }
 225 
 226         /*
 227          * token object related initialization
 228          */
 229         soft_slot.authenticated = 0;
 230         soft_slot.userpin_change_needed = 0;
 231         soft_slot.token_object_list = NULL;
 232         soft_slot.keystore_load_status = KEYSTORE_UNINITIALIZED;
 233 
 234         if ((rv = soft_init_token_session()) != CKR_OK) {
 235                 (void) pthread_mutex_destroy(&soft_sessionlist_mutex);
 236                 (void) pthread_mutex_unlock(&soft_giant_mutex);
 237                 return (rv);
 238         }
 239 
 240         /* Initialize the slot lock */
 241         if (pthread_mutex_init(&soft_slot.slot_mutex, NULL) != 0) {
 242                 (void) pthread_mutex_destroy(&soft_sessionlist_mutex);
 243                 (void) soft_destroy_token_session();
 244                 (void) pthread_mutex_unlock(&soft_giant_mutex);
 245                 return (CKR_CANT_LOCK);
 246         }
 247 
 248         /* Initialize the keystore lock */
 249         if (pthread_mutex_init(&soft_slot.keystore_mutex, NULL) != 0) {
 250                 (void) pthread_mutex_destroy(&soft_slot.slot_mutex);
 251                 (void) pthread_mutex_destroy(&soft_sessionlist_mutex);
 252                 (void) soft_destroy_token_session();
 253                 (void) pthread_mutex_unlock(&soft_giant_mutex);
 254                 return (CKR_CANT_LOCK);
 255         }
 256 
 257         /* Initialize the object_to_be_freed list */
 258         if (pthread_mutex_init(&obj_delay_freed.obj_to_be_free_mutex, NULL)
 259             != 0) {
 260                 (void) pthread_mutex_destroy(&soft_slot.keystore_mutex);
 261                 (void) pthread_mutex_destroy(&soft_slot.slot_mutex);
 262                 (void) pthread_mutex_destroy(&soft_sessionlist_mutex);
 263                 (void) soft_destroy_token_session();
 264                 (void) pthread_mutex_unlock(&soft_giant_mutex);
 265                 return (CKR_CANT_LOCK);
 266         }
 267         obj_delay_freed.count = 0;
 268         obj_delay_freed.first = NULL;
 269         obj_delay_freed.last = NULL;
 270 
 271         if (pthread_mutex_init(&ses_delay_freed.ses_to_be_free_mutex, NULL)
 272             != 0) {
 273                 (void) pthread_mutex_destroy(
 274                     &obj_delay_freed.obj_to_be_free_mutex);
 275                 (void) pthread_mutex_destroy(&soft_slot.keystore_mutex);
 276                 (void) pthread_mutex_destroy(&soft_slot.slot_mutex);
 277                 (void) pthread_mutex_destroy(&soft_sessionlist_mutex);
 278                 (void) soft_destroy_token_session();
 279                 (void) pthread_mutex_unlock(&soft_giant_mutex);
 280                 return (CKR_CANT_LOCK);
 281         }
 282         ses_delay_freed.count = 0;
 283         ses_delay_freed.first = NULL;
 284         ses_delay_freed.last = NULL;
 285 
 286         if (rv != CKR_OK) {
 287                 (void) pthread_mutex_destroy(
 288                     &ses_delay_freed.ses_to_be_free_mutex);
 289                 (void) pthread_mutex_destroy(
 290                     &obj_delay_freed.obj_to_be_free_mutex);
 291                 (void) pthread_mutex_destroy(&soft_slot.keystore_mutex);
 292                 (void) pthread_mutex_destroy(&soft_slot.slot_mutex);
 293                 (void) pthread_mutex_destroy(&soft_sessionlist_mutex);
 294                 (void) soft_destroy_token_session();
 295                 (void) pthread_mutex_unlock(&soft_giant_mutex);
 296                 return (CKR_FUNCTION_FAILED);
 297         }
 298 
 299         softtoken_pid = initialize_pid;
 300         softtoken_initialized = B_TRUE;
 301         (void) pthread_mutex_unlock(&soft_giant_mutex);
 302 
 303         return (CKR_OK);
 304 }
 305 
 306 /*
 307  * C_Finalize is a wrapper around finalize_common. The
 308  * soft_giant_mutex should be locked by C_Finalize().
 309  */
 310 CK_RV
 311 C_Finalize(CK_VOID_PTR pReserved)
 312 {
 313 
 314         CK_RV rv;
 315 
 316         (void) pthread_mutex_lock(&soft_giant_mutex);
 317 
 318         rv = finalize_common(B_FALSE, pReserved);
 319 
 320         (void) pthread_mutex_unlock(&soft_giant_mutex);
 321 
 322         return (rv);
 323 
 324 }
 325 
 326 /*
 327  * finalize_common() does the work for C_Finalize.  soft_giant_mutex
 328  * must be held before calling this function.
 329  */
 330 static CK_RV
 331 finalize_common(boolean_t force, CK_VOID_PTR pReserved) {
 332 
 333         CK_RV rv = CKR_OK;
 334         struct object *delay_free_obj, *tmpo;
 335         struct session *delay_free_ses, *tmps;
 336 
 337         if (!softtoken_initialized) {
 338                 return (CKR_CRYPTOKI_NOT_INITIALIZED);
 339         }
 340 
 341         /* Check to see if pReseved is NULL */
 342         if (pReserved != NULL) {
 343                 return (CKR_ARGUMENTS_BAD);
 344         }
 345 
 346         (void) pthread_mutex_lock(&soft_sessionlist_mutex);
 347         /*
 348          * Set all_sessions_closing flag so any access to any
 349          * existing sessions will be rejected.
 350          */
 351         all_sessions_closing = 1;
 352         (void) pthread_mutex_unlock(&soft_sessionlist_mutex);
 353 
 354         /* Delete all the sessions and release the allocated resources */
 355         rv = soft_delete_all_sessions(force);
 356 
 357         (void) pthread_mutex_lock(&soft_sessionlist_mutex);
 358         /* Reset all_sessions_closing flag. */
 359         all_sessions_closing = 0;
 360         (void) pthread_mutex_unlock(&soft_sessionlist_mutex);
 361 
 362         softtoken_initialized = B_FALSE;
 363         softtoken_pid = 0;
 364 
 365         pkcs11_close_urandom();
 366         pkcs11_close_urandom_seed();
 367         pkcs11_close_random();
 368 
 369         /* Destroy the session list lock here */
 370         (void) pthread_mutex_destroy(&soft_sessionlist_mutex);
 371 
 372         /*
 373          * Destroy token object related stuffs
 374          * 1. Clean up the token object list
 375          * 2. Destroy slot mutex
 376          * 3. Destroy mutex in token_session
 377          */
 378         soft_delete_all_in_core_token_objects(ALL_TOKEN);
 379         (void) pthread_mutex_destroy(&soft_slot.slot_mutex);
 380         (void) pthread_mutex_destroy(&soft_slot.keystore_mutex);
 381         (void) soft_destroy_token_session();
 382 
 383         /*
 384          * free all entries in the delay_freed list
 385          */
 386         delay_free_obj = obj_delay_freed.first;
 387         while (delay_free_obj != NULL) {
 388                 tmpo = delay_free_obj->next;
 389                 free(delay_free_obj);
 390                 delay_free_obj = tmpo;
 391         }
 392 
 393         soft_slot.keystore_load_status = KEYSTORE_UNINITIALIZED;
 394         (void) pthread_mutex_destroy(&obj_delay_freed.obj_to_be_free_mutex);
 395 
 396         delay_free_ses = ses_delay_freed.first;
 397         while (delay_free_ses != NULL) {
 398                 tmps = delay_free_ses->next;
 399                 free(delay_free_ses);
 400                 delay_free_ses = tmps;
 401         }
 402         (void) pthread_mutex_destroy(&ses_delay_freed.ses_to_be_free_mutex);
 403 
 404         return (rv);
 405 }
 406 
 407 static void
 408 softtoken_init()
 409 {
 410         /* Children inherit parent's atfork handlers */
 411         (void) pthread_atfork(softtoken_fork_prepare,
 412             softtoken_fork_after, softtoken_fork_after);
 413 }
 414 
 415 /*
 416  * softtoken_fini() function required to make sure complete cleanup
 417  * is done if softtoken is ever unloaded without a C_Finalize() call.
 418  */
 419 static void
 420 softtoken_fini()
 421 {
 422         int rc;
 423 
 424         rc = pthread_mutex_trylock(&soft_giant_mutex);
 425         /*
 426          * Check to see if it was acquired by softtoken_fork_prepare().
 427          */
 428         if (rc == EBUSY && fork_prepared)
 429                 rc = 0;
 430 
 431         if (rc != 0) {
 432                 /*
 433                  * I don't know WHAT just happened, but it's pretty bad.  Grab
 434                  * the lock for real, even if it means deadlocking here.
 435                  */
 436                 (void) pthread_mutex_lock(&soft_giant_mutex);
 437         } /* Else we acquired the lock and life is good. */
 438 
 439         /* Only finalize if we're initialized. */
 440         if (softtoken_initialized) {
 441                 /*
 442                  * We also have to DROP all of the other locks that
 443                  * softtoken_fork_prepare did IF it was prepared, because
 444                  * finalize_common() is going to pick them right back up.
 445                  */
 446                 if (fork_prepared)
 447                         softtoken_fork_after_droplocks();
 448                 (void) finalize_common(B_TRUE, NULL_PTR);
 449                 /* ASSERT(!softtoken_initialized); */
 450         }
 451 
 452         /*
 453          * If we don't want to drop the lock, we assume softtoken_fork_after()
 454          * will get called.
 455          */
 456         if (!fork_prepared)
 457                 (void) pthread_mutex_unlock(&soft_giant_mutex);
 458 }
 459 
 460 CK_RV
 461 C_GetInfo(CK_INFO_PTR pInfo)
 462 {
 463         if (!softtoken_initialized)
 464                 return (CKR_CRYPTOKI_NOT_INITIALIZED);
 465 
 466         if (pInfo == NULL) {
 467                 return (CKR_ARGUMENTS_BAD);
 468         }
 469 
 470         /* Provide general information in the provided buffer */
 471         pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
 472         pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
 473         (void) strncpy((char *)pInfo->manufacturerID,
 474             SOFT_MANUFACTURER_ID, 32);
 475         pInfo->flags = 0;
 476         (void) strncpy((char *)pInfo->libraryDescription,
 477             LIBRARY_DESCRIPTION, 32);
 478         pInfo->libraryVersion.major = LIBRARY_VERSION_MAJOR;
 479         pInfo->libraryVersion.minor = LIBRARY_VERSION_MINOR;
 480 
 481         return (CKR_OK);
 482 }
 483 
 484 CK_RV
 485 C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
 486 {
 487         if (ppFunctionList == NULL) {
 488                 return (CKR_ARGUMENTS_BAD);
 489         }
 490 
 491         *ppFunctionList = &functionList;
 492 
 493         return (CKR_OK);
 494 }
 495 
 496 /*
 497  * PKCS#11 states that C_GetFunctionStatus should always return
 498  * CKR_FUNCTION_NOT_PARALLEL
 499  */
 500 /*ARGSUSED*/
 501 CK_RV
 502 C_GetFunctionStatus(CK_SESSION_HANDLE hSession)
 503 {
 504         return (CKR_FUNCTION_NOT_PARALLEL);
 505 }
 506 
 507 /*
 508  * PKCS#11 states that C_CancelFunction should always return
 509  * CKR_FUNCTION_NOT_PARALLEL
 510  */
 511 /*ARGSUSED*/
 512 CK_RV
 513 C_CancelFunction(CK_SESSION_HANDLE hSession)
 514 {
 515         return (CKR_FUNCTION_NOT_PARALLEL);
 516 }
 517 
 518 /*
 519  * Take out all mutexes before fork.
 520  *
 521  * Order:
 522  * 1. soft_giant_mutex
 523  * 2. soft_sessionlist_mutex
 524  * 3. soft_slot.slot_mutex
 525  * 4. soft_slot.keystore_mutex
 526  * 5. token_session mutexes via soft_acquire_all_session_mutexes()
 527  * 6. all soft_session_list mutexes via soft_acquire_all_session_mutexes()
 528  * 7. obj_delay_freed.obj_to_be_free_mutex;
 529  * 8. ses_delay_freed.ses_to_be_free_mutex
 530  */
 531 void
 532 softtoken_fork_prepare(void)
 533 {
 534         (void) pthread_mutex_lock(&soft_giant_mutex);
 535         if (softtoken_initialized) {
 536                 (void) pthread_mutex_lock(&soft_sessionlist_mutex);
 537                 (void) pthread_mutex_lock(&soft_slot.slot_mutex);
 538                 (void) pthread_mutex_lock(&soft_slot.keystore_mutex);
 539                 soft_acquire_all_session_mutexes(&token_session);
 540                 soft_acquire_all_session_mutexes(soft_session_list);
 541                 (void) pthread_mutex_lock(
 542                     &obj_delay_freed.obj_to_be_free_mutex);
 543                 (void) pthread_mutex_lock(
 544                     &ses_delay_freed.ses_to_be_free_mutex);
 545         }
 546         fork_prepared = B_TRUE;
 547 }
 548 
 549 static void
 550 softtoken_fork_after_droplocks(void)
 551 {
 552         /* ASSERT(softtoken_initialized); */
 553         (void) pthread_mutex_unlock(&ses_delay_freed.ses_to_be_free_mutex);
 554         (void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex);
 555         soft_release_all_session_mutexes(soft_session_list);
 556         soft_release_all_session_mutexes(&token_session);
 557         (void) pthread_mutex_unlock(&soft_slot.keystore_mutex);
 558         (void) pthread_mutex_unlock(&soft_slot.slot_mutex);
 559         (void) pthread_mutex_unlock(&soft_sessionlist_mutex);
 560 }
 561 
 562 /*
 563  * Release in opposite order to softtoken_fork_prepare().
 564  * Function is used for parent and child.
 565  */
 566 void
 567 softtoken_fork_after(void)
 568 {
 569         if (softtoken_initialized)
 570                 softtoken_fork_after_droplocks();
 571         fork_prepared = B_FALSE;
 572         (void) pthread_mutex_unlock(&soft_giant_mutex);
 573 }