Diff

Differences From Artifact [e326e231e2]:

To Artifact [d2a004aade]:


154
155
156
157
158
159
160

161
162
163
164
165
166
167
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168







+







#define GSCIS_TAG_EXPIRE_DATE         0x53
#define GSCIS_TAG_CARD_TYPE           0x54
#define GSCIS_TAG_SECURITY_CODE       0x57
#define GSCIS_TAG_CARDID_AID          0x58

/*** PIV Codes ***/
#define NISTSP800_73_3_INSTR_GET_DATA 0xCB
#define NISTSP800_73_3_INSTR_GENAUTH  0x87

/*** PKI Information - EF 7000 ***/
#define GSCIS_TAG_CERTIFICATE         0x70
#define GSCIS_TAG_CERT_ISSUE_DATE     0x71
#define GSCIS_TAG_CERT_EXPIRE_DATE    0x72

/** Applet IDs **/
1376
1377
1378
1379
1380
1381
1382
1383

1384
1385
1386
1387
1388
1389
1390
1377
1378
1379
1380
1381
1382
1383

1384
1385
1386
1387
1388
1389
1390
1391







-
+







 *     cackey_pcsc_connect() if needed.
 *
 *     It will connect to the card in the reader attached to the slot
 *     specified.  It will reconnect to the card if the connection
 *     goes away.
 *
 */
