move some examples to utils/ since they are not examples anymore :) (Fixes Issue 164)

This commit is contained in:
Romuald Conty 2011-09-30 11:33:31 +00:00
parent 311d12feef
commit 8c7b61eaba
34 changed files with 126 additions and 83 deletions

View file

@ -1,23 +1,15 @@
SET(EXAMPLES-SOURCES nfc-anticol nfc-dep-initiator nfc-dep-target nfc-emulate-forum-tag4 nfc-emulate-tag nfc-emulate-uid nfc-list nfc-poll nfc-relay nfc-relay-picc nfc-mfclassic nfc-mfultralight)
#TODO pn53x-diagnose pn53x-sam pn53x-tamashell
SET(EXAMPLES-SOURCES nfc-anticol nfc-dep-initiator nfc-dep-target nfc-emulate-tag nfc-emulate-uid nfc-poll nfc-relay pn53x-diagnose pn53x-sam pn53x-tamashell)
# XXX: Examples should not use private API!
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libnfc)
INCLUDE_DIRECTORIES(${LIBUSB_INCLUDE_DIRS} ${PCSC_INCLUDE_DIRS})
LINK_DIRECTORIES(${LIBUSB_LIBRARY_DIRS} ${PCSC_LIBRARY_DIRS})
ADD_LIBRARY(nfc-utils nfc-utils)
# Examples
FOREACH(source ${EXAMPLES-SOURCES})
IF((${source} MATCHES "nfc-mfultralight") OR (${source} MATCHES "nfc-mfclassic"))
ADD_EXECUTABLE(${source} ${source}.c mifare)
ELSE()
ADD_EXECUTABLE(${source} ${source}.c)
ENDIF((${source} MATCHES "nfc-mfultralight") OR (${source} MATCHES "nfc-mfclassic"))
ADD_EXECUTABLE(${source} ${source}.c)
TARGET_LINK_LIBRARIES(${source} nfc)
TARGET_LINK_LIBRARIES(${source} nfc-utils)
TARGET_LINK_LIBRARIES(${source} nfcutils)
INSTALL(TARGETS ${source} RUNTIME DESTINATION bin COMPONENT examples)
ENDFOREACH(source)

View file

@ -4,17 +4,10 @@ bin_PROGRAMS = \
nfc-anticol \
nfc-dep-initiator \
nfc-dep-target \
nfc-emulate-forum-tag2 \
nfc-emulate-forum-tag4 \
nfc-emulate-tag \
nfc-emulate-uid \
nfc-list \
nfc-mfclassic \
nfc-mfsetuid \
nfc-mfultralight \
nfc-poll \
nfc-relay \
nfc-relay-picc \
pn53x-diagnose \
pn53x-sam
@ -28,93 +21,55 @@ INCLUDES= $(all_includes) $(LIBNFC_CFLAGS)
AM_CFLAGS = -I$(top_srcdir)/libnfc
noinst_HEADERS = mifare.h nfc-utils.h
noinst_LTLIBRARIES = libnfcutils.la
libnfcutils_la_SOURCES = nfc-utils.c
nfc_poll_SOURCES = nfc-poll.c
nfc_poll_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
$(top_builddir)/utils/libnfcutils.la
nfc_anticol_SOURCES = nfc-anticol.c
nfc_anticol_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
nfc_list_SOURCES = nfc-list.c
nfc_list_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
nfc_mfultralight_SOURCES = nfc-mfultralight.c mifare.c mifare.h
nfc_mfultralight_LDADD = $(top_builddir)/libnfc/libnfc.la
nfc_mfclassic_SOURCES = nfc-mfclassic.c mifare.c mifare.h
nfc_mfclassic_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
nfc_mfsetuid_SOURCES = nfc-mfsetuid.c
nfc_mfsetuid_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
$(top_builddir)/utils/libnfcutils.la
nfc_relay_SOURCES = nfc-relay.c
nfc_relay_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
nfc_relay_picc_SOURCES = nfc-relay-picc.c
nfc_relay_picc_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
nfc_emulate_forum_tag2_SOURCES = nfc-emulate-forum-tag2.c
nfc_emulate_forum_tag2_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
nfc_emulate_forum_tag4_SOURCES = nfc-emulate-forum-tag4.c
nfc_emulate_forum_tag4_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
$(top_builddir)/utils/libnfcutils.la
nfc_emulate_tag_SOURCES = nfc-emulate-tag.c
nfc_emulate_tag_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
$(top_builddir)/utils/libnfcutils.la
nfc_emulate_uid_SOURCES = nfc-emulate-uid.c
nfc_emulate_uid_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
$(top_builddir)/utils/libnfcutils.la
nfc_dep_target_SOURCES = nfc-dep-target.c
nfc_dep_target_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
$(top_builddir)/utils/libnfcutils.la
nfc_dep_initiator_SOURCES = nfc-dep-initiator.c
nfc_dep_initiator_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
$(top_builddir)/utils/libnfcutils.la
pn53x_diagnose_SOURCES = pn53x-diagnose.c
pn53x_diagnose_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
$(top_builddir)/utils/libnfcutils.la
pn53x_sam_SOURCES = pn53x-sam.c
pn53x_sam_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
$(top_builddir)/utils/libnfcutils.la
pn53x_tamashell_SOURCES = pn53x-tamashell.c
pn53x_tamashell_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
$(top_builddir)/utils/libnfcutils.la
pn53x_tamashell_LDFLAGS = @READLINE_LIBS@
dist_man_MANS = \
nfc-anticol.1 \
nfc-dep-initiator.1 \
nfc-dep-target.1 \
nfc-emulate-forum-tag4.1 \
nfc-emulate-tag.1 \
nfc-emulate-uid.1 \
nfc-list.1 \
nfc-mfclassic.1 \
nfc-mfsetuid.1 \
nfc-mfultralight.1 \
nfc-poll.1 \
nfc-relay.1 \
nfc-relay-picc.1 \
pn53x-diagnose.1 \
pn53x-sam.1 \
pn53x-tamashell.1

View file

@ -1,130 +0,0 @@
/*-
* Public platform independent Near Field Communication (NFC) library examples
*
* Copyright (C) 2009, Roel Verdult
* Copyright (C) 2010, Romuald Conty, Romain Tartière
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2 )Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Note that this license only applies on the examples, NFC library itself is under LGPL
*
*/
#include "mifare.h"
#include <string.h>
#include <nfc/nfc.h>
/**
* @brief Execute a MIFARE Classic Command
* @return Returns true if action was successfully performed; otherwise returns false.
* @param pmp Some commands need additional information. This information should be supplied in the mifare_param union.
*
* The specified MIFARE command will be executed on the tag. There are different commands possible, they all require the destination block number.
* @note There are three different types of information (Authenticate, Data and Value).
*
* First an authentication must take place using Key A or B. It requires a 48 bit Key (6 bytes) and the UID.
* They are both used to initialize the internal cipher-state of the PN53X chip (http://libnfc.org/hardware/pn53x-chip).
* After a successful authentication it will be possible to execute other commands (e.g. Read/Write).
* The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process.
*/
bool
nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param * pmp)
{
byte_t abtRx[265];
size_t szRx = sizeof(abtRx);
size_t szParamLen;
byte_t abtCmd[265];
bool bEasyFraming;
abtCmd[0] = mc; // The MIFARE Classic command
abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
switch (mc) {
// Read and store command have no parameter
case MC_READ:
case MC_STORE:
szParamLen = 0;
break;
// Authenticate command
case MC_AUTH_A:
case MC_AUTH_B:
szParamLen = sizeof (mifare_param_auth);
break;
// Data command
case MC_WRITE:
szParamLen = sizeof (mifare_param_data);
break;
// Value command
case MC_DECREMENT:
case MC_INCREMENT:
case MC_TRANSFER:
szParamLen = sizeof (mifare_param_value);
break;
// Please fix your code, you never should reach this statement
default:
return false;
break;
}
// When available, copy the parameter bytes
if (szParamLen)
memcpy (abtCmd + 2, (byte_t *) pmp, szParamLen);
bEasyFraming = pnd->bEasyFraming;
if (!nfc_configure (pnd, NDO_EASY_FRAMING, true)) {
nfc_perror (pnd, "nfc_configure");
return false;
}
// Fire the mifare command
if (!nfc_initiator_transceive_bytes (pnd, abtCmd, 2 + szParamLen, abtRx, &szRx, NULL)) {
if (pnd->iLastError == EINVRXFRAM) {
// "Invalid received frame" AKA EINVRXFRAM, usual means we are
// authenticated on a sector but the requested MIFARE cmd (read, write)
// is not permitted by current acces bytes;
// So there is nothing to do here.
} else {
nfc_perror (pnd, "nfc_initiator_transceive_bytes");
}
nfc_configure (pnd, NDO_EASY_FRAMING, bEasyFraming);
return false;
}
if (!nfc_configure (pnd, NDO_EASY_FRAMING, bEasyFraming)) {
nfc_perror (pnd, "nfc_configure");
return false;
}
// When we have executed a read command, copy the received bytes into the param
if (mc == MC_READ) {
if (szRx == 16) {
memcpy (pmp->mpd.abtData, abtRx, 16);
} else {
return false;
}
}
// Command succesfully executed
return true;
}

View file

@ -1,139 +0,0 @@
/*-
* Public platform independent Near Field Communication (NFC) library examples
*
* Copyright (C) 2009, Roel Verdult
* Copyright (C) 2010, Romuald Conty, Romain Tartière
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2 )Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Note that this license only applies on the examples, NFC library itself is under LGPL
*
*/
/**
* @file mifaretag.h
* @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc
*/
#ifndef _LIBNFC_MIFARE_H_
# define _LIBNFC_MIFARE_H_
# include <nfc/nfc-types.h>
// Compiler directive, set struct alignment to 1 byte_t for compatibility
# pragma pack(1)
typedef enum {
MC_AUTH_A = 0x60,
MC_AUTH_B = 0x61,
MC_READ = 0x30,
MC_WRITE = 0xA0,
MC_TRANSFER = 0xB0,
MC_DECREMENT = 0xC0,
MC_INCREMENT = 0xC1,
MC_STORE = 0xC2
} mifare_cmd;
// MIFARE command params
typedef struct {
byte_t abtKey[6];
byte_t abtUid[4];
} mifare_param_auth;
typedef struct {
byte_t abtData[16];
} mifare_param_data;
typedef struct {
byte_t abtValue[4];
} mifare_param_value;
typedef union {
mifare_param_auth mpa;
mifare_param_data mpd;
mifare_param_value mpv;
} mifare_param;
// Reset struct alignment to default
# pragma pack()
bool nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param * pmp);
// Compiler directive, set struct alignment to 1 byte_t for compatibility
# pragma pack(1)
// MIFARE Classic
typedef struct {
byte_t abtUID[4];
byte_t btBCC;
byte_t btUnknown;
byte_t abtATQA[2];
byte_t abtUnknown[8];
} mifare_classic_block_manufacturer;
typedef struct {
byte_t abtData[16];
} mifare_classic_block_data;
typedef struct {
byte_t abtKeyA[6];
byte_t abtAccessBits[4];
byte_t abtKeyB[6];
} mifare_classic_block_trailer;
typedef union {
mifare_classic_block_manufacturer mbm;
mifare_classic_block_data mbd;
mifare_classic_block_trailer mbt;
} mifare_classic_block;
typedef struct {
mifare_classic_block amb[256];
} mifare_classic_tag;
// MIFARE Ultralight
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;
// Reset struct alignment to default
# pragma pack()
#endif // _LIBNFC_MIFARE_H_

View file

@ -45,7 +45,7 @@
#include <nfc/nfc.h>
#include "nfc-utils.h"
#include "utils/nfc-utils.h"
#define SAK_FLAG_ATS_SUPPORTED 0x20

View file

@ -44,7 +44,7 @@
#include <nfc/nfc.h>
#include "nfc-utils.h"
#include "utils/nfc-utils.h"
#define MAX_FRAME_LEN 264

View file

@ -43,7 +43,7 @@
#include <nfc/nfc.h>
#include "nfc-utils.h"
#include "utils/nfc-utils.h"
#define MAX_FRAME_LEN 264

View file

