Improve the target emulation functions (ATM, only ISO14443A), add an example (nfc-emulate-tag), update examples to use the new API.

This commit is contained in:
Romuald Conty 2010-10-04 12:46:03 +00:00
parent d2d15afa3b
commit 5233fceda7
11 changed files with 272 additions and 38 deletions

View file

@ -2,6 +2,7 @@ bin_PROGRAMS = \
nfc-anticol \
nfc-emulate \
nfc-emulate-ndef \
nfc-emulate-tag \
nfc-list \
nfc-mfclassic \
nfc-mfultralight \
@ -51,7 +52,15 @@ nfc_emulate_LDADD = $(top_builddir)/libnfc/libnfc.la \
nfc_emulate_ndef_SOURCES = nfc-emulate-ndef.c
nfc_emulate_ndef_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
libnfcutils.la
nfc_emulate_tag_SOURCES = nfc-emulate-tag.c
nfc_emulate_tag_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
nfc_sam_SOURCES = nfc-sam.c
nfc_sam_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
nfcip_target_SOURCES = nfcip-target.c
nfcip_target_LDADD = $(top_builddir)/libnfc/libnfc.la
@ -61,17 +70,13 @@ nfcip_initiator_LDADD = $(top_builddir)/libnfc/libnfc.la
pn53x_diagnose_SOURCES = pn53x-diagnose.c
pn53x_diagnose_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
libnfcutils.la
pn53x_tamashell_SOURCES = pn53x-tamashell.c
pn53x_tamashell_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
pn53x_tamashell_LDFLAGS = @READLINE_LIBS@
nfc_sam_SOURCES = nfc-sam.c
nfc_sam_LDADD = $(top_builddir)/libnfc/libnfc.la \
libnfcutils.la
dist_man_MANS = nfc-anticol.1 nfc-emulate.1 nfc-list.1 nfc-mfclassic.1 nfc-mfultralight.1 nfc-relay.1 nfc-sam.1
EXTRA_DIST = CMakeLists.txt

View file

@ -91,7 +91,17 @@ main (int argc, char *argv[])
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_target_init (pnd, NTM_PICC, abtRx, &szRxLen)) {
nfc_target_t nt = {
.ntt = NTT_MIFARE,
.nti.nai.abtAtqa = { 0x00, 0x04 },
.nti.nai.abtUid = { 0x08, 0x00, 0xb0, 0x0b },
.nti.nai.btSak = 0x20,
.nti.nai.szUidLen = 4,
.nti.nai.szAtsLen = 0,
};
if (!nfc_target_init (pnd, NTM_PICC, nt, abtRx, &szRxLen)) {
nfc_perror (pnd, "nfc_target_init");
ERR("Could not come out of auto-emulation, no command was received");
return EXIT_FAILURE;

152
examples/nfc-emulate-tag.c Normal file
View file

@ -0,0 +1,152 @@
/*-
* Public platform independent Near Field Communication (NFC) library
*
* Copyright (C) 2010, Romuald Conty
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
/**
* @file nfc-emulate-ndef.c
* @brief Emulate a tag
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif // HAVE_CONFIG_H
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <nfc/nfc.h>
#include <nfc/nfc-messages.h>
#include "nfc-utils.h"
#define MAX_FRAME_LEN 264
static byte_t abtRx[MAX_FRAME_LEN];
static size_t szRxLen;
static nfc_device_t *pnd;
static bool quiet_output = false;
bool
target_io( const nfc_target_t nt, const byte_t * pbtInput, const size_t szInput, byte_t * pbtOutput, size_t *pszOutput )
{
bool loop = true;
*pszOutput = 0;
// Show transmitted command
if (!quiet_output) {
printf (" In: ");
print_hex (pbtInput, szInput);
}
if(szInput) {
switch(pbtInput[0]) {
case 0xe0: // RATS
// Send ATS
*pszOutput = nt.nti.nai.szAtsLen + 1;
pbtOutput[0] = nt.nti.nai.szAtsLen + 1; // ISO14443-4 says that ATS contains ATS_Lenght as first byte
if(nt.nti.nai.szAtsLen) {
memcpy(pbtOutput+1, nt.nti.nai.abtAts, nt.nti.nai.szAtsLen);
}
break;
default: // Unknown
if (!quiet_output) {
printf("Unknown frame, emulated target abort.\n");
}
loop = false;
}
}
// Show transmitted command
if (!quiet_output) {
printf (" Out: ");
print_hex (pbtOutput, *pszOutput);
}
return loop;
}
bool
nfc_target_emulate_tag(nfc_device_t* pnd, const nfc_target_t nt)
{
size_t szTx;
byte_t abtTx[MAX_FRAME_LEN];
bool loop = true;
if (!nfc_target_init (pnd, NTM_PASSIVE, nt, abtRx, &szRxLen)) {
return false;
}
while ( loop ) {
loop = target_io( nt, abtRx, szRxLen, abtTx, &szTx );
if (szTx) {
if (!nfc_target_send_bytes(pnd, abtTx, szTx)) {
return false;
}
}
if ( loop ) {
if (!nfc_target_receive_bytes(pnd, abtRx, &szRxLen)) {
return false;
}
}
}
return true;
}
int
main (int argc, char *argv[])
{
const char *acLibnfcVersion;
// Try to open the NFC reader
pnd = nfc_connect (NULL);
// Display libnfc version
acLibnfcVersion = nfc_version ();
printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
if (pnd == NULL) {
ERR("Unable to connect to NFC device");
return EXIT_FAILURE;
}
printf ("Connected to NFC device: %s\n", pnd->acName);
nfc_target_t nt = {
.ntt = NTT_MIFARE,
.nti.nai.abtAtqa = { 0x03, 0x44 },
.nti.nai.abtUid = { 0x08, 0xab, 0xcd, 0xef },
.nti.nai.btSak = 0x20,
.nti.nai.szUidLen = 4,
.nti.nai.abtAts = { 0x75, 0x77, 0x81, 0x02, 0x80 },
.nti.nai.szAtsLen = 5,
};
printf ("%s will emulate this ISO14443-A tag:\n", argv[0]);
print_nfc_iso14443a_info( nt.nti.nai );
printf ("NFC device (configured as target) is now emulating the tag, please touch it with a second NFC device (initiator)\n");
if (!nfc_target_emulate_tag (pnd, nt)) {
nfc_perror (pnd, "nfc_target_emulate_tag");
ERR("Could not come out of auto-emulation, no command was received");
return EXIT_FAILURE;
}
nfc_disconnect(pnd);
exit (EXIT_SUCCESS);
}

View file

@ -19,7 +19,7 @@
/**
* @file nfc-emulate.c
* @brief
* @brief This example can be used to emulate a tag which which have a "really" custom UID
*/
#ifdef HAVE_CONFIG_H
@ -106,7 +106,17 @@ main (int argc, char *argv[])
printf ("[+] Try to break out the auto-emulation, this requires a second reader!\n");
printf ("[+] To do this, please send any command after the anti-collision\n");
printf ("[+] For example, send a RATS command or use the \"nfc-anticol\" tool\n");
if (!nfc_target_init (pnd, NTM_PASSIVE, abtRecv, &szRecvBits)) {
// Note: We have to build a "fake" nfc_target_t in order to do exactly the same that was done before the new nfc_target_init() was introduced.
nfc_target_t nt = {
.ntt = NTT_GENERIC_PASSIVE_106,
.nti.nai.abtAtqa = "\x04\x00",
.nti.nai.abtUid = "\xde\xad\xbe\xaf\x62",
.nti.nai.btSak = 0x20,
.nti.nai.szUidLen = 5,
.nti.nai.szAtsLen = 0,
};
if (!nfc_target_init (pnd, NTM_PASSIVE, nt, abtRecv, &szRecvBits)) {
printf ("Error: Could not come out of auto-emulation, no command was received\n");
return 1;
}

View file

@ -125,7 +125,18 @@ main (int argc, char *argv[])
printf ("[+] Try to break out the auto-emulation, this requires a second reader!\n");
printf ("[+] To do this, please send any command after the anti-collision\n");
printf ("[+] For example, send a RATS command or use the \"nfc-anticol\" tool\n");
if (!nfc_target_init (pndTag, NTM_PASSIVE, abtReaderRx, &szReaderRxBits)) {
// Note: We have to build a "fake" nfc_target_t in order to do exactly the same that was done before the new nfc_target_init() was introduced.
nfc_target_t nt = {
.ntt = NTT_GENERIC_PASSIVE_106,
.nti.nai.abtAtqa = "\x04\x00",
.nti.nai.abtUid = "\xde\xad\xbe\xaf\x62",
.nti.nai.btSak = 0x20,
.nti.nai.szUidLen = 5,
.nti.nai.szAtsLen = 0,
};
if (!nfc_target_init (pndTag, NTM_PASSIVE, nt, abtReaderRx, &szReaderRxBits)) {
ERR ("%s", "Initialization of NFC emulator failed");
nfc_disconnect (pndTag);
return EXIT_FAILURE;

View file

@ -19,7 +19,7 @@
/**
* @file nfc-sam.c
* @brief Configure the reader to comunicate with a SAM (Secure Access Module).
* @brief Configure the NFC device to comunicate with a SAM (Secure Access Module).
*/
#ifdef HAVE_CONFIG_H
@ -129,7 +129,7 @@ main (int argc, const char *argv[])
return EXIT_FAILURE;
}
printf ("Connected to NFC reader: %s\n", pnd->acName);
printf ("Connected to NFC device: %s\n", pnd->acName);
// Print the example's menu
printf ("\nSelect the comunication mode:\n");
@ -152,7 +152,7 @@ main (int argc, const char *argv[])
switch (mode) {
case VIRTUAL_CARD_MODE:
{
// FIXME: after the loop the reader doesn't respond to host commands...
// FIXME: after the loop the device doesn't respond to host commands...
printf ("Now the SAM is readable for 1 minute from an external reader.\n");
wait_one_minute ();
}
@ -207,7 +207,15 @@ main (int argc, const char *argv[])
// FIXME: it does not work as expected...Probably the issue is in "nfc_target_init"
// which doesn't provide a way to set custom data for SENS_RES, NFCID1, SEL_RES, etc.
if (!nfc_target_init (pnd, NTM_PICC, abtRx, &szRxLen))
nfc_target_t nt = {
.ntt = NTT_GENERIC_PASSIVE_106,
.nti.nai.abtAtqa = "\x04\x00",
.nti.nai.abtUid = "\x08\xad\xbe\xaf",
.nti.nai.btSak = 0x20,
.nti.nai.szUidLen = 4,
.nti.nai.szAtsLen = 0,
};
if (!nfc_target_init (pnd, NTM_PICC, nt, abtRx, &szRxLen))
return EXIT_FAILURE;
printf ("Now both the NFC reader and SAM are readable for 1 minute from an external reader.\n");

View file

@ -59,7 +59,17 @@ main (int argc, const char *argv[])
errx (1, "usage: %s", argv[0]);
}
if (!pnd || !nfc_target_init (pnd, NTM_DEP, abtRecv, &szRecvBits)) {
// Note: We have to build a "fake" nfc_target_t in order to do exactly the same that was done before the new nfc_target_init() was introduced.
nfc_target_t nt = {
.ntt = NTT_GENERIC_PASSIVE_106,
.nti.nai.abtAtqa = "\x04\x00",
.nti.nai.abtUid = "\xde\xad\xbe\xaf\x62",
.nti.nai.btSak = 0x20,
.nti.nai.szUidLen = 5,
.nti.nai.szAtsLen = 0,
};
if (!pnd || !nfc_target_init (pnd, NTM_DEP, nt, abtRecv, &szRecvBits)) {
printf ("unable to connect or initialize\n");
return 1;
}