static cackey_ret cackey_send_apdu(struct cackey_slot *slot, unsigned char class, unsigned char instruction, unsigned char p1, unsigned char p2, unsigned char lc, unsigned char *data, unsigned char le, uint16_t *respcode, unsigned char *respdata, size_t *respdata_len) {
static cackey_ret cackey_send_apdu(struct cackey_slot *slot, unsigned char class, unsigned char instruction, unsigned char p1, unsigned char p2, unsigned int lc, unsigned char *data, unsigned int le, uint16_t *respcode, unsigned char *respdata, size_t *respdata_len) {
	uint8_t major_rc, minor_rc;
	size_t bytes_to_copy, tmp_respdata_len;
	LPCSCARD_IO_REQUEST pioSendPci;
	DWORD protocol;
	DWORD xmit_len, recv_len;
	LONG scard_xmit_ret, scard_reconn_ret;
	BYTE xmit_buf[1024], recv_buf[1024];
1425
1426
1427
1428
1429
1430
1431





1432


1433
1434
1435
1436
1437
1438







1439


1440
1441
1442
1443
1444
1445
1446
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452

1453
1454
1455
1456
1457
1458
1459
1460
1461







+
+
+
+
+
-
+
+






+
+
+
+
+
+
+
-
+
+







	/* Transmit */
	xmit_len = 0;
	xmit_buf[xmit_len++] = class;
	xmit_buf[xmit_len++] = instruction;
	xmit_buf[xmit_len++] = p1;
	xmit_buf[xmit_len++] = p2;
	if (data) {
		if (lc > 256) {
			xmit_buf[xmit_len++] = 0x80; /* XXX UNTESTED */
			xmit_buf[xmit_len++] = (lc & 0xff00) >> 8;
			xmit_buf[xmit_len++] = lc & 0xff;
		} else {
		xmit_buf[xmit_len++] = lc;
			xmit_buf[xmit_len++] = lc;
		}
		for (idx = 0; idx < lc; idx++) {
			xmit_buf[xmit_len++] = data[idx];
		}
	}

	if (le != 0x00) {
		if (le > 256) {
			xmit_buf[xmit_len++] = 0x80; /* XXX UNTESTED */
			xmit_buf[xmit_len++] = (le & 0xff00) >> 8;
			xmit_buf[xmit_len++] = le & 0xff;
		} else if (le == 256) {
			xmit_buf[xmit_len++] = 0x00;
		} else {
		xmit_buf[xmit_len++] = le;
			xmit_buf[xmit_len++] = le;
		}
	}

	/* Begin Smartcard Transaction */
	cackey_begin_transaction(slot);

	if (class == GSCIS_CLASS_ISO7816 && instruction == GSCIS_INSTR_VERIFY && p1 == 0x00) {
		CACKEY_DEBUG_PRINTF("Sending APDU: <<censored>>");
2281
2282
2283
2284
2285
2286
2287
2288

2289
2290
2291
2292
2293
2294
2295
2296


2297
2298
2299
2300
2301
2302
2303
2296
2297
2298
2299
2300
2301
2302

2303
2304
2305
2306
2307
2308
2309
2310

2311
2312
2313
2314
2315
2316
2317
2318
2319







-
+







-
+
+







 *     ...
 *
 */
static struct cackey_pcsc_identity *cackey_read_certs(struct cackey_slot *slot, struct cackey_pcsc_identity *certs, unsigned long *count) {
	struct cackey_pcsc_identity *curr_id;
	struct cackey_tlv_entity *ccc_tlv, *ccc_curr, *app_tlv, *app_curr;
	unsigned char ccc_aid[] = {GSCIS_AID_CCC}, piv_aid[] = {NISTSP800_73_3_PIV_AID};
	unsigned char piv_oid_pivauth[] = {NISTSP800_73_3_OID_PIVAUTH};
	unsigned char *piv_oid, piv_oid_pivauth[] = {NISTSP800_73_3_OID_PIVAUTH}, piv_oid_signature[] = {NISTSP800_73_3_OID_SIGNATURE}, piv_oid_keymgt[] = {NISTSP800_73_3_OID_KEYMGT};
	unsigned char curr_aid[7];
	unsigned char buffer[8192];
	unsigned long outidx = 0;
	cackey_ret transaction_ret;
	ssize_t read_ret;
	int certs_resizable;
	int send_ret, select_ret;
	int piv = 0;
	int piv_key, piv = 0;
	int idx;

	CACKEY_DEBUG_PRINTF("Called.");

	if (count == NULL) {
		CACKEY_DEBUG_PRINTF("count is NULL, returning in failure");

		return(NULL);
2368
2369
2370
2371
2372
2373
2374
















2375

2376




2377
2378


2379
2380
2381
2382



2383
2384
2385
2386






2387
2388
2389
2390
2391
2392
2393
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406

2407
2408
2409
2410
2411
2412


2413
2414
2415



2416
2417
2418
2419



2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+

+
+
+
+
-
-
+
+

-
-
-
+
+
+

-
-
-
+
+
+
+
+
+







			cackey_end_transaction(slot);

			return(NULL);
		}
	}

	if (piv) {
		for (idx = 0; idx < 3; idx++) {
			switch (idx) {
				case 0:
					piv_oid = piv_oid_pivauth;
					piv_key = NISTSP800_78_3_KEY_PIVAUTH;
					break;
				case 1:
					piv_oid = piv_oid_signature;
					piv_key = NISTSP800_78_3_KEY_SIGNATURE;
					break;
				case 2:
					piv_oid = piv_oid_keymgt;
					piv_key = NISTSP800_78_3_KEY_KEYMGT;
					break;
			}

		read_ret = cackey_get_data(slot, buffer, sizeof(buffer), piv_oid_pivauth);
			read_ret = cackey_get_data(slot, buffer, sizeof(buffer), piv_oid);

			if (read_ret <= 0) {
				continue;
			}

		curr_id = &certs[outidx];
		outidx++;
			curr_id = &certs[outidx];
			outidx++;

		curr_id->keysize = -1;
		curr_id->file = 0xFFFF;
		curr_id->applet[0] = NISTSP800_78_3_KEY_PIVAUTH;
			curr_id->keysize = -1;
			curr_id->file = 0xFFFF;
			curr_id->applet[0] = piv_key;

		curr_id->certificate_len = read_ret;
		curr_id->certificate = malloc(curr_id->certificate_len);
		memcpy(curr_id->certificate, buffer + 4, curr_id->certificate_len - 4); /* XXX TODO PIV */
			curr_id->certificate_len = read_ret;
			curr_id->certificate = malloc(curr_id->certificate_len);
			memcpy(curr_id->certificate, buffer + 4, curr_id->certificate_len - 4); /* XXX TODO PIV (-4 header, -5 trailer == why ?) */
			curr_id->certificate_len -= 4;
			curr_id->certificate_len -= 5;
		}
	} else {
		/* Read all the applets from the CCC's TLV */
		ccc_tlv = cackey_read_tlv(slot);

		/* Look for CARDURLs that coorespond to PKI applets */
		for (ccc_curr = ccc_tlv; ccc_curr; ccc_curr = ccc_curr->_next) {
			CACKEY_DEBUG_PRINTF("Found tag: %s ... ", CACKEY_DEBUG_FUNC_TAG_TO_STR(ccc_curr->tag));
2500
2501
2502
2503
2504
2505
2506

2507
2508

2509
2510
2511
2512
2513
2514
2515
2539
2540
2541
2542
2543
2544
2545
2546
2547

2548
2549
2550
2551
2552
2553
2554
2555







+

-
+







 *     ...
 *
 * NOTES
 *     ...
 *
 */
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) {
	unsigned char dyn_auth_template[10];
	unsigned char *tmpbuf, *tmpbuf_s, *outbuf_s;
	unsigned char bytes_to_send, p1;
	unsigned char bytes_to_send, p1, class;
	unsigned char blocktype;
	cackey_ret send_ret;
	uint16_t respcode;
	ssize_t retval = 0, unpadoffset;
	size_t tmpbuflen, padlen, tmpoutbuflen;
	int free_tmpbuf = 0;
	int le;
2597
2598
2599
2600
2601
2602
2603
2604

2605
2606
2607
2608
2609
2610

2611

2612
2613
2614
2615
2616
2617
2618
2619
2620











2621



2622
2623
2624
2625
2626









2627
2628

2629
2630






2631
2632
2633
2634
2635



2636



2637

2638
2639


2640
2641
2642
2643
2644
2645





2646
2647
2648


2649
2650
2651


2652
2653
2654


2655
2656
2657


2658
2659
2660


2661
2662

2663
2664
2665


2666
2667
2668


2669
2670
2671


2672
2673
2674
2675



2676
2677
2678
2679
2680
2681
2682
2683
2637
2638
2639
2640
2641
2642
2643

2644
2645
2646
2647
2648
2649
2650
2651

2652




2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672





2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684


2685
2686
2687
2688
2689
2690
2691
2692
2693


2694
2695
2696
2697
2698
2699
2700
2701
2702


2703
2704
2705





2706
2707
2708
2709
2710
2711


2712
2713
2714


2715
2716
2717


2718
2719
2720


2721
2722
2723


2724
2725
2726

2727
2728


2729
2730
2731


2732
2733
2734


2735
2736
2737



2738
2739
2740

2741
2742
2743
2744
2745
2746
2747







-
+






+
-
+
-
-
-
-





+
+
+
+
+
+
+
+
+
+
+

+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+


+
-
-
+
+
+
+
+
+



-
-
+
+
+

+
+
+

+
-
-
+
+

-
-
-
-
-
+
+
+
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
-
+
+
+
-







		free_tmpbuf = 0;
		padlen = 0;
	}

	/* Begin transaction */
	cackey_begin_transaction(slot);

	/* Select correct applet */
	/* Determine type of transaction */
	if (identity->pcsc_identity->file == 0xFFFF) {
		piv = 1;
	} else {
		piv = 0;
	}

	/* Select correct applet */
	if (piv) {
	if (!piv) {
		CACKEY_DEBUG_PRINTF("Sign/Decrypt not implemented XXX TODO PIV");
		cackey_end_transaction(slot);
		return(-1);
	} else {
		CACKEY_DEBUG_PRINTF("Selecting applet found at %p ...", identity->pcsc_identity->applet);
		cackey_select_applet(slot, identity->pcsc_identity->applet, sizeof(identity->pcsc_identity->applet));

		/* Select correct file */
		cackey_select_file(slot, identity->pcsc_identity->file);
	} else {
		dyn_auth_template[0] = 0x7C;
		dyn_auth_template[1] = 0x82;
		dyn_auth_template[2] = ((tmpbuflen + 6) & 0xff00) >> 8;
		dyn_auth_template[3] = (tmpbuflen + 6) & 0x00ff;
		dyn_auth_template[4] = 0x82;
		dyn_auth_template[5] = 0x00;
		dyn_auth_template[6] = 0x81;
		dyn_auth_template[7] = 0x82;
		dyn_auth_template[8] = (tmpbuflen & 0xff00) >> 8;
		dyn_auth_template[9] = tmpbuflen & 0x00ff;

		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);
	}

		tmpbuf_s = tmpbuf;
		outbuf_s = outbuf;
		while (tmpbuflen) {
			if (tmpbuflen > 245) {
				bytes_to_send = 245;
	tmpbuf_s = tmpbuf;
	outbuf_s = outbuf;
	while (tmpbuflen) {
		if (tmpbuflen > 245) {
			bytes_to_send = 245;
			if (piv) {
				class = 0x10;
				le = 0x00;
			} else {
				p1 = 0x80;
				le = 0x00;
			}
			} else {
				bytes_to_send = tmpbuflen;
		} else {
			bytes_to_send = tmpbuflen;
			if (piv) {
				class = GSCIS_CLASS_ISO7816;
				le = 256;
			} else {
				p1 = 0x00;
				le = 0x00;
			}

			tmpoutbuflen = outbuflen;
		}

		tmpoutbuflen = outbuflen;

		if (piv) {
			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);
		} else {
			send_ret = cackey_send_apdu(slot, GSCIS_CLASS_GLOBAL_PLATFORM, GSCIS_INSTR_SIGNDECRYPT, p1, 0x00, bytes_to_send, tmpbuf, le, &respcode, outbuf, &tmpoutbuflen);
		}
			if (send_ret != CACKEY_PCSC_S_OK) {
				CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- returning in error.");
		if (send_ret != CACKEY_PCSC_S_OK) {
			CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- returning in error.");

				if (free_tmpbuf) {
					if (tmpbuf_s) {
						free(tmpbuf_s);
					}
				}
			if (free_tmpbuf) {
				if (tmpbuf_s) {
					free(tmpbuf_s);
				}
			}

				/* End transaction */
				cackey_end_transaction(slot);
			/* End transaction */
			cackey_end_transaction(slot);

				if (respcode == 0x6982) {
					CACKEY_DEBUG_PRINTF("Security status not satisified.  Returning NEEDLOGIN");
			if (respcode == 0x6982) {
				CACKEY_DEBUG_PRINTF("Security status not satisified.  Returning NEEDLOGIN");

					cackey_mark_slot_reset(slot);
					slot->token_flags = CKF_LOGIN_REQUIRED;
				cackey_mark_slot_reset(slot);
				slot->token_flags = CKF_LOGIN_REQUIRED;

					return(CACKEY_PCSC_E_NEEDLOGIN);
				}
				return(CACKEY_PCSC_E_NEEDLOGIN);
			}

				if (send_ret == CACKEY_PCSC_E_TOKENABSENT) {
					CACKEY_DEBUG_PRINTF("Token absent.  Returning TOKENABSENT");
			if (send_ret == CACKEY_PCSC_E_TOKENABSENT) {
				CACKEY_DEBUG_PRINTF("Token absent.  Returning TOKENABSENT");

					cackey_mark_slot_reset(slot);
				cackey_mark_slot_reset(slot);

					return(CACKEY_PCSC_E_TOKENABSENT);
				}
				return(CACKEY_PCSC_E_TOKENABSENT);
			}

				return(-1);
			}
			return(-1);
		}

			tmpbuf += bytes_to_send;
			tmpbuflen -= bytes_to_send;
		tmpbuf += bytes_to_send;
		tmpbuflen -= bytes_to_send;

			outbuf += tmpoutbuflen;
			outbuflen -= tmpoutbuflen;
			retval += tmpoutbuflen;
		outbuf += tmpoutbuflen;
		outbuflen -= tmpoutbuflen;
		retval += tmpoutbuflen;
		}
	}

	if (free_tmpbuf) {
		if (tmpbuf_s) {
			free(tmpbuf_s);
		}
	}
2692
2693
2694
2695
2696
2697
2698














2699
2700
2701
2702
2703
2704
2705
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783







+
+
+
+
+
+
+
+
+
+
+
+
+
+







	if (outbuflen > _POSIX_SSIZE_MAX) {
		CACKEY_DEBUG_PRINTF("Outbuflen exceeds maximum value, returning in failure. (max = %li, outbuflen = %lu)", (long) _POSIX_SSIZE_MAX, (unsigned long) outbuflen);

		return(-1);
	}
#  endif
#endif

	/* We must remove the "7C" tag to get to the signature */
	if (piv) {
		if (outbuf[0] != 0x7C) {
			CACKEY_DEBUG_PRINTF("Response from PIV for GENERATE AUTHENTICATION was not a 0x7C tag, returning in failure");


			return(-1);
		}

		/* XXX TODO PIV */
		memmove(outbuf, outbuf + 8, retval - 8);
		retval -= 8;
	}

	/* Unpad reply */
	if (unpadOutput) {
		if (retval < 3) {
			CACKEY_DEBUG_PRINTF("Reply is too small, we are not able to unpad -- passing back and hoping for the best!");

			CACKEY_DEBUG_PRINTF("Returning in success, retval = %li (bytes)", (long) retval);