@ -1,208 +0,0 @@
/*-
* Public platform independent Near Field Communication (NFC) library examples
*
* Copyright (C) 2011, Romuald Conty
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2 )Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Note that this license only applies on the examples, NFC library itself is under LGPL
*
*/
/**
* @file nfc-emulate-forum-tag2.c
* @brief Emulates a NFC Forum Tag Type 2 with a NDEF message
* This example allow to emulate an NFC Forum Tag Type 2 that contains a read-only NDEF message.
*
* It have been developed using PN533 USB hardware as target and Google Nexus S phone as initiator.
*
* This is know to NOT work with Nokia 6212 Classic and could not work with
* several NFC Forum compiliant devices due to these reasons:
* - The emulated target only have a 4 bytes UID where 7 bytes UID (as a real
* Mifare Ultralight tag) are usually attempted;
* - The chip is emulating a ISO/IEC 14443-3 tag, without any hardware helper.
* If the initiator have too short timeouts for software-based emulation
* (which is usually the case), this example will failed, this is not a bug
* and we can't do anything using this kind of hardware (PN531/PN533).
*/
/*
* This implementation was written based on information provided by the
* following documents:
*
* NFC Forum Type 2 Tag Operation
* Technical Specification
* NFCForum-TS-Type-2-Tag_1.0 - 2007-07-09
*
* ISO/IEC 14443-3
* First edition - 2001-02-01
* Identification cards Contactless integrated circuit(s) cards Proximity cards
* Part 3: Initialization and anticollision
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif // HAVE_CONFIG_H
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <nfc/nfc.h>
#include <nfc/nfc-emulation.h>
#include "nfc-utils.h"
static nfc_device_t *pnd;
void
stop_emulation (int sig)
{
(void)sig;
if (pnd) {
nfc_abort_command(pnd);
} else {
exit (EXIT_FAILURE);
}
}
static uint8_t __nfcforum_tag2_memory_area[] = {
0x00, 0x00, 0x00, 0x00, // Block 0
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF, // Block 2 (Static lock bytes: CC area and data area are read-only locked)
0xE1, 0x10, 0x06, 0x0F, // Block 3 (CC - NFC-Forum Tag Type 2 version 1.0, Data area (from block 4 to the end) is 48 bytes, Read-only mode)
0x03, 33, 0xd1, 0x02, // Block 4 (NDEF)
0x1c, 0x53, 0x70, 0x91,
0x01, 0x09, 0x54, 0x02,
0x65, 0x6e, 0x4c, 0x69,
0x62, 0x6e, 0x66, 0x63,
0x51, 0x01, 0x0b, 0x55,
0x03, 0x6c, 0x69, 0x62,
0x6e, 0x66, 0x63, 0x2e,
0x6f, 0x72, 0x67, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
#define READ 0x30
#define WRITE 0xA2
#define SECTOR_SELECT 0xC2
#define HALT 0x50
int
nfcforum_tag2_io (struct nfc_emulator *emulator, const byte_t *data_in, const size_t data_in_len, byte_t *data_out, const size_t data_out_len)
{
int res = 0;
uint8_t *nfcforum_tag2_memory_area = (uint8_t *)(emulator->user_data);
printf (" In: ");
print_hex (data_in, data_in_len);
switch (data_in[0]) {
case READ:
if (data_out_len >= 16) {
memcpy(data_out, nfcforum_tag2_memory_area + (data_in[1] * 4), 16);
res = 16;
} else {
res = -ENOSPC;
}
break;
case HALT:
printf ("HALT sent\n");
res = -ECONNABORTED;
break;
default:
printf ("Unknown command: 0x%02x\n", data_in[0]);
res = -ENOTSUP;
}
if (res < 0) {
ERR ("%s (%d)", strerror (-res), -res);
} else {
printf (" Out: ");
print_hex (data_out, res);
}
return res;
}
int
main(int argc, char *argv[])
{
(void)argc;
(void)argv;
nfc_target_t nt = {
.nm = {
.nmt = NMT_ISO14443A,
.nbr = NBR_UNDEFINED, // Will be updated by nfc_target_init()
},
.nti = {
.nai = {
.abtAtqa = { 0x00, 0x04 },
.abtUid = { 0x08, 0x00, 0xb0, 0x0b },
.szUidLen = 4,
.btSak = 0x00,
.szAtsLen = 0,
},
}
};
struct nfc_emulation_state_machine state_machine = {
.io = nfcforum_tag2_io
};
struct nfc_emulator emulator = {
.target= &nt,
.state_machine = &state_machine,
.user_data = __nfcforum_tag2_memory_area,
};
signal (SIGINT, stop_emulation);
pnd = nfc_connect (NULL);
if (pnd == NULL) {
ERR("Unable to connect to NFC device");
exit (EXIT_FAILURE);
}
printf ("Connected to NFC device: %s\n", pnd->acName);
printf ("Emulating NDEF tag now, please touch it with a second NFC device\n");
if (nfc_emulate_target (pnd, &emulator) < 0) {
goto error;
}
nfc_disconnect(pnd);
exit (EXIT_SUCCESS);
error:
if (pnd) {
nfc_perror (pnd, argv[0]);
nfc_disconnect (pnd);
}
}

View file

@ -1,57 +0,0 @@
.Dd March 12, 2011
.Dt NFC-EMULATE-FORUM-TAG4 1 URM
.Sh NAME
.Nm nfc-emulate-forum-tag4
.Nd NFC Forum tag type 4 emulation command line demonstration tool
.Sh SYNOPSIS
.Nm
.Op infile Op outfile
.Sh DESCRIPTION
.Nm
is a demonstration tool that emulates a NFC Forum tag type 4 with NDEF content.
.Pp
.Ar infile
is the file which contains NDEF message you want to share with the NFC-Forum
compiliant initiator device (e.g. Nokia 6212 Classic)
.Pp
If you want to save a shared content by the initiator device, we have to give
.Ar outfile
argument to point where the NDEF message will be saved.
.Pp
This example uses the hardware capability of PN532 to handle ISO/IEC 14443-4
low-level frames like RATS/ATS, WTX, etc.
.Pp
All devices compiliant with NFC-Forum Tag Type 4 (Version 1.0) can be used with
this example in read-write mode.
.Pp
If no argument is given, a default NDEF file is available.
.Sh IMPLEMENTATION NOTES
You can specify the same
.Ar infile
and
.Ar outfile
.Sh IMPORTANT
Only PN532 equipped devices can use this example. (e.g. PN532 breakout board)
.Pp
ACR122 devices (like touchatag, etc.) can be used by this example, but if
something goes wrong, you will have to unplug/replug your device.
This is not a
.Em libnfc's
bug, this problem is due to ACR122's internal MCU in front of NFC chip (PN532).
.Sh BUGS
Please report any bugs on the
.Em libnfc
forum at
.Em http://www.libnfc.org/community/ "."
.Sh LICENCE
.Em libnfc
and
.Em libnfc-examples
are covered by the GNU Lesser General Public License (LGPL), version 3.
.Sh AUTHORS
.An Roel Verdult Aq roel@libnfc.org
.An Romain Tartière Aq romain@libnfc.org
.An Romuald Conty Aq romuald@libnfc.org
.Pp
This manual page was written by Romuald Conty.
It is licensed under the terms of the GNU GPL (version 2 or later).

View file

@ -1,375 +0,0 @@
/*-
* Public platform independent Near Field Communication (NFC) library examples
*
* Copyright (C) 2010, Roel Verdult, Romuald Conty
* Copyright (C) 2011, Romain Tartière, Romuald Conty
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2 )Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Note that this license only applies on the examples, NFC library itself is under LGPL
*
*/
/**
* @file nfc-emulate-forum-tag4.c
* @brief Emulates a NFC Forum Tag Type 4 with a NDEF message
*/
/*
* This implementation was written based on information provided by the
* following documents:
*
* NFC Forum Type 4 Tag Operation
* Technical Specification
* NFCForum-TS-Type-4-Tag_1.0 - 2007-03-13
*/
// Notes & differences with nfc-emulate-tag:
// - This example only works with PN532 because it relies on
// its internal handling of ISO14443-4 specificities.
// - Thanks to this internal handling & injection of WTX frames,
// this example works on readers very strict on timing
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif // HAVE_CONFIG_H
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <nfc/nfc.h>
#include <nfc/nfc-emulation.h>
#include "nfc-utils.h"
static nfc_device_t *pnd;
static bool quiet_output = false;
#define SYMBOL_PARAM_fISO14443_4_PICC 0x20
typedef enum { NONE, CC_FILE, NDEF_FILE } file;
struct nfcforum_tag4_ndef_data {
uint8_t *ndef_file;
size_t ndef_file_len;
};
struct nfcforum_tag4_state_machine_data {
file current_file;
};
uint8_t nfcforum_capability_container[] = {
0x00, 0x0F, /* CCLEN 15 bytes */
0x10, /* Mapping version 1.0 */
0x00, 0x54, /* MLe Maximum R-ADPU data size */
// Notes:
// - I (Romuald) don't know why Nokia 6212 Classic refuses the NDEF message if MLe is more than 0xFD (any suggests are welcome);
// - ARYGON devices doesn't support extended frame sending, consequently these devices can't sent more than 0xFE bytes as APDU, so 0xFB APDU data bytes.
// - I (Romuald) don't know why ARYGON device doesn't ACK when MLe > 0x54 (ARYGON frame lenght = 0xC2 (192 bytes))
0x00, 0xFF, /* MLc Maximum C-ADPU data size */
0x04, /* T field of the NDEF File-Control TLV */
0x06, /* L field of the NDEF File-Control TLV */
/* V field of the NDEF File-Control TLV */
0xE1, 0x04, /* File identifier */
0xFF, 0xFE, /* Maximum NDEF Size */
0x00, /* NDEF file read access condition */
0x00, /* NDEF file write access condition */
};
/* C-ADPU offsets */
#define CLA 0
#define INS 1
#define P1 2
#define P2 3
#define LC 4
#define DATA 5
#define ISO144434A_RATS 0xE0
int
nfcforum_tag4_io (struct nfc_emulator *emulator, const byte_t *data_in, const size_t data_in_len, byte_t *data_out, const size_t data_out_len)
{
int res = 0;
struct nfcforum_tag4_ndef_data *ndef_data = (struct nfcforum_tag4_ndef_data *)(emulator->user_data);
struct nfcforum_tag4_state_machine_data *state_machine_data = (struct nfcforum_tag4_state_machine_data *)(emulator->state_machine->data);
if (data_in_len == 0) {
// No input data, nothing to do
return res;
}
// Show transmitted command
if (!quiet_output) {
printf (" In: ");
print_hex (data_in, data_in_len);
}
if(data_in_len >= 4) {
if (data_in[CLA] != 0x00)
return -ENOTSUP;
#define ISO7816_SELECT 0xA4
#define ISO7816_READ_BINARY 0xB0
#define ISO7816_UPDATE_BINARY 0xD6
switch(data_in[INS]) {
case ISO7816_SELECT:
switch (data_in[P1]) {
case 0x00: /* Select by ID */
if ((data_in[P2] | 0x0C) != 0x0C)
return -ENOTSUP;
const uint8_t ndef_capability_container[] = { 0xE1, 0x03 };
const uint8_t ndef_file[] = { 0xE1, 0x04 };
if ((data_in[LC] == sizeof (ndef_capability_container)) && (0 == memcmp (ndef_capability_container, data_in + DATA, data_in[LC]))) {
memcpy (data_out, "\x90\x00", res = 2);
state_machine_data->current_file = CC_FILE;
} else if ((data_in[LC] == sizeof (ndef_file)) && (0 == memcmp (ndef_file, data_in + DATA, data_in[LC]))) {
memcpy (data_out, "\x90\x00", res = 2);
state_machine_data->current_file = NDEF_FILE;
} else {
memcpy (data_out, "\x6a\x00", res = 2);
state_machine_data->current_file = NONE;
}
break;
case 0x04: /* Select by name */
if (data_in[P2] != 0x00)
return -ENOTSUP;
const uint8_t ndef_tag_application_name[] = { 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x00 };
if ((data_in[LC] == sizeof (ndef_tag_application_name)) && (0 == memcmp (ndef_tag_application_name, data_in + DATA, data_in[LC])))
memcpy (data_out, "\x90\x00", res = 2);
else
memcpy (data_out, "\x6a\x82", res = 2);
break;
default:
return -ENOTSUP;
}
break;
case ISO7816_READ_BINARY:
if ((size_t)(data_in[LC] + 2) > data_out_len) {
return -ENOSPC;
}
switch (state_machine_data->current_file) {
case NONE:
memcpy (data_out, "\x6a\x82", res = 2);
break;
case CC_FILE:
memcpy (data_out, nfcforum_capability_container + (data_in[P1] << 8) + data_in[P2], data_in[LC]);
memcpy (data_out + data_in[LC], "\x90\x00", 2);
res = data_in[LC] + 2;
break;
case NDEF_FILE:
memcpy (data_out, ndef_data->ndef_file + (data_in[P1] << 8) + data_in[P2], data_in[LC]);
memcpy (data_out + data_in[LC], "\x90\x00", 2);
res = data_in[LC] + 2;
break;
}
break;
case ISO7816_UPDATE_BINARY:
memcpy (ndef_data->ndef_file + (data_in[P1] << 8) + data_in[P2], data_in + DATA, data_in[LC]);
if ((data_in[P1] << 8) + data_in[P2] == 0) {
ndef_data->ndef_file_len = (ndef_data->ndef_file[0] << 8) + ndef_data->ndef_file[1] + 2;
}
memcpy (data_out, "\x90\x00", res = 2);
break;
default: // Unknown
if (!quiet_output) {
printf("Unknown frame, emulated target abort.\n");
}
res = -ENOTSUP;
}
} else {
res = -ENOTSUP;
}
// Show transmitted command
if (!quiet_output) {
if (res < 0) {
ERR ("%s (%d)", strerror (-res), -res);
} else {
printf (" Out: ");
print_hex (data_out, res);
}
}
return res;
}
void stop_emulation (int sig)
{
(void) sig;
if (pnd)
nfc_abort_command (pnd);
else
exit (EXIT_FAILURE);
}
size_t
ndef_message_load (char *filename, struct nfcforum_tag4_ndef_data *tag_data)
{
struct stat sb;
if (stat (filename, &sb) < 0)
return 0;
/* Check file size */
if (sb.st_size > 0xFFFF) {
errx (EXIT_FAILURE, "file size too large '%s'", filename);
}
tag_data->ndef_file_len = sb.st_size + 2;
tag_data->ndef_file[0] = (uint8_t)(sb.st_size >> 8);
tag_data->ndef_file[1] = (uint8_t)(sb.st_size);
FILE *F;
if (!(F = fopen (filename, "r")))
err (EXIT_FAILURE, "fopen (%s, \"r\")", filename);
if (1 != fread (tag_data->ndef_file + 2, sb.st_size, 1, F))
err (EXIT_FAILURE, "Can't read from %s", filename);
fclose (F);
return sb.st_size;
}
size_t
ndef_message_save (char *filename, struct nfcforum_tag4_ndef_data *tag_data)
{
FILE *F;
if (!(F= fopen (filename, "w")))
err (EXIT_FAILURE, "fopen (%s, w)", filename);
if (1 != fwrite (tag_data->ndef_file + 2, tag_data->ndef_file_len - 2, 1, F)) {
err (EXIT_FAILURE, "fwrite (%d)", (int) tag_data->ndef_file_len -2);
}
fclose (F);
return tag_data->ndef_file_len - 2;
}
void
usage (char *progname)
{
fprintf (stderr, "usage: %s [infile [outfile]]\n", progname);
}
int
main (int argc, char *argv[])
{
nfc_target_t nt = {
.nm = {
.nmt = NMT_ISO14443A,
.nbr = NBR_UNDEFINED, // Will be updated by nfc_target_init()
},
.nti = {
.nai = {
.abtAtqa = { 0x00, 0x04 },
.abtUid = { 0x08, 0x00, 0xb0, 0x0b },
.szUidLen = 4,
.btSak = 0x20,
.abtAts = { 0x75, 0x33, 0x92, 0x03 }, /* Not used by PN532 */
.szAtsLen = 4,
},
},
};
uint8_t ndef_file[0xfffe] = {
0x00, 33,
0xd1, 0x02, 0x1c, 0x53, 0x70, 0x91, 0x01, 0x09, 0x54, 0x02,
0x65, 0x6e, 0x4c, 0x69, 0x62, 0x6e, 0x66, 0x63, 0x51, 0x01,
0x0b, 0x55, 0x03, 0x6c, 0x69, 0x62, 0x6e, 0x66, 0x63, 0x2e,
0x6f, 0x72, 0x67
};
struct nfcforum_tag4_ndef_data nfcforum_tag4_data = {
.ndef_file = ndef_file,
.ndef_file_len = ndef_file[1] + 2,
};
struct nfcforum_tag4_state_machine_data state_machine_data = {
.current_file = NONE,
};
struct nfc_emulation_state_machine state_machine = {
.io = nfcforum_tag4_io,
.data = &state_machine_data,
};
struct nfc_emulator emulator = {
.target = &nt,
.state_machine = &state_machine,
.user_data = &nfcforum_tag4_data,
};
if (argc > 3) {
usage (argv[0]);
exit (EXIT_FAILURE);
}
// If some file is provided load it
if (argc >= 2) {
if (!ndef_message_load (argv[1], &nfcforum_tag4_data)) {
err (EXIT_FAILURE, "Can't load NDEF file '%s'", argv[1]);
}
}
// Try to open the NFC reader
pnd = nfc_connect (NULL);
if (pnd == NULL) {
ERR("Unable to connect to NFC device");
exit (EXIT_FAILURE);
}
signal (SIGINT, stop_emulation);
printf ("Connected to NFC device: %s\n", pnd->acName);
printf ("Emulating NDEF tag now, please touch it with a second NFC device\n");
if (0 != nfc_emulate_target (pnd, &emulator)) { // contains already nfc_target_init() call
nfc_perror (pnd, "nfc_emulate_target");
}
nfc_disconnect(pnd);
if (argc == 3) {
if (!(ndef_message_save (argv[2], &nfcforum_tag4_data))) {
err (EXIT_FAILURE, "Can't save NDEF file '%s'", argv[2]);
}
}
exit (EXIT_SUCCESS);
}

View file

@ -49,7 +49,7 @@
#include <nfc/nfc.h>
#include "nfc-utils.h"
#include "utils/nfc-utils.h"
#define MAX_FRAME_LEN (264)
#define SAK_ISO14443_4_COMPLIANT 0x20

View file

@ -52,7 +52,7 @@
#include <nfc/nfc.h>
#include "nfc-utils.h"
#include "utils/nfc-utils.h"
#define MAX_FRAME_LEN 264

View file

