Diff

Differences From Artifact [f720f246a4]:

To Artifact [9baedfd1c9]:


   682    682   #  define CACKEY_DEBUG_FUNC_TAG_TO_STR(x) "DEBUG_DISABLED"
   683    683   #  define CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(x) "DEBUG_DISABLED"
   684    684   #  define CACKEY_DEBUG_FUNC_OBJID_TO_STR(x) "DEBUG_DISABLED"
   685    685   #  define CACKEY_DEBUG_FUNC_APPTYPE_TO_STR(x) "DEBUG_DISABLED"
   686    686   #  define CACKEY_DEBUG_FUNC_ATTRIBUTE_TO_STR(x) "DEBUG_DISABLED"
   687    687   #endif
   688    688   
          689  +typedef enum {
          690  +	CACKEY_ID_TYPE_CAC,
          691  +	CACKEY_ID_TYPE_PIV,
          692  +	CACKEY_ID_TYPE_CERT_ONLY
          693  +} cackey_pcsc_id_type;
          694  +
   689    695   struct cackey_pcsc_identity {
   690         -	unsigned char applet[7];
   691         -	uint16_t file;
          696  +	cackey_pcsc_id_type id_type;
   692    697   
   693    698   	size_t certificate_len;
   694    699   	unsigned char *certificate;
   695    700   
   696    701   	ssize_t keysize;
          702  +
          703  +	union {
          704  +		struct {
          705  +			unsigned char applet[7];
          706  +			uint16_t file;
          707  +		} cac;
          708  +
          709  +		struct {
          710  +			unsigned char key_id;
          711  +		} piv;
          712  +	} card;
   697    713   };
   698    714   
   699    715   struct cackey_identity {
   700    716   	struct cackey_pcsc_identity *pcsc_identity;
   701    717   
   702    718   	CK_ATTRIBUTE *attributes;
   703    719   	CK_ULONG attributes_count;
................................................................................
  1685   1701    *     None
  1686   1702    *
  1687   1703    */
  1688   1704   static ssize_t cackey_get_data(struct cackey_slot *slot, unsigned char *buffer, size_t count, unsigned char oid[3]) {
  1689   1705   	unsigned char *buffer_p;
  1690   1706   	size_t init_count;
  1691   1707   
  1692         -	size_t offset = 0, max_offset, max_count, size;
         1708  +	size_t offset = 0, size;
  1693   1709   	unsigned char cmd[] = {0x5C, 0x03, 0x00, 0x00, 0x00};
  1694   1710   	uint16_t respcode;
  1695   1711   	int send_ret;
  1696   1712   	int idx;
  1697   1713   
  1698   1714   	CACKEY_DEBUG_PRINTF("Called.");
  1699   1715   
  1700   1716   	init_count = count;
  1701   1717   
  1702         -	max_offset = count;
  1703         -	max_count = CACKEY_APDU_MTU;
  1704         -
  1705   1718   	cmd[2] = oid[0];
  1706   1719   	cmd[3] = oid[1];
  1707   1720   	cmd[4] = oid[2];
  1708   1721   
  1709   1722   	/* 256 to indicate the largest message size -- not clear if this will work with all messages */
  1710   1723   	send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, NISTSP800_73_3_INSTR_GET_DATA, 0x3F, 0xFF, sizeof(cmd), cmd, 256, &respcode, buffer, &count);
  1711   1724   
................................................................................
  2275   2288   	}
  2276   2289   
  2277   2290   	if (dest == NULL) {
  2278   2291   		dest = malloc(sizeof(*dest) * count);
  2279   2292   	}
  2280   2293   
  2281   2294   	for (idx = 0; idx < count; idx++) {
  2282         -		memcpy(dest[idx].applet, start[idx].applet, sizeof(dest[idx].applet));
  2283         -		dest[idx].file = start[idx].file;
         2295  +		switch (dest[idx].id_type) {
         2296  +			case CACKEY_ID_TYPE_CAC:
         2297  +				memcpy(dest[idx].card.cac.applet, start[idx].card.cac.applet, sizeof(dest[idx].card.cac.applet));
         2298  +				dest[idx].card.cac.file = start[idx].card.cac.file;
         2299  +				break;
         2300  +			case CACKEY_ID_TYPE_PIV:
         2301  +				dest[idx].card.piv.key_id = start[idx].card.piv.key_id;
         2302  +				break;
         2303  +			case CACKEY_ID_TYPE_CERT_ONLY:
         2304  +				break;
         2305  +		}
  2284   2306   		dest[idx].certificate_len = start[idx].certificate_len;
  2285   2307   		dest[idx].keysize = start[idx].keysize;
  2286   2308   
  2287   2309   		dest[idx].certificate = malloc(dest[idx].certificate_len);
  2288   2310   		memcpy(dest[idx].certificate, start[idx].certificate, dest[idx].certificate_len);
  2289   2311   	}
  2290   2312   
