Example #1
0
struct json_object *tlv_to_json(const struct tlv *tlv)
{
	struct json_object *result = NULL;
	char *hex = NULL;
	void *enc = NULL;
	size_t enc_sz = 0;
	int rc = TLV_RC_OK;

	rc = tlv_encode(tlv, NULL, &enc_sz);
	if (rc != TLV_RC_OK)
		goto done;

	enc = malloc(enc_sz);
	if (!enc)
		goto done;

	rc = tlv_encode(tlv, enc, &enc_sz);
	if (rc != TLV_RC_OK)
		goto done;

	hex = malloc(enc_sz * 2 + 1);
	if (!hex)
		goto done;

	result = json_object_new_string(libtlv_bin_to_hex(enc, enc_sz, hex));

done:
	if (hex)
		free(hex);

	if (enc)
		free(enc);

	return result;
}
Example #2
0
void
test_tlv_append (void)
{
    const uint8_t a[] = { 0xde, 0xad, 0xbe, 0xef };
    const uint8_t b[] = { 0x42 };

    uint8_t ndef_ab_ref[] = { 0x03, 0x04, 0xde, 0xad, 0xbe, 0xef, 0x03, 0x01, 0x42, 0xfe };

    uint8_t *ndef_a = tlv_encode (3, a, 4, NULL);
    uint8_t *ndef_b = tlv_encode (3, b, 1, NULL);
    ndef_a = tlv_append (ndef_a, ndef_b);
    cut_assert_equal_memory (ndef_ab_ref, sizeof (ndef_ab_ref), ndef_a, sizeof (ndef_ab_ref), cut_message ("Wrong appended data"));

    free (ndef_a);
    free (ndef_b);
}
Example #3
0
void
test_tlv_rfu (void)
{
    uint8_t *data = malloc (0xffff);
    cut_assert_not_null (data, cut_message ("Out of memory"));

    uint8_t *res = tlv_encode (7, data, 0xffff, NULL);
    cut_assert_null (res, cut_message ("Size reserved for future use"));

    free (data);
}
Example #4
0
void
test_tlv_encode_short (void)
{
    uint8_t *res;
    size_t osize;

    res = tlv_encode (3, shortdata, sizeof (shortdata), &osize);
    cut_assert_equal_int (sizeof (eshortdata), osize, cut_message ("Wrong encoded message length."));
    cut_assert_equal_int (3, res[0], cut_message ("Wrong type"));
    cut_assert_equal_int (sizeof (shortdata), res[1], cut_message ("Wrong value length"));
    cut_assert_equal_memory (eshortdata, sizeof (eshortdata), res, osize, cut_message ("Wrong encoded value"));
    free (res);
}
Example #5
0
void
test_tlv_encode_long (void)
{
    uint8_t *res;
    size_t osize;

    res = tlv_encode (7, longdata, sizeof (longdata), &osize);
    cut_assert_equal_int (sizeof (elongdata), osize, cut_message ("Wrong encoded message length."));
    cut_assert_equal_int (7, res[0], cut_message ("Wrong type"));
    cut_assert_equal_int (0xff, res[1], cut_message ("Wrong value length"));
    cut_assert_equal_int (0x02, res[2], cut_message ("Wrong value length"));
    cut_assert_equal_int (0x94, res[3], cut_message ("Wrong value length"));
    cut_assert_equal_memory (elongdata, sizeof (elongdata), res, osize, cut_message ("Wrong encoded value"));
    free (res);
}
Example #6
0
int
main(int argc, char *argv[])
{
	
	MYSQL *conn;
	MYSQL_RES *result;
	MYSQL_ROW row;
	int retval;
	
	conn = mysql_init(NULL);
	
	retval = mysql_real_connect(conn, def_host_name, def_user_name, def_password, def_db_name, def_port_num, def_socket_name, def_client_flag);
	if(!retval)
	{
		printf("Error connecting to database: %s\n", mysql_error(conn));
		return -1;
	}
	printf("Connection successful\n");
	
	int error = 0;
    nfc_device_t *device = NULL;
    MifareTag *tags = NULL;
    Mad mad;
    MifareClassicKey transport_key = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
	
	char ndef_input[15] = {'\0'};
	char ID[9] = {'\0'};
	double balance = 0;

	printf("\nID: ");
	scanf("%s", ID);
	while (getchar() != '\n') continue;
	
	printf("\nBalance: ");
	scanf("%lf", &balance);
	while (getchar() != '\n') continue;
	
	ID[0] = toupper(ID[0]);
	ID[1] = toupper(ID[1]);
	
	char balance_char[6] = {'\0'};
	snprintf(balance_char, 6, "%.2f", balance);
	
	//ensure balance always with 4 digit, 4.00 => 04.00
	char final_balance[6] = {'\0'};
	if(strlen(balance_char) != 5)
	{
		strcat(final_balance, "0");
		strcat(final_balance, balance_char);
	}
	else
	{
		strcpy(final_balance, balance_char);
	}

	strcat(ndef_input, ID);
	strcat(ndef_input, final_balance);

	int i = 0;
    if (ndef_input == NULL) {
		printf("Write default message.\n");
		for(i=0; i < sizeof(ndef_default_msg); i++)
		{
			ndef_msg[i] = (uint8_t)ndef_default_msg[i];
		}
			
        ndef_msg_len = sizeof(ndef_default_msg);
    } 
	else {
		for(i=0; i < strlen(ndef_input); i++)
		{
			ndef_msg[i] = (uint8_t)ndef_input[i];
		}
			
		ndef_msg_len = strlen(ndef_input);
    }
    printf ("NDEF message is %zu bytes long.\n", ndef_msg_len);

    struct mifare_classic_key_and_type *card_write_keys;
    if (!(card_write_keys = malloc (40 * sizeof (*card_write_keys)))) {
		err (EXIT_FAILURE, "malloc");
    }

    nfc_device_desc_t devices[8];
    size_t device_count;

    nfc_list_devices (devices, 8, &device_count);
    if (!device_count)
		errx (EXIT_FAILURE, "No NFC device found.");

    for (size_t d = 0; d < device_count; d++) {
		device = nfc_connect (&(devices[d]));
		if (!device) {
			warnx ("nfc_connect() failed.");
			error = EXIT_FAILURE;
			continue;
		}

		tags = freefare_get_tags (device);
		if (!tags) {
			nfc_disconnect (device);
			errx (EXIT_FAILURE, "Error listing MIFARE classic tag.");
		}

		for (int i = 0; (!error) && tags[i]; i++) 
		{
			switch (freefare_get_tag_type (tags[i])) {
				case CLASSIC_1K:
				case CLASSIC_4K:
					break;
				default:
					continue;
			}

			char *tag_uid = freefare_get_tag_uid (tags[i]);
			char buffer[BUFSIZ];

			printf ("Found %s with UID %s.\n", freefare_get_tag_friendly_name (tags[i]), tag_uid);
			bool write_ndef = true;
				
			for (int n = 0; n < 40; n++) {
				memcpy(card_write_keys[n].key, transport_key, sizeof (transport_key));
				card_write_keys[n].type = MFC_KEY_A;
			}

			if (write_ndef) 
			{
				switch (freefare_get_tag_type (tags[i])) {
					case CLASSIC_4K:
						if (!search_sector_key (tags[i], 0x10, &(card_write_keys[0x10].key), &(card_write_keys[0x10].type))) {
							error = 1;
							goto error;
						}
						/* fallthrough */
					case CLASSIC_1K:
						if (!search_sector_key (tags[i], 0x00, &(card_write_keys[0x00].key), &(card_write_keys[0x00].type))) {
							error = 1;
							goto error;
						}
						break;
					default:
						/* Keep compiler quiet */
						break;
				}

				if (!error) {
					/* Ensure the auth key is always a B one. If not, change it! */
					switch (freefare_get_tag_type (tags[i])) {
						case CLASSIC_4K:
						if (card_write_keys[0x10].type != MFC_KEY_B) {
							if( 0 != fix_mad_trailer_block (device, tags[i], 0x10, card_write_keys[0x10].key, card_write_keys[0x10].type)) {
								error = 1;
								goto error;
							}
							memcpy (&(card_write_keys[0x10].key), &default_keyb, sizeof (MifareClassicKey));
							card_write_keys[0x10].type = MFC_KEY_B;
						}
						/* fallthrough */
						case CLASSIC_1K:
						if (card_write_keys[0x00].type != MFC_KEY_B) {
							if( 0 != fix_mad_trailer_block (device, tags[i], 0x00, card_write_keys[0x00].key, card_write_keys[0x00].type)) {
								error = 1;
								goto error;
							}
							memcpy (&(card_write_keys[0x00].key), &default_keyb, sizeof (MifareClassicKey));
							card_write_keys[0x00].type = MFC_KEY_B;
							}
							break;
						default:
							/* Keep compiler quiet */
							break;
					}
				}

				size_t encoded_size;
				uint8_t *tlv_data = tlv_encode (3, ndef_msg, ndef_msg_len, &encoded_size);

				/*
				 * At his point, we should have collected all information needed to
				 * succeed.
				 */

				// If the card already has a MAD, load it.
				if ((mad = mad_read (tags[i]))) {
					// If our application already exists, erase it.
					MifareClassicSectorNumber *sectors, *p;
					sectors = p = mifare_application_find (mad, mad_nfcforum_aid);
					if (sectors) {
						while (*p) {
							if (mifare_classic_authenticate (tags[i], mifare_classic_sector_last_block(*p), default_keyb, MFC_KEY_B) < 0) {
								nfc_perror (device, "mifare_classic_authenticate");
								error = 1;
								goto error;
							}
							if (mifare_classic_format_sector (tags[i], *p) < 0) {
								nfc_perror (device, "mifare_classic_format_sector");
								error = 1;
								goto error;
							}
							p++;
						}
					}
					free (sectors);
					mifare_application_free (mad, mad_nfcforum_aid);
				} else {

					// Create a MAD and mark unaccessible sectors in the card
					if (!(mad = mad_new ((freefare_get_tag_type (tags[i]) == CLASSIC_4K) ? 2 : 1))) {
						perror ("mad_new");
						error = 1;
						goto error;
					}

					MifareClassicSectorNumber max_s;
					switch (freefare_get_tag_type (tags[i])) {
						case CLASSIC_1K:
							max_s = 15;
							break;
						case CLASSIC_4K:
							max_s = 39;
							break;
						default:
							/* Keep compiler quiet */
							break;
					}

					// Mark unusable sectors as so
					for (size_t s = max_s; s; s--) {
						if (s == 0x10) 
							continue;
						if (!search_sector_key (tags[i], s, &(card_write_keys[s].key), &(card_write_keys[s].type))) {
							mad_set_aid (mad, s, mad_defect_aid);
						} else if ((memcmp (card_write_keys[s].key, transport_key, sizeof (transport_key)) != 0) &&
							   (card_write_keys[s].type != MFC_KEY_A)) {
									// Revert to transport configuration
									if (mifare_classic_format_sector (tags[i], s) < 0) {
										nfc_perror (device, "mifare_classic_format_sector");
										error = 1;
										goto error;
									}
						}
					}
				}

				MifareClassicSectorNumber *sectors = mifare_application_alloc (mad, mad_nfcforum_aid, encoded_size);
				if (!sectors) {
					nfc_perror (device, "mifare_application_alloc");
					error = EXIT_FAILURE;
					goto error;
				}

				if (mad_write (tags[i], mad, card_write_keys[0x00].key, card_write_keys[0x10].key) < 0) {
					nfc_perror (device, "mad_write");
					error = EXIT_FAILURE;
					goto error;
				}

				int s = 0;
				while (sectors[s]) {
					MifareClassicBlockNumber block = mifare_classic_sector_last_block (sectors[s]);
					MifareClassicBlock block_data;
					mifare_classic_trailer_block (&block_data, mifare_classic_nfcforum_public_key_a, 0x0, 0x0, 0x0, 0x6, 0x40, default_keyb);
					if (mifare_classic_authenticate (tags[i], block, card_write_keys[sectors[s]].key, card_write_keys[sectors[s]].type) < 0) {
						nfc_perror (device, "mifare_classic_authenticate");
						error = EXIT_FAILURE;
						goto error;
					}
					if (mifare_classic_write (tags[i], block, block_data) < 0) {
						nfc_perror (device, "mifare_classic_write");
						error = EXIT_FAILURE;
						goto error;
					}
					s++;
				}

				if ((ssize_t) encoded_size != mifare_application_write (tags[i], mad, mad_nfcforum_aid, tlv_data, encoded_size, default_keyb, MCAB_WRITE_KEYB)) {
					nfc_perror (device, "mifare_application_write");
					error = EXIT_FAILURE;
					goto error;
				}


				//create new student record in database
				char sql_stmnt[57] = {'\0'};
				int n = 0;
				
				//filter tag_uid
				ulong uid_length = strlen(tag_uid);
				char uid_esc[(2 * uid_length)+1];
				mysql_real_escape_string(conn, uid_esc, tag_uid, uid_length);

				//filter ID
				ulong id_length = strlen(ID);
				char id_esc[(2 * id_length)+1];
				mysql_real_escape_string(conn, id_esc, ID, id_length);
				
				n = snprintf(sql_stmnt, 57, "INSERT INTO student VALUES('%s', '%s', %.1f)", uid_esc, id_esc, balance);
				retval = mysql_real_query(conn, sql_stmnt, n);
				if(retval)
				{
					printf("Inserting data from DB Failed\n");
					return -1;
				}
				printf("Insert to DB successful\n");
				
				free (sectors);

				free (tlv_data);

				free (mad);
			
			}
			error:
			free (tag_uid);
			
		}
		//should at the line 412, but the compiler keep on complaining
		//jump into scope of identifier with variably modified type
		//no idea why that happens, goto is always call inside any {} to outside error:
		//even at 412, still not outside enough
		

		freefare_free_tags (tags);
		nfc_disconnect (device);
    }

    free (card_write_keys);
	mysql_free_result(result);
	mysql_close(conn);

		exit (error);
}
Example #7
0
static struct emu_df *read_df(FILE *f, struct sc *sc, const unsigned char *name, size_t name_len)
{
	struct emu_df *df;
	int i, j;
	struct tlvdb *s;
	unsigned short sw;
	size_t outlen;
	unsigned char *outbuf;
	struct tlv pdol_data_tlv;
	size_t pdol_data_len;
	unsigned char *pdol_data;