@ -1,44 +0,0 @@
.TH NFC-LIST 1 "June 26, 2009"
.SH NAME
nfc-list \- List NFC targets
.SH SYNOPSIS
.B nfc-list
.SH DESCRIPTION
.B nfc-list
is a utility for listing any available tags like ISO14443-A, FeliCa, Jewel
or ISO14443-B (according to the device capabilities).
It may detect several tags at once thanks to a mechanism called anti-collision
but all types of tags don't support anti-collision and there is some physical
limitation of the number of tags the reader can discover.
This tool displays all available information at selection time.
.SH OPTIONS
\fB-v\fP, \fB--verbose\fP
Verbose mode
Tries to interpret data
.SH EXAMPLE
For an ISO/IEC 14443-A tag (i.e.Mifare DESFire):
ATQA (SENS_RES): 03 44
UID (NFCID1): 04 45 35 01 db 24 80
SAK (SEL_RES): 20
ATS (ATR): 75 77 81 02 80
.SH BUGS
Please report any bugs on the
.B libnfc
forum at
.BR http://www.libnfc.org/community/ "."
.SH LICENCE
.B libnfc
and
.B libnfc-examples
are covered by the GNU Lesser General Public License (LGPL), version 3.
.SH AUTHORS
Roel Verdult <roel@libnfc.org>
Romuald Conty <romuald@libnfc.org>
.PP
This manual page was written by Romuald Conty <romuald@libnfc.org>.
It is licensed under the terms of the GNU GPL (version 2 or later).

View file

@ -1,248 +0,0 @@
/*-
* Public platform independent Near Field Communication (NFC) library examples
*
* Copyright (C) 2009, Roel Verdult
* Copyright (C) 2010, Romuald Conty, Romain Tartière
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2 )Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Note that this license only applies on the examples, NFC library itself is under LGPL
*
*/
/**
* @file nfc-list.c
* @brief Lists the first target present of each founded device
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif // HAVE_CONFIG_H
#ifdef HAVE_LIBUSB
# ifdef DEBUG
# include <sys/param.h>
# include <usb.h>
# endif
#endif
#include <err.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <nfc/nfc.h>
#include "nfc-utils.h"
#define MAX_DEVICE_COUNT 16
#define MAX_TARGET_COUNT 16
static nfc_device_t *pnd;
int
main (int argc, const char *argv[])
{
const char *acLibnfcVersion;
size_t szDeviceFound;
size_t szTargetFound;
size_t i;
bool verbose = false;
nfc_device_desc_t *pnddDevices;
// Display libnfc version
acLibnfcVersion = nfc_version ();
printf ("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
pnddDevices = parse_args (argc, argv, &szDeviceFound, &verbose);
#ifdef HAVE_LIBUSB
# ifdef DEBUG
usb_set_debug (4);
# endif
#endif
/* Lazy way to open an NFC device */
#if 0
pnd = nfc_connect (NULL);
#endif
/* If specific device is wanted, i.e. an ARYGON device on /dev/ttyUSB0 */
#if 0
nfc_device_desc_t ndd;
ndd.pcDriver = "ARYGON";
ndd.pcPort = "/dev/ttyUSB0";
ndd.uiSpeed = 115200;
pnd = nfc_connect (&ndd);
#endif
/* If specific device is wanted, i.e. a SCL3711 on USB */
#if 0
nfc_device_desc_t ndd;
ndd.pcDriver = "PN533_USB";
strcpy(ndd.acDevice, "SCM Micro / SCL3711-NFC&RW");
pnd = nfc_connect (&ndd);
#endif
if (szDeviceFound == 0) {
if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) {
fprintf (stderr, "malloc() failed\n");
return EXIT_FAILURE;
}
nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szDeviceFound);
}
if (szDeviceFound == 0) {
printf ("No NFC device found.\n");
}
for (i = 0; i < szDeviceFound; i++) {
nfc_target_t ant[MAX_TARGET_COUNT];
pnd = nfc_connect (&(pnddDevices[i]));
if (pnd == NULL) {
ERR ("%s", "Unable to connect to NFC device.");
return EXIT_FAILURE;
}
nfc_initiator_init (pnd);
printf ("Connected to NFC device: %s\n", pnd->acName);
nfc_modulation_t nm;
nm.nmt = NMT_ISO14443A;
nm.nbr = NBR_106;
// List ISO14443A targets
if (nfc_initiator_list_passive_targets (pnd, nm, ant, MAX_TARGET_COUNT, &szTargetFound)) {
size_t n;
if (verbose || (szTargetFound > 0)) {
printf ("%d ISO14443A passive target(s) found%s\n", (int) szTargetFound, (szTargetFound == 0) ? ".\n" : ":");
}
for (n = 0; n < szTargetFound; n++) {
print_nfc_iso14443a_info (ant[n].nti.nai, verbose);
printf ("\n");
}
}
nm.nmt = NMT_FELICA;
nm.nbr = NBR_212;
// List Felica tags
if (nfc_initiator_list_passive_targets (pnd, nm, ant, MAX_TARGET_COUNT, &szTargetFound)) {
size_t n;
if (verbose || (szTargetFound > 0)) {
printf ("%d Felica (212 kbps) passive target(s) found%s\n", (int) szTargetFound,
(szTargetFound == 0) ? ".\n" : ":");
}
for (n = 0; n < szTargetFound; n++) {
print_nfc_felica_info (ant[n].nti.nfi, verbose);
printf ("\n");
}
}
nm.nbr = NBR_424;
if (nfc_initiator_list_passive_targets (pnd, nm, ant, MAX_TARGET_COUNT, &szTargetFound)) {
size_t n;
if (verbose || (szTargetFound > 0)) {
printf ("%d Felica (424 kbps) passive target(s) found%s\n", (int) szTargetFound,
(szTargetFound == 0) ? ".\n" : ":");
}
for (n = 0; n < szTargetFound; n++) {
print_nfc_felica_info (ant[n].nti.nfi, verbose);
printf ("\n");
}
}
nm.nmt = NMT_ISO14443B;
nm.nbr = NBR_106;
// List ISO14443B targets
if (nfc_initiator_list_passive_targets (pnd, nm, ant, MAX_TARGET_COUNT, &szTargetFound)) {
size_t n;
if (verbose || (szTargetFound > 0)) {
printf ("%d ISO14443B passive target(s) found%s\n", (int) szTargetFound, (szTargetFound == 0) ? ".\n" : ":");
}
for (n = 0; n < szTargetFound; n++) {
print_nfc_iso14443b_info (ant[n].nti.nbi, verbose);
printf ("\n");
}
}
nm.nmt = NMT_ISO14443BI;
nm.nbr = NBR_106;
// List ISO14443B' targets
if (nfc_initiator_list_passive_targets (pnd, nm, ant, MAX_TARGET_COUNT, &szTargetFound)) {
size_t n;
if (verbose || (szTargetFound > 0)) {
printf ("%d ISO14443B' passive target(s) found%s\n", (int) szTargetFound, (szTargetFound == 0) ? ".\n" : ":");
}
for (n = 0; n < szTargetFound; n++) {
print_nfc_iso14443bi_info (ant[n].nti.nii, verbose);
printf ("\n");
}
}
nm.nmt = NMT_ISO14443B2SR;
nm.nbr = NBR_106;
// List ISO14443B-2 ST SRx family targets
if (nfc_initiator_list_passive_targets (pnd, nm, ant, MAX_TARGET_COUNT, &szTargetFound)) {
size_t n;
if (verbose || (szTargetFound > 0)) {
printf ("%d ISO14443B-2 ST SRx passive target(s) found%s\n", (int) szTargetFound, (szTargetFound == 0) ? ".\n" : ":");
}
for (n = 0; n < szTargetFound; n++) {
print_nfc_iso14443b2sr_info (ant[n].nti.nsi, verbose);
printf ("\n");
}
}
nm.nmt = NMT_ISO14443B2CT;
nm.nbr = NBR_106;
// List ISO14443B-2 ASK CTx family targets
if (nfc_initiator_list_passive_targets (pnd, nm, ant, MAX_TARGET_COUNT, &szTargetFound)) {
size_t n;
if (verbose || (szTargetFound > 0)) {
printf ("%d ISO14443B-2 ASK CTx passive target(s) found%s\n", (int) szTargetFound, (szTargetFound == 0) ? ".\n" : ":");
}
for (n = 0; n < szTargetFound; n++) {
print_nfc_iso14443b2ct_info (ant[n].nti.nci, verbose);
printf ("\n");
}
}
nm.nmt = NMT_JEWEL;
nm.nbr = NBR_106;
// List Jewel targets
if (nfc_initiator_list_passive_targets(pnd, nm, ant, MAX_TARGET_COUNT, &szTargetFound )) {
size_t n;
if (verbose || (szTargetFound > 0)) {
printf("%d Jewel passive target(s) found%s\n", (int)szTargetFound, (szTargetFound==0)?".\n":":");
}
for(n=0; n<szTargetFound; n++) {
print_nfc_jewel_info (ant[n].nti.nji, verbose);
printf("\n");
}
}
nfc_disconnect (pnd);
}
free (pnddDevices);
return 0;
}

View file

@ -1,78 +0,0 @@
.TH NFC-MFCLASSIC 1 "Nov 02, 2009"
.SH NAME
nfc-mfclassic \- MIFARE Classic command line tool
.SH SYNOPSIS
.B nfc-mfclassic
.RI \fR\fBr\fR|\fR\fBR\fR|\fBw\fR\fR|\fBW\fR
.RI \fR\fBa\fR|\fBb\fR
.IR DUMP
.IR [KEYS]
.SH DESCRIPTION
.B nfc-mfclassic
is a MIFARE Classic tool that allow to read or write
.IR DUMP
file using Mifare keys provided in
.IR KEYS
file.
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 demonstrates the speed of this library
and its ease-of-use. It's possible to read and write the complete content of a
Mifare Classic 4KB tag within 1 second. It uses a binary Mifare Dump file (MFD)
to store the keys and data for all sectors.
Be cautious that some parts of a Mifare Classic memory are used for r/w access
of the rest of the memory, so please read the tag documentation before experimenting too much!
The 'W' option allows writing of special Mifare cards that can be 'unlocked' to allow block 0
to be overwritten. This includes UID and manufacturer data. Take care when amending UIDs to set
the correct BCC (UID checksum). Currently only 4 byte UIDs are supported.
Similarly, the 'R' option allows an 'unlocked' read. This bypasses authentication and allows
reading of the Key A and Key B data regardless of ACLs.
*** Note that 'W' and 'R' options only work on special versions of Mifare 1K cards (Chinese clones).
.SH OPTIONS
.BR r " | " R " | " w " | " W
Perform read from (
.B r
) or unlocked read from (
.B R
) or write to (
.B w
) or unlocked write to (
.B W
) card.
.TP
.BR a " | " b
Use A or B Mifare keys.
.TP
.IR DUMP
MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)
.TP
.IR KEYS
MiFare Dump (MFD) that contains the keys (optional). Data part of the dump is ignored.
.SH BUGS
Please report any bugs on the
.B libnfc
forum at
.BR http://www.libnfc.org/community/ "."
.SH LICENCE
.B libnfc
and
.B libnfc-examples
are covered by the GNU Lesser General Public License (LGPL), version 3.
.SH AUTHORS
Roel Verdult <roel@libnfc.org>
Romuald Conty <romuald@libnfc.org>
Romain Tartière <romain@blogreen.org>
Adam Laurie <adam@algroup.co.uk>
.PP
This manual page was written by Romuald Conty <romuald@libnfc.org>.
It is licensed under the terms of the GNU GPL (version 2 or later).

View file

