void pkcs11h_openssl_freeSession ( IN const pkcs11h_openssl_session_t openssl_session ) { CK_RV rv; _PKCS11H_ASSERT (openssl_session!=NULL); _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_openssl_freeSession - entry openssl_session=%p, count=%d", (void *)openssl_session, openssl_session->reference_count ); #if defined(ENABLE_PKCS11H_THREADING) if ((rv = _pkcs11h_threading_mutexLock(&openssl_session->reference_count_lock)) != CKR_OK) { _PKCS11H_LOG (PKCS11H_LOG_ERROR, "PKCS#11: Cannot lock mutex %ld:'%s'", rv, pkcs11h_getMessage (rv)); goto cleanup; } #endif openssl_session->reference_count--; #if defined(ENABLE_PKCS11H_THREADING) _pkcs11h_threading_mutexRelease(&openssl_session->reference_count_lock); #endif _PKCS11H_ASSERT (openssl_session->reference_count>=0); if (openssl_session->reference_count == 0) { #if defined(ENABLE_PKCS11H_THREADING) _pkcs11h_threading_mutexFree(&openssl_session->reference_count_lock); #endif if (openssl_session->cleanup_hook != NULL) { openssl_session->cleanup_hook (openssl_session->certificate); } if (openssl_session->x509 != NULL) { X509_free (openssl_session->x509); openssl_session->x509 = NULL; } if (openssl_session->certificate != NULL) { pkcs11h_certificate_freeCertificate (openssl_session->certificate); openssl_session->certificate = NULL; } _pkcs11h_mem_free ((void *)&openssl_session); } cleanup: _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_openssl_freeSession - return" ); }
CK_RV _pkcs11h_session_release ( IN const _pkcs11h_session_t session ) { #if defined(ENABLE_PKCS11H_THREADING) PKCS11H_BOOL mutex_locked = TRUE; #endif CK_RV rv = CKR_FUNCTION_FAILED; _PKCS11H_ASSERT (session!=NULL); _PKCS11H_ASSERT (session->reference_count>=0); _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: _pkcs11h_session_release entry session=%p", (void *)session ); #if defined(ENABLE_PKCS11H_THREADING) if ((rv = _pkcs11h_threading_mutexLock (&session->mutex)) != CKR_OK) { goto cleanup; } mutex_locked = TRUE; #endif /* * Never logout for now */ if (session->reference_count > 0) { session->reference_count--; } rv = CKR_OK; #if defined(ENABLE_PKCS11H_THREADING) cleanup: if (mutex_locked) { _pkcs11h_threading_mutexRelease (&session->mutex); mutex_locked = FALSE; } #endif _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: _pkcs11h_session_release return rv=%lu-'%s'", rv, pkcs11h_getMessage (rv) ); return rv; }
EVP_PKEY * pkcs11h_openssl_session_getEVP ( IN const pkcs11h_openssl_session_t openssl_session ) { X509 *x509 = NULL; EVP_PKEY *evp = NULL; EVP_PKEY *ret = NULL; _PKCS11H_ASSERT (openssl_session!=NULL); _PKCS11H_ASSERT (!openssl_session->initialized); _PKCS11H_ASSERT (openssl_session!=NULL); _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_openssl_session_getEVP - entry openssl_session=%p", (void *)openssl_session ); /* * Dup x509 so RSA will not hold session x509 */ if ((x509 = pkcs11h_openssl_session_getX509 (openssl_session)) == NULL) { _PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot get certificate object"); goto cleanup; } if ((evp = X509_get_pubkey (x509)) == NULL) { _PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot get public key"); goto cleanup; } if (0) { } #ifndef OPENSSL_NO_RSA else if (EVP_PKEY_id (evp) == EVP_PKEY_RSA) { if (!__pkcs11h_openssl_session_setRSA(openssl_session, evp)) { goto cleanup; } } #endif #ifndef OPENSSL_NO_RSA else if (EVP_PKEY_id (evp) == EVP_PKEY_DSA) { if (!__pkcs11h_openssl_session_setDSA(openssl_session, evp)) { goto cleanup; } } #endif #ifdef __ENABLE_EC else if (evp->type == EVP_PKEY_EC) { if (!__pkcs11h_openssl_session_setECDSA(openssl_session, evp)) { goto cleanup; } } #endif else { _PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Invalid public key algorithm %d", EVP_PKEY_id (evp)); goto cleanup; } #if defined(ENABLE_PKCS11H_THREADING) _pkcs11h_threading_mutexLock(&openssl_session->reference_count_lock); #endif openssl_session->reference_count++; #if defined(ENABLE_PKCS11H_THREADING) _pkcs11h_threading_mutexRelease(&openssl_session->reference_count_lock); #endif openssl_session->initialized = TRUE; ret = evp; evp = NULL; cleanup: /* * openssl objects have reference * count, so release them */ if (evp != NULL) { EVP_PKEY_free (evp); evp = NULL; } if (x509 != NULL) { X509_free (x509); x509 = NULL; } _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_openssl_session_getEVP - return ret=%p", (void *)ret ); return ret; }
CK_RV pkcs11h_plugAndPlay (void) { #if defined(ENABLE_PKCS11H_DEBUG) #if defined(_WIN32) int mypid = 0; #else pid_t mypid = getpid (); #endif #endif _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_plugAndPlay entry pid=%d", mypid ); if (_g_pkcs11h_data != NULL && _g_pkcs11h_data->initialized) { _pkcs11h_provider_t current; #if defined(ENABLE_PKCS11H_SLOTEVENT) PKCS11H_BOOL slot_event_active = FALSE; #endif #if defined(ENABLE_PKCS11H_THREADING) _pkcs11h_threading_mutexLock (&_g_pkcs11h_data->mutexes.global); #endif for ( current = _g_pkcs11h_data->providers; current != NULL; current = current->next ) { if (current->enabled) { current->f->C_Finalize (NULL); } } #if defined(ENABLE_PKCS11H_SLOTEVENT) if (_g_pkcs11h_data->slotevent.initialized) { slot_event_active = TRUE; _pkcs11h_slotevent_terminate (); } #endif for ( current = _g_pkcs11h_data->providers; current != NULL; current = current->next ) { if (current->enabled) { current->f->C_Initialize (NULL); } } #if defined(ENABLE_PKCS11H_SLOTEVENT) if (slot_event_active) { _pkcs11h_slotevent_init (); } #endif #if defined(ENABLE_PKCS11H_THREADING) _pkcs11h_threading_mutexRelease (&_g_pkcs11h_data->mutexes.global); #endif } _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_plugAndPlay return" ); return CKR_OK; }
CK_RV pkcs11h_removeProvider ( IN const char * const reference ) { #if defined(ENABLE_PKCS11H_THREADING) _pkcs11h_session_t current_session = NULL; PKCS11H_BOOL has_mutex_global = FALSE; PKCS11H_BOOL has_mutex_cache = FALSE; PKCS11H_BOOL has_mutex_session = FALSE; #endif _pkcs11h_provider_t provider = NULL; CK_RV rv = CKR_FUNCTION_FAILED; _PKCS11H_ASSERT (reference!=NULL); _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_removeProvider entry reference='%s'", reference ); _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG1, "PKCS#11: Removing provider '%s'", reference ); #if defined(ENABLE_PKCS11H_THREADING) if ((rv = _pkcs11h_threading_mutexLock (&_g_pkcs11h_data->mutexes.cache)) != CKR_OK) { goto cleanup; } has_mutex_cache = TRUE; if ((rv = _pkcs11h_threading_mutexLock (&_g_pkcs11h_data->mutexes.session)) != CKR_OK) { goto cleanup; } has_mutex_session = TRUE; if ((rv = _pkcs11h_threading_mutexLock (&_g_pkcs11h_data->mutexes.global)) != CKR_OK) { goto cleanup; } has_mutex_global = TRUE; for ( current_session = _g_pkcs11h_data->sessions; current_session != NULL; current_session = current_session->next ) { _pkcs11h_threading_mutexLock (¤t_session->mutex); } #endif provider = _g_pkcs11h_data->providers; while ( provider != NULL && strcmp (reference, provider->reference) ) { provider = provider->next; } if (provider == NULL) { rv = CKR_OBJECT_HANDLE_INVALID; goto cleanup; } provider->enabled = FALSE; provider->reference[0] = '\0'; if (provider->should_finalize) { provider->f->C_Finalize (NULL); provider->should_finalize = FALSE; } #if defined(ENABLE_PKCS11H_SLOTEVENT) _pkcs11h_slotevent_notify (); /* * Wait until manager join this thread * this happens saldom so I can poll */ while (provider->slotevent_thread != PKCS11H_THREAD_NULL) { _pkcs11h_threading_sleep (500); } #endif if (provider->f != NULL) { provider->f = NULL; } if (provider->handle != NULL) { #if defined(_WIN32) FreeLibrary (provider->handle); #else dlclose (provider->handle); #endif provider->handle = NULL; } rv = CKR_OK; cleanup: #if defined(ENABLE_PKCS11H_THREADING) for ( current_session = _g_pkcs11h_data->sessions; current_session != NULL; current_session = current_session->next ) { _pkcs11h_threading_mutexRelease (¤t_session->mutex); } if (has_mutex_cache) { _pkcs11h_threading_mutexRelease (&_g_pkcs11h_data->mutexes.cache); has_mutex_cache = FALSE; } if (has_mutex_session) { _pkcs11h_threading_mutexRelease (&_g_pkcs11h_data->mutexes.session); has_mutex_session = FALSE; } if (has_mutex_global) { _pkcs11h_threading_mutexRelease (&_g_pkcs11h_data->mutexes.global); has_mutex_global = FALSE; } #endif _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_removeProvider return rv=%lu-'%s'", rv, pkcs11h_getMessage (rv) ); return rv; }
CK_RV pkcs11h_addProvider ( IN const char * const reference, IN const char * const provider_location, IN const PKCS11H_BOOL allow_protected_auth, IN const unsigned mask_private_mode, IN const unsigned slot_event_method, IN const unsigned slot_poll_interval, IN const PKCS11H_BOOL cert_is_private ) { #if defined(ENABLE_PKCS11H_THREADING) PKCS11H_BOOL mutex_locked = FALSE; #endif #if defined(ENABLE_PKCS11H_DEBUG) #if defined(_WIN32) int mypid = 0; #else pid_t mypid = getpid (); #endif #endif #if !defined(_WIN32) void *p; #endif _pkcs11h_provider_t provider = NULL; CK_C_GetFunctionList gfl = NULL; CK_C_INITIALIZE_ARGS initargs; CK_C_INITIALIZE_ARGS_PTR pinitargs = NULL; CK_INFO info; CK_RV rv = CKR_FUNCTION_FAILED; _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL); _PKCS11H_ASSERT (_g_pkcs11h_data->initialized); _PKCS11H_ASSERT (provider_location!=NULL); /*_PKCS11H_ASSERT (szSignMode!=NULL); NOT NEEDED*/ _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_addProvider entry version='%s', pid=%d, reference='%s', provider_location='%s', allow_protected_auth=%d, mask_private_mode=%08x, cert_is_private=%d", PACKAGE_VERSION, mypid, reference, provider_location, allow_protected_auth ? 1 : 0, mask_private_mode, cert_is_private ? 1 : 0 ); _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG1, "PKCS#11: Adding provider '%s'-'%s'", reference, provider_location ); #if defined(ENABLE_PKCS11H_THREADING) if ((rv = _pkcs11h_threading_mutexLock (&_g_pkcs11h_data->mutexes.global)) != CKR_OK) { goto cleanup; } mutex_locked = TRUE; #endif if ((rv = _pkcs11h_mem_malloc ((void *)&provider, sizeof (struct _pkcs11h_provider_s))) != CKR_OK) { goto cleanup; } strncpy ( provider->reference, reference, sizeof (provider->reference)-1 ); provider->reference[sizeof (provider->reference)-1] = '\x0'; strncpy ( provider->manufacturerID, ( strlen (provider_location) < sizeof (provider->manufacturerID) ? provider_location : provider_location+strlen (provider_location)-sizeof (provider->manufacturerID)+1 ), sizeof (provider->manufacturerID)-1 ); provider->manufacturerID[sizeof (provider->manufacturerID)-1] = '\x0'; provider->allow_protected_auth = allow_protected_auth; provider->mask_private_mode = mask_private_mode; provider->slot_event_method = slot_event_method; provider->slot_poll_interval = slot_poll_interval; provider->cert_is_private = cert_is_private; #if defined(_WIN32) provider->handle = LoadLibraryA (provider_location); #else provider->handle = dlopen (provider_location, RTLD_NOW); #endif if (provider->handle == NULL) { rv = CKR_FUNCTION_FAILED; goto cleanup; } #if defined(_WIN32) gfl = (CK_C_GetFunctionList)GetProcAddress ( provider->handle, "C_GetFunctionList" ); #else /* * Make compiler happy! */ p = dlsym ( provider->handle, "C_GetFunctionList" ); memmove ( &gfl, &p, sizeof (void *) ); #endif if (gfl == NULL) { rv = CKR_FUNCTION_FAILED; goto cleanup; } if ((rv = gfl (&provider->f)) != CKR_OK) { goto cleanup; } memset(&initargs, 0, sizeof(initargs)); if ((initargs.pReserved = getenv("PKCS11H_INIT_ARGS_RESERVED")) != NULL) { pinitargs = &initargs; } if ((rv = provider->f->C_Initialize (pinitargs)) != CKR_OK) { if (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED) { rv = CKR_OK; } else { goto cleanup; } } else { provider->should_finalize = TRUE; } if ((rv = provider->f->C_GetInfo (&info)) != CKR_OK) { goto cleanup; } _pkcs11h_util_fixupFixedString ( provider->manufacturerID, (char *)info.manufacturerID, sizeof (info.manufacturerID) ); _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_addProvider Provider '%s' manufacturerID '%s'", reference, provider->manufacturerID ); provider->enabled = TRUE; if (_g_pkcs11h_data->providers == NULL) { _g_pkcs11h_data->providers = provider; } else { _pkcs11h_provider_t last = NULL; for ( last = _g_pkcs11h_data->providers; last->next != NULL; last = last->next ); last->next = provider; } provider = NULL; rv = CKR_OK; cleanup: if (provider != NULL) { if (provider->handle != NULL) { #if defined(_WIN32) FreeLibrary (provider->handle); #else dlclose (provider->handle); #endif provider->handle = NULL; } _pkcs11h_mem_free ((void *)&provider); provider = NULL; } #if defined(ENABLE_PKCS11H_THREADING) if (mutex_locked) { _pkcs11h_threading_mutexRelease (&_g_pkcs11h_data->mutexes.global); mutex_locked = FALSE; } #endif #if defined(ENABLE_PKCS11H_SLOTEVENT) _pkcs11h_slotevent_notify (); #endif _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG1, "PKCS#11: Provider '%s' added rv=%lu-'%s'", reference, rv, pkcs11h_getMessage (rv) ); _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_addProvider return rv=%lu-'%s'", rv, pkcs11h_getMessage (rv) ); return rv; }
CK_RV pkcs11h_terminate (void) { _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_terminate entry" ); if (_g_pkcs11h_data != NULL) { _pkcs11h_provider_t current_provider = NULL; _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG1, "PKCS#11: Removing providers" ); for ( current_provider = _g_pkcs11h_data->providers; current_provider != NULL; current_provider = current_provider->next ) { pkcs11h_removeProvider (current_provider->reference); } #if defined(ENABLE_PKCS11H_THREADING) _pkcs11h_threading_mutexLock (&_g_pkcs11h_data->mutexes.cache); _pkcs11h_threading_mutexLock (&_g_pkcs11h_data->mutexes.session); _pkcs11h_threading_mutexLock (&_g_pkcs11h_data->mutexes.global); #endif _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG1, "PKCS#11: Releasing sessions" ); while (_g_pkcs11h_data->sessions != NULL) { _pkcs11h_session_t current = _g_pkcs11h_data->sessions; _g_pkcs11h_data->sessions = _g_pkcs11h_data->sessions->next; #if defined(ENABLE_PKCS11H_THREADING) _pkcs11h_threading_mutexLock (¤t->mutex); #endif current->valid = FALSE; if (current->reference_count != 0) { _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG1, "PKCS#11: Warning: Found session with references" ); } if (current->token_id != NULL) { pkcs11h_token_freeTokenId (current->token_id); current->token_id = NULL; } #if defined(ENABLE_PKCS11H_CERTIFICATE) pkcs11h_certificate_freeCertificateIdList (current->cached_certs); #endif current->provider = NULL; #if defined(ENABLE_PKCS11H_THREADING) _pkcs11h_threading_mutexFree (¤t->mutex); #endif _pkcs11h_mem_free ((void *)¤t); } #if defined(ENABLE_PKCS11H_SLOTEVENT) _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG1, "PKCS#11: Terminating slotevent" ); _pkcs11h_slotevent_terminate (); #endif _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG1, "PKCS#11: Marking as uninitialized" ); _g_pkcs11h_data->initialized = FALSE; while (_g_pkcs11h_data->providers != NULL) { _pkcs11h_provider_t current = _g_pkcs11h_data->providers; _g_pkcs11h_data->providers = _g_pkcs11h_data->providers->next; _pkcs11h_mem_free ((void *)¤t); } #if defined(ENABLE_PKCS11H_THREADING) _pkcs11h_threading_mutexFree (&_g_pkcs11h_data->mutexes.global); _pkcs11h_threading_mutexFree (&_g_pkcs11h_data->mutexes.cache); _pkcs11h_threading_mutexFree (&_g_pkcs11h_data->mutexes.session); #endif _g_pkcs11h_crypto_engine.uninitialize (_g_pkcs11h_crypto_engine.global_data); _pkcs11h_mem_free ((void *)&_g_pkcs11h_data); } _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_terminate return" ); return CKR_OK; }
static CK_RV __pkcs11h_forkFixup ( IN const PKCS11H_BOOL activate_slotevent ) { #if defined(ENABLE_PKCS11H_THREADING) PKCS11H_BOOL mutex_locked = FALSE; #endif #if defined(ENABLE_PKCS11H_DEBUG) pid_t mypid = getpid (); #endif _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: __pkcs11h_forkFixup entry pid=%d, activate_slotevent=%d", mypid, activate_slotevent ? 1 : 0 ); #if !defined(ENABLE_PKCS11H_SLOTEVENT) (void)activate_slotevent; #endif if (_g_pkcs11h_data != NULL && _g_pkcs11h_data->initialized) { _pkcs11h_provider_t current; #if defined(ENABLE_PKCS11H_THREADING) if (_pkcs11h_threading_mutexLock (&_g_pkcs11h_data->mutexes.global) != CKR_OK) { goto cleanup; } mutex_locked = TRUE; #endif for ( current = _g_pkcs11h_data->providers; current != NULL; current = current->next ) { if (current->enabled) { current->f->C_Initialize (NULL); } #if defined(ENABLE_PKCS11H_SLOTEVENT) /* * After fork we have no threads... * So just initialized. */ if (_g_pkcs11h_data->slotevent.initialized) { _pkcs11h_slotevent_terminate_force (); if (activate_slotevent) { _pkcs11h_slotevent_init (); } } #endif } #if defined(ENABLE_PKCS11H_THREADING) cleanup: if (mutex_locked) { _pkcs11h_threading_mutexRelease (&_g_pkcs11h_data->mutexes.global); mutex_locked = FALSE; } #endif } _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: __pkcs11h_forkFixup return" ); return CKR_OK; }
CK_RV pkcs11h_logout (void) { _pkcs11h_session_t current_session = NULL; CK_RV rv = CKR_OK; _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_logout entry" ); if (_g_pkcs11h_data == NULL || !_g_pkcs11h_data->initialized) { goto cleanup; } for ( current_session = _g_pkcs11h_data->sessions; current_session != NULL; current_session = current_session->next ) { CK_RV _rv; #if defined(ENABLE_PKCS11H_THREADING) if ((_rv = _pkcs11h_threading_mutexLock (¤t_session->mutex)) == CKR_OK) { #else { #endif _rv = _pkcs11h_session_logout (current_session); #if defined(ENABLE_PKCS11H_THREADING) _pkcs11h_threading_mutexRelease (¤t_session->mutex); #endif } if (_rv != CKR_OK) { rv = _rv; } } cleanup: _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_logout return rv=%lu-'%s'", rv, pkcs11h_getMessage (rv) ); return rv; } /*======================================================================* * COMMON INTERNAL INTERFACE *======================================================================*/ void _pkcs11h_log ( IN const unsigned flags, IN const char * const format, IN ... ) { va_list args; _PKCS11H_ASSERT (format!=NULL); va_start (args, format); if ( _g_pkcs11h_data != NULL && _g_pkcs11h_data->initialized ) { if (__PKCS11H_MSG_LEVEL_TEST (flags)) { if (_g_pkcs11h_data->hooks.log == NULL) { __pkcs11h_hooks_default_log ( NULL, flags, format, args ); } else { _g_pkcs11h_data->hooks.log ( _g_pkcs11h_data->hooks.log_data, flags, format, args ); } } } va_end (args); }
CK_RV pkcs11h_token_enumTokenIds ( IN const unsigned method, OUT pkcs11h_token_id_list_t * const p_token_id_list ) { #if defined(ENABLE_PKCS11H_THREADING) PKCS11H_BOOL mutex_locked = FALSE; #endif pkcs11h_token_id_list_t token_id_list = NULL; _pkcs11h_provider_t current_provider; CK_RV rv = CKR_FUNCTION_FAILED; _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL); _PKCS11H_ASSERT (_g_pkcs11h_data->initialized); _PKCS11H_ASSERT (p_token_id_list!=NULL); _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_token_enumTokenIds entry method=%u, p_token_id_list=%p", method, (void *)p_token_id_list ); *p_token_id_list = NULL; #if defined(ENABLE_PKCS11H_THREADING) if ((rv = _pkcs11h_threading_mutexLock (&_g_pkcs11h_data->mutexes.global)) != CKR_OK) { goto cleanup; } mutex_locked = TRUE; #endif for ( current_provider = _g_pkcs11h_data->providers; current_provider != NULL; current_provider = current_provider->next ) { CK_SLOT_ID_PTR slots = NULL; CK_ULONG slotnum; CK_SLOT_ID slot_index; /* * Skip disabled providers */ if (!current_provider->enabled) { continue; } if ( (rv = _pkcs11h_session_getSlotList ( current_provider, CK_TRUE, &slots, &slotnum )) != CKR_OK ) { _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG1, "PKCS#11: Cannot get slot list for provider '%s' rv=%lu-'%s'", current_provider->manufacturerID, rv, pkcs11h_getMessage (rv) ); goto retry1; } for ( slot_index=0; slot_index < slotnum; slot_index++ ) { pkcs11h_token_id_list_t entry = NULL; CK_TOKEN_INFO info; if ( (rv = _pkcs11h_mem_malloc ( (void *)&entry, sizeof (struct pkcs11h_token_id_list_s) )) != CKR_OK || (rv = current_provider->f->C_GetTokenInfo ( slots[slot_index], &info )) != CKR_OK || (rv = _pkcs11h_token_getTokenId ( &info, &entry->token_id )) ) { goto retry11; } entry->next = token_id_list; token_id_list = entry; entry = NULL; rv = CKR_OK; retry11: if (entry != NULL) { pkcs11h_token_freeTokenIdList (entry); entry = NULL; } } retry1: if (slots != NULL) { _pkcs11h_mem_free ((void *)&slots); slots = NULL; } } if (method == PKCS11H_ENUM_METHOD_CACHE) { _pkcs11h_session_t session = NULL; for ( session = _g_pkcs11h_data->sessions; session != NULL; session = session->next ) { pkcs11h_token_id_list_t entry = NULL; PKCS11H_BOOL found = FALSE; for ( entry = token_id_list; entry != NULL && !found; entry = entry->next ) { if ( pkcs11h_token_sameTokenId ( session->token_id, entry->token_id ) ) { found = TRUE; } } if (!found) { entry = NULL; if ( (rv = _pkcs11h_mem_malloc ( (void *)&entry, sizeof (struct pkcs11h_token_id_list_s) )) != CKR_OK || (rv = pkcs11h_token_duplicateTokenId ( &entry->token_id, session->token_id )) != CKR_OK ) { goto retry12; } entry->next = token_id_list; token_id_list = entry; entry = NULL; retry12: if (entry != NULL) { if (entry->token_id != NULL) { pkcs11h_token_freeTokenId (entry->token_id); } _pkcs11h_mem_free ((void *)&entry); } } } } *p_token_id_list = token_id_list; token_id_list = NULL; rv = CKR_OK; cleanup: if (token_id_list != NULL) { pkcs11h_token_freeTokenIdList (token_id_list); token_id_list = NULL; } #if defined(ENABLE_PKCS11H_THREADING) if (mutex_locked) { rv = _pkcs11h_threading_mutexRelease (&_g_pkcs11h_data->mutexes.global); mutex_locked = FALSE; } #endif _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_token_enumTokenIds return rv=%lu-'%s', *p_token_id_list=%p", rv, pkcs11h_getMessage (rv), (void *)p_token_id_list ); return rv; }
CK_RV pkcs11h_token_ensureAccess ( IN const pkcs11h_token_id_t token_id, IN void * const user_data, IN const unsigned mask_prompt ) { #if defined(ENABLE_PKCS11H_THREADING) PKCS11H_BOOL mutex_locked = FALSE; #endif _pkcs11h_session_t session = NULL; CK_RV rv = CKR_FUNCTION_FAILED; CK_SLOT_ID slot; _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL); _PKCS11H_ASSERT (_g_pkcs11h_data->initialized); _PKCS11H_ASSERT (token_id!=NULL); /*_PKCS11H_ASSERT (user_data) NOT NEEDED */ _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_token_ensureAccess entry token_id=%p, user_data=%p, mask_prompt=%08x", (void *)token_id, user_data, mask_prompt ); if ( (rv = _pkcs11h_session_getSessionByTokenId ( token_id, &session )) != CKR_OK ) { goto cleanup; } #if defined(ENABLE_PKCS11H_THREADING) if ((rv = _pkcs11h_threading_mutexLock (&session->mutex)) != CKR_OK) { goto cleanup; } mutex_locked = TRUE; #endif if ( (rv = _pkcs11h_session_reset ( session, user_data, mask_prompt, &slot )) != CKR_OK ) { goto cleanup; } rv = CKR_OK; cleanup: #if defined(ENABLE_PKCS11H_THREADING) if (mutex_locked) { _pkcs11h_threading_mutexRelease (&session->mutex); mutex_locked = FALSE; } #endif if (session != NULL) { _pkcs11h_session_release (session); session = NULL; } _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_token_ensureAccess return rv=%lu-'%s'", rv, pkcs11h_getMessage (rv) ); return rv; }
CK_RV pkcs11h_token_login ( IN const pkcs11h_token_id_t token_id, IN const PKCS11H_BOOL readonly, IN const char * const pin ) { #if defined(ENABLE_PKCS11H_THREADING) PKCS11H_BOOL mutex_locked = FALSE; #endif CK_SLOT_ID slot = _PKCS11H_INVALID_SLOT_ID; CK_ULONG pin_size = 0; CK_RV rv = CKR_FUNCTION_FAILED; _pkcs11h_session_t session = NULL; _PKCS11H_ASSERT (token_id!=NULL); /*_PKCS11H_ASSERT (pin!=NULL); NOT NEEDED*/ _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_token_login entry token_id=%p, readonly=%d\n", (void *)token_id, readonly ? 1 : 0 ); if (pin != NULL) { pin_size = strlen (pin); } if ( (rv = _pkcs11h_session_getSessionByTokenId ( token_id, &session )) != CKR_OK ) { goto cleanup; } #if defined(ENABLE_PKCS11H_THREADING) if ((rv = _pkcs11h_threading_mutexLock (&session->mutex)) != CKR_OK) { goto cleanup; } mutex_locked = TRUE; #endif if ( (rv = _pkcs11h_session_logout (session)) != CKR_OK || (rv = _pkcs11h_session_reset (session, NULL, 0, &slot)) != CKR_OK || (rv = __pkcs11h_session_touch (session)) != CKR_OK || (rv = session->provider->f->C_OpenSession ( slot, ( CKF_SERIAL_SESSION | (readonly ? 0 : CKF_RW_SESSION) ), NULL_PTR, NULL_PTR, &session->session_handle )) != CKR_OK ) { goto cleanup; } if ( (rv = session->provider->f->C_Login ( session->session_handle, CKU_USER, (CK_UTF8CHAR_PTR)pin, pin_size )) != CKR_OK ) { if (rv != CKR_USER_ALREADY_LOGGED_IN) { goto cleanup; } } rv = CKR_OK; cleanup: #if defined(ENABLE_PKCS11H_THREADING) if (mutex_locked) { _pkcs11h_threading_mutexRelease (&session->mutex); mutex_locked = FALSE; } #endif if (session != NULL) { _pkcs11h_session_release (session); session = NULL; } _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_token_login return rv=%lu-'%s'", rv, pkcs11h_getMessage (rv) ); return rv; }
CK_RV pkcs11h_token_logout ( IN const pkcs11h_token_id_t token_id ) { #if defined(ENABLE_PKCS11H_THREADING) PKCS11H_BOOL mutex_locked = FALSE; #endif CK_RV rv = CKR_FUNCTION_FAILED; _pkcs11h_session_t session = NULL; _PKCS11H_ASSERT (token_id!=NULL); _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_token_logout entry token_id=%p\n", (void *)token_id ); if ( (rv = _pkcs11h_session_getSessionByTokenId ( token_id, &session )) != CKR_OK ) { goto cleanup; } #if defined(ENABLE_PKCS11H_THREADING) if ((rv = _pkcs11h_threading_mutexLock (&session->mutex)) != CKR_OK) { goto cleanup; } mutex_locked = TRUE; #endif if ( (rv = _pkcs11h_session_logout (session)) != CKR_OK ) { goto cleanup; } rv = CKR_OK; cleanup: #if defined(ENABLE_PKCS11H_THREADING) if (mutex_locked) { _pkcs11h_threading_mutexRelease (&session->mutex); mutex_locked = FALSE; } #endif if (session != NULL) { _pkcs11h_session_release (session); session = NULL; } _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_token_logout return rv=%lu-'%s'", rv, pkcs11h_getMessage (rv) ); return rv; }
CK_RV _pkcs11h_session_getSessionByTokenId ( IN const pkcs11h_token_id_t token_id, OUT _pkcs11h_session_t * const p_session ) { #if defined(ENABLE_PKCS11H_THREADING) PKCS11H_BOOL mutex_locked = FALSE; PKCS11H_BOOL have_session_mutex = FALSE; #endif _pkcs11h_session_t session = NULL; _pkcs11h_session_t current_session; CK_RV rv = CKR_FUNCTION_FAILED; _PKCS11H_ASSERT (token_id!=NULL); _PKCS11H_ASSERT (p_session!=NULL); _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: _pkcs11h_session_getSessionByTokenId entry token_id=%p, p_session=%p", (void *)token_id, (void *)p_session ); *p_session = NULL; #if defined(ENABLE_PKCS11H_THREADING) if ((rv = _pkcs11h_threading_mutexLock (&_g_pkcs11h_data->mutexes.session)) != CKR_OK) { goto cleanup; } mutex_locked = TRUE; #endif for ( current_session = _g_pkcs11h_data->sessions; current_session != NULL && session == NULL; current_session = current_session->next ) { if ( pkcs11h_token_sameTokenId ( current_session->token_id, token_id ) ) { _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG1, "PKCS#11: Using cached session" ); session = current_session; session->reference_count++; } } if (session == NULL) { _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG1, "PKCS#11: Creating a new session" ); if ( (rv = _pkcs11h_mem_malloc ( (void *)&session, sizeof (struct _pkcs11h_session_s)) ) != CKR_OK ) { goto cleanup; } session->reference_count = 1; session->session_handle = _PKCS11H_INVALID_SESSION_HANDLE; session->pin_cache_period = _g_pkcs11h_data->pin_cache_period; if ( (rv = pkcs11h_token_duplicateTokenId ( &session->token_id, token_id )) != CKR_OK ) { goto cleanup; } #if defined(ENABLE_PKCS11H_THREADING) if ((rv = _pkcs11h_threading_mutexInit (&session->mutex)) != CKR_OK) { goto cleanup; } have_session_mutex = TRUE; #endif session->valid = TRUE; session->next = _g_pkcs11h_data->sessions; _g_pkcs11h_data->sessions = session; } *p_session = session; session = NULL; rv = CKR_OK; cleanup: if (session != NULL) { #if defined(ENABLE_PKCS11H_THREADING) if (have_session_mutex) { _pkcs11h_threading_mutexFree (&session->mutex); } #endif _pkcs11h_mem_free ((void *)&session); } #if defined(ENABLE_PKCS11H_THREADING) if (mutex_locked) { _pkcs11h_threading_mutexRelease (&_g_pkcs11h_data->mutexes.session); mutex_locked = FALSE; } #endif _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: _pkcs11h_session_getSessionByTokenId return rv=%lu-'%s', *p_session=%p", rv, pkcs11h_getMessage (rv), (void *)*p_session ); return rv; }