From bbae6dcee58498e5805b29870e1ce1f12a4d704a Mon Sep 17 00:00:00 2001 From: Roel Verdult Date: Wed, 29 Apr 2009 12:47:41 +0000 Subject: [PATCH] moving win32 binaries --- README.TXT | 146 +---- anticol.c | 292 +++++----- bitutils.c | 68 ++- bitutils.h | 59 +- defines.h | 57 +- libnfc.c | 1285 ++++++++++++++++++++++++----------------- libnfc.h | 73 ++- list.c | 85 +-- mifaretag.h | 76 +-- relay.c | 206 ++++--- simulate.c | 219 +++---- types.h | 166 ++++-- win32/anticol.vcproj | 6 +- win32/libnfc.def | 41 +- win32/libnfc.sln | 21 +- win32/libnfc.vcproj | 42 +- win32/list.vcproj | 6 +- win32/relay.vcproj | 6 +- win32/simulate.vcproj | 6 +- win32bin/anticol.exe | Bin 7168 -> 0 bytes win32bin/libnfc.dll | Bin 15360 -> 0 bytes win32bin/libnfc.lib | Bin 8896 -> 0 bytes win32bin/list.exe | Bin 6656 -> 0 bytes win32bin/mfread.exe | Bin 8192 -> 0 bytes win32bin/mfwrite.exe | Bin 8192 -> 0 bytes win32bin/relay.exe | Bin 7680 -> 0 bytes win32bin/simulate.exe | Bin 7168 -> 0 bytes 27 files changed, 1550 insertions(+), 1310 deletions(-) delete mode 100644 win32bin/anticol.exe delete mode 100644 win32bin/libnfc.dll delete mode 100644 win32bin/libnfc.lib delete mode 100644 win32bin/list.exe delete mode 100644 win32bin/mfread.exe delete mode 100644 win32bin/mfwrite.exe delete mode 100644 win32bin/relay.exe delete mode 100644 win32bin/simulate.exe diff --git a/README.TXT b/README.TXT index 22c3e77..01ce245 100644 --- a/README.TXT +++ b/README.TXT @@ -2,145 +2,23 @@ Public platform independent Near Field Communication (NFC) library Copyright (C) 2009, Roel Verdult -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. +------------------------------------------------------------------------ +Welcome to the developers community of libnfc. -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. +Since it is hard to keep all information up to date +we decided to only maintain the online documentation. +Please visit the official website for more info: +http://www.libnfc.org -You should have received a copy of the GNU General Public License -along with this program. If not, see . +If you have questions, remarks, bug-reports, we encourage you to +post this in the developers community: +http://www.libnfc.org/community ------------------------------------------------------------------------ -Welcome to the community of libnfc (website: http://www.libnfc.org). +Proprietary Notes: -libnfc version 1.0.0 - -Index: -1. Introduction -2. Hardware -3. Compilation -4. Examples -5. Todo -6. Contact - ------------------------------------------------------------------------- -1. Introduction - -Since the RFID market is spoiled by proprietary hard and software -we want to contribute constructively by distributing a free library -which can be used in RFID/NFC applications. - ------------------------------------------------------------------------- -2. Hardware - -To communicate with NFC targets/tags you need a USB device which is -called a "RFID Reader". The cheapest hardware around that can carries -a fully NFC complied chip is the ACR122 from the company ACS, Advanced -Card Systems Limited (website: http://www.acs.com.hk/acr122.php). -This reader uses the PN532 chipset from NXP Semiconductors. The reader -costs around the €60 and is available in different webshops all over -the world. The NFC reader used in the "tikitag" project is exactly the -same reader as the ACR122 but with a different logo. This reader is -available for only €35,- (website: http://www.tikitag.com). We would -recommend to use one of these readers, since we tested both of them. - -Other NFC readers, like the SCL3710 from SCM Microsystems (website: -http://www.scmmicro.com/scl3710/) are not supported yet. They use the -same chipset, so the instruction set is completely the same. This means -that with little effort these readers could be added to be part of the -NFC library. We would be very pleased if someone is willing to add this -support to libnfc. - ------------------------------------------------------------------------- -3. Compilation - -If you use linux, please make sure you have libpcsc-lite installed. -For Ubuntu this means you have to install the following packages: -$sudo apt-get install pcscd -$sudo apt-get install libpcsclite-dev -When these are installed, just run "make" and you are ready to go. - -MacOSX users have to edit the "Makefile" file in the main directory. -Uncomment the following lines: -#LIB_TYPE=... -#LIB_FLAGS=... -#PCSC_HEADERS=... -#PCSC_LIB=... -Run "make" and you it should work like a charm. - -Windows users can use the binairy files located in the "win32bin" -directory. Or they can open the VS2005 solution which can be found -in the "win32" directory. Compilation should work "out of the box". - ------------------------------------------------------------------------- -4. Examples - -There are 6 example tools coming with this library. They can be used -as a reference during development of your software. All tools try to -demonstrate a different feature. Below there is short description of -the tools and their purpose. - -anticol - Anti-collision demonstration tool for ISO14443A tags using - self constructed REQA/WUPA and SELECT frames. - -list - List passive tags tool for ISO14443A tags using the commands - available in the instruction set of the hardware chip. - -simulate - With this example you can turn your reader into a NFC target. - For testing purposes it simulates a ISO14443A tag with a UID - that consists of 0xDEADBEAF. The frames are delayed because - of the USB communication, so not all readers will recognize - the tag. The "Omnikey 5121" though has no problems with this - small delay. - -relay - This tool allows the user to use 2 readers. One will similate - a ISO14443A tag, while the 2nd reader will stay a reader. - The original tag can be placed on the 2nd reader and the - simulated tag can be placed on top of the original reader. - All communication is relayed now and showed on the screen. - NOTE: relaying frames is time-consuming, not all readers - allow slow responds from the (simulated) tag. Though, one of - the most used RFID readers, the "Omnikey 5121" has no problem - and can perfectly be used for demonstrating this features. - -mfread - With this tool a complete MIFARE card can be readout and stored - in a MIFARE dump file (*.mfd). - -mfwrite - With this tool a complete MIFARE card can be restored from a - a MIFARE dump file (*.mfd) back to the tag. - -A MIFARE dump file (*.mfd) is a plain 4KB image of a mifare tag. This -image should contain the data, keys and access bits on their usual position. -A Dump file is always 4KB, even when a 1KB tag is dumped. From the first -block, the manufacturer data, can be determined if you are dealing with -a 1KB or a 4KB tag. This is stored in the ATQA part of block0 (byte 6/7). -More info can be found in the MIFARE functional specification from NXP. -(Website: http://www.nxp.com/products/identification/mifare/classic) - ------------------------------------------------------------------------- -5. Todo - -Support more communication protocols. Sony Felica, ISO14443B and Innovision -Jewel Topaz tags are supported by the chipset, but they are not used by -this library. It would be very useful if we could add support for these -tags in this library. - ------------------------------------------------------------------------- -6. Contact - -Please visit the website (http://www.libnfc.org) and place your questions -in the community forum there. We are sure a member of the community will -help you out. - ------------------------------------------------------------------------- -Proprietary notes: - -Note: FeliCa is s registered trademark of Sony Corporation. MIFARE is a +FeliCa is s registered trademark of Sony Corporation. MIFARE is a trademark of NXP Semiconductors. Jewel Topaz is a trademark of Innovision Research & Technology. All other trademarks are the property of their respective owners. + diff --git a/anticol.c b/anticol.c index 876d0a9..e4e4e34 100644 --- a/anticol.c +++ b/anticol.c @@ -1,142 +1,150 @@ -/* - -Public platform independent Near Field Communication (NFC) library -Copyright (C) 2009, Roel Verdult - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU 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 General Public License -along with this program. If not, see . - -*/ - -#include -#include -#include -#include "libnfc.h" - -static byte abtRecv[MAX_FRAME_LEN]; -static ui32 uiRecvLen; -static byte abtUid[10]; -static ui32 uiUidLen = 4; -static dev_id di; - -// ISO14443A Anti-Collision Commands -byte abtWupa [1] = { 0x52 }; -byte abtSelectAll [2] = { 0x93,0x20 }; -byte abtSelectTag [9] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; -byte abtRats [4] = { 0xe0,0x50,0xbc,0xa5 }; -byte abtHalt [4] = { 0x50,0x00,0x57,0xcd }; - -bool transmit_7bits(const byte btTx) -{ - bool bResult; - printf("R: %02x\n",btTx); - uiRecvLen = MAX_FRAME_LEN; - bResult = nfc_reader_transceive_7bits(di,btTx,abtRecv,&uiRecvLen); - if (bResult) - { - printf("T: "); - print_hex(abtRecv,uiRecvLen); - } - return bResult; -} - -bool transmit_bytes(const byte* pbtTx, const ui32 uiTxLen) -{ - bool bResult; - printf("R: "); - print_hex(pbtTx,uiTxLen); - uiRecvLen = MAX_FRAME_LEN; - bResult = nfc_reader_transceive_bytes(di,pbtTx,uiTxLen,abtRecv,&uiRecvLen); - if (bResult) - { - printf("T: "); - print_hex(abtRecv,uiRecvLen); - } - return bResult; -} - -int main(int argc, const char* argv[]) -{ - // Try to open the NFC reader - di = acr122_connect(0); - - if (di == INVALID_DEVICE_ID) - { - printf("Error connecting NFC reader\n"); - return 1; - } - nfc_reader_init(di); - - // Let the reader only try once to find a tag - nfc_configure_list_passive_infinite(di,false); - - // Drop the field so the tag will be reset - nfc_configure_field(di,false); - - // Configure the communication channel, we use our own CRC - nfc_configure_handle_crc(di,false); - nfc_configure_handle_parity(di,true); - - // Enable the field so the more power consuming tags will respond - nfc_configure_field(di,true); - - printf("\nConnected to NFC reader\n\n"); - - if (!transmit_7bits(*abtWupa)) - { - printf("Error: No tag available\n"); - return 1; - } - // Anti-collision - transmit_bytes(abtSelectAll,2); - - // Save the UID - memcpy(abtUid,abtRecv,4); - memcpy(abtSelectTag+2,abtRecv,5); - append_iso14443a_crc(abtSelectTag,7); - transmit_bytes(abtSelectTag,9); - - if (abtUid[0] == 0x88) - { - abtSelectAll[0] = 0x95; - abtSelectTag[0] = 0x95; - - // Anti-collision - transmit_bytes(abtSelectAll,2); - - // Save the UID - memcpy(abtUid+4,abtRecv,4); - memcpy(abtSelectTag+2,abtRecv,5); - append_iso14443a_crc(abtSelectTag,7); - transmit_bytes(abtSelectTag,9); - uiUidLen = 7; - } - - // Request ATS, this only applies to tags that support ISO 14443A-4 - if (abtRecv[0] & 0x20) - { - transmit_bytes(abtRats,4); - } - - // Done, halt the tag now - transmit_bytes(abtHalt,4); - - printf("\nFound tag with UID: "); - if (uiUidLen == 4) - { - printf("%08x\n",swap_endian32(abtUid)); - } else { - printf("%014llx\n",swap_endian64(abtUid)&0x00ffffffffffffffull); - } - return 0; -} +/* + +Public platform independent Near Field Communication (NFC) library +Copyright (C) 2009, Roel Verdult + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU 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 General Public License +along with this program. If not, see . + +*/ + +#include +#include +#include +#include "libnfc.h" + +#define SAK_FLAG_ATS_SUPPORTED 0x20 + +static byte abtRx[MAX_FRAME_LEN]; +static ui32 uiRxBits; +static ui32 uiRxLen; +static byte abtUid[10]; +static ui32 uiUidLen = 4; +static dev_info* pdi; + +// ISO14443A Anti-Collision Commands +byte abtReqa [1] = { 0x26 }; +byte abtSelectAll [2] = { 0x93,0x20 }; +byte abtSelectTag [9] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; +byte abtRats [4] = { 0xe0,0x50,0xbc,0xa5 }; +byte abtHalt [4] = { 0x50,0x00,0x57,0xcd }; + +bool transmit_bits(const byte* pbtTx, const ui32 uiTxBits) +{ + // Show transmitted command + printf("R: "); print_hex_bits(pbtTx,uiTxBits); + + // Transmit the bit frame command, we don't use the arbitrary parity feature + if (!nfc_reader_transceive_bits(pdi,pbtTx,uiTxBits,null,abtRx,&uiRxBits,null)) return false; + + // Show received answer + printf("T: "); print_hex_bits(abtRx,uiRxBits); + + // Succesful transfer + return true; +} + + +bool transmit_bytes(const byte* pbtTx, const ui32 uiTxLen) +{ + // Show transmitted command + printf("R: "); print_hex(pbtTx,uiTxLen); + + // Transmit the command bytes + if (!nfc_reader_transceive_bytes(pdi,pbtTx,uiTxLen,abtRx,&uiRxLen)) return false; + + // Show received answer + printf("T: "); print_hex(abtRx,uiRxLen); + + // Succesful transfer + return true; +} + +int main(int argc, const char* argv[]) +{ + // Try to open the NFC reader + pdi = nfc_connect(); + + if (!pdi) + { + printf("Error connecting NFC reader\n"); + return 1; + } + nfc_reader_init(pdi); + + // Drop the field for a while + nfc_configure(pdi,DCO_ACTIVATE_FIELD,false); + + // Configure the CRC and Parity settings + nfc_configure(pdi,DCO_HANDLE_CRC,false); + nfc_configure(pdi,DCO_HANDLE_PARITY,true); + + // Enable field so more power consuming cards can power themselves up + nfc_configure(pdi,DCO_ACTIVATE_FIELD,true); + + printf("\nConnected to NFC reader: %s\n\n",pdi->acName); + + // Send the 7 bits request command specified in ISO 14443A (0x26) + if (!transmit_bits(abtReqa,7)) + { + printf("Error: No tag available\n"); + nfc_disconnect(pdi); + return 1; + } + + // Anti-collision + transmit_bytes(abtSelectAll,2); + + // Save the UID + memcpy(abtUid,abtRx,4); + memcpy(abtSelectTag+2,abtRx,5); + append_iso14443a_crc(abtSelectTag,7); + transmit_bytes(abtSelectTag,9); + + // Test if we are dealing with a 4 bytes uid + if (abtUid[0]!= 0x88) + { + uiUidLen = 4; + } else { + // We have to do the anti-collision for cascade level 2 + abtSelectAll[0] = 0x95; + abtSelectTag[0] = 0x95; + + // Anti-collision + transmit_bytes(abtSelectAll,2); + + // Save the UID + memcpy(abtUid+4,abtRx,4); + memcpy(abtSelectTag+2,abtRx,5); + append_iso14443a_crc(abtSelectTag,7); + transmit_bytes(abtSelectTag,9); + uiUidLen = 7; + } + + // Request ATS, this only applies to tags that support ISO 14443A-4 + if (abtRx[0] & SAK_FLAG_ATS_SUPPORTED) transmit_bytes(abtRats,4); + + // Done, halt the tag now + transmit_bytes(abtHalt,4); + + printf("\nFound tag with UID: "); + if (uiUidLen == 4) + { + printf("%08x\n",swap_endian32(abtUid)); + } else { + printf("%014llx\n",swap_endian64(abtUid)&0x00ffffffffffffffull); + } + + nfc_disconnect(pdi); + return 0; +} diff --git a/bitutils.c b/bitutils.c index f7f9458..5fda4b1 100644 --- a/bitutils.c +++ b/bitutils.c @@ -1,23 +1,23 @@ -/* - -Public platform independent Near Field Communication (NFC) library -Copyright (C) 2009, Roel Verdult - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU 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 General Public License -along with this program. If not, see . - -*/ - +/* + +Public platform independent Near Field Communication (NFC) library +Copyright (C) 2009, Roel Verdult + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU 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 General Public License +along with this program. If not, see . + +*/ + #include #include "bitutils.h" @@ -116,7 +116,7 @@ ui32 swap_endian32(const void* pui32) ui64 swap_endian64(const void* pui64) { ui64 ui64N = *((ui64*)pui64); - return (((ui64N&0xFF)<<56)+((ui64N&0xFF00)<<40)+((ui64N&0xFF0000)<<24)+((ui64N&0xFF000000)<<8)+((ui64N&0xFF00000000)>>8)+((ui64N&0xFF0000000000)>>24)+((ui64N&0xFF000000000000)>>40)+((ui64N&0xFF00000000000000)>>56)); + return (((ui64N&0xFF)<<56)+((ui64N&0xFF00)<<40)+((ui64N&0xFF0000)<<24)+((ui64N&0xFF000000)<<8)+((ui64N&0xFF00000000ull)>>8)+((ui64N&0xFF0000000000ull)>>24)+((ui64N&0xFF000000000000ull)>>40)+((ui64N&0xFF00000000000000ull)>>56)); } void append_iso14443a_crc(byte* pbtData, ui32 uiLen) @@ -135,16 +135,33 @@ void append_iso14443a_crc(byte* pbtData, ui32 uiLen) *pbtData = (byte) ((wCrc >> 8) & 0xFF); } -void print_hex(const byte* pbtData, const ui32 uiLen) +void print_hex(const byte* pbtData, const ui32 uiBytes) { ui32 uiPos; - for (uiPos=0; uiPos < uiLen; uiPos++) + + for (uiPos=0; uiPos < uiBytes; uiPos++) { printf("%02x ",pbtData[uiPos]); } printf("\n"); } +void print_hex_bits(const byte* pbtData, const ui32 uiBits) +{ + ui32 uiPos; + ui32 uiBytes = uiBits/8; + + for (uiPos=0; uiPos < uiBytes; uiPos++) + { + printf("%02x ",pbtData[uiPos]); + } + + // Print the rest bits, these cannot have no parity bit + if (uiBits%8 != 0) printf("%02x",pbtData[uiBytes]); + + printf("\n"); +} + void print_hex_par(const byte* pbtData, const ui32 uiBits, const byte* pbtDataPar) { ui32 uiPos; @@ -162,10 +179,7 @@ void print_hex_par(const byte* pbtData, const ui32 uiBits, const byte* pbtDataPa } // Print the rest bits, these cannot have no parity bit - if (uiBits%8 != 0) - { - printf("%02x",pbtData[uiBytes]); - } + if (uiBits%8 != 0) printf("%02x",pbtData[uiBytes]); printf("\n"); } diff --git a/bitutils.h b/bitutils.h index e231678..312c968 100644 --- a/bitutils.h +++ b/bitutils.h @@ -1,46 +1,28 @@ -/* - -Public platform independent Near Field Communication (NFC) library -Copyright (C) 2009, Roel Verdult - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU 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 General Public License -along with this program. If not, see . - -*/ - +/* + +Public platform independent Near Field Communication (NFC) library +Copyright (C) 2009, Roel Verdult + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU 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 General Public License +along with this program. If not, see . + +*/ + #ifndef _LIBNFC_BITUTILS_H_ #define _LIBNFC_BITUTILS_H_ #include "defines.h" -#define INNER_XOR8(n) {\ - n ^= (n >> 4); \ - n ^= (n >> 2); \ - n ^= (n >> 1); \ - n &= 0x01; \ -} - -#define INNER_XOR32(n) {\ - n ^= (n >> 16); \ - n ^= (n >> 8); \ - INNER_XOR8(n); \ -} - -#define INNER_XOR64(n) {\ - n ^= (n >> 32); \ - INNER_XOR32(n); \ -} - byte oddparity(const byte bt); void oddparity_bytes(const byte* pbtData, const ui32 uiLen, byte* pbtPar); @@ -55,6 +37,7 @@ ui64 swap_endian64(const void* pui64); void append_iso14443a_crc(byte* pbtData, ui32 uiLen); void print_hex(const byte* pbtData, const ui32 uiLen); +void print_hex_bits(const byte* pbtData, const ui32 uiBits); void print_hex_par(const byte* pbtData, const ui32 uiBits, const byte* pbtDataPar); #endif // _LIBNFC_BITUTILS_H_ diff --git a/defines.h b/defines.h index 99edc19..6ec18e2 100644 --- a/defines.h +++ b/defines.h @@ -1,26 +1,28 @@ -/* - -Public platform independent Near Field Communication (NFC) library -Copyright (C) 2009, Roel Verdult - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU 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 General Public License -along with this program. If not, see . - -*/ - +/* + +Public platform independent Near Field Communication (NFC) library +Copyright (C) 2009, Roel Verdult + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU 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 General Public License +along with this program. If not, see . + +*/ + #ifndef _LIBNFC_DEFINES_H_ #define _LIBNFC_DEFINES_H_ +// #define _LIBNFC_VERBOSE_ + typedef unsigned char byte; typedef unsigned char ui8; typedef unsigned short ui16; @@ -33,13 +35,16 @@ typedef int i32; #define null 0 -typedef void* dev_id; // Device Id -#define INVALID_DEVICE_ID null +typedef void* dev_spec; // Device connection specification +#define INVALID_DEVICE_INFO null #define MAX_FRAME_LEN 264 +#define DEVICE_NAME_LENGTH 256 -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#define max(a,b) (((a) > (b)) ? (a) : (b)) - -// #define _LIBNFC_VERBOSE_ +// Useful macros +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define INNER_XOR8(n) {n ^= (n >> 4); n ^= (n >> 2); n ^= (n >> 1); n &= 0x01; } +#define INNER_XOR32(n) {n ^= (n >> 16); n ^= (n >> 8); INNER_XOR8(n); } +#define INNER_XOR64(n) {n ^= (n >> 32); INNER_XOR32(n); } #endif // _LIBNFC_DEFINES_H_ diff --git a/libnfc.c b/libnfc.c index f832b28..8d87140 100644 --- a/libnfc.c +++ b/libnfc.c @@ -1,524 +1,761 @@ -/* - -Public platform independent Near Field Communication (NFC) library -Copyright (C) 2009, Roel Verdult - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU 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 General Public License -along with this program. If not, see . - -*/ - -#include -#include -#include "libnfc.h" -#include "acr122.h" -#include "bitutils.h" - -#define REG_CIU_TX_MODE 0x6302 -#define REG_CIU_RX_MODE 0x6303 -#define REG_CIU_TX_AUTO 0x6305 -#define REG_CIU_MANUAL_RCV 0x630D -#define REG_CIU_CONTROL 0x633C -#define REG_CIU_BIT_FRAMING 0x633D - -#define PARAM_NONE 0x00 -#define PARAM_NAD_USED 0x01 -#define PARAM_DID_USED 0x02 -#define PARAM_AUTO_ATR_RES 0x04 -#define PARAM_AUTO_RATS 0x10 -#define PARAM_14443_4_PICC 0x20 -#define PARAM_NO_AMBLE 0x40 - -// PN532 configuration -byte pncmd_get_firmware_version [ 2] = { 0xD4,0x02 }; -byte pncmd_get_general_status [ 2] = { 0xD4,0x04 }; -byte pncmd_get_register [ 4] = { 0xD4,0x06 }; -byte pncmd_set_register [ 5] = { 0xD4,0x08 }; -byte pncmd_set_parameters [ 3] = { 0xD4,0x12 }; - -// RF field configuration -byte pncmd_rf_configure_field [ 4] = { 0xD4,0x32,0x01 }; -byte pncmd_rf_configure_timing [ 4] = { 0xD4,0x32,0x02 }; -byte pncmd_rf_configure_retry_data [ 4] = { 0xD4,0x32,0x04 }; -byte pncmd_rf_configure_retry_select [ 6] = { 0xD4,0x32,0x05 }; - -// Reader -byte pncmd_reader_list_passive [264] = { 0xD4,0x4A }; -byte pncmd_reader_select [ 3] = { 0xD4,0x54 }; -byte pncmd_reader_deselect [ 3] = { 0xD4,0x44 }; -byte pncmd_reader_release [ 3] = { 0xD4,0x52 }; -byte pncmd_reader_set_baud_rate [ 5] = { 0xD4,0x4E }; -byte pncmd_reader_exchange_data [265] = { 0xD4,0x40 }; -byte pncmd_reader_auto_poll [ 5] = { 0xD4,0x60 }; - -// Target -byte pncmd_target_get_data [ 2] = { 0xD4,0x86 }; -byte pncmd_target_init [ 39] = { 0xD4,0x8C }; -byte pncmd_target_virtual_card [ 4] = { 0xD4,0x14 }; -byte pncmd_target_receive [ 2] = { 0xD4,0x88 }; -byte pncmd_target_send [264] = { 0xD4,0x90 }; -byte pncmd_target_get_status [ 2] = { 0xD4,0x8A }; - -// Exchange raw data frames -byte pncmd_exchange_raw_data [266] = { 0xD4,0x42 }; - -// Global buffers used for communication with the PN532 chip -#define MAX_FRAME_LEN 264 -static byte abtRx[MAX_FRAME_LEN]; -static ui32 uiRxLen; -static ui8 ui8Value; -static ui32 ui32Len = 1; - -bool pn532_transceive(const dev_id di, const byte* pbtTx, const ui32 uiTxLen) -{ - uiRxLen = MAX_FRAME_LEN; - return acr122_transceive(di,pbtTx,uiTxLen,abtRx,&uiRxLen); -} - -bool pn532_set_reg(const dev_id di, ui16 ui16Reg, ui8 ui8Value) -{ - pncmd_set_register[2] = ui16Reg >> 8; - pncmd_set_register[3] = ui16Reg & 0xff; - pncmd_set_register[4] = ui8Value; - return acr122_transceive(di,pncmd_set_register,5,null,null); -} - -byte pn532_get_reg(const dev_id di, ui16 ui16Reg) -{ - pncmd_get_register[2] = ui16Reg >> 8; - pncmd_get_register[3] = ui16Reg & 0xff; - acr122_transceive(di,pncmd_get_register,4,&ui8Value,&ui32Len); - return ui8Value; -} - -bool pn532_set_parameters(const dev_id di, ui8 ui8Value) -{ - pncmd_set_parameters[2] = ui8Value; - return acr122_transceive(di,pncmd_set_parameters,3,null,null); -} - -bool pn532_wrap_frame(const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar, byte* pbtFrame, ui32* puiFrameBits) -{ - byte btFrame; - byte btData; - ui32 uiBitPos; - ui32 uiDataPos = 0; - ui32 uiBitsLeft = uiTxBits; - - // Make sure we should frame at least something - if (uiBitsLeft == 0) return false; - - // Handle a short response (1byte) as a special case - if (uiBitsLeft < 9) - { - *pbtFrame = *pbtTx; - *puiFrameBits = uiTxBits; - return true; - } - - // We start by calculating the frame length in bits - *puiFrameBits = uiTxBits + (uiTxBits/8); - - // Parse the data bytes and add the parity bits - // This is really a sensitive process, mirror the frame bytes and append parity bits - // buffer = mirror(frame-byte) + parity + mirror(frame-byte) + parity + ... - // split "buffer" up in segments of 8 bits again and mirror them - // air-bytes = mirror(buffer-byte) + mirror(buffer-byte) + mirror(buffer-byte) + .. - while(true) - { - // Reset the temporary frame byte; - btFrame = 0; - - for (uiBitPos=0; uiBitPos<8; uiBitPos++) - { - // Copy as much data that fits in the frame byte - btData = mirror(pbtTx[uiDataPos]); - btFrame |= (btData >> uiBitPos); - // Save this frame byte - *pbtFrame = mirror(btFrame); - // Set the remaining bits of the date in the new frame byte and append the parity bit - btFrame = (btData << (8-uiBitPos)); - btFrame |= ((pbtTxPar[uiDataPos] & 0x01) << (7-uiBitPos)); - // Backup the frame bits we have so far - pbtFrame++; - *pbtFrame = mirror(btFrame); - // Increase the data (without parity bit) position - uiDataPos++; - // Test if we are done - if (uiBitsLeft < 9) return true; - uiBitsLeft -= 8; - } - // Every 8 data bytes we lose one frame byte to the parities - pbtFrame++; - } -} - -bool pn532_unwrap_frame(const byte* pbtFrame, const ui32 uiFrameBits, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar) -{ - byte btFrame; - byte btData; - ui8 uiBitPos; - ui32 uiDataPos = 0; - byte* pbtFramePos = (byte*) pbtFrame; - ui32 uiBitsLeft = uiFrameBits; - - // Make sure we should frame at least something - if (uiBitsLeft == 0) return false; - - // Handle a short response (1byte) as a special case - if (uiBitsLeft < 9) - { - *pbtRx = *pbtFrame; - *puiRxBits = uiFrameBits; - return true; - } - - // Calculate the data length in bits - *puiRxBits = uiFrameBits - (uiFrameBits/9); - - // Parse the frame bytes, remove the parity bits and store them in the parity array - // This process is the reverse of WrapFrame(), look there for more info - while(true) - { - for (uiBitPos=0; uiBitPos<8; uiBitPos++) - { - btFrame = mirror(pbtFramePos[uiDataPos]); - btData = (btFrame << uiBitPos); - btFrame = mirror(pbtFramePos[uiDataPos+1]); - btData |= (btFrame >> (8-uiBitPos)); - pbtRx[uiDataPos] = mirror(btData); - if(pbtRxPar != null) pbtRxPar[uiDataPos] = ((btFrame >> (7-uiBitPos)) & 0x01); - // Increase the data (without parity bit) position - uiDataPos++; - // Test if we are done - if (uiBitsLeft < 9) return true; - uiBitsLeft -= 9; - } - // Every 8 data bytes we lose one frame byte to the parities - pbtFramePos++; - } -} - -bool nfc_configure_handle_crc(const dev_id di, const bool bEnable) -{ - if (bEnable) - { - // Enable automatic receiving/sending of CRC bytes - if (!pn532_set_reg(di,REG_CIU_TX_MODE,pn532_get_reg(di,REG_CIU_TX_MODE) | 0x80)) return false; - if (!pn532_set_reg(di,REG_CIU_RX_MODE,pn532_get_reg(di,REG_CIU_RX_MODE) | 0x80)) return false; - } else { - // Disable automatic receiving/sending of CRC bytes - if (!pn532_set_reg(di,REG_CIU_TX_MODE,pn532_get_reg(di,REG_CIU_TX_MODE) & 0x7f)) return false; - if (!pn532_set_reg(di,REG_CIU_RX_MODE,pn532_get_reg(di,REG_CIU_RX_MODE) & 0x7f)) return false; - } - return true; -} - -bool nfc_configure_handle_parity(const dev_id di, const bool bEnable) -{ - if (bEnable) - { - // Handle parity by chip - if (!pn532_set_reg(di,REG_CIU_MANUAL_RCV,pn532_get_reg(di,REG_CIU_MANUAL_RCV) & 0xef)) return false; - - } else { - // Parse parity as data bit - if (!pn532_set_reg(di,REG_CIU_MANUAL_RCV,pn532_get_reg(di,REG_CIU_MANUAL_RCV) | 0x10)) return false; - } - return true; -} - -bool nfc_configure_field(const dev_id di, const bool bEnable) -{ - pncmd_rf_configure_field[3] = (bEnable) ? 1 : 0; - return acr122_transceive(di,pncmd_rf_configure_field,4,null,null); -} - -bool nfc_configure_list_passive_infinite(const dev_id di, const bool bEnable) -{ - // Retry format: 0x00 means only 1 try, 0xff means infinite - pncmd_rf_configure_retry_select[3] = (bEnable) ? 0xff : 0x00; // MxRtyATR, default: active = 0xff, passive = 0x02 - pncmd_rf_configure_retry_select[4] = (bEnable) ? 0xff : 0x00; // MxRtyPSL, default: 0x01 - pncmd_rf_configure_retry_select[5] = (bEnable) ? 0xff : 0x00; // MxRtyPassiveActivation, default: 0xff - return acr122_transceive(di,pncmd_rf_configure_retry_select,6,null,null); -} - -bool nfc_configure_accept_invalid_frames(const dev_id di, const bool bEnable) -{ - if (bEnable) - { - // Handle parity by chip - if (!pn532_set_reg(di,REG_CIU_RX_MODE,pn532_get_reg(di,REG_CIU_RX_MODE) | 0x08)) return false; - - } else { - // Parse parity as data bit - if (!pn532_set_reg(di,REG_CIU_RX_MODE,pn532_get_reg(di,REG_CIU_RX_MODE) | 0xf7)) return false; - } - return true; -} - -bool nfc_configure_accept_multiple_frames(const dev_id di, const bool bEnable) -{ - if (bEnable) - { - // Handle parity by chip - if (!pn532_set_reg(di,REG_CIU_RX_MODE,pn532_get_reg(di,REG_CIU_RX_MODE) | 0x04)) return false; - - } else { - // Parse parity as data bit - if (!pn532_set_reg(di,REG_CIU_RX_MODE,pn532_get_reg(di,REG_CIU_RX_MODE) | 0xfb)) return false; - } - return true; -} - -bool nfc_reader_init(const dev_id di) -{ - // Try to connect to the NFC reader - if (di == INVALID_DEVICE_ID) return INVALID_DEVICE_ID; - - // Let the PN5XX automatically be activated by the RF level detector - if (!pn532_set_reg(di,REG_CIU_TX_AUTO,pn532_get_reg(di,REG_CIU_TX_AUTO) | 0x40)) return false; - - // Configure the PN532 to be an Initiator or Reader/Writer - if (!pn532_set_reg(di,REG_CIU_CONTROL,pn532_get_reg(di,REG_CIU_CONTROL) | 0x10)) return false; - - return true; -} - -bool nfc_reader_list_passive(const dev_id di, const ModulationType mt, const byte* pbtInitData, const ui32 uiInitDataLen, byte* pbtTag, ui32* puiTagLen) -{ - pncmd_reader_list_passive[2] = 1; // MaxTg, we only want to select 1 tag at the time - pncmd_reader_list_passive[3] = mt; // BrTy, the type of modulation used for polling a passive tag - - // Set the optional initiator data (used for Felica, ISO14443B, Topaz Polling or selecting a specific UID). - if (pbtInitData) memcpy(pncmd_reader_list_passive+4,pbtInitData,uiInitDataLen); - - // Try to find the available tags - if (!acr122_transceive(di,pncmd_reader_list_passive,4+uiInitDataLen,pbtTag,puiTagLen)) return false; - - // Return true only if at least one tag has been found, the PN532 returns 0x00 if none was available - return (pbtTag[0] != 0x00); -} - -bool nfc_reader_transceive_7bits(const dev_id di, const byte btTx, byte* pbtRx, ui32* puiRxLen) -{ - // Set transmission bits to 7 - if (!pn532_set_reg(di,REG_CIU_BIT_FRAMING,7)) return false; - - pncmd_exchange_raw_data[2] = btTx; - if (!pn532_transceive(di,pncmd_exchange_raw_data,3)) return false; - - if (uiRxLen == 1 || abtRx[0] != 0) return false; - *puiRxLen = uiRxLen-1; - memcpy(pbtRx,abtRx+1,*puiRxLen); - - // Reset transmission bits count - if (!pn532_set_reg(di,REG_CIU_BIT_FRAMING,0)) return false; - - return true; -} - -bool nfc_reader_transceive_bytes(const dev_id di, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen) -{ - memcpy(pncmd_exchange_raw_data+2,pbtTx,uiTxLen); - - if (!pn532_transceive(di,pncmd_exchange_raw_data,2+uiTxLen)) return false; - - if (uiRxLen == 1 || abtRx[0] != 0) return false; - *puiRxLen = uiRxLen-1; - memcpy(pbtRx,abtRx+1,*puiRxLen); - - return true; -} - -bool nfc_reader_transceive_bits(const dev_id di, const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar) -{ - ui32 uiFrameBits = 0; - ui8 ui8Bits = 0; - - // Convert data to a frame - pn532_wrap_frame(pbtTx,uiTxBits,pbtTxPar,pncmd_exchange_raw_data+2,&uiFrameBits); - - // Retrieve the resting bits - ui8Bits = uiFrameBits%8; - - // Set the amount of transmission bits in the pn532 chip register - if (!pn532_set_reg(di,REG_CIU_BIT_FRAMING,ui8Bits)) return false; - - // Send the frame to the pn532 chip and get the answer - // We have to give the amount of bytes + 1 byte if there are leading bits + the two 0xD4,0x42 - if (!pn532_transceive(di,pncmd_exchange_raw_data,(uiFrameBits/8)+((ui8Bits==0)?0:1)+2)) return false; - - // Make sure there was no failure reported by the PN532 chip (0 == OK) - // TODO: is this ACR122 specific? - if (uiRxLen == 1 || abtRx[0] != 0) return false; - - // Get the last bit-count that is stored in the received byte - ui8Bits = pn532_get_reg(di,REG_CIU_CONTROL) & 0x07; - - // Unwrap the response frame - pn532_unwrap_frame(abtRx+1,((uiRxLen-1-((ui8Bits==0)?0:1))*8)+ui8Bits,pbtRx,puiRxBits,pbtRxPar); - - // Everything went successful - return true; -} - -bool nfc_reader_mifare_cmd(const dev_id di, const MifareCmd mc, const ui8 ui8Block, MifareParam* pmp) -{ - ui32 uiParamLen; - pncmd_reader_exchange_data[2] = 0x01; // Use first target/card - pncmd_reader_exchange_data[3] = mc; // The MIFARE Classic command - pncmd_reader_exchange_data[4] = 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: - uiParamLen = 0; - break; - - // Authenticate command - case MC_AUTH_A: - case MC_AUTH_B: - uiParamLen = sizeof(MifareParamAuth); - break; - - // Data command - case MC_WRITE: - uiParamLen = sizeof(MifareParamData); - break; - - // Value command - case MC_DECREMENT: - case MC_INCREMENT: - case MC_TRANSFER: - uiParamLen = sizeof(MifareParamValue); - break; - - // Please fix your code, you never should reach this statement - default: - return false; - break; - } - - // When available, copy the parameter bytes - if (uiParamLen) memcpy(pncmd_reader_exchange_data+5,(byte*)pmp,uiParamLen); - - // Fire the mifare command - if (!pn532_transceive(di,pncmd_reader_exchange_data,5+uiParamLen)) return false; - - // Make sure there was no failure reported by the PN532 chip (0 == OK) - // TODO: is this ACR122 specific? - if (abtRx[0] != 0) return false; - - // When we have executed a read command, copy the received bytes into the param - if (mc == MC_READ) memcpy(pmp->mpd.abtData,abtRx+1,16); - - // Command succesfully executed - return true; -} - -bool nfc_target_init(const dev_id di, byte* pbtRx, ui32* puiRxLen) -{ - // Clear the target init struct, reset to all zeros - memset(pncmd_target_init+2,0x00,37); - - // Set ATQA (SENS_RES) - pncmd_target_init[3] = 0x04; - pncmd_target_init[4] = 0x00; - - // Set SAK (SEL_RES) - pncmd_target_init[8] = 0x20; - - // Set UID - pncmd_target_init[5] = 0x00; - pncmd_target_init[6] = 0xb0; - pncmd_target_init[7] = 0x0b; - - // Enable CRC & parity, needed for target_init to work properly - nfc_configure_handle_crc(di,true); - nfc_configure_handle_parity(di,true); - - // Request the initialization as a target - if (!pn532_transceive(di,pncmd_target_init,39)) return false; - - if (uiRxLen == 1 || abtRx[0] != 0) return false; - *puiRxLen = uiRxLen-1; - memcpy(pbtRx,abtRx+1,*puiRxLen); - - return true; -} - -bool nfc_target_receive_bytes(const dev_id di, byte* pbtRx, ui32* puiRxLen) -{ - if (!pn532_transceive(di,pncmd_target_receive,2)) return false; - - if (uiRxLen == 1 || abtRx[0] != 0) return false; - *puiRxLen = uiRxLen-1; - memcpy(pbtRx,abtRx+1,*puiRxLen); - - return true; -} - -bool nfc_target_receive_bits(const dev_id di, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar) -{ - ui8 ui8Bits; - - // Try to gather the received frames from the reader - if (!pn532_transceive(di,pncmd_target_receive,2)) return false; - - // Make sure there was no failure reported by the PN532 chip (0 == OK) - // TODO: is this ACR122 specific? - if (uiRxLen == 1 || abtRx[0] != 0) return false; - - // Get the last bit-count that is stored in the received byte - ui8Bits = pn532_get_reg(di,REG_CIU_CONTROL) & 0x07; - - // Unwrap the response frame - pn532_unwrap_frame(abtRx+1,((uiRxLen-1-((ui8Bits==0)?0:1))*8)+ui8Bits,pbtRx,puiRxBits,pbtRxPar); - - return true; -} - -bool nfc_target_send_bytes(const dev_id di, const byte* pbtTx, const ui32 uiTxLen) -{ - memcpy(pncmd_target_send+2,pbtTx,uiTxLen); - return acr122_transceive(di,pncmd_target_send,2+uiTxLen,null,null); -} - -bool nfc_target_send_bits(const dev_id di, const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar) -{ - ui32 uiFrameBits = 0; - ui8 ui8Bits = 0; - - // Convert data to a frame - pn532_wrap_frame(pbtTx,uiTxBits,pbtTxPar,pncmd_target_send+2,&uiFrameBits); - - // Retrieve the resting bits - ui8Bits = uiFrameBits%8; - - // Set the amount of transmission bits in the pn532 chip register - if (!pn532_set_reg(di,REG_CIU_BIT_FRAMING,ui8Bits)) return false; - - // Try to send the bits to the reader - if (!pn532_transceive(di,pncmd_target_send,(uiFrameBits/8)+((ui8Bits==0)?0:1)+2)) return false; - - // Make sure there was no failure reported by the PN532 chip (0 == OK) - // TODO: is this ACR122 specific? - if (uiRxLen == 1 || abtRx[0] != 0) return false; - - // Everyting seems ok, return true - return true; -} - +/* + +Public platform independent Near Field Communication (NFC) library +Copyright (C) 2009, Roel Verdult + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU 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 General Public License +along with this program. If not, see . + +*/ + +#include "libnfc.h" +#include "bitutils.h" +#include +#include + +// Registers and symbols masks used to covers parts within a register +#define REG_CIU_TX_MODE 0x6302 + #define SYMBOL_TX_CRC_ENABLE 0x80 +#define REG_CIU_RX_MODE 0x6303 + #define SYMBOL_RX_CRC_ENABLE 0x80 + #define SYMBOL_RX_NO_ERROR 0x08 + #define SYMBOL_RX_MULTIPLE 0x04 +#define REG_CIU_TX_AUTO 0x6305 + #define SYMBOL_FORCE_100_ASK 0x40 + #define SYMBOL_AUTO_WAKE_UP 0x20 + #define SYMBOL_INITIAL_RF_ON 0x04 +#define REG_CIU_MANUAL_RCV 0x630D + #define SYMBOL_PARITY_DISABLE 0x10 +#define REG_CIU_STATUS2 0x6338 + #define SYMBOL_MF_CRYPTO1_ON 0x08 +#define REG_CIU_CONTROL 0x633C + #define SYMBOL_INITIATOR 0x10 + #define SYMBOL_RX_LAST_BITS 0x07 +#define REG_CIU_BIT_FRAMING 0x633D + #define SYMBOL_TX_LAST_BITS 0x07 + +#define PARAM_NONE 0x00 +#define PARAM_NAD_USED 0x01 +#define PARAM_DID_USED 0x02 +#define PARAM_AUTO_ATR_RES 0x04 +#define PARAM_AUTO_RATS 0x10 +#define PARAM_14443_4_PICC 0x20 +#define PARAM_NO_AMBLE 0x40 + +// PN53X configuration +byte pncmd_get_firmware_version [ 2] = { 0xD4,0x02 }; +byte pncmd_get_general_status [ 2] = { 0xD4,0x04 }; +byte pncmd_get_register [ 4] = { 0xD4,0x06 }; +byte pncmd_set_register [ 5] = { 0xD4,0x08 }; +byte pncmd_set_parameters [ 3] = { 0xD4,0x12 }; + +// RF field configuration +byte pncmd_rf_configure_field [ 4] = { 0xD4,0x32,0x01 }; +byte pncmd_rf_configure_timing [ 4] = { 0xD4,0x32,0x02 }; +byte pncmd_rf_configure_retry_data [ 4] = { 0xD4,0x32,0x04 }; +byte pncmd_rf_configure_retry_select [ 6] = { 0xD4,0x32,0x05 }; + +// Reader +byte pncmd_reader_list_passive [264] = { 0xD4,0x4A }; +byte pncmd_reader_select [ 3] = { 0xD4,0x54 }; +byte pncmd_reader_deselect [ 3] = { 0xD4,0x44,0x00 }; +byte pncmd_reader_release [ 3] = { 0xD4,0x52,0x00 }; +byte pncmd_reader_set_baud_rate [ 5] = { 0xD4,0x4E }; +byte pncmd_reader_exchange_data [265] = { 0xD4,0x40 }; +byte pncmd_reader_auto_poll [ 5] = { 0xD4,0x60 }; + +// Target +byte pncmd_target_get_data [ 2] = { 0xD4,0x86 }; +byte pncmd_target_init [ 39] = { 0xD4,0x8C }; +byte pncmd_target_virtual_card [ 4] = { 0xD4,0x14 }; +byte pncmd_target_receive [ 2] = { 0xD4,0x88 }; +byte pncmd_target_send [264] = { 0xD4,0x90 }; +byte pncmd_target_get_status [ 2] = { 0xD4,0x8A }; + +// Exchange raw data frames +byte pncmd_exchange_raw_data [266] = { 0xD4,0x42 }; + +// Global buffers used for communication with the PN53X chip +#define MAX_FRAME_LEN 264 +static byte abtRx[MAX_FRAME_LEN]; +static ui32 uiRxLen; + +bool pn53x_transceive(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxLen) +{ + // Reset the receiving buffer + uiRxLen = MAX_FRAME_LEN; + + // Call the tranceive callback function of the current device + if (!pdi->pdc->transceive(pdi->ds,pbtTx,uiTxLen,abtRx,&uiRxLen)) return false; + + // Make sure there was no failure reported by the PN53X chip (0x00 == OK) + if (abtRx[0] != 0) return false; + + // Succesful transmission + return true; +} + +byte pn53x_get_reg(const dev_info* pdi, ui16 ui16Reg) +{ + ui8 ui8Value; + ui32 uiValueLen = 1; + pncmd_get_register[2] = ui16Reg >> 8; + pncmd_get_register[3] = ui16Reg & 0xff; + pdi->pdc->transceive(pdi->ds,pncmd_get_register,4,&ui8Value,&uiValueLen); + return ui8Value; +} + +bool pn53x_set_reg(const dev_info* pdi, ui16 ui16Reg, ui8 ui8SybmolMask, ui8 ui8Value) +{ + pncmd_set_register[2] = ui16Reg >> 8; + pncmd_set_register[3] = ui16Reg & 0xff; + pncmd_set_register[4] = ui8Value | (pn53x_get_reg(pdi,ui16Reg) & (~ui8SybmolMask)); + return pdi->pdc->transceive(pdi->ds,pncmd_set_register,5,null,null); +} + +bool pn53x_set_parameters(const dev_info* pdi, ui8 ui8Value) +{ + pncmd_set_parameters[2] = ui8Value; + return pdi->pdc->transceive(pdi->ds,pncmd_set_parameters,3,null,null); +} + +bool pn53x_set_tx_bits(const dev_info* pdi, ui8 ui8Bits) +{ + // Test if we need to update the transmission bits register setting + if (pdi->ui8TxBits != ui8Bits) + { + // Set the amount of transmission bits in the PN53X chip register + if (!pn53x_set_reg(pdi,REG_CIU_BIT_FRAMING,SYMBOL_TX_LAST_BITS,ui8Bits)) return false; + + // Store the new setting + ((dev_info*)pdi)->ui8TxBits = ui8Bits; + } + return true; +} + +bool pn53x_wrap_frame(const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar, byte* pbtFrame, ui32* puiFrameBits) +{ + byte btFrame; + byte btData; + ui32 uiBitPos; + ui32 uiDataPos = 0; + ui32 uiBitsLeft = uiTxBits; + + // Make sure we should frame at least something + if (uiBitsLeft == 0) return false; + + // Handle a short response (1byte) as a special case + if (uiBitsLeft < 9) + { + *pbtFrame = *pbtTx; + *puiFrameBits = uiTxBits; + return true; + } + + // We start by calculating the frame length in bits + *puiFrameBits = uiTxBits + (uiTxBits/8); + + // Parse the data bytes and add the parity bits + // This is really a sensitive process, mirror the frame bytes and append parity bits + // buffer = mirror(frame-byte) + parity + mirror(frame-byte) + parity + ... + // split "buffer" up in segments of 8 bits again and mirror them + // air-bytes = mirror(buffer-byte) + mirror(buffer-byte) + mirror(buffer-byte) + .. + while(true) + { + // Reset the temporary frame byte; + btFrame = 0; + + for (uiBitPos=0; uiBitPos<8; uiBitPos++) + { + // Copy as much data that fits in the frame byte + btData = mirror(pbtTx[uiDataPos]); + btFrame |= (btData >> uiBitPos); + // Save this frame byte + *pbtFrame = mirror(btFrame); + // Set the remaining bits of the date in the new frame byte and append the parity bit + btFrame = (btData << (8-uiBitPos)); + btFrame |= ((pbtTxPar[uiDataPos] & 0x01) << (7-uiBitPos)); + // Backup the frame bits we have so far + pbtFrame++; + *pbtFrame = mirror(btFrame); + // Increase the data (without parity bit) position + uiDataPos++; + // Test if we are done + if (uiBitsLeft < 9) return true; + uiBitsLeft -= 8; + } + // Every 8 data bytes we lose one frame byte to the parities + pbtFrame++; + } +} + +bool pn53x_unwrap_frame(const byte* pbtFrame, const ui32 uiFrameBits, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar) +{ + byte btFrame; + byte btData; + ui8 uiBitPos; + ui32 uiDataPos = 0; + byte* pbtFramePos = (byte*) pbtFrame; + ui32 uiBitsLeft = uiFrameBits; + + // Make sure we should frame at least something + if (uiBitsLeft == 0) return false; + + // Handle a short response (1byte) as a special case + if (uiBitsLeft < 9) + { + *pbtRx = *pbtFrame; + *puiRxBits = uiFrameBits; + return true; + } + + // Calculate the data length in bits + *puiRxBits = uiFrameBits - (uiFrameBits/9); + + // Parse the frame bytes, remove the parity bits and store them in the parity array + // This process is the reverse of WrapFrame(), look there for more info + while(true) + { + for (uiBitPos=0; uiBitPos<8; uiBitPos++) + { + btFrame = mirror(pbtFramePos[uiDataPos]); + btData = (btFrame << uiBitPos); + btFrame = mirror(pbtFramePos[uiDataPos+1]); + btData |= (btFrame >> (8-uiBitPos)); + pbtRx[uiDataPos] = mirror(btData); + if(pbtRxPar != null) pbtRxPar[uiDataPos] = ((btFrame >> (7-uiBitPos)) & 0x01); + // Increase the data (without parity bit) position + uiDataPos++; + // Test if we are done + if (uiBitsLeft < 9) return true; + uiBitsLeft -= 9; + } + // Every 8 data bytes we lose one frame byte to the parities + pbtFramePos++; + } +} + +dev_info* nfc_connect() +{ + dev_info* pdi; + ui32 uiDev; + byte abtFw[4]; + ui32 uiFwLen = sizeof(abtFw); + + // Search through the device list for an available device + for (uiDev=0; uiDevpdc = &(dev_callbacks_list[uiDev]); + pdi->pdc->transceive(pdi->ds,pncmd_get_register,4,null,null); + + // Try to retrieve PN53x chip revision + if (!pdi->pdc->transceive(pdi->ds,pncmd_get_firmware_version,2,abtFw,&uiFwLen)) + { + // Failed to get firmware revision??, whatever...let's disconnect and clean up and return err + pdi->pdc->disconnect(pdi); + return INVALID_DEVICE_INFO; + } + + // Add the firmware revision to the device name, PN531 gives 2 bytes info, but PN532 gives 4 + switch(pdi->ct) + { + case CT_PN531: sprintf(pdi->acName,"%s - PN531 v%d.%d",pdi->acName,abtFw[0],abtFw[1]); break; + case CT_PN532: sprintf(pdi->acName,"%s - PN532 v%d.%d (0x%02x)",pdi->acName,abtFw[1],abtFw[2],abtFw[3]); break; + case CT_PN533: sprintf(pdi->acName,"%s - PN533 v%d.%d (0x%02x)",pdi->acName,abtFw[1],abtFw[2],abtFw[3]); break; + } + + // Reset the ending transmission bits register, it is unknown what the last tranmission used there + if (!pn53x_set_reg(pdi,REG_CIU_BIT_FRAMING,SYMBOL_TX_LAST_BITS,0x00)) return INVALID_DEVICE_INFO; + + // Make sure we reset the CRC and parity to chip handling. + if (!nfc_configure(pdi,DCO_HANDLE_CRC,true)) return INVALID_DEVICE_INFO; + if (!nfc_configure(pdi,DCO_HANDLE_PARITY,true)) return INVALID_DEVICE_INFO; + + // Deactivate the CRYPTO1 chiper, it may could cause problems when still active + if (!nfc_configure(pdi,DCO_ACTIVATE_CRYPTO1,false)) return INVALID_DEVICE_INFO; + + return pdi; + } + } + + // To bad, no reader is ready to be claimed + return INVALID_DEVICE_INFO; +} + +void nfc_disconnect(dev_info* pdi) +{ + // Disconnect, clean up and release the device + pdi->pdc->disconnect(pdi); +} + +bool nfc_configure(dev_info* pdi, const dev_config_option dco, const bool bEnable) +{ + byte btValue; + + // Make sure we are dealing with a active device + if (!pdi->bActive) return false; + + switch(dco) + { + case DCO_HANDLE_CRC: + // Enable or disable automatic receiving/sending of CRC bytes + // TX and RX are both represented by the symbol 0x80 + btValue = (bEnable) ? 0x80 : 0x00; + if (!pn53x_set_reg(pdi,REG_CIU_TX_MODE,SYMBOL_TX_CRC_ENABLE,btValue)) return false; + if (!pn53x_set_reg(pdi,REG_CIU_RX_MODE,SYMBOL_RX_CRC_ENABLE,btValue)) return false; + pdi->bCrc = bEnable; + break; + + case DCO_HANDLE_PARITY: + // Handle parity bit by PN53X chip or parse it as data bit + btValue = (bEnable) ? 0x00 : SYMBOL_PARITY_DISABLE; + if (!pn53x_set_reg(pdi,REG_CIU_MANUAL_RCV,SYMBOL_PARITY_DISABLE,btValue)) return false; + pdi->bPar = bEnable; + break; + + case DCO_ACTIVATE_FIELD: + pncmd_rf_configure_field[3] = (bEnable) ? 1 : 0; + if (!pdi->pdc->transceive(pdi->ds,pncmd_rf_configure_field,4,null,null)) return false; + break; + + case DCO_ACTIVATE_CRYPTO1: + btValue = (bEnable) ? SYMBOL_MF_CRYPTO1_ON : 0x00; + if (!pn53x_set_reg(pdi,REG_CIU_STATUS2,SYMBOL_MF_CRYPTO1_ON,btValue)) return false; + break; + + case DCO_INFINITE_SELECT: + // Retry format: 0x00 means only 1 try, 0xff means infinite + pncmd_rf_configure_retry_select[3] = (bEnable) ? 0xff : 0x00; // MxRtyATR, default: active = 0xff, passive = 0x02 + pncmd_rf_configure_retry_select[4] = (bEnable) ? 0xff : 0x00; // MxRtyPSL, default: 0x01 + pncmd_rf_configure_retry_select[5] = (bEnable) ? 0xff : 0x00; // MxRtyPassiveActivation, default: 0xff + if(!pdi->pdc->transceive(pdi->ds,pncmd_rf_configure_retry_select,6,null,null)) return false; + break; + + case DCO_ACCEPT_INVALID_FRAMES: + btValue = (bEnable) ? SYMBOL_RX_NO_ERROR : 0x00; + if (!pn53x_set_reg(pdi,REG_CIU_RX_MODE,SYMBOL_RX_NO_ERROR,btValue)) return false; + break; + + case DCO_ACCEPT_MULTIPLE_FRAMES: + btValue = (bEnable) ? SYMBOL_RX_MULTIPLE : 0x00; + if (!pn53x_set_reg(pdi,REG_CIU_RX_MODE,SYMBOL_RX_MULTIPLE,btValue)) return false; + return true; + + break; + } + + // When we reach this, the configuration is completed and succesful + return true; +} + +bool nfc_reader_init(const dev_info* pdi) +{ + // Make sure we are dealing with a active device + if (!pdi->bActive) return false; + + // Set the PN53X to force 100% ASK Modified miller decoding (default for 14443A cards) + if (!pn53x_set_reg(pdi,REG_CIU_TX_AUTO,SYMBOL_FORCE_100_ASK,0x40)) return false; + + // Configure the PN53X to be an Initiator or Reader/Writer + if (!pn53x_set_reg(pdi,REG_CIU_CONTROL,SYMBOL_INITIATOR,0x10)) return false; + + return true; +} + +bool nfc_reader_select(const dev_info* pdi, const init_modulation im, const byte* pbtInitData, const ui32 uiInitDataLen, tag_info* pti) +{ + // Make sure we are dealing with a active device + if (!pdi->bActive) return false; + + pncmd_reader_list_passive[2] = 1; // MaxTg, we only want to select 1 tag at the time + pncmd_reader_list_passive[3] = im; // BrTy, the type of init modulation used for polling a passive tag + + // Set the optional initiator data (used for Felica, ISO14443B, Topaz Polling or for ISO14443A selecting a specific UID). + if (pbtInitData) memcpy(pncmd_reader_list_passive+4,pbtInitData,uiInitDataLen); + + // Try to find a tag, call the tranceive callback function of the current device + uiRxLen = MAX_FRAME_LEN; + if (!pdi->pdc->transceive(pdi->ds,pncmd_reader_list_passive,4+uiInitDataLen,abtRx,&uiRxLen)) return false; + + // Make sure one tag has been found, the PN53X returns 0x00 if none was available + if (abtRx[0] != 1) return false; + + // Is a tag info struct available + if (pti) + { + // Fill the tag info struct with the values corresponding to this init modulation + switch(im) + { + case IM_ISO14443A_106: + // Somehow they switched the lower and upper ATQA bytes around for the PN531 chipset + if (pdi->ct == CT_PN531) + { + pti->tia.abtAtqa[0] = abtRx[3]; + pti->tia.abtAtqa[1] = abtRx[2]; + } else { + memcpy(pti->tia.abtAtqa,abtRx+2,2); + } + pti->tia.btSak = abtRx[4]; + // Copy the NFCID1 + pti->tia.uiUidLen = abtRx[5]; + memcpy(pti->tia.abtUid,abtRx+6,pti->tia.uiUidLen); + // Did we received an optional ATS (Smardcard ATR) + if (uiRxLen > pti->tia.uiUidLen+6) + { + pti->tia.uiAtsLen = abtRx[pti->tia.uiUidLen+6]; + memcpy(pti->tia.abtAts,abtRx+pti->tia.uiUidLen+6,pti->tia.uiAtsLen); + } else { + pti->tia.uiAtsLen = 0; + } + break; + + case IM_FELICA_212: + case IM_FELICA_424: + // Store the mandatory info + pti->tif.uiLen = abtRx[2]; + pti->tif.btResCode = abtRx[3]; + // Copy the NFCID2t + memcpy(pti->tif.abtId,abtRx+4,8); + // Copy the felica padding + memcpy(pti->tif.abtPad,abtRx+12,8); + // Test if the System code (SYST_CODE) is available + if (uiRxLen > 20) + { + memcpy(pti->tif.abtSysCode,abtRx+20,2); + } + break; + + case IM_ISO14443B_106: + // Store the mandatory info + memcpy(pti->tib.abtAtqb,abtRx+2,12); + // Ignore the 0x1D byte, and just store the 4 byte id + memcpy(pti->tib.abtId,abtRx+15,4); + pti->tib.btParam1 = abtRx[19]; + pti->tib.btParam2 = abtRx[20]; + pti->tib.btParam3 = abtRx[21]; + pti->tib.btParam4 = abtRx[22]; + // Test if the Higher layer (INF) is available + if (uiRxLen > 22) + { + pti->tib.uiInfLen = abtRx[23]; + memcpy(pti->tib.abtInf,abtRx+24,pti->tib.uiInfLen); + } else { + pti->tib.uiInfLen = 0; + } + break; + + case IM_JEWEL_106: + // Store the mandatory info + memcpy(pti->tij.btSensRes,abtRx+2,2); + memcpy(pti->tij.btId,abtRx+4,4); + break; + + default: + // Should not be possible, so whatever... + break; + } + } + return true; +} + +bool nfc_reader_deselect(const dev_info* pdi) +{ + return (pdi->pdc->transceive(pdi->ds,pncmd_reader_deselect,3,null,null)); +} + +bool nfc_reader_transceive_bits(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar) +{ + ui32 uiFrameBits = 0; + ui32 uiFrameBytes = 0; + ui8 ui8Bits = 0; + + // Check if we should prepare the parity bits ourself + if (!pdi->bPar) + { + // Convert data with parity to a frame + pn53x_wrap_frame(pbtTx,uiTxBits,pbtTxPar,pncmd_exchange_raw_data+2,&uiFrameBits); + } else { + uiFrameBits = uiTxBits; + } + + // Retrieve the leading bits + ui8Bits = uiFrameBits%8; + + // Get the amount of frame bytes + optional (1 byte if there are leading bits) + uiFrameBytes = (uiFrameBits/8)+((ui8Bits==0)?0:1); + + // When the parity is handled before us, we just copy the data + if (pdi->bPar) memcpy(pncmd_exchange_raw_data+2,pbtTx,uiFrameBytes); + + // Set the amount of transmission bits in the PN53X chip register + if (!pn53x_set_tx_bits(pdi,ui8Bits)) return false; + + // Send the frame to the PN53X chip and get the answer + // We have to give the amount of bytes + (the two command bytes 0xD4, 0x42) + if (!pn53x_transceive(pdi,pncmd_exchange_raw_data,uiFrameBytes+2)) return false; + + // Get the last bit-count that is stored in the received byte + ui8Bits = pn53x_get_reg(pdi,REG_CIU_CONTROL) & SYMBOL_RX_LAST_BITS; + + // Recover the real frame length in bits + uiFrameBits = ((uiRxLen-1-((ui8Bits==0)?0:1))*8)+ui8Bits; + + // Ignore the status byte from the PN53X here, it was checked earlier in pn53x_transceive() + // Check if we should recover the parity bits ourself + if (!pdi->bPar) + { + // Unwrap the response frame + pn53x_unwrap_frame(abtRx+1,uiFrameBits,pbtRx,puiRxBits,pbtRxPar); + } else { + // Save the received bits + *puiRxBits = uiFrameBits; + // Copy the received bytes + memcpy(pbtRx,abtRx+1,uiRxLen-1); + } + + // Everything went successful + return true; +} + +bool nfc_reader_transceive_bytes(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen) +{ + // We can not just send bytes without parity if while the PN53X expects we handled them + if (!pdi->bPar) return false; + + // Copy the data into the command frame + memcpy(pncmd_exchange_raw_data+2,pbtTx,uiTxLen); + + // To transfer command frames bytes we can not have any leading bits, reset this to zero + if (!pn53x_set_tx_bits(pdi,0)) return false; + + // Send the frame to the PN53X chip and get the answer + // We have to give the amount of bytes + (the two command bytes 0xD4, 0x42) + if (!pn53x_transceive(pdi,pncmd_exchange_raw_data,uiTxLen+2)) return false; + + // Save the received byte count + *puiRxLen = uiRxLen-1; + + // Copy the received bytes + memcpy(pbtRx,abtRx+1,*puiRxLen); + + // Everything went successful + return true; +} + +bool nfc_reader_mifare_cmd(const dev_info* pdi, const mifare_cmd mc, const ui8 ui8Block, mifare_param* pmp) +{ + ui32 uiParamLen; + + // Make sure we are dealing with a active device + if (!pdi->bActive) return false; + + pncmd_reader_exchange_data[2] = 0x01; // Use first target/card + pncmd_reader_exchange_data[3] = mc; // The MIFARE Classic command + pncmd_reader_exchange_data[4] = 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: + uiParamLen = 0; + break; + + // Authenticate command + case MC_AUTH_A: + case MC_AUTH_B: + uiParamLen = sizeof(mifare_param_auth); + break; + + // Data command + case MC_WRITE: + uiParamLen = sizeof(mifare_param_data); + break; + + // Value command + case MC_DECREMENT: + case MC_INCREMENT: + case MC_TRANSFER: + uiParamLen = 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 (uiParamLen) memcpy(pncmd_reader_exchange_data+5,(byte*)pmp,uiParamLen); + + // Fire the mifare command + if (!pn53x_transceive(pdi,pncmd_reader_exchange_data,5+uiParamLen)) return false; + + // When we have executed a read command, copy the received bytes into the param + if (mc == MC_READ) memcpy(pmp->mpd.abtData,abtRx+1,16); + + // Command succesfully executed + return true; +} + +bool nfc_target_init(const dev_info* pdi, byte* pbtRx, ui32* puiRxBits) +{ + ui8 ui8Bits; + + // Save the current configuration settings + bool bCrc = pdi->bCrc; + bool bPar = pdi->bPar; + + // Clear the target init struct, reset to all zeros + memset(pncmd_target_init+2,0x00,37); + + // Set ATQA (SENS_RES) + pncmd_target_init[3] = 0x04; + pncmd_target_init[4] = 0x00; + + // Set SAK (SEL_RES) + pncmd_target_init[8] = 0x20; + + // Set UID + pncmd_target_init[5] = 0x00; + pncmd_target_init[6] = 0xb0; + pncmd_target_init[7] = 0x0b; + + // Make sure the CRC & parity are handled by the device, this is needed for target_init to work properly + if (!bCrc) nfc_configure((dev_info*)pdi,DCO_HANDLE_CRC,true); + if (!bPar) nfc_configure((dev_info*)pdi,DCO_HANDLE_CRC,true); + + // Let the PN53X be activated by the RF level detector from power down mode + if (!pn53x_set_reg(pdi,REG_CIU_TX_AUTO, SYMBOL_INITIAL_RF_ON,0x04)) return false; + + // Request the initialization as a target, we can not use pn53x_transceive() because + // abtRx[0] contains the emulation mode (baudrate, 14443-4?, DEP and framing type) + uiRxLen = MAX_FRAME_LEN; + if (!pdi->pdc->transceive(pdi->ds,pncmd_target_init,39,abtRx,&uiRxLen)) return false; + + // Get the last bit-count that is stored in the received byte + ui8Bits = pn53x_get_reg(pdi,REG_CIU_CONTROL) & SYMBOL_RX_LAST_BITS; + + // We are sure the parity is handled by the PN53X chip, so we handle it this way + *puiRxBits = ((uiRxLen-1-((ui8Bits==0)?0:1))*8)+ui8Bits; + // Copy the received bytes + memcpy(pbtRx,abtRx+1,uiRxLen-1); + + // Restore the CRC & parity setting to the original value (if needed) + if (!bCrc) nfc_configure((dev_info*)pdi,DCO_HANDLE_CRC,false); + if (!bPar) nfc_configure((dev_info*)pdi,DCO_HANDLE_CRC,false); + + return true; +} + +bool nfc_target_receive_bits(const dev_info* pdi, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar) +{ + ui32 uiFrameBits; + ui8 ui8Bits; + + // Try to gather a received frame from the reader + if (!pn53x_transceive(pdi,pncmd_target_receive,2)) return false; + + // Get the last bit-count that is stored in the received byte + ui8Bits = pn53x_get_reg(pdi,REG_CIU_CONTROL) & SYMBOL_RX_LAST_BITS; + + // Recover the real frame length in bits + uiFrameBits = ((uiRxLen-1-((ui8Bits==0)?0:1))*8)+ui8Bits; + + // Ignore the status byte from the PN53X here, it was checked earlier in pn53x_transceive() + // Check if we should recover the parity bits ourself + if (!pdi->bPar) + { + // Unwrap the response frame + pn53x_unwrap_frame(abtRx+1,uiFrameBits,pbtRx,puiRxBits,pbtRxPar); + } else { + // Save the received bits + *puiRxBits = uiFrameBits; + // Copy the received bytes + memcpy(pbtRx,abtRx+1,uiRxLen-1); + } + // Everyting seems ok, return true + return true; +} + +bool nfc_target_receive_bytes(const dev_info* pdi, byte* pbtRx, ui32* puiRxLen) +{ + // Try to gather a received frame from the reader + if (!pn53x_transceive(pdi,pncmd_target_receive,2)) return false; + + // Save the received byte count + *puiRxLen = uiRxLen-1; + + // Copy the received bytes + memcpy(pbtRx,abtRx+1,*puiRxLen); + + // Everyting seems ok, return true + return true; +} + +bool nfc_target_send_bits(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar) +{ + ui32 uiFrameBits = 0; + ui32 uiFrameBytes = 0; + ui8 ui8Bits = 0; + + // Check if we should prepare the parity bits ourself + if (!pdi->bPar) + { + // Convert data with parity to a frame + pn53x_wrap_frame(pbtTx,uiTxBits,pbtTxPar,pncmd_target_send+2,&uiFrameBits); + } else { + uiFrameBits = uiTxBits; + } + + // Retrieve the leading bits + ui8Bits = uiFrameBits%8; + + // Get the amount of frame bytes + optional (1 byte if there are leading bits) + uiFrameBytes = (uiFrameBits/8)+((ui8Bits==0)?0:1); + + // When the parity is handled before us, we just copy the data + if (pdi->bPar) memcpy(pncmd_target_send+2,pbtTx,uiFrameBytes); + + // Set the amount of transmission bits in the PN53X chip register + if (!pn53x_set_tx_bits(pdi,ui8Bits)) return false; + + // Try to send the bits to the reader + if (!pn53x_transceive(pdi,pncmd_target_send,uiFrameBytes+2)) return false; + + // Everyting seems ok, return true + return true; +} + + +bool nfc_target_send_bytes(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxLen) +{ + // We can not just send bytes without parity if while the PN53X expects we handled them + if (!pdi->bPar) return false; + + // Copy the data into the command frame + memcpy(pncmd_target_send+2,pbtTx,uiTxLen); + + // Try to send the bits to the reader + if (!pn53x_transceive(pdi,pncmd_target_send,uiTxLen+2)) return false; + + // Everyting seems ok, return true + return true; +} diff --git a/libnfc.h b/libnfc.h index ba8802a..f122137 100644 --- a/libnfc.h +++ b/libnfc.h @@ -1,50 +1,47 @@ -/* - -Public platform independent Near Field Communication (NFC) library -Copyright (C) 2009, Roel Verdult - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU 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 General Public License -along with this program. If not, see . - -*/ - +/* + +Public platform independent Near Field Communication (NFC) library +Copyright (C) 2009, Roel Verdult + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU 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 General Public License +along with this program. If not, see . + +*/ + #ifndef _LIBNFC_H_ #define _LIBNFC_H_ #include "defines.h" #include "types.h" #include "bitutils.h" -#include "acr122.h" +#include "devices.h" -bool nfc_configure_handle_crc(const dev_id di, const bool bEnable); -bool nfc_configure_handle_parity(const dev_id di, const bool bEnable); -bool nfc_configure_field(const dev_id di, const bool bEnable); -bool nfc_configure_list_passive_infinite(const dev_id di, const bool bEnable); -bool nfc_configure_accept_invalid_frames(const dev_id di, const bool bEnable); -bool nfc_configure_accept_multiple_frames(const dev_id di, const bool bEnable); +dev_info* nfc_connect(); +void nfc_disconnect(dev_info* pdi); +bool nfc_configure(dev_info* pdi, const dev_config_option dco, const bool bEnable); -bool nfc_reader_init(const dev_id di); -bool nfc_reader_list_passive(const dev_id di, const ModulationType mt, const byte* pbtInitData, const ui32 uiInitDataLen, byte* pbtTag, ui32* puiTagLen); -bool nfc_reader_transceive_7bits(const dev_id di, const byte btTx, byte* pbtRx, ui32* puiRxLen); -bool nfc_reader_transceive_bytes(const dev_id di, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen); -bool nfc_reader_transceive_bits(const dev_id di, const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar); -bool nfc_reader_mifare_cmd(const dev_id di, const MifareCmd mc, const ui8 ui8Block, MifareParam* pmp); +bool nfc_reader_init(const dev_info* pdi); +bool nfc_reader_select(const dev_info* pdi, const init_modulation im, const byte* pbtInitData, const ui32 uiInitDataLen, tag_info* pti); +bool nfc_reader_deselect(const dev_info* pdi); +bool nfc_reader_transceive_bits(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar); +bool nfc_reader_transceive_bytes(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen); +bool nfc_reader_mifare_cmd(const dev_info* pdi, const mifare_cmd mc, const ui8 ui8Block, mifare_param* pmp); -bool nfc_target_init(const dev_id di, byte* pbtRx, ui32* puiRxLen); -bool nfc_target_receive_bytes(const dev_id di, byte* pbtRx, ui32* puiRxLen); -bool nfc_target_receive_bits(const dev_id di, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar); -bool nfc_target_send_bytes(const dev_id di, const byte* pbtTx, const ui32 uiTxLen); -bool nfc_target_send_bits(const dev_id di, const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar); +bool nfc_target_init(const dev_info* pdi, byte* pbtRx, ui32* puiRxBits); +bool nfc_target_receive_bits(const dev_info* pdi, byte* pbtRx, ui32* puiRxBits, byte* pbtRxPar); +bool nfc_target_receive_bytes(const dev_info* pdi, byte* pbtRx, ui32* puiRxLen); +bool nfc_target_send_bits(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxBits, const byte* pbtTxPar); +bool nfc_target_send_bytes(const dev_info* pdi, const byte* pbtTx, const ui32 uiTxLen); #endif // _LIBNFC_H_ diff --git a/list.c b/list.c index 7cb111b..be02e9b 100644 --- a/list.c +++ b/list.c @@ -23,61 +23,74 @@ along with this program. If not, see . #include #include "libnfc.h" -static byte abtRecv[MAX_FRAME_LEN]; -static ui32 uiRecvLen; -static dev_id di; +static dev_info* pdi; +static byte abtFelica[5] = { 0x00, 0xff, 0xff, 0x00, 0x00 }; int main(int argc, const char* argv[]) { + tag_info ti; + // Try to open the NFC reader - di = acr122_connect(0); + pdi = nfc_connect(); - if (di == INVALID_DEVICE_ID) + if (pdi == INVALID_DEVICE_INFO) { printf("Error connecting NFC reader\n"); return 1; } - nfc_reader_init(di); + nfc_reader_init(pdi); + + // Drop the field for a while + nfc_configure(pdi,DCO_ACTIVATE_FIELD,false); // Let the reader only try once to find a tag - nfc_configure_list_passive_infinite(di,false); + nfc_configure(pdi,DCO_INFINITE_SELECT,false); - // Drop the field so the tag will be reset - nfc_configure_field(di,false); + // Configure the CRC and Parity settings + nfc_configure(pdi,DCO_HANDLE_CRC,true); + nfc_configure(pdi,DCO_HANDLE_PARITY,true); - // Configure the communication channel - nfc_configure_handle_crc(di,true); - nfc_configure_handle_parity(di,true); + // Enable field so more power consuming cards can power themselves up + nfc_configure(pdi,DCO_ACTIVATE_FIELD,true); - printf("\nConnected to NFC reader\n\n"); - - uiRecvLen = MAX_FRAME_LEN; - if (nfc_reader_list_passive(di,MT_ISO14443A_106,null,null,abtRecv,&uiRecvLen)) + printf("\nConnected to NFC reader: %s\n\n",pdi->acName); + + // Poll for a ISO14443A (MIFARE) tag + if (nfc_reader_select(pdi,IM_ISO14443A_106,null,null,&ti)) { - // ISO14443A tag info = ( tag_count[1], tag_nr[1], ATQA[2], SAK[1], uid_len[1], UID[uid_len], ats_len[1], ATS[ats_len-1] ) - // ATS is optional printf("The following (NFC) ISO14443A tag was found:\n\n"); - printf("%17s","ATQA (SENS_RES): "); - print_hex(abtRecv+2,2); - printf("%17s","UID (NFCID1): "); - print_hex(abtRecv+6,abtRecv[5]); - printf("%17s","SAK (SEL_RES): "); - print_hex(abtRecv+4,1); - if (uiRecvLen > 6+(ui32)abtRecv[5]) + printf(" ATQA (SENS_RES): "); print_hex(ti.tia.abtAtqa,2); + printf(" UID (NFCID%c): ",(ti.tia.abtUid[0]==0x08?'3':'1')); print_hex(ti.tia.abtUid,ti.tia.uiUidLen); + printf(" SAK (SEL_RES): "); print_hex(&ti.tia.btSak,1); + if (ti.tia.uiAtsLen) { - printf("%17s","ATS (ATR): "); - print_hex(abtRecv+6+abtRecv[5]+1,abtRecv[6+abtRecv[5]]-1); + printf(" ATS (ATR): "); + print_hex(ti.tia.abtAts,ti.tia.uiAtsLen); } - } else { - printf("Error: no tag was found\n"); } - // Todo: listing the folllowing tags types - // - // MT_FELICA_212 - // MT_FELICA_424 - // MT_ISO14443B_106 - // MT_TOPAZ_106 + // Poll for a Felica tag + if (nfc_reader_select(pdi,IM_FELICA_212,abtFelica,5,&ti) || nfc_reader_select(pdi,IM_FELICA_424,abtFelica,5,&ti)) + { + printf("The following (NFC) Felica tag was found:\n\n"); + printf("%18s","ID (NFCID2): "); print_hex(ti.tif.abtId,8); + printf("%18s","Parameter (PAD): "); print_hex(ti.tif.abtPad,8); + } - return 0; + // Poll for a ISO14443B tag + if (nfc_reader_select(pdi,IM_ISO14443B_106,null,null,&ti)) + { + // No test results yet + printf("iso14443b\n"); + } + + // Poll for a Jewel tag + if (nfc_reader_select(pdi,IM_JEWEL_106,null,null,&ti)) + { + // No test results yet + printf("jewel\n"); + } + + nfc_disconnect(pdi); + return 1; } diff --git a/mifaretag.h b/mifaretag.h index f6bc772..b07e43d 100644 --- a/mifaretag.h +++ b/mifaretag.h @@ -1,54 +1,54 @@ -/* - -Public platform independent Near Field Communication (NFC) library -Copyright (C) 2009, Roel Verdult - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU 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 General Public License -along with this program. If not, see . - -*/ - -#ifndef _MIFARE_TAG_H_ -#define _MIFARE_TAG_H_ +/* + +Public platform independent Near Field Communication (NFC) library +Copyright (C) 2009, Roel Verdult + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU 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 General Public License +along with this program. If not, see . + +*/ + +#ifndef _LIBNFC_MIFARE_TAG_H_ +#define _LIBNFC_MIFARE_TAG_H_ #include "defines.h" -typedef struct tagBlockManufacturer { +typedef struct { byte abtUID[4]; byte btBCC; byte btUnknown; byte abtATQA[2]; byte abtUnknown[8]; -} BlockManufacturer; +} mifare_block_manufacturer; -typedef struct tagBlockData { - byte abtContent[16]; -} BlockData; +typedef struct { + byte abtData[16]; +} mifare_block_data; -typedef struct tagBlockTrailer { +typedef struct { byte abtKeyA[6]; byte abtAccessBits[4]; byte abtKeyB[6]; -} BlockTrailer; +} mifare_block_trailer; -typedef union tagBlock { - BlockManufacturer bm; - BlockData bd; - BlockTrailer bt; -} Block; +typedef union { + mifare_block_manufacturer mbm; + mifare_block_data mbd; + mifare_block_trailer mbt; +} mifare_block; -typedef struct tagMifareTag { - Block blContent[256]; -} MifareTag; +typedef struct { + mifare_block amb[256]; +} mifare_tag; -#endif // _MIFARE_TAG_H_ +#endif // _LIBNFC_MIFARE_TAG_H_ diff --git a/relay.c b/relay.c index f6295bd..65c1566 100644 --- a/relay.c +++ b/relay.c @@ -1,107 +1,99 @@ -/* - -Public platform independent Near Field Communication (NFC) library -Copyright (C) 2009, Roel Verdult - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU 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 General Public License -along with this program. If not, see . - -*/ - -#include -#include -#include -#include "libnfc.h" - -static byte abtReaderRecv[MAX_FRAME_LEN]; -static byte abtReaderRecvPar[MAX_FRAME_LEN]; -static ui32 uiReaderRecvBits; -static byte abtTagRecv[MAX_FRAME_LEN]; -static byte abtTagRecvPar[MAX_FRAME_LEN]; -static ui32 uiTagRecvBits; -static dev_id diReader; -static dev_id diTag; - -int main(int argc, const char* argv[]) -{ - // Try to open the NFC reader - diReader = acr122_connect(0); - if (diReader == INVALID_DEVICE_ID) - { - printf("Error connecting first NFC reader\n"); - return 1; - } - - diTag = acr122_connect(1); - if (diTag == INVALID_DEVICE_ID) - { - printf("Error connecting second NFC reader\n"); - return 1; - } - - printf("\n"); - printf("[+] Connected to the both NFC readers\n"); - acr122_led_red(diTag,true); - printf("[+] Identified simulated tag by setting the red light\n"); - printf("[+] Place both readers on top of each other\n"); - printf("[+] Please run 'anticol' tool in a different shell\n"); - nfc_target_init(diTag,abtReaderRecv,&uiReaderRecvBits); - nfc_configure_handle_crc(diTag,false); - nfc_configure_handle_parity(diTag,false); - nfc_configure_accept_invalid_frames(diTag,true); - printf("[+] Thank you, the simulated tag is initialized\n"); - - printf("[+] Attaching to first NFC reader \n"); - // Retry until it becomes ready - while (!nfc_reader_init(diReader)) - { - acr122_disconnect(diReader); - printf("error\n"); - diReader = acr122_connect(0); - } - nfc_configure_handle_crc(diReader,false); - nfc_configure_handle_parity(diReader,false); - nfc_configure_accept_invalid_frames(diReader,true); - printf("[+] Done, relaying frames now!\n\n"); - - while(true) - { - // Test if we received a frame from the reader - if (nfc_target_receive_bits(diTag,abtReaderRecv,&uiReaderRecvBits,abtReaderRecvPar)) - { - // Drop down the field before sending a REQA command and start a new session - if (uiReaderRecvBits == 7 && abtReaderRecv[0] == 0x26) - { - // Drop down field for a very short time (tag will reboot) - nfc_configure_field(diReader,false); - printf("\n"); - nfc_configure_field(diReader,true); - } - - // Print the reader frame to the screen - printf("R: "); - print_hex_par(abtReaderRecv,uiReaderRecvBits,abtReaderRecvPar); - - // Forward the frame to the original tag - if (nfc_reader_transceive_bits(diReader,abtReaderRecv,uiReaderRecvBits,abtReaderRecvPar,abtTagRecv,&uiTagRecvBits,abtTagRecvPar)) - { - // Redirect the answer back to the reader - nfc_target_send_bits(diTag,abtTagRecv,uiTagRecvBits,abtTagRecvPar); - - // Print the tag frame to the screen - printf("T: "); - print_hex_par(abtTagRecv,uiTagRecvBits,abtTagRecvPar); - } - } - } -} +/* + +Public platform independent Near Field Communication (NFC) library +Copyright (C) 2009, Roel Verdult + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU 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 General Public License +along with this program. If not, see . + +*/ + +#include +#include +#include +#include "libnfc.h" + +static byte abtReaderRx[MAX_FRAME_LEN]; +static byte abtReaderRxPar[MAX_FRAME_LEN]; +static ui32 uiReaderRxBits; +static byte abtTagRx[MAX_FRAME_LEN]; +static byte abtTagRxPar[MAX_FRAME_LEN]; +static ui32 uiTagRxBits; +static dev_info* pdiReader; +static dev_info* pdiTag; + +int main(int argc, const char* argv[]) +{ + // Try to open the NFC emulator device + pdiTag = nfc_connect(); + if (pdiTag == INVALID_DEVICE_INFO) + { + printf("Error connecting NFC emulator device\n"); + return 1; + } + + printf("\n"); + printf("[+] Connected to the NFC emulator device\n"); + printf("[+] Try to break out the auto-simulation, 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 \"anticol\" tool\n"); + nfc_target_init(pdiTag,abtReaderRx,&uiReaderRxBits); + printf("[+] Configuring emulator settings\n"); + nfc_configure(pdiTag,DCO_HANDLE_CRC,false); + nfc_configure(pdiTag,DCO_HANDLE_PARITY,false); + nfc_configure(pdiTag,DCO_ACCEPT_INVALID_FRAMES,true); + printf("[+] Thank you, the emulated tag is initialized\n"); + + // Try to open the NFC reader + pdiReader = INVALID_DEVICE_INFO; + while (pdiReader == INVALID_DEVICE_INFO) pdiReader = nfc_connect(); + printf("[+] Configuring NFC reader settings\n"); + nfc_configure(pdiReader,DCO_HANDLE_CRC,false); + nfc_configure(pdiReader,DCO_HANDLE_PARITY,false); + nfc_configure(pdiReader,DCO_ACCEPT_INVALID_FRAMES,true); + printf("[+] Done, relaying frames now!\n\n"); + + while(true) + { + // Test if we received a frame from the reader + if (nfc_target_receive_bits(pdiTag,abtReaderRx,&uiReaderRxBits,abtReaderRxPar)) + { + // Drop down the field before sending a REQA command and start a new session + if (uiReaderRxBits == 7 && abtReaderRx[0] == 0x26) + { + // Drop down field for a very short time (original tag will reboot) + nfc_configure(pdiReader,DCO_ACTIVATE_FIELD,false); + printf("\n"); + nfc_configure(pdiReader,DCO_ACTIVATE_FIELD,true); + } + + // Print the reader frame to the screen + printf("R: "); + print_hex_par(abtReaderRx,uiReaderRxBits,abtReaderRxPar); + + // Forward the frame to the original tag + if (nfc_reader_transceive_bits(pdiReader,abtReaderRx,uiReaderRxBits,abtReaderRxPar,abtTagRx,&uiTagRxBits,abtTagRxPar)) + { + // Redirect the answer back to the reader + nfc_target_send_bits(pdiTag,abtTagRx,uiTagRxBits,abtTagRxPar); + + // Print the tag frame to the screen + printf("T: "); + print_hex_par(abtTagRx,uiTagRxBits,abtTagRxPar); + } + } + } + + nfc_disconnect(pdiTag); + nfc_disconnect(pdiReader); +} diff --git a/simulate.c b/simulate.c index ad522a1..d8cf0eb 100644 --- a/simulate.c +++ b/simulate.c @@ -1,108 +1,111 @@ -/* - -Public platform independent Near Field Communication (NFC) library -Copyright (C) 2009, Roel Verdult - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU 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 General Public License -along with this program. If not, see . - -*/ - -#include -#include -#include -#include "libnfc.h" - -static byte abtRecv[MAX_FRAME_LEN]; -static ui32 uiRecvLen; -static dev_id di; - -// ISO14443A Anti-Collision response -byte abtAtqa [2] = { 0x04,0x00 }; -byte abtUidBcc [5] = { 0xDE,0xAD,0xBE,0xAF,0x62 }; -byte abtSak [9] = { 0x08,0xb6,0xdd }; - -int main(int argc, const char* argv[]) -{ - byte* pbtTx; - ui32 uiTxLen; - - // Try to open the NFC reader - di = acr122_connect(0); - - if (di == INVALID_DEVICE_ID) - { - printf("Error connecting NFC reader\n"); - return 1; - } - - printf("\n"); - printf("[+] Connected to NFC target\n"); - acr122_led_red(di,true); - printf("[+] Identified simulated tag by setting the red light\n"); - printf("[+] First we have to come out auto-simulation\n"); - printf("[+] To do this, please send any command after the\n"); - printf("[+] anti-collision, for example, the RATS command\n\n"); - nfc_target_init(di,abtRecv,&uiRecvLen); - printf("[+] Initiator command: "); - print_hex(abtRecv,uiRecvLen); - printf("[+] Configuring communication"); - nfc_configure_accept_invalid_frames(di,true); - nfc_configure_handle_crc(di,false); - printf("[+] Done, the simulated tag is initialized \n"); - - - while(true) - { - // Test if we received a frame - if (nfc_target_receive_bytes(di,abtRecv,&uiRecvLen)) - { - // Prepare the command to send back for the anti-collision request - switch(uiRecvLen) - { - case 1: // Request or Wakeup - pbtTx = abtAtqa; - uiTxLen = 2; - // New anti-collsion session started - printf("\n"); - break; - - case 2: // Select All - pbtTx = abtUidBcc; - uiTxLen = 5; - break; - - case 9: // Select Tag - pbtTx = abtSak; - uiTxLen = 3; - break; - - default: // unknown length? - uiTxLen = 0; - break; - } - - printf("R: "); - print_hex(abtRecv,uiRecvLen); - - // Test if we know how to respond - if(uiTxLen) - { - // Send and print the command to the screen - nfc_target_send_bytes(di,pbtTx,uiTxLen); - printf("T: "); - print_hex(pbtTx,uiTxLen); - } - } - } -} +/* + +Public platform independent Near Field Communication (NFC) library +Copyright (C) 2009, Roel Verdult + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU 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 General Public License +along with this program. If not, see . + +*/ + +#include +#include +#include +#include "libnfc.h" + +static byte abtRecv[MAX_FRAME_LEN]; +static ui32 uiRecvBits; +static dev_info* pdi; + +// ISO14443A Anti-Collision response +byte abtAtqa [2] = { 0x04,0x00 }; +byte abtUidBcc [5] = { 0xDE,0xAD,0xBE,0xAF,0x62 }; +byte abtSak [9] = { 0x08,0xb6,0xdd }; + +int main(int argc, const char* argv[]) +{ + byte* pbtTx = null; + ui32 uiTxBits; + + // Try to open the NFC reader + pdi = nfc_connect(); + + if (pdi == INVALID_DEVICE_INFO) + { + printf("Error connecting NFC second reader\n"); + return 1; + } + + printf("\n"); + printf("[+] Connected to NFC reader: %s\n",pdi->acName); + printf("[+] Try to break out the auto-simulation, 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 \"anticol\" tool\n"); + if (!nfc_target_init(pdi,abtRecv,&uiRecvBits)) + { + printf("Error: Could not come out of auto-simulation, no command was received\n"); + return 1; + } + printf("[+] Received initiator command: "); + print_hex_bits(abtRecv,uiRecvBits); + printf("[+] Configuring communication\n"); + nfc_configure(pdi,DCO_HANDLE_CRC,false); + nfc_configure(pdi,DCO_HANDLE_PARITY,true); + printf("[+] Done, the simulated tag is initialized\n\n"); + + while(true) + { + // Test if we received a frame + if (nfc_target_receive_bits(pdi,abtRecv,&uiRecvBits,null)) + { + // Prepare the command to send back for the anti-collision request + switch(uiRecvBits) + { + case 7: // Request or Wakeup + pbtTx = abtAtqa; + uiTxBits = 16; + // New anti-collsion session started + printf("\n"); + break; + + case 16: // Select All + pbtTx = abtUidBcc; + uiTxBits = 40; + break; + + case 72: // Select Tag + pbtTx = abtSak; + uiTxBits = 24; + break; + + default: // unknown length? + uiTxBits = 0; + break; + } + + printf("R: "); + print_hex_bits(abtRecv,uiRecvBits); + + // Test if we know how to respond + if(uiTxBits) + { + // Send and print the command to the screen + nfc_target_send_bits(pdi,pbtTx,uiTxBits,null); + printf("T: "); + print_hex_bits(pbtTx,uiTxBits); + } + } + } + + nfc_disconnect(pdi); +} diff --git a/types.h b/types.h index cba978e..ab3c02d 100644 --- a/types.h +++ b/types.h @@ -1,40 +1,126 @@ -/* - -Public platform independent Near Field Communication (NFC) library -Copyright (C) 2009, Roel Verdult - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU 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 General Public License -along with this program. If not, see . - -*/ - +/* + +Public platform independent Near Field Communication (NFC) library +Copyright (C) 2009, Roel Verdult + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU 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 General Public License +along with this program. If not, see . + +*/ + #ifndef _LIBNFC_TYPES_H_ #define _LIBNFC_TYPES_H_ #include "defines.h" -typedef enum { - false = 0x00, - true = 0x01 -}bool; +// Compiler directive, set struct alignment to 1 byte for compatibility +#pragma pack(1) typedef enum { - MT_ISO14443A_106 = 0x00, - MT_FELICA_212 = 0x01, - MT_FELICA_424 = 0x02, - MT_ISO14443B_106 = 0x03, - MT_TOPAZ_106 = 0x04, -}ModulationType; + false = 0x00, + true = 0x01 +} bool; + +typedef enum { + CT_PN531 = 0x10, + CT_PN532 = 0x20, + CT_PN533 = 0x30, +} chip_type; + +struct dev_callbacks; // Prototype the callback struct + +typedef struct { + const struct dev_callbacks* pdc; // Callback functions for handling device specific wrapping + char acName[DEVICE_NAME_LENGTH]; // Device name string, including device wrapper firmware + chip_type ct; // PN53X chip type, this is useful for some "bug" work-arounds + dev_spec ds; // Pointer to the device connection specification + bool bActive; // This represents if the PN53X device was initialized succesful + bool bCrc; // Is the crc automaticly added, checked and removed from the frames + bool bPar; // Does the PN53x chip handles parity bits, all parities are handled as data + ui8 ui8TxBits; // The last tx bits setting, we need to reset this if it does not apply anymore +} dev_info; + +struct dev_callbacks { + const char* acDriver; // Driver description + dev_info* (*connect)(const ui32 uiIndex); + bool (*transceive)(const dev_spec ds, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen); + void (*disconnect)(dev_info* pdi); +}; + +typedef enum { + DCO_HANDLE_CRC = 0x00, + DCO_HANDLE_PARITY = 0x01, + DCO_ACTIVATE_FIELD = 0x10, + DCO_ACTIVATE_CRYPTO1 = 0x11, + DCO_INFINITE_SELECT = 0x20, + DCO_ACCEPT_INVALID_FRAMES = 0x30, + DCO_ACCEPT_MULTIPLE_FRAMES = 0x31 +}dev_config_option; + +//////////////////////////////////////////////////////////////////// +// nfc_reader_list_passive - using InListPassiveTarget + +typedef enum { + IM_ISO14443A_106 = 0x00, + IM_FELICA_212 = 0x01, + IM_FELICA_424 = 0x02, + IM_ISO14443B_106 = 0x03, + IM_JEWEL_106 = 0x04 +}init_modulation; + +typedef struct { + byte abtAtqa[2]; + byte btSak; + ui32 uiUidLen; + byte abtUid[10]; + ui32 uiAtsLen; + byte abtAts[36]; +}tag_info_iso14443a; + +typedef struct { + ui32 uiLen; + byte btResCode; + byte abtId[8]; + byte abtPad[8]; + byte abtSysCode[2]; +}tag_info_felica; + +typedef struct { + byte abtAtqb[12]; + byte abtId[4]; + byte btParam1; + byte btParam2; + byte btParam3; + byte btParam4; + byte btCid; + ui32 uiInfLen; + byte abtInf[64]; +}tag_info_iso14443b; + +typedef struct { + byte btSensRes[2]; + byte btId[4]; +}tag_info_jewel; + +typedef union { + tag_info_iso14443a tia; + tag_info_felica tif; + tag_info_iso14443b tib; + tag_info_jewel tij; +}tag_info; + +//////////////////////////////////////////////////////////////////// +// InDataExchange, MIFARE Classic card typedef enum { MC_AUTH_A = 0x60, @@ -45,25 +131,29 @@ typedef enum { MC_DECREMENT = 0xC0, MC_INCREMENT = 0xC1, MC_STORE = 0xC2, -}MifareCmd; +}mifare_cmd; +// MIFARE Classic command params typedef struct { byte abtKey[6]; byte abtUid[4]; -}MifareParamAuth; +}mifare_param_auth; typedef struct { byte abtData[16]; -}MifareParamData; +}mifare_param_data; typedef struct { byte abtValue[4]; -}MifareParamValue; +}mifare_param_value; typedef union { - MifareParamAuth mpa; - MifareParamData mpd; - MifareParamValue mpv; -}MifareParam; + mifare_param_auth mpa; + mifare_param_data mpd; + mifare_param_value mpv; +}mifare_param; + +// Reset struct alignment to default +#pragma pack() #endif // _LIBNFC_TYPES_H_ diff --git a/win32/anticol.vcproj b/win32/anticol.vcproj index 3e27c8a..b96d8d3 100644 --- a/win32/anticol.vcproj +++ b/win32/anticol.vcproj @@ -1,7 +1,7 @@ - - - - @@ -195,6 +191,26 @@ RelativePath="..\defines.h" > + + + + + + + + + + diff --git a/win32/list.vcproj b/win32/list.vcproj index d329b0a..69a3dae 100644 --- a/win32/list.vcproj +++ b/win32/list.vcproj @@ -1,7 +1,7 @@ $ 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 Yvwd6t9`ClkzMXsS9U3YQ{u=ZD2WE@=x&QzG diff --git a/win32bin/libnfc.dll b/win32bin/libnfc.dll deleted file mode 100644 index d0cd5bf6e21c9bf47f04bf8fa1d4cdad3a9274c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15360 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 YumU}dk0E-QUarr^TABBM@$U4$01CWYivR!s diff --git a/win32bin/libnfc.lib b/win32bin/libnfc.lib deleted file mode 100644 index 060ad6d6df8032addc191bf11c7af825d0136aad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8896 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 diff --git a/win32bin/mfread.exe b/win32bin/mfread.exe deleted file mode 100644 index ba3331a0316cccdcf69376cf7963b278592537c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8192 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 V@*BOI8XC52f2_Sd)A_#`|2GkNS%Uxo diff --git a/win32bin/mfwrite.exe b/win32bin/mfwrite.exe deleted file mode 100644 index 12f31457fbd75dba2a6eb6feeefd152b2409a1bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8192 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 diff --git a/win32bin/relay.exe b/win32bin/relay.exe deleted file mode 100644 index 7f1050face88dfb9e24a1e4b63057171b9bbed0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7680 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 diff --git a/win32bin/simulate.exe b/win32bin/simulate.exe deleted file mode 100644 index 5eef268486dad5e556492d29b61f8edc9b094769..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7168 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 E0{q~^;{X5v