@ -1,663 +0,0 @@
/*-
* Public platform independent Near Field Communication (NFC) library examples
*
* Copyright (C) 2009, Roel Verdult
* Copyright (C) 2010, Romuald Conty, Romain Tartière
* Copyright (C) 2011, Adam Laurie
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2 )Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Note that this license only applies on the examples, NFC library itself is under LGPL
*
*/
/**
* @file nfc-mfclassic.c
* @brief MIFARE Classic manipulation example
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif // HAVE_CONFIG_H
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#include <nfc/nfc.h>
#include "mifare.h"
#include "nfc-utils.h"
static nfc_device_t *pnd;
static nfc_target_t nt;
static mifare_param mp;
static mifare_classic_tag mtKeys;
static mifare_classic_tag mtDump;
static bool bUseKeyA;
static bool bUseKeyFile;
static uint8_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,
0xab, 0xcd, 0xef, 0x12, 0x34, 0x56
};
static const nfc_modulation_t nmMifare = {
.nmt = NMT_ISO14443A,
.nbr = NBR_106,
};
static size_t num_keys = sizeof (keys) / 6;
#define MAX_FRAME_LEN 264
static byte_t abtRx[MAX_FRAME_LEN];
static size_t szRxBits;
static size_t szRx = sizeof(abtRx);
byte_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
// special unlock command
byte_t abtUnlock1[1] = { 0x40 };
byte_t abtUnlock2[1] = { 0x43 };
static bool
transmit_bits (const byte_t * pbtTx, const size_t szTxBits)
{
// Show transmitted command
printf ("Sent bits: ");
print_hex_bits (pbtTx, szTxBits);
// Transmit the bit frame command, we don't use the arbitrary parity feature
if (!nfc_initiator_transceive_bits (pnd, pbtTx, szTxBits, NULL, abtRx, &szRxBits, NULL))
return false;
// Show received answer
printf ("Received bits: ");
print_hex_bits (abtRx, szRxBits);
// Succesful transfer
return true;
}
static bool
transmit_bytes (const byte_t * pbtTx, const size_t szTx)
{
// Show transmitted command
printf ("Sent bits: ");
print_hex (pbtTx, szTx);
// Transmit the command bytes
if (!nfc_initiator_transceive_bytes (pnd, pbtTx, szTx, abtRx, &szRx, NULL))
return false;
// Show received answer
printf ("Received bits: ");
print_hex (abtRx, szRx);
// Succesful transfer
return true;
}
static void
print_success_or_failure (bool bFailure, uint32_t * uiBlockCounter)
{
printf ("%c", (bFailure) ? 'x' : '.');
if (uiBlockCounter && !bFailure)
*uiBlockCounter += (*uiBlockCounter < 128) ? 4 : 16;
}
static 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);
}
static 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);
}
static uint32_t
get_trailer_block (uint32_t uiFirstBlock)
{
// Test if we are in the small or big sectors
uint32_t trailer_block = 0;
if (uiFirstBlock < 128) {
trailer_block = uiFirstBlock + (3 - (uiFirstBlock % 4));
} else {
trailer_block = uiFirstBlock + (15 - (uiFirstBlock % 16));
}
return trailer_block;
}
static bool
authenticate (uint32_t uiBlock)
{
mifare_cmd mc;
uint32_t uiTrailerBlock;
size_t key_index;
// Set the authentication information (uid)
memcpy (mp.mpa.abtUid, nt.nti.nai.abtUid + nt.nti.nai.szUidLen - 4, 4);
// Should we use key A or B?
mc = (bUseKeyA) ? MC_AUTH_A : MC_AUTH_B;
// Key file authentication.
if (bUseKeyFile) {
// Locate the trailer (with the keys) used for this sector
uiTrailerBlock = get_trailer_block (uiBlock);
// Extract the right key from dump file
if (bUseKeyA)
memcpy (mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyA, 6);
else
memcpy (mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyB, 6);
// Try to authenticate for the current sector
if (nfc_initiator_mifare_cmd (pnd, mc, uiBlock, &mp))
return true;
} else {
// Try to guess the right key
for (key_index = 0; key_index < num_keys; key_index++) {
memcpy (mp.mpa.abtKey, keys + (key_index * 6), 6);
if (nfc_initiator_mifare_cmd (pnd, mc, uiBlock, &mp)) {
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_passive_target (pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, NULL);
}
}
return false;
}
static bool
unlock_card()
{
printf ("Unlocking card\n");
// Configure the CRC
if (!nfc_configure (pnd, NDO_HANDLE_CRC, false)) {
nfc_perror (pnd, "nfc_configure");
exit (EXIT_FAILURE);
}
// Use raw send/receive methods
if (!nfc_configure (pnd, NDO_EASY_FRAMING, false)) {
nfc_perror (pnd, "nfc_configure");
exit (EXIT_FAILURE);
}
iso14443a_crc_append(abtHalt, 2);
transmit_bytes (abtHalt, 4);
// now send unlock
if (!transmit_bits (abtUnlock1, 7)) {
printf("unlock failure!\n");
return false;
}
if (!transmit_bytes (abtUnlock2, 1)) {
printf("unlock failure!\n");
return false;
}
// reset reader
// Configure the CRC
if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) {
nfc_perror (pnd, "nfc_configure");
exit (EXIT_FAILURE);
}
// Switch off raw send/receive methods
if (!nfc_configure (pnd, NDO_EASY_FRAMING, true)) {
nfc_perror (pnd, "nfc_configure");
exit (EXIT_FAILURE);
}
return true;
}
static bool
read_card (int read_unlocked)
{
int32_t iBlock;
bool bFailure = false;
uint32_t uiReadBlocks = 0;
if(read_unlocked)
if (!unlock_card())
return 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)) {
// Skip this the first time, bFailure it means nothing (yet)
if (iBlock != uiBlocks)
print_success_or_failure (bFailure, &uiReadBlocks);
// Show if the readout went well
if (bFailure) {
// When a failure occured we need to redo the anti-collision
if (!nfc_initiator_select_passive_target (pnd, nmMifare, NULL, 0, &nt)) {
printf ("!\nError: tag was removed\n");
return false;
}
bFailure = false;
}
fflush (stdout);
// Try to authenticate for the current sector
if (!read_unlocked && !authenticate (iBlock)) {
printf ("!\nError: authentication failed for block 0x%02x\n", iBlock);
return false;
}
// Try to read out the trailer
if (nfc_initiator_mifare_cmd (pnd, MC_READ, iBlock, &mp)) {
if(read_unlocked) {
memcpy (mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16);
} else {
// 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 {
printf ("!\nError: unable to read trailer block 0x%02x\n", iBlock);
}
} else {
// Make sure a earlier readout did not fail
if (!bFailure) {
// Try to read out the data block
if (nfc_initiator_mifare_cmd (pnd, MC_READ, iBlock, &mp)) {
memcpy (mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16);
} else {
bFailure = true;
printf ("!\nError: unable to read block 0x%02x\n", iBlock);
return false;
}
}
}
}
print_success_or_failure (bFailure, &uiReadBlocks);
printf ("|\n");
printf ("Done, %d of %d blocks read.\n", uiReadBlocks, uiBlocks + 1);
fflush (stdout);
return true;
}
static bool
write_card (int write_block_zero)
{
uint32_t uiBlock;
bool bFailure = false;
uint32_t uiWriteBlocks = 0;
if(write_block_zero)
if (!unlock_card())
return 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)) {
// Skip this the first time, bFailure it means nothing (yet)
if (uiBlock != 0)
print_success_or_failure (bFailure, &uiWriteBlocks);
// Show if the readout went well
if (bFailure) {
// When a failure occured we need to redo the anti-collision
if (!nfc_initiator_select_passive_target (pnd, nmMifare, NULL, 0, &nt)) {
printf ("!\nError: tag was removed\n");
return false;
}
bFailure = false;
}
fflush (stdout);
// Try to authenticate for the current sector
if (!write_block_zero && !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
if (nfc_initiator_mifare_cmd (pnd, MC_WRITE, uiBlock, &mp) == false) {
printf ("failed to write trailer block %d \n", uiBlock);
bFailure = true;
}
} else {
// The first block 0x00 is read only, skip this
if (uiBlock == 0 && ! write_block_zero)
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);
// do not write a block 0 with incorrect BCC - card will be made invalid!
if (uiBlock == 0) {
if((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00) {
printf ("!\nError: incorrect BCC in MFD file!\n");
return false;
}
}
if (!nfc_initiator_mifare_cmd (pnd, MC_WRITE, uiBlock, &mp))
bFailure = true;
}
}
}
print_success_or_failure (bFailure, &uiWriteBlocks);
printf ("|\n");
printf ("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
fflush (stdout);
return true;
}
static void
mifare_classic_extract_payload (const char *abDump, char *pbPayload)
{
uint8_t uiSectorIndex;
uint8_t uiBlockIndex;
size_t szDumpOffset;
size_t szPayloadIndex = 0;
for (uiSectorIndex = 1; uiSectorIndex < 16; uiSectorIndex++) {
for (uiBlockIndex = 0; uiBlockIndex < 3; uiBlockIndex++) {
szDumpOffset = uiSectorIndex * 16 * 4 + uiBlockIndex * 16;
// for(uint8_t uiByteIndex=0; uiByteIndex<16; uiByteIndex++) printf("%02x ", abDump[szPayloadIndex+uiByteIndex]);
memcpy (pbPayload + szPayloadIndex, abDump + szDumpOffset, 16);
szPayloadIndex += 16;
}
}
}
typedef enum {
ACTION_READ,
ACTION_WRITE,
ACTION_EXTRACT,
ACTION_USAGE
} action_t;
static void
print_usage (const char *pcProgramName)
{
printf ("Usage: ");
printf ("%s r|R|w|W a|b <dump.mfd> [<keys.mfd>]\n", pcProgramName);
printf (" r|R|w|W - Perform read from (r) or unlocked read from (R) or write to (w) or unlocked write to (W) card\n");
printf (" *** note that unlocked write will attempt to overwrite block 0 including UID\n");
printf (" *** unlocked read does not require authentication and will reveal A and B keys\n");
printf (" *** unlocking only works with special Mifare 1K cards (Chinese clones)\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 ("Or: ");
printf ("%s x <dump.mfd> <payload.bin>\n", pcProgramName);
printf (" x - Extract payload (data blocks) from MFD\n");
printf (" <dump.mfd> - MiFare Dump (MFD) that contains wanted payload\n");
printf (" <payload.bin> - Binary file where payload will be extracted\n");
}
int
main (int argc, const char *argv[])
{
action_t atAction = ACTION_USAGE;
byte_t *pbtUID;
FILE *pfKeys = NULL;
FILE *pfDump = NULL;
int unlock= 0;
if (argc < 2) {
print_usage (argv[0]);
exit (EXIT_FAILURE);
}
const char *command = argv[1];
if (strcmp (command, "r") == 0 || strcmp (command, "R") == 0) {
if (argc < 4) {
print_usage (argv[0]);
exit (EXIT_FAILURE);
}
atAction = ACTION_READ;
if (strcmp (command, "R") == 0)
unlock= 1;
bUseKeyA = tolower ((int) ((unsigned char) *(argv[2]))) == 'a';
bUseKeyFile = (argc > 4);
} else if (strcmp (command, "w") == 0 || strcmp (command, "W") == 0) {
if (argc < 4) {
print_usage (argv[0]);
exit (EXIT_FAILURE);
}
atAction = ACTION_WRITE;
if (strcmp (command, "W") == 0)
unlock= 1;
bUseKeyA = tolower ((int) ((unsigned char) *(argv[2]))) == 'a';
bUseKeyFile = (argc > 4);
} else if (strcmp (command, "x") == 0) {
if (argc < 4) {
print_usage (argv[0]);
exit (EXIT_FAILURE);
}
atAction = ACTION_EXTRACT;
}
switch (atAction) {
case ACTION_USAGE:
print_usage (argv[0]);
exit (EXIT_FAILURE);
break;
case ACTION_READ:
case ACTION_WRITE:
if (bUseKeyFile) {
pfKeys = fopen (argv[4], "rb");
if (pfKeys == NULL) {
printf ("Could not open keys file: %s\n", argv[4]);
exit (EXIT_FAILURE);
}
if (fread (&mtKeys, 1, sizeof (mtKeys), pfKeys) != sizeof (mtKeys)) {
printf ("Could not read keys file: %s\n", argv[4]);
fclose (pfKeys);
exit (EXIT_FAILURE);
}
fclose (pfKeys);
}
if (atAction == ACTION_READ) {
memset (&mtDump, 0x00, sizeof (mtDump));
} else {
pfDump = fopen (argv[3], "rb");
if (pfDump == NULL) {
printf ("Could not open dump file: %s\n", argv[3]);
exit (EXIT_FAILURE);
}
if (fread (&mtDump, 1, sizeof (mtDump), pfDump) != sizeof (mtDump)) {
printf ("Could not read dump file: %s\n", argv[3]);
fclose (pfDump);
exit (EXIT_FAILURE);
}
fclose (pfDump);
}
// printf("Successfully opened required files\n");
// Try to open the NFC reader
pnd = nfc_connect (NULL);
if (pnd == NULL) {
printf ("Error connecting NFC reader\n");
exit (EXIT_FAILURE);
}
nfc_initiator_init (pnd);
// Let the reader only try once to find a tag
if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
nfc_perror (pnd, "nfc_configure");
exit (EXIT_FAILURE);
}
// Disable ISO14443-4 switching in order to read devices that emulate Mifare Classic with ISO14443-4 compliance.
nfc_configure (pnd, NDO_AUTO_ISO14443_4, false);
printf ("Connected to NFC reader: %s\n", pnd->acName);
// Try to find a MIFARE Classic tag
if (!nfc_initiator_select_passive_target (pnd, nmMifare, NULL, 0, &nt)) {
printf ("Error: no tag was found\n");
nfc_disconnect (pnd);
exit (EXIT_FAILURE);
}
// Test if we are dealing with a MIFARE compatible tag
if ((nt.nti.nai.btSak & 0x08) == 0) {
printf ("Warning: tag is probably not a MFC!\n");
}
// Get the info from the current tag
pbtUID = nt.nti.nai.abtUid;
if (bUseKeyFile) {
byte_t fileUid[4];
memcpy (fileUid, mtKeys.amb[0].mbm.abtUID, 4);
// Compare if key dump UID is the same as the current tag UID, at least for the first 4 bytes
if (memcmp (nt.nti.nai.abtUid, fileUid, 4) != 0) {
printf ("Expected MIFARE Classic card with UID starting as: %02x%02x%02x%02x\n",
fileUid[0], fileUid[1], fileUid[2], fileUid[3]);
}
}
printf ("Found MIFARE Classic card:\n");
print_nfc_iso14443a_info (nt.nti.nai, false);
// Guessing size
if ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x02)
// 4K
uiBlocks = 0xff;
else if ((nt.nti.nai.btSak & 0x01) == 0x01)
// 320b
uiBlocks = 0x13;
else
// 1K
// TODO: for MFP it is 0x7f (2K) but how to be sure it's a MFP? Try to get RATS?
uiBlocks = 0x3f;
printf ("Guessing size: seems to be a %i-byte card\n", (uiBlocks + 1) * 16);
if (atAction == ACTION_READ) {
if (read_card (unlock)) {
printf ("Writing data to file: %s ...", argv[3]);
fflush (stdout);
pfDump = fopen (argv[3], "wb");
if (pfDump == NULL) {
printf ("Could not open dump file: %s\n", argv[3]);
exit (EXIT_FAILURE);
}
if (fwrite (&mtDump, 1, sizeof (mtDump), pfDump) != sizeof (mtDump)) {
printf ("\nCould not write to file: %s\n", argv[3]);
exit (EXIT_FAILURE);
}
printf ("Done.\n");
fclose (pfDump);
}
} else if (atAction == ACTION_WRITE) {
write_card (unlock);
}
nfc_disconnect (pnd);
break;
case ACTION_EXTRACT:{
const char *pcDump = argv[2];
const char *pcPayload = argv[3];
FILE *pfDump = NULL;
FILE *pfPayload = NULL;
char abDump[4096];
char abPayload[4096];
pfDump = fopen (pcDump, "rb");
if (pfDump == NULL) {
printf ("Could not open dump file: %s\n", pcDump);
exit (EXIT_FAILURE);
}
if (fread (abDump, 1, sizeof (abDump), pfDump) != sizeof (abDump)) {
printf ("Could not read dump file: %s\n", pcDump);
fclose (pfDump);
exit (EXIT_FAILURE);
}
fclose (pfDump);
mifare_classic_extract_payload (abDump, abPayload);
printf ("Writing data to file: %s\n", pcPayload);
pfPayload = fopen (pcPayload, "wb");
if (pfPayload == NULL) {
printf ("Could not open file %s for writting.\n", pcPayload);
exit (EXIT_FAILURE);
}
if (fwrite (abPayload, 1, sizeof (abPayload), pfPayload) != sizeof (abPayload)) {
printf ("Could not write to file: %s\n", pcPayload);
exit (EXIT_FAILURE);
}
fclose (pfPayload);
printf ("Done, all bytes have been extracted!\n");
}
};
exit (EXIT_SUCCESS);
}

View file

@ -1,35 +0,0 @@
.TH NFC-MFSETUID 1 "Sep 05, 2011"
.SH NAME
nfc-mfsetuid \- MIFARE 1K special card UID setting and recovery tool
.SH SYNOPSIS
.B nfc-mfsetuid
[UID]
.SH DESCRIPTION
.B nfc-mfsetuid
is a MIFARE tool that allows setting of UID on special versions (Chinese clones) of Mifare 1K cards. It will also recover
damaged cards that have had invalid data written to block 0 (e.g. wrong BCC). Currently only 4 Byte UID is supported.
Specify an eight hex character UID or leave blank for the default '01234567'.
.SH OPTIONS
.B -f
Format. Wipe all data (set to 0xFF) and reset ACLs to defaults.
.B -q
Quiet. Suppress output of commands and responses.
.SH BUGS
Please report any bugs on the
.B libnfc
forum at
.BR http://www.libnfc.org/community/ "."
.SH LICENCE
.B libnfc
and
.B libnfc-examples
are covered by the GNU Lesser General Public License (LGPL), version 3.
.SH AUTHORS
Roel Verdult <roel@libnfc.org>
Adam Laurie <adam@algroup.co.uk>
.PP
This manual page was written by Adam Laurie <adam@algroup.co.uk>.
It is licensed under the terms of the GNU GPL (version 2 or later).

View file

@ -1,352 +0,0 @@
/*-
* Public platform independent Near Field Communication (NFC) library examples
*
* Copyright (C) 2009, Roel Verdult
* Copyright (C) 2011, Adam Laurie
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2 )Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Note that this license only applies on the examples, NFC library itself is under LGPL
*
*/
/**
* @file nfc-mfsetuid.c
* @brief Set UID of special Mifare cards
*/
/**
* based on nfc-anticol.c
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif // HAVE_CONFIG_H
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <nfc/nfc.h>
#include "nfc-utils.h"
#define SAK_FLAG_ATS_SUPPORTED 0x20
#define MAX_FRAME_LEN 264
static byte_t abtRx[MAX_FRAME_LEN];
static size_t szRxBits;
static size_t szRx = sizeof(abtRx);
static byte_t abtRawUid[12];
static byte_t abtAtqa[2];
static byte_t abtSak;
static byte_t abtAts[MAX_FRAME_LEN];
static byte_t szAts = 0;
static size_t szCL = 1;//Always start with Cascade Level 1 (CL1)
static nfc_device_t *pnd;
bool quiet_output = false;
bool iso_ats_supported = 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, 0x00, 0x00 };
byte_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
#define CASCADE_BIT 0x04
// special unlock command
byte_t abtUnlock1[1] = { 0x40 };
byte_t abtUnlock2[1] = { 0x43 };
byte_t abtWipe[1] = { 0x41 };
byte_t abtWrite[4] = { 0xa0, 0x00, 0x5f, 0xb1 };
byte_t abtData[18] = { 0x01, 0x23, 0x45, 0x67, 0x00, 0x08, 0x04, 0x00, 0x46, 0x59, 0x25, 0x58, 0x49, 0x10, 0x23, 0x02, 0x23, 0xeb };
byte_t abtBlank[18] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x36, 0xCC };
static bool
transmit_bits (const byte_t * pbtTx, const size_t szTxBits)
{
// Show transmitted command
if (!quiet_output) {
printf ("Sent bits: ");
print_hex_bits (pbtTx, szTxBits);
}
// Transmit the bit frame command, we don't use the arbitrary parity feature
if (!nfc_initiator_transceive_bits (pnd, pbtTx, szTxBits, NULL, abtRx, &szRxBits, NULL))
return false;
// Show received answer
if (!quiet_output) {
printf ("Received bits: ");
print_hex_bits (abtRx, szRxBits);
}
// Succesful transfer
return true;
}
static bool
transmit_bytes (const byte_t * pbtTx, const size_t szTx)
{
// Show transmitted command
if (!quiet_output) {
printf ("Sent bits: ");
print_hex (pbtTx, szTx);
}
// Transmit the command bytes
if (!nfc_initiator_transceive_bytes (pnd, pbtTx, szTx, abtRx, &szRx, NULL))
return false;
// Show received answer
if (!quiet_output) {
printf ("Received bits: ");
print_hex (abtRx, szRx);
}
// Succesful transfer
return true;
}
static 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-f\tFormat. Delete all data (set to 0xFF) and reset ACLs to default.\n");
printf ("\t-q\tQuiet mode. Suppress output of READER and CARD data (improves timing).\n");
printf ("\n\tSpecify UID (4 HEX bytes) to set UID, or leave blank for default '01234567'.\n");
printf ("\tThis utility can be used to recover cards that have been damaged by writing bad\n");
printf ("\tdata (e.g. wrong BCC), thus making them non-selectable by most tools/readers.\n");
printf ("\n\t*** Note: this utility only works with special Mifare 1K cards (Chinese clones).\n\n");
}
int
main (int argc, char *argv[])
{
int arg, i;
bool format= false;
unsigned int c;
char tmp[3]= { 0x00, 0x00, 0x00 };
// Get commandline options
for (arg = 1; arg < argc; arg++) {
if (0 == strcmp (argv[arg], "-h")) {
print_usage (argv);
exit(EXIT_SUCCESS);
} else if (0 == strcmp (argv[arg], "-f")) {
format= true;
} else if (0 == strcmp (argv[arg], "-q")) {
quiet_output = true;
} else if (strlen(argv[arg]) == 8) {
for(i= 0 ; i < 4 ; ++i) {
memcpy(tmp, argv[arg]+i*2, 2);
sscanf(tmp, "%02x", &c);
abtData[i]= (char) c;
}
abtData[4]= abtData[0] ^ abtData[1] ^ abtData[2] ^ abtData[3];
iso14443a_crc_append (abtData, 16);
} else {
ERR ("%s is not supported option.", argv[arg]);
print_usage (argv);
exit(EXIT_FAILURE);
}
}
// Try to open the NFC reader
pnd = nfc_connect (NULL);
if (!pnd) {
printf ("Error connecting NFC reader\n");
exit(EXIT_FAILURE);
}
// Initialise NFC device as "initiator"
nfc_initiator_init (pnd);
// Configure the CRC
if (!nfc_configure (pnd, NDO_HANDLE_CRC, false)) {
nfc_perror (pnd, "nfc_configure");
exit (EXIT_FAILURE);
}
// Use raw send/receive methods
if (!nfc_configure (pnd, NDO_EASY_FRAMING, false)) {
nfc_perror (pnd, "nfc_configure");
exit (EXIT_FAILURE);
}
// Disable 14443-4 autoswitching
if (!nfc_configure (pnd, NDO_AUTO_ISO14443_4, false)) {
nfc_perror (pnd, "nfc_configure");
exit (EXIT_FAILURE);
}
printf ("Connected to NFC reader: %s\n\n", pnd->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 (pnd);
return 1;
}
memcpy (abtAtqa, abtRx, 2);
// Anti-collision
transmit_bytes (abtSelectAll, 2);
// Check answer
if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
printf("WARNING: BCC check failed!\n");
}
// Save the UID CL1
memcpy (abtRawUid, abtRx, 4);
//Prepare and send CL1 Select-Command
memcpy (abtSelectTag + 2, abtRx, 5);
iso14443a_crc_append (abtSelectTag, 7);
transmit_bytes (abtSelectTag, 9);
abtSak = abtRx[0];
// Test if we are dealing with a CL2
if (abtSak & CASCADE_BIT) {
szCL = 2;//or more
// Check answer
if (abtRawUid[0] != 0x88) {
printf("WARNING: Cascade bit set but CT != 0x88!\n");
}
}
if(szCL == 2) {
// We have to do the anti-collision for cascade level 2
// Prepare CL2 commands
abtSelectAll[0] = 0x95;
// Anti-collision
transmit_bytes (abtSelectAll, 2);
// Check answer
if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
printf("WARNING: BCC check failed!\n");
}
// Save UID CL2
memcpy (abtRawUid + 4, abtRx, 4);
// Selection
abtSelectTag[0] = 0x95;
memcpy (abtSelectTag + 2, abtRx, 5);
iso14443a_crc_append (abtSelectTag, 7);
transmit_bytes (abtSelectTag, 9);
abtSak = abtRx[0];
// Test if we are dealing with a CL3
if (abtSak & CASCADE_BIT) {
szCL = 3;
// Check answer
if (abtRawUid[0] != 0x88) {
printf("WARNING: Cascade bit set but CT != 0x88!\n");
}
}
if ( szCL == 3) {
// We have to do the anti-collision for cascade level 3
// Prepare and send CL3 AC-Command
abtSelectAll[0] = 0x97;
transmit_bytes (abtSelectAll, 2);
// Check answer
if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
printf("WARNING: BCC check failed!\n");
}
// Save UID CL3
memcpy (abtRawUid + 8, abtRx, 4);
// Prepare and send final Select-Command
abtSelectTag[0] = 0x97;
memcpy (abtSelectTag + 2, abtRx, 5);
iso14443a_crc_append (abtSelectTag, 7);
transmit_bytes (abtSelectTag, 9);
abtSak = abtRx[0];
}
}
// Request ATS, this only applies to tags that support ISO 14443A-4
if (abtRx[0] & SAK_FLAG_ATS_SUPPORTED) {
iso_ats_supported = true;
}
printf ("\nFound tag with\n UID: ");
switch (szCL) {
case 1:
printf ("%02x%02x%02x%02x", abtRawUid[0], abtRawUid[1], abtRawUid[2], abtRawUid[3]);
break;
case 2:
printf ("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]);
printf ("%02x%02x%02x%02x", abtRawUid[4], abtRawUid[5], abtRawUid[6], abtRawUid[7]);
break;
case 3:
printf ("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]);
printf ("%02x%02x%02x", abtRawUid[5], abtRawUid[6], abtRawUid[7]);
printf ("%02x%02x%02x%02x", abtRawUid[8], abtRawUid[9], abtRawUid[10], abtRawUid[11]);
break;
}
printf("\n");
printf("ATQA: %02x%02x\n SAK: %02x\n", abtAtqa[1], abtAtqa[0], abtSak);
if (szAts > 1) { // if = 1, it's not actual ATS but error code
printf(" ATS: ");
print_hex (abtAts, szAts);
}
printf("\n");
// now reset UID
iso14443a_crc_append(abtHalt, 2);
transmit_bytes (abtHalt, 4);
transmit_bits (abtUnlock1,7);
if(format) {
transmit_bytes (abtWipe,1);
transmit_bytes (abtHalt, 4);
transmit_bits (abtUnlock1,7);
}
transmit_bytes (abtUnlock2,1);
transmit_bytes (abtWrite,4);
transmit_bytes (abtData,18);
if(format) {
for(i= 3 ; i < 64 ; i += 4) {
abtWrite[1]= (char) i;
iso14443a_crc_append (abtWrite, 2);
transmit_bytes (abtWrite,4);
transmit_bytes (abtBlank,18);
}
}
nfc_disconnect (pnd);
return 0;
}

View file

@ -1,50 +0,0 @@
.TH NFC-MFULTRALIGHT 1 "Nov 02, 2009"
.SH NAME
nfc-mfultralight \- MIFARE Ultralight command line tool
.SH SYNOPSIS
.B nfc-mfultralight
.RI \fR\fBr\fR|\fBw\fR
.IR DUMP
.SH DESCRIPTION
.B nfc-mfultralight
is a MIFARE Ultralight tool that allows to read or write
a tag data to/from a
.IR DUMP
file.
MIFARE Ultralight tag is one of the most widely used RFID tags for ticketing application.
It uses a binary Mifare Dump file (MFD) to store data for all sectors.
Be cautious that some parts of a Ultralight memory can be written only once
and some parts are used as lock bits, so please read the tag documentation
before experimenting too much!
.SH OPTIONS
.BR r " | " w
Perform read from (
.B r
) or write to (
.B w
) card.
.TP
.IR DUMP
MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)
.SH BUGS
Please report any bugs on the
.B libnfc
forum at
.BR http://www.libnfc.org/community/ "."
.SH LICENCE
.B libnfc
and
.B libnfc-examples
are covered by the GNU Lesser General Public License (LGPL), version 3.
.SH AUTHORS
Roel Verdult <roel@libnfc.org>
Romuald Conty <romuald@libnfc.org>
.PP
This manual page was written by Romuald Conty <romuald@libnfc.org>.
It is licensed under the terms of the GNU GPL (version 2 or later).

View file

@ -1,268 +0,0 @@
/*-
* Public platform independent Near Field Communication (NFC) library examples
*
* Copyright (C) 2009, Roel Verdult
* Copyright (C) 2010, Romuald Conty
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2 )Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Note that this license only applies on the examples, NFC library itself is under LGPL
*
*/
/**
* @file nfc-mfultralight.c
* @brief MIFARE Ultralight dump/restore tool
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif // HAVE_CONFIG_H
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#include <nfc/nfc.h>
#include "nfc-utils.h"
#include "mifare.h"
static nfc_device_t *pnd;
static nfc_target_t nt;
static mifare_param mp;
static mifareul_tag mtDump;
static uint32_t uiBlocks = 0xF;
static const nfc_modulation_t nmMifare = {
.nmt = NMT_ISO14443A,
.nbr = NBR_106,
};
static void
print_success_or_failure (bool bFailure, uint32_t * uiCounter)
{
printf ("%c", (bFailure) ? 'x' : '.');
if (uiCounter)
*uiCounter += (bFailure) ? 0 : 1;
}
static bool
read_card (void)
{
uint32_t page;
bool bFailure = false;
uint32_t uiReadedPages = 0;
printf ("Reading %d pages |", uiBlocks + 1);
for (page = 0; page <= uiBlocks; page += 4) {
// Try to read out the data block
if (nfc_initiator_mifare_cmd (pnd, MC_READ, page, &mp)) {
memcpy (mtDump.amb[page / 4].mbd.abtData, mp.mpd.abtData, 16);
} else {
bFailure = true;
break;
}
print_success_or_failure (bFailure, &uiReadedPages);
print_success_or_failure (bFailure, &uiReadedPages);
print_success_or_failure (bFailure, &uiReadedPages);
print_success_or_failure (bFailure, &uiReadedPages);
}
printf ("|\n");
printf ("Done, %d of %d pages readed.\n", uiReadedPages, uiBlocks + 1);
fflush (stdout);
return (!bFailure);
}
static bool
write_card (void)
{
uint32_t uiBlock = 0;
bool bFailure = false;
uint32_t uiWritenPages = 0;
uint32_t uiSkippedPages;
char buffer[BUFSIZ];
bool write_otp;
bool write_lock;
printf ("Write OTP bytes ? [yN] ");
if (!fgets (buffer, BUFSIZ, stdin)) {
ERR ("Unable to read standard input.");
}
write_otp = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
printf ("Write Lock bytes ? [yN] ");
if (!fgets (buffer, BUFSIZ, stdin)) {
ERR ("Unable to read standard input.");
}
write_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
printf ("Writing %d pages |", uiBlocks + 1);
/* We need to skip 2 first pages. */
printf ("ss");
uiSkippedPages = 2;
for (int page = 0x2; page <= 0xF; page++) {
if ((page==0x2) && (!write_lock)) {
printf ("s");
uiSkippedPages++;
continue;
}
if ((page==0x3) && (!write_otp)) {
printf ("s");
uiSkippedPages++;
continue;
}
// Show if the readout went well
if (bFailure) {
// When a failure occured we need to redo the anti-collision
if (!nfc_initiator_select_passive_target (pnd, nmMifare, NULL, 0, &nt)) {
ERR ("tag was removed");
return false;
}
bFailure = false;
}
// 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 (pnd, MC_WRITE, page, &mp))
bFailure = true;
print_success_or_failure (bFailure, &uiWritenPages);
}
printf ("|\n");
printf ("Done, %d of %d pages written (%d pages skipped).\n", uiWritenPages, uiBlocks + 1, uiSkippedPages);
return true;
}
int
main (int argc, const char *argv[])
{
bool bReadAction;
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;
}
DBG ("\nChecking arguments and settings\n");
bReadAction = tolower ((int) ((unsigned char) *(argv[1])) == 'r');
if (bReadAction) {
memset (&mtDump, 0x00, sizeof (mtDump));
} else {
pfDump = fopen (argv[2], "rb");
if (pfDump == NULL) {
ERR ("Could not open dump file: %s\n", argv[2]);
return 1;
}
if (fread (&mtDump, 1, sizeof (mtDump), pfDump) != sizeof (mtDump)) {
ERR ("Could not read from dump file: %s\n", argv[2]);
fclose (pfDump);
return 1;
}
fclose (pfDump);
}
DBG ("Successfully opened the dump file\n");
// Try to open the NFC device
pnd = nfc_connect (NULL);
if (pnd == NULL) {
ERR ("Error connecting NFC device\n");
return 1;
}
nfc_initiator_init (pnd);
// Let the device only try once to find a tag
if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
nfc_perror (pnd, "nfc_configure");
exit (EXIT_FAILURE);
}
printf ("Connected to NFC device: %s\n", pnd->acName);
// Try to find a MIFARE Ultralight tag
if (!nfc_initiator_select_passive_target (pnd, nmMifare, NULL, 0, &nt)) {
ERR ("no tag was found\n");
nfc_disconnect (pnd);
return 1;
}
// Test if we are dealing with a MIFARE compatible tag
if (nt.nti.nai.abtAtqa[1] != 0x44) {
ERR ("tag is not a MIFARE Ultralight card\n");
nfc_disconnect (pnd);
return EXIT_FAILURE;
}
// Get the info from the current tag
printf ("Found MIFARE Ultralight card with UID: ");
size_t szPos;
for (szPos = 0; szPos < nt.nti.nai.szUidLen; szPos++) {
printf ("%02x", nt.nti.nai.abtUid[szPos]);
}
printf("\n");
if (bReadAction) {
if (read_card ()) {
printf ("Writing data to file: %s ... ", argv[2]);
fflush (stdout);
pfDump = fopen (argv[2], "wb");
if (pfDump == NULL) {
printf ("Could not open file: %s\n", argv[2]);
return EXIT_FAILURE;
}
if (fwrite (&mtDump, 1, sizeof (mtDump), pfDump) != sizeof (mtDump)) {
printf ("Could not write to file: %s\n", argv[2]);
return EXIT_FAILURE;
}
fclose (pfDump);
printf ("Done.\n");
}
} else {
write_card ();
}
nfc_disconnect (pnd);
return EXIT_SUCCESS;
}