................................................................................
  2382   2404   		/* Try PIV application */
  2383   2405   		send_ret = cackey_select_applet(slot, piv_aid, sizeof(piv_aid));
  2384   2406   		if (send_ret == CACKEY_PCSC_S_OK) {
  2385   2407   			CACKEY_DEBUG_PRINTF("We have a PIV card -- not using the CCC, pulling pre-selected keys");
  2386   2408   
  2387   2409   			piv = 1;
  2388   2410   		} else {
  2389         -
  2390   2411   			CACKEY_DEBUG_PRINTF("Unable to select CCC Applet, returning in failure");
  2391   2412   
  2392   2413   			/* Terminate SmartCard Transaction */
  2393   2414   			cackey_end_transaction(slot);
  2394   2415   
  2395   2416   			return(NULL);
  2396   2417   		}
................................................................................
  2419   2440   				continue;
  2420   2441   			}
  2421   2442   
  2422   2443   			curr_id = &certs[outidx];
  2423   2444   			outidx++;
  2424   2445   
  2425   2446   			curr_id->keysize = -1;
  2426         -			curr_id->file = 0xFFFF;
  2427         -			curr_id->applet[0] = piv_key;
         2447  +			curr_id->id_type = CACKEY_ID_TYPE_PIV;
         2448  +			curr_id->card.piv.key_id = piv_key;
  2428   2449   
  2429   2450   			curr_id->certificate_len = read_ret;
  2430   2451   			curr_id->certificate = malloc(curr_id->certificate_len);
  2431   2452   			memcpy(curr_id->certificate, buffer + 4, curr_id->certificate_len - 4); /* XXX TODO PIV (-4 header, -5 trailer == why ?) */
  2432   2453   			curr_id->certificate_len -= 4;
  2433   2454   			curr_id->certificate_len -= 5;
  2434   2455   		}
