Diff

Differences From Artifact [984e852cb7]:

To Artifact [3db9c71bd5]:


    40     40   #    include <zlib.h>
    41     41   #  endif
    42     42   #else
    43     43   #  ifdef HAVE_LIBZ
    44     44   #    undef HAVE_LIBZ
    45     45   #  endif
    46     46   #endif
           47  +#ifdef CACKEY_DEBUG_SEARCH_SPEEDTEST
           48  +#  include <sys/time.h>
           49  +#endif
    47     50   
    48     51   #define CK_PTR *
    49     52   #define CK_DEFINE_FUNCTION(returnType, name) returnType name
    50     53   #define CK_DECLARE_FUNCTION(returnType, name) returnType name
    51     54   #define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name)
    52     55   #define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name)
    53     56   #ifndef NULL_PTR
................................................................................
   726    729   	int slot_reset;
   727    730   
   728    731   	CK_FLAGS token_flags;
   729    732   
   730    733   	unsigned char *label;
   731    734   
   732    735   	DWORD protocol;
          736  +
          737  +	unsigned int cached_certs_count;
          738  +	struct cackey_pcsc_identity *cached_certs;
   733    739   };
   734    740   
   735    741   typedef enum {
   736    742   	CACKEY_TLV_APP_GENERIC = 0x01,
   737    743   	CACKEY_TLV_APP_SKI     = 0x02,
   738    744   	CACKEY_TLV_APP_PKI     = 0x04
   739    745   } cackey_tlv_apptype;
................................................................................
  2082   2088   
  2083   2089   	if (free_start) {
  2084   2090   		free(start);
  2085   2091   	}
  2086   2092   
  2087   2093   	return;
  2088   2094   }
         2095  +
         2096  +static struct cackey_pcsc_identity *cackey_copy_certs(struct cackey_pcsc_identity *dest, struct cackey_pcsc_identity *start, size_t count) {
         2097  +	size_t idx;
         2098  +
         2099  +	if (start == NULL) {
         2100  +		return(NULL);
         2101  +	}
         2102  +
         2103  +	if (dest == NULL) {
         2104  +		dest = malloc(sizeof(*dest) * count);
         2105  +	}
         2106  +
         2107  +	for (idx = 0; idx < count; idx++) {
         2108  +		memcpy(dest[idx].applet, start[idx].applet, sizeof(dest[idx].applet));
         2109  +		dest[idx].file = start[idx].file;
         2110  +		dest[idx].certificate_len = start[idx].certificate_len;
         2111  +		dest[idx].keysize = start[idx].keysize;
         2112  +
         2113  +		dest[idx].certificate = malloc(dest[idx].certificate_len);
         2114  +		memcpy(dest[idx].certificate, start[idx].certificate, dest[idx].certificate_len);
         2115  +	}
         2116  +
         2117  +	return(dest);
         2118  +}
  2089   2119   
  2090   2120   /*
  2091   2121    * SYNPOSIS
  2092   2122    *     ...
  2093   2123    *
  2094   2124    * ARGUMENTS
  2095   2125    *     ...
................................................................................
  2122   2152   	if (certs != NULL) {
  2123   2153   		if (*count == 0) {
  2124   2154   			CACKEY_DEBUG_PRINTF("Requested we return 0 objects, short-circuit");
  2125   2155   
  2126   2156   			return(certs);
  2127   2157   		}
  2128   2158   	}
         2159  +
         2160  +	if (!slot->slot_reset) {
         2161  +		if (slot->cached_certs) {
         2162  +			if (certs == NULL) {
         2163  +				certs = malloc(sizeof(*certs) * slot->cached_certs_count);
         2164  +				*count = slot->cached_certs_count;
         2165  +
         2166  +			} else {
         2167  +				if (*count > slot->cached_certs_count) {
         2168  +					*count = slot->cached_certs_count;
         2169  +				}
         2170  +			}
         2171  +
         2172  +			cackey_copy_certs(certs, slot->cached_certs, *count);
         2173  +
         2174  +			return(certs);
         2175  +		}
         2176  +	}
         2177  +
         2178  +	if (slot->cached_certs) {
         2179  +		cackey_free_certs(slot->cached_certs, slot->cached_certs_count, 1);
         2180  +
         2181  +		slot->cached_certs = NULL;
         2182  +	}
  2129   2183   
  2130   2184   	/* Begin a SmartCard transaction */
  2131   2185   	transaction_ret = cackey_begin_transaction(slot);
  2132   2186   	if (transaction_ret != CACKEY_PCSC_S_OK) {
  2133   2187   		CACKEY_DEBUG_PRINTF("Unable begin transaction, returning in failure");
  2134   2188   
  2135   2189   		return(NULL);
................................................................................
  2243   2297   	cackey_free_tlv(ccc_tlv);
  2244   2298   
  2245   2299   	*count = outidx;
  2246   2300   
  2247   2301   	if (certs_resizable) {
  2248   2302   		certs = realloc(certs, sizeof(*certs) * (*count));
  2249   2303   	}
         2304  +
         2305  +	slot->cached_certs = cackey_copy_certs(NULL, certs, *count);
         2306  +	slot->cached_certs_count = *count;
  2250   2307   
  2251   2308   	/* Terminate SmartCard Transaction */
  2252   2309   	cackey_end_transaction(slot);
  2253   2310   
  2254   2311   	return(certs);
  2255   2312   }
  2256   2313   
