Beispiel #1
0
static int sda_test_pk(void)
{
	const struct emv_pk *pk = &vsdc_01;
	struct tlvdb *db;

	db = tlvdb_external(0x90, sizeof(issuer_cert), issuer_cert);
	tlvdb_add(db, tlvdb_external(0x9f32, sizeof(issuer_exp), issuer_exp));
	tlvdb_add(db, tlvdb_external(0x92, sizeof(issuer_rem), issuer_rem));

	struct emv_pk *ipk = emv_pki_recover_issuer_cert(pk, db);
	if (!ipk) {
		fprintf(stderr, "Could not recover Issuer certificate!\n");
		tlvdb_free(db);
		return 2;
	}

	tlvdb_add(db, tlvdb_external(0x93, sizeof(ssad_cr), ssad_cr));

	struct tlvdb *dacdb = emv_pki_recover_dac(ipk, db, ssd1, sizeof(ssd1));
	if (!dacdb) {
		fprintf(stderr, "Could not recover DAC!\n");
		emv_pk_free(ipk);
		tlvdb_free(db);
		return 2;
	}

	const struct tlv *dac = tlvdb_get(dacdb, 0x9f45, NULL);
	if (!dac) {
		fprintf(stderr, "DAC not found!\n");
		tlvdb_free(dacdb);
		emv_pk_free(ipk);
		tlvdb_free(db);
		return 2;
	}

	dump_buffer(dac->value, dac->len, stdout);

	tlvdb_free(dacdb);
	emv_pk_free(ipk);
	tlvdb_free(db);

	return 0;
}
Beispiel #2
0
static int cda_test_pk(void)
{
	const struct emv_pk *pk = &mchip_05;
	struct tlvdb *db;

	db = tlvdb_external(0x90, sizeof(issuer_cert), issuer_cert);
	tlvdb_add(db, tlvdb_external(0x9f32, sizeof(issuer_exp), issuer_exp));
	tlvdb_add(db, tlvdb_external(0x92, sizeof(issuer_rem), issuer_rem));
	tlvdb_add(db, tlvdb_external(0x5a, sizeof(pan), pan));

	struct emv_pk *ipk = emv_pki_recover_issuer_cert(pk, db);
	if (!ipk) {
		fprintf(stderr, "Could not recover Issuer certificate!\n");
		tlvdb_free(db);
		return 2;
	}

	tlvdb_add(db, tlvdb_external(0x9f46, sizeof(icc_cert), icc_cert));
	tlvdb_add(db, tlvdb_external(0x9f47, sizeof(icc_exp), icc_exp));
	/*tlvdb_add(db, tlvdb_external(0x9f48, sizeof(issuer_rem), issuer_rem));*/

	struct emv_pk *iccpk = emv_pki_recover_icc_cert(ipk, db, &ssd1_tlv);
	if (!iccpk) {
		fprintf(stderr, "Could not recover ICC certificate!\n");
		emv_pk_free(ipk);
		tlvdb_free(db);
		return 2;
	}

	tlvdb_add(db, tlvdb_fixed(0x9f37, sizeof(dd1), dd1));

	struct tlvdb *cda_db;
	cda_db = tlvdb_fixed(0x9f27, 1, (unsigned char[]){ 0x40 });
Beispiel #3
0
struct tlvdb *dol_parse(const struct tlv *tlv, const unsigned char *data, size_t data_len)
{
	if (!tlv)
		return NULL;

	const unsigned char *buf = tlv->value;
	size_t left = tlv->len;
	size_t res_len = dol_calculate_len(tlv, data_len);
	size_t pos = 0;
	struct tlvdb *db = NULL;

	if (res_len != data_len)
		return NULL;

	while (left) {
		struct tlv cur_tlv;
		if (!tlv_parse_tl(&buf, &left, &cur_tlv) || pos + cur_tlv.len > res_len) {
			tlvdb_free(db);
			return NULL;
		}

		/* Last tag can be of variable length */
		if (cur_tlv.len == 0 && left == 0)
			cur_tlv.len = res_len - pos;

		struct tlvdb *tag_db = tlvdb_fixed(cur_tlv.tag, cur_tlv.len, data + pos);
		if (!db)
			db = tag_db;
		else
			tlvdb_add(db, tag_db);

		pos += cur_tlv.len;
	}

	return db;
}
Beispiel #4
0
int main(void)
{
	int i;
	struct sc *sc;

	sc = scard_init(NULL);
	if (!sc) {
		printf("Cannot init scard\n");
		return 1;
	}

	scard_connect(sc, openemv_config_get_int("scard.reader", 0));
	if (scard_is_error(sc)) {
		printf("%s\n", scard_error(sc));
		return 1;
	}

	struct tlvdb *s;
	struct tlvdb *t;
	for (i = 0, s = NULL; apps[i].name_len != 0; i++) {
		const struct tlv aid_tlv = {
			.len = apps[i].name_len,
			.value = apps[i].name,
		};
		s = emv_select(sc, &aid_tlv);
		if (s)
			break;
	}
	if (!s)
		return 1;

	struct tlv *pdol_data_tlv = dol_process(tlvdb_get(s, 0x9f38, NULL), s, 0x83);
	if (!pdol_data_tlv)
		return 1;

	t = emv_gpo(sc, pdol_data_tlv);
	free(pdol_data_tlv);
	if (!t)
		return 1;
	tlvdb_add(s, t);

	struct tlv *sda_tlv = emv_read_records(sc, s);
	if (!sda_tlv)
		return 1;

	/* Only PTC read should happen before VERIFY */
	tlvdb_add(s, emv_get_data(sc, 0x9f17));

	verify_offline_clear(s, sc);

#define TAG(tag, len, value...) tlvdb_add(s, tlvdb_fixed(tag, len, (unsigned char[]){value}))
//	TAG(0x9f02, 6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
//	TAG(0x9f1a, 2, 0x06, 0x43);
	TAG(0x95, 5, 0x80, 0x00, 0x00, 0x00, 0x00);
//	TAG(0x5f2a, 2, 0x06, 0x43);
//	TAG(0x9a, 3, 0x14, 0x09, 0x25);
//	TAG(0x9c, 1, 0x50);
//	TAG(0x9f37, 4, 0x12, 0x34, 0x57, 0x79);
	TAG(0x9f35, 1, 0x34);
	TAG(0x9f34, 3, 0x01, 0x00, 0x02);
#undef TAG

	/* Generate ARQC */
	struct tlv *crm_tlv = dol_process(tlvdb_get(s, 0x8c, NULL), s, 0);
	if (!crm_tlv)
		return 1;
	t = emv_generate_ac(sc, 0x80, crm_tlv);
	free(crm_tlv);
	tlvdb_add(s, t);

	build_cap(s);

#define TAG(tag, len, value...) tlvdb_add(s, tlvdb_fixed(tag, len, (unsigned char[]){value}))
	TAG(0x8a, 2, 'Z', '3');
#undef TAG

	/* Generate AC asking for AAC */
	crm_tlv = dol_process(tlvdb_get(s, 0x8d, NULL), s, 0);
	if (!crm_tlv)
		return 1;
	t = emv_generate_ac(sc, 0x00, crm_tlv);
	free(crm_tlv);
	tlvdb_add(s, t);

	tlvdb_visit(s, print_cb, NULL);
	tlvdb_free(s);

	scard_disconnect(sc);
	if (scard_is_error(sc)) {
		printf("%s\n", scard_error(sc));
		return 1;
	}
	scard_shutdown(sc);

	return 0;
}
Beispiel #5
0
bool emv_read_records(struct sc *sc, struct tlvdb *db, unsigned char **pdata, size_t *plen)
{
	*pdata = NULL;
	*plen = 0;

	const struct tlv *afl = tlvdb_get(db, 0x94, NULL);
	if (!afl)
		return 1;

	unsigned char *sda_data = NULL;
	size_t sda_len = 0;

	int i;
	for (i = 0; i < afl->len; i += 4) {
		unsigned char p2 = afl->value[i + 0];
		unsigned char first = afl->value[i + 1];
		unsigned char last = afl->value[i + 2];
		unsigned char sdarec = afl->value[i + 3];
		unsigned char sfi = p2 >> 3;

		if (sfi == 0 || sfi == 31 || first == 0 || first > last)
			return false;

		for (; first <= last; first ++) {
			unsigned short sw;
			size_t outlen;
			unsigned char *outbuf;
			struct tlvdb *t;

			outbuf = emv_read_record(sc, sfi, first, &sw, &outlen);
			if (!outbuf)
				return false;

			if (sw == 0x9000) {
				t = tlvdb_parse(outbuf, outlen);
				if (!t)
					return false;
			} else
				return false;

			if (sdarec) {
				const unsigned char *data;
				size_t data_len;

				if (sfi < 11) {
					const struct tlv *e = tlvdb_get(t, 0x70, NULL);
					if (!e)
						return false;

					data = e->value;
					data_len = e->len;
				} else {
					data = outbuf;
					data_len = outlen;
				}

				sda_data = realloc(sda_data, sda_len + data_len);
				memcpy(sda_data + sda_len, data, data_len);
				sda_len += data_len;
				sdarec --;
			}

			free(outbuf);
			tlvdb_add(db, t);
		}
	}

	const struct tlv *sdatl_tlv = tlvdb_get(db, 0x9f4a, NULL);
	if (sdatl_tlv) {
		const struct tlv *aip_tlv = tlvdb_get(db, 0x82, NULL);
		if (sdatl_tlv->len == 1 && sdatl_tlv->value[0] == 0x82 && aip_tlv) {
			sda_data = realloc(sda_data, sda_len + aip_tlv->len);
			memcpy(sda_data + sda_len, aip_tlv->value, aip_tlv->len);
			sda_len += aip_tlv->len;
		} else {
			/* Error!! */
			free(sda_data);
			sda_data = NULL;
			sda_len = 0;
		}
	}

	*pdata = sda_data;
	*plen = sda_len;

	return true;
}
Beispiel #6
0
int main(void)
{
	int i;
	struct sc *sc;

	sc = scard_init(NULL);
	if (!sc) {
		printf("Cannot init scard\n");
		return 1;
	}

	scard_connect(sc, 0);
	if (scard_is_error(sc)) {
		printf("%s\n", scard_error(sc));
		return 1;
	}

	struct tlvdb *s;
	struct tlvdb *t;
	for (i = 0, s = NULL; apps[i].name_len != 0; i++) {
		s = emv_select(sc, apps[i].name, apps[i].name_len);
		if (s)
			break;
	}
	if (!s)
		return 1;

	size_t pdol_data_len;
	unsigned char *pdol_data = dol_process(tlvdb_get(s, 0x9f38, NULL), s, &pdol_data_len);
	struct tlv pdol_data_tlv = { .tag = 0x83, .len = pdol_data_len, .value = pdol_data };

	size_t pdol_data_tlv_data_len;
	unsigned char *pdol_data_tlv_data = tlv_encode(&pdol_data_tlv, &pdol_data_tlv_data_len);
	free(pdol_data);
	if (!pdol_data_tlv_data)
		return 1;

	t = emv_gpo(sc, pdol_data_tlv_data, pdol_data_tlv_data_len);
	free(pdol_data_tlv_data);
	if (!t)
		return 1;
	tlvdb_add(s, t);

	unsigned char *sda_data = NULL;
	size_t sda_len = 0;
	bool ok = emv_read_records(sc, s, &sda_data, &sda_len);
	if (!ok)
		return 1;

	free(sda_data);

	/* Generate AC asking for AAC */
	size_t crm_data_len;
	unsigned char *crm_data = dol_process(tlvdb_get(s, 0x8c, NULL), s, &crm_data_len);
	t = emv_generate_ac(sc, 0x00, crm_data, crm_data_len);
	free(crm_data);
	tlvdb_add(s, t);

	tlvdb_add(s, emv_get_data(sc, 0x9f36));
	tlvdb_add(s, emv_get_data(sc, 0x9f13));
	tlvdb_add(s, emv_get_data(sc, 0x9f17));
	tlvdb_add(s, emv_get_data(sc, 0x9f4f));

	tlvdb_visit(s, print_cb, NULL);

	const struct tlv *logent_tlv = tlvdb_get(s, 0x9f4d, NULL);
	const struct tlv *logent_dol = tlvdb_get(s, 0x9f4f, NULL);
	if (logent_tlv && logent_tlv->len == 2 && logent_dol) {
		for (i = 1; i <= logent_tlv->value[1]; i++) {
			unsigned short sw;
			size_t log_len;
			unsigned char *log = emv_read_record(sc, logent_tlv->value[0], i, &sw, &log_len);
			if (!log)
				continue;

			if (sw == 0x9000) {
				printf("Log #%d\n", i);
				struct tlvdb *log_db = dol_parse(logent_dol, log, log_len);
				tlvdb_visit(log_db, print_cb, NULL);
				tlvdb_free(log_db);
			}
			free(log);
		}
	}

	tlvdb_free(s);

	scard_disconnect(sc);
	if (scard_is_error(sc)) {
		printf("%s\n", scard_error(sc));
		return 1;
	}
	scard_shutdown(sc);

	return 0;
}