Check-in [0c536f15c1]
Overview
Comment:Moved certificate examination to occur during search initialization

Added support for logging in via PC/SC in C_Login()

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:0c536f15c1629c78ef1e0ce3f33eb4d76a257538
User & Date: rkeene on 2010-05-12 23:58:50
Other Links: manifest | tags
Context
2010-05-13
00:03
Added missing cleanup target check-in: 374bb50b7f user: rkeene tags: trunk
2010-05-12
23:58
Moved certificate examination to occur during search initialization

Added support for logging in via PC/SC in C_Login() check-in: 0c536f15c1 user: rkeene tags: trunk

21:52
Added routines for reading certificates

Updated OpenSession to use PC/SC certificates

Comment and debugging update

Updated to read in larger chunks to improve speed check-in: 06e07b8f0d user: rkeene tags: trunk

Changes

Modified cackey.c from [80414011fe] to [cd6ed6e22a].

   504    504   	CACKEY_TLV_OBJID_CAC_PERSON        = 0x0200,
   505    505   	CACKEY_TLV_OBJID_CAC_BENEFITS      = 0x0202,
   506    506   	CACKEY_TLV_OBJID_CAC_OTHERBENEFITS = 0x0203,
   507    507   	CACKEY_TLV_OBJID_CAC_PERSONNEL     = 0x0201,
   508    508   	CACKEY_TLV_OBJID_CAC_PKICERT       = 0x02FE
   509    509   } cackey_tlv_objectid;
   510    510   
          511  +typedef enum {
          512  +	CACKEY_LOGIN_OK     = 0,
          513  +	CACKEY_LOGIN_BADPIN = -1,
          514  +	CACKEY_LOGIN_LOCKED = -2
          515  +} cackey_login_ret;
          516  +
   511    517   struct cackey_tlv_cardurl {
   512    518   	unsigned char        rid[5];
   513    519   	cackey_tlv_apptype   apptype;
   514    520   	cackey_tlv_objectid  objectid;
   515    521   	cackey_tlv_objectid  appid;
   516    522   	unsigned char        pinid;
   517    523   };