................................................................................
  2409   2466   				return(CACKEY_PCSC_E_NEEDLOGIN);
  2410   2467   			}
  2411   2468   
  2412   2469   			if (send_ret == CACKEY_PCSC_E_TOKENABSENT) {
  2413   2470   				CACKEY_DEBUG_PRINTF("Token absent.  Returning TOKENABSENT");
  2414   2471   
  2415   2472   				cackey_mark_slot_reset(slot);
  2416         -				slot->token_flags = CKF_LOGIN_REQUIRED;
  2417   2473   
  2418   2474   				return(CACKEY_PCSC_E_TOKENABSENT);
  2419   2475   			}
  2420   2476   
  2421   2477   			return(-1);
  2422   2478   		}
  2423   2479   
................................................................................
  3640   3696   		if (cackey_slots[idx].internal) {
  3641   3697   			continue;
  3642   3698   		}
  3643   3699   
  3644   3700   		if (cackey_slots[idx].pcsc_reader) {
  3645   3701   			free(cackey_slots[idx].pcsc_reader);
  3646   3702   		}
         3703  +
         3704  +		if (cackey_slots[idx].cached_certs) {
         3705  +			cackey_free_certs(cackey_slots[idx].cached_certs, cackey_slots[idx].cached_certs_count, 1);
         3706  +
         3707  +			cackey_slots[idx].cached_certs = NULL;
         3708  +		}
  3647   3709   	}
  3648   3710   
  3649   3711   	cackey_pcsc_disconnect();
  3650   3712   
  3651   3713   	cackey_initialized = 0;
  3652   3714   
  3653   3715   	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
