Пример #1
0
void
test_mifare_application (void)
{
    /* Card publisher part */

    MadAid aid = { 0x22, 0x42 };
    Mad mad = mad_new (2);

    int i;

    cut_assert_not_null (mad, cut_message ("mad_new() failed"));

    MifareClassicSectorNumber *s_alloc = mifare_application_alloc (mad, aid, 3*3*16);
    cut_assert_not_null (s_alloc, cut_message ("mifare_application_alloc() failed"));

    MifareClassicSectorNumber *s_found = mifare_application_find (mad, aid);
    cut_assert_not_null (s_found, cut_message ("mifare_application_alloc() failed"));

    for (i = 0; s_alloc[i]; i++) {
	cut_assert_equal_int (s_alloc[i], s_found[i], cut_message ("Allocated and found blocks don't match at position %d", i));
    }

    cut_assert_equal_int (0, s_alloc[i], cut_message ("Invalid size"));
    cut_assert_equal_int (0, s_found[i], cut_message ("Invalid size"));

    mifare_application_free (mad, aid);

    free (s_alloc);
    free (s_found);

    s_found = mifare_application_find (mad, aid);
    cut_assert_null (s_found, cut_message ("mifare_application_free() failed"));

    s_alloc = mifare_application_alloc (mad, aid, 15*16 + 1*16 + 1);
    cut_assert_not_null (s_alloc, cut_message ("mifare_application_alloc() failed"));

    s_found = mifare_application_find (mad, aid);
    cut_assert_not_null (s_found, cut_message ("mifare_application_alloc() failed"));



    for (i = 0; s_alloc[i]; i++) {
	cut_assert_equal_int (s_alloc[i], s_found[i], cut_message ("Allocated and found blocks don't match at position %d", i));
    }

    cut_assert_equal_int (0, s_alloc[i], cut_message ("Invalid size"));
    cut_assert_equal_int (0, s_found[i], cut_message ("Invalid size"));


    mifare_application_free (mad, aid);

    free (s_alloc);
    free (s_found);

    s_found = mifare_application_find (mad, aid);
    cut_assert_null (s_found, cut_message ("mifare_application_free() failed"));

    mad_free (mad);
}
Пример #2
0
ssize_t
mifare_application_write (MifareTag tag, Mad mad, const MadAid aid, const void *buf, size_t nbytes, const MifareClassicKey key, const MifareClassicKeyType key_type)
{
    ssize_t res = 0;

    MifareClassicSectorNumber *sectors = mifare_application_find (mad, aid);
    MifareClassicSectorNumber *s = sectors;

    if (!sectors)
	return errno = EBADF, -1;

    while (*s && nbytes && (res >= 0)) {
	MifareClassicBlockNumber first_block = mifare_classic_sector_first_block (*s);
	MifareClassicBlockNumber last_block  = mifare_classic_sector_last_block (*s);

	MifareClassicBlockNumber b = first_block;
	MifareClassicBlock block;

	if (mifare_classic_authenticate (tag, first_block, key, key_type) < 0) {
	    res = -1;
	    break;
	}

	while ((b < last_block) && nbytes) {
	    size_t n = MIN (nbytes, 16);
	    // Avoid overwriting existing data with uninitialized memory.
	    if (n < 16) {
		if (mifare_classic_read (tag, b, &block) < 0) {
		    res = -1;
		    break;
		}
	    }

	    memcpy (&block, (uint8_t *)buf + res, n);
	    if (mifare_classic_write (tag, b, block) < 0) {
		res = -1;
		break;
	    }

	    nbytes -= n;
	    res += n;

	    b++;
	}

	s++;
    }

    free (sectors);
    return res;

}
Пример #3
0
/*
 * Remove an application from a MAD.
 */
void
mifare_application_free (Mad mad, MadAid aid)
{
    MifareClassicSectorNumber *sectors = mifare_application_find (mad, aid);
    MifareClassicSectorNumber *p = sectors;
    MadAid free_aid = { 0x00, 0x00 };
    while (*p) {
	mad_set_aid (mad, *p, free_aid);
	p++;
    }

    free (sectors);
}
Пример #4
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);
}
Пример #5
0
/*
 * Allocates a new application into a MAD.
 */
MifareClassicSectorNumber *
mifare_application_alloc (Mad mad, MadAid aid, size_t size)
{
    uint8_t sector_map[40];
    MifareClassicSectorNumber sector;
    MadAid sector_aid;
    MifareClassicSectorNumber *res = NULL;
    ssize_t s = size;

    /*
     * Ensure the card does not already have the application registered.
     */
    MifareClassicSectorNumber *found;
    if ((found = mifare_application_find (mad, aid))) {
	free (found);
	return NULL;
    }

    for (size_t i = 0; i < sizeof (sector_map); i++)
	sector_map[i] = 0;

    /*
     * Try to minimize lost space and allocate as many large pages as possible
     * when the target is a Mifare Classic 4k.
     */
    MadAid free_aid = { 0x00, 0x00 };
    if (mad_get_version (mad) == 2) {
	sector = 32;
	while ((s >= 12*16) && sector < 40) {
	    mad_get_aid (mad, sector, &sector_aid);
	    if (0 == aidcmp (sector_aid, free_aid)) {
		sector_map[sector] = 1;
		s -= 15*16;
	    }
	    sector++;
	}
    }

    sector = FIRST_SECTOR;
    MifareClassicSectorNumber s_max = (mad_get_version (mad) == 1) ? 15 : 31;
    while ((s > 0) && (sector <= s_max)) {
	if (mad_sector_reserved (sector))
	    continue;
	mad_get_aid (mad, sector, &sector_aid);
	if (0 == aidcmp (sector_aid, free_aid)) {
	    sector_map[sector] = 1;
	    s -= 3*16;
	}
	sector++;
    }

    /*
     * Ensure the remaining free space is suficient before destroying the MAD.
     */
    if (s > 0)
	return NULL;

    int n = 0;
    for (size_t i = FIRST_SECTOR; i < sizeof (sector_map); i++)
	if (sector_map[i])
	    n++;

    if (!(res = malloc (sizeof (*res) * (n+1))))
	return NULL;

    n = 0;
    for (size_t i = FIRST_SECTOR; i < sizeof (sector_map); i++)
	if (sector_map[i]) {
	    res[n] = i;
	    mad_set_aid (mad, i, aid);
	    n++;
	}

    res[n] = 0;

    /* Return the list of allocated sectors */
    return res;
}