View file

@ -47,7 +47,7 @@
#include <nfc/nfc.h>
#include <nfc/nfc-types.h>
#include "nfc-utils.h"
#include "utils/nfc-utils.h"
#define MAX_DEVICE_COUNT 16

View file

@ -1,74 +0,0 @@
.TH NFC-RELAY-PICC 1 "October 12, 2010"
.SH NAME
nfc-relay-picc \- Relay demonstration tool for ISO14443-4
.SH SYNOPSIS
.B nfc-relay-picc
.SH DESCRIPTION
.B nfc-relay-picc
This tool requires two NFC devices. One device (configured as target) will
emulate an ISO/IEC 14443-4 type A tag, while the second device (configured as
initiator) will act as a reader. The genuine tag can be placed on the second
device (initiator) and the tag emulator (target) can be placed close to the
original reader. All communication is now relayed and shown in the screen on
real-time.
tag <---> initiator (relay) <---> target (relay) <---> original reader
.SH OPTIONS
\fB-h\fP
Help
List options
\fB-q\fP
Quiet mode
Suppress printing of relayed data (improves timing)
\fB-t\fP
Target mode only (to be used on reader side)
Commands are sent to file descriptor 4
Responses are read from file descriptor 3
\fB-i\fP
Initiator mode only (to be used on tag side)
Commands are read from file descriptor 3
Responses are sent to file descriptor 4
\fB-n\fP \fIN\fP
Adds a waiting time of \fIN\fP seconds (integer) in the loop
.SH EXAMPLES
Basic usage:
\fBnfc-relay-picc\fP
Remote relay over TCP/IP:
\fBsocat\fP
TCP-LISTEN:port,reuseaddr
"EXEC:\fBnfc-relay-picc -i\fP,fdin=3,fdout=4"
\fBsocat\fP
TCP:remotehost:port
"EXEC:\fBnfc-relay-picc -t\fP,fdin=3,fdout=4"
.SH NOTES
There are some differences with \fBnfc-relay\fP:
This example only works with PN532 because it relies on
its internal handling of ISO14443-4 specificities.
Thanks to this internal handling & injection of WTX frames,
this example works on readers very strict on timing.
.SH BUGS
Please report any bugs on the
.B libnfc
forum at
.BR http://www.libnfc.org/community/ "."
.SH LICENCE
.B libnfc
and
.B libnfc-examples
are covered by the GNU Lesser General Public License (LGPL), version 3.
.PP
This manual page is licensed under the terms of the GNU GPL (version 2 or later).