................................................................................
  3692   3754   	return(CKR_OK);
  3693   3755   }
  3694   3756   
  3695   3757   /*
  3696   3758    * Process list of readers, and create mapping between reader name and slot ID
  3697   3759    */
  3698   3760   CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) {
         3761  +	static int first_call = 1;
  3699   3762   	int mutex_retval;
  3700   3763   	int pcsc_connect_ret;
  3701   3764   	CK_ULONG count, slot_count = 0, currslot, slot_idx;
  3702   3765   	char *pcsc_readers, *pcsc_readers_s, *pcsc_readers_e;
  3703   3766   	DWORD pcsc_readers_len;
  3704   3767   	LONG scard_listreaders_ret;
  3705   3768   	size_t curr_reader_len;
         3769  +	int slot_reset;
  3706   3770   
  3707   3771   	CACKEY_DEBUG_PRINTF("Called.");
  3708   3772   
  3709   3773   	if (pulCount == NULL) {
  3710   3774   		CACKEY_DEBUG_PRINTF("Error. pulCount is NULL.");
  3711   3775   
  3712   3776   		return(CKR_ARGUMENTS_BAD);
................................................................................
  3722   3786   	if (mutex_retval != 0) {
  3723   3787   		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
  3724   3788   
  3725   3789   		return(CKR_GENERAL_ERROR);
  3726   3790   	}
  3727   3791   
  3728   3792   	/* Clear list of slots */
         3793  +	slot_reset = 0;
  3729   3794   	if (pSlotList) {
  3730         -		CACKEY_DEBUG_PRINTF("Purging all slot information.");
         3795  +		if (first_call) {
         3796  +			first_call = 0;
  3731   3797   
  3732         -		/* Only update the list of slots if we are actually being supply the slot information */
  3733         -		cackey_slots_disconnect_all();
         3798  +			slot_reset = 1;
         3799  +		}
  3734   3800   
         3801  +		/* If any of the slots have been reset then purge all information and check again */
  3735   3802   		for (currslot = 0; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) {
  3736   3803   			if (cackey_slots[currslot].internal) {
  3737   3804   				continue;
  3738   3805   			}
  3739   3806   
  3740         -			if (cackey_slots[currslot].pcsc_reader) {
  3741         -				free(cackey_slots[currslot].pcsc_reader);
  3742         -
  3743         -				cackey_slots[currslot].pcsc_reader = NULL;
  3744         -			}
  3745         -
  3746         -			if (cackey_slots[currslot].label) {
  3747         -				free(cackey_slots[currslot].label);
  3748         -
  3749         -				cackey_slots[currslot].label = NULL;
  3750         -			}
  3751         -
  3752         -			cackey_slots[currslot].active = 0;
         3807  +			if (!cackey_slots[currslot].active) {
         3808  +				continue;
         3809  +			}
         3810  +
         3811  +			if (cackey_slots[currslot].slot_reset) {
         3812  +				slot_reset = 1;
         3813  +
         3814  +				break;
         3815  +			}
         3816  +		}
         3817  +
         3818  +		if (slot_reset) {
         3819  +			CACKEY_DEBUG_PRINTF("Purging all slot information.");
         3820  +
         3821  +			/* Only update the list of slots if we are actually being supply the slot information */
         3822  +			cackey_slots_disconnect_all();
         3823  +
         3824  +			for (currslot = 0; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) {
         3825  +				if (cackey_slots[currslot].internal) {
         3826  +					continue;
         3827  +				}
         3828  +
         3829  +				if (cackey_slots[currslot].pcsc_reader) {
         3830  +					free(cackey_slots[currslot].pcsc_reader);
         3831  +
         3832  +					cackey_slots[currslot].pcsc_reader = NULL;
         3833  +				}
         3834  +
         3835  +				if (cackey_slots[currslot].label) {
         3836  +					free(cackey_slots[currslot].label);
         3837  +
         3838  +					cackey_slots[currslot].label = NULL;
         3839  +				}
         3840  +
         3841  +				cackey_slots[currslot].active = 0;
         3842  +			}
         3843  +		} else {
         3844  +			
  3753   3845   		}
  3754   3846   	}
  3755   3847   
  3756   3848   	/* Determine list of readers */
  3757   3849   	pcsc_connect_ret = cackey_pcsc_connect();
  3758   3850   	if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
  3759   3851   		CACKEY_DEBUG_PRINTF("Connection to PC/SC failed, assuming no slots");
................................................................................
  3810   3902   						break;
  3811   3903   					}
  3812   3904   
  3813   3905   					CACKEY_DEBUG_PRINTF("Found reader: %s", pcsc_readers);
  3814   3906   
  3815   3907   					/* Only update the list of slots if we are actually being asked supply the slot information */
  3816   3908   					if (pSlotList) {
  3817         -						cackey_slots[currslot].active = 1;
  3818         -						cackey_slots[currslot].internal = 0;
  3819         -						cackey_slots[currslot].pcsc_reader = strdup(pcsc_readers);
  3820         -						cackey_slots[currslot].pcsc_card_connected = 0;
  3821         -						cackey_slots[currslot].transaction_depth = 0;
  3822         -						cackey_slots[currslot].transaction_need_hw_lock = 0;
  3823         -						cackey_slots[currslot].slot_reset = 1;
  3824         -						cackey_slots[currslot].token_flags = CKF_LOGIN_REQUIRED;
  3825         -						cackey_slots[currslot].label = NULL;
         3909  +						if (slot_reset) {
         3910  +							cackey_slots[currslot].active = 1;
         3911  +							cackey_slots[currslot].internal = 0;
         3912  +							cackey_slots[currslot].pcsc_reader = strdup(pcsc_readers);
         3913  +							cackey_slots[currslot].pcsc_card_connected = 0;
         3914  +							cackey_slots[currslot].transaction_depth = 0;
         3915  +							cackey_slots[currslot].transaction_need_hw_lock = 0;
         3916  +							cackey_slots[currslot].token_flags = CKF_LOGIN_REQUIRED;
         3917  +							cackey_slots[currslot].label = NULL;
  3826   3918   
  3827         -						cackey_mark_slot_reset(&cackey_slots[currslot]);
         3919  +							cackey_mark_slot_reset(&cackey_slots[currslot]);
         3920  +						}
  3828   3921   					} else {
  3829   3922   						/* Artificially increase the number of active slots by what will become active */
  3830   3923   						slot_count++;
  3831   3924   					}
  3832   3925   					currslot++;
  3833   3926   
  3834   3927   					pcsc_readers += curr_reader_len + 1;
................................................................................
  5120   5213   
  5121   5214   CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount) {
  5122   5215   	struct cackey_identity *curr_id;
  5123   5216   	CK_ATTRIBUTE *curr_attr;
  5124   5217   	CK_ULONG curr_id_idx, curr_out_id_idx, curr_attr_idx, sess_attr_idx;
  5125   5218   	CK_ULONG matched_count, prev_matched_count;
  5126   5219   	int mutex_retval;
         5220  +#ifdef CACKEY_DEBUG_SEARCH_SPEEDTEST
         5221  +	struct timeval start, end;
         5222  +	uint64_t start_int, end_int;
         5223  +#endif
  5127   5224   
  5128   5225   	CACKEY_DEBUG_PRINTF("Called.");
  5129   5226   
  5130   5227   	if (!cackey_initialized) {
  5131   5228   		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
  5132   5229   
  5133   5230   		return(CKR_CRYPTOKI_NOT_INITIALIZED);
................................................................................
  5184   5281   	if (!cackey_sessions[hSession].search_active) {
  5185   5282   		cackey_mutex_unlock(cackey_biglock);
  5186   5283   
  5187   5284   		CACKEY_DEBUG_PRINTF("Error.  Search not active.");
  5188   5285   		
  5189   5286   		return(CKR_OPERATION_NOT_INITIALIZED);
  5190   5287   	}
         5288  +
         5289  +#ifdef CACKEY_DEBUG_SEARCH_SPEEDTEST
         5290  +	gettimeofday(&start, NULL);
         5291  +#endif
  5191   5292   
  5192   5293   	curr_out_id_idx = 0;
  5193   5294   	for (curr_id_idx = cackey_sessions[hSession].search_curr_id; curr_id_idx < cackey_sessions[hSession].identities_count && ulMaxObjectCount; curr_id_idx++) {
  5194   5295   		curr_id = &cackey_sessions[hSession].identities[curr_id_idx];
  5195   5296   
  5196   5297   		CACKEY_DEBUG_PRINTF("Processing identity:%lu", (unsigned long) curr_id_idx);
  5197   5298   
................................................................................
  5229   5330   			curr_out_id_idx++;
  5230   5331   		} else {
  5231   5332   			CACKEY_DEBUG_PRINTF("  ... Not all %i (only found %i) attributes checked for found, not adding identity:%i", (int) cackey_sessions[hSession].search_query_count, (int) matched_count, (int) curr_id_idx);
  5232   5333   		}
  5233   5334   	}
  5234   5335   	cackey_sessions[hSession].search_curr_id = curr_id_idx;
  5235   5336   	*pulObjectCount = curr_out_id_idx;
         5337  +
         5338  +#ifdef CACKEY_DEBUG_SEARCH_SPEEDTEST
         5339  +	gettimeofday(&end, NULL);
         5340  +	start_int = (start.tv_sec * 1000000) + start.tv_usec;
         5341  +	end_int = (end.tv_sec * 1000000) + end.tv_usec;
         5342  +	fprintf(stderr, "Search took %lu microseconds\n", (unsigned long) (end_int - start_int));
         5343  +#endif
  5236   5344   
  5237   5345   	mutex_retval = cackey_mutex_unlock(cackey_biglock);
  5238   5346   	if (mutex_retval != 0) {
  5239   5347   		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
  5240   5348   
  5241   5349   		return(CKR_GENERAL_ERROR);
  5242   5350   	}