diff options
Diffstat (limited to 'usr/src/lib/pkcs11/pkcs11_kms/common/kmsGeneral.c')
-rw-r--r-- | usr/src/lib/pkcs11/pkcs11_kms/common/kmsGeneral.c | 548 |
1 files changed, 0 insertions, 548 deletions
diff --git a/usr/src/lib/pkcs11/pkcs11_kms/common/kmsGeneral.c b/usr/src/lib/pkcs11/pkcs11_kms/common/kmsGeneral.c deleted file mode 100644 index 192d53827f..0000000000 --- a/usr/src/lib/pkcs11/pkcs11_kms/common/kmsGeneral.c +++ /dev/null @@ -1,548 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - * - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - */ - -#include <fcntl.h> -#include <pthread.h> -#include <strings.h> -#include <unistd.h> /* for pid */ -#include <errno.h> -#include <security/cryptoki.h> - -#include "kmsKeystoreUtil.h" -#include "kmsGlobal.h" -#include "kmsSession.h" -#include "kmsSlot.h" - -/* - * PKCS#11 KMS Crypto provider module. - * - * This module provides access to a Key Management System (v 2.0) - * through the Solaris Cryptographic Framework interfaces (PKCS#11). - * - * PREREQUISITES - * ============= - * 1. You must have access to a KMS on the network and you must - * know the IP address and name of the "Agent" assigned to - * you and the passphrase needed to access the Agent information. - * - * 2. The token configuration must be completed prior - * to using this provider using the kmscfg(1m) utility. - * - * This provider provides support for 3 AES mechanisms: - * CKM_AES_KEY_GEN (for 256 bit keys only) - * CKM_AES_CBC (encrypt/decrypt) - * CKM_AES_CBC_PAD (encrypt/decrypt) - * - * DETAILS - * ======= - * Each user has their own local configuration for the KMS. - * The local configuration information is typically located - * in a private token directory - /var/tmp/kms/$USERNAME - * The location may be overridden using an environment variable - * $KMSTOKEN_DIR. The user's private token namespace is configured - * using kmscfg(1M) which establishes the directory and populates - * it with a simple configuration file that this module later uses - * to access the KMS. - * - * INITIALIZING - * ============ - * Once the token configuration is established, C_InitToken - * is used to initialize the first contact with the KMS. This - * will cause the provider to contact the KMS and download - * the profile configuration data, a server certificate, and a - * private entity key and certificate (in a PKCS#12 file). - * Once the above data is collected it is stored under $KMSTOKEN_DIR. - * The user may then proceed with normal PKCS#11 activity. - * - * LOGIN - * ===== - * The concept of a "Login" is established when the user provides - * a PIN that will successfully unwrap the private data in the - * PKCS#12 file downloaded earlier when C_InitToken was called. - * If the PKCS#12 file is successfully opened, then the user - * is considered "logged in" and may use the private key and - * certificate to initiate secure communications with the KMS. - * - * CHANGE PIN - * ========== - * The C_SetPIN interface may be used to change the passphrase - * on the PKCS#12 file and thus effectively change the passphrase - * for the token itself (even though the wrapped private key and - * certificate do not change). - * - * KEY STORAGE - * =========== - * Keys generated in the KMS are always kept securely in the KMS. - * The local token area contains only a list of CKA_LABEL values - * for all successfully created keys, no sensitive key data - * is stored on the client system. When a key is "destroyed", the - * local references to that key's label is removed and it is no - * longer visible to the token provider. - * - * NOTE: The KMS itself does not have an interface for destroying - * keys, it only allows for the keys to be disassociated from - * a particular "DataUnit". Key labels should not be re-used. - */ -#pragma init(kms_init) -#pragma fini(kms_fini) - -static struct CK_FUNCTION_LIST functionList = { - { 2, 20 }, /* version */ - C_Initialize, - C_Finalize, - C_GetInfo, - C_GetFunctionList, - C_GetSlotList, - C_GetSlotInfo, - C_GetTokenInfo, - C_GetMechanismList, - C_GetMechanismInfo, - C_InitToken, - C_InitPIN, - C_SetPIN, - C_OpenSession, - C_CloseSession, - C_CloseAllSessions, - C_GetSessionInfo, - C_GetOperationState, - C_SetOperationState, - C_Login, - C_Logout, - C_CreateObject, - C_CopyObject, - C_DestroyObject, - C_GetObjectSize, - C_GetAttributeValue, - C_SetAttributeValue, - C_FindObjectsInit, - C_FindObjects, - C_FindObjectsFinal, - C_EncryptInit, - C_Encrypt, - C_EncryptUpdate, - C_EncryptFinal, - C_DecryptInit, - C_Decrypt, - C_DecryptUpdate, - C_DecryptFinal, - C_DigestInit, - C_Digest, - C_DigestUpdate, - C_DigestKey, - C_DigestFinal, - C_SignInit, - C_Sign, - C_SignUpdate, - C_SignFinal, - C_SignRecoverInit, - C_SignRecover, - C_VerifyInit, - C_Verify, - C_VerifyUpdate, - C_VerifyFinal, - C_VerifyRecoverInit, - C_VerifyRecover, - C_DigestEncryptUpdate, - C_DecryptDigestUpdate, - C_SignEncryptUpdate, - C_DecryptVerifyUpdate, - C_GenerateKey, - C_GenerateKeyPair, - C_WrapKey, - C_UnwrapKey, - C_DeriveKey, - C_SeedRandom, - C_GenerateRandom, - C_GetFunctionStatus, - C_CancelFunction, - C_WaitForSlotEvent -}; - -boolean_t kms_initialized = B_FALSE; -static pid_t kms_pid = 0; - - -/* protects kms_initialized and entrance to C_Initialize/Finalize */ -static pthread_mutex_t globalmutex = PTHREAD_MUTEX_INITIALIZER; - -ses_to_be_freed_list_t ses_delay_freed; -object_to_be_freed_list_t obj_delay_freed; -kms_elem_t **kms_mechhash; /* Hash table for kCF mech numbers */ - -static void kms_finalize_common(); -static void kms_cleanup_library(); -static void kms_init(); -static void kms_fini(); -static void kms_fork_prepare(); -static void kms_fork_after(); - -CK_RV -C_Initialize(CK_VOID_PTR pInitArgs) -{ - int initialize_pid; - boolean_t supplied_ok; - CK_RV rv = CKR_OK; - - /* - * Grab lock to insure that only one thread enters this - * function at a time. - */ - (void) pthread_mutex_lock(&globalmutex); - initialize_pid = getpid(); - - if (kms_initialized) { - if (initialize_pid == kms_pid) { - /* - * This process has called C_Initialize already - */ - (void) pthread_mutex_unlock(&globalmutex); - return (CKR_CRYPTOKI_ALREADY_INITIALIZED); - } else { - /* - * A fork has happened and the child is - * reinitializing. Do a kms_cleanup_library to close - * out any state from the parent, and then - * continue on. - */ - kms_cleanup_library(); - } - } - - if (pInitArgs != NULL) { - CK_C_INITIALIZE_ARGS *initargs1 = - (CK_C_INITIALIZE_ARGS *) pInitArgs; - - /* pReserved must be NULL */ - if (initargs1->pReserved != NULL) { - (void) pthread_mutex_unlock(&globalmutex); - return (CKR_ARGUMENTS_BAD); - } - - /* - * ALL supplied function pointers need to have the value - * either NULL or non-NULL. - */ - supplied_ok = (initargs1->CreateMutex == NULL && - initargs1->DestroyMutex == NULL && - initargs1->LockMutex == NULL && - initargs1->UnlockMutex == NULL) || - (initargs1->CreateMutex != NULL && - initargs1->DestroyMutex != NULL && - initargs1->LockMutex != NULL && - initargs1->UnlockMutex != NULL); - - if (!supplied_ok) { - (void) pthread_mutex_unlock(&globalmutex); - return (CKR_ARGUMENTS_BAD); - } - - /* - * When the CKF_OS_LOCKING_OK flag isn't set and mutex - * function pointers are supplied by an application, - * return an error. We must be able to use our own locks. - */ - if (!(initargs1->flags & CKF_OS_LOCKING_OK) && - (initargs1->CreateMutex != NULL)) { - (void) pthread_mutex_unlock(&globalmutex); - return (CKR_CANT_LOCK); - } - } - - /* Create the hash table */ - kms_mechhash = calloc(KMECH_HASHTABLE_SIZE, sizeof (void *)); - if (kms_mechhash == NULL) { - (void) pthread_mutex_unlock(&globalmutex); - return (CKR_HOST_MEMORY); - } - - /* Initialize the slot table */ - rv = kms_slottable_init(); - if (rv != CKR_OK) { - free(kms_mechhash); - goto end; - } - - /* Initialize the object_to_be_freed list */ - (void) pthread_mutex_init(&obj_delay_freed.obj_to_be_free_mutex, NULL); - obj_delay_freed.count = 0; - obj_delay_freed.first = NULL; - obj_delay_freed.last = NULL; - - /* Initialize the session_to_be_freed list */ - (void) pthread_mutex_init(&ses_delay_freed.ses_to_be_free_mutex, NULL); - ses_delay_freed.count = 0; - ses_delay_freed.first = NULL; - ses_delay_freed.last = NULL; - - rv = KMS_Initialize(); - if (rv != CKR_OK) { - free(kms_mechhash); - goto end; - } - - kms_initialized = B_TRUE; - kms_pid = initialize_pid; - -end: - (void) pthread_mutex_unlock(&globalmutex); - - return (CKR_OK); -} - -/* - * C_Finalize is a wrapper around kms_finalize_common. The - * globalmutex should be locked by C_Finalize(). - */ -CK_RV -C_Finalize(CK_VOID_PTR pReserved) -{ - (void) pthread_mutex_lock(&globalmutex); - - if (!kms_initialized) { - (void) pthread_mutex_unlock(&globalmutex); - return (CKR_CRYPTOKI_NOT_INITIALIZED); - } - - /* Check to see if pReseved is NULL */ - if (pReserved != NULL) { - (void) pthread_mutex_unlock(&globalmutex); - return (CKR_ARGUMENTS_BAD); - } - - /* - * Delete all the sessions for each slot and release the allocated - * resources - */ - kms_delete_all_sessions(B_FALSE); - - kms_finalize_common(); - - (void) pthread_mutex_unlock(&globalmutex); - - return (CKR_OK); -} - -/* - * kms_finalize_common() does the work for C_Finalize. globalmutex - * must be held before calling this function. - */ -static void -kms_finalize_common() { - - int i; - kms_elem_t *elem, *next; - kms_object_t *delay_free_obj, *tmpo; - kms_session_t *delay_free_ses, *tmps; - - cleanup_slottable(); - /* Walk the hash table and free all entries */ - for (i = 0; i < KMECH_HASHTABLE_SIZE; i++) { - elem = kms_mechhash[i]; - while (elem != NULL) { - next = elem->knext; - free(elem); - elem = next; - } - } - - free(kms_mechhash); - - kms_mechhash = NULL; - kms_initialized = B_FALSE; - kms_pid = 0; - - /* - * free all entries in the delay_freed list - */ - delay_free_obj = obj_delay_freed.first; - while (delay_free_obj != NULL) { - tmpo = delay_free_obj->next; - free(delay_free_obj); - delay_free_obj = tmpo; - } - obj_delay_freed.count = 0; - obj_delay_freed.first = NULL; - obj_delay_freed.last = NULL; - (void) pthread_mutex_destroy(&obj_delay_freed.obj_to_be_free_mutex); - - delay_free_ses = ses_delay_freed.first; - while (delay_free_ses != NULL) { - tmps = delay_free_ses->next; - free(delay_free_ses); - delay_free_ses = tmps; - } - ses_delay_freed.count = 0; - ses_delay_freed.first = NULL; - ses_delay_freed.last = NULL; - (void) pthread_mutex_destroy(&ses_delay_freed.ses_to_be_free_mutex); -} - -/* - * This function cleans up all the resources in the library (user space only) - */ -static void -kms_cleanup_library() -{ - kms_slot_t *pslot = get_slotinfo(); - - if (pslot) - kms_cleanup_pri_objects_in_slot(pslot, NULL); - - /* - * Delete all the sessions for each slot and release the allocated - * resources from the library. The boolean argument TRUE indicates - * that we only wants to clean up the resource in the library only. - * We don't want to clean up the corresponding kernel part of - * resources, because they are used by the parent process still. - */ - kms_delete_all_sessions(B_TRUE); - - kms_finalize_common(); -} - -static void -kms_init() -{ - (void) pthread_atfork(kms_fork_prepare, kms_fork_after, - kms_fork_after); -} - -/* - * kms_fini() function required to make sure complete cleanup - * is done if pkcs11_kms is ever unloaded without - * a C_Finalize() call. - */ -static void -kms_fini() -{ - (void) pthread_mutex_lock(&globalmutex); - - (void) KMS_Finalize(); - - /* if we're not initilized, do not attempt to finalize */ - if (!kms_initialized) { - (void) pthread_mutex_unlock(&globalmutex); - return; - } - - kms_cleanup_library(); - - (void) pthread_mutex_unlock(&globalmutex); -} - -CK_RV -C_GetInfo(CK_INFO_PTR pInfo) -{ - if (!kms_initialized) - return (CKR_CRYPTOKI_NOT_INITIALIZED); - - if (pInfo == NULL) { - return (CKR_ARGUMENTS_BAD); - } - - /* Check if the cryptoki was initialized */ - pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR; - pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR; - (void) strncpy((char *)pInfo->manufacturerID, - MANUFACTURER_ID, 32); - pInfo->flags = 0; - (void) strncpy((char *)pInfo->libraryDescription, - LIBRARY_DESCRIPTION, 32); - pInfo->libraryVersion.major = LIBRARY_VERSION_MAJOR; - pInfo->libraryVersion.minor = LIBRARY_VERSION_MINOR; - - return (CKR_OK); -} - -CK_RV -C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) -{ - if (ppFunctionList == NULL) { - return (CKR_ARGUMENTS_BAD); - } - - *ppFunctionList = &functionList; - - return (CKR_OK); -} - -/* - * PKCS#11 states that C_GetFunctionStatus should always return - * CKR_FUNCTION_NOT_PARALLEL - */ -/*ARGSUSED*/ -CK_RV -C_GetFunctionStatus(CK_SESSION_HANDLE hSession) -{ - return (CKR_FUNCTION_NOT_PARALLEL); -} - -/* - * Take out all mutexes before fork. - * Order: - * 1. globalmutex - * 2. all slots mutexes (and all their sessions) via - * kms_acquire_all_slots_mutexes() - * 3. obj_delay_freed.obj_to_be_free_mutex; - * 4. ses_delay_freed.ses_to_be_free_mutex - */ -void -kms_fork_prepare() -{ - (void) pthread_mutex_lock(&globalmutex); - if (kms_initialized) { - kms_acquire_all_slots_mutexes(); - (void) pthread_mutex_lock( - &obj_delay_freed.obj_to_be_free_mutex); - (void) pthread_mutex_lock( - &ses_delay_freed.ses_to_be_free_mutex); - } -} - -/* - * Release in opposite order to kms_fork_prepare(). - * Function is used for parent and child. - */ -void -kms_fork_after() -{ - if (kms_initialized) { - (void) pthread_mutex_unlock( - &ses_delay_freed.ses_to_be_free_mutex); - (void) pthread_mutex_unlock( - &obj_delay_freed.obj_to_be_free_mutex); - kms_release_all_slots_mutexes(); - } - (void) pthread_mutex_unlock(&globalmutex); -} - -/* - * PKCS#11 states that C_CancelFunction should always return - * CKR_FUNCTION_NOT_PARALLEL - */ -/*ARGSUSED*/ -CK_RV -C_CancelFunction(CK_SESSION_HANDLE hSession) -{ - return (CKR_FUNCTION_NOT_PARALLEL); -} |