Move examples into src/examples subdirectory.
Change examples names to nfc-* (or nfcip-*).
This commit is contained in:
parent
de537473a0
commit
6aae96e1e1
18 changed files with 37 additions and 33 deletions
35
src/examples/Makefile.am
Normal file
35
src/examples/Makefile.am
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
bin_PROGRAMS = nfc-anticol nfc-list nfc-mftool nfc-mfultool nfc-relay nfc-emulate nfcip-target nfcip-initiator
|
||||
|
||||
# set the include path found by configure
|
||||
INCLUDES= $(all_includes)
|
||||
|
||||
AM_CFLAGS = -I$(top_srcdir)/src
|
||||
|
||||
nfc_anticol_SOURCES = nfc-anticol.c
|
||||
nfc_anticol_LDADD = $(top_builddir)/src/libnfc.la
|
||||
|
||||
nfc_list_SOURCES = nfc-list.c
|
||||
nfc_list_LDADD = $(top_builddir)/src/libnfc.la
|
||||
|
||||
nfc_mfultool_SOURCES = nfc-mfultool.c mifareultag.h
|
||||
nfc_mfultool_LDADD = $(top_builddir)/src/libnfc.la
|
||||
|
||||
nfc_mftool_SOURCES = nfc-mftool.c mifaretag.h
|
||||
nfc_mftool_LDADD = $(top_builddir)/src/libnfc.la
|
||||
|
||||
nfc_relay_SOURCES = nfc-relay.c
|
||||
nfc_relay_LDADD = $(top_builddir)/src/libnfc.la
|
||||
|
||||
nfc_emulate_SOURCES = nfc-emulate.c
|
||||
nfc_emulate_LDADD = $(top_builddir)/src/libnfc.la
|
||||
|
||||
nfcip_target_SOURCES = nfcip-target.c
|
||||
nfcip_target_LDADD = $(top_builddir)/src/libnfc.la
|
||||
|
||||
nfcip_initiator_SOURCES = nfcip-initiator.c
|
||||
nfcip_initiator_LDADD = $(top_builddir)/src/libnfc.la
|
||||
|
||||
dist_man_MANS = nfc-anticol.1 nfc-emulate.1 nfc-list.1 nfc-mftool.1 nfc-relay.1
|
||||
#dist_man_MANS = $(man_MANS)
|
||||
#EXTRA_DIST = $(man_MANS)
|
||||
|
||||
54
src/examples/mifaretag.h
Normal file
54
src/examples/mifaretag.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
|
||||
Public platform independent Near Field Communication (NFC) library
|
||||
Copyright (C) 2009, Roel Verdult
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _LIBNFC_MIFARE_TAG_H_
|
||||
#define _LIBNFC_MIFARE_TAG_H_
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
typedef struct {
|
||||
byte_t abtUID[4];
|
||||
byte_t btBCC;
|
||||
byte_t btUnknown;
|
||||
byte_t abtATQA[2];
|
||||
byte_t abtUnknown[8];
|
||||
} mifare_block_manufacturer;
|
||||
|
||||
typedef struct {
|
||||
byte_t abtData[16];
|
||||
} mifare_block_data;
|
||||
|
||||
typedef struct {
|
||||
byte_t abtKeyA[6];
|
||||
byte_t abtAccessBits[4];
|
||||
byte_t abtKeyB[6];
|
||||
} mifare_block_trailer;
|
||||
|
||||
typedef union {
|
||||
mifare_block_manufacturer mbm;
|
||||
mifare_block_data mbd;
|
||||
mifare_block_trailer mbt;
|
||||
} mifare_block;
|
||||
|
||||
typedef struct {
|
||||
mifare_block amb[256];
|
||||
} mifare_tag;
|
||||
|
||||
#endif // _LIBNFC_MIFARE_TAG_H_
|
||||
49
src/examples/mifareultag.h
Normal file
49
src/examples/mifareultag.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
|
||||
Public platform independent Near Field Communication (NFC) library
|
||||
Copyright (C) 2009, Roel Verdult
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _LIBNFC_MIFARE_UL_TAG_H_
|
||||
#define _LIBNFC_MIFARE_UL_TAG_H_
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
typedef struct {
|
||||
byte_t sn0[3];
|
||||
byte_t btBCC0;
|
||||
byte_t sn1[4];
|
||||
byte_t btBCC1;
|
||||
byte_t internal;
|
||||
byte_t lock[2];
|
||||
byte_t otp[4];
|
||||
} mifareul_block_manufacturer;
|
||||
|
||||
typedef struct {
|
||||
byte_t abtData[16];
|
||||
} mifareul_block_data;
|
||||
|
||||
typedef union {
|
||||
mifareul_block_manufacturer mbm;
|
||||
mifareul_block_data mbd;
|
||||
} mifareul_block;
|
||||
|
||||
typedef struct {
|
||||
mifareul_block amb[4];
|
||||
} mifareul_tag;
|
||||
|
||||
#endif // _LIBNFC_MIFARE_UL_TAG_H_
|
||||
30
src/examples/nfc-anticol.1
Normal file
30
src/examples/nfc-anticol.1
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
.TH NFC-ANTICOL 1 "June 26, 2009"
|
||||
.SH NAME
|
||||
nfc-anticol \- Demonstration NFC anti-collison command line tool based on libnfc
|
||||
.SH SYNOPSIS
|
||||
.B nfc-anticol
|
||||
.SH DESCRIPTION
|
||||
.B nfc-anticol
|
||||
is an anti-collision demonstration tool for ISO/IEC 14443-A tags, performed
|
||||
by custom constructed frames. The first frame must be a short frame which
|
||||
is only 7 bits long. Commercial SDK's often don't support a feature to send
|
||||
frames that are not a multiple of 8 bits (1 byte) long.
|
||||
This makes it impossible to do the anti-collision yourself.
|
||||
The developer has to rely on closed proprietary software and should hope it does not contain vulnerabilities during the anti-collision phase.
|
||||
Performing the anti-collision using custom frames could protect against a malicious tag that, for example, violates the standard by sending frames with unsupported lengths.
|
||||
|
||||
.SH BUGS
|
||||
Please report any bugs on the
|
||||
.B libnfc
|
||||
forum at
|
||||
.BR http://www.libnfc.org/community/ "."
|
||||
.SH LICENCE
|
||||
.B libnfc
|
||||
and
|
||||
.B nfc-tools
|
||||
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||
.SH AUTHORS
|
||||
Roel Verdult <roel@libnfc.org>
|
||||
.PP
|
||||
This manual page was written by Romuald Conty <romuald.conty@free.fr>.
|
||||
It is licensed under the terms of the GNU GPL (version 2 or later).
|
||||
199
src/examples/nfc-anticol.c
Normal file
199
src/examples/nfc-anticol.c
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
|
||||
Public platform independent Near Field Communication (NFC) library
|
||||
Copyright (C) 2009, Roel Verdult
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libnfc.h"
|
||||
|
||||
#include "messages.h"
|
||||
|
||||
#define SAK_FLAG_ATS_SUPPORTED 0x20
|
||||
|
||||
static byte_t abtRx[MAX_FRAME_LEN];
|
||||
static size_t szRxBits;
|
||||
static size_t szRxLen;
|
||||
static byte_t abtUid[10];
|
||||
static size_t szUidLen = 4;
|
||||
static dev_info* pdi;
|
||||
|
||||
bool quiet_output = false;
|
||||
|
||||
// ISO14443A Anti-Collision Commands
|
||||
byte_t abtReqa [1] = { 0x26 };
|
||||
byte_t abtSelectAll [2] = { 0x93,0x20 };
|
||||
byte_t abtSelectTag [9] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
||||
byte_t abtRats [4] = { 0xe0,0x50,0xbc,0xa5 };
|
||||
byte_t abtHalt [4] = { 0x50,0x00,0x57,0xcd };
|
||||
|
||||
bool transmit_bits(const byte_t* pbtTx, const size_t szTxBits)
|
||||
{
|
||||
// Show transmitted command
|
||||
if(!quiet_output)
|
||||
{
|
||||
printf("R: ");
|
||||
print_hex_bits(pbtTx,szTxBits);
|
||||
}
|
||||
|
||||
// Transmit the bit frame command, we don't use the arbitrary parity feature
|
||||
if (!nfc_initiator_transceive_bits(pdi,pbtTx,szTxBits,NULL,abtRx,&szRxBits,NULL)) return false;
|
||||
|
||||
// Show received answer
|
||||
if(!quiet_output)
|
||||
{
|
||||
printf("T: ");
|
||||
print_hex_bits(abtRx,szRxBits);
|
||||
}
|
||||
|
||||
// Succesful transfer
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool transmit_bytes(const byte_t* pbtTx, const size_t szTxLen)
|
||||
{
|
||||
// Show transmitted command
|
||||
if(!quiet_output)
|
||||
{
|
||||
printf("R: ");
|
||||
print_hex(pbtTx,szTxLen);
|
||||
}
|
||||
|
||||
// Transmit the command bytes
|
||||
if (!nfc_initiator_transceive_bytes(pdi,pbtTx,szTxLen,abtRx,&szRxLen)) return false;
|
||||
|
||||
// Show received answer
|
||||
if(!quiet_output)
|
||||
{
|
||||
printf("T: ");
|
||||
print_hex(abtRx,szRxLen);
|
||||
}
|
||||
|
||||
// Succesful transfer
|
||||
return true;
|
||||
}
|
||||
|
||||
void print_usage(char* argv[])
|
||||
{
|
||||
printf("Usage: %s [OPTIONS]\n", argv[0]);
|
||||
printf("Options:\n");
|
||||
printf("\t-h\tHelp. Print this message.\n");
|
||||
printf("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
|
||||
}
|
||||
|
||||
int main(int argc,char* argv[])
|
||||
{
|
||||
int arg;
|
||||
|
||||
// Get commandline options
|
||||
for (arg=1;arg<argc;arg++) {
|
||||
if (0 == strcmp(argv[arg], "-h")) {
|
||||
print_usage(argv);
|
||||
return 0;
|
||||
} else if (0 == strcmp(argv[arg], "-q")) {
|
||||
INFO("Quiet mode.");
|
||||
quiet_output = true;
|
||||
} else {
|
||||
ERR("%s is not supported option.", argv[arg]);
|
||||
print_usage(argv);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to open the NFC reader
|
||||
pdi = nfc_connect(NULL);
|
||||
|
||||
if (!pdi)
|
||||
{
|
||||
printf("Error connecting NFC reader\n");
|
||||
return 1;
|
||||
}
|
||||
nfc_initiator_init(pdi);
|
||||
|
||||
// Drop the field for a while
|
||||
nfc_configure(pdi,DCO_ACTIVATE_FIELD,false);
|
||||
|
||||
// Configure the CRC and Parity settings
|
||||
nfc_configure(pdi,DCO_HANDLE_CRC,false);
|
||||
nfc_configure(pdi,DCO_HANDLE_PARITY,true);
|
||||
|
||||
// Enable field so more power consuming cards can power themselves up
|
||||
nfc_configure(pdi,DCO_ACTIVATE_FIELD,true);
|
||||
|
||||
printf("\nConnected to NFC reader: %s\n\n",pdi->acName);
|
||||
|
||||
// Send the 7 bits request command specified in ISO 14443A (0x26)
|
||||
if (!transmit_bits(abtReqa,7))
|
||||
{
|
||||
printf("Error: No tag available\n");
|
||||
nfc_disconnect(pdi);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Anti-collision
|
||||
transmit_bytes(abtSelectAll,2);
|
||||
|
||||
// Save the UID
|
||||
memcpy(abtUid,abtRx,4);
|
||||
memcpy(abtSelectTag+2,abtRx,5);
|
||||
append_iso14443a_crc(abtSelectTag,7);
|
||||
transmit_bytes(abtSelectTag,9);
|
||||
|
||||
// Test if we are dealing with a 4 bytes uid
|
||||
if (abtUid[0]!= 0x88)
|
||||
{
|
||||
szUidLen = 4;
|
||||
} else {
|
||||
// We have to do the anti-collision for cascade level 2
|
||||
abtSelectAll[0] = 0x95;
|
||||
abtSelectTag[0] = 0x95;
|
||||
|
||||
// Anti-collision
|
||||
transmit_bytes(abtSelectAll,2);
|
||||
|
||||
// Save the UID
|
||||
memcpy(abtUid+4,abtRx,4);
|
||||
memcpy(abtSelectTag+2,abtRx,5);
|
||||
append_iso14443a_crc(abtSelectTag,7);
|
||||
transmit_bytes(abtSelectTag,9);
|
||||
szUidLen = 7;
|
||||
}
|
||||
|
||||
// Request ATS, this only applies to tags that support ISO 14443A-4
|
||||
if (abtRx[0] & SAK_FLAG_ATS_SUPPORTED) transmit_bytes(abtRats,4);
|
||||
|
||||
// Done, halt the tag now
|
||||
transmit_bytes(abtHalt,4);
|
||||
|
||||
printf("\nFound tag with UID: ");
|
||||
if (szUidLen == 4)
|
||||
{
|
||||
printf("%08x\n",swap_endian32(abtUid));
|
||||
} else {
|
||||
printf("%014llx\n",swap_endian64(abtUid)&0x00ffffffffffffffull);
|
||||
}
|
||||
|
||||
nfc_disconnect(pdi);
|
||||
return 0;
|
||||
}
|
||||
37
src/examples/nfc-emulate.1
Normal file
37
src/examples/nfc-emulate.1
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
.TH NFC-EMULATE 1 "June 26, 2009"
|
||||
.SH NAME
|
||||
nfc-emulate \- NFC target emulation command line tool based on libnfc
|
||||
.SH SYNOPSIS
|
||||
.B nfc-emulate
|
||||
.RI [ UID ]
|
||||
.SH DESCRIPTION
|
||||
.B nfc-emulate
|
||||
is an tag emulatation tool. Tag emulation is one of the main added features in NFC.
|
||||
To avoid abuse of existing systems, manufacturers of the NFC controller intentionally did not
|
||||
support emulation of custom UID numbers.
|
||||
The emulate tool demonstrates that this can still be done using transmission of raw-frames,
|
||||
and the desired UID can be optionally specified.
|
||||
Fast communication is necessary to respond in time during the anti-collision protocol.
|
||||
Using the USB interface gives some timing issues but an embedded microprocessor could
|
||||
be fast enough to emulate a tag with any UID. This makes it a serious thread
|
||||
for security systems that rely only on the uniqueness of the UID.
|
||||
|
||||
.SH OPTIONS
|
||||
.IR UID
|
||||
8 hex digits format that represents desired UID (default is DEADBEAF).
|
||||
|
||||
.SH BUGS
|
||||
Please report any bugs on the
|
||||
.B libnfc
|
||||
forum at
|
||||
.BR http://www.libnfc.org/community/ "."
|
||||
.SH LICENCE
|
||||
.B libnfc
|
||||
and
|
||||
.B nfc-tools
|
||||
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||
.SH AUTHORS
|
||||
Roel Verdult <roel@libnfc.org>
|
||||
.PP
|
||||
This manual page was written by Romuald Conty <romuald.conty@free.fr>.
|
||||
It is licensed under the terms of the GNU GPL (version 2 or later).
|
||||
160
src/examples/nfc-emulate.c
Normal file
160
src/examples/nfc-emulate.c
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
|
||||
Public platform independent Near Field Communication (NFC) library
|
||||
Copyright (C) 2009, Roel Verdult
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libnfc.h"
|
||||
#include "messages.h"
|
||||
|
||||
static byte_t abtRecv[MAX_FRAME_LEN];
|
||||
static size_t szRecvBits;
|
||||
static dev_info* pdi;
|
||||
|
||||
// ISO14443A Anti-Collision response
|
||||
byte_t abtAtqa [2] = { 0x04,0x00 };
|
||||
byte_t abtUidBcc [5] = { 0xDE,0xAD,0xBE,0xAF,0x62 };
|
||||
byte_t abtSak [9] = { 0x08,0xb6,0xdd };
|
||||
|
||||
void print_usage(char* argv[])
|
||||
{
|
||||
printf("Usage: %s [OPTIONS] [UID]\n", argv[0]);
|
||||
printf("Options:\n");
|
||||
printf("\t-h\tHelp. Print this message.\n");
|
||||
printf("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
|
||||
printf("\n");
|
||||
printf("\t[UID]\tUID to emulate, specified as 8 HEX digits (default is DEADBEAF).\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
byte_t* pbtTx = NULL;
|
||||
size_t szTxBits;
|
||||
bool quiet_output = false;
|
||||
|
||||
int arg, i;
|
||||
|
||||
// Get commandline options
|
||||
for (arg=1;arg<argc;arg++) {
|
||||
if (0 == strcmp(argv[arg], "-h")) {
|
||||
print_usage(argv);
|
||||
return 0;
|
||||
} else if (0 == strcmp(argv[arg], "-q")) {
|
||||
INFO("Quiet mode.");
|
||||
quiet_output = true;
|
||||
} else if((arg == argc-1) && (strlen(argv[arg]) == 8)) { // See if UID was specified as HEX string
|
||||
byte_t abtTmp[3] = { 0x00,0x00,0x00 };
|
||||
printf("[+] Using UID: %s\n",argv[arg]);
|
||||
abtUidBcc[4]= 0x00;
|
||||
for(i= 0; i < 4; ++i)
|
||||
{
|
||||
memcpy(abtTmp,argv[arg]+i*2,2);
|
||||
abtUidBcc[i]= (byte_t) strtol((char*)abtTmp,NULL,16);
|
||||
abtUidBcc[4] ^= abtUidBcc[i];
|
||||
}
|
||||
} else {
|
||||
ERR("%s is not supported option.", argv[arg]);
|
||||
print_usage(argv);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to open the NFC reader
|
||||
pdi = nfc_connect(NULL);
|
||||
|
||||
if (pdi == INVALID_DEVICE_INFO)
|
||||
{
|
||||
printf("Error connecting NFC reader\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf("[+] Connected to NFC reader: %s\n",pdi->acName);
|
||||
printf("[+] Try to break out the auto-emulation, this requires a second reader!\n");
|
||||
printf("[+] To do this, please send any command after the anti-collision\n");
|
||||
printf("[+] For example, send a RATS command or use the \"nfc-anticol\" tool\n");
|
||||
if (!nfc_target_init(pdi,abtRecv,&szRecvBits))
|
||||
{
|
||||
printf("Error: Could not come out of auto-emulation, no command was received\n");
|
||||
return 1;
|
||||
}
|
||||
printf("[+] Received initiator command: ");
|
||||
print_hex_bits(abtRecv,szRecvBits);
|
||||
printf("[+] Configuring communication\n");
|
||||
nfc_configure(pdi,DCO_HANDLE_CRC,false);
|
||||
nfc_configure(pdi,DCO_HANDLE_PARITY,true);
|
||||
printf("[+] Done, the emulated tag is initialized with UID: %02X%02X%02X%02X\n\n",abtUidBcc[0],abtUidBcc[1],abtUidBcc[2],abtUidBcc[3]);
|
||||
|
||||
while(true)
|
||||
{
|
||||
// Test if we received a frame
|
||||
if (nfc_target_receive_bits(pdi,abtRecv,&szRecvBits,NULL))
|
||||
{
|
||||
// Prepare the command to send back for the anti-collision request
|
||||
switch(szRecvBits)
|
||||
{
|
||||
case 7: // Request or Wakeup
|
||||
pbtTx = abtAtqa;
|
||||
szTxBits = 16;
|
||||
// New anti-collsion session started
|
||||
if (!quiet_output) printf("\n");
|
||||
break;
|
||||
|
||||
case 16: // Select All
|
||||
pbtTx = abtUidBcc;
|
||||
szTxBits = 40;
|
||||
break;
|
||||
|
||||
case 72: // Select Tag
|
||||
pbtTx = abtSak;
|
||||
szTxBits = 24;
|
||||
break;
|
||||
|
||||
default: // unknown length?
|
||||
szTxBits = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!quiet_output)
|
||||
{
|
||||
printf("R: ");
|
||||
print_hex_bits(abtRecv,szRecvBits);
|
||||
}
|
||||
|
||||
// Test if we know how to respond
|
||||
if(szTxBits)
|
||||
{
|
||||
// Send and print the command to the screen
|
||||
nfc_target_send_bits(pdi,pbtTx,szTxBits,NULL);
|
||||
if(!quiet_output)
|
||||
{
|
||||
printf("T: ");
|
||||
print_hex_bits(pbtTx,szTxBits);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nfc_disconnect(pdi);
|
||||
}
|
||||
|
||||
27
src/examples/nfc-list.1
Normal file
27
src/examples/nfc-list.1
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
.TH NFC-LIST 1 "June 26, 2009"
|
||||
.SH NAME
|
||||
nfc-list \- List NFC targets command line tool based on libnfc
|
||||
.SH SYNOPSIS
|
||||
.B nfc-list
|
||||
.SH DESCRIPTION
|
||||
.B nfc-list
|
||||
utility attempts to select available tags in the field. The NFC
|
||||
controller is used to perform the selection procedure. This is different for each modulation type.
|
||||
It tries to find a ISO/IEC 14443 type A, type B, Felica or Jewel Topaz tags.
|
||||
This tool demonstrates that it is possible to setup a simple NFC system using less than 10 lines of code.
|
||||
|
||||
.SH BUGS
|
||||
Please report any bugs on the
|
||||
.B libnfc
|
||||
forum at
|
||||
.BR http://www.libnfc.org/community/ "."
|
||||
.SH LICENCE
|
||||
.B libnfc
|
||||
and
|
||||
.B nfc-tools
|
||||
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||
.SH AUTHORS
|
||||
Roel Verdult <roel@libnfc.org>
|
||||
.PP
|
||||
This manual page was written by Romuald Conty <romuald.conty@free.fr>.
|
||||
It is licensed under the terms of the GNU GPL (version 2 or later).
|
||||
117
src/examples/nfc-list.c
Normal file
117
src/examples/nfc-list.c
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
|
||||
Public platform independent Near Field Communication (NFC) library
|
||||
Copyright (C) 2009, Roel Verdult
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "libnfc.h"
|
||||
#include "messages.h"
|
||||
|
||||
static dev_info* pdi;
|
||||
static byte_t abtFelica[5] = { 0x00, 0xff, 0xff, 0x00, 0x00 };
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
tag_info ti;
|
||||
|
||||
// Try to open the NFC device
|
||||
pdi = nfc_connect(NULL);
|
||||
|
||||
// If specific device is wanted, i.e. an ARYGON device on /dev/ttyUSB0
|
||||
/*
|
||||
nfc_device_desc_t ndd;
|
||||
ndd.pcDriver = "ARYGON";
|
||||
ndd.pcPort = "/dev/ttyUSB0";
|
||||
ndd.uiSpeed = 115200;
|
||||
|
||||
pdi = nfc_connect(&ndd);
|
||||
*/
|
||||
|
||||
if (pdi == INVALID_DEVICE_INFO)
|
||||
{
|
||||
ERR("Unable to connect to NFC device.");
|
||||
return 1;
|
||||
}
|
||||
nfc_initiator_init(pdi);
|
||||
|
||||
// Drop the field for a while
|
||||
nfc_configure(pdi,DCO_ACTIVATE_FIELD,false);
|
||||
|
||||
// Let the reader only try once to find a tag
|
||||
nfc_configure(pdi,DCO_INFINITE_SELECT,false);
|
||||
|
||||
// Configure the CRC and Parity settings
|
||||
nfc_configure(pdi,DCO_HANDLE_CRC,true);
|
||||
nfc_configure(pdi,DCO_HANDLE_PARITY,true);
|
||||
|
||||
// Enable field so more power consuming cards can power themselves up
|
||||
nfc_configure(pdi,DCO_ACTIVATE_FIELD,true);
|
||||
|
||||
printf("Connected to NFC reader: %s\n\n",pdi->acName);
|
||||
|
||||
// Poll for a ISO14443A (MIFARE) tag
|
||||
if (nfc_initiator_select_tag(pdi,IM_ISO14443A_106,NULL,0,&ti))
|
||||
{
|
||||
printf("The following (NFC) ISO14443A tag was found:\n\n");
|
||||
printf(" ATQA (SENS_RES): "); print_hex(ti.tia.abtAtqa,2);
|
||||
printf(" UID (NFCID%c): ",(ti.tia.abtUid[0]==0x08?'3':'1')); print_hex(ti.tia.abtUid,ti.tia.szUidLen);
|
||||
printf(" SAK (SEL_RES): "); print_hex(&ti.tia.btSak,1);
|
||||
if (ti.tia.szAtsLen)
|
||||
{
|
||||
printf(" ATS (ATR): ");
|
||||
print_hex(ti.tia.abtAts,ti.tia.szAtsLen);
|
||||
}
|
||||
}
|
||||
|
||||
// Poll for a Felica tag
|
||||
if (nfc_initiator_select_tag(pdi,IM_FELICA_212,abtFelica,5,&ti) || nfc_initiator_select_tag(pdi,IM_FELICA_424,abtFelica,5,&ti))
|
||||
{
|
||||
printf("The following (NFC) Felica tag was found:\n\n");
|
||||
printf("%18s","ID (NFCID2): "); print_hex(ti.tif.abtId,8);
|
||||
printf("%18s","Parameter (PAD): "); print_hex(ti.tif.abtPad,8);
|
||||
}
|
||||
|
||||
// Poll for a ISO14443B tag
|
||||
if (nfc_initiator_select_tag(pdi,IM_ISO14443B_106,(byte_t*)"\x00",1,&ti))
|
||||
{
|
||||
printf("The following (NFC) ISO14443-B tag was found:\n\n");
|
||||
printf(" ATQB: "); print_hex(ti.tib.abtAtqb,12);
|
||||
printf(" ID: "); print_hex(ti.tib.abtId,4);
|
||||
printf(" CID: %02x\n",ti.tib.btCid);
|
||||
if (ti.tib.szInfLen>0)
|
||||
{
|
||||
printf(" INF: "); print_hex(ti.tib.abtInf,ti.tib.szInfLen);
|
||||
}
|
||||
printf("PARAMS: %02x %02x %02x %02x\n",ti.tib.btParam1,ti.tib.btParam2,ti.tib.btParam3,ti.tib.btParam4);
|
||||
}
|
||||
|
||||
// Poll for a Jewel tag
|
||||
if (nfc_initiator_select_tag(pdi,IM_JEWEL_106,NULL,0,&ti))
|
||||
{
|
||||
// No test results yet
|
||||
printf("jewel\n");
|
||||
}
|
||||
|
||||
nfc_disconnect(pdi);
|
||||
return 1;
|
||||
}
|
||||
57
src/examples/nfc-mftool.1
Normal file
57
src/examples/nfc-mftool.1
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
.TH NFC-MFTOOL 1 "June 26, 2009"
|
||||
.SH NAME
|
||||
nfc-mftool \- Mifare Classic command line tool based on libnfc
|
||||
.SH SYNOPSIS
|
||||
.B nfc-mftool
|
||||
.RI \fR\fBr\fR|\fBw\fR
|
||||
.RI \fR\fBa\fR|\fBb\fR
|
||||
.IR KEYS
|
||||
.IR DUMP
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B nfc-mftool
|
||||
is an Mifare Classic tool that allow to read or write
|
||||
.IR DUMP
|
||||
file using Mifare keys provide in
|
||||
.IR KEYS
|
||||
file.
|
||||
|
||||
The Mifare Classic tag is one of the most widely used RFID tags.
|
||||
The firmware in the NFC controller supports authenticating, reading and writing to/from Mifare Classic tags.
|
||||
This tool demonstrate the speed of this library and its easy-of-use.
|
||||
It possible to read and write the complete content of a Mifare Classic 4KB tag within 1 second.
|
||||
It uses a binary Mifare Dump File to store the keys and date for all sectors.
|
||||
|
||||
.SH OPTIONS
|
||||
.BR r " | " w
|
||||
Perform read from (
|
||||
.B r
|
||||
) or write to (
|
||||
.B w
|
||||
)card.
|
||||
.TP
|
||||
.BR a " | " b
|
||||
Use A or B Mifare keys.
|
||||
.TP
|
||||
.IR KEYS
|
||||
Mifare dump that contain Mifare keys.
|
||||
.TP
|
||||
.IR DUMP
|
||||
Used to write card to file ( r ) or file to card ( w )
|
||||
|
||||
|
||||
.SH BUGS
|
||||
Please report any bugs on the
|
||||
.B libnfc
|
||||
forum at
|
||||
.BR http://www.libnfc.org/community/ "."
|
||||
.SH LICENCE
|
||||
.B libnfc
|
||||
and
|
||||
.B nfc-tools
|
||||
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||
.SH AUTHORS
|
||||
Roel Verdult <roel@libnfc.org>
|
||||
.PP
|
||||
This manual page was written by Romuald Conty <romuald.conty@free.fr>.
|
||||
It is licensed under the terms of the GNU GPL (version 2 or later).
|
||||
423
src/examples/nfc-mftool.c
Normal file
423
src/examples/nfc-mftool.c
Normal file
|
|
@ -0,0 +1,423 @@
|
|||
/*
|
||||
|
||||
Public platform independent Near Field Communication (NFC) library
|
||||
Copyright (C) 2009, Roel Verdult
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libnfc.h"
|
||||
#include "mifaretag.h"
|
||||
|
||||
static dev_info* pdi;
|
||||
static tag_info ti;
|
||||
static mifare_param mp;
|
||||
static mifare_tag mtKeys;
|
||||
static mifare_tag mtDump;
|
||||
static bool bUseKeyA;
|
||||
static bool bUseKeyFile;
|
||||
static uint32_t uiBlocks;
|
||||
static byte_t keys[] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xd3,0xf7,0xd3,0xf7,0xd3,0xf7,
|
||||
0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,
|
||||
0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,
|
||||
0x4d,0x3a,0x99,0xc3,0x51,0xdd,
|
||||
0x1a,0x98,0x2c,0x7e,0x45,0x9a,
|
||||
0xaa,0xbb,0xcc,0xdd,0xee,0xff,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00
|
||||
};
|
||||
static size_t num_keys = sizeof(keys) / 6;
|
||||
|
||||
bool is_first_block(uint32_t uiBlock)
|
||||
{
|
||||
// Test if we are in the small or big sectors
|
||||
if (uiBlock < 128) return ((uiBlock)%4 == 0); else return ((uiBlock)%16 == 0);
|
||||
}
|
||||
|
||||
bool is_trailer_block(uint32_t uiBlock)
|
||||
{
|
||||
// Test if we are in the small or big sectors
|
||||
if (uiBlock < 128) return ((uiBlock+1)%4 == 0); else return ((uiBlock+1)%16 == 0);
|
||||
}
|
||||
|
||||
uint32_t get_trailer_block(uint32_t uiFirstBlock)
|
||||
{
|
||||
// Test if we are in the small or big sectors
|
||||
if (uiFirstBlock<128) return uiFirstBlock+3; else return uiFirstBlock+15;
|
||||
}
|
||||
|
||||
bool authenticate(uint32_t uiBlock)
|
||||
{
|
||||
mifare_cmd mc;
|
||||
uint32_t uiTrailerBlock;
|
||||
size_t key_index;
|
||||
|
||||
// Key file authentication.
|
||||
if (bUseKeyFile)
|
||||
{
|
||||
// Set the authentication information (uid)
|
||||
memcpy(mp.mpa.abtUid,ti.tia.abtUid,4);
|
||||
|
||||
// Locate the trailer (with the keys) used for this sector
|
||||
uiTrailerBlock = get_trailer_block(uiBlock);
|
||||
|
||||
// Determin if we should use the a or the b key
|
||||
if (bUseKeyA)
|
||||
{
|
||||
mc = MC_AUTH_A;
|
||||
memcpy(mp.mpa.abtKey,mtKeys.amb[uiTrailerBlock].mbt.abtKeyA,6);
|
||||
} else {
|
||||
mc = MC_AUTH_B;
|
||||
memcpy(mp.mpa.abtKey,mtKeys.amb[uiTrailerBlock].mbt.abtKeyB,6);
|
||||
}
|
||||
|
||||
// Try to authenticate for the current sector
|
||||
if (nfc_initiator_mifare_cmd(pdi,mc,uiBlock,&mp))
|
||||
return true;
|
||||
}
|
||||
|
||||
// Auto authentication.
|
||||
else
|
||||
{
|
||||
// Determin if we should use the a or the b key
|
||||
mc = (bUseKeyA) ? MC_AUTH_A : MC_AUTH_B;
|
||||
|
||||
// Set the authentication information (uid)
|
||||
memcpy(mp.mpa.abtUid,ti.tia.abtUid,4);
|
||||
|
||||
for (key_index = 0; key_index < num_keys; key_index++)
|
||||
{
|
||||
memcpy(mp.mpa.abtKey, keys + (key_index*6), 6);
|
||||
if (nfc_initiator_mifare_cmd(pdi, mc, uiBlock, &mp))
|
||||
{
|
||||
/**
|
||||
* @note: what about the other key?
|
||||
*/
|
||||
if (bUseKeyA)
|
||||
memcpy(mtKeys.amb[uiBlock].mbt.abtKeyA,&mp.mpa.abtKey,6);
|
||||
else
|
||||
memcpy(mtKeys.amb[uiBlock].mbt.abtKeyB,&mp.mpa.abtKey,6);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nfc_initiator_select_tag(pdi, IM_ISO14443A_106, mp.mpa.abtUid, 4, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool read_card()
|
||||
{
|
||||
int32_t iBlock;
|
||||
bool bFailure = false;
|
||||
|
||||
printf("Reading out %d blocks |",uiBlocks+1);
|
||||
|
||||
// Read the card from end to begin
|
||||
for (iBlock=uiBlocks; iBlock>=0; iBlock--)
|
||||
{
|
||||
// Authenticate everytime we reach a trailer block
|
||||
if (is_trailer_block(iBlock))
|
||||
{
|
||||
// Show if the readout went well
|
||||
if (bFailure)
|
||||
{
|
||||
printf("x");
|
||||
// When a failure occured we need to redo the anti-collision
|
||||
if (!nfc_initiator_select_tag(pdi,IM_ISO14443A_106,NULL,0,&ti))
|
||||
{
|
||||
printf("!\nError: tag was removed\n");
|
||||
return 1;
|
||||
}
|
||||
bFailure = false;
|
||||
} else {
|
||||
// Skip this the first time, bFailure it means nothing (yet)
|
||||
if (iBlock != uiBlocks)
|
||||
{
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
|
||||
// Try to authenticate for the current sector
|
||||
if (!authenticate(iBlock))
|
||||
{
|
||||
printf("!\nError: authentication failed for block %02x\n",iBlock);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to read out the trailer
|
||||
if (nfc_initiator_mifare_cmd(pdi,MC_READ,iBlock,&mp))
|
||||
{
|
||||
// Copy the keys over from our key dump and store the retrieved access bits
|
||||
memcpy(mtDump.amb[iBlock].mbt.abtKeyA,mtKeys.amb[iBlock].mbt.abtKeyA,6);
|
||||
memcpy(mtDump.amb[iBlock].mbt.abtAccessBits,mp.mpd.abtData+6,4);
|
||||
memcpy(mtDump.amb[iBlock].mbt.abtKeyB,mtKeys.amb[iBlock].mbt.abtKeyB,6);
|
||||
}
|
||||
} else {
|
||||
// Make sure a earlier readout did not fail
|
||||
if (!bFailure)
|
||||
{
|
||||
// Try to read out the data block
|
||||
if (nfc_initiator_mifare_cmd(pdi,MC_READ,iBlock,&mp))
|
||||
{
|
||||
memcpy(mtDump.amb[iBlock].mbd.abtData,mp.mpd.abtData,16);
|
||||
} else {
|
||||
bFailure = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("%c|\n",(bFailure)?'x':'.');
|
||||
fflush(stdout);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool write_card()
|
||||
{
|
||||
uint32_t uiBlock;
|
||||
bool bFailure = false;
|
||||
|
||||
printf("Writing %d blocks |",uiBlocks+1);
|
||||
|
||||
// Write the card from begin to end;
|
||||
for (uiBlock=0; uiBlock<=uiBlocks; uiBlock++)
|
||||
{
|
||||
// Authenticate everytime we reach the first sector of a new block
|
||||
if (is_first_block(uiBlock))
|
||||
{
|
||||
// Show if the readout went well
|
||||
if (bFailure)
|
||||
{
|
||||
printf("x");
|
||||
// When a failure occured we need to redo the anti-collision
|
||||
if (!nfc_initiator_select_tag(pdi,IM_ISO14443A_106,NULL,0,&ti))
|
||||
{
|
||||
printf("!\nError: tag was removed\n");
|
||||
return false;
|
||||
}
|
||||
bFailure = false;
|
||||
} else {
|
||||
// Skip this the first time, bFailure it means nothing (yet)
|
||||
if (uiBlock != 0)
|
||||
{
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
|
||||
// Try to authenticate for the current sector
|
||||
if (!authenticate(uiBlock))
|
||||
{
|
||||
printf("!\nError: authentication failed for block %02x\n",uiBlock);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_trailer_block(uiBlock))
|
||||
{
|
||||
// Copy the keys over from our key dump and store the retrieved access bits
|
||||
memcpy(mp.mpd.abtData,mtDump.amb[uiBlock].mbt.abtKeyA,6);
|
||||
memcpy(mp.mpd.abtData+6,mtDump.amb[uiBlock].mbt.abtAccessBits,4);
|
||||
memcpy(mp.mpd.abtData+10,mtDump.amb[uiBlock].mbt.abtKeyB,6);
|
||||
|
||||
// Try to write the trailer
|
||||
nfc_initiator_mifare_cmd(pdi,MC_WRITE,uiBlock,&mp);
|
||||
|
||||
} else {
|
||||
|
||||
// The first block 0x00 is read only, skip this
|
||||
if (uiBlock == 0) continue;
|
||||
|
||||
// Make sure a earlier write did not fail
|
||||
if (!bFailure)
|
||||
{
|
||||
// Try to write the data block
|
||||
memcpy(mp.mpd.abtData,mtDump.amb[uiBlock].mbd.abtData,16);
|
||||
if (!nfc_initiator_mifare_cmd(pdi,MC_WRITE,uiBlock,&mp)) bFailure = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("%c|\n",(bFailure)?'x':'.');
|
||||
fflush(stdout);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
bool b4K;
|
||||
bool bReadAction;
|
||||
byte_t* pbtUID;
|
||||
FILE* pfKeys = NULL;
|
||||
FILE* pfDump = NULL;
|
||||
|
||||
if (argc < 4)
|
||||
{
|
||||
printf("\n");
|
||||
printf("%s r|w a|b <dump.mfd> [<keys.mfd>]\n", argv[0]);
|
||||
printf("\n");
|
||||
printf("r|w - Perform read from (r) or write to (w) card\n");
|
||||
printf("a|b - Use A or B keys for action\n");
|
||||
printf("<dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
|
||||
printf("<keys.mfd> - MiFare Dump (MFD) that contain the keys (optional)\n");
|
||||
printf("\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\nChecking arguments and settings\n");
|
||||
|
||||
bReadAction = (tolower(*(argv[1])) == 'r');
|
||||
bUseKeyA = (tolower(*(argv[2])) == 'a');
|
||||
bUseKeyFile = (argc > 4);
|
||||
|
||||
if (bUseKeyFile)
|
||||
{
|
||||
pfKeys = fopen(argv[4],"rb");
|
||||
if (pfKeys == NULL)
|
||||
{
|
||||
printf("Could not open file: %s\n",argv[3]);
|
||||
return 1;
|
||||
}
|
||||
if (fread(&mtKeys,1,sizeof(mtKeys),pfKeys) != sizeof(mtKeys))
|
||||
{
|
||||
printf("Could not read from keys file: %s\n",argv[4]);
|
||||
fclose(pfKeys);
|
||||
return 1;
|
||||
}
|
||||
fclose(pfKeys);
|
||||
}
|
||||
|
||||
if (bReadAction)
|
||||
{
|
||||
memset(&mtDump,0x00,sizeof(mtDump));
|
||||
} else {
|
||||
pfDump = fopen(argv[3],"rb");
|
||||
|
||||
if (pfDump == NULL)
|
||||
{
|
||||
printf("Could not open dump file: %s\n",argv[3]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fread(&mtDump,1,sizeof(mtDump),pfDump) != sizeof(mtDump))
|
||||
{
|
||||
printf("Could not read from dump file: %s\n",argv[3]);
|
||||
fclose(pfDump);
|
||||
return 1;
|
||||
}
|
||||
fclose(pfDump);
|
||||
}
|
||||
printf("Succesful opened MIFARE the required files\n");
|
||||
|
||||
// Try to open the NFC reader
|
||||
pdi = nfc_connect(NULL);
|
||||
if (pdi == INVALID_DEVICE_INFO)
|
||||
{
|
||||
printf("Error connecting NFC reader\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
nfc_initiator_init(pdi);
|
||||
|
||||
// Drop the field for a while
|
||||
nfc_configure(pdi,DCO_ACTIVATE_FIELD,false);
|
||||
|
||||
// Let the reader only try once to find a tag
|
||||
nfc_configure(pdi,DCO_INFINITE_SELECT,false);
|
||||
nfc_configure(pdi,DCO_HANDLE_CRC,true);
|
||||
nfc_configure(pdi,DCO_HANDLE_PARITY,true);
|
||||
|
||||
// Enable field so more power consuming cards can power themselves up
|
||||
nfc_configure(pdi,DCO_ACTIVATE_FIELD,true);
|
||||
|
||||
printf("Connected to NFC reader: %s\n",pdi->acName);
|
||||
|
||||
// Try to find a MIFARE Classic tag
|
||||
if (!nfc_initiator_select_tag(pdi,IM_ISO14443A_106,NULL,0,&ti))
|
||||
{
|
||||
printf("Error: no tag was found\n");
|
||||
nfc_disconnect(pdi);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Test if we are dealing with a MIFARE compatible tag
|
||||
if ((ti.tia.btSak & 0x08) == 0)
|
||||
{
|
||||
printf("Error: tag is not a MIFARE Classic card\n");
|
||||
nfc_disconnect(pdi);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bUseKeyFile)
|
||||
{
|
||||
// Get the info from the key dump
|
||||
b4K = (mtKeys.amb[0].mbm.abtATQA[1] == 0x02);
|
||||
pbtUID = mtKeys.amb[0].mbm.abtUID;
|
||||
|
||||
// Compare if key dump UID is the same as the current tag UID
|
||||
if (memcmp(ti.tia.abtUid,pbtUID,4) != 0)
|
||||
{
|
||||
printf("Expected MIFARE Classic %cK card with uid: %08x\n",b4K?'4':'1',swap_endian32(pbtUID));
|
||||
}
|
||||
}
|
||||
|
||||
// Get the info from the current tag
|
||||
pbtUID = ti.tia.abtUid;
|
||||
b4K = (ti.tia.abtAtqa[1] == 0x02);
|
||||
printf("Found MIFARE Classic %cK card with uid: %08x\n",b4K?'4':'1',swap_endian32(pbtUID));
|
||||
|
||||
uiBlocks = (b4K)?0xff:0x3f;
|
||||
|
||||
if (bReadAction)
|
||||
{
|
||||
if (read_card())
|
||||
{
|
||||
printf("Writing data to file: %s\n",argv[3]);
|
||||
fflush(stdout);
|
||||
pfDump = fopen(argv[3],"wb");
|
||||
if (fwrite(&mtDump,1,sizeof(mtDump),pfDump) != sizeof(mtDump))
|
||||
{
|
||||
printf("Could not write to file: %s\n",argv[3]);
|
||||
return 1;
|
||||
}
|
||||
fclose(pfDump);
|
||||
printf("Done, all bytes dumped to file!\n");
|
||||
}
|
||||
} else {
|
||||
if (write_card())
|
||||
{
|
||||
printf("Done, all data is written to the card!\n");
|
||||
}
|
||||
}
|
||||
|
||||
nfc_disconnect(pdi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
219
src/examples/nfc-mfultool.c
Normal file
219
src/examples/nfc-mfultool.c
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
|
||||
Public platform independent Near Field Communication (NFC) library
|
||||
Copyright (C) 2009, Roel Verdult
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libnfc.h"
|
||||
#include "mifareultag.h"
|
||||
|
||||
static dev_info* pdi;
|
||||
static tag_info ti;
|
||||
static mifare_param mp;
|
||||
static mifareul_tag mtDump;
|
||||
|
||||
bool read_card()
|
||||
{
|
||||
int page;
|
||||
bool bSuccess = true;
|
||||
|
||||
// these are pages of 4 bytes each; we can read 4 pages at once.
|
||||
for (page = 0; page <= 0xF; page += 4){
|
||||
// Try to read out the data block
|
||||
if (nfc_initiator_mifare_cmd(pdi,MC_READ,page,&mp))
|
||||
{
|
||||
memcpy(mtDump.amb[page / 4].mbd.abtData, mp.mpd.abtData, 16);
|
||||
} else {
|
||||
bSuccess = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
bool write_card()
|
||||
{
|
||||
uint32_t uiBlock = 0;
|
||||
int page;
|
||||
bool bFailure = false;
|
||||
|
||||
for (page = 0x4; page <= 0xF; page++) {
|
||||
// Show if the readout went well
|
||||
if (bFailure)
|
||||
{
|
||||
printf("x");
|
||||
// When a failure occured we need to redo the anti-collision
|
||||
if (!nfc_initiator_select_tag(pdi,IM_ISO14443A_106,NULL,0,&ti))
|
||||
{
|
||||
printf("!\nError: tag was removed\n");
|
||||
return false;
|
||||
}
|
||||
bFailure = false;
|
||||
} else {
|
||||
// Skip this the first time, bFailure it means nothing (yet)
|
||||
if (uiBlock != 0)
|
||||
{
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
|
||||
// Make sure a earlier write did not fail
|
||||
if (!bFailure)
|
||||
{
|
||||
// For the Mifare Ultralight, this write command can be used
|
||||
// in compatibility mode, which only actually writes the first
|
||||
// page (4 bytes). The Ultralight-specific Write command only
|
||||
// writes one page at a time.
|
||||
uiBlock = page / 4;
|
||||
memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData + ((page % 4) * 4), 16);
|
||||
if (!nfc_initiator_mifare_cmd(pdi, MC_WRITE, page, &mp)) bFailure = true;
|
||||
}
|
||||
}
|
||||
printf("%c|\n",(bFailure)?'x':'.');
|
||||
fflush(stdout);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
bool bReadAction;
|
||||
byte_t* pbtUID;
|
||||
FILE* pfDump;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
printf("\n");
|
||||
printf("%s r|w <dump.mfd>\n", argv[0]);
|
||||
printf("\n");
|
||||
printf("r|w - Perform read from or write to card\n");
|
||||
printf("<dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
|
||||
printf("\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\nChecking arguments and settings\n");
|
||||
|
||||
bReadAction = (tolower(*(argv[1])) == 'r');
|
||||
|
||||
if (bReadAction)
|
||||
{
|
||||
memset(&mtDump,0x00,sizeof(mtDump));
|
||||
} else {
|
||||
pfDump = fopen(argv[2],"rb");
|
||||
|
||||
if (pfDump == NULL)
|
||||
{
|
||||
printf("Could not open dump file: %s\n",argv[2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fread(&mtDump,1,sizeof(mtDump),pfDump) != sizeof(mtDump))
|
||||
{
|
||||
printf("Could not read from dump file: %s\n",argv[2]);
|
||||
fclose(pfDump);
|
||||
return 1;
|
||||
}
|
||||
fclose(pfDump);
|
||||
}
|
||||
printf("Succesful opened the dump file\n");
|
||||
|
||||
// Try to open the NFC reader
|
||||
pdi = nfc_connect(NULL);
|
||||
if (pdi == INVALID_DEVICE_INFO)
|
||||
{
|
||||
printf("Error connecting NFC reader\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
nfc_initiator_init(pdi);
|
||||
|
||||
// Drop the field for a while
|
||||
nfc_configure(pdi,DCO_ACTIVATE_FIELD,false);
|
||||
|
||||
// Let the reader only try once to find a tag
|
||||
nfc_configure(pdi,DCO_INFINITE_SELECT,false);
|
||||
nfc_configure(pdi,DCO_HANDLE_CRC,true);
|
||||
nfc_configure(pdi,DCO_HANDLE_PARITY,true);
|
||||
|
||||
// Enable field so more power consuming cards can power themselves up
|
||||
nfc_configure(pdi,DCO_ACTIVATE_FIELD,true);
|
||||
|
||||
printf("Connected to NFC reader: %s\n",pdi->acName);
|
||||
|
||||
// Try to find a MIFARE Ultralight tag
|
||||
if (!nfc_initiator_select_tag(pdi,IM_ISO14443A_106,NULL,0,&ti))
|
||||
{
|
||||
printf("Error: no tag was found\n");
|
||||
nfc_disconnect(pdi);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Test if we are dealing with a MIFARE compatible tag
|
||||
|
||||
if (ti.tia.abtAtqa[1] != 0x44){
|
||||
printf("Error: tag is not a MIFARE Ultralight card\n");
|
||||
nfc_disconnect(pdi);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// Get the info from the current tag
|
||||
pbtUID = ti.tia.abtUid;
|
||||
printf("Found MIFARE Ultralight card with uid: %08x\n", swap_endian32(pbtUID));
|
||||
|
||||
if (bReadAction)
|
||||
{
|
||||
if (read_card())
|
||||
{
|
||||
printf("Writing data to file: %s\n",argv[2]);
|
||||
fflush(stdout);
|
||||
pfDump = fopen(argv[2],"wb");
|
||||
if (pfDump == NULL)
|
||||
{
|
||||
printf("Could not open file: %s\n",argv[2]);
|
||||
return 1;
|
||||
}
|
||||
if (fwrite(&mtDump,1,sizeof(mtDump),pfDump) != sizeof(mtDump))
|
||||
{
|
||||
printf("Could not write to file: %s\n",argv[2]);
|
||||
return 1;
|
||||
}
|
||||
fclose(pfDump);
|
||||
printf("Done, all bytes dumped to file!\n");
|
||||
}
|
||||
} else {
|
||||
if (write_card())
|
||||
{
|
||||
printf("Done, all data is written to the card!\n");
|
||||
}
|
||||
}
|
||||
|
||||
nfc_disconnect(pdi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
28
src/examples/nfc-relay.1
Normal file
28
src/examples/nfc-relay.1
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
.TH NFC-RELAY 1 "June 26, 2009"
|
||||
.SH NAME
|
||||
nfc-relay \- Relay attack command line tool based on libnfc
|
||||
.SH SYNOPSIS
|
||||
.B nfc-relay
|
||||
.SH DESCRIPTION
|
||||
.B nfc-relay
|
||||
is an utility that demonstrates an relay attack. For this it requires two
|
||||
NFC devices. One will emulate an ISO/IEC 14443 type A tag, while the 2nd
|
||||
device will act as a reader. The genuine tag can be placed on the 2nd reader and
|
||||
the tag emulator can be placed close to the original reader. All communication
|
||||
is now relayed and shown in the screen on real-time.
|
||||
|
||||
.SH BUGS
|
||||
Please report any bugs on the
|
||||
.B libnfc
|
||||
forum at
|
||||
.BR http://www.libnfc.org/community/ "."
|
||||
.SH LICENCE
|
||||
.B libnfc
|
||||
and
|
||||
.B nfc-tools
|
||||
are covered by the GNU Lesser General Public License (LGPL), version 3.
|
||||
.SH AUTHORS
|
||||
Roel Verdult <roel@libnfc.org>
|
||||
.PP
|
||||
This manual page was written by Romuald Conty <romuald.conty@free.fr>.
|
||||
It is licensed under the terms of the GNU GPL (version 2 or later).
|
||||
134
src/examples/nfc-relay.c
Normal file
134
src/examples/nfc-relay.c
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
|
||||
Public platform independent Near Field Communication (NFC) library
|
||||
Copyright (C) 2009, Roel Verdult
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libnfc.h"
|
||||
#include "messages.h"
|
||||
|
||||
static byte_t abtReaderRx[MAX_FRAME_LEN];
|
||||
static byte_t abtReaderRxPar[MAX_FRAME_LEN];
|
||||
static size_t szReaderRxBits;
|
||||
static byte_t abtTagRx[MAX_FRAME_LEN];
|
||||
static byte_t abtTagRxPar[MAX_FRAME_LEN];
|
||||
static size_t szTagRxBits;
|
||||
static dev_info* pdiReader;
|
||||
static dev_info* pdiTag;
|
||||
|
||||
void print_usage(char* argv[])
|
||||
{
|
||||
printf("Usage: %s [OPTIONS]\n", argv[0]);
|
||||
printf("Options:\n");
|
||||
printf("\t-h\tHelp. Print this message.\n");
|
||||
printf("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
|
||||
}
|
||||
|
||||
int main(int argc,char* argv[])
|
||||
{
|
||||
int arg;
|
||||
bool quiet_output = false;
|
||||
|
||||
// Get commandline options
|
||||
for (arg=1;arg<argc;arg++) {
|
||||
if (0 == strcmp(argv[arg], "-h")) {
|
||||
print_usage(argv);
|
||||
return 0;
|
||||
} else if (0 == strcmp(argv[arg], "-q")) {
|
||||
INFO("Quiet mode.");
|
||||
quiet_output = true;
|
||||
} else {
|
||||
ERR("%s is not supported option.", argv[arg]);
|
||||
print_usage(argv);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to open the NFC emulator device
|
||||
pdiTag = nfc_connect(NULL);
|
||||
if (pdiTag == INVALID_DEVICE_INFO)
|
||||
{
|
||||
printf("Error connecting NFC emulator device\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf("[+] Connected to the NFC emulator device\n");
|
||||
printf("[+] Try to break out the auto-emulation, this requires a second reader!\n");
|
||||
printf("[+] To do this, please send any command after the anti-collision\n");
|
||||
printf("[+] For example, send a RATS command or use the \"nfc-anticol\" tool\n");
|
||||
nfc_target_init(pdiTag,abtReaderRx,&szReaderRxBits);
|
||||
printf("[+] Configuring emulator settings\n");
|
||||
nfc_configure(pdiTag,DCO_HANDLE_CRC,false);
|
||||
nfc_configure(pdiTag,DCO_HANDLE_PARITY,false);
|
||||
nfc_configure(pdiTag,DCO_ACCEPT_INVALID_FRAMES,true);
|
||||
printf("[+] Thank you, the emulated tag is initialized\n");
|
||||
|
||||
// Try to open the NFC reader
|
||||
pdiReader = INVALID_DEVICE_INFO;
|
||||
while (pdiReader == INVALID_DEVICE_INFO) pdiReader = nfc_connect(NULL);
|
||||
printf("[+] Configuring NFC reader settings\n");
|
||||
nfc_configure(pdiReader,DCO_HANDLE_CRC,false);
|
||||
nfc_configure(pdiReader,DCO_HANDLE_PARITY,false);
|
||||
nfc_configure(pdiReader,DCO_ACCEPT_INVALID_FRAMES,true);
|
||||
printf("[+] Done, relaying frames now!\n\n");
|
||||
|
||||
while(true)
|
||||
{
|
||||
// Test if we received a frame from the reader
|
||||
if (nfc_target_receive_bits(pdiTag,abtReaderRx,&szReaderRxBits,abtReaderRxPar))
|
||||
{
|
||||
// Drop down the field before sending a REQA command and start a new session
|
||||
if (szReaderRxBits == 7 && abtReaderRx[0] == 0x26)
|
||||
{
|
||||
// Drop down field for a very short time (original tag will reboot)
|
||||
nfc_configure(pdiReader,DCO_ACTIVATE_FIELD,false);
|
||||
if(!quiet_output)
|
||||
printf("\n");
|
||||
nfc_configure(pdiReader,DCO_ACTIVATE_FIELD,true);
|
||||
}
|
||||
|
||||
// Print the reader frame to the screen
|
||||
if(!quiet_output)
|
||||
{
|
||||
printf("R: ");
|
||||
print_hex_par(abtReaderRx,szReaderRxBits,abtReaderRxPar);
|
||||
}
|
||||
// Forward the frame to the original tag
|
||||
if (nfc_initiator_transceive_bits(pdiReader,abtReaderRx,szReaderRxBits,abtReaderRxPar,abtTagRx,&szTagRxBits,abtTagRxPar))
|
||||
{
|
||||
// Redirect the answer back to the reader
|
||||
nfc_target_send_bits(pdiTag,abtTagRx,szTagRxBits,abtTagRxPar);
|
||||
|
||||
// Print the tag frame to the screen
|
||||
if(!quiet_output)
|
||||
{
|
||||
printf("T: ");
|
||||
print_hex_par(abtTagRx,szTagRxBits,abtTagRxPar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nfc_disconnect(pdiTag);
|
||||
nfc_disconnect(pdiReader);
|
||||
}
|
||||
37
src/examples/nfcip-initiator.c
Normal file
37
src/examples/nfcip-initiator.c
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "libnfc.h"
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
dev_info *pdi;
|
||||
tag_info ti;
|
||||
byte_t abtRecv[MAX_FRAME_LEN];
|
||||
size_t szRecvBits;
|
||||
byte_t send[] = "Hello World!";
|
||||
|
||||
pdi = nfc_connect(NULL);
|
||||
if (!pdi || !nfc_initiator_init(pdi)
|
||||
|| !nfc_initiator_select_dep_target(pdi, IM_PASSIVE_DEP, NULL, 0,
|
||||
NULL, 0, NULL, 0, &ti)) {
|
||||
printf
|
||||
("unable to connect, initialize, or select the target\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Sending : %s\n", send);
|
||||
if (!nfc_initiator_transceive_dep_bytes(pdi,
|
||||
send,
|
||||
strlen((char*)send), abtRecv,
|
||||
&szRecvBits)) {
|
||||
printf("unable to send data\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
abtRecv[szRecvBits] = 0;
|
||||
printf("Received: %s\n", abtRecv);
|
||||
|
||||
nfc_initiator_deselect_tag(pdi);
|
||||
nfc_disconnect(pdi);
|
||||
return 0;
|
||||
}
|
||||
31
src/examples/nfcip-target.c
Normal file
31
src/examples/nfcip-target.c
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#include <stdio.h>
|
||||
#include "libnfc.h"
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
byte_t abtRecv[MAX_FRAME_LEN];
|
||||
size_t szRecvBits;
|
||||
byte_t send[] = "Hello Mars!";
|
||||
dev_info *pdi = nfc_connect(NULL);
|
||||
|
||||
if (!pdi || !nfc_target_init(pdi, abtRecv, &szRecvBits)) {
|
||||
printf("unable to connect or initialize\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!nfc_target_receive_dep_bytes(pdi, abtRecv, &szRecvBits)) {
|
||||
printf("unable to receive data\n");
|
||||
return 1;
|
||||
}
|
||||
abtRecv[szRecvBits] = 0;
|
||||
printf("Received: %s\n", abtRecv);
|
||||
printf("Sending : %s\n", send);
|
||||
|
||||
if (!nfc_target_send_dep_bytes(pdi, send, 11)) {
|
||||
printf("unable to send data\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
nfc_disconnect(pdi);
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue