diff --git a/examples/Makefile.am b/examples/Makefile.am index 7dd8f5a..28f124f 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -5,7 +5,7 @@ INCLUDES= $(all_includes) $(LIBNFC_CFLAGS) AM_CFLAGS = -I$(top_srcdir)/libnfc -noinst_HEADERS = mifaretag.h mifareultag.h nfc-utils.h +noinst_HEADERS = mifare.h nfc-utils.h noinst_LTLIBRARIES = libnfcutils.la libnfcutils_la_SOURCES = nfc-utils.c @@ -22,10 +22,10 @@ nfc_list_SOURCES = nfc-list.c nfc_list_LDADD = $(top_builddir)/libnfc/libnfc.la \ libnfcutils.la -nfc_mfultralight_SOURCES = nfc-mfultralight.c mifareultag.h +nfc_mfultralight_SOURCES = nfc-mfultralight.c mifare.c mifare.h nfc_mfultralight_LDADD = $(top_builddir)/libnfc/libnfc.la -nfc_mfclassic_SOURCES = nfc-mfclassic.c mifaretag.h +nfc_mfclassic_SOURCES = nfc-mfclassic.c mifare.c mifare.h nfc_mfclassic_LDADD = $(top_builddir)/libnfc/libnfc.la nfc_relay_SOURCES = nfc-relay.c diff --git a/examples/mifare.c b/examples/mifare.c new file mode 100644 index 0000000..1deb523 --- /dev/null +++ b/examples/mifare.c @@ -0,0 +1,80 @@ +#include "mifare.h" + +#include + +#include "chips/pn53x.h" + +extern const byte_t pncmd_initiator_exchange_data [265]; + +/** + * @brief Execute a MIFARE Classic Command + * @return Returns true if action was successfully performed; otherwise returns false. + * @param pmp Some commands need additional information. This information should be supplied in the mifare_param union. + * + * The specified MIFARE command will be executed on the tag. There are different commands possible, they all require the destination block number. + * @note There are three different types of information (Authenticate, Data and Value). + * + * First an authentication must take place using Key A or B. It requires a 48 bit Key (6 bytes) and the UID. + * They are both used to initialize the internal cipher-state of the PN53X chip (http://libnfc.org/hardware/pn53x-chip). + * After a successful authentication it will be possible to execute other commands (e.g. Read/Write). + * The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process. + */ +bool nfc_initiator_mifare_cmd(const nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp) +{ + byte_t abtRx[MAX_FRAME_LEN]; + size_t szRxLen; + size_t szParamLen; + byte_t abtCmd[sizeof(pncmd_initiator_exchange_data)]; + memcpy(abtCmd,pncmd_initiator_exchange_data,sizeof(pncmd_initiator_exchange_data)); + + // Make sure we are dealing with a active device + if (!pnd->bActive) return false; + + abtCmd[2] = 0x01; // Use first target/card + abtCmd[3] = mc; // The MIFARE Classic command + abtCmd[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: + szParamLen = 0; + break; + + // Authenticate command + case MC_AUTH_A: + case MC_AUTH_B: + szParamLen = sizeof(mifare_param_auth); + break; + + // Data command + case MC_WRITE: + szParamLen = sizeof(mifare_param_data); + break; + + // Value command + case MC_DECREMENT: + case MC_INCREMENT: + case MC_TRANSFER: + szParamLen = sizeof(mifare_param_value); + break; + + // Please fix your code, you never should reach this statement + default: + return false; + break; + } + + // When available, copy the parameter bytes + if (szParamLen) memcpy(abtCmd+5,(byte_t*)pmp,szParamLen); + + // Fire the mifare command + if (!pn53x_transceive(pnd,abtCmd,5+szParamLen,abtRx,&szRxLen)) return false; + + // When we have executed a read command, copy the received bytes into the param + if (mc == MC_READ && szRxLen == 17) memcpy(pmp->mpd.abtData,abtRx+1,16); + + // Command succesfully executed + return true; +} diff --git a/examples/mifare.h b/examples/mifare.h new file mode 100644 index 0000000..886ebc2 --- /dev/null +++ b/examples/mifare.h @@ -0,0 +1,127 @@ +/** + * Public platform independent Near Field Communication (NFC) library + * + * Copyright (C) 2009, Roel Verdult, 2010, Romuald Conty + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see + * + * + * @file mifaretag.h + * @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc + */ + +#ifndef _LIBNFC_MIFARE_H_ +#define _LIBNFC_MIFARE_H_ + +#include + +// Compiler directive, set struct alignment to 1 byte_t for compatibility +#pragma pack(1) + +typedef enum { + MC_AUTH_A = 0x60, + MC_AUTH_B = 0x61, + MC_READ = 0x30, + MC_WRITE = 0xA0, + MC_TRANSFER = 0xB0, + MC_DECREMENT = 0xC0, + MC_INCREMENT = 0xC1, + MC_STORE = 0xC2 +} mifare_cmd; + +// MIFARE command params +typedef struct { + byte_t abtKey[6]; + byte_t abtUid[4]; +} mifare_param_auth; + +typedef struct { + byte_t abtData[16]; +} mifare_param_data; + +typedef struct { + byte_t abtValue[4]; +} mifare_param_value; + +typedef union { + mifare_param_auth mpa; + mifare_param_data mpd; + mifare_param_value mpv; +} mifare_param; + +// Reset struct alignment to default +#pragma pack() + +bool nfc_initiator_mifare_cmd(const nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp); + +// Compiler directive, set struct alignment to 1 byte_t for compatibility +#pragma pack(1) + +// MIFARE Classic +typedef struct { + byte_t abtUID[4]; + byte_t btBCC; + byte_t btUnknown; + byte_t abtATQA[2]; + byte_t abtUnknown[8]; +} mifare_classic_block_manufacturer; + +typedef struct { + byte_t abtData[16]; +} mifare_classic_block_data; + +typedef struct { + byte_t abtKeyA[6]; + byte_t abtAccessBits[4]; + byte_t abtKeyB[6]; +} mifare_classic_block_trailer; + +typedef union { + mifare_classic_block_manufacturer mbm; + mifare_classic_block_data mbd; + mifare_classic_block_trailer mbt; +} mifare_classic_block; + +typedef struct { + mifare_classic_block amb[256]; +} mifare_classic_tag; + +// MIFARE Ultralight +typedef struct { + byte_t sn0[3]; + byte_t btBCC0; + byte_t sn1[4]; + byte_t btBCC1; + byte_t internal; + byte_t lock[2]; + byte_t otp[4]; +} mifareul_block_manufacturer; + +typedef struct { + byte_t abtData[16]; +} mifareul_block_data; + +typedef union { + mifareul_block_manufacturer mbm; + mifareul_block_data mbd; +} mifareul_block; + +typedef struct { + mifareul_block amb[4]; +} mifareul_tag; + +// Reset struct alignment to default +#pragma pack() + +#endif // _LIBNFC_MIFARE_H_ diff --git a/examples/mifaretag.h b/examples/mifaretag.h deleted file mode 100644 index 32fbaf3..0000000 --- a/examples/mifaretag.h +++ /dev/null @@ -1,55 +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 Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see - * - * - * @file mifaretag.h - * @brief - */ - -#ifndef _LIBNFC_MIFARE_TAG_H_ -#define _LIBNFC_MIFARE_TAG_H_ - -typedef struct { - byte_t abtUID[4]; - byte_t btBCC; - byte_t btUnknown; - byte_t abtATQA[2]; - byte_t abtUnknown[8]; -} mifare_block_manufacturer; - -typedef struct { - byte_t abtData[16]; -} mifare_block_data; - -typedef struct { - byte_t abtKeyA[6]; - byte_t abtAccessBits[4]; - byte_t abtKeyB[6]; -} mifare_block_trailer; - -typedef union { - mifare_block_manufacturer mbm; - mifare_block_data mbd; - mifare_block_trailer mbt; -} mifare_block; - -typedef struct { - mifare_block amb[256]; -} mifare_tag; - -#endif // _LIBNFC_MIFARE_TAG_H_ diff --git a/examples/nfc-mfclassic.c b/examples/nfc-mfclassic.c index f8458db..d186742 100644 --- a/examples/nfc-mfclassic.c +++ b/examples/nfc-mfclassic.c @@ -37,14 +37,14 @@ #include -#include "mifaretag.h" +#include "mifare.h" #include "nfc-utils.h" static nfc_device_t *pnd; static nfc_target_info_t nti; static mifare_param mp; -static mifare_tag mtKeys; -static mifare_tag mtDump; +static mifare_classic_tag mtKeys; +static mifare_classic_tag mtDump; static bool bUseKeyA; static bool bUseKeyFile; static uint8_t uiBlocks; diff --git a/examples/nfc-mfultralight.c b/examples/nfc-mfultralight.c index fe63132..5956b1e 100644 --- a/examples/nfc-mfultralight.c +++ b/examples/nfc-mfultralight.c @@ -37,7 +37,7 @@ #include -#include "mifareultag.h" +#include "mifare.h" #include "nfc-utils.h" static nfc_device_t* pnd; diff --git a/include/nfc/nfc-types.h b/include/nfc/nfc-types.h index 001b22a..61c02c9 100644 --- a/include/nfc/nfc-types.h +++ b/include/nfc/nfc-types.h @@ -279,40 +279,6 @@ typedef struct { nfc_target_type_t ntt; } nfc_target_t; -//////////////////////////////////////////////////////////////////// -// InDataExchange, MIFARE Classic card - -typedef enum { - MC_AUTH_A = 0x60, - MC_AUTH_B = 0x61, - MC_READ = 0x30, - MC_WRITE = 0xA0, - MC_TRANSFER = 0xB0, - MC_DECREMENT = 0xC0, - MC_INCREMENT = 0xC1, - MC_STORE = 0xC2 -}mifare_cmd; - -// MIFARE Classic command params -typedef struct { - byte_t abtKey[6]; - byte_t abtUid[4]; -}mifare_param_auth; - -typedef struct { - byte_t abtData[16]; -}mifare_param_data; - -typedef struct { - byte_t abtValue[4]; -}mifare_param_value; - -typedef union { - mifare_param_auth mpa; - mifare_param_data mpd; - mifare_param_value mpv; -}mifare_param; - // Reset struct alignment to default #pragma pack() diff --git a/include/nfc/nfc.h b/include/nfc/nfc.h index ba920bc..a81913c 100644 --- a/include/nfc/nfc.h +++ b/include/nfc/nfc.h @@ -68,7 +68,6 @@ NFC_EXPORT bool nfc_initiator_poll_targets(const nfc_device_t* pnd, const nfc_ta NFC_EXPORT bool nfc_initiator_transceive_bits(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxBits, const byte_t* pbtTxPar, byte_t* pbtRx, size_t* pszRxBits, byte_t* pbtRxPar); NFC_EXPORT bool nfc_initiator_transceive_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); NFC_EXPORT bool nfc_initiator_transceive_dep_bytes(const nfc_device_t* pnd, const byte_t* pbtTx, const size_t szTxLen, byte_t* pbtRx, size_t* pszRxLen); -NFC_EXPORT bool nfc_initiator_mifare_cmd(const nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp); /* NFC target: act as tag (i.e. MIFARE Classic) or NFC target device. */ NFC_EXPORT bool nfc_target_init(const nfc_device_t* pnd, byte_t* pbtRx, size_t* pszRxBits); diff --git a/libnfc/nfc.c b/libnfc/nfc.c index abb7784..b5ceb88 100644 --- a/libnfc/nfc.c +++ b/libnfc/nfc.c @@ -769,76 +769,6 @@ bool nfc_initiator_transceive_bytes(const nfc_device_t* pnd, const byte_t* pbtTx return true; } -/** - * @brief Execute a MIFARE Classic Command - * @return Returns true if action was successfully performed; otherwise returns false. - * @param pmp Some commands need additional information. This information should be supplied in the mifare_param union. - * - * The specified MIFARE command will be executed on the tag. There are different commands possible, they all require the destination block number. - * @note There are three different types of information (Authenticate, Data and Value). - * - * First an authentication must take place using Key A or B. It requires a 48 bit Key (6 bytes) and the UID. They are both used to initialize the internal cipher-state of the PN53X chip (http://libnfc.org/hardware/pn53x-chip). After a successful authentication it will be possible to execute other commands (e.g. Read/Write). The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process. - */ -bool nfc_initiator_mifare_cmd(const nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp) -{ - byte_t abtRx[MAX_FRAME_LEN]; - size_t szRxLen; - size_t szParamLen; - byte_t abtCmd[sizeof(pncmd_initiator_exchange_data)]; - memcpy(abtCmd,pncmd_initiator_exchange_data,sizeof(pncmd_initiator_exchange_data)); - - // Make sure we are dealing with a active device - if (!pnd->bActive) return false; - - abtCmd[2] = 0x01; // Use first target/card - abtCmd[3] = mc; // The MIFARE Classic command - abtCmd[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: - szParamLen = 0; - break; - - // Authenticate command - case MC_AUTH_A: - case MC_AUTH_B: - szParamLen = sizeof(mifare_param_auth); - break; - - // Data command - case MC_WRITE: - szParamLen = sizeof(mifare_param_data); - break; - - // Value command - case MC_DECREMENT: - case MC_INCREMENT: - case MC_TRANSFER: - szParamLen = sizeof(mifare_param_value); - break; - - // Please fix your code, you never should reach this statement - default: - return false; - break; - } - - // When available, copy the parameter bytes - if (szParamLen) memcpy(abtCmd+5,(byte_t*)pmp,szParamLen); - - // Fire the mifare command - if (!pn53x_transceive(pnd,abtCmd,5+szParamLen,abtRx,&szRxLen)) return false; - - // When we have executed a read command, copy the received bytes into the param - if (mc == MC_READ && szRxLen == 17) memcpy(pmp->mpd.abtData,abtRx+1,16); - - // Command succesfully executed - return true; -} - /** * @brief Initialize NFC device as an emulated tag * @return Returns true if action was successfully performed; otherwise returns false.