View file

@ -1,461 +0,0 @@
/*-
* Public platform independent Near Field Communication (NFC) library examples
*
* Copyright (C) 2010, Romuald Conty
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2 )Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Note that this license only applies on the examples, NFC library itself is under LGPL
*
*/
/**
* @file nfc-relay-picc.c
* @brief Relay example using two PN532 devices.
*/
// Notes & differences with nfc-relay:
// - This example only works with PN532 because it relies on
// its internal handling of ISO14443-4 specificities.
// - Thanks to this internal handling & injection of WTX frames,
// this example works on readers very strict on timing
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <nfc/nfc.h>
#include "nfc-utils.h"
#define MAX_FRAME_LEN 264
#define MAX_DEVICE_COUNT 2
static byte_t abtCapdu[MAX_FRAME_LEN];
static size_t szCapduLen;
static byte_t abtRapdu[MAX_FRAME_LEN];
static size_t szRapduLen;
static nfc_device_t *pndInitiator;
static nfc_device_t *pndTarget;
static bool quitting = false;
static bool quiet_output = false;
static bool initiator_only_mode = false;
static bool target_only_mode = false;
static int waiting_time = 0;
FILE * fd3;
FILE * fd4;
void
intr_hdlr (void)
{
printf ("\nQuitting...\n");
printf ("Please send a last command to the emulator to quit properly.\n");
quitting = true;
return;
}
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 printing of relayed data (improves timing).\n");
printf ("\t-t\tTarget mode only (the one on reader side). Data expected from FD3 to FD4.\n");
printf ("\t-i\tInitiator mode only (the one on tag side). Data expected from FD3 to FD4.\n");
printf ("\t-n N\tAdds a waiting time of N seconds (integer) in the relay to mimic long distance.\n");
}
bool print_hex_fd4 (const byte_t * pbtData, const size_t szBytes, const char * pchPrefix)
{
size_t szPos;
if (szBytes > MAX_FRAME_LEN) {
return EXIT_FAILURE;
}
if (fprintf (fd4, "#%s %04zx: ", pchPrefix, szBytes)<0) {
return EXIT_FAILURE;
}
for (szPos = 0; szPos < szBytes; szPos++) {
if (fprintf (fd4, "%02x ", pbtData[szPos])<0) {
return EXIT_FAILURE;
}
}
if (fprintf (fd4, "\n")<0) {
return EXIT_FAILURE;
}
fflush(fd4);
return EXIT_SUCCESS;
}
bool scan_hex_fd3 (byte_t *pbtData, size_t *pszBytes, const char * pchPrefix)
{
size_t szPos;
unsigned int uiBytes;
unsigned int uiData;
char pchScan[256];
int c;
// Look for our next sync marker
while ( (c=fgetc(fd3)) != '#') {
if (c == EOF) {
return EXIT_FAILURE;
}
}
strncpy(pchScan, pchPrefix, 250);
strcat(pchScan, " %04x:");
if (fscanf (fd3, pchScan, &uiBytes)<1) {
return EXIT_FAILURE;
}
*pszBytes=uiBytes;
if (*pszBytes > MAX_FRAME_LEN) {
return EXIT_FAILURE;
}
for (szPos = 0; szPos < *pszBytes; szPos++) {
if (fscanf (fd3, "%02x", &uiData)<1) {
return EXIT_FAILURE;
}
pbtData[szPos]=uiData;
}
return EXIT_SUCCESS;
}
int
main (int argc, char *argv[])
{
int arg;
size_t szFound;
nfc_device_desc_t *pnddDevices;
const char *acLibnfcVersion = nfc_version ();
nfc_target_t ntRealTarget;
// Get commandline options
for (arg = 1; arg < argc; arg++) {
if (0 == strcmp (argv[arg], "-h")) {
print_usage (argv);
return EXIT_SUCCESS;
} else if (0 == strcmp (argv[arg], "-q")) {
quiet_output = true;
} else if (0 == strcmp (argv[arg], "-t")) {
printf ("INFO: %s\n", "Target mode only.");
initiator_only_mode = false;
target_only_mode = true;
} else if (0 == strcmp (argv[arg], "-i")) {
printf ("INFO: %s\n", "Initiator mode only.");
initiator_only_mode = true;
target_only_mode = false;
} else if (0 == strcmp (argv[arg], "-n")) {
if (++arg==argc || (sscanf(argv[arg], "%i", &waiting_time)<1)) {
ERR ("Missing or wrong waiting time value: %s.", argv[arg]);
print_usage (argv);
return EXIT_FAILURE;
}
printf ("Waiting time: %i secs.\n", waiting_time);
} else {
ERR ("%s is not supported option.", argv[arg]);
print_usage (argv);
return EXIT_FAILURE;
}
}
// Display libnfc version
printf ("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
#ifdef WIN32
signal (SIGINT, (void (__cdecl *) (int)) intr_hdlr);
#else
signal (SIGINT, (void (*)()) intr_hdlr);
#endif
// Allocate memory to put the result of available devices listing
if (!(pnddDevices = malloc (MAX_DEVICE_COUNT * sizeof (*pnddDevices)))) {
fprintf (stderr, "malloc() failed\n");
return EXIT_FAILURE;
}
// List available devices
nfc_list_devices (pnddDevices, MAX_DEVICE_COUNT, &szFound);
if (initiator_only_mode || target_only_mode) {
if (szFound < 1) {
ERR ("No device found");
return EXIT_FAILURE;
}
fd3 = fdopen(3, "r");
fd4 = fdopen(4, "w");
}
else {
if (szFound < 2) {
ERR ("%zd device found but two connected devices are needed to relay NFC.", szFound);
return EXIT_FAILURE;
}
}
if (!target_only_mode) {
// Try to open the NFC reader used as initiator
// Little hack to allow using initiator no matter if
// there is already a target used locally or not on the same machine:
// if there is more than one readers connected we connect to the second reader
// (we hope they're always detected in the same order)
if (szFound == 1) {
pndInitiator = nfc_connect (&(pnddDevices[0]));
} else {
pndInitiator = nfc_connect (&(pnddDevices[1]));
}
if (!pndInitiator) {
printf ("Error connecting NFC reader\n");
exit(EXIT_FAILURE);
}
printf ("Connected to the NFC reader device: %s\n", pndInitiator->acName);
if (!nfc_initiator_init (pndInitiator)) {
printf ("Error: fail initializing initiator\n");
nfc_disconnect (pndInitiator);
exit (EXIT_FAILURE);
}
// Try to find a ISO 14443-4A tag
nfc_modulation_t nm = {
.nmt = NMT_ISO14443A,
.nbr = NBR_106,
};
if (!nfc_initiator_select_passive_target (pndInitiator, nm, NULL, 0, &ntRealTarget)) {
printf ("Error: no tag was found\n");
nfc_disconnect (pndInitiator);
exit (EXIT_FAILURE);
}
printf("Found tag:\n");
print_nfc_iso14443a_info (ntRealTarget.nti.nai, false);
if (initiator_only_mode) {
if (print_hex_fd4(ntRealTarget.nti.nai.abtUid, ntRealTarget.nti.nai.szUidLen, "UID") != EXIT_SUCCESS) {
fprintf (stderr, "Error while printing UID to FD4\n");
nfc_disconnect (pndInitiator);
exit(EXIT_FAILURE);
}
if (print_hex_fd4(ntRealTarget.nti.nai.abtAtqa, 2, "ATQA") != EXIT_SUCCESS) {
fprintf (stderr, "Error while printing ATQA to FD4\n");
nfc_disconnect (pndInitiator);
exit(EXIT_FAILURE);
}
if (print_hex_fd4(&(ntRealTarget.nti.nai.btSak), 1, "SAK") != EXIT_SUCCESS) {
fprintf (stderr, "Error while printing SAK to FD4\n");
nfc_disconnect (pndInitiator);
exit(EXIT_FAILURE);
}
if (print_hex_fd4(ntRealTarget.nti.nai.abtAts, ntRealTarget.nti.nai.szAtsLen, "ATS") != EXIT_SUCCESS) {
fprintf (stderr, "Error while printing ATS to FD4\n");
nfc_disconnect (pndInitiator);
exit(EXIT_FAILURE);
}
}
}
if (initiator_only_mode) {
printf ("Hint: tag <---> *INITIATOR* (relay) <-FD3/FD4-> target (relay) <---> original reader\n\n");
} else if (target_only_mode) {
printf ("Hint: tag <---> initiator (relay) <-FD3/FD4-> *TARGET* (relay) <---> original reader\n\n");
} else {
printf ("Hint: tag <---> initiator (relay) <---> target (relay) <---> original reader\n\n");
}
if (!initiator_only_mode) {
nfc_target_t ntEmulatedTarget = {
.nm = {
.nmt = NMT_ISO14443A,
.nbr = NBR_106,
},
};
if (target_only_mode) {
size_t foo;
if (scan_hex_fd3(ntEmulatedTarget.nti.nai.abtUid, &(ntEmulatedTarget.nti.nai.szUidLen), "UID") != EXIT_SUCCESS) {
fprintf (stderr, "Error while scanning UID from FD3\n");
nfc_disconnect (pndInitiator);
exit(EXIT_FAILURE);
}
if (scan_hex_fd3(ntEmulatedTarget.nti.nai.abtAtqa, &foo, "ATQA") != EXIT_SUCCESS) {
fprintf (stderr, "Error while scanning ATQA from FD3\n");
nfc_disconnect (pndInitiator);
exit(EXIT_FAILURE);
}
if (scan_hex_fd3(&(ntEmulatedTarget.nti.nai.btSak), &foo, "SAK") != EXIT_SUCCESS) {
fprintf (stderr, "Error while scanning SAK from FD3\n");
nfc_disconnect (pndInitiator);
exit(EXIT_FAILURE);
}
if (scan_hex_fd3(ntEmulatedTarget.nti.nai.abtAts, &(ntEmulatedTarget.nti.nai.szAtsLen), "ATS") != EXIT_SUCCESS) {
fprintf (stderr, "Error while scanning ATS from FD3\n");
nfc_disconnect (pndInitiator);
exit(EXIT_FAILURE);
}
} else {
ntEmulatedTarget.nti = ntRealTarget.nti;
}
// We can only emulate a short UID, so fix length & ATQA bit:
ntEmulatedTarget.nti.nai.szUidLen = 4;
ntEmulatedTarget.nti.nai.abtAtqa[1] &= (0xFF-0x40);
// First byte of UID is always automatically replaced by 0x08 in this mode anyway
ntEmulatedTarget.nti.nai.abtUid[0] = 0x08;
// ATS is always automatically replaced by PN532, we've no control on it:
// ATS = (05) 75 33 92 03
// (TL) T0 TA TB TC
// | | | +-- CID supported, NAD supported
// | | +----- FWI=9 SFGI=2 => FWT=154ms, SFGT=1.21ms
// | +-------- DR=2,4 DS=2,4 => supports 106, 212 & 424bps in both directions
// +----------- TA,TB,TC, FSCI=5 => FSC=64
// It seems hazardous to tell we support NAD if the tag doesn't support NAD but I don't know how to disable it
// PC/SC pseudo-ATR = 3B 80 80 01 01 if there is no historical bytes
// Creates ATS and copy max 48 bytes of Tk:
byte_t * pbtTk;
size_t szTk;
pbtTk = iso14443a_locate_historical_bytes (ntEmulatedTarget.nti.nai.abtAts, ntEmulatedTarget.nti.nai.szAtsLen, &szTk);
szTk = (szTk > 48) ? 48 : szTk;
byte_t pbtTkt[48];
memcpy(pbtTkt, pbtTk, szTk);
ntEmulatedTarget.nti.nai.abtAts[0] = 0x75;
ntEmulatedTarget.nti.nai.abtAts[1] = 0x33;
ntEmulatedTarget.nti.nai.abtAts[2] = 0x92;
ntEmulatedTarget.nti.nai.abtAts[3] = 0x03;
ntEmulatedTarget.nti.nai.szAtsLen = 4 + szTk;
memcpy(&(ntEmulatedTarget.nti.nai.abtAts[4]), pbtTkt, szTk);
printf("We will emulate:\n");
print_nfc_iso14443a_info (ntEmulatedTarget.nti.nai, false);
// Try to open the NFC emulator device
pndTarget = nfc_connect (&(pnddDevices[0]));
if (pndTarget == NULL) {
printf ("Error connecting NFC emulator device\n");
if (!target_only_mode) {
nfc_disconnect (pndInitiator);
}
return EXIT_FAILURE;
}
printf ("Connected to the NFC emulator device: %s\n", pndTarget->acName);
if (!nfc_target_init (pndTarget, &ntEmulatedTarget, abtCapdu, &szCapduLen)) {
ERR ("%s", "Initialization of NFC emulator failed");
if (!target_only_mode) {
nfc_disconnect (pndInitiator);
}
nfc_disconnect (pndTarget);
exit(EXIT_FAILURE);
}
printf ("%s\n", "Done, relaying frames now!");
}
while (!quitting) {
bool ret;
if (!initiator_only_mode) {
// Receive external reader command through target
if (!nfc_target_receive_bytes(pndTarget,abtCapdu,&szCapduLen, NULL)) {
nfc_perror (pndTarget, "nfc_target_receive_bytes");
if (!target_only_mode) {
nfc_disconnect (pndInitiator);
}
nfc_disconnect (pndTarget);
exit(EXIT_FAILURE);
}
if (target_only_mode) {
if (print_hex_fd4(abtCapdu, szCapduLen, "C-APDU") != EXIT_SUCCESS) {
fprintf (stderr, "Error while printing C-APDU to FD4\n");
nfc_disconnect (pndTarget);
exit(EXIT_FAILURE);
}
}
} else {
if (scan_hex_fd3(abtCapdu, &szCapduLen, "C-APDU") != EXIT_SUCCESS) {
fprintf (stderr, "Error while scanning C-APDU from FD3\n");
nfc_disconnect (pndInitiator);
exit(EXIT_FAILURE);
}
}
// Show transmitted response
if (!quiet_output) {
printf ("Forwarding C-APDU: ");
print_hex (abtCapdu, szCapduLen);
}
if (!target_only_mode) {
// Forward the frame to the original tag
ret = nfc_initiator_transceive_bytes
(pndInitiator, abtCapdu, szCapduLen, abtRapdu, &szRapduLen, NULL);
} else {
if (scan_hex_fd3(abtRapdu, &szRapduLen, "R-APDU") != EXIT_SUCCESS) {
fprintf (stderr, "Error while scanning R-APDU from FD3\n");
nfc_disconnect (pndTarget);
exit(EXIT_FAILURE);
}
ret = true;
}
if (ret) {
// Redirect the answer back to the external reader
if (waiting_time > 0) {
if (!quiet_output) {
printf ("Waiting %is to simulate longer relay...\n", waiting_time);
}
sleep(waiting_time);
}
// Show transmitted response
if (!quiet_output) {
printf ("Forwarding R-APDU: ");
print_hex (abtRapdu, szRapduLen);
}
if (!initiator_only_mode) {
// Transmit the response bytes
if (!nfc_target_send_bytes(pndTarget, abtRapdu, szRapduLen, NULL)) {
nfc_perror (pndTarget, "nfc_target_send_bytes");
if (!target_only_mode) {
nfc_disconnect (pndInitiator);
}
if (!initiator_only_mode) {
nfc_disconnect (pndTarget);
}
exit(EXIT_FAILURE);
}
} else {
if (print_hex_fd4(abtRapdu, szRapduLen, "R-APDU") != EXIT_SUCCESS) {
fprintf (stderr, "Error while printing R-APDU to FD4\n");
nfc_disconnect (pndInitiator);
exit(EXIT_FAILURE);
}
}
}
}
if (!target_only_mode) {
nfc_disconnect (pndInitiator);
}
if (!initiator_only_mode) {
nfc_disconnect (pndTarget);
}
exit (EXIT_SUCCESS);
}

View file

@ -45,7 +45,7 @@
#include <nfc/nfc.h>
#include "nfc-utils.h"
#include "utils/nfc-utils.h"
#define MAX_FRAME_LEN 264
#define MAX_DEVICE_COUNT 2

View file

@ -1,777 +0,0 @@
/*-
* Public platform independent Near Field Communication (NFC) library examples
*
* Copyright (C) 2009, Roel Verdult
* Copyright (C) 2010, Romuald Conty, Romain Tartière
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2 )Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Note that this license only applies on the examples, NFC library itself is under LGPL
*
*/
#include <nfc/nfc.h>
#include <err.h>
#include "nfc-utils.h"
static const byte_t OddParity[256] = {
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
};
byte_t
oddparity (const byte_t bt)
{
return OddParity[bt];
}
void
oddparity_bytes_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar)
{
size_t szByteNr;
// Calculate the parity bits for the command
for (szByteNr = 0; szByteNr < szLen; szByteNr++) {
pbtPar[szByteNr] = OddParity[pbtData[szByteNr]];
}
}
void
print_hex (const byte_t * pbtData, const size_t szBytes)
{
size_t szPos;
for (szPos = 0; szPos < szBytes; szPos++) {
printf ("%02x ", pbtData[szPos]);
}
printf ("\n");
}
void
print_hex_bits (const byte_t * pbtData, const size_t szBits)
{
uint8_t uRemainder;
size_t szPos;
size_t szBytes = szBits / 8;
for (szPos = 0; szPos < szBytes; szPos++) {
printf ("%02x ", pbtData[szPos]);
}
uRemainder = szBits % 8;
// Print the rest bits
if (uRemainder != 0) {
if (uRemainder < 5)
printf ("%01x (%d bits)", pbtData[szBytes], uRemainder);
else
printf ("%02x (%d bits)", pbtData[szBytes], uRemainder);
}
printf ("\n");
}
void
print_hex_par (const byte_t * pbtData, const size_t szBits, const byte_t * pbtDataPar)
{
uint8_t uRemainder;
size_t szPos;
size_t szBytes = szBits / 8;
for (szPos = 0; szPos < szBytes; szPos++) {
printf ("%02x", pbtData[szPos]);
if (OddParity[pbtData[szPos]] != pbtDataPar[szPos]) {
printf ("! ");
} else {
printf (" ");
}
}
uRemainder = szBits % 8;
// Print the rest bits, these cannot have parity bit
if (uRemainder != 0) {
if (uRemainder < 5)
printf ("%01x (%d bits)", pbtData[szBytes], uRemainder);
else
printf ("%02x (%d bits)", pbtData[szBytes], uRemainder);
}
printf ("\n");
}
#define SAK_UID_NOT_COMPLETE 0x04
#define SAK_ISO14443_4_COMPLIANT 0x20
#define SAK_ISO18092_COMPLIANT 0x40
void
print_nfc_iso14443a_info (const nfc_iso14443a_info_t nai, bool verbose)
{
printf (" ATQA (SENS_RES): ");
print_hex (nai.abtAtqa, 2);
if (verbose) {
printf("* UID size: ");
switch ((nai.abtAtqa[1] & 0xc0)>>6) {
case 0:
printf("single\n");
break;
case 1:
printf("double\n");
break;
case 2:
printf("triple\n");
break;
case 3:
printf("RFU\n");
break;
}
printf("* bit frame anticollision ");
switch (nai.abtAtqa[1] & 0x1f) {
case 0x01:
case 0x02:
case 0x04:
case 0x08:
case 0x10:
printf("supported\n");
break;
default:
printf("not supported\n");
break;
}
}
printf (" UID (NFCID%c): ", (nai.abtUid[0] == 0x08 ? '3' : '1'));
print_hex (nai.abtUid, nai.szUidLen);
if (verbose) {
if (nai.abtUid[0] == 0x08) {
printf ("* Random UID\n");
}
}
printf (" SAK (SEL_RES): ");
print_hex (&nai.btSak, 1);
if (verbose) {
if (nai.btSak & SAK_UID_NOT_COMPLETE) {
printf ("* Warning! Cascade bit set: UID not complete\n");
}
if (nai.btSak & SAK_ISO14443_4_COMPLIANT) {
printf ("* Compliant with ISO/IEC 14443-4\n");
} else {
printf ("* Not compliant with ISO/IEC 14443-4\n");
}
if (nai.btSak & SAK_ISO18092_COMPLIANT) {
printf ("* Compliant with ISO/IEC 18092\n");
} else {
printf ("* Not compliant with ISO/IEC 18092\n");
}
}
if (nai.szAtsLen) {
printf (" ATS: ");
print_hex (nai.abtAts, nai.szAtsLen);
}
if (nai.szAtsLen && verbose) {
// Decode ATS according to ISO/IEC 14443-4 (5.2 Answer to select)
const int iMaxFrameSizes[] = { 16, 24, 32, 40, 48, 64, 96, 128, 256 };
printf ("* Max Frame Size accepted by PICC: %d bytes\n", iMaxFrameSizes[nai.abtAts[0] & 0x0F]);
size_t offset = 1;
if (nai.abtAts[0] & 0x10) { // TA(1) present
byte_t TA = nai.abtAts[offset];
offset++;
printf ("* Bit Rate Capability:\n");
if (TA == 0) {
printf (" * PICC supports only 106 kbits/s in both directions\n");
}
if (TA & 1<<7) {
printf (" * Same bitrate in both directions mandatory\n");
}
if (TA & 1<<4) {
printf (" * PICC to PCD, DS=2, bitrate 212 kbits/s supported\n");
}
if (TA & 1<<5) {
printf (" * PICC to PCD, DS=4, bitrate 424 kbits/s supported\n");
}
if (TA & 1<<6) {
printf (" * PICC to PCD, DS=8, bitrate 847 kbits/s supported\n");
}
if (TA & 1<<0) {
printf (" * PCD to PICC, DR=2, bitrate 212 kbits/s supported\n");
}
if (TA & 1<<1) {
printf (" * PCD to PICC, DR=4, bitrate 424 kbits/s supported\n");
}
if (TA & 1<<2) {
printf (" * PCD to PICC, DR=8, bitrate 847 kbits/s supported\n");
}
if (TA & 1<<3) {
printf (" * ERROR unknown value\n");
}
}
if (nai.abtAts[0] & 0x20) { // TB(1) present
byte_t TB= nai.abtAts[offset];
offset++;
printf ("* Frame Waiting Time: %.4g ms\n",256.0*16.0*(1<<((TB & 0xf0) >> 4))/13560.0);
if ((TB & 0x0f) == 0) {
printf ("* No Start-up Frame Guard Time required\n");
} else {
printf ("* Start-up Frame Guard Time: %.4g ms\n",256.0*16.0*(1<<(TB & 0x0f))/13560.0);
}
}
if (nai.abtAts[0] & 0x40) { // TC(1) present
byte_t TC = nai.abtAts[offset];
offset++;
if (TC & 0x1) {
printf("* Node ADdress supported\n");
} else {
printf("* Node ADdress not supported\n");
}
if (TC & 0x2) {
printf("* Card IDentifier supported\n");
} else {
printf("* Card IDentifier not supported\n");
}
}
if (nai.szAtsLen > offset) {
printf ("* Historical bytes Tk: " );
print_hex (nai.abtAts + offset, (nai.szAtsLen - offset));
byte_t CIB = nai.abtAts[offset];
offset++;
if (CIB != 0x00 && CIB != 0x10 && (CIB & 0xf0) != 0x80) {
printf(" * Proprietary format\n");
if (CIB == 0xc1) {
printf(" * Tag byte: Mifare or virtual cards of various types\n");
byte_t L = nai.abtAts[offset];
offset++;
if (L != (nai.szAtsLen - offset)) {
printf(" * Warning: Type Identification Coding length (%i)", L);
printf(" not matching Tk length (%zi)\n", (nai.szAtsLen - offset));
}
if ((nai.szAtsLen - offset - 2) > 0) { // Omit 2 CRC bytes
byte_t CTC = nai.abtAts[offset];
offset++;
printf(" * Chip Type: ");
switch (CTC & 0xf0) {
case 0x00:
printf("(Multiple) Virtual Cards\n");
break;
case 0x10:
printf("Mifare DESFire\n");
break;
case 0x20:
printf("Mifare Plus\n");
break;
default:
printf("RFU\n");
break;
}
printf(" * Memory size: ");
switch (CTC & 0x0f) {
case 0x00:
printf("<1 kbyte\n");
break;
case 0x01:
printf("1 kbyte\n");
break;
case 0x02:
printf("2 kbyte\n");
break;
case 0x03:
printf("4 kbyte\n");
break;
case 0x04:
printf("8 kbyte\n");
break;
case 0x0f:
printf("Unspecified\n");
break;
default:
printf("RFU\n");
break;
}
}
if ((nai.szAtsLen - offset) > 0) { // Omit 2 CRC bytes
byte_t CVC = nai.abtAts[offset];
offset++;
printf(" * Chip Status: ");
switch (CVC & 0xf0) {
case 0x00:
printf("Engineering sample\n");
break;
case 0x20:
printf("Released\n");
break;
default:
printf("RFU\n");
break;
}
printf(" * Chip Generation: ");
switch (CVC & 0x0f) {
case 0x00:
printf("Generation 1\n");
break;
case 0x01:
printf("Generation 2\n");
break;
case 0x02:
printf("Generation 3\n");
break;
case 0x0f:
printf("Unspecified\n");
break;
default:
printf("RFU\n");
break;
}
}
if ((nai.szAtsLen - offset) > 0) { // Omit 2 CRC bytes
byte_t VCS = nai.abtAts[offset];
offset++;
printf(" * Specifics (Virtual Card Selection):\n");
if ((VCS & 0x09) == 0x00) {
printf(" * Only VCSL supported\n");
} else if ((VCS & 0x09) == 0x01) {
printf(" * VCS, VCSL and SVC supported\n");
}
if ((VCS & 0x0e) == 0x00) {
printf(" * SL1, SL2(?), SL3 supported\n");
} else if ((VCS & 0x0e) == 0x02) {
printf(" * SL3 only card\n");
} else if ((VCS & 0x0f) == 0x0e) {
printf(" * No VCS command supported\n");
} else if ((VCS & 0x0f) == 0x0f) {
printf(" * Unspecified\n");
} else {
printf(" * RFU\n");
}
}
}
} else {
if (CIB == 0x00) {
printf(" * Tk after 0x00 consist of optional consecutive COMPACT-TLV data objects\n");
printf(" followed by a mandatory status indicator (the last three bytes, not in TLV)\n");
printf(" See ISO/IEC 7816-4 8.1.1.3 for more info\n");
}
if (CIB == 0x10) {
printf(" * DIR data reference: %02x\n", nai.abtAts[offset]);
}
if (CIB == 0x80) {
if (nai.szAtsLen == offset) {
printf(" * No COMPACT-TLV objects found, no status found\n");
} else {
printf(" * Tk after 0x80 consist of optional consecutive COMPACT-TLV data objects;\n");
printf(" the last data object may carry a status indicator of one, two or three bytes.\n");
printf(" See ISO/IEC 7816-4 8.1.1.3 for more info\n");
}
}
}
}
}
if (verbose) {
printf("Fingerprinting based on ATQA & SAK values:\n");
uint32_t atqasak = 0;
atqasak += (((uint32_t)nai.abtAtqa[0] & 0xff)<<16);
atqasak += (((uint32_t)nai.abtAtqa[1] & 0xff)<<8);
atqasak += ((uint32_t)nai.btSak & 0xff);
bool found_possible_match = false;
switch (atqasak) {
case 0x000218:
printf("* Mifare Classic 4K\n");
found_possible_match = true;
break;
case 0x000408:
printf("* Mifare Classic 1K\n");
printf("* Mifare Plus (4-byte UID) 2K SL1\n");
found_possible_match = true;
break;
case 0x000409:
printf("* Mifare MINI\n");
found_possible_match = true;
break;
case 0x000410:
printf("* Mifare Plus (4-byte UID) 2K SL2\n");
found_possible_match = true;
break;
case 0x000411:
printf("* Mifare Plus (4-byte UID) 4K SL2\n");
found_possible_match = true;
break;
case 0x000418:
printf("* Mifare Plus (4-byte UID) 4K SL1\n");
found_possible_match = true;
break;
case 0x000420:
printf("* Mifare Plus (4-byte UID) 2K/4K SL3\n");
found_possible_match = true;
break;
case 0x004400:
printf("* Mifare Ultralight\n");
printf("* Mifare UltralightC\n");
found_possible_match = true;
break;
case 0x004208:
case 0x004408:
printf("* Mifare Plus (7-byte UID) 2K SL1\n");
found_possible_match = true;
break;
case 0x004218:
case 0x004418:
printf("* Mifare Plus (7-byte UID) 4K SL1\n");
found_possible_match = true;
break;
case 0x004210:
case 0x004410:
printf("* Mifare Plus (7-byte UID) 2K SL2\n");
found_possible_match = true;
break;
case 0x004211:
case 0x004411:
printf("* Mifare Plus (7-byte UID) 4K SL2\n");
found_possible_match = true;
break;
case 0x004220:
case 0x004420:
printf("* Mifare Plus (7-byte UID) 2K/4K SL3\n");
found_possible_match = true;
break;
case 0x034420:
printf("* Mifare DESFire / Desfire EV1\n");
found_possible_match = true;
break;
}
// Other matches not described in
// AN MIFARE Type Identification Procedure
// but seen in the field:
switch (atqasak) {
case 0x000488:
printf("* Mifare Classic 1K Infineon\n");
found_possible_match = true;
break;
case 0x000298:
printf("* Gemplus MPCOS\n");
found_possible_match = true;
break;
case 0x030428:
printf("* JCOP31\n");
found_possible_match = true;
break;
case 0x004820:
printf("* JCOP31 v2.4.1\n");
printf("* JCOP31 v2.2\n");
found_possible_match = true;
break;
case 0x000428:
printf("* JCOP31 v2.3.1\n");
found_possible_match = true;
break;
case 0x000453:
printf("* Fudan FM1208SH01\n");
found_possible_match = true;
break;
case 0x000820:
printf("* Fudan FM1208\n");
found_possible_match = true;
break;
case 0x000238:
printf("* MFC 4K emulated by Nokia 6212 Classic\n");
found_possible_match = true;
break;
case 0x000838:
printf("* MFC 4K emulated by Nokia 6131 NFC\n");
found_possible_match = true;
break;
}
if ((nai.abtAtqa[0] & 0xf0) == 0) {
switch (nai.abtAtqa[1]) {
case 0x02:
printf("* SmartMX with Mifare 4K emulation\n");
found_possible_match = true;
break;
case 0x04:
printf("* SmartMX with Mifare 1K emulation\n");
found_possible_match = true;
break;
case 0x48:
printf("* SmartMX with 7-byte UID\n");
found_possible_match = true;
break;
}
}
if (! found_possible_match) {
printf("* Unknown card, sorry\n");
}
}
}
void
print_nfc_felica_info (const nfc_felica_info_t nfi, bool verbose)
{
(void) verbose;
printf (" ID (NFCID2): ");
print_hex (nfi.abtId, 8);
printf (" Parameter (PAD): ");
print_hex (nfi.abtPad, 8);
}
void
print_nfc_jewel_info (const nfc_jewel_info_t nji, bool verbose)
{
(void) verbose;
printf (" ATQA (SENS_RES): ");
print_hex (nji.btSensRes, 2);
printf (" 4-LSB JEWELID: ");
print_hex (nji.btId, 4);
}
#define PI_ISO14443_4_SUPPORTED 0x01
#define PI_NAD_SUPPORTED 0x01
#define PI_CID_SUPPORTED 0x02
void
print_nfc_iso14443b_info (const nfc_iso14443b_info_t nbi, bool verbose)
{
const int iMaxFrameSizes[] = { 16, 24, 32, 40, 48, 64, 96, 128, 256 };
printf (" PUPI: ");
print_hex (nbi.abtPupi, 4);
printf (" Application Data: ");
print_hex (nbi.abtApplicationData, 4);
printf (" Protocol Info: ");
print_hex (nbi.abtProtocolInfo, 3);
if (verbose) {
printf ("* Bit Rate Capability:\n");
if (nbi.abtProtocolInfo[0] == 0) {
printf (" * PICC supports only 106 kbits/s in both directions\n");
}
if (nbi.abtProtocolInfo[0] & 1<<7) {
printf (" * Same bitrate in both directions mandatory\n");
}
if (nbi.abtProtocolInfo[0] & 1<<4) {
printf (" * PICC to PCD, 1etu=64/fc, bitrate 212 kbits/s supported\n");
}
if (nbi.abtProtocolInfo[0] & 1<<5) {
printf (" * PICC to PCD, 1etu=32/fc, bitrate 424 kbits/s supported\n");
}
if (nbi.abtProtocolInfo[0] & 1<<6) {
printf (" * PICC to PCD, 1etu=16/fc, bitrate 847 kbits/s supported\n");
}
if (nbi.abtProtocolInfo[0] & 1<<0) {
printf (" * PCD to PICC, 1etu=64/fc, bitrate 212 kbits/s supported\n");
}
if (nbi.abtProtocolInfo[0] & 1<<1) {
printf (" * PCD to PICC, 1etu=32/fc, bitrate 424 kbits/s supported\n");
}
if (nbi.abtProtocolInfo[0] & 1<<2) {
printf (" * PCD to PICC, 1etu=16/fc, bitrate 847 kbits/s supported\n");
}
if (nbi.abtProtocolInfo[0] & 1<<3) {
printf (" * ERROR unknown value\n");
}
if( (nbi.abtProtocolInfo[1] & 0xf0) <= 0x80 ) {
printf ("* Maximum frame sizes: %d bytes\n", iMaxFrameSizes[((nbi.abtProtocolInfo[1] & 0xf0) >> 4)]);
}
if((nbi.abtProtocolInfo[1] & 0x0f) == PI_ISO14443_4_SUPPORTED) {
printf ("* Protocol types supported: ISO/IEC 14443-4\n");
}
printf ("* Frame Waiting Time: %.4g ms\n",256.0*16.0*(1<<((nbi.abtProtocolInfo[2] & 0xf0) >> 4))/13560.0);
if((nbi.abtProtocolInfo[2] & (PI_NAD_SUPPORTED|PI_CID_SUPPORTED)) != 0) {
printf ("* Frame options supported: ");
if ((nbi.abtProtocolInfo[2] & PI_NAD_SUPPORTED) != 0) printf ("NAD ");
if ((nbi.abtProtocolInfo[2] & PI_CID_SUPPORTED) != 0) printf ("CID ");
printf("\n");
}
}
}
void
print_nfc_iso14443bi_info (const nfc_iso14443bi_info_t nii, bool verbose)
{
printf (" DIV: ");
print_hex (nii.abtDIV, 4);
if (verbose) {
int version = (nii.btVerLog & 0x1e)>>1;
printf (" Software Version: ");
if (version == 15) {
printf ("Undefined\n");
} else {
printf ("%i\n", version);
}
if ((nii.btVerLog & 0x80) && (nii.btConfig & 0x80)){
printf (" Wait Enable: yes");
}
}
if ((nii.btVerLog & 0x80) && (nii.btConfig & 0x40)) {
printf (" ATS: ");
print_hex (nii.abtAtr, nii.szAtrLen);
}
}
void
print_nfc_iso14443b2sr_info (const nfc_iso14443b2sr_info_t nsi, bool verbose)
{
(void) verbose;
printf (" UID: ");
print_hex (nsi.abtUID, 8);
}
void
print_nfc_iso14443b2ct_info (const nfc_iso14443b2ct_info_t nci, bool verbose)
{
(void) verbose;
uint32_t uid;
uid = (nci.abtUID[3] << 24) + (nci.abtUID[2] << 16) + (nci.abtUID[1] << 8) + nci.abtUID[0];
printf (" UID: ");
print_hex (nci.abtUID, sizeof(nci.abtUID));
printf (" UID (decimal): %010u\n", uid);
printf (" Product Code: %02X\n", nci.btProdCode);
printf (" Fab Code: %02X\n", nci.btFabCode);
}
void
print_nfc_dep_info (const nfc_dep_info_t ndi, bool verbose)
{
(void) verbose;
printf (" NFCID3: ");
print_hex (ndi.abtNFCID3, 10);
printf (" BS: %02x\n", ndi.btBS);
printf (" BR: %02x\n", ndi.btBR);
printf (" TO: %02x\n", ndi.btTO);
printf (" PP: %02x\n", ndi.btPP);
if (ndi.szGB) {
printf ("General Bytes: ");
print_hex (ndi.abtGB, ndi.szGB);
}
}
/**
* @brief Tries to parse arguments to find device descriptions.
* @return Returns the list of found device descriptions.
*/
nfc_device_desc_t *
parse_args (int argc, const char *argv[], size_t * szFound, bool * verbose)
{
nfc_device_desc_t *pndd = 0;
int arg;
*szFound = 0;
// Get commandline options
for (arg = 1; arg < argc; arg++) {
if (0 == strcmp (argv[arg], "--device")) {
// FIXME: this device selection by command line options is terrible & does not support USB/PCSC drivers
if (argc > arg + 1) {
char buffer[256];
pndd = malloc (sizeof (nfc_device_desc_t));
strncpy (buffer, argv[++arg], 256);
// Driver.
pndd->pcDriver = (char *) malloc (256);
strcpy (pndd->pcDriver, strtok (buffer, ":"));
// Port.
strcpy (pndd->acPort, strtok (NULL, ":"));
// Speed.
sscanf (strtok (NULL, ":"), "%u", &pndd->uiSpeed);
*szFound = 1;
} else {
errx (1, "usage: %s [--device driver:port:speed]", argv[0]);
}
}
if ((0 == strcmp (argv[arg], "-v")) || (0 == strcmp (argv[arg], "--verbose"))) {
*verbose = true;
}
}
return pndd;
}
const char *
str_nfc_baud_rate (const nfc_baud_rate_t nbr)
{
switch(nbr) {
case NBR_UNDEFINED:
return "undefined baud rate";
break;
case NBR_106:
return "106 kbps";
break;
case NBR_212:
return "212 kbps";
break;
case NBR_424:
return "424 kbps";
break;
case NBR_847:
return "847 kbps";
break;
}
return "";
}
void
print_nfc_target (const nfc_target_t nt, bool verbose)
{
switch(nt.nm.nmt) {
case NMT_ISO14443A:
printf ("ISO/IEC 14443A (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
print_nfc_iso14443a_info (nt.nti.nai, verbose);
break;
case NMT_JEWEL:
printf ("Innovision Jewel (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
print_nfc_jewel_info (nt.nti.nji, verbose);
break;
case NMT_FELICA:
printf ("FeliCa (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
print_nfc_felica_info (nt.nti.nfi, verbose);
break;
case NMT_ISO14443B:
printf ("ISO/IEC 14443-4B (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
print_nfc_iso14443b_info (nt.nti.nbi, verbose);
break;
case NMT_ISO14443BI:
printf ("ISO/IEC 14443-4B' (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
print_nfc_iso14443bi_info (nt.nti.nii, verbose);
break;
case NMT_ISO14443B2SR:
printf ("ISO/IEC 14443-2B ST SRx (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
print_nfc_iso14443b2sr_info (nt.nti.nsi, verbose);
break;
case NMT_ISO14443B2CT:
printf ("ISO/IEC 14443-2B ASK CTx (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
print_nfc_iso14443b2ct_info (nt.nti.nci, verbose);
break;
case NMT_DEP:
printf ("D.E.P. (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
print_nfc_dep_info (nt.nti.ndi, verbose);
break;
}
}

View file

@ -1,102 +0,0 @@
/*-
* Public platform independent Near Field Communication (NFC) library examples
*
* Copyright (C) 2009, Roel Verdult
* Copyright (C) 2010, Romuald Conty, Romain Tartière
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2 )Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Note that this license only applies on the examples, NFC library itself is under LGPL
*
*/
/**
* @file nfc-utils.h
* @brief Provide some examples shared functions like print, parity calculation, options parsing.
*/
#ifndef _EXAMPLES_NFC_UTILS_H_
# define _EXAMPLES_NFC_UTILS_H_
# include <stdlib.h>
# include <string.h>
# include <err.h>
/**
* @macro DBG
* @brief Print a message of standard output only in DEBUG mode
*/
#ifdef DEBUG
# define DBG(...) do { \
warnx ("DBG %s:%d", __FILE__, __LINE__); \
warnx (" " __VA_ARGS__ ); \
} while (0)
#else
# define DBG(...) {}
#endif
/**
* @macro WARN
* @brief Print a warn message
*/
#ifdef DEBUG
# define WARN(...) do { \
warnx ("WARNING %s:%d", __FILE__, __LINE__); \
warnx (" " __VA_ARGS__ ); \
} while (0)
#else
# define WARN(...) warnx ("WARNING: " __VA_ARGS__ )
#endif
/**
* @macro ERR
* @brief Print a error message
*/
#ifdef DEBUG
# define ERR(...) do { \
warnx ("ERROR %s:%d", __FILE__, __LINE__); \
warnx (" " __VA_ARGS__ ); \
} while (0)
#else
# define ERR(...) warnx ("ERROR: " __VA_ARGS__ )
#endif
byte_t oddparity (const byte_t bt);
void oddparity_byte_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar);
void print_hex (const byte_t * pbtData, const size_t szLen);
void print_hex_bits (const byte_t * pbtData, const size_t szBits);
void print_hex_par (const byte_t * pbtData, const size_t szBits, const byte_t * pbtDataPar);
void print_nfc_iso14443a_info (const nfc_iso14443a_info_t nai, bool verbose);
void print_nfc_iso14443b_info (const nfc_iso14443b_info_t nbi, bool verbose);
void print_nfc_iso14443bi_info (const nfc_iso14443bi_info_t nii, bool verbose);
void print_nfc_iso14443b2sr_info (const nfc_iso14443b2sr_info_t nsi, bool verbose);
void print_nfc_iso14443b2ct_info (const nfc_iso14443b2ct_info_t nci, bool verbose);
void print_nfc_felica_info (const nfc_felica_info_t nfi, bool verbose);
void print_nfc_jewel_info (const nfc_jewel_info_t nji, bool verbose);
void print_nfc_dep_info (const nfc_dep_info_t ndi, bool verbose);
void print_nfc_target (const nfc_target_t nt, bool verbose);
nfc_device_desc_t *parse_args (int argc, const char *argv[], size_t * szFound, bool * verbose);
#endif

View file

@ -44,8 +44,8 @@
#include <nfc/nfc.h>
#include "nfc-utils.h"
#include "chips/pn53x.h"
#include "utils/nfc-utils.h"
#include "libnfc/chips/pn53x.h"
#define MAX_DEVICE_COUNT 16

View file

@ -45,8 +45,8 @@
#include <nfc/nfc.h>
#include "nfc-utils.h"
#include "chips/pn53x.h"
#include "utils/nfc-utils.h"
#include "libnfc/chips/pn53x.h"
#define MAX_FRAME_LEN 264
#define TIMEOUT 60 // secs.

View file

@ -64,9 +64,8 @@
#include <nfc/nfc.h>
#include "nfc-utils.h"
#include "chips/pn53x.h"
#include "utils/nfc-utils.h"
#include "libnfc/chips/pn53x.h"
#define MAX_FRAME_LEN 264