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 <fcntl.h> 30 #include <pthread.h> 31 #include <strings.h> 32 #include <unistd.h> /* for pid */ 33 #include <errno.h> 34 #include <security/cryptoki.h> 35 #include "kernelGlobal.h" 36 #include "kernelSession.h" 37 #include "kernelSlot.h" 38 39 #pragma fini(kernel_fini) 40 41 static struct CK_FUNCTION_LIST functionList = { 42 { 2, 20 }, /* version */ 43 C_Initialize, 44 C_Finalize, 45 C_GetInfo, 46 C_GetFunctionList, 47 C_GetSlotList, 48 C_GetSlotInfo, 49 C_GetTokenInfo, 50 C_GetMechanismList, 51 C_GetMechanismInfo, 52 C_InitToken, 53 C_InitPIN, 54 C_SetPIN, 55 C_OpenSession, 56 C_CloseSession, 57 C_CloseAllSessions, 58 C_GetSessionInfo, 59 C_GetOperationState, 60 C_SetOperationState, 61 C_Login, 62 C_Logout, 63 C_CreateObject, 64 C_CopyObject, 65 C_DestroyObject, 66 C_GetObjectSize, 67 C_GetAttributeValue, 68 C_SetAttributeValue, 69 C_FindObjectsInit, 70 C_FindObjects, 71 C_FindObjectsFinal, 72 C_EncryptInit, 73 C_Encrypt, 74 C_EncryptUpdate, 75 C_EncryptFinal, 76 C_DecryptInit, 77 C_Decrypt, 78 C_DecryptUpdate, 79 C_DecryptFinal, 80 C_DigestInit, 81 C_Digest, 82 C_DigestUpdate, 83 C_DigestKey, 84 C_DigestFinal, 85 C_SignInit, 86 C_Sign, 87 C_SignUpdate, 88 C_SignFinal, 89 C_SignRecoverInit, 90 C_SignRecover, 91 C_VerifyInit, 92 C_Verify, 93 C_VerifyUpdate, 94 C_VerifyFinal, 95 C_VerifyRecoverInit, 96 C_VerifyRecover, 97 C_DigestEncryptUpdate, 98 C_DecryptDigestUpdate, 99 C_SignEncryptUpdate, 100 C_DecryptVerifyUpdate, 101 C_GenerateKey, 102 C_GenerateKeyPair, 103 C_WrapKey, 104 C_UnwrapKey, 105 C_DeriveKey, 106 C_SeedRandom, 107 C_GenerateRandom, 108 C_GetFunctionStatus, 109 C_CancelFunction, 110 C_WaitForSlotEvent 111 }; 112 113 boolean_t kernel_initialized = B_FALSE; 114 static pid_t kernel_pid = 0; 115 116 int kernel_fd = -1; 117 118 119 /* protects kernel_initialized and entrance to C_Initialize/Finalize */ 120 static pthread_mutex_t globalmutex = PTHREAD_MUTEX_INITIALIZER; 121 122 ses_to_be_freed_list_t ses_delay_freed; 123 object_to_be_freed_list_t obj_delay_freed; 124 125 static void finalize_common(); 126 static void cleanup_library(); 127 static void kernel_fini(); 128 129 CK_RV 130 C_Initialize(CK_VOID_PTR pInitArgs) 131 { 132 133 int initialize_pid; 134 boolean_t supplied_ok; 135 CK_RV rv = CKR_OK; 136 137 /* 138 * Grab lock to insure that only one thread enters this 139 * function at a time. 140 */ 141 (void) pthread_mutex_lock(&globalmutex); 142 initialize_pid = getpid(); 143 144 if (kernel_initialized) { 145 if (initialize_pid == kernel_pid) { 146 /* 147 * This process has called C_Initialize already 148 */ 149 (void) pthread_mutex_unlock(&globalmutex); 150 return (CKR_CRYPTOKI_ALREADY_INITIALIZED); 151 } else { 152 /* 153 * A fork has happened and the child is 154 * reinitializing. Do a cleanup_library to close 155 * out any state from the parent, and then 156 * continue on. 157 */ 158 cleanup_library(); 159 } 160 } 161 162 if (pInitArgs != NULL) { 163 CK_C_INITIALIZE_ARGS *initargs1 = 164 (CK_C_INITIALIZE_ARGS *) pInitArgs; 165 166 /* pReserved must be NULL */ 167 if (initargs1->pReserved != NULL) { 168 (void) pthread_mutex_unlock(&globalmutex); 169 return (CKR_ARGUMENTS_BAD); 170 } 171 172 /* 173 * ALL supplied function pointers need to have the value 174 * either NULL or non-NULL. 175 */ 176 supplied_ok = (initargs1->CreateMutex == NULL && 177 initargs1->DestroyMutex == NULL && 178 initargs1->LockMutex == NULL && 179 initargs1->UnlockMutex == NULL) || 180 (initargs1->CreateMutex != NULL && 181 initargs1->DestroyMutex != NULL && 182 initargs1->LockMutex != NULL && 183 initargs1->UnlockMutex != NULL); 184 185 if (!supplied_ok) { 186 (void) pthread_mutex_unlock(&globalmutex); 187 return (CKR_ARGUMENTS_BAD); 188 } 189 190 /* 191 * When the CKF_OS_LOCKING_OK flag isn't set and mutex 192 * function pointers are supplied by an application, 193 * return an error. We must be able to use our own locks. 194 */ 195 if (!(initargs1->flags & CKF_OS_LOCKING_OK) && 196 (initargs1->CreateMutex != NULL)) { 197 (void) pthread_mutex_unlock(&globalmutex); 198 return (CKR_CANT_LOCK); 199 } 200 } 201 202 while ((kernel_fd = open(CRYPTO_DEVICE, O_RDWR)) < 0) { 203 if (errno != EINTR) 204 break; 205 } 206 if (kernel_fd < 0) { 207 (void) pthread_mutex_unlock(&globalmutex); 208 return (CKR_FUNCTION_FAILED); 209 } 210 211 /* Mark kernel_fd "close on exec" */ 212 (void) fcntl(kernel_fd, F_SETFD, FD_CLOEXEC); 213 214 /* Initialize the slot table */ 215 rv = kernel_slottable_init(); 216 if (rv != CKR_OK) { 217 (void) close(kernel_fd); 218 (void) pthread_mutex_unlock(&globalmutex); 219 return (rv); 220 } 221 222 /* Initialize the object_to_be_freed list */ 223 (void) pthread_mutex_init(&obj_delay_freed.obj_to_be_free_mutex, NULL); 224 obj_delay_freed.count = 0; 225 obj_delay_freed.first = NULL; 226 obj_delay_freed.last = NULL; 227 228 /* Initialize the session_to_be_freed list */ 229 (void) pthread_mutex_init(&ses_delay_freed.ses_to_be_free_mutex, NULL); 230 ses_delay_freed.count = 0; 231 ses_delay_freed.first = NULL; 232 ses_delay_freed.last = NULL; 233 234 kernel_initialized = B_TRUE; 235 kernel_pid = initialize_pid; 236 237 (void) pthread_mutex_unlock(&globalmutex); 238 239 return (CKR_OK); 240 241 } 242 243 244 /* 245 * C_Finalize is a wrapper around finalize_common. The 246 * globalmutex should be locked by C_Finalize(). 247 */ 248 CK_RV 249 C_Finalize(CK_VOID_PTR pReserved) 250 { 251 int i; 252 253 (void) pthread_mutex_lock(&globalmutex); 254 255 if (!kernel_initialized) { 256 return (CKR_CRYPTOKI_NOT_INITIALIZED); 257 } 258 259 /* Check to see if pReseved is NULL */ 260 if (pReserved != NULL) { 261 return (CKR_ARGUMENTS_BAD); 262 } 263 264 /* 265 * Delete all the sessions for each slot and release the allocated 266 * resources 267 */ 268 for (i = 0; i < slot_count; i++) { 269 kernel_delete_all_sessions(i, B_FALSE); 270 } 271 272 finalize_common(); 273 274 (void) pthread_mutex_unlock(&globalmutex); 275 276 return (CKR_OK); 277 } 278 279 /* 280 * finalize_common() does the work for C_Finalize. globalmutex 281 * must be held before calling this function. 282 */ 283 static void 284 finalize_common() { 285 286 int i; 287 kernel_object_t *delay_free_obj, *tmpo; 288 kernel_session_t *delay_free_ses, *tmps; 289 290 /* 291 * Free the resources allocated for the slot table and reset 292 * slot_count to 0. 293 */ 294 if (slot_count > 0) { 295 for (i = 0; i < slot_count; i++) { 296 (void) pthread_mutex_destroy(&slot_table[i]->sl_mutex); 297 (void) free(slot_table[i]); 298 } 299 (void) free(slot_table); 300 slot_count = 0; 301 } 302 303 /* Close CRYPTO_DEVICE */ 304 if (kernel_fd >= 0) { 305 (void) close(kernel_fd); 306 } 307 308 kernel_fd = -1; 309 kernel_initialized = B_FALSE; 310 kernel_pid = 0; 311 312 /* 313 * free all entries in the delay_freed list 314 */ 315 delay_free_obj = obj_delay_freed.first; 316 while (delay_free_obj != NULL) { 317 tmpo = delay_free_obj->next; 318 free(delay_free_obj); 319 delay_free_obj = tmpo; 320 } 321 (void) pthread_mutex_destroy(&obj_delay_freed.obj_to_be_free_mutex); 322 323 delay_free_ses = ses_delay_freed.first; 324 while (delay_free_ses != NULL) { 325 tmps = delay_free_ses->next; 326 free(delay_free_ses); 327 delay_free_ses = tmps; 328 } 329 (void) pthread_mutex_destroy(&ses_delay_freed.ses_to_be_free_mutex); 330 } 331 332 /* 333 * This function cleans up all the resources in the library (user space only) 334 */ 335 static void 336 cleanup_library() 337 { 338 int i; 339 340 /* 341 * Delete all the sessions for each slot and release the allocated 342 * resources from the library. The boolean argument TRUE indicates 343 * that we only wants to clean up the resource in the library only. 344 * We don't want to clean up the corresponding kernel part of 345 * resources, because they are used by the parent process still. 346 */ 347 348 for (i = 0; i < slot_count; i++) { 349 kernel_delete_all_sessions(i, B_TRUE); 350 } 351 352 finalize_common(); 353 } 354 355 /* 356 * kernel_fini() function required to make sure complete cleanup 357 * is done if pkcs11_kernel is ever unloaded without 358 * a C_Finalize() call. 359 */ 360 static void 361 kernel_fini() 362 { 363 364 (void) pthread_mutex_lock(&globalmutex); 365 366 /* if we're not initilized, do not attempt to finalize */ 367 if (!kernel_initialized) { 368 (void) pthread_mutex_unlock(&globalmutex); 369 return; 370 } 371 372 cleanup_library(); 373 374 (void) pthread_mutex_unlock(&globalmutex); 375 } 376 377 CK_RV 378 C_GetInfo(CK_INFO_PTR pInfo) 379 { 380 if (!kernel_initialized) 381 return (CKR_CRYPTOKI_NOT_INITIALIZED); 382 383 if (pInfo == NULL) { 384 return (CKR_ARGUMENTS_BAD); 385 } 386 387 /* Check if the cryptoki was initialized */ 388 389 pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR; 390 pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR; 391 (void) strncpy((char *)pInfo->manufacturerID, 392 MANUFACTURER_ID, 32); 393 pInfo->flags = 0; 394 (void) strncpy((char *)pInfo->libraryDescription, 395 LIBRARY_DESCRIPTION, 32); 396 pInfo->libraryVersion.major = LIBRARY_VERSION_MAJOR; 397 pInfo->libraryVersion.minor = LIBRARY_VERSION_MINOR; 398 399 return (CKR_OK); 400 } 401 402 CK_RV 403 C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) 404 { 405 if (ppFunctionList == NULL) { 406 return (CKR_ARGUMENTS_BAD); 407 } 408 409 *ppFunctionList = &functionList; 410 411 return (CKR_OK); 412 } 413 414 /* 415 * PKCS#11 states that C_GetFunctionStatus should always return 416 * CKR_FUNCTION_NOT_PARALLEL 417 */ 418 /*ARGSUSED*/ 419 CK_RV 420 C_GetFunctionStatus(CK_SESSION_HANDLE hSession) 421 { 422 return (CKR_FUNCTION_NOT_PARALLEL); 423 } 424 425 /* 426 * PKCS#11 states that C_CancelFunction should always return 427 * CKR_FUNCTION_NOT_PARALLEL 428 */ 429 /*ARGSUSED*/ 430 CK_RV 431 C_CancelFunction(CK_SESSION_HANDLE hSession) 432 { 433 return (CKR_FUNCTION_NOT_PARALLEL); 434 } 435