	outbuf = sc_command(sc, 0x00, 0xa4, 0x04, 0x00, name_len, name, &sw, &outlen);
	if (sw != 0x9000)
		return NULL;

	s = tlvdb_parse(outbuf, outlen);
	if (!s)
		return NULL;

	df = emu_df_new();

	pdol_data_tlv.tag = 0x83;
	pdol_data_tlv.value = dol_process(tlvdb_get(s, 0x9f38, NULL), s, &pdol_data_tlv.len);
	pdol_data = tlv_encode(&pdol_data_tlv, &pdol_data_len);
	if (!pdol_data)
		return NULL;
	free((unsigned char *)pdol_data_tlv.value);

	tlvdb_free(s);

	emu_df_append(df, emu_property_new("name", emu_value_new_buf(name, name_len)));

	emu_df_append(df, emu_property_new("fci", emu_value_new_buf(outbuf, outlen)));
	free(outbuf);

	outbuf = sc_command(sc, 0x80, 0xa8, 0x00, 0x00, pdol_data_len, pdol_data, &sw, &outlen);
	free(pdol_data);
	if (sw == 0x9000) {
		emu_df_append(df, emu_property_new("gpo", emu_value_new_buf(outbuf, outlen)));
		free(outbuf);
	}

	for (i = 1; i < 31; i++) {
		int last = 0;
		struct emu_value *value = NULL;
		char buf[7];

		snprintf(buf, sizeof(buf), "sfi%d", i);

		for (j = 1; j < 256; j++) {
			outbuf = sc_command(sc, 0x00, 0xb2, j, (i << 3) | 4, 0, NULL, &sw, &outlen);
			if (sw == 0x6985)
				continue;
			else if (sw != 0x9000)
				break;

			for (; last < j - 1; last++)
				value = emu_value_append(value, "");

			value = emu_value_append_buf(value, outbuf, outlen);
			last ++;
			free(outbuf);
		}
		if (value)
			emu_df_append(df, emu_property_new(buf, value));
	}

	for (i = 0; card_data[i]; i++) {
		char buf[10];
		tlv_tag_t tag = card_data[i];
		outbuf = sc_command(sc, 0x80, 0xca, tag >> 8, tag & 0xff, 0, NULL, &sw, &outlen);
		if (sw != 0x9000)
			continue;

		snprintf(buf, sizeof(buf), "data%x", tag);
		emu_df_append(df, emu_property_new(buf, emu_value_new_buf(outbuf, outlen)));
		free(outbuf);
	}

	return df;
}
Example #8
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;
}