................................................................................
  2486   2507   
  2487   2508   					continue;
  2488   2509   				}
  2489   2510   
  2490   2511   				curr_id = &certs[outidx];
  2491   2512   				outidx++;
  2492   2513   
  2493         -				memcpy(curr_id->applet, curr_aid, sizeof(curr_id->applet));
  2494         -				curr_id->file = ccc_curr->value_cardurl->objectid;
         2514  +				curr_id->id_type = CACKEY_ID_TYPE_CAC;
         2515  +				memcpy(curr_id->card.cac.applet, curr_aid, sizeof(curr_id->card.cac.applet));
         2516  +				curr_id->card.cac.file = ccc_curr->value_cardurl->objectid;
  2495   2517   				curr_id->keysize = -1;
  2496   2518   
  2497         -				CACKEY_DEBUG_PRINTF("Filling curr_id->applet (%p) with %lu bytes:", curr_id->applet, (unsigned long) sizeof(curr_id->applet));
  2498         -				CACKEY_DEBUG_PRINTBUF("VAL:", curr_id->applet, sizeof(curr_id->applet));
         2519  +				CACKEY_DEBUG_PRINTF("Filling curr_id->card.cac.applet (%p) with %lu bytes:", curr_id->card.cac.applet, (unsigned long) sizeof(curr_id->card.cac.applet));
         2520  +				CACKEY_DEBUG_PRINTBUF("VAL:", curr_id->card.cac.applet, sizeof(curr_id->card.cac.applet));
  2499   2521   
  2500   2522   				curr_id->certificate_len = app_curr->length;
  2501   2523   
  2502   2524   				curr_id->certificate = malloc(curr_id->certificate_len);
  2503   2525   				memcpy(curr_id->certificate, app_curr->value, curr_id->certificate_len);
  2504   2526   
  2505   2527   				if (outidx >= *count) {
................................................................................
  2548   2570    *     ...
  2549   2571    *
  2550   2572    * NOTES
  2551   2573    *     ...
  2552   2574    *
  2553   2575    */
  2554   2576   static ssize_t cackey_signdecrypt(struct cackey_slot *slot, struct cackey_identity *identity, unsigned char *buf, size_t buflen, unsigned char *outbuf, size_t outbuflen, int padInput, int unpadOutput) {
         2577  +	cackey_pcsc_id_type id_type;
  2555   2578   	unsigned char dyn_auth_template[10];
  2556   2579   	unsigned char *tmpbuf, *tmpbuf_s, *outbuf_s;
  2557   2580   	unsigned char bytes_to_send, p1, class;
  2558   2581   	unsigned char blocktype;
  2559   2582   	cackey_ret send_ret;
  2560   2583   	uint16_t respcode;
  2561   2584   	ssize_t retval = 0, unpadoffset;
  2562   2585   	size_t tmpbuflen, padlen, tmpoutbuflen;
  2563   2586   	int free_tmpbuf = 0;
  2564   2587   	int le;
  2565         -	int piv;
  2566   2588   
  2567   2589   	CACKEY_DEBUG_PRINTF("Called.");
  2568   2590   
  2569   2591   	if (slot == NULL) {
  2570   2592   		CACKEY_DEBUG_PRINTF("Error.  slot is NULL");
  2571   2593   
  2572   2594   		return(-1);
................................................................................
  2591   2613   	}
  2592   2614   
  2593   2615   	if (identity->pcsc_identity == NULL) {
  2594   2616   		CACKEY_DEBUG_PRINTF("Error.  identity->pcsc_identity is NULL");
  2595   2617   
  2596   2618   		return(-1);
  2597   2619   	}
         2620  +
         2621  +	id_type = identity->pcsc_identity->id_type;
         2622  +	if (id_type == CACKEY_ID_TYPE_CERT_ONLY) {
         2623  +		CACKEY_DEBUG_PRINTF("Error.  identity->pcsc_identity is CACKEY_ID_TYPE_CERT_ONLY, which cannot be used for sign/decrypt");
         2624  +
         2625  +		return(-1);
         2626  +	}
         2627  +
         2628  +	switch (id_type) {
         2629  +		case CACKEY_ID_TYPE_PIV:
         2630  +		case CACKEY_ID_TYPE_CAC:
         2631  +			break;
         2632  +		default:
         2633  +			CACKEY_DEBUG_PRINTF("Error.  identity->pcsc_identity is not a supported value.");
         2634  +
         2635  +			return(-1);
         2636  +	}
  2598   2637   
  2599   2638   	/* Determine identity Key size */
  2600   2639   	if (identity->pcsc_identity->keysize < 0) {
  2601   2640   		identity->pcsc_identity->keysize = x509_to_keysize(identity->pcsc_identity->certificate, identity->pcsc_identity->certificate_len);
  2602   2641   	}
  2603   2642   
  2604   2643   	/* Pad message to key size */
................................................................................
  2646   2685   		free_tmpbuf = 0;
  2647   2686   		padlen = 0;
  2648   2687   	}
  2649   2688   
  2650   2689   	/* Begin transaction */
  2651   2690   	cackey_begin_transaction(slot);
  2652   2691   
  2653         -	/* Determine type of transaction */
  2654         -	if (identity->pcsc_identity->file == 0xFFFF) {
  2655         -		piv = 1;
  2656         -	} else {
  2657         -		piv = 0;
  2658         -	}
  2659         -
  2660   2692   	/* Select correct applet */
  2661         -	if (!piv) {
  2662         -		CACKEY_DEBUG_PRINTF("Selecting applet found at %p ...", identity->pcsc_identity->applet);
  2663         -		cackey_select_applet(slot, identity->pcsc_identity->applet, sizeof(identity->pcsc_identity->applet));
  2664         -
  2665         -		/* Select correct file */
  2666         -		cackey_select_file(slot, identity->pcsc_identity->file);
  2667         -	} else {
  2668         -		dyn_auth_template[0] = 0x7C;
  2669         -		dyn_auth_template[1] = 0x82;
  2670         -		dyn_auth_template[2] = ((tmpbuflen + 6) & 0xff00) >> 8;
  2671         -		dyn_auth_template[3] = (tmpbuflen + 6) & 0x00ff;
  2672         -		dyn_auth_template[4] = 0x82;
  2673         -		dyn_auth_template[5] = 0x00;
  2674         -		dyn_auth_template[6] = 0x81;
  2675         -		dyn_auth_template[7] = 0x82;
  2676         -		dyn_auth_template[8] = (tmpbuflen & 0xff00) >> 8;
  2677         -		dyn_auth_template[9] = tmpbuflen & 0x00ff;
  2678         -
  2679         -		send_ret = cackey_send_apdu(slot, 0x10, NISTSP800_73_3_INSTR_GENAUTH, NISTSP800_78_3_ALGO_RSA2048, identity->pcsc_identity->applet[0], sizeof(dyn_auth_template), dyn_auth_template, 0x00, NULL, NULL, NULL);
         2693  +	switch (id_type) {
         2694  +		case CACKEY_ID_TYPE_CAC:
         2695  +			CACKEY_DEBUG_PRINTF("Selecting applet found at %p ...", identity->pcsc_identity->card.cac.applet);
         2696  +			cackey_select_applet(slot, identity->pcsc_identity->card.cac.applet, sizeof(identity->pcsc_identity->card.cac.applet));
         2697  +
         2698  +			/* Select correct file */
         2699  +			cackey_select_file(slot, identity->pcsc_identity->card.cac.file);
         2700  +			break;
         2701  +		case CACKEY_ID_TYPE_PIV:
         2702  +			dyn_auth_template[0] = 0x7C;
         2703  +			dyn_auth_template[1] = 0x82;
         2704  +			dyn_auth_template[2] = ((tmpbuflen + 6) & 0xff00) >> 8;
         2705  +			dyn_auth_template[3] = (tmpbuflen + 6) & 0x00ff;
         2706  +			dyn_auth_template[4] = 0x82;
         2707  +			dyn_auth_template[5] = 0x00;
         2708  +			dyn_auth_template[6] = 0x81;
         2709  +			dyn_auth_template[7] = 0x82;
         2710  +			dyn_auth_template[8] = (tmpbuflen & 0xff00) >> 8;
         2711  +			dyn_auth_template[9] = tmpbuflen & 0x00ff;
         2712  +
         2713  +			send_ret = cackey_send_apdu(slot, 0x10, NISTSP800_73_3_INSTR_GENAUTH, NISTSP800_78_3_ALGO_RSA2048, identity->pcsc_identity->card.piv.key_id, sizeof(dyn_auth_template), dyn_auth_template, 0x00, NULL, NULL, NULL);
         2714  +			break;
         2715  +		case CACKEY_ID_TYPE_CERT_ONLY:
         2716  +			break;
  2680   2717   	}
  2681   2718   
  2682   2719   	tmpbuf_s = tmpbuf;
  2683   2720   	outbuf_s = outbuf;
  2684   2721   	while (tmpbuflen) {
  2685         -		if (tmpbuflen > 245) {
  2686         -			bytes_to_send = 245;
  2687         -			if (piv) {
  2688         -				class = 0x10;
  2689         -				le = 0x00;
  2690         -			} else {
  2691         -				p1 = 0x80;
  2692         -				le = 0x00;
  2693         -			}
         2722  +		tmpoutbuflen = outbuflen;
         2723  +
         2724  +		if (tmpbuflen > CACKEY_APDU_MTU) {
         2725  +			bytes_to_send = CACKEY_APDU_MTU;
  2694   2726   		} else {
  2695   2727   			bytes_to_send = tmpbuflen;
  2696         -			if (piv) {
  2697         -				class = GSCIS_CLASS_ISO7816;
  2698         -				le = 256;
  2699         -			} else {
  2700         -				p1 = 0x00;
  2701         -				le = 0x00;
  2702         -			}
  2703         -		}
  2704         -
  2705         -		tmpoutbuflen = outbuflen;
  2706         -
  2707         -		if (piv) {
  2708         -			send_ret = cackey_send_apdu(slot, class, NISTSP800_73_3_INSTR_GENAUTH, NISTSP800_78_3_ALGO_RSA2048, identity->pcsc_identity->applet[0], bytes_to_send, tmpbuf, le, &respcode, outbuf, &tmpoutbuflen);
  2709         -		} else {
  2710         -			send_ret = cackey_send_apdu(slot, GSCIS_CLASS_GLOBAL_PLATFORM, GSCIS_INSTR_SIGNDECRYPT, p1, 0x00, bytes_to_send, tmpbuf, le, &respcode, outbuf, &tmpoutbuflen);
  2711         -		}
         2728  +		}
         2729  +
         2730  +		send_ret = CACKEY_PCSC_E_GENERIC;
         2731  +		switch (id_type) {
         2732  +			case CACKEY_ID_TYPE_CAC:
         2733  +				if (tmpbuflen > CACKEY_APDU_MTU) {
         2734  +					p1 = 0x80;
         2735  +					le = 0x00;
         2736  +				} else {
         2737  +					p1 = 0x00;
         2738  +					le = 0x00;
         2739  +				}
         2740  +
         2741  +				send_ret = cackey_send_apdu(slot, GSCIS_CLASS_GLOBAL_PLATFORM, GSCIS_INSTR_SIGNDECRYPT, p1, 0x00, bytes_to_send, tmpbuf, le, &respcode, outbuf, &tmpoutbuflen);
         2742  +				break;
         2743  +			case CACKEY_ID_TYPE_PIV:
         2744  +				if (tmpbuflen > CACKEY_APDU_MTU) {
         2745  +					class = 0x10;
         2746  +					le = 0x00;
         2747  +				} else {
         2748  +					class = GSCIS_CLASS_ISO7816;
         2749  +					le = 256;
         2750  +				}
         2751  +
         2752  +				send_ret = cackey_send_apdu(slot, class, NISTSP800_73_3_INSTR_GENAUTH, NISTSP800_78_3_ALGO_RSA2048, identity->pcsc_identity->card.piv.key_id, bytes_to_send, tmpbuf, le, &respcode, outbuf, &tmpoutbuflen);
         2753  +				break;
         2754  +			case CACKEY_ID_TYPE_CERT_ONLY:
         2755  +				break;
         2756  +		}
         2757  +
  2712   2758   		if (send_ret != CACKEY_PCSC_S_OK) {
  2713   2759   			CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- returning in error.");
  2714   2760   
  2715   2761   			if (free_tmpbuf) {
  2716   2762   				if (tmpbuf_s) {
  2717   2763   					free(tmpbuf_s);
  2718   2764   				}
................................................................................
  2767   2813   
  2768   2814   		return(-1);
  2769   2815   	}
  2770   2816   #  endif
  2771   2817   #endif
  2772   2818   
  2773   2819   	/* We must remove the "7C" tag to get to the signature */
  2774         -	if (piv) {
  2775         -		if (outbuf[0] != 0x7C) {
  2776         -			CACKEY_DEBUG_PRINTF("Response from PIV for GENERATE AUTHENTICATION was not a 0x7C tag, returning in failure");
         2820  +	switch (id_type) {
         2821  +		case CACKEY_ID_TYPE_PIV:
         2822  +			if (outbuf[0] != 0x7C) {
         2823  +				CACKEY_DEBUG_PRINTF("Response from PIV for GENERATE AUTHENTICATION was not a 0x7C tag, returning in failure");
  2777   2824   
         2825  +				return(-1);
  2778   2826   
  2779         -			return(-1);
         2827  +			/* XXX TODO PIV */
         2828  +			memmove(outbuf, outbuf + 8, retval - 8);
         2829  +			retval -= 8;
  2780   2830   		}
  2781         -
  2782         -		/* XXX TODO PIV */
  2783         -		memmove(outbuf, outbuf + 8, retval - 8);
  2784         -		retval -= 8;
         2831  +		case CACKEY_ID_TYPE_CAC:
         2832  +		case CACKEY_ID_TYPE_CERT_ONLY:
         2833  +			break;
  2785   2834   	}
  2786   2835   
  2787   2836   	/* Unpad reply */
  2788   2837   	if (unpadOutput) {
  2789   2838   		if (retval < 3) {
  2790   2839   			CACKEY_DEBUG_PRINTF("Reply is too small, we are not able to unpad -- passing back and hoping for the best!");
  2791   2840