................................................................................
  1260   1266   
  1261   1267   	if (certs_resizable) {
  1262   1268   		certs = realloc(certs, sizeof(*certs) * (*count));
  1263   1269   	}
  1264   1270   
  1265   1271   	return(certs);
  1266   1272   }
         1273  +
         1274  +static int cackey_login(struct cackey_slot *slot, unsigned char *pin, unsigned long pin_len, int *tries_remaining_p) {
         1275  +	uint16_t response_code;
         1276  +	int tries_remaining;
         1277  +	int send_ret;
         1278  +
         1279  +	/* Indicate that we do not know about how many tries are remaining */
         1280  +	if (tries_remaining_p) {
         1281  +		*tries_remaining_p = -1;
         1282  +	}
         1283  +
         1284  +	/* Issue PIN Verify */
         1285  +	send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_VERIFY, 0x00, 0x00, pin_len, pin, 0x00, &response_code, NULL, NULL);
         1286  +	if (send_ret < 0) {
         1287  +		if ((response_code & 0x63C0) == 0x63C0) {
         1288  +			tries_remaining = (response_code & 0xF);
         1289  +
         1290  +			CACKEY_DEBUG_PRINTF("PIN Verification failed, %i tries remaining", tries_remaining);
         1291  +
         1292  +			if (tries_remaining_p) {
         1293  +				*tries_remaining_p = tries_remaining;
         1294  +			}
         1295  +		}
         1296  +
         1297  +		if (response_code == 0x6983) {
         1298  +			return(CACKEY_LOGIN_LOCKED);
         1299  +		} else {
         1300  +			return(CACKEY_LOGIN_BADPIN);
         1301  +		}
         1302  +	}
         1303  +
         1304  +	return(CACKEY_LOGIN_OK);
         1305  +}
  1267   1306   
  1268   1307   /* Returns 1 if a token is in the specified slot, 0 otherwise */
  1269   1308   static int cackey_token_present(struct cackey_slot *slot) {
  1270   1309   	unsigned char ccc_aid[] = {GSCIS_AID_CCC};
  1271   1310   	int send_ret;
  1272   1311   
  1273   1312   	/* Select the CCC Applet */
................................................................................
  2112   2151   
  2113   2152   	pInfo->hardwareVersion.major = (cackey_getversion() >> 16) & 0xff;
  2114   2153   	pInfo->hardwareVersion.minor = (cackey_getversion() >> 8) & 0xff;
  2115   2154   
  2116   2155   	pInfo->firmwareVersion.major = 0x00;
  2117   2156   	pInfo->firmwareVersion.minor = 0x00;
  2118   2157   
  2119         -	pInfo->flags = CKF_WRITE_PROTECTED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED;
         2158  +	pInfo->flags = CKF_WRITE_PROTECTED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED | CKF_LOGIN_REQUIRED;
  2120   2159   
  2121   2160   	pInfo->ulMaxSessionCount = (sizeof(cackey_sessions) / sizeof(cackey_sessions[0])) - 1;
  2122   2161   	pInfo->ulSessionCount = CK_UNAVAILABLE_INFORMATION;
  2123   2162   	pInfo->ulMaxRwSessionCount = 0;
  2124   2163   	pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION;
  2125   2164   	pInfo->ulMaxPinLen = 128;
  2126   2165   	pInfo->ulMinPinLen = 0;
................................................................................
  2285   2324   
  2286   2325   	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
  2287   2326   
  2288   2327   	return(CKR_FUNCTION_NOT_SUPPORTED);
  2289   2328   }
  2290   2329   
  2291   2330   CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY notify, CK_SESSION_HANDLE_PTR phSession) {
  2292         -	struct cackey_pcsc_identity *pcsc_identities;
  2293         -	struct cackey_identity *identities;
  2294         -	unsigned long idx, num_ids, id_idx, curr_id_type;
  2295         -	unsigned long num_certs, cert_idx;
         2331  +	unsigned long idx;
  2296   2332   	int mutex_retval;
  2297   2333   	int found_session = 0;
  2298   2334   
  2299   2335   	CACKEY_DEBUG_PRINTF("Called.");
  2300   2336   
  2301   2337   	if (slotID < 0 || slotID >= (sizeof(cackey_slots) / sizeof(cackey_slots[0]))) {
  2302   2338   		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), outside of valid range", slotID);
................................................................................
  2347   2383   			cackey_sessions[idx].ulDeviceError = 0;
  2348   2384   			cackey_sessions[idx].pApplication = pApplication;
  2349   2385   			cackey_sessions[idx].Notify = notify;
  2350   2386   
  2351   2387   			cackey_sessions[idx].identities = NULL;
  2352   2388   			cackey_sessions[idx].identities_count = 0;
  2353   2389   
  2354         -			pcsc_identities = cackey_read_certs(&cackey_slots[slotID], NULL, &num_certs);
  2355         -			if (pcsc_identities != NULL) {
  2356         -				/* Convert number of IDs to number of objects */
  2357         -				num_ids = (CKO_PRIVATE_KEY - CKO_CERTIFICATE + 1) * num_certs;
  2358         -
  2359         -				identities = malloc(num_ids * sizeof(*identities));
  2360         -
  2361         -				id_idx = 0;
  2362         -				for (cert_idx = 0; cert_idx < num_certs; cert_idx++) {
  2363         -					for (curr_id_type = CKO_CERTIFICATE; curr_id_type <= CKO_PRIVATE_KEY; curr_id_type++) {
  2364         -						identities[id_idx].attributes = cackey_get_attributes(curr_id_type, &pcsc_identities[cert_idx], -1, &identities[id_idx].attributes_count);
  2365         -
  2366         -						if (identities[id_idx].attributes == NULL) {
  2367         -							identities[id_idx].attributes_count = 0;
  2368         -						}
  2369         -
  2370         -						id_idx++;
  2371         -					}
  2372         -				}
  2373         -
  2374         -				cackey_sessions[idx].identities = identities;
  2375         -				cackey_sessions[idx].identities_count = num_ids;
  2376         -
  2377         -				cackey_free_certs(pcsc_identities, num_certs, 1);
  2378         -			}
  2379         -
  2380   2390   			cackey_sessions[idx].search_active = 0;
  2381   2391   
  2382   2392   			cackey_sessions[idx].sign_active = 0;
  2383   2393   
  2384   2394   			cackey_sessions[idx].decrypt_active = 0;
  2385   2395   
  2386   2396   			break;
................................................................................
  2606   2616   	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
  2607   2617   
  2608   2618   	return(CKR_FUNCTION_NOT_SUPPORTED);
  2609   2619   }
  2610   2620   
  2611   2621   CK_DEFINE_FUNCTION(CK_RV, C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) {
  2612   2622   	int mutex_retval;
         2623  +	int login_ret;
  2613   2624   
  2614   2625   	CACKEY_DEBUG_PRINTF("Called.");
  2615   2626   
  2616   2627   	if (!cackey_initialized) {
  2617   2628   		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
  2618   2629   
  2619   2630   		return(CKR_CRYPTOKI_NOT_INITIALIZED);
................................................................................
  2641   2652   	if (!cackey_sessions[hSession].active) {
  2642   2653   		cackey_mutex_unlock(cackey_biglock);
  2643   2654   
  2644   2655   		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
  2645   2656   		
  2646   2657   		return(CKR_SESSION_HANDLE_INVALID);
  2647   2658   	}
         2659  +
         2660  +	login_ret = cackey_login(&cackey_slots[cackey_sessions[hSession].slotID], pPin, ulPinLen, NULL);
         2661  +	if (login_ret != CACKEY_LOGIN_OK) {
         2662  +		cackey_mutex_unlock(cackey_biglock);
         2663  +
         2664  +		if (login_ret == CACKEY_LOGIN_LOCKED) {
         2665  +			CACKEY_DEBUG_PRINTF("Error.  Token is locked.");
         2666  +
         2667  +			return(CKR_PIN_LOCKED);
         2668  +		} else {
         2669  +			CACKEY_DEBUG_PRINTF("Error.  Invalid PIN.");
         2670  +
         2671  +			return(CKR_PIN_INCORRECT);
         2672  +		}
         2673  +	}
  2648   2674   
  2649   2675   	cackey_sessions[hSession].state = CKS_RO_USER_FUNCTIONS;
  2650   2676   
  2651   2677   	mutex_retval = cackey_mutex_unlock(cackey_biglock);
  2652   2678   	if (mutex_retval != 0) {
  2653   2679   		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
  2654   2680   
................................................................................
  2894   2920   
  2895   2921   	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
  2896   2922   
  2897   2923   	return(CKR_FUNCTION_NOT_SUPPORTED);
  2898   2924   }
  2899   2925   
  2900   2926   CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) {
         2927  +	struct cackey_pcsc_identity *pcsc_identities;
         2928  +	struct cackey_identity *identities;
         2929  +	unsigned long num_ids, id_idx, curr_id_type;
         2930  +	unsigned long num_certs, cert_idx;
  2901   2931   	int mutex_retval;
  2902   2932   
  2903   2933   	CACKEY_DEBUG_PRINTF("Called.");
  2904   2934   
  2905   2935   	if (!cackey_initialized) {
  2906   2936   		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
  2907   2937   
................................................................................
  2932   2962   	if (cackey_sessions[hSession].search_active) {
  2933   2963   		cackey_mutex_unlock(cackey_biglock);
  2934   2964   
  2935   2965   		CACKEY_DEBUG_PRINTF("Error.  Search already active.");
  2936   2966   		
  2937   2967   		return(CKR_OPERATION_ACTIVE);
  2938   2968   	}
         2969  +
         2970  +	if (cackey_sessions[hSession].identities == NULL) {
         2971  +		pcsc_identities = cackey_read_certs(&cackey_slots[cackey_sessions[hSession].slotID], NULL, &num_certs);
         2972  +		if (pcsc_identities != NULL) {
         2973  +			/* Convert number of Certs to number of objects */
         2974  +			num_ids = (CKO_PRIVATE_KEY - CKO_CERTIFICATE + 1) * num_certs;
         2975  +
         2976  +			identities = malloc(num_ids * sizeof(*identities));
         2977  +
         2978  +			id_idx = 0;
         2979  +			for (cert_idx = 0; cert_idx < num_certs; cert_idx++) {
         2980  +				for (curr_id_type = CKO_CERTIFICATE; curr_id_type <= CKO_PRIVATE_KEY; curr_id_type++) {
         2981  +					identities[id_idx].attributes = cackey_get_attributes(curr_id_type, &pcsc_identities[cert_idx], -1, &identities[id_idx].attributes_count);
         2982  +
         2983  +					if (identities[id_idx].attributes == NULL) {
         2984  +						identities[id_idx].attributes_count = 0;
         2985  +					}
         2986  +
         2987  +					id_idx++;
         2988  +				}
         2989  +			}
         2990  +
         2991  +			cackey_sessions[hSession].identities = identities;
         2992  +			cackey_sessions[hSession].identities_count = num_ids;
         2993  +
         2994  +			cackey_free_certs(pcsc_identities, num_certs, 1);
         2995  +		}
         2996  +	}
  2939   2997   
  2940   2998   	if (pTemplate != NULL) {
  2941   2999   		if (ulCount != 0) {
  2942   3000   			cackey_sessions[hSession].search_query_count = ulCount;
  2943   3001   			cackey_sessions[hSession].search_query = malloc(ulCount * sizeof(*pTemplate));
  2944   3002   
  2945   3003   			memcpy(cackey_sessions[hSession].search_query, pTemplate, ulCount * sizeof(*pTemplate));