From 7e221462a0819ddf67b83885fa3d35b73e6c552d Mon Sep 17 00:00:00 2001 From: Roel Verdult Date: Wed, 29 Apr 2009 12:51:13 +0000 Subject: [PATCH] updating svn mess --- acr122.c | 187 ------------- dev_acr122.c | 269 ++++++++++++++++++ dev_acr122.h | 39 +++ dev_pn531.c | 247 ++++++++++++++++ acr122.h => dev_pn531.h | 57 ++-- mfread.c | 225 --------------- mftool.c | 374 +++++++++++++++++++++++++ mfwrite.c | 232 --------------- win32/{mfread.vcproj => mftool.vcproj} | 10 +- win32/mfwrite.vcproj | 185 ------------ 10 files changed, 962 insertions(+), 863 deletions(-) delete mode 100644 acr122.c create mode 100644 dev_acr122.c create mode 100644 dev_acr122.h create mode 100644 dev_pn531.c rename acr122.h => dev_pn531.h (60%) delete mode 100644 mfread.c create mode 100644 mftool.c delete mode 100644 mfwrite.c rename win32/{mfread.vcproj => mftool.vcproj} (89%) delete mode 100644 win32/mfwrite.vcproj diff --git a/acr122.c b/acr122.c deleted file mode 100644 index edd5525..0000000 --- a/acr122.c +++ /dev/null @@ -1,187 +0,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 "acr122.h" -#include "bitutils.h" - -#define SCARD_OPERATION_SUCCESS 0x61 -#define SCARD_OPERATION_ERROR 0x63 - -#define FIRMWARE_TEXT "ACR122U10" // ACR122U101(ACS), ACR122U102(Tikitag) - -#define ACR122_WRAP_LEN 5 -#define ACR122_COMMAND_LEN 266 - -#define ACR122_RESPONSE_LEN 268 - -#define MAX_READERS 16 - -static SCARDCONTEXT hCtx = null; - -static byte abtTxBuf[ACR122_WRAP_LEN+ACR122_COMMAND_LEN] = { 0xFF, 0x00, 0x00, 0x00 }; -static byte abtRxCmd[5] = { 0xFF,0xC0,0x00,0x00 }; -static byte uiRxCmdLen = sizeof(abtRxCmd); -static byte abtRxBuf[ACR122_RESPONSE_LEN]; -static ulong ulRxBufLen; -static byte abtGetFw[5] = { 0xFF,0x00,0x48,0x00,0x00 }; -static byte abtLed[9] = { 0xFF,0x00,0x40,0x05,0x04,0x00,0x00,0x00,0x00 }; - -dev_id acr122_connect(const ui32 uiDeviceIndex) -{ - SCARDHANDLE hCard = null; - char* pacReaders[MAX_READERS]; - char acList[256+64*MAX_READERS]; - ulong ulListLen = sizeof(acList); - ulong ulActiveProtocol = 0; - ui32 uiPos; - ui32 uiReaderCount; - ui32 uiReader; - ui32 uiReaderIndex; - - // Clear the reader list - memset(acList,0x00,ulListLen); - - // Test if context succeeded - if (SCardEstablishContext(SCARD_SCOPE_USER,null,null,&hCtx) != SCARD_S_SUCCESS) return INVALID_DEVICE_ID; - - // Retrieve the string array of all available pcsc readers - if (SCardListReaders(hCtx,null,acList,(void*)&ulListLen) != SCARD_S_SUCCESS) return INVALID_DEVICE_ID; - - pacReaders[0] = acList; - uiReaderCount = 1; - for (uiPos=0; uiPos ACR122_COMMAND_LEN) return false; - - // Store the length of the command we are going to send - abtTxBuf[4] = uiTxLen; - - #ifdef _LIBNFC_VERBOSE_ - printf("Tx: "); - print_hex(pbtTx,uiTxLen); - #endif - // Prepare and transmit the send buffer - memcpy(abtTxBuf+5,pbtTx,uiTxLen); - ulRxBufLen = sizeof(abtRxBuf); - if (SCardTransmit((SCARDHANDLE)di,SCARD_PCI_T0,abtTxBuf,uiTxLen+5,null,abtRxBuf,(void*)&ulRxBufLen) != SCARD_S_SUCCESS) return false; - - // Make sure we received the byte-count we expected - if (ulRxBufLen != 2) return false; - - // Check if the operation was successful, so an answer is available - if (*abtRxBuf == SCARD_OPERATION_ERROR) return false; - - // Retrieve the response bytes - abtRxCmd[4] = abtRxBuf[1]; - ulRxBufLen = sizeof(abtRxBuf); - if (SCardTransmit((SCARDHANDLE)di,SCARD_PCI_T0,abtRxCmd,uiRxCmdLen,null,abtRxBuf,(void*)&ulRxBufLen) != SCARD_S_SUCCESS) return false; - - // When the answer should be ignored, just return true - if (pbtRx == null || puiRxLen == null) return true; - - // Make sure we have an emulated answer that fits the return buffer - if (ulRxBufLen < 4 || (ulRxBufLen-4) > *puiRxLen) return false; - - // Wipe out the 4 APDU emulation bytes: D5 4B .. .. .. 90 00 - *puiRxLen = ulRxBufLen-4; - memcpy(pbtRx,abtRxBuf+2,*puiRxLen); - #ifdef _LIBNFC_VERBOSE_ - printf("Rx: "); - print_hex(pbtRx,*puiRxLen); - #endif - - // Transmission went successful - return true; -} - -char* acr122_firmware(const dev_id di) -{ - static char abtFw[11]; - ulong ulFwLen = sizeof(abtFw); - memset(abtFw,0x00,ulFwLen); - SCardTransmit((SCARDHANDLE)di,SCARD_PCI_T0,abtGetFw,sizeof(abtGetFw),null,(byte*)abtFw,(void*)&ulFwLen); - return abtFw; -} - -bool acr122_led_red(const dev_id di, bool bOn) -{ - byte abtBuf[2]; - ulong ulBufLen = sizeof(abtBuf); - return (SCardTransmit((SCARDHANDLE)di,SCARD_PCI_T0,abtLed,sizeof(abtLed),null,(byte*)abtBuf,(void*)&ulBufLen) == SCARD_S_SUCCESS); -} - diff --git a/dev_acr122.c b/dev_acr122.c new file mode 100644 index 0000000..b8bb640 --- /dev/null +++ b/dev_acr122.c @@ -0,0 +1,269 @@ +/* + +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 "defines.h" + +#include +#include +#include +#include +#include "dev_acr122.h" +#include "bitutils.h" + +// WINDOWS: #define IOCTL_CCID_ESCAPE_SCARD_CTL_CODE SCARD_CTL_CODE(3500) +#define IOCTL_CCID_ESCAPE_SCARD_CTL_CODE (((0x31) << 16) | ((3500) << 2)) +#define SCARD_OPERATION_SUCCESS 0x61 +#define SCARD_OPERATION_ERROR 0x63 + +#ifndef SCARD_PROTOCOL_UNDEFINED + #define SCARD_PROTOCOL_UNDEFINED SCARD_PROTOCOL_UNSET +#endif + +#define FIRMWARE_TEXT "ACR122U" // Tested on: ACR122U101(ACS), ACR122U102(Tikitag), ACR122U203(ACS) + +#define ACR122_WRAP_LEN 5 +#define ACR122_COMMAND_LEN 266 +#define ACR122_RESPONSE_LEN 268 +#define MAX_READERS 16 + +typedef struct { + SCARDCONTEXT hCtx; + SCARDHANDLE hCard; + SCARD_IO_REQUEST ioCard; +} dev_spec_acr122; + +static byte abtTxBuf[ACR122_WRAP_LEN+ACR122_COMMAND_LEN] = { 0xFF, 0x00, 0x00, 0x00 }; +static byte abtRxCmd[5] = { 0xFF,0xC0,0x00,0x00 }; +static byte uiRxCmdLen = sizeof(abtRxCmd); +static byte abtRxBuf[ACR122_RESPONSE_LEN]; +static ulong ulRxBufLen; +static byte abtGetFw[5] = { 0xFF,0x00,0x48,0x00,0x00 }; +static byte abtLed[9] = { 0xFF,0x00,0x40,0x05,0x04,0x00,0x00,0x00,0x00 }; + +dev_info* dev_acr122_connect(const ui32 uiIndex) +{ + char* pacReaders[MAX_READERS]; + char acList[256+64*MAX_READERS]; + ulong ulListLen = sizeof(acList); + ui32 uiPos; + ui32 uiReaderCount; + ui32 uiReader; + ui32 uiDevIndex; + dev_info* pdi; + dev_spec_acr122* pdsa; + dev_spec_acr122 dsa; + char* pcFirmware; + + // Clear the reader list + memset(acList,0x00,ulListLen); + + // Test if context succeeded + if (SCardEstablishContext(SCARD_SCOPE_USER,null,null,&(dsa.hCtx)) != SCARD_S_SUCCESS) return INVALID_DEVICE_INFO; + + // Retrieve the string array of all available pcsc readers + if (SCardListReaders(dsa.hCtx,null,acList,(void*)&ulListLen) != SCARD_S_SUCCESS) return INVALID_DEVICE_INFO; + + #ifdef _LIBNFC_VERBOSE_ + printf("Found the following PCSC device(s)\n"); + printf("- %s\n",acList); + #endif + + pacReaders[0] = acList; + uiReaderCount = 1; + for (uiPos=0; uiPos2.0 + if (SCardConnect(dsa.hCtx,pacReaders[uiReader],SCARD_SHARE_DIRECT,0,&(dsa.hCard),(void*)&(dsa.ioCard.dwProtocol)) != SCARD_S_SUCCESS) + { + // We can not connect to this device, we will just ignore it + continue; + } + } + // Configure I/O settings for card communication + dsa.ioCard.cbPciLength = sizeof(SCARD_IO_REQUEST); + + // Retrieve the current firmware version + pcFirmware = dev_acr122_firmware((dev_info*)&dsa); + if (strstr(pcFirmware,FIRMWARE_TEXT) != null) + { + // We found a occurence, test if it has the right index + if (uiDevIndex != 0) + { + // Let's look for the next reader + uiDevIndex--; + continue; + } + + // Allocate memory and store the device specification + pdsa = malloc(sizeof(dev_spec_acr122)); + *pdsa = dsa; + + // Done, we found the reader we are looking for + pdi = malloc(sizeof(dev_info)); + strcpy(pdi->acName,pcFirmware); + pdi->ct = CT_PN532; + pdi->ds = (dev_spec)pdsa; + pdi->bActive = true; + pdi->bCrc = true; + pdi->bPar = true; + pdi->ui8TxBits = 0; + return pdi; + } + } + + // Too bad, the reader could not be located; + return INVALID_DEVICE_INFO; +} + +void dev_acr122_disconnect(dev_info* pdi) +{ + dev_spec_acr122* pdsa = (dev_spec_acr122*)pdi->ds; + SCardDisconnect(pdsa->hCard,SCARD_LEAVE_CARD); + SCardReleaseContext(pdsa->hCtx); + free(pdsa); + free(pdi); +} + +bool dev_acr122_transceive(const dev_spec ds, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen) +{ + dev_spec_acr122* pdsa = (dev_spec_acr122*)ds; + + // Make sure the command does not overflow the send buffer + if (uiTxLen > ACR122_COMMAND_LEN) return false; + + // Store the length of the command we are going to send + abtTxBuf[4] = uiTxLen; + + // Prepare and transmit the send buffer + memcpy(abtTxBuf+5,pbtTx,uiTxLen); + ulRxBufLen = sizeof(abtRxBuf); + #ifdef _LIBNFC_VERBOSE_ + printf("Tx: "); + print_hex(abtTxBuf,uiTxLen+5); + #endif + + if (pdsa->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED) + { + if (SCardControl(pdsa->hCard,IOCTL_CCID_ESCAPE_SCARD_CTL_CODE,abtTxBuf,uiTxLen+5,abtRxBuf,ulRxBufLen,(void*)&ulRxBufLen) != SCARD_S_SUCCESS) return false; + } else { + if (SCardTransmit(pdsa->hCard,&(pdsa->ioCard),abtTxBuf,uiTxLen+5,null,abtRxBuf,(void*)&ulRxBufLen) != SCARD_S_SUCCESS) return false; + } + + if (pdsa->ioCard.dwProtocol == SCARD_PROTOCOL_T0) + { + // Make sure we received the byte-count we expected + if (ulRxBufLen != 2) return false; + + // Check if the operation was successful, so an answer is available + if (*abtRxBuf == SCARD_OPERATION_ERROR) return false; + + // Retrieve the response bytes + abtRxCmd[4] = abtRxBuf[1]; + ulRxBufLen = sizeof(abtRxBuf); + if (SCardTransmit(pdsa->hCard,&(pdsa->ioCard),abtRxCmd,uiRxCmdLen,null,abtRxBuf,(void*)&ulRxBufLen) != SCARD_S_SUCCESS) return false; + } + + #ifdef _LIBNFC_VERBOSE_ + printf("Rx: "); + print_hex(abtRxBuf,ulRxBufLen); + #endif + + // When the answer should be ignored, just return a succesful result + if (pbtRx == null || puiRxLen == null) return true; + + // Make sure we have an emulated answer that fits the return buffer + if (ulRxBufLen < 4 || (ulRxBufLen-4) > *puiRxLen) return false; + // Wipe out the 4 APDU emulation bytes: D5 4B .. .. .. 90 00 + *puiRxLen = ulRxBufLen-4; + memcpy(pbtRx,abtRxBuf+2,*puiRxLen); + + // Transmission went successful + return true; +} + +char* dev_acr122_firmware(const dev_spec ds) +{ + ui32 uiResult; + + dev_spec_acr122* pdsa = (dev_spec_acr122*)ds; + static char abtFw[11]; + ulong ulFwLen = sizeof(abtFw); + memset(abtFw,0x00,ulFwLen); + if (pdsa->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED) + { + uiResult = SCardControl(pdsa->hCard,IOCTL_CCID_ESCAPE_SCARD_CTL_CODE,abtGetFw,sizeof(abtGetFw),abtFw,ulFwLen,(void*)&ulFwLen); + } else { + uiResult = SCardTransmit(pdsa->hCard,&(pdsa->ioCard),abtGetFw,sizeof(abtGetFw),null,(byte*)abtFw,(void*)&ulFwLen); + } + + #ifdef _LIBNFC_VERBOSE_ + if (uiResult != SCARD_S_SUCCESS) + { + printf("No ACR122 firmware received, Error: %08x\n",uiResult); + } + #endif + + return abtFw; +} + +bool dev_acr122_led_red(const dev_spec ds, bool bOn) +{ + dev_spec_acr122* pdsa = (dev_spec_acr122*)ds; + byte abtBuf[2]; + ulong ulBufLen = sizeof(abtBuf); + if (pdsa->ioCard.dwProtocol == SCARD_PROTOCOL_UNDEFINED) + { + return (SCardControl(pdsa->hCard,IOCTL_CCID_ESCAPE_SCARD_CTL_CODE,abtLed,sizeof(abtLed),abtBuf,ulBufLen,(void*)&ulBufLen) == SCARD_S_SUCCESS); + } else { + return (SCardTransmit(pdsa->hCard,&(pdsa->ioCard),abtLed,sizeof(abtLed),null,(byte*)abtBuf,(void*)&ulBufLen) == SCARD_S_SUCCESS); + } +} + diff --git a/dev_acr122.h b/dev_acr122.h new file mode 100644 index 0000000..95c763d --- /dev/null +++ b/dev_acr122.h @@ -0,0 +1,39 @@ +/* + +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_DEV_ACR122_H_ +#define _LIBNFC_DEV_ACR122_H_ + +#include "defines.h" +#include "types.h" + +// Functions used by developer to handle connection to this device +dev_info* dev_acr122_connect(const ui32 uiIndex); +void dev_acr122_disconnect(dev_info* pdi); + +// Callback function used by libnfc to transmit commands to the PN53X chip +bool dev_acr122_transceive(const dev_spec ds, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen); + +// Various additional features this device supports +char* dev_acr122_firmware(const dev_spec ds); +bool dev_acr122_led_red(const dev_spec ds, bool bOn); + +#endif // _LIBNFC_DEV_ACR122_H_ + diff --git a/dev_pn531.c b/dev_pn531.c new file mode 100644 index 0000000..0a8a1b8 --- /dev/null +++ b/dev_pn531.c @@ -0,0 +1,247 @@ +/* + +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 . + +Thanks to d18c7db and Okko for example code + +*/ + +#include "defines.h" + +#include +#include +#include +#include "dev_pn531.h" +#include "bitutils.h" + +#define BUFFER_LENGTH 256 +#define USB_TIMEOUT 30000 +static char buffer[BUFFER_LENGTH] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff" + +typedef struct { + usb_dev_handle* pudh; + ui32 uiEndPointIn; + ui32 uiEndPointOut; +} dev_spec_pn531; + +// Find transfer endpoints for bulk transfers +void get_end_points(struct usb_device *dev, dev_spec_pn531* pdsp) +{ + ui32 uiIndex; + ui32 uiEndPoint; + struct usb_interface_descriptor* puid = dev->config->interface->altsetting; + + // 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out + for(uiIndex = 0; uiIndex < puid->bNumEndpoints; uiIndex++) + { + // Only accept bulk transfer endpoints (ignore interrupt endpoints) + if(puid->endpoint[uiIndex].bmAttributes != USB_ENDPOINT_TYPE_BULK) continue; + + // Copy the endpoint to a local var, makes it more readable code + uiEndPoint = puid->endpoint[uiIndex].bEndpointAddress; + + // Test if we dealing with a bulk IN endpoint + if((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN) + { + #ifdef _LIBNFC_VERBOSE_ + printf("Bulk endpoint in : 0x%02X\n", uiEndPoint); + #endif + pdsp->uiEndPointIn = uiEndPoint; + } + + // Test if we dealing with a bulk OUT endpoint + if((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT) + { + #ifdef _LIBNFC_VERBOSE_ + printf("Bulk endpoint in : 0x%02X\n", uiEndPoint); + #endif + pdsp->uiEndPointOut = uiEndPoint; + } + } +} + +dev_info* dev_pn531_connect(const ui32 uiIndex) +{ + int idvendor = 0x04CC; + int idproduct = 0x0531; + struct usb_bus *bus; + struct usb_device *dev; + dev_info* pdi = INVALID_DEVICE_INFO; + dev_spec_pn531* pdsp; + dev_spec_pn531 dsp; + ui32 uiDevIndex; + + dsp.uiEndPointIn = 0; + dsp.uiEndPointOut = 0; + dsp.pudh = null; + + usb_init(); + if (usb_find_busses() < 0) return INVALID_DEVICE_INFO; + if (usb_find_devices() < 0) return INVALID_DEVICE_INFO; + + // Initialize the device index we are seaching for + uiDevIndex = uiIndex; + + for (bus = usb_get_busses(); bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) + { + if (idvendor==dev->descriptor.idVendor && idproduct==dev->descriptor.idProduct) + { + // Make sure there are 2 endpoints available + if (dev->config->interface->altsetting->bNumEndpoints < 2) return pdi; + + // Test if we are looking for this device according to the current index + if (uiDevIndex != 0) + { + // Nope, we maybe want the next one, let's try to find another + uiDevIndex--; + continue; + } + #ifdef _LIBNFC_VERBOSE_ + printf("Found PN531 device\n"); + #endif + + // Open the PN531 USB device + dsp.pudh = usb_open(dev); + + get_end_points(dev,&dsp); + if(usb_set_configuration(dsp.pudh,1) < 0) + { + #ifdef _LIBNFC_VERBOSE_ + printf("Setting config failed\n"); + #endif + usb_close(dsp.pudh); + return INVALID_DEVICE_INFO; + } + + if(usb_claim_interface(dsp.pudh,0) < 0) + { + #ifdef _LIBNFC_VERBOSE_ + printf("Can't claim interface\n"); + #endif + usb_close(dsp.pudh); + return INVALID_DEVICE_INFO; + } + // Allocate memory for the device info and specification, fill it and return the info + pdsp = malloc(sizeof(dev_spec_pn531)); + *pdsp = dsp; + pdi = malloc(sizeof(dev_info)); + strcpy(pdi->acName,"PN531USB"); + pdi->ct = CT_PN531; + pdi->ds = (dev_spec)pdsp; + pdi->bActive = true; + pdi->bCrc = true; + pdi->bPar = true; + pdi->ui8TxBits = 0; + return pdi; + } + } + } + return pdi; +} + +void dev_pn531_disconnect(dev_info* pdi) +{ + dev_spec_pn531* pdsp = (dev_spec_pn531*)pdi->ds; + usb_release_interface(pdsp->pudh,0); + usb_close(pdsp->pudh); + free(pdi->ds); + free(pdi); +} + +bool dev_pn531_transceive(const dev_spec ds, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen) +{ + ui32 uiPos = 0; + int ret = 0; + char buf[BUFFER_LENGTH]; + dev_spec_pn531* pdsp = (dev_spec_pn531*)ds; + + // Packet length = data length (len) + checksum (1) + end of stream marker (1) + buffer[3] = uiTxLen; + // Packet length checksum + buffer[4] = BUFFER_LENGTH - buffer[3]; + // Copy the PN53X command into the packet buffer + memmove(buffer+5,pbtTx,uiTxLen); + + // Calculate data payload checksum + buffer[uiTxLen+5] = 0; + for(uiPos=0; uiPos < uiTxLen; uiPos++) + { + buffer[uiTxLen+5] -= buffer[uiPos+5]; + } + + // End of stream marker + buffer[uiTxLen+6] = 0; + + #ifdef _LIBNFC_VERBOSE_ + printf("Tx: "); + print_hex((byte*)buffer,uiTxLen+7); + #endif + + ret = usb_bulk_write(pdsp->pudh, pdsp->uiEndPointOut, buffer, uiTxLen+7, USB_TIMEOUT); + if( ret < 0 ) + { + #ifdef _LIBNFC_VERBOSE_ + printf("usb_bulk_write failed with error %d\n", ret); + #endif + return false; + } + + ret = usb_bulk_read(pdsp->pudh, pdsp->uiEndPointIn, buf, BUFFER_LENGTH, USB_TIMEOUT); + if( ret < 0 ) + { + #ifdef _LIBNFC_VERBOSE_ + printf( "usb_bulk_read failed with error %d\n", ret); + #endif + return false; + } + + #ifdef _LIBNFC_VERBOSE_ + printf("Rx: "); + print_hex((byte*)buf,ret); + #endif + + if( ret == 6 ) + { + ret = usb_bulk_read(pdsp->pudh, pdsp->uiEndPointIn, buf, BUFFER_LENGTH, USB_TIMEOUT); + if( ret < 0 ) + { + #ifdef _LIBNFC_VERBOSE_ + printf("usb_bulk_read failed with error %d\n", ret); + #endif + return false; + } + + #ifdef _LIBNFC_VERBOSE_ + printf("Rx: "); + print_hex((byte*)buf,ret); + #endif + } + + // When the answer should be ignored, just return a succesful result + if(pbtRx == null || puiRxLen == null) return true; + + // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable) + if(ret < 9) return false; + + // Remove the preceding and appending bytes 00 00 FF xx Fx .. .. .. xx 00 (x = variable) + *puiRxLen = ret - 7 - 2; + memcpy( pbtRx, buf + 7, *puiRxLen); + + return true; +} diff --git a/acr122.h b/dev_pn531.h similarity index 60% rename from acr122.h rename to dev_pn531.h index d2c7786..65419c4 100644 --- a/acr122.h +++ b/dev_pn531.h @@ -1,36 +1,35 @@ -/* - -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_ACR122_H_ -#define _LIBNFC_ACR122_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_DEV_PN531_H_ +#define _LIBNFC_DEV_PN531_H_ #include "defines.h" #include "types.h" -dev_id acr122_connect(const ui32 uiDeviceIndex); -void acr122_disconnect(const dev_id di); -bool acr122_transceive(const dev_id di, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen); -bool acr122_transceive_(const dev_id di, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen); +// Functions used by developer to handle connection to this device +dev_info* dev_pn531_connect(const ui32 uiIndex); +void dev_pn531_disconnect(dev_info* pdi); -char* acr122_firmware(const dev_id di); -bool acr122_led_red(const dev_id di, bool bOn); +// Callback function used by libnfc to transmit commands to the PN53X chip +bool dev_pn531_transceive(const dev_spec ds, const byte* pbtTx, const ui32 uiTxLen, byte* pbtRx, ui32* puiRxLen); -#endif // _LIBNFC_ACR122_H_ +#endif // _LIBNFC_DEV_PN531_H_ diff --git a/mfread.c b/mfread.c deleted file mode 100644 index ce0ad2f..0000000 --- a/mfread.c +++ /dev/null @@ -1,225 +0,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 . - -*/ - -#define _CRT_SECURE_NO_WARNINGS - -#include -#include -#include - -#include "libnfc.h" -#include "mifaretag.h" - -static byte abtRecv[MAX_FRAME_LEN]; -static ui32 uiRecvLen; -static dev_id di; -static MifareParam mp; -static MifareTag mtKeys; -static MifareTag mtDump; - -bool is_trailer_block(ui32 uiBlock) -{ - // Test if we are in the small or big sectors - if (uiBlock < 128) return ((uiBlock+1)%4 == 0); else return ((uiBlock+1)%16 == 0); -} - -ui32 get_trailer_block(ui32 uiSector) -{ - // Test if we are in the small or big sectors - if (uiSector<32) - { - return (uiSector*4)+3; - } else { - return 128+((uiSector-32)*16)+15; - } -} - -int main(int argc, const char* argv[]) -{ - bool b4K; - bool bKeyA; - byte* pbtUID; - bool bFailure; - i32 iBlock; - ui32 uiBlocks; - FILE* pfKeys; - FILE* pfDump; - MifareCmd mc; - - if (argc < 4) - { - printf("mfread \n"); - printf("\n"); - return 1; - } - - bKeyA = (*(argv[1]) == 'a'); - - pfKeys = fopen(argv[2],"rb"); - if (pfKeys == null) - { - printf("Could not open file: %s\n",argv[2]); - return 1; - } - fread(&mtKeys,1,sizeof(mtKeys),pfKeys); - fclose(pfKeys); - - pfDump = fopen(argv[3],"wb"); - if (pfKeys == null) - { - printf("Could not open file: %s\n",argv[3]); - return 1; - } - memset(&mtDump,0x00,sizeof(mtDump)); - printf("Succesful opened MIFARE dump files\n"); - - // 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 - nfc_configure_handle_crc(di,true); - nfc_configure_handle_parity(di,true); - printf("Connected to NFC reader\n"); - - // MIFARE Classic tag info = ( tag_count[1], tag_nr[1], ATQA[2], SAK[1], uid_len[1], UID[uid_len] ) - uiRecvLen = MAX_FRAME_LEN; - if (!nfc_reader_list_passive(di,MT_ISO14443A_106,null,null,abtRecv,&uiRecvLen)) - { - printf("Error: no tag was found\n"); - return 1; - } - - // Test if we are dealing with a MIFARE compatible tag - if ((abtRecv[4] & 0x08) == 0) - { - printf("Error: tag is not a MIFARE Classic card\n"); - return 1; - } - - // Get the info from the key dump - b4K = (mtKeys.blContent[0].bm.abtATQA[0] == 0x02); - pbtUID = mtKeys.blContent[0].bm.abtUID; - - // Compare if key dump UID is the same as the current tag UID - if (memcmp(abtRecv+6,pbtUID,4) != 0) - { - printf("Expected MIFARE Classic %cK card with uid: %08x\n",b4K?'4':'1',swap_endian32(pbtUID)); - } - - // Get the info from the current tag - pbtUID = abtRecv+6; - b4K = (abtRecv[3] == 0x02); - printf("Found MIFARE Classic %cK card with uid: %08x\n",b4K?'4':'1',swap_endian32(pbtUID)); - - uiBlocks = (b4K)?0xff:0x3f; - bFailure = false; - printf("Reading out %d blocks |",uiBlocks+1); - - // Read the card from end to begin - for (iBlock=uiBlocks; iBlock>=0; iBlock--) - { - // Authenticate everytime we reach a trailer block - if (is_trailer_block(iBlock)) - { - // Show if the readout went well - if (bFailure) - { - printf("x"); - // When a failure occured we need to redo the anti-collision - if (!nfc_reader_list_passive(di,MT_ISO14443A_106,null,null,abtRecv,&uiRecvLen)) - { - printf("!\nError: tag was removed\n"); - return 1; - } - bFailure = false; - } else { - // Skip this the first time, bFailure it means nothing (yet) - if (iBlock != uiBlocks) - { - printf("."); - } - } - fflush(stdout); - - // Set the authentication information (uid) - memcpy(mp.mpa.abtUid,abtRecv+6,4); - - // Determin if we should use the a or the b key - if (bKeyA) - { - mc = MC_AUTH_A; - memcpy(mp.mpa.abtKey,mtKeys.blContent[iBlock].bt.abtKeyA,6); - } else { - mc = MC_AUTH_B; - memcpy(mp.mpa.abtKey,mtKeys.blContent[iBlock].bt.abtKeyB,6); - } - - // Try to authenticate for the current sector - if (!nfc_reader_mifare_cmd(di,MC_AUTH_A,iBlock,&mp)) - { - printf("!\nError: authentication failed for block %02x\n",iBlock); - return 1; - } - - // Try to read out the trailer - if (nfc_reader_mifare_cmd(di,MC_READ,iBlock,&mp)) - { - // Copy the keys over from our key dump and store the retrieved access bits - memcpy(mtDump.blContent[iBlock].bd.abtContent,mtKeys.blContent[iBlock].bt.abtKeyA,6); - memcpy(mtDump.blContent[iBlock].bt.abtAccessBits,mp.mpd.abtData+6,4); - memcpy(mtDump.blContent[iBlock].bd.abtContent+10,mtKeys.blContent[iBlock].bt.abtKeyB,6); - } - } else { - // Make sure a earlier readout did not fail - if (!bFailure) - { - // Try to read out the data block - if (nfc_reader_mifare_cmd(di,MC_READ,iBlock,&mp)) - { - memcpy(mtDump.blContent[iBlock].bd.abtContent,mp.mpd.abtData,16); - } else { - bFailure = true; - } - } - } - } - printf("%c|\n",(bFailure)?'x':'.'); - fflush(stdout); - - printf("Writing dump to file: %s\n",argv[3]); - fflush(stdout); - fwrite(&mtDump,1,sizeof(mtDump),pfDump); - fclose(pfKeys); - - printf("Done, all data is dumped!\n"); - - return 0; -} diff --git a/mftool.c b/mftool.c new file mode 100644 index 0000000..fb390d2 --- /dev/null +++ b/mftool.c @@ -0,0 +1,374 @@ +/* + +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 + +#include "libnfc.h" +#include "mifaretag.h" + +static dev_info* pdi; +static tag_info ti; +static mifare_param mp; +static mifare_tag mtKeys; +static mifare_tag mtDump; +static bool bUseKeyA; +static ui32 uiBlocks; + +bool is_first_block(ui32 uiBlock) +{ + // Test if we are in the small or big sectors + if (uiBlock < 128) return ((uiBlock)%4 == 0); else return ((uiBlock)%16 == 0); +} + +bool is_trailer_block(ui32 uiBlock) +{ + // Test if we are in the small or big sectors + if (uiBlock < 128) return ((uiBlock+1)%4 == 0); else return ((uiBlock+1)%16 == 0); +} + +ui32 get_trailer_block(ui32 uiFirstBlock) +{ + // Test if we are in the small or big sectors + if (uiFirstBlock<128) return uiFirstBlock+3; else return uiFirstBlock+15; +} + +bool read_card() +{ + i32 iBlock; + mifare_cmd mc; + bool bFailure = false; + + printf("Reading out %d blocks |",uiBlocks+1); + + // Read the card from end to begin + for (iBlock=uiBlocks; iBlock>=0; iBlock--) + { + // Authenticate everytime we reach a trailer block + if (is_trailer_block(iBlock)) + { + // Show if the readout went well + if (bFailure) + { + printf("x"); + // When a failure occured we need to redo the anti-collision + if (!nfc_reader_select(pdi,IM_ISO14443A_106,null,null,&ti)) + { + printf("!\nError: tag was removed\n"); + return 1; + } + bFailure = false; + } else { + // Skip this the first time, bFailure it means nothing (yet) + if (iBlock != uiBlocks) + { + printf("."); + } + } + fflush(stdout); + + // Set the authentication information (uid) + memcpy(mp.mpa.abtUid,ti.tia.abtUid,4); + + // Determin if we should use the a or the b key + if (bUseKeyA) + { + mc = MC_AUTH_A; + memcpy(mp.mpa.abtKey,mtKeys.amb[iBlock].mbt.abtKeyA,6); + } else { + mc = MC_AUTH_B; + memcpy(mp.mpa.abtKey,mtKeys.amb[iBlock].mbt.abtKeyB,6); + } + + // Try to authenticate for the current sector + if (!nfc_reader_mifare_cmd(pdi,MC_AUTH_A,iBlock,&mp)) + { + printf("!\nError: authentication failed for block %02x\n",iBlock); + return false; + } + + // Try to read out the trailer + if (nfc_reader_mifare_cmd(pdi,MC_READ,iBlock,&mp)) + { + // Copy the keys over from our key dump and store the retrieved access bits + memcpy(mtDump.amb[iBlock].mbt.abtKeyA,mtKeys.amb[iBlock].mbt.abtKeyA,6); + memcpy(mtDump.amb[iBlock].mbt.abtAccessBits,mp.mpd.abtData+6,4); + memcpy(mtDump.amb[iBlock].mbt.abtKeyB,mtKeys.amb[iBlock].mbt.abtKeyB,6); + } + } else { + // Make sure a earlier readout did not fail + if (!bFailure) + { + // Try to read out the data block + if (nfc_reader_mifare_cmd(pdi,MC_READ,iBlock,&mp)) + { + memcpy(mtDump.amb[iBlock].mbd.abtData,mp.mpd.abtData,16); + } else { + bFailure = true; + } + } + } + } + printf("%c|\n",(bFailure)?'x':'.'); + fflush(stdout); + + return true; +} + +bool write_card() +{ + ui32 uiBlock; + ui32 uiTrailerBlock; + bool bFailure = false; + mifare_cmd mc; + + printf("Writing %d blocks |",uiBlocks+1); + + // Write the card from begin to end; + for (uiBlock=0; uiBlock<=uiBlocks; uiBlock++) + { + // Authenticate everytime we reach the first sector of a new block + if (is_first_block(uiBlock)) + { + // Show if the readout went well + if (bFailure) + { + printf("x"); + // When a failure occured we need to redo the anti-collision + if (!nfc_reader_select(pdi,IM_ISO14443A_106,null,null,&ti)) + { + printf("!\nError: tag was removed\n"); + return false; + } + bFailure = false; + } else { + // Skip this the first time, bFailure it means nothing (yet) + if (uiBlock != 0) + { + printf("."); + } + } + fflush(stdout); + + // Locate the trailer (with the keys) used for this sector + uiTrailerBlock = get_trailer_block(uiBlock); + + // Set the authentication information (uid) + memcpy(mp.mpa.abtUid,ti.tia.abtUid,4); + + // Determin if we should use the a or the b key + if (bUseKeyA) + { + mc = MC_AUTH_A; + memcpy(mp.mpa.abtKey,mtKeys.amb[uiTrailerBlock].mbt.abtKeyA,6); + } else { + mc = MC_AUTH_B; + memcpy(mp.mpa.abtKey,mtKeys.amb[uiTrailerBlock].mbt.abtKeyB,6); + } + + // Try to authenticate for the current sector + if (!nfc_reader_mifare_cmd(pdi,mc,uiBlock,&mp)) + { + printf("!\nError: authentication failed for block %02x\n",uiBlock); + return false; + } + } + + if (is_trailer_block(uiBlock)) + { + // Copy the keys over from our key dump and store the retrieved access bits + memcpy(mp.mpd.abtData,mtDump.amb[uiBlock].mbt.abtKeyA,6); + memcpy(mp.mpd.abtData+6,mtDump.amb[uiBlock].mbt.abtAccessBits,4); + memcpy(mp.mpd.abtData+10,mtDump.amb[uiBlock].mbt.abtKeyB,6); + + // Try to write the trailer + nfc_reader_mifare_cmd(pdi,MC_WRITE,uiBlock,&mp); + + } else { + + // The first block 0x00 is read only, skip this + if (uiBlock == 0) continue; + + // Make sure a earlier write did not fail + if (!bFailure) + { + // Try to write the data block + memcpy(mp.mpd.abtData,mtDump.amb[uiBlock].mbd.abtData,16); + if (!nfc_reader_mifare_cmd(pdi,MC_WRITE,uiBlock,&mp)) bFailure = true; + } + } + } + printf("%c|\n",(bFailure)?'x':'.'); + fflush(stdout); + + return true; +} + +int main(int argc, const char* argv[]) +{ + bool b4K; + bool bReadAction; + byte* pbtUID; + FILE* pfKeys; + FILE* pfDump; + + if (argc < 5) + { + printf("\n"); + printf("mftool \n"); + printf("\n"); + printf(" - Perform (read from) or (write to) card\n"); + printf(" - Use A or B keys to for action\n"); + printf(" - Mifare-dump that contain the keys\n"); + printf(" - Used to write (card to file) or (file to card)\n"); + printf("\n"); + return 1; + } + + printf("\nChecking arguments and settings\n"); + + bReadAction = (tolower(*(argv[1])) == 'r'); + bUseKeyA = (tolower(*(argv[2])) == 'a'); + + pfKeys = fopen(argv[3],"rb"); + if (pfKeys == null) + { + printf("Could not open file: %s\n",argv[3]); + return 1; + } + if (fread(&mtKeys,1,sizeof(mtKeys),pfKeys) != sizeof(mtKeys)) + { + printf("Could not read from keys file: %s\n",argv[3]); + fclose(pfKeys); + return 1; + } + fclose(pfKeys); + + if (bReadAction) + { + memset(&mtDump,0x00,sizeof(mtDump)); + } else { + pfDump = fopen(argv[4],"rb"); + + if (pfDump == null) + { + printf("Could not open dump file: %s\n",argv[4]); + return 1; + } + + if (fread(&mtDump,1,sizeof(mtDump),pfDump) != sizeof(mtDump)) + { + printf("Could not read from dump file: %s\n",argv[4]); + fclose(pfDump); + return 1; + } + fclose(pfDump); + } + printf("Succesful opened MIFARE the required files\n"); + + // Try to open the NFC reader + pdi = nfc_connect(); + if (pdi == INVALID_DEVICE_INFO) + { + 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); + + // Let the reader only try once to find a tag + nfc_configure(pdi,DCO_INFINITE_SELECT,false); + nfc_configure(pdi,DCO_HANDLE_CRC,true); + nfc_configure(pdi,DCO_HANDLE_PARITY,true); + + // Enable field so more power consuming cards can power themselves up + nfc_configure(pdi,DCO_ACTIVATE_FIELD,true); + + printf("Connected to NFC reader: %s\n",pdi->acName); + + // Try to find a MIFARE Classic tag + if (!nfc_reader_select(pdi,IM_ISO14443A_106,null,null,&ti)) + { + printf("Error: no tag was found\n"); + nfc_disconnect(pdi); + return 1; + } + + // Test if we are dealing with a MIFARE compatible tag + if ((ti.tia.btSak & 0x08) == 0) + { + printf("Error: tag is not a MIFARE Classic card\n"); + nfc_disconnect(pdi); + return 1; + } + + // Get the info from the key dump + b4K = (mtKeys.amb[0].mbm.abtATQA[1] == 0x02); + pbtUID = mtKeys.amb[0].mbm.abtUID; + + // Compare if key dump UID is the same as the current tag UID + if (memcmp(ti.tia.abtUid,pbtUID,4) != 0) + { + printf("Expected MIFARE Classic %cK card with uid: %08x\n",b4K?'4':'1',swap_endian32(pbtUID)); + } + + // Get the info from the current tag + pbtUID = ti.tia.abtUid; + b4K = (ti.tia.abtAtqa[1] == 0x02); + printf("Found MIFARE Classic %cK card with uid: %08x\n",b4K?'4':'1',swap_endian32(pbtUID)); + + uiBlocks = (b4K)?0xff:0x3f; + + if (bReadAction) + { + if (read_card()) + { + printf("Writing data to file: %s\n",argv[4]); + fflush(stdout); + pfDump = fopen(argv[4],"wb"); + if (pfKeys == null) + { + printf("Could not open file: %s\n",argv[4]); + return 1; + } + if (fwrite(&mtDump,1,sizeof(mtDump),pfDump) != sizeof(mtDump)) + { + printf("Could not write to file: %s\n",argv[4]); + return 1; + } + fclose(pfDump); + printf("Done, all bytes dumped to file!\n"); + } + } else { + if (write_card()) + { + printf("Done, all data is written to the card!\n"); + } + } + + nfc_disconnect(pdi); + + return 0; +} diff --git a/mfwrite.c b/mfwrite.c deleted file mode 100644 index 82e44af..0000000 --- a/mfwrite.c +++ /dev/null @@ -1,232 +0,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 . - -*/ - -#define _CRT_SECURE_NO_WARNINGS - -#include -#include -#include - -#include "libnfc.h" -#include "mifaretag.h" - -static byte abtRecv[MAX_FRAME_LEN]; -static ui32 uiRecvLen; -static dev_id di; -static MifareParam mp; -static MifareTag mtKeys; -static MifareTag mtDump; - -bool is_first_block(ui32 uiBlock) -{ - // Test if we are in the small or big sectors - if (uiBlock < 128) return ((uiBlock)%4 == 0); else return ((uiBlock)%16 == 0); -} - -bool is_trailer_block(ui32 uiBlock) -{ - // Test if we are in the small or big sectors - if (uiBlock < 128) return ((uiBlock+1)%4 == 0); else return ((uiBlock+1)%16 == 0); -} - -ui32 get_trailer_block(ui32 uiFirstBlock) -{ - // Test if we are in the small or big sectors - if (uiFirstBlock<128) return uiFirstBlock+3; else return uiFirstBlock+15; -} - -int main(int argc, const char* argv[]) -{ - bool b4K; - bool bKeyA; - byte* pbtUID; - bool bFailure; - ui32 uiBlock; - ui32 uiBlocks; - ui32 uiTrailerBlock; - FILE* pfKeys; - FILE* pfDump; - MifareCmd mc; - - if (argc < 4) - { - printf("mfwrite \n"); - printf("\n"); - return 1; - } - - bKeyA = (*(argv[1]) == 'a'); - - pfKeys = fopen(argv[2],"rb"); - if (pfKeys == null) - { - printf("Could not open file: %s\n",argv[2]); - return 1; - } - fread(&mtKeys,1,sizeof(mtKeys),pfKeys); - fclose(pfKeys); - - pfDump = fopen(argv[3],"rb"); - if (pfKeys == null) - { - printf("Could not open file: %s\n",argv[3]); - return 1; - } - fread(&mtDump,1,sizeof(mtDump),pfDump); - fclose(pfDump); - printf("Succesful opened MIFARE dump files\n"); - - // 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 - nfc_configure_handle_crc(di,true); - nfc_configure_handle_parity(di,true); - printf("Connected to NFC reader\n"); - - // MIFARE Classic tag info = ( tag_count[1], tag_nr[1], ATQA[2], SAK[1], uid_len[1], UID[uid_len] ) - uiRecvLen = MAX_FRAME_LEN; - if (!nfc_reader_list_passive(di,MT_ISO14443A_106,null,null,abtRecv,&uiRecvLen)) - { - printf("Error: no tag was found\n"); - return 1; - } - - // Test if we are dealing with a MIFARE compatible tag - if ((abtRecv[4] & 0x08) == 0) - { - printf("Error: tag is not a MIFARE Classic card\n"); - return 1; - } - - // Get the info from the key dump - b4K = (mtKeys.blContent[0].bm.abtATQA[0] == 0x02); - pbtUID = mtKeys.blContent[0].bm.abtUID; - - // Compare if key dump UID is the same as the current tag UID - if (memcmp(abtRecv+6,pbtUID,4) != 0) - { - printf("Expected MIFARE Classic %cK card with uid: %08x\n",b4K?'4':'1',swap_endian32(pbtUID)); - } - - // Get the info from the current tag - pbtUID = abtRecv+6; - b4K = (abtRecv[3] == 0x02); - printf("Found MIFARE Classic %cK card with uid: %08x\n",b4K?'4':'1',swap_endian32(pbtUID)); - - uiBlocks = (b4K)?0xff:0x3f; - bFailure = false; - printf("Writing %d blocks |",uiBlocks+1); - - // Write the card from begin to end; - for (uiBlock=0; uiBlock<=uiBlocks; uiBlock++) - { - // Authenticate everytime we reach the first sector of a new block - if (is_first_block(uiBlock)) - { - // Show if the readout went well - if (bFailure) - { - printf("x"); - // When a failure occured we need to redo the anti-collision - if (!nfc_reader_list_passive(di,MT_ISO14443A_106,null,null,abtRecv,&uiRecvLen)) - { - printf("!\nError: tag was removed\n"); - return 1; - } - bFailure = false; - } else { - // Skip this the first time, bFailure it means nothing (yet) - if (uiBlock != 0) - { - printf("."); - } - } - fflush(stdout); - - // Locate the trailer (with the keys) used for this sector - uiTrailerBlock = get_trailer_block(uiBlock); - - // Set the authentication information (uid) - memcpy(mp.mpa.abtUid,abtRecv+6,4); - - // Determin if we should use the a or the b key - if (bKeyA) - { - mc = MC_AUTH_A; - memcpy(mp.mpa.abtKey,mtKeys.blContent[uiTrailerBlock].bt.abtKeyA,6); - } else { - mc = MC_AUTH_B; - memcpy(mp.mpa.abtKey,mtKeys.blContent[uiTrailerBlock].bt.abtKeyB,6); - } - - // Try to authenticate for the current sector - if (!nfc_reader_mifare_cmd(di,mc,uiBlock,&mp)) - { - printf("!\nError: authentication failed for block %02x\n",uiBlock); - return 1; - } - } - - if (is_trailer_block(uiBlock)) - { - // Copy the keys over from our key dump and store the retrieved access bits - memcpy(mp.mpd.abtData,mtDump.blContent[uiBlock].bt.abtKeyA,6); - memcpy(mp.mpd.abtData+6,mtDump.blContent[uiBlock].bt.abtAccessBits,4); - memcpy(mp.mpd.abtData+10,mtDump.blContent[uiBlock].bt.abtKeyB,6); - - // Try to write the trailer - nfc_reader_mifare_cmd(di,MC_WRITE,uiBlock,&mp); - - } else { - - // The first block 0x00 is read only, skip this - if (uiBlock == 0) continue; - - // Make sure a earlier write did not fail - if (!bFailure) - { - // Try to write the data block - memcpy(mp.mpd.abtData,mtDump.blContent[uiBlock].bd.abtContent,16); - if (!nfc_reader_mifare_cmd(di,MC_WRITE,uiBlock,&mp)) - { - bFailure = true; - } - } - } - } - printf("%c|\n",(bFailure)?'x':'.'); - fflush(stdout); - - printf("Done, all data is written!\n"); - - return 0; -} diff --git a/win32/mfread.vcproj b/win32/mftool.vcproj similarity index 89% rename from win32/mfread.vcproj rename to win32/mftool.vcproj index 4db8719..4528069 100644 --- a/win32/mfread.vcproj +++ b/win32/mftool.vcproj @@ -1,8 +1,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -