Merge branch 'master' into patch-2
This commit is contained in:
commit
ff4e1efa7b
11 changed files with 921 additions and 97 deletions
|
@ -14,7 +14,6 @@ addons:
|
||||||
- libusb-dev
|
- libusb-dev
|
||||||
- doxygen
|
- doxygen
|
||||||
- cmake
|
- cmake
|
||||||
- libcutter-dev
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- if [ $BLD == autoconf ]; then autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install; fi
|
- if [ $BLD == autoconf ]; then autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install; fi
|
||||||
|
|
|
@ -18,14 +18,15 @@ SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
|
||||||
|
|
||||||
# config.h
|
# config.h
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_windows.h.cmake ${CMAKE_CURRENT_SOURCE_DIR}/config.h)
|
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_windows.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
SET(LIBNFC_SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/config" CACHE PATH "libnfc configuration directory")
|
SET(LIBNFC_SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/config" CACHE PATH "libnfc configuration directory")
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/contrib/win32)
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/contrib/win32)
|
||||||
ELSE(WIN32)
|
ELSE(WIN32)
|
||||||
SET(_XOPEN_SOURCE 600)
|
SET(_XOPEN_SOURCE 600)
|
||||||
SET(SYSCONFDIR "/etc" CACHE PATH "System configuration directory")
|
SET(SYSCONFDIR "/etc" CACHE PATH "System configuration directory")
|
||||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_posix.h.cmake ${CMAKE_CURRENT_SOURCE_DIR}/config.h)
|
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_posix.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
ADD_DEFINITIONS("-DHAVE_CONFIG_H")
|
ADD_DEFINITIONS("-DHAVE_CONFIG_H")
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,11 @@ if DRIVER_PN532_I2C_ENABLED
|
||||||
libnfcdrivers_la_SOURCES += pn532_i2c.c pn532_i2c.h
|
libnfcdrivers_la_SOURCES += pn532_i2c.c pn532_i2c.h
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if DRIVER_PN71XX_ENABLED
|
||||||
|
libnfcdrivers_la_LIBADD += -lnfc_nci_linux
|
||||||
|
libnfcdrivers_la_SOURCES += pn71xx.c pn71xx.h
|
||||||
|
endif
|
||||||
|
|
||||||
if PCSC_ENABLED
|
if PCSC_ENABLED
|
||||||
libnfcdrivers_la_CFLAGS += @libpcsclite_CFLAGS@
|
libnfcdrivers_la_CFLAGS += @libpcsclite_CFLAGS@
|
||||||
libnfcdrivers_la_LIBADD += @libpcsclite_LIBS@
|
libnfcdrivers_la_LIBADD += @libpcsclite_LIBS@
|
||||||
|
|
|
@ -132,13 +132,13 @@ struct pn53x_usb_supported_device {
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct pn53x_usb_supported_device pn53x_usb_supported_devices[] = {
|
const struct pn53x_usb_supported_device pn53x_usb_supported_devices[] = {
|
||||||
{ 0x04CC, 0x0531, NXP_PN531, "Philips / PN531", 0, 0, 0 },
|
{ 0x04CC, 0x0531, NXP_PN531, "Philips / PN531", 0x84, 0x04, 0x40 },
|
||||||
{ 0x04CC, 0x2533, NXP_PN533, "NXP / PN533", 0x04, 0x84, 40 },
|
{ 0x04CC, 0x2533, NXP_PN533, "NXP / PN533", 0x84, 0x04, 0x40 },
|
||||||
{ 0x04E6, 0x5591, SCM_SCL3711, "SCM Micro / SCL3711-NFC&RW", 0x04, 0x84, 40 },
|
{ 0x04E6, 0x5591, SCM_SCL3711, "SCM Micro / SCL3711-NFC&RW", 0x84, 0x04, 0x40 },
|
||||||
{ 0x04E6, 0x5594, SCM_SCL3712, "SCM Micro / SCL3712-NFC&RW", 0, 0, 0 },
|
{ 0x04E6, 0x5594, SCM_SCL3712, "SCM Micro / SCL3712-NFC&RW", 0, 0, 0 }, // to check on real device
|
||||||
{ 0x054c, 0x0193, SONY_PN531, "Sony / PN531", 0, 0, 0 },
|
{ 0x054c, 0x0193, SONY_PN531, "Sony / PN531", 0x84, 0x04, 0x40 },
|
||||||
{ 0x1FD3, 0x0608, ASK_LOGO, "ASK / LoGO", 0x04, 0x84, 40 },
|
{ 0x1FD3, 0x0608, ASK_LOGO, "ASK / LoGO", 0x84, 0x04, 0x40 },
|
||||||
{ 0x054C, 0x02E1, SONY_RCS360, "Sony / FeliCa S360 [PaSoRi]", 0, 0, 0 }
|
{ 0x054C, 0x02E1, SONY_RCS360, "Sony / FeliCa S360 [PaSoRi]", 0x84, 0x04, 0x40 }
|
||||||
};
|
};
|
||||||
|
|
||||||
// PN533 USB descriptors backup buffers
|
// PN533 USB descriptors backup buffers
|
||||||
|
@ -421,6 +421,11 @@ pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring)
|
||||||
// Open the USB device
|
// Open the USB device
|
||||||
if ((data.pudh = usb_open(dev)) == NULL)
|
if ((data.pudh = usb_open(dev)) == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
//To retrieve real USB endpoints configuration:
|
||||||
|
//pn53x_usb_get_end_points(dev, &data);
|
||||||
|
//printf("DEBUG ENDPOINTS In:0x%x Out:0x%x Size:0x%x\n", data.uiEndPointIn, data.uiEndPointOut, data.uiMaxPacketSize);
|
||||||
|
|
||||||
// Retrieve end points, using hardcoded defaults if available
|
// Retrieve end points, using hardcoded defaults if available
|
||||||
// or using the descriptors otherwise.
|
// or using the descriptors otherwise.
|
||||||
if (pn53x_usb_get_end_points_default(dev, &data) == false) {
|
if (pn53x_usb_get_end_points_default(dev, &data) == false) {
|
||||||
|
|
596
libnfc/drivers/pn71xx.c
Normal file
596
libnfc/drivers/pn71xx.c
Normal file
|
@ -0,0 +1,596 @@
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file pn71xx.h
|
||||||
|
* @brief Driver for PN71XX using libnfc-nci library
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
|
#include "pn71xx.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
|
#include "drivers.h"
|
||||||
|
#include "nfc-internal.h"
|
||||||
|
|
||||||
|
#include "linux_nfc_api.h"
|
||||||
|
|
||||||
|
#define PN71XX_DRIVER_NAME "pn71xx"
|
||||||
|
|
||||||
|
#define LOG_CATEGORY "libnfc.driver.pn71xx"
|
||||||
|
#define LOG_GROUP NFC_LOG_GROUP_DRIVER
|
||||||
|
|
||||||
|
const nfc_modulation_type pn71xx_supported_modulation_as_target[] = {NMT_ISO14443A, NMT_FELICA, NMT_ISO14443B, NMT_ISO14443BI, NMT_ISO14443B2SR, NMT_ISO14443B2CT, NMT_JEWEL, NMT_DEP, 0};
|
||||||
|
const nfc_modulation_type pn71xx_supported_modulation_as_initiator[] = {NMT_ISO14443A, NMT_FELICA, NMT_ISO14443B, NMT_ISO14443BI, NMT_ISO14443B2SR, NMT_ISO14443B2CT, NMT_JEWEL, NMT_DEP, 0};
|
||||||
|
|
||||||
|
const nfc_baud_rate pn71xx_iso14443a_supported_baud_rates[] = { NBR_847, NBR_424, NBR_212, NBR_106, 0 };
|
||||||
|
const nfc_baud_rate pn71xx_felica_supported_baud_rates[] = { NBR_424, NBR_212, 0 };
|
||||||
|
const nfc_baud_rate pn71xx_dep_supported_baud_rates[] = { NBR_424, NBR_212, NBR_106, 0 };
|
||||||
|
const nfc_baud_rate pn71xx_jewel_supported_baud_rates[] = { NBR_847, NBR_424, NBR_212, NBR_106, 0 };
|
||||||
|
const nfc_baud_rate pn71xx_iso14443b_supported_baud_rates[] = { NBR_847, NBR_424, NBR_212, NBR_106, 0 };
|
||||||
|
|
||||||
|
static nfcTagCallback_t TagCB;
|
||||||
|
static nfc_tag_info_t *TagInfo = NULL;
|
||||||
|
|
||||||
|
static void onTagArrival(nfc_tag_info_t *pTagInfo);
|
||||||
|
static void onTagDeparture(void);
|
||||||
|
|
||||||
|
/** ------------------------------------------------------------------------ */
|
||||||
|
/** ------------------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @brief Initialize libnfc_nci library to verify presence of PN71xx device.
|
||||||
|
*
|
||||||
|
* @param context NFC context.
|
||||||
|
* @param connstrings array of 'nfc_connstring' buffer (allocated by caller). It is used to store the
|
||||||
|
* connection info strings of devices found.
|
||||||
|
* @param connstrings_len length of the connstrings array.
|
||||||
|
* @return number of devices found.
|
||||||
|
*/
|
||||||
|
static size_t
|
||||||
|
pn71xx_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len)
|
||||||
|
{
|
||||||
|
size_t device_found = 0;
|
||||||
|
|
||||||
|
if ((context == NULL) || (connstrings_len == 0)) return 0;
|
||||||
|
|
||||||
|
if (nfcManager_doInitialize() == 0) {
|
||||||
|
nfc_connstring connstring = "pn71xx";
|
||||||
|
memcpy(connstrings[device_found++], connstring, sizeof(nfc_connstring));
|
||||||
|
}
|
||||||
|
|
||||||
|
return device_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Close connection to PN71xx by stopping the discovery loop and deinitializing the libnfc_nci library.
|
||||||
|
*
|
||||||
|
* @param pnd pointer on the device to close.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
pn71xx_close(nfc_device *pnd)
|
||||||
|
{
|
||||||
|
nfcManager_disableDiscovery();
|
||||||
|
nfcManager_deregisterTagCallback();
|
||||||
|
nfcManager_doDeinitialize();
|
||||||
|
nfc_device_free(pnd);
|
||||||
|
pnd = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Open a connection to PN71xx, starting the discovery loop for tag detection.
|
||||||
|
*
|
||||||
|
* @param context NFC context.
|
||||||
|
* @param connstring connection info to the device
|
||||||
|
* @return pointer to the device, or NULL in case of error.
|
||||||
|
*/
|
||||||
|
static nfc_device *
|
||||||
|
pn71xx_open(const nfc_context *context, const nfc_connstring connstring)
|
||||||
|
{
|
||||||
|
nfc_device *pnd;
|
||||||
|
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "open: %s", connstring);
|
||||||
|
|
||||||
|
pnd = nfc_device_new(context, connstring);
|
||||||
|
if (!pnd) {
|
||||||
|
perror("malloc");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pnd->driver = &pn71xx_driver;
|
||||||
|
strcpy(pnd->name, "pn71xx-device");
|
||||||
|
strcpy(pnd->connstring, connstring);
|
||||||
|
|
||||||
|
TagCB.onTagArrival = onTagArrival;
|
||||||
|
TagCB.onTagDeparture = onTagDeparture;
|
||||||
|
nfcManager_registerTagCallback(&TagCB);
|
||||||
|
|
||||||
|
nfcManager_enableDiscovery(DEFAULT_NFA_TECH_MASK, 1, 0, 0);
|
||||||
|
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "wait 1 seconds for polling");
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
|
return pnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ------------------------------------------------------------------------ */
|
||||||
|
/** ------------------------------------------------------------------------ */
|
||||||
|
static bool IsTechnology(nfc_tag_info_t *TagInfo, nfc_modulation_type nmt)
|
||||||
|
{
|
||||||
|
switch (nmt) {
|
||||||
|
case NMT_ISO14443A:
|
||||||
|
if (TagInfo->technology == TARGET_TYPE_ISO14443_4
|
||||||
|
|| TagInfo->technology == TARGET_TYPE_ISO14443_3A
|
||||||
|
|| TagInfo->technology == TARGET_TYPE_MIFARE_CLASSIC
|
||||||
|
|| TagInfo->technology == TARGET_TYPE_MIFARE_UL)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NMT_ISO14443B:
|
||||||
|
case NMT_ISO14443BI:
|
||||||
|
case NMT_ISO14443B2SR:
|
||||||
|
case NMT_ISO14443B2CT:
|
||||||
|
if (TagInfo->technology == TARGET_TYPE_ISO14443_3B)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NMT_FELICA:
|
||||||
|
if (TagInfo->technology == TARGET_TYPE_FELICA)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NMT_JEWEL:
|
||||||
|
if (TagInfo->technology == TARGET_TYPE_ISO14443_3A
|
||||||
|
&& TagInfo->protocol == NFA_PROTOCOL_T1T)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void BufferPrintBytes(char* buffer, unsigned int buflen, const uint8_t *data, unsigned int datalen)
|
||||||
|
{
|
||||||
|
int cx = 0;
|
||||||
|
for(unsigned int i = 0x00; i < datalen; i++) {
|
||||||
|
cx += snprintf(buffer + cx, buflen - cx, "%02X ", data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PrintTagInfo (nfc_tag_info_t *TagInfo)
|
||||||
|
{
|
||||||
|
switch (TagInfo->technology)
|
||||||
|
{
|
||||||
|
case TARGET_TYPE_UNKNOWN:
|
||||||
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type Unknown'");
|
||||||
|
} break;
|
||||||
|
case TARGET_TYPE_ISO14443_3A:
|
||||||
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type 3A'");
|
||||||
|
} break;
|
||||||
|
case TARGET_TYPE_ISO14443_3B:
|
||||||
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type 3B'");
|
||||||
|
} break;
|
||||||
|
case TARGET_TYPE_ISO14443_4:
|
||||||
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type 4A'");
|
||||||
|
} break;
|
||||||
|
case TARGET_TYPE_FELICA:
|
||||||
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type F'");
|
||||||
|
} break;
|
||||||
|
case TARGET_TYPE_ISO15693:
|
||||||
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type V'");
|
||||||
|
} break;
|
||||||
|
case TARGET_TYPE_NDEF:
|
||||||
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type NDEF'");
|
||||||
|
} break;
|
||||||
|
case TARGET_TYPE_NDEF_FORMATABLE:
|
||||||
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type Formatable'");
|
||||||
|
} break;
|
||||||
|
case TARGET_TYPE_MIFARE_CLASSIC:
|
||||||
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A - Mifare Classic'");
|
||||||
|
} break;
|
||||||
|
case TARGET_TYPE_MIFARE_UL:
|
||||||
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A - Mifare Ul'");
|
||||||
|
} break;
|
||||||
|
case TARGET_TYPE_KOVIO_BARCODE:
|
||||||
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A - Kovio Barcode'");
|
||||||
|
} break;
|
||||||
|
case TARGET_TYPE_ISO14443_3A_3B:
|
||||||
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type A/B'");
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "'Type %d (Unknown or not supported)'\n", TagInfo->technology);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
/*32 is max UID len (Kovio tags)*/
|
||||||
|
if((0x00 != TagInfo->uid_length) && (32 >= TagInfo->uid_length))
|
||||||
|
{
|
||||||
|
char buffer [100];
|
||||||
|
int cx = 0;
|
||||||
|
|
||||||
|
if(4 == TagInfo->uid_length || 7 == TagInfo->uid_length || 10 == TagInfo->uid_length)
|
||||||
|
{
|
||||||
|
cx += snprintf(buffer + cx, sizeof(buffer) - cx, "NFCID1 : \t'");
|
||||||
|
}
|
||||||
|
else if(8 == TagInfo->uid_length)
|
||||||
|
{
|
||||||
|
cx += snprintf(buffer + cx, sizeof(buffer) - cx, "NFCID2 : \t'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cx += snprintf(buffer + cx, sizeof(buffer) - cx, "UID : \t'");
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferPrintBytes(buffer + cx, sizeof(buffer) - cx, (unsigned char*) TagInfo->uid, TagInfo->uid_length);
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s'", buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ------------------------------------------------------------------------ */
|
||||||
|
/** ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
static void onTagArrival(nfc_tag_info_t *pTagInfo)
|
||||||
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "tag found");
|
||||||
|
|
||||||
|
TagInfo = malloc(sizeof(nfc_tag_info_t));
|
||||||
|
memcpy(TagInfo, pTagInfo, sizeof(nfc_tag_info_t));
|
||||||
|
|
||||||
|
PrintTagInfo(TagInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onTagDeparture(void)
|
||||||
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "tag lost");
|
||||||
|
|
||||||
|
free(TagInfo);
|
||||||
|
TagInfo = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pn71xx_initiator_init(struct nfc_device *pnd)
|
||||||
|
{
|
||||||
|
if (pnd == NULL) return NFC_EIO;
|
||||||
|
return NFC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pn71xx_initiator_select_passive_target(struct nfc_device *pnd,
|
||||||
|
const nfc_modulation nm,
|
||||||
|
const uint8_t *pbtInitData, const size_t szInitData,
|
||||||
|
nfc_target *pnt)
|
||||||
|
{
|
||||||
|
if (pnd == NULL) return NFC_EIO;
|
||||||
|
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "select_passive_target");
|
||||||
|
|
||||||
|
if (TagInfo) {
|
||||||
|
|
||||||
|
nfc_target nttmp;
|
||||||
|
memset(&nttmp, 0x00, sizeof(nfc_target));
|
||||||
|
nttmp.nm = nm;
|
||||||
|
|
||||||
|
void* uidPtr = NULL;
|
||||||
|
unsigned int maxLen = 0;
|
||||||
|
|
||||||
|
switch (nm.nmt) {
|
||||||
|
case NMT_ISO14443A:
|
||||||
|
if (IsTechnology(TagInfo, nm.nmt)) {
|
||||||
|
maxLen = 10;
|
||||||
|
uidPtr = nttmp.nti.nai.abtUid;
|
||||||
|
|
||||||
|
if (TagInfo->technology == TARGET_TYPE_MIFARE_CLASSIC) {
|
||||||
|
nttmp.nti.nai.btSak = 0x08;
|
||||||
|
} else {
|
||||||
|
// make hardcoded desfire for freefare lib check
|
||||||
|
nttmp.nti.nai.btSak = 0x20;
|
||||||
|
nttmp.nti.nai.szAtsLen = 5;
|
||||||
|
memcpy (nttmp.nti.nai.abtAts, "\x75\x77\x81\x02", 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NMT_ISO14443B:
|
||||||
|
if (IsTechnology(TagInfo, nm.nmt)) {
|
||||||
|
maxLen = 4;
|
||||||
|
uidPtr = nttmp.nti.nbi.abtPupi;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NMT_ISO14443BI:
|
||||||
|
if (IsTechnology(TagInfo, nm.nmt)) {
|
||||||
|
maxLen = 4;
|
||||||
|
uidPtr = nttmp.nti.nii.abtDIV;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NMT_ISO14443B2SR:
|
||||||
|
if (IsTechnology(TagInfo, nm.nmt)) {
|
||||||
|
maxLen = 8;
|
||||||
|
uidPtr = nttmp.nti.nsi.abtUID;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NMT_ISO14443B2CT:
|
||||||
|
if (IsTechnology(TagInfo, nm.nmt)) {
|
||||||
|
maxLen = 4;
|
||||||
|
uidPtr = nttmp.nti.nci.abtUID;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NMT_FELICA:
|
||||||
|
if (IsTechnology(TagInfo, nm.nmt)) {
|
||||||
|
maxLen = 8;
|
||||||
|
uidPtr = nttmp.nti.nfi.abtId;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NMT_JEWEL:
|
||||||
|
if (IsTechnology(TagInfo, nm.nmt)) {
|
||||||
|
maxLen = 4;
|
||||||
|
uidPtr = nttmp.nti.nji.btId;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uidPtr && TagInfo->uid_length) {
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "target found");
|
||||||
|
int len = TagInfo->uid_length > maxLen ? maxLen : TagInfo->uid_length;
|
||||||
|
memcpy(uidPtr, TagInfo->uid, len);
|
||||||
|
if (nm.nmt == NMT_ISO14443A)
|
||||||
|
nttmp.nti.nai.szUidLen = len;
|
||||||
|
|
||||||
|
// Is a tag info struct available
|
||||||
|
if (pnt) {
|
||||||
|
memcpy(pnt, &nttmp, sizeof(nfc_target));
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pn71xx_initiator_deselect_target(struct nfc_device *pnd)
|
||||||
|
{
|
||||||
|
if (pnd == NULL) return NFC_EIO;
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "deselect_passive_target");
|
||||||
|
return NFC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
pn71xx_initiator_transceive_bytes(struct nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx,
|
||||||
|
const size_t szRx, int timeout)
|
||||||
|
{
|
||||||
|
if (pnd == NULL) return NFC_EIO;
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "transceive_bytes timeout=%d", timeout);
|
||||||
|
|
||||||
|
if (!TagInfo) return NFC_EINVARG;
|
||||||
|
|
||||||
|
char buffer[500];
|
||||||
|
BufferPrintBytes(buffer, sizeof(buffer), pbtTx, szTx);
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "===> %s", buffer);
|
||||||
|
|
||||||
|
int received = nfcTag_transceive(TagInfo->handle, (uint8_t *) pbtTx, szTx, pbtRx, szRx, 500);
|
||||||
|
if (received <= 0)
|
||||||
|
return NFC_EIO;
|
||||||
|
|
||||||
|
BufferPrintBytes(buffer, sizeof(buffer), pbtRx, received);
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "<=== %s", buffer);
|
||||||
|
|
||||||
|
return received;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pn71xx_initiator_poll_target(struct nfc_device *pnd,
|
||||||
|
const nfc_modulation *pnmModulations, const size_t szModulations,
|
||||||
|
const uint8_t uiPollNr, const uint8_t uiPeriod,
|
||||||
|
nfc_target *pnt)
|
||||||
|
{
|
||||||
|
static int periodFactor = 150000;
|
||||||
|
int period = uiPeriod * periodFactor;
|
||||||
|
|
||||||
|
if (pnd == NULL) return 0;
|
||||||
|
|
||||||
|
for (int j = 0; j < uiPollNr; j++) {
|
||||||
|
for (unsigned int i = 0; i < szModulations; i++) {
|
||||||
|
const nfc_modulation nm = pnmModulations[i];
|
||||||
|
|
||||||
|
nfc_target nt;
|
||||||
|
int res = pn71xx_initiator_select_passive_target(pnd, nm, 0, 0, &nt);
|
||||||
|
if (res > 0 && pnt) {
|
||||||
|
memcpy(pnt, &nt, sizeof(nfc_target));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
usleep(period);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pn71xx_initiator_target_is_present(struct nfc_device *pnd, const nfc_target *pnt)
|
||||||
|
{
|
||||||
|
if ((pnd == NULL) || (pnt == NULL)) return 1;
|
||||||
|
return !TagInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** ------------------------------------------------------------------------ */
|
||||||
|
/** ------------------------------------------------------------------------ */
|
||||||
|
static int
|
||||||
|
pn71xx_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt)
|
||||||
|
{
|
||||||
|
if (pnd == NULL) return NFC_EIO;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case N_TARGET:
|
||||||
|
*supported_mt = (nfc_modulation_type *)pn71xx_supported_modulation_as_target;
|
||||||
|
break;
|
||||||
|
case N_INITIATOR:
|
||||||
|
*supported_mt = (nfc_modulation_type *)pn71xx_supported_modulation_as_initiator;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return NFC_EINVARG;
|
||||||
|
}
|
||||||
|
return NFC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pn71xx_get_supported_baud_rate(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type nmt, const nfc_baud_rate **const supported_br)
|
||||||
|
{
|
||||||
|
if (pnd == NULL) return NFC_EIO;
|
||||||
|
if (mode) {}
|
||||||
|
|
||||||
|
switch (nmt) {
|
||||||
|
case NMT_FELICA:
|
||||||
|
*supported_br = (nfc_baud_rate *)pn71xx_felica_supported_baud_rates;
|
||||||
|
break;
|
||||||
|
case NMT_ISO14443A:
|
||||||
|
*supported_br = (nfc_baud_rate *)pn71xx_iso14443a_supported_baud_rates;
|
||||||
|
break;
|
||||||
|
case NMT_ISO14443B:
|
||||||
|
case NMT_ISO14443BI:
|
||||||
|
case NMT_ISO14443B2SR:
|
||||||
|
case NMT_ISO14443B2CT:
|
||||||
|
*supported_br = (nfc_baud_rate *)pn71xx_iso14443b_supported_baud_rates;
|
||||||
|
break;
|
||||||
|
case NMT_JEWEL:
|
||||||
|
*supported_br = (nfc_baud_rate *)pn71xx_jewel_supported_baud_rates;
|
||||||
|
break;
|
||||||
|
case NMT_DEP:
|
||||||
|
*supported_br = (nfc_baud_rate *)pn71xx_dep_supported_baud_rates;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return NFC_EINVARG;
|
||||||
|
}
|
||||||
|
return NFC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ------------------------------------------------------------------------ */
|
||||||
|
/** ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
static int
|
||||||
|
pn71xx_set_property_bool(struct nfc_device *pnd, const nfc_property property, const bool bEnable)
|
||||||
|
{
|
||||||
|
if (pnd == NULL) return NFC_EIO;
|
||||||
|
return NFC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pn71xx_set_property_int(struct nfc_device *pnd, const nfc_property property, const int value)
|
||||||
|
{
|
||||||
|
if (pnd == NULL) return NFC_EIO;
|
||||||
|
return NFC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pn71xx_get_information_about(nfc_device *pnd, char **pbuf)
|
||||||
|
{
|
||||||
|
static const char* info = "PN71XX nfc driver using libnfc-nci userspace library";
|
||||||
|
size_t buflen = strlen(info) + 1;
|
||||||
|
|
||||||
|
if (pnd == NULL) return NFC_EIO;
|
||||||
|
|
||||||
|
*pbuf = malloc(buflen);
|
||||||
|
memcpy(*pbuf, info, buflen);
|
||||||
|
|
||||||
|
return buflen;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief Abort any pending operation
|
||||||
|
*
|
||||||
|
* @param pnd pointer on the NFC device.
|
||||||
|
* @return NFC_SUCCESS
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
pn71xx_abort_command(nfc_device *pnd)
|
||||||
|
{
|
||||||
|
if (pnd == NULL) return NFC_EIO;
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "abort_command");
|
||||||
|
return NFC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pn71xx_idle(struct nfc_device *pnd)
|
||||||
|
{
|
||||||
|
if (pnd == NULL) return NFC_EIO;
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "idle");
|
||||||
|
return NFC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pn71xx_PowerDown(struct nfc_device *pnd)
|
||||||
|
{
|
||||||
|
if (pnd == NULL) return NFC_EIO;
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "PowerDown");
|
||||||
|
return NFC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ------------------------------------------------------------------------ */
|
||||||
|
/** ------------------------------------------------------------------------ */
|
||||||
|
const struct nfc_driver pn71xx_driver = {
|
||||||
|
.name = PN71XX_DRIVER_NAME,
|
||||||
|
.scan_type = NOT_INTRUSIVE,
|
||||||
|
.scan = pn71xx_scan,
|
||||||
|
.open = pn71xx_open,
|
||||||
|
.close = pn71xx_close,
|
||||||
|
.strerror = NULL,
|
||||||
|
|
||||||
|
.initiator_init = pn71xx_initiator_init,
|
||||||
|
.initiator_init_secure_element = NULL,
|
||||||
|
.initiator_select_passive_target = pn71xx_initiator_select_passive_target,
|
||||||
|
.initiator_poll_target = pn71xx_initiator_poll_target,
|
||||||
|
.initiator_select_dep_target = NULL,
|
||||||
|
.initiator_deselect_target = pn71xx_initiator_deselect_target,
|
||||||
|
.initiator_transceive_bytes = pn71xx_initiator_transceive_bytes,
|
||||||
|
.initiator_transceive_bits = NULL,
|
||||||
|
.initiator_transceive_bytes_timed = NULL,
|
||||||
|
.initiator_transceive_bits_timed = NULL,
|
||||||
|
.initiator_target_is_present = pn71xx_initiator_target_is_present,
|
||||||
|
|
||||||
|
.target_init = NULL,
|
||||||
|
.target_send_bytes = NULL,
|
||||||
|
.target_receive_bytes = NULL,
|
||||||
|
.target_send_bits = NULL,
|
||||||
|
.target_receive_bits = NULL,
|
||||||
|
|
||||||
|
.device_set_property_bool = pn71xx_set_property_bool,
|
||||||
|
.device_set_property_int = pn71xx_set_property_int,
|
||||||
|
.get_supported_modulation = pn71xx_get_supported_modulation,
|
||||||
|
.get_supported_baud_rate = pn71xx_get_supported_baud_rate,
|
||||||
|
.device_get_information_about = pn71xx_get_information_about,
|
||||||
|
|
||||||
|
.abort_command = pn71xx_abort_command,
|
||||||
|
.idle = pn71xx_idle,
|
||||||
|
.powerdown = pn71xx_PowerDown,
|
||||||
|
};
|
||||||
|
|
14
libnfc/drivers/pn71xx.h
Normal file
14
libnfc/drivers/pn71xx.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/**
|
||||||
|
* @file pn71xx.h
|
||||||
|
* @brief Driver for PN71XX using libnfc-nci library
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __NFC_DRIVER_PN71XX_H__
|
||||||
|
#define __NFC_DRIVER_PN71XX_H__
|
||||||
|
|
||||||
|
#include <nfc/nfc-types.h>
|
||||||
|
|
||||||
|
/* Reference to the driver structure */
|
||||||
|
extern const struct nfc_driver pn71xx_driver;
|
||||||
|
|
||||||
|
#endif // ! __NFC_DRIVER_7120_H__
|
28
libnfc/nfc.c
28
libnfc/nfc.c
|
@ -119,6 +119,10 @@
|
||||||
# include "drivers/pn532_i2c.h"
|
# include "drivers/pn532_i2c.h"
|
||||||
#endif /* DRIVER_PN532_I2C_ENABLED */
|
#endif /* DRIVER_PN532_I2C_ENABLED */
|
||||||
|
|
||||||
|
#if defined (DRIVER_PN71XX_ENABLED)
|
||||||
|
# include "drivers/pn71xx.h"
|
||||||
|
#endif /* DRIVER_PN71XX_ENABLED */
|
||||||
|
|
||||||
|
|
||||||
#define LOG_CATEGORY "libnfc.general"
|
#define LOG_CATEGORY "libnfc.general"
|
||||||
#define LOG_GROUP NFC_LOG_GROUP_GENERAL
|
#define LOG_GROUP NFC_LOG_GROUP_GENERAL
|
||||||
|
@ -130,6 +134,25 @@ struct nfc_driver_list {
|
||||||
|
|
||||||
const struct nfc_driver_list *nfc_drivers = NULL;
|
const struct nfc_driver_list *nfc_drivers = NULL;
|
||||||
|
|
||||||
|
// descritions for debugging
|
||||||
|
const char * nfc_property_name[] = {
|
||||||
|
"NP_TIMEOUT_COMMAND",
|
||||||
|
"NP_TIMEOUT_ATR",
|
||||||
|
"NP_TIMEOUT_COM",
|
||||||
|
"NP_HANDLE_CRC",
|
||||||
|
"NP_HANDLE_PARITY",
|
||||||
|
"NP_ACTIVATE_FIELD",
|
||||||
|
"NP_ACTIVATE_CRYPTO1",
|
||||||
|
"NP_INFINITE_SELECT",
|
||||||
|
"NP_ACCEPT_INVALID_FRAMES",
|
||||||
|
"NP_ACCEPT_MULTIPLE_FRAMES",
|
||||||
|
"NP_AUTO_ISO14443_4",
|
||||||
|
"NP_EASY_FRAMING",
|
||||||
|
"NP_FORCE_ISO14443_A",
|
||||||
|
"NP_FORCE_ISO14443_B",
|
||||||
|
"NP_FORCE_SPEED_106"
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nfc_drivers_init(void)
|
nfc_drivers_init(void)
|
||||||
{
|
{
|
||||||
|
@ -157,6 +180,9 @@ nfc_drivers_init(void)
|
||||||
#if defined (DRIVER_ARYGON_ENABLED)
|
#if defined (DRIVER_ARYGON_ENABLED)
|
||||||
nfc_register_driver(&arygon_driver);
|
nfc_register_driver(&arygon_driver);
|
||||||
#endif /* DRIVER_ARYGON_ENABLED */
|
#endif /* DRIVER_ARYGON_ENABLED */
|
||||||
|
#if defined (DRIVER_PN71XX_ENABLED)
|
||||||
|
nfc_register_driver(&pn71xx_driver);
|
||||||
|
#endif /* DRIVER_PN71XX_ENABLED */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -409,6 +435,7 @@ nfc_list_devices(nfc_context *context, nfc_connstring connstrings[], const size_
|
||||||
int
|
int
|
||||||
nfc_device_set_property_int(nfc_device *pnd, const nfc_property property, const int value)
|
nfc_device_set_property_int(nfc_device *pnd, const nfc_property property, const int value)
|
||||||
{
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "set_property_int %s %s", nfc_property_name[property], value ? "True" : "False");
|
||||||
HAL(device_set_property_int, pnd, property, value);
|
HAL(device_set_property_int, pnd, property, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,6 +455,7 @@ nfc_device_set_property_int(nfc_device *pnd, const nfc_property property, const
|
||||||
int
|
int
|
||||||
nfc_device_set_property_bool(nfc_device *pnd, const nfc_property property, const bool bEnable)
|
nfc_device_set_property_bool(nfc_device *pnd, const nfc_property property, const bool bEnable)
|
||||||
{
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "set_property_bool %s %s", nfc_property_name[property], bEnable ? "True" : "False");
|
||||||
HAL(device_set_property_bool, pnd, property, bEnable);
|
HAL(device_set_property_bool, pnd, property, bEnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -503,7 +503,7 @@ snprint_nfc_barcode_info(char *dst, size_t size, const nfc_barcode_info *pnti, b
|
||||||
{
|
{
|
||||||
(void) verbose;
|
(void) verbose;
|
||||||
int off = 0;
|
int off = 0;
|
||||||
off += snprintf(dst + off, size - off, " Size (bits): %lu\n", pnti->szDataLen * 8);
|
off += snprintf(dst + off, size - off, " Size (bits): %lu\n", (unsigned long)(pnti->szDataLen * 8));
|
||||||
off += snprintf(dst + off, size - off, " Content: ");
|
off += snprintf(dst + off, size - off, " Content: ");
|
||||||
for (uint8_t i = 0; i < pnti->szDataLen; i++) {
|
for (uint8_t i = 0; i < pnti->szDataLen; i++) {
|
||||||
off += snprintf(dst + off, size - off, "%02X", pnti->abtData[i]);
|
off += snprintf(dst + off, size - off, "%02X", pnti->abtData[i]);
|
||||||
|
|
|
@ -4,7 +4,7 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS],
|
||||||
[
|
[
|
||||||
AC_MSG_CHECKING(which drivers to build)
|
AC_MSG_CHECKING(which drivers to build)
|
||||||
AC_ARG_WITH(drivers,
|
AC_ARG_WITH(drivers,
|
||||||
AS_HELP_STRING([--with-drivers=DRIVERS], [Use a custom driver set, where DRIVERS is a coma-separated list of drivers to build support for. Available drivers are: 'acr122_pcsc', 'acr122_usb', 'acr122s', 'arygon', 'pn532_i2c', 'pn532_spi', 'pn532_uart' and 'pn53x_usb'. Default drivers set is 'acr122_usb,acr122s,arygon,pn532_i2c,pn532_spi,pn532_uart,pn53x_usb'. The special driver set 'all' compile all available drivers.]),
|
AS_HELP_STRING([--with-drivers=DRIVERS], [Use a custom driver set, where DRIVERS is a coma-separated list of drivers to build support for. Available drivers are: 'acr122_pcsc', 'acr122_usb', 'acr122s', 'arygon', 'pn532_i2c', 'pn532_spi', 'pn532_uart', 'pn53x_usb' and 'pn71xx'. Default drivers set is 'acr122_usb,acr122s,arygon,pn532_i2c,pn532_spi,pn532_uart,pn53x_usb'. The special driver set 'all' compile all available drivers.]),
|
||||||
[ case "${withval}" in
|
[ case "${withval}" in
|
||||||
yes | no)
|
yes | no)
|
||||||
dnl ignore calls without any arguments
|
dnl ignore calls without any arguments
|
||||||
|
@ -36,7 +36,7 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS],
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
all)
|
all)
|
||||||
DRIVER_BUILD_LIST="acr122_pcsc acr122_usb acr122s arygon pn53x_usb pn532_uart"
|
DRIVER_BUILD_LIST="acr122_pcsc acr122_usb acr122s arygon pn53x_usb pn532_uart pn71xx"
|
||||||
if test x"$spi_available" = x"yes"
|
if test x"$spi_available" = x"yes"
|
||||||
then
|
then
|
||||||
DRIVER_BUILD_LIST="$DRIVER_BUILD_LIST pn532_spi"
|
DRIVER_BUILD_LIST="$DRIVER_BUILD_LIST pn532_spi"
|
||||||
|
@ -58,6 +58,7 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS],
|
||||||
driver_pn532_uart_enabled="no"
|
driver_pn532_uart_enabled="no"
|
||||||
driver_pn532_spi_enabled="no"
|
driver_pn532_spi_enabled="no"
|
||||||
driver_pn532_i2c_enabled="no"
|
driver_pn532_i2c_enabled="no"
|
||||||
|
driver_pn71xx_enabled="no"
|
||||||
|
|
||||||
for driver in ${DRIVER_BUILD_LIST}
|
for driver in ${DRIVER_BUILD_LIST}
|
||||||
do
|
do
|
||||||
|
@ -102,6 +103,10 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS],
|
||||||
driver_pn532_i2c_enabled="yes"
|
driver_pn532_i2c_enabled="yes"
|
||||||
DRIVERS_CFLAGS="$DRIVERS_CFLAGS -DDRIVER_PN532_I2C_ENABLED"
|
DRIVERS_CFLAGS="$DRIVERS_CFLAGS -DDRIVER_PN532_I2C_ENABLED"
|
||||||
;;
|
;;
|
||||||
|
pn71xx)
|
||||||
|
driver_pn71xx_enabled="yes"
|
||||||
|
DRIVERS_CFLAGS="$DRIVERS_CFLAGS -DDRIVER_PN71XX_ENABLED"
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
AC_MSG_ERROR([Unknow driver: $driver])
|
AC_MSG_ERROR([Unknow driver: $driver])
|
||||||
;;
|
;;
|
||||||
|
@ -116,6 +121,7 @@ AC_DEFUN([LIBNFC_ARG_WITH_DRIVERS],
|
||||||
AM_CONDITIONAL(DRIVER_PN532_UART_ENABLED, [test x"$driver_pn532_uart_enabled" = xyes])
|
AM_CONDITIONAL(DRIVER_PN532_UART_ENABLED, [test x"$driver_pn532_uart_enabled" = xyes])
|
||||||
AM_CONDITIONAL(DRIVER_PN532_SPI_ENABLED, [test x"$driver_pn532_spi_enabled" = xyes])
|
AM_CONDITIONAL(DRIVER_PN532_SPI_ENABLED, [test x"$driver_pn532_spi_enabled" = xyes])
|
||||||
AM_CONDITIONAL(DRIVER_PN532_I2C_ENABLED, [test x"$driver_pn532_i2c_enabled" = xyes])
|
AM_CONDITIONAL(DRIVER_PN532_I2C_ENABLED, [test x"$driver_pn532_i2c_enabled" = xyes])
|
||||||
|
AM_CONDITIONAL(DRIVER_PN71XX_ENABLED, [test x"$driver_pn71xx_enabled" = xyes])
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN([LIBNFC_DRIVERS_SUMMARY],[
|
AC_DEFUN([LIBNFC_DRIVERS_SUMMARY],[
|
||||||
|
@ -129,4 +135,5 @@ echo " pn53x_usb........ $driver_pn53x_usb_enabled"
|
||||||
echo " pn532_uart....... $driver_pn532_uart_enabled"
|
echo " pn532_uart....... $driver_pn532_uart_enabled"
|
||||||
echo " pn532_spi....... $driver_pn532_spi_enabled"
|
echo " pn532_spi....... $driver_pn532_spi_enabled"
|
||||||
echo " pn532_i2c........ $driver_pn532_i2c_enabled"
|
echo " pn532_i2c........ $driver_pn532_i2c_enabled"
|
||||||
|
echo " pn71xx........... $driver_pn71xx_enabled"
|
||||||
])
|
])
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
* See AUTHORS file for a more comprehensive list of contributors.
|
* See AUTHORS file for a more comprehensive list of contributors.
|
||||||
* Additional contributors of this file:
|
* Additional contributors of this file:
|
||||||
* Copyright (C) 2011-2013 Adam Laurie
|
* Copyright (C) 2011-2013 Adam Laurie
|
||||||
|
* Copyright (C) 2018-2019 Danielle Bruneo
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -70,7 +71,9 @@ static bool bForceKeyFile;
|
||||||
static bool bTolerateFailures;
|
static bool bTolerateFailures;
|
||||||
static bool bFormatCard;
|
static bool bFormatCard;
|
||||||
static bool magic2 = false;
|
static bool magic2 = false;
|
||||||
|
static bool magic3 = false;
|
||||||
static bool unlocked = false;
|
static bool unlocked = false;
|
||||||
|
static bool bForceSizeMismatch;
|
||||||
static uint8_t uiBlocks;
|
static uint8_t uiBlocks;
|
||||||
static uint8_t keys[] = {
|
static uint8_t keys[] = {
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
@ -208,10 +211,18 @@ authenticate(uint32_t uiBlock)
|
||||||
// Try to authenticate for the current sector
|
// Try to authenticate for the current sector
|
||||||
if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp))
|
if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp))
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
|
} else if (magic3) {
|
||||||
|
//If it's a One Time Write card, we're gonna authenticate with the default keys
|
||||||
|
memcpy(mp.mpa.abtKey, default_key, sizeof(default_key));
|
||||||
|
|
||||||
|
|
||||||
|
// Try to authenticate for the current sector
|
||||||
|
if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// If formatting or not using key file, try to guess the right key
|
// If formatting or not using key file, try to guess the right key
|
||||||
if (bFormatCard || !bUseKeyFile) {
|
} else if (bFormatCard || !bUseKeyFile) {
|
||||||
for (size_t key_index = 0; key_index < num_keys; key_index++) {
|
for (size_t key_index = 0; key_index < num_keys; key_index++) {
|
||||||
memcpy(mp.mpa.abtKey, keys + (key_index * 6), 6);
|
memcpy(mp.mpa.abtKey, keys + (key_index * 6), 6);
|
||||||
if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) {
|
if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) {
|
||||||
|
@ -352,10 +363,17 @@ read_card(int read_unlocked)
|
||||||
if (read_unlocked) {
|
if (read_unlocked) {
|
||||||
memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, sizeof(mtDump.amb[iBlock].mbd.abtData));
|
memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, sizeof(mtDump.amb[iBlock].mbd.abtData));
|
||||||
} else {
|
} else {
|
||||||
// Copy the keys over from our key dump and store the retrieved access bits
|
//If we're using a One Time Write ('Magic 3') Badge - we'll use default keys + ACL
|
||||||
memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, sizeof(mtDump.amb[iBlock].mbt.abtKeyA));
|
if (magic3) {
|
||||||
memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits));
|
memcpy(mtDump.amb[iBlock].mbt.abtKeyA, default_key, sizeof(default_key));
|
||||||
memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, sizeof(mtDump.amb[iBlock].mbt.abtKeyB));
|
memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits));
|
||||||
|
memcpy(mtDump.amb[iBlock].mbt.abtKeyB, default_key, sizeof(default_key));
|
||||||
|
} 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, sizeof(mtDump.amb[iBlock].mbt.abtKeyA));
|
||||||
|
memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits));
|
||||||
|
memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, sizeof(mtDump.amb[iBlock].mbt.abtKeyB));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("!\nfailed to read trailer block 0x%02x\n", iBlock);
|
printf("!\nfailed to read trailer block 0x%02x\n", iBlock);
|
||||||
|
@ -392,6 +410,7 @@ write_card(int write_block_zero)
|
||||||
bool bFailure = false;
|
bool bFailure = false;
|
||||||
uint32_t uiWriteBlocks = 0;
|
uint32_t uiWriteBlocks = 0;
|
||||||
|
|
||||||
|
//Determine if we have to unlock the card
|
||||||
if (write_block_zero) {
|
if (write_block_zero) {
|
||||||
//If the user is attempting an unlocked write, but has a direct-write type magic card, they don't
|
//If the user is attempting an unlocked write, but has a direct-write type magic card, they don't
|
||||||
//need to use the W mode. We'll trigger a warning and let them proceed.
|
//need to use the W mode. We'll trigger a warning and let them proceed.
|
||||||
|
@ -407,8 +426,8 @@ write_card(int write_block_zero)
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Writing %d blocks |", uiBlocks + 1);
|
printf("Writing %d blocks |", uiBlocks + 1);
|
||||||
// Write the card from begin to end;
|
// Completely write the card, end to start, but skipping block 0
|
||||||
for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) {
|
for (uiBlock = 4; uiBlock <= uiBlocks; uiBlock++) {
|
||||||
// Authenticate everytime we reach the first sector of a new block
|
// Authenticate everytime we reach the first sector of a new block
|
||||||
if (is_first_block(uiBlock)) {
|
if (is_first_block(uiBlock)) {
|
||||||
if (bFailure) {
|
if (bFailure) {
|
||||||
|
@ -423,44 +442,116 @@ write_card(int write_block_zero)
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
// Try to authenticate for the current sector
|
// Try to authenticate for the current sector
|
||||||
if (!write_block_zero && !authenticate(uiBlock) && !bTolerateFailures) {
|
// If we are are writing to a chinese magic card, we've already unlocked
|
||||||
printf("!\nError: authentication failed for block %02x\n", uiBlock);
|
// If we're writing to a One Time Write card, we need to authenticate
|
||||||
return false;
|
// If we're writing something else, we'll need to authenticate
|
||||||
|
if ((write_block_zero && magic3) || !write_block_zero) {
|
||||||
|
if (!authenticate(uiBlock) && !bTolerateFailures) {
|
||||||
|
printf("!\nError: authentication failed for block %02x\n", uiBlock);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_trailer_block(uiBlock)) {
|
||||||
|
if (bFormatCard) {
|
||||||
|
// Copy the default key and reset the access bits
|
||||||
|
memcpy(mp.mpt.abtKeyA, default_key, sizeof(mp.mpt.abtKeyA));
|
||||||
|
memcpy(mp.mpt.abtAccessBits, default_acl, sizeof(mp.mpt.abtAccessBits));
|
||||||
|
memcpy(mp.mpt.abtKeyB, default_key, sizeof(mp.mpt.abtKeyB));
|
||||||
|
} else {
|
||||||
|
// Copy the keys over from our key dump and store the retrieved access bits
|
||||||
|
memcpy(mp.mpt.abtKeyA, mtDump.amb[uiBlock].mbt.abtKeyA, sizeof(mp.mpt.abtKeyA));
|
||||||
|
memcpy(mp.mpt.abtAccessBits, mtDump.amb[uiBlock].mbt.abtAccessBits, sizeof(mp.mpt.abtAccessBits));
|
||||||
|
memcpy(mp.mpt.abtKeyB, mtDump.amb[uiBlock].mbt.abtKeyB, sizeof(mp.mpt.abtKeyB));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 && !magic2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Make sure a earlier write did not fail
|
||||||
|
if (!bFailure) {
|
||||||
|
// Try to write the data block
|
||||||
|
if (bFormatCard && uiBlock)
|
||||||
|
|
||||||
|
memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData));
|
||||||
|
else
|
||||||
|
memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData));
|
||||||
|
// 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 && !magic2) {
|
||||||
|
printf("!\nError: incorrect BCC in MFD file!\n");
|
||||||
|
printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) {
|
||||||
|
bFailure = true;
|
||||||
|
printf("Failure to write to data block %i\n", uiBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
printf("Failure during write process.\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Show if the write went well for each block
|
||||||
|
print_success_or_failure(bFailure, &uiWriteBlocks);
|
||||||
|
if ((! bTolerateFailures) && bFailure)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_trailer_block(uiBlock)) {
|
//Write Block 0 if necessary
|
||||||
if (bFormatCard) {
|
if (write_block_zero || magic2 || magic3) {
|
||||||
// Copy the default key and reset the access bits
|
for (uiBlock = 0; uiBlock < 4; uiBlock++) {
|
||||||
memcpy(mp.mpt.abtKeyA, default_key, sizeof(mp.mpt.abtKeyA));
|
|
||||||
memcpy(mp.mpt.abtAccessBits, default_acl, sizeof(mp.mpt.abtAccessBits));
|
// The first block 0x00 is read only, skip this
|
||||||
memcpy(mp.mpt.abtKeyB, default_key, sizeof(mp.mpt.abtKeyB));
|
if (uiBlock == 0) {
|
||||||
} else {
|
//If the card is not magic, we're gonna skip over
|
||||||
// Copy the keys over from our key dump and store the retrieved access bits
|
if (write_block_zero || magic2 || magic3) {
|
||||||
memcpy(mp.mpt.abtKeyA, mtDump.amb[uiBlock].mbt.abtKeyA, sizeof(mp.mpt.abtKeyA));
|
//NOP
|
||||||
memcpy(mp.mpt.abtAccessBits, mtDump.amb[uiBlock].mbt.abtAccessBits, sizeof(mp.mpt.abtAccessBits));
|
} else {
|
||||||
memcpy(mp.mpt.abtKeyB, mtDump.amb[uiBlock].mbt.abtKeyB, sizeof(mp.mpt.abtKeyB));
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_first_block(uiBlock)) {
|
||||||
|
if (bFailure) {
|
||||||
|
// When a failure occured we need to redo the anti-collision
|
||||||
|
if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
|
||||||
|
printf("!\nError: tag was removed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bFailure = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
// Try to authenticate for the current sector
|
||||||
|
// If we are are writing to a chinese magic card, we've already unlocked
|
||||||
|
// If we're writing to a One Time Write, we need to authenticate
|
||||||
|
// If we're writing something else, we'll need to authenticate
|
||||||
|
if ((write_block_zero && magic3) || !write_block_zero) {
|
||||||
|
if (!authenticate(uiBlock) && !bTolerateFailures) {
|
||||||
|
printf("!\nError: authentication failed for block %02x\n", uiBlock);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to write the trailer
|
// Make sure a earlier write did not fail
|
||||||
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 && !magic2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
|
|
||||||
// Make sure a earlier write did not fail
|
|
||||||
if (!bFailure) {
|
if (!bFailure) {
|
||||||
// Try to write the data block
|
// Try to write the data block
|
||||||
if (bFormatCard && uiBlock)
|
if (bFormatCard && uiBlock)
|
||||||
memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData));
|
memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData));
|
||||||
else
|
else
|
||||||
memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData));
|
memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData));
|
||||||
// do not write a block 0 with incorrect BCC - card will be made invalid!
|
// do not write a block 0 with incorrect BCC - card will be made invalid!
|
||||||
if (uiBlock == 0) {
|
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 && !magic2) {
|
if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) {
|
||||||
printf("!\nError: incorrect BCC in MFD file!\n");
|
printf("!\nError: incorrect BCC in MFD file!\n");
|
||||||
|
@ -468,15 +559,24 @@ write_card(int write_block_zero)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp))
|
if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) {
|
||||||
bFailure = true;
|
bFailure = true;
|
||||||
|
printf("Failure to write to data block %i\n", uiBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
printf("Failure during write process.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show if the write went well for each block
|
||||||
|
print_success_or_failure(bFailure, &uiWriteBlocks);
|
||||||
|
if ((! bTolerateFailures) && bFailure)
|
||||||
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
// Show if the write went well for each block
|
|
||||||
print_success_or_failure(bFailure, &uiWriteBlocks);
|
|
||||||
if ((!bTolerateFailures) && bFailure)
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("|\n");
|
printf("|\n");
|
||||||
printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
|
printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
@ -505,6 +605,7 @@ print_usage(const char *pcProgramName)
|
||||||
printf(" <dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\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(" <keys.mfd> - MiFare Dump (MFD) that contain the keys (optional)\n");
|
||||||
printf(" f - Force using the keyfile even if UID does not match (optional)\n");
|
printf(" f - Force using the keyfile even if UID does not match (optional)\n");
|
||||||
|
|
||||||
printf("Examples: \n\n");
|
printf("Examples: \n\n");
|
||||||
printf(" Read card to file, using key A:\n\n");
|
printf(" Read card to file, using key A:\n\n");
|
||||||
printf(" %s r a u mycard.mfd\n\n", pcProgramName);
|
printf(" %s r a u mycard.mfd\n\n", pcProgramName);
|
||||||
|
@ -519,6 +620,54 @@ print_usage(const char *pcProgramName)
|
||||||
printf(" %s r a U01ab23cd mycard.mfd\n\n", pcProgramName);
|
printf(" %s r a U01ab23cd mycard.mfd\n\n", pcProgramName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool is_directwrite(){
|
||||||
|
printf("Checking if Badge is DirectWrite...\n");
|
||||||
|
|
||||||
|
// Set default keys
|
||||||
|
memcpy(mtDump.amb[0].mbt.abtKeyA, default_key, sizeof(default_key));
|
||||||
|
memcpy(mtDump.amb[0].mbt.abtAccessBits, default_acl, sizeof(mp.mpt.abtAccessBits));
|
||||||
|
memcpy(mtDump.amb[0].mbt.abtKeyB, default_key, sizeof(default_key));
|
||||||
|
|
||||||
|
// Temporarly override bUseKeyFile
|
||||||
|
bool orig_bUseKeyFile=bUseKeyFile;
|
||||||
|
bUseKeyFile=false;
|
||||||
|
// Try to authenticate for the current sector
|
||||||
|
if (!authenticate(0)) {
|
||||||
|
printf("!\nError: authentication failed for block 0x%02x\n", 0);
|
||||||
|
bUseKeyFile=orig_bUseKeyFile;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// restore bUseKeyFile
|
||||||
|
bUseKeyFile=orig_bUseKeyFile;
|
||||||
|
|
||||||
|
// Try to read block 0
|
||||||
|
uint8_t original_b0[16];
|
||||||
|
if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) {
|
||||||
|
memcpy(original_b0, mp.mpd.abtData, sizeof(mp.mpd.abtData));
|
||||||
|
printf(" Original Block 0: ");
|
||||||
|
for(int i=0;i<16;i++){
|
||||||
|
printf("%02x", original_b0[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
printf(" Original UID: %02x%02x%02x%02x\n",
|
||||||
|
original_b0[0], original_b0[1], original_b0[2], original_b0[3]);
|
||||||
|
} else {
|
||||||
|
printf("!\nError: unable to read block 0x%02x\n", 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" Attempt to write Block 0 ...\n");
|
||||||
|
memcpy(mp.mpd.abtData, original_b0, sizeof(original_b0));
|
||||||
|
if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, 0, &mp)) {
|
||||||
|
printf("Failure to write to data block %i\n", 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
printf(" Block 0 written successfully\n");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, const char *argv[])
|
main(int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
|
@ -683,6 +832,7 @@ main(int argc, const char *argv[])
|
||||||
// Testing RATS
|
// Testing RATS
|
||||||
int res;
|
int res;
|
||||||
if ((res = get_rats()) > 0) {
|
if ((res = get_rats()) > 0) {
|
||||||
|
printf("RATS support: yes\n");
|
||||||
if ((res >= 10) && (abtRx[5] == 0xc1) && (abtRx[6] == 0x05)
|
if ((res >= 10) && (abtRx[5] == 0xc1) && (abtRx[6] == 0x05)
|
||||||
&& (abtRx[7] == 0x2f) && (abtRx[8] == 0x2f)
|
&& (abtRx[7] == 0x2f) && (abtRx[8] == 0x2f)
|
||||||
&& ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x00)) {
|
&& ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x00)) {
|
||||||
|
@ -694,8 +844,29 @@ main(int argc, const char *argv[])
|
||||||
&& (abtRx[7] == 0x19) && (abtRx[8] == 0x10)) {
|
&& (abtRx[7] == 0x19) && (abtRx[8] == 0x10)) {
|
||||||
magic2 = true;
|
magic2 = true;
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
printf("RATS support: no\n");
|
||||||
|
printf("Guessing size: seems to be a %lu-byte card\n", (unsigned long) ((uiBlocks + 1) * sizeof(mifare_classic_block)));
|
||||||
|
|
||||||
|
//If size is 4k check for direct-write card
|
||||||
|
if (uiBlocks == 0xff) {
|
||||||
|
if (is_directwrite()){
|
||||||
|
printf("Card is DirectWrite\n");
|
||||||
|
magic3=true;
|
||||||
|
unlock=0;
|
||||||
|
} else {
|
||||||
|
printf("Card is not DirectWrite\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
printf("Guessing size: seems to be a %lu-byte card\n", (uiBlocks + 1) * sizeof(mifare_classic_block));
|
|
||||||
|
//Check to see if we have a One Time Write badge (magic3)
|
||||||
|
if (pbtUID[0] == 0xaa && pbtUID[1] == 0x55 &&
|
||||||
|
pbtUID[2] == 0xc3 && pbtUID[3] == 0x96) {
|
||||||
|
printf("Card appears to be a One Time Write Card..\n");
|
||||||
|
magic3 = true;
|
||||||
|
unlock = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (bUseKeyFile) {
|
if (bUseKeyFile) {
|
||||||
FILE *pfKeys = fopen(argv[5], "rb");
|
FILE *pfKeys = fopen(argv[5], "rb");
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
* See AUTHORS file for a more comprehensive list of contributors.
|
* See AUTHORS file for a more comprehensive list of contributors.
|
||||||
* Additional contributors of this file:
|
* Additional contributors of this file:
|
||||||
* Copyright (C) 2013-2018 Adam Laurie
|
* Copyright (C) 2013-2018 Adam Laurie
|
||||||
|
* Copyright (C) 2018-2019 Daniele Bruneo
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -292,48 +293,44 @@ unlock_card(void)
|
||||||
|
|
||||||
static bool check_magic(void)
|
static bool check_magic(void)
|
||||||
{
|
{
|
||||||
bool bFailure = false;
|
bool directWrite = true;
|
||||||
int uid_data;
|
// Try to read pages 0, 1, 2
|
||||||
|
uint8_t original_b0[12];
|
||||||
for (uint32_t page = 0; page <= 1; page++) {
|
printf("Checking if UL badge is DirectWrite...\n");
|
||||||
// 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) <= 0) {
|
|
||||||
ERR("tag was removed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bFailure = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uid_data = 0x00000000;
|
|
||||||
|
|
||||||
memcpy(mp.mpd.abtData, &uid_data, sizeof uid_data);
|
|
||||||
memset(mp.mpd.abtData + 4, 0, 12);
|
|
||||||
|
|
||||||
//Force the write without checking for errors - otherwise the writes to the sector 0 seem to complain
|
|
||||||
nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check that the ID is now set to 0x000000000000
|
|
||||||
if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) {
|
if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) {
|
||||||
//printf("%u", mp.mpd.abtData);
|
memcpy(original_b0, mp.mpd.abtData, 12);
|
||||||
bool result = true;
|
printf(" Original Block 0 (Pages 0-2): ");
|
||||||
for (int i = 0; i <= 7; i++) {
|
for(int i=0;i<12;i++){
|
||||||
if (mp.mpd.abtData[i] != 0x00) result = false;
|
printf("%02x", original_b0[i]);
|
||||||
}
|
}
|
||||||
|
printf("\n");
|
||||||
if (result) {
|
printf(" Original UID: %02x%02x%02x%02x%02x%02x%02x\n",
|
||||||
return true;
|
original_b0[0], original_b0[1], original_b0[2], original_b0[4], original_b0[5], original_b0[6], original_b0[7]);
|
||||||
}
|
} else {
|
||||||
|
printf("!\nError: unable to read block 0x%02x\n", 0);
|
||||||
|
directWrite = false;
|
||||||
}
|
}
|
||||||
|
printf(" Attempt to write Block 0 (pages 0-2) ...\n");
|
||||||
//Initially check if we can unlock via the MF method
|
for (uint32_t page = 0; page <= 2; page++) {
|
||||||
if (unlock_card()) {
|
printf(" Writing Page %i:", page);
|
||||||
|
memcpy(mp.mpd.abtData, original_b0 + page*4, 4);
|
||||||
|
for(int i=0;i<4;i++){
|
||||||
|
printf(" %02x", mp.mpd.abtData[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp)) {
|
||||||
|
printf(" Failure writing Page %i\n", page);
|
||||||
|
directWrite = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(directWrite){
|
||||||
|
printf(" Block 0 written successfully\n");
|
||||||
|
printf("Card is DirectWrite\n");
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
printf("Card is not DirectWrite\n");
|
||||||
|
return unlock_card();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -383,9 +380,9 @@ write_card(bool write_otp, bool write_lock, bool write_dyn_lock, bool write_uid)
|
||||||
write_uid = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
|
write_uid = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Writing %d pages |", uiBlocks);
|
|
||||||
/* We may need to skip 2 first pages. */
|
/* We may need to skip 2 first pages. */
|
||||||
if (!write_uid) {
|
if (!write_uid) {
|
||||||
|
printf("Writing %d pages |", uiBlocks);
|
||||||
printf("ss");
|
printf("ss");
|
||||||
uiSkippedPages = 2;
|
uiSkippedPages = 2;
|
||||||
} else {
|
} else {
|
||||||
|
@ -393,6 +390,7 @@ write_card(bool write_otp, bool write_lock, bool write_dyn_lock, bool write_uid)
|
||||||
printf("\nUnable to unlock card - are you sure the card is magic?\n");
|
printf("\nUnable to unlock card - are you sure the card is magic?\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
printf("Writing %d pages |", uiBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t page = uiSkippedPages; page < uiBlocks; page++) {
|
for (uint32_t page = uiSkippedPages; page < uiBlocks; page++) {
|
||||||
|
@ -527,7 +525,7 @@ main(int argc, const char *argv[])
|
||||||
bool bFilename = false;
|
bool bFilename = false;
|
||||||
FILE *pfDump;
|
FILE *pfDump;
|
||||||
|
|
||||||
if (argc < 3) {
|
if (argc == 0) {
|
||||||
print_usage(argv);
|
print_usage(argv);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -580,7 +578,7 @@ main(int argc, const char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (! bFilename) {
|
if (iAction != 3 && !bFilename) {
|
||||||
ERR("Please supply a Mifare Dump filename");
|
ERR("Please supply a Mifare Dump filename");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -650,7 +648,7 @@ main(int argc, const char *argv[])
|
||||||
if (get_ev1_version()) {
|
if (get_ev1_version()) {
|
||||||
if (!bPWD)
|
if (!bPWD)
|
||||||
printf("WARNING: Tag is EV1 or NTAG - PASSWORD may be required\n");
|
printf("WARNING: Tag is EV1 or NTAG - PASSWORD may be required\n");
|
||||||
if (abtRx[6] == 0x0b) {
|
if (abtRx[6] == 0x0b || abtRx[6] == 0x00) {
|
||||||
printf("EV1 type: MF0UL11 (48 bytes)\n");
|
printf("EV1 type: MF0UL11 (48 bytes)\n");
|
||||||
uiBlocks = 20; // total number of 4 byte 'pages'
|
uiBlocks = 20; // total number of 4 byte 'pages'
|
||||||
iDumpSize = uiBlocks * 4;
|
iDumpSize = uiBlocks * 4;
|
||||||
|
@ -714,7 +712,7 @@ main(int argc, const char *argv[])
|
||||||
|
|
||||||
size_t szDump;
|
size_t szDump;
|
||||||
if (((szDump = fread(&mtDump, 1, sizeof(mtDump), pfDump)) != iDumpSize && !bPart) || szDump <= 0) {
|
if (((szDump = fread(&mtDump, 1, sizeof(mtDump), pfDump)) != iDumpSize && !bPart) || szDump <= 0) {
|
||||||
ERR("Could not read from dump file or size mismatch: %s (read %lu, expected %lu)\n", argv[2], szDump, iDumpSize);
|
ERR("Could not read from dump file or size mismatch: %s (read %lu, expected %lu)\n", argv[2], (unsigned long)szDump, (unsigned long)iDumpSize);
|
||||||
fclose(pfDump);
|
fclose(pfDump);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue