Beispiel #1
0
int
fix_mad_trailer_block (nfc_device_t *device, MifareTag tag, MifareClassicSectorNumber sector, MifareClassicKey key, MifareClassicKeyType key_type)
{
    MifareClassicBlock block;
    mifare_classic_trailer_block (&block, mad_public_key_a, 0x0, 0x1, 0x1, 0x6, 0x00, default_keyb);
    if (mifare_classic_authenticate (tag, mifare_classic_sector_last_block (sector), key, key_type) < 0) {
		nfc_perror (device, "fix_mad_trailer_block mifare_classic_authenticate");
		return -1;
    }
    if (mifare_classic_write (tag, mifare_classic_sector_last_block (sector), block) < 0) {
		nfc_perror (device, "mifare_classic_write");
		return -1;
    }
    return 0;
}
void
test_mifare_classic_sector_boundaries (void)
{
    for (int i=0; i < 32; i++) {
	for (int j=0; j < 4; j++) {
	    cut_assert_equal_int (4 * i, mifare_classic_sector_first_block (mifare_classic_block_sector (4 * i)), cut_message ("Wrong first block number for block %d", i));
	    cut_assert_equal_int (4 * i + 3, mifare_classic_sector_last_block (mifare_classic_block_sector (4 * i + j)), cut_message ("Wrong last block number for block %d", i));
	}
    }

    for (int i=0; i < 8; i++) {
	for (int j=0; j < 16; j++) {
	    cut_assert_equal_int (128 + 16 * i, mifare_classic_sector_first_block (mifare_classic_block_sector (128 + 16 * i)), cut_message ("Wrong last block number for block %d", i));
	    cut_assert_equal_int (128 + 16 * i + 15, mifare_classic_sector_last_block (mifare_classic_block_sector (128 + 16 * i + j)), cut_message ("Wrong last block number for block %d", i));
	}
    }
}
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;

}
Beispiel #4
0
int try_format_sector (MifareTag tag, MifareClassicSectorNumber sector)
{
    display_progress ();
    size_t i;
    for (i = 0; i < (sizeof (default_keys) / sizeof (MifareClassicKey)); i++)
    {
	MifareClassicBlockNumber block = mifare_classic_sector_last_block (sector);
	if ((0 == mifare_classic_connect (tag)) && (0 == mifare_classic_authenticate (tag, block, default_keys[i], MFC_KEY_A)))
    {
	    if (0 == mifare_classic_format_sector (tag, sector))
        {
		mifare_classic_disconnect (tag);
		return 1;
	    }
        else if (EIO == errno)
        {
		err (EXIT_FAILURE, "sector %d", sector);
	    }
	    mifare_classic_disconnect (tag);
	}
	if ((0 == mifare_classic_connect (tag)) && (0 == mifare_classic_authenticate (tag, block, default_keys[i], MFC_KEY_B)))
    {
	    if (0 == mifare_classic_format_sector (tag, sector))
        {
		mifare_classic_disconnect (tag);
		return 1;
	    }
        else if (EIO == errno)
        {
		err (EXIT_FAILURE, "sector %d", sector);
	    }
	    mifare_classic_disconnect (tag);
	}
    }
    sprintf(message_erreur,"No known authentication key for sector %d !", sector);
    return 0;
}
Beispiel #5
0
int
search_sector_key (MifareTag tag, MifareClassicSectorNumber sector, MifareClassicKey *key, MifareClassicKeyType *key_type)
{
    MifareClassicBlockNumber block = mifare_classic_sector_last_block (sector);

    /*
     * FIXME: We should not assume that if we have full access to trailer block
     *        we also have a full access to data blocks.
     */
    mifare_classic_disconnect (tag);
    for (size_t i = 0; i < (sizeof (default_keys) / sizeof (MifareClassicKey)); i++) {
		if ((0 == mifare_classic_connect (tag)) && (0 == mifare_classic_authenticate (tag, block, default_keys[i], MFC_KEY_A))) {
			if ((1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_KEYA, MFC_KEY_A)) &&
				(1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_ACCESS_BITS, MFC_KEY_A)) &&
				(1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_KEYB, MFC_KEY_A))) {
					memcpy (key, &default_keys[i], sizeof (MifareClassicKey));
					*key_type = MFC_KEY_A;
					return 1;
			}
		}
		mifare_classic_disconnect (tag);

		if ((0 == mifare_classic_connect (tag)) && (0 == mifare_classic_authenticate (tag, block, default_keys[i], MFC_KEY_B))) {
			if ((1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_KEYA, MFC_KEY_B)) &&
				(1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_ACCESS_BITS, MFC_KEY_B)) &&
				(1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_KEYB, MFC_KEY_B))) {
					memcpy (key, &default_keys[i], sizeof (MifareClassicKey));
					*key_type = MFC_KEY_B;
					return 1;
			}
		}
		mifare_classic_disconnect (tag);
    }

    warnx ("No known authentication key for sector 0x%02x\n", sector);
    return 0;
}
Beispiel #6
0
int main(int argc, const char *argv[])
{
  nfc_device *pnd;
  //nfc_target nt;
  MifareTag *tags = NULL;
  int i,j,k;
  int nbrsect=0;

  MifareClassicBlock data;

  // Allocate only a pointer to nfc_context
  nfc_context *context;

  // Initialize libnfc and set the nfc_context
  nfc_init(&context);
  if (context == NULL) {
    printf("Unable to init libnfc\n");
    exit(EXIT_FAILURE);
  }

  // Open, using the first available NFC device which can be in order of selection:
  //   - default device specified using environment variable or
  //   - first specified device in libnfc.conf (/etc/nfc) or
  //   - first specified device in device-configuration directory (/etc/nfc/devices.d) or
  //   - first auto-detected (if feature is not disabled in libnfc.conf) device
  pnd = nfc_open(context, NULL);

  if (pnd == NULL) {
    printf("ERROR: %s\n", "Unable to open NFC device.");
    exit(EXIT_FAILURE);
  }

  printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));

  tags = freefare_get_tags(pnd);

  if (!tags) {
    printf("no Mifare classic\n");
  } else {
    for (i = 0; tags[i]; i++) {
      switch(freefare_get_tag_type(tags[i])) {
	case CLASSIC_1K:
	  printf("%u : Mifare 1k (S50) : %s\n", i, freefare_get_tag_uid(tags[i]));
	  nbrsect=16;
	  break;
	case CLASSIC_4K:
	  printf("%u : Mifare 4k (S70) : %s\n", i, freefare_get_tag_uid(tags[i]));
	  nbrsect=40;
	  break;
	default:
	  printf("%u : other ISO14443A tag : %s\n", i, freefare_get_tag_uid(tags[i]));
      }
    }
  }

  if (!tags[0]) {
    printf("no tag found !\n");
    nfc_close(pnd);
    nfc_exit(context);
    exit(EXIT_FAILURE);
  }

  printf ("Found %s\n", freefare_get_tag_friendly_name (tags[0]));

  /*
     MifareClassicBlockNumber dablock = 1;
     if(mifare_classic_connect(tags[0]) == OPERATION_OK) {
     printf("Connected !\n");
     if(mifare_classic_authenticate(tags[0], dablock, keys[0], MFC_KEY_A) == OPERATION_OK) {
     printf("Authenticated !\n");
     if(mifare_classic_get_data_block_permission (tags[0], dablock, MCAB_R|MCAB_W, MFC_KEY_A))
     printf("i can READ block %d with key A\n", dablock);
     if(mifare_classic_get_trailer_block_permission (tags[0], ((dablock)/4)*4+3, MCAB_READ_KEYB, MFC_KEY_B))
     printf("i can READ KEY A in trailer\n");
     }
     }
   */

  for(i=0; i<nbrsect; i++) {
    for(j=0; j < sizeof(keys)/sizeof(keys[0]); j++) {
      if((mifare_classic_connect(tags[0]) == OPERATION_OK) && 
	  (mifare_classic_authenticate(
				       tags[0], 
				       mifare_classic_sector_last_block(i), 
				       keys[j], 
				       MFC_KEY_A) == OPERATION_OK)) {
	printf("sector %02d auth with A[%d]\n", i, j);
	for(k=mifare_classic_sector_first_block(i); 
	    k<=mifare_classic_sector_last_block(i); k++) {
	  if(mifare_classic_read(tags[0], k, &data) == OPERATION_OK) {
	    print_hex(data,16);
	  } else {
	    printf("read error\n");
	  }
	}
	mifare_classic_disconnect(tags[0]);
	break;
      }
      mifare_classic_disconnect(tags[0]);
    }
    printf("\n");
  }
  printf("\n");

  freefare_free_tags(tags);

  // Close NFC device
  nfc_close(pnd);
  // Release the context
  nfc_exit(context);
  exit(EXIT_SUCCESS);
}
int main(int argc, char **argv) {
	int res;
	nfc_connstring devices[8];
	size_t device_count;
	nfc_context *nfcctx;
	char *uid = NULL;
	init_crypto_state();
	nfc_init(&nfcctx);
	
	device_count = nfc_list_devices(nfcctx,devices,8);

	if (device_count <= 0) {
		std::cerr << "No device found" << std::endl;
	}

	device = nfc_open(nfcctx, devices[0]);
    	tags = freefare_get_tags(device);

	if (tags[0] == NULL) {
        	std::cerr << "No tag on device" << std::endl;
    		exit(1);
	}

	for (int i = 0; tags[i]; i++) {
        	if (freefare_get_tag_type(tags[i]) == CLASSIC_1K) {
        	    tag = tags[i];
        	    res = mifare_classic_connect(tag);
        	    if (res != 0) {
        	        std::cout << "Error connecting to MiFare Classic" << std::endl;
			exit(1);
			}
			std::cout << "Connected to MiFare Classic" << std::endl;
		 	uid = freefare_get_tag_uid(tag);
			 break;
        	}
    	}
	std::cout << "UID: " << uid << std::endl;
	MifareClassicKey *keyA = (MifareClassicKey *)get_random_bytes(6);
	std::cout << "Key A: ";
	print_hex(*keyA,6);
	char *b64KeyA = getBase64String((char *)keyA,6);
	std::cout << b64KeyA << std::endl;
	std::cout << "Key B: ";
	MifareClassicKey *keyB = (MifareClassicKey *)get_random_bytes(6);
	print_hex(*keyB,6);	
	char *b64KeyB = getBase64String((char *)keyB,6);	
	bool addedToServer = addCard(uid,b64KeyA,b64KeyB);	
	if (!addedToServer) {
		printf("Not added to server\n");
	}

	// Authenticate with default key to make changes
	
	MifareClassicBlockNumber lastTrailer = mifare_classic_sector_last_block(15);
	res = mifare_classic_authenticate(tag,lastTrailer,defaultKey,MFC_KEY_A);
	if (res != 0) {
		printf("Could not authenticate with default key.. card already formatted?\n");
		return -1;
	}	
	
	MifareClassicBlockNumber firstBlock = mifare_classic_sector_first_block(15);
	res = mifare_classic_init_value(tag,firstBlock,SECTOR_15_BLOCK_0_INIT,firstBlock);
	if (res != 0) {
		printf("Could not init value block %d\n",firstBlock);
	}
	MifareClassicBlock trailerBlock;
	
	mifare_classic_trailer_block(&trailerBlock,*keyA,0x03,0x00,0x00,0x04,0x00, *keyB);
	print_hex(trailerBlock, sizeof(MifareClassicBlock));
	res = mifare_classic_write(tag,lastTrailer,trailerBlock);	
	if (res != 0) {
		printf("Could not write sector 15 trailer. STOP\n");
		return -1;
	} 
	

	MifareClassicBlock normalTrailerBlock;
	mifare_classic_trailer_block(&normalTrailerBlock,*keyA,0x00,0x00,0x00,0x04,0x00,*keyB);
	printf("Writing normal trailer block ");
	print_hex(&normalTrailerBlock[0], sizeof(MifareClassicBlock));
	MifareClassicSectorNumber sector;
	for(sector=0; sector<15;sector++) {
		MifareClassicBlockNumber trailerBlockNumber = mifare_classic_sector_last_block(sector);
		res = mifare_classic_authenticate(tag,trailerBlockNumber,defaultKey,MFC_KEY_A);
		if (res != 0) {
			printf("Could not authenticate with default key.. card already formatted?\n");
			return -1;
		}	

		res = mifare_classic_write(tag,trailerBlockNumber,normalTrailerBlock);
		if (res != 0) {
			printf("Could not write trailer block for sector %d\n",sector);
			return -1;
		} else {
			printf("Wrote trailer block for sector %d\n",sector);
		}
	}	
		
	free(keyA);
	free(keyB);
	free(b64KeyA);
	free(b64KeyB);
	free(uid);

	
	freefare_free_tags(tags);
	nfc_close(device);
}
Beispiel #8
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);
}