diff --git a/AUTHORS b/AUTHORS index 5c4fd2c..24030eb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1 +1,7 @@ += Author Andrei Costin , http://andreicostin.com + += Contributors + +Romuald Conty - porting to libnfc 1.3.x, 1.4.x, 1.5.x +Nethemba Core Team - core AC, AM, configure and packaging diff --git a/README b/README index 051862b..fcb8c00 100644 --- a/README +++ b/README @@ -1,6 +1,15 @@ README ====== +Compiling: + automake + autoconf + ./configure + make + +Running (most basic): + ./mfcuk -C -R 0:A -v 2 + PACKAGE ------- MiFare Classic Universal toolKit (MFCUK) diff --git a/src/bin/libnfc.dll b/bin_old/libnfc.dll similarity index 100% rename from src/bin/libnfc.dll rename to bin_old/libnfc.dll diff --git a/src/bin/libnfc.lib b/bin_old/libnfc.lib similarity index 100% rename from src/bin/libnfc.lib rename to bin_old/libnfc.lib diff --git a/src/bin/mfcuk_keyrecovery_darkside_cygwin.exe b/bin_old/mfcuk_keyrecovery_darkside_cygwin.exe similarity index 100% rename from src/bin/mfcuk_keyrecovery_darkside_cygwin.exe rename to bin_old/mfcuk_keyrecovery_darkside_cygwin.exe diff --git a/src/bin/mfcuk_keyrecovery_darkside_win32.exe b/bin_old/mfcuk_keyrecovery_darkside_win32.exe similarity index 100% rename from src/bin/mfcuk_keyrecovery_darkside_win32.exe rename to bin_old/mfcuk_keyrecovery_darkside_win32.exe diff --git a/configure.ac b/configure.ac index d645258..97dda8d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([mfcuk], [0.3.2], [zveriu@gmail.com]) +AC_INIT([mfcuk], [0.3.3], [zveriu@gmail.com]) AC_CONFIG_MACRO_DIR([m4]) @@ -6,68 +6,27 @@ AC_PROG_CC AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_SRCDIR([src/mfcuk.c]) + AM_INIT_AUTOMAKE m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) -# Checks for libnfc. -WITH_NFC=0 -## Search libnfc with command line option (default prefix: auto) -LIBNFC_PREFIX="auto" -AC_ARG_WITH(libnfc,[--with-libnfc=DIR location of the libnfc], - [if test "$withval" != no; then - if test "$withval" != yes; then - LIBNFC_PREFIX=$withval - fi - fi]) -if test x"$LIBNFC_PREFIX" != "xauto"; then - LIBNFC_CFLAGS="-L$LIBNFC_PREFIX/lib/ -I$LIBNFC_PREFIX/include/" - LIBNFC_LIBS="-lnfc" -fi - -# Search using pkg-config -AC_PATH_PROG(PKG_CONFIG, pkg-config, [AC_MSG_WARN([pkg-config not found.])]) -if test x"$WITH_NFC" = "x0"; then - if test x"$PKG_CONFIG" != "x"; then - LIBNFC_REQUIRED_VERSION=1.5.1 - PKG_CHECK_MODULES([LIBNFC], [libnfc >= $LIBNFC_REQUIRED_VERSION], [WITH_NFC=1], [WITH_NFC=0]) - fi -fi -CFLAGS="$CFLAGS $LIBNFC_CFLAGS" -AC_CHECK_HEADERS([nfc/nfc.h],[WITH_NFC=1], AC_MSG_ERROR([A version of libnfc greater than or equal to $LIBNFC_REQUIRED_VERSION is required])) - -if test x"$WITH_NFC" = "x0"; then - AC_MSG_ERROR([A version of libnfc greater than or equal to $LIBNFC_REQUIRED_VERSION is required.]) -fi - -# Checks for programs. -AC_PROG_CC - -# Checks for libraries. -AC_CHECK_LIB([nfc], [nfc_version]) +# Checks for pkg-config modules. +LIBNFC_REQUIRED_VERSION=1.5.1 +PKG_CHECK_MODULES([LIBNFC], [libnfc >= $LIBNFC_REQUIRED_VERSION], [], [AC_MSG_ERROR([libnfc >= $LIBNFC_REQUIRED_VERSION is mandatory.])]) -# Checks for header files. -AC_CHECK_HEADERS([byteswap.h]) -AC_CHECK_HEADERS([endian.h sys/endian.h CoreFoundation/CoreFoundation.h]) -AC_CHECK_HEADERS([stdint.h stdlib.h string.h sys/time.h unistd.h]) - -AC_DEFINE(_XOPEN_SOURCE, 600, [Enable POSIX extensions if present]) +PKG_CONFIG_REQUIRES="libnfc" +AC_SUBST([PKG_CONFIG_REQUIRES]) # Checks for typedefs, structures, and compiler characteristics. AC_HEADER_STDBOOL -AC_TYPE_SIZE_T -AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T -AC_TYPE_UINT8_T # Checks for library functions. AC_FUNC_MALLOC AC_FUNC_REALLOC -AC_CHECK_FUNCS([memset strchr]) - -# Help us to write great code ;-) -CFLAGS="$CFLAGS -Wall -pedantic -Wextra -std=c99" AC_CONFIG_FILES([Makefile src/Makefile]) diff --git a/src/Makefile.am b/src/Makefile.am index 04137af..4010a4f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,26 +1,9 @@ -bin_PROGRAMS = mfcuk_keyrecovery_darkside +AM_CFLAGS = @LIBNFC_CFLAGS@ +AM_LDFLAGS = @LIBNFC_LIBS@ -noinst_HEADERS = \ - crapto1.h \ - mfcuk_finger.h \ - mfcuk_keyrecovery_darkside.h \ - mfcuk_mifare.h \ - mfcuk_utils.h \ - mifare.h \ - nfc-utils.h \ - xgetopt.h +bin_PROGRAMS = mfcuk -# set the include path found by configure -mfcuk_keyrecovery_darkside_SOURCES = \ - crapto1.c \ - crypto1.c \ - mfcuk_finger.c \ - mfcuk_keyrecovery_darkside.c \ - mfcuk_mifare.c \ - mfcuk_utils.c \ - mifare.c \ - nfc-utils.c +noinst_HEADERS = crapto1.h mifare.h nfc-utils.h mfcuk_mifare.h mfcuk_finger.h mfcuk_utils.h xgetopt.h mfcuk.h +mfcuk_SOURCES = crapto1.c crypto1.c mifare.c nfc-utils.c mfcuk_mifare.c mfcuk_finger.c mfcuk_utils.c xgetopt.c mfcuk.c -mfcuk_keyrecovery_darkside_LDADD = -lnfc -lusb -lpcsclite - -# dist_man_MANS = mfcuk_keyrecovery_darkside.1 +# dist_man_MANS = mfcuk.1 diff --git a/src/crapto1.c b/src/crapto1.c index 38f66c4..ab599a6 100644 --- a/src/crapto1.c +++ b/src/crapto1.c @@ -57,7 +57,7 @@ static void quicksort(uint32_t* const start, uint32_t* const stop) /** binsearch * Binary search for the first occurence of *stop's MSB in sorted [start,stop] */ -static /*inline*/ uint32_t* +static inline uint32_t* binsearch(uint32_t *start, uint32_t *stop) { uint32_t mid, val = *stop & 0xff000000; @@ -73,7 +73,7 @@ binsearch(uint32_t *start, uint32_t *stop) /** update_contribution * helper, calculates the partial linear feedback contributions and puts in MSB */ -static /*inline*/ void +static inline void update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2) { uint32_t p = *item >> 25; @@ -86,7 +86,7 @@ update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2) /** extend_table * using a bit of the keystream extend the table of possible lfsr states */ -static /*inline*/ void +static inline void extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in) { in <<= 24; @@ -108,7 +108,7 @@ extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in /** extend_table_simple * using a bit of the keystream extend the table of possible lfsr states */ -static /*inline*/ void +static inline void extend_table_simple(uint32_t *tbl, uint32_t **end, int bit) { for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) diff --git a/src/crapto1.h b/src/crapto1.h index 8f0ce79..7547344 100644 --- a/src/crapto1.h +++ b/src/crapto1.h @@ -15,7 +15,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US$ - Copyright (C) 2008-2008 bla + Copyright (C) 2008-2009 bla */ #ifndef CRAPTO1_INCLUDED #define CRAPTO1_INCLUDED @@ -35,12 +35,8 @@ uint32_t prng_successor(uint32_t x, uint32_t n); struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in); struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3); -uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd); -struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]); -uint8_t lfsr_rollback_bit(struct Crypto1State* s, uint32_t in, int fb); -uint8_t lfsr_rollback_byte(struct Crypto1State* s, uint32_t in, int fb); -uint32_t lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb); +void lfsr_rollback(struct Crypto1State* s, uint32_t in, int fb); int nonce_distance(uint32_t from, uint32_t to); #define FOREACH_VALID_NONCE(N, FILTER, FSIZE)\ uint32_t __n = 0,__M = 0, N = 0;\ @@ -57,7 +53,7 @@ int nonce_distance(uint32_t from, uint32_t to); #define LF_POLY_EVEN (0x870804) #define BIT(x, n) ((x) >> (n) & 1) #define BEBIT(x, n) BIT(x, (n) ^ 24) -static /*inline*/ int parity(uint32_t x) +static inline int parity(uint32_t x) { #if !defined __i386__ || !defined __GNUC__ x ^= x >> 16; @@ -65,17 +61,17 @@ static /*inline*/ int parity(uint32_t x) x ^= x >> 4; return BIT(0x6996, x & 0xf); #else - asm( "movl %1, %%eax\n" + asm( "movl %1, %%eax\n" "mov %%ax, %%cx\n" "shrl $0x10, %%eax\n" "xor %%ax, %%cx\n" - "xor %%ch, %%cl\n" - "setpo %%al\n" - "movzx %%al, %0\n": "=r"(x) : "r"(x): "eax","ecx"); + "xor %%ch, %%cl\n" + "setpo %%al\n" + "movzx %%al, %0\n": "=r"(x) : "r"(x): "eax","ecx"); return x; #endif } -static /*inline*/ int filter(uint32_t const x) +static inline int filter(uint32_t const x) { uint32_t f; diff --git a/src/bin/data/logs_proxmark3/trace1.txt b/src/data/logs_proxmark3/trace1.txt similarity index 100% rename from src/bin/data/logs_proxmark3/trace1.txt rename to src/data/logs_proxmark3/trace1.txt diff --git a/src/bin/data/logs_proxmark3/trace2.txt b/src/data/logs_proxmark3/trace2.txt similarity index 100% rename from src/bin/data/logs_proxmark3/trace2.txt rename to src/data/logs_proxmark3/trace2.txt diff --git a/src/bin/data/logs_proxmark3/trace3.txt b/src/data/logs_proxmark3/trace3.txt similarity index 100% rename from src/bin/data/logs_proxmark3/trace3.txt rename to src/data/logs_proxmark3/trace3.txt diff --git a/src/bin/data/tmpls_fingerprints/mfcuk_tmpl_oyster.mfd b/src/data/tmpls_fingerprints/mfcuk_tmpl_oyster.mfd similarity index 100% rename from src/bin/data/tmpls_fingerprints/mfcuk_tmpl_oyster.mfd rename to src/data/tmpls_fingerprints/mfcuk_tmpl_oyster.mfd diff --git a/src/bin/data/tmpls_fingerprints/mfcuk_tmpl_ratb.mfd b/src/data/tmpls_fingerprints/mfcuk_tmpl_ratb.mfd similarity index 100% rename from src/bin/data/tmpls_fingerprints/mfcuk_tmpl_ratb.mfd rename to src/data/tmpls_fingerprints/mfcuk_tmpl_ratb.mfd diff --git a/src/bin/data/tmpls_fingerprints/mfcuk_tmpl_skgt.mfd b/src/data/tmpls_fingerprints/mfcuk_tmpl_skgt.mfd similarity index 100% rename from src/bin/data/tmpls_fingerprints/mfcuk_tmpl_skgt.mfd rename to src/data/tmpls_fingerprints/mfcuk_tmpl_skgt.mfd diff --git a/src/mfcuk_keyrecovery_darkside.c b/src/mfcuk.c similarity index 98% rename from src/mfcuk_keyrecovery_darkside.c rename to src/mfcuk.c index 0a135d0..19d61ff 100644 --- a/src/mfcuk_keyrecovery_darkside.c +++ b/src/mfcuk.c @@ -132,7 +132,31 @@ #endif #if defined(HAVE_BYTESWAP_H) -# include + +#include + +#elif __GNUC__ * 100 + __GNUC_MINOR__ >= 430 + +#warning "NO byteswap.h found! But since GCC >= 4.30, using __builtin_bswapXX() alternatives..." +#define bswap_16 __builtin_bswap16 +#define bswap_32 __builtin_bswap32 +#define bswap_64 __builtin_bswap64 + +#else + +#warning "NO byteswap.h found! Using untested alternatives..." + +static inline unsigned short bswap_16(unsigned short x) { + return (x>>8) | (x<<8); +} + +static inline unsigned int bswap_32(unsigned int x) { + return (bswap_16(x&0xffff)<<16) | (bswap_16(x>>16)); +} + +static inline unsigned long long bswap_64(unsigned long long x) { + return (((unsigned long long)bswap_32(x&0xffffffffull))<<32) | (bswap_32(x>>32)); +} #endif #include @@ -171,7 +195,7 @@ #include "mfcuk_mifare.h" #include "mfcuk_utils.h" #include "mfcuk_finger.h" -#include "mfcuk_keyrecovery_darkside.h" +#include "mfcuk.h" #define MAX_FRAME_LEN 264 @@ -1293,7 +1317,7 @@ int main(int argc, char* argv[]) } break; case 'I': - // // Input extended dump file of type mifare_classic_tag_ext, Options i and I are autoexclusive + // Input extended dump file of type mifare_classic_tag_ext, Options i and I are autoexclusive if (!bfOpts['i'] && !bfOpts['I']) { if ( !mfcuk_load_tag_dump_ext(optarg, &(dump_loaded_tag)) ) @@ -1308,7 +1332,7 @@ int main(int argc, char* argv[]) break; case 'o': case 'O': - // // Output simple/extended dump file, Options o and O are autoexclusive + // Output simple/extended dump file, Options o and O are autoexclusive if (!bfOpts['o'] && !bfOpts['O']) { strncpy( strOutputFilename, optarg, sizeof(strOutputFilename) ); diff --git a/src/mfcuk_keyrecovery_darkside.h b/src/mfcuk.h similarity index 100% rename from src/mfcuk_keyrecovery_darkside.h rename to src/mfcuk.h diff --git a/src/mfcuk_finger.c b/src/mfcuk_finger.c index 52788db..781c156 100644 --- a/src/mfcuk_finger.c +++ b/src/mfcuk_finger.c @@ -42,7 +42,7 @@ mfcuk_finger_tmpl_entry mfcuk_finger_db[] = { { "./data/tmpls_fingerprints/mfcuk_tmpl_skgt.mfd", "Sofia SKGT", mfcuk_finger_default_comparator, mfcuk_finger_skgt_decoder, NULL }, { "./data/tmpls_fingerprints/mfcuk_tmpl_ratb.mfd", "Bucharest RATB", mfcuk_finger_default_comparator, mfcuk_finger_default_decoder, NULL }, - { "./data/tmpls_fingerprints/mfcuk_tmpl_oyster.mfd", "London OYSTER", mfcuk_finger_default_comparator, mfcuk_finger_default_decoder, NULL } + { "./data/tmpls_fingerprints/mfcuk_tmpl_oyster.mfd", "London OYSTER", mfcuk_finger_default_comparator, mfcuk_finger_default_decoder, NULL }, }; int mfcuk_finger_db_entries = sizeof(mfcuk_finger_db)/sizeof(mfcuk_finger_db[0]); @@ -172,13 +172,13 @@ int mfcuk_finger_load() fclose(fp); continue; } - fclose(fp); if (mfcuk_finger_db[i].tmpl_data == NULL) { if ( (tmpl_new = (mfcuk_finger_template *) malloc(sizeof(mfcuk_finger_template))) == NULL) { fprintf(stderr, "WARN: cannot allocate memory to template record %d\n", i); + fclose(fp); continue; } @@ -188,9 +188,14 @@ int mfcuk_finger_load() mfcuk_finger_db[i].tmpl_data = tmpl_new; template_loaded_count++; } + + if (fp) + { + fclose(fp); + fp = NULL; + } } - return template_loaded_count; } diff --git a/src/mifare.c b/src/mifare.c index ef9d147..360d5cf 100644 --- a/src/mifare.c +++ b/src/mifare.c @@ -100,12 +100,14 @@ nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t return false; } // Fire the mifare command - if (!nfc_initiator_transceive_bytes (pnd, abtCmd, 2 + szParamLen, abtRx, &szRx, NULL)) { + if (!nfc_initiator_transceive_bytes (pnd, abtCmd, 2 + szParamLen, abtRx, &szRx)) { if (pnd->iLastError == EINVRXFRAM) { // "Invalid received frame" AKA EINVRXFRAM, usual means we are // authenticated on a sector but the requested MIFARE cmd (read, write) // is not permitted by current acces bytes; // So there is nothing to do here. + } else if (pnd->iLastError == EMFAUTH) { + // In MFOC, we have to hide authentication errors :) } else { nfc_perror (pnd, "nfc_initiator_transceive_bytes"); } diff --git a/src/mifare.h b/src/mifare.h index 1b98b22..df357df 100644 --- a/src/mifare.h +++ b/src/mifare.h @@ -1,57 +1,69 @@ -/** - * Public platform independent Near Field Communication (NFC) library - * - * Copyright (C) 2009, Roel Verdult, 2010, Romuald Conty +/*- + * Public platform independent Near Field Communication (NFC) library examples * - * 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. + * Copyright (C) 2009, Roel Verdult + * Copyright (C) 2010, Romuald Conty, Romain Tartière * - * 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. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1) Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2 )Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see - * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. * + * Note that this license only applies on the examples, NFC library itself is under LGPL + * + */ + +/** * @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_ +# define _LIBNFC_MIFARE_H_ -#include +# include // Compiler directive, set struct alignment to 1 byte_t for compatibility -#pragma pack(1) +# 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 + 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]; + byte_t abtKey[6]; + byte_t abtUid[4]; } mifare_param_auth; typedef struct { - byte_t abtData[16]; + byte_t abtData[16]; } mifare_param_data; typedef struct { - byte_t abtValue[4]; + byte_t abtValue[4]; } mifare_param_value; typedef union { @@ -61,30 +73,30 @@ typedef union { } mifare_param; // Reset struct alignment to default -#pragma pack() +# pragma pack() -bool nfc_initiator_mifare_cmd(nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp); +bool nfc_initiator_mifare_cmd (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) +# 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]; + 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]; + byte_t abtData[16]; } mifare_classic_block_data; typedef struct { - byte_t abtKeyA[6]; - byte_t abtAccessBits[4]; - byte_t abtKeyB[6]; + byte_t abtKeyA[6]; + byte_t abtAccessBits[4]; + byte_t abtKeyB[6]; } mifare_classic_block_trailer; typedef union { @@ -99,17 +111,17 @@ typedef struct { // 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]; + 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]; + byte_t abtData[16]; } mifareul_block_data; typedef union { @@ -122,6 +134,6 @@ typedef struct { } mifareul_tag; // Reset struct alignment to default -#pragma pack() +# pragma pack() #endif // _LIBNFC_MIFARE_H_ diff --git a/src/nfc-utils.c b/src/nfc-utils.c index 61d9105..9a0f0fb 100644 --- a/src/nfc-utils.c +++ b/src/nfc-utils.c @@ -1,4 +1,35 @@ +/*- + * Public platform independent Near Field Communication (NFC) library examples + * + * Copyright (C) 2009, Roel Verdult + * Copyright (C) 2010, Romuald Conty, Romain Tartière + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1) Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2 )Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Note that this license only applies on the examples, NFC library itself is under LGPL + * + */ + #include +#include #include "nfc-utils.h" @@ -21,116 +52,509 @@ static const byte_t OddParity[256] = { 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 }; -byte_t oddparity(const byte_t bt) +byte_t +oddparity (const byte_t bt) { return OddParity[bt]; } -void oddparity_bytes_ts(const byte_t* pbtData, const size_t szLen, byte_t* pbtPar) +void +oddparity_bytes_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar) { - size_t szByteNr; + size_t szByteNr; // Calculate the parity bits for the command - for (szByteNr=0; szByteNr>6) { + case 0: + printf("single\n"); + break; + case 1: + printf("double\n"); + break; + case 2: + printf("triple\n"); + break; + case 3: + printf("RFU\n"); + break; + } + printf("* bit frame anticollision "); + switch (nai.abtAtqa[1] & 0x1f) { + case 0x01: + case 0x02: + case 0x04: + case 0x08: + case 0x10: + printf("supported\n"); + break; + default: + printf("not supported\n"); + break; + } + } + printf (" UID (NFCID%c): ", (nai.abtUid[0] == 0x08 ? '3' : '1')); + print_hex (nai.abtUid, nai.szUidLen); + if (verbose) { + if (nai.abtUid[0] == 0x08) { + printf ("* Random UID\n"); + } + } + printf (" SAK (SEL_RES): "); + print_hex (&nai.btSak, 1); + if (verbose) { + if (nai.btSak & SAK_UID_NOT_COMPLETE) { + printf ("* Warning! Cascade bit set: UID not complete\n"); + } + if (nai.btSak & SAK_ISO14443_4_COMPLIANT) { + printf ("* Compliant with ISO/IEC 14443-4\n"); + } else { + printf ("* Not compliant with ISO/IEC 14443-4\n"); + } + if (nai.btSak & SAK_ISO18092_COMPLIANT) { + printf ("* Compliant with ISO/IEC 18092\n"); + } else { + printf ("* Not compliant with ISO/IEC 18092\n"); + } + } if (nai.szAtsLen) { - printf(" ATS (ATR): "); - print_hex(nai.abtAts, nai.szAtsLen); + printf (" ATS: "); + print_hex (nai.abtAts, nai.szAtsLen); } - if ( (nai.btSak & SAK_ISO14443_4_COMPLIANT) || (nai.btSak & SAK_ISO18092_COMPLIANT) ) { - printf(" Compliant with: "); - if (nai.btSak & SAK_ISO14443_4_COMPLIANT) printf("ISO/IEC 14443-4 "); - if (nai.btSak & SAK_ISO18092_COMPLIANT) printf("ISO/IEC 18092"); - printf("\n"); + if (nai.szAtsLen && verbose) { + // Decode ATS according to ISO/IEC 14443-4 (5.2 Answer to select) + const int iMaxFrameSizes[] = { 16, 24, 32, 40, 48, 64, 96, 128, 256 }; + printf ("* Max Frame Size accepted by PICC: %d bytes\n", iMaxFrameSizes[nai.abtAts[0] & 0x0F]); + + size_t offset = 1; + if (nai.abtAts[0] & 0x10) { // TA(1) present + byte_t TA = nai.abtAts[offset]; + offset++; + printf ("* Bit Rate Capability:\n"); + if (TA == 0) { + printf (" * PICC supports only 106 kbits/s in both directions\n"); + } + if (TA & 1<<7) { + printf (" * Same bitrate in both directions mandatory\n"); + } + if (TA & 1<<4) { + printf (" * PICC to PCD, DS=2, bitrate 212 kbits/s supported\n"); + } + if (TA & 1<<5) { + printf (" * PICC to PCD, DS=4, bitrate 424 kbits/s supported\n"); + } + if (TA & 1<<6) { + printf (" * PICC to PCD, DS=8, bitrate 847 kbits/s supported\n"); + } + if (TA & 1<<0) { + printf (" * PCD to PICC, DR=2, bitrate 212 kbits/s supported\n"); + } + if (TA & 1<<1) { + printf (" * PCD to PICC, DR=4, bitrate 424 kbits/s supported\n"); + } + if (TA & 1<<2) { + printf (" * PCD to PICC, DR=8, bitrate 847 kbits/s supported\n"); + } + if (TA & 1<<3) { + printf (" * ERROR unknown value\n"); + } + } + if (nai.abtAts[0] & 0x20) { // TB(1) present + byte_t TB= nai.abtAts[offset]; + offset++; + printf ("* Frame Waiting Time: %.4g ms\n",256.0*16.0*(1<<((TB & 0xf0) >> 4))/13560.0); + if ((TB & 0x0f) == 0) { + printf ("* No Start-up Frame Guard Time required\n"); + } else { + printf ("* Start-up Frame Guard Time: %.4g ms\n",256.0*16.0*(1<<(TB & 0x0f))/13560.0); + } + } + if (nai.abtAts[0] & 0x40) { // TC(1) present + byte_t TC = nai.abtAts[offset]; + offset++; + if (TC & 0x1) { + printf("* Node ADdress supported\n"); + } else { + printf("* Node ADdress not supported\n"); + } + if (TC & 0x2) { + printf("* Card IDentifier supported\n"); + } else { + printf("* Card IDentifier not supported\n"); + } + } + if (nai.szAtsLen > offset) { + printf ("* Historical bytes Tk: " ); + print_hex (nai.abtAts + offset, (nai.szAtsLen - offset)); + byte_t CIB = nai.abtAts[offset]; + offset++; + if (CIB != 0x00 && CIB != 0x10 && (CIB & 0xf0) != 0x80) { + printf(" * Proprietary format\n"); + if (CIB == 0xc1) { + printf(" * Tag byte: Mifare or virtual cards of various types\n"); + byte_t L = nai.abtAts[offset]; + offset++; + if (L != (nai.szAtsLen - offset)) { + printf(" * Warning: Type Identification Coding length (%i)", L); + printf(" not matching Tk length (%zi)\n", (nai.szAtsLen - offset)); + } + if ((nai.szAtsLen - offset - 2) > 0) { // Omit 2 CRC bytes + byte_t CTC = nai.abtAts[offset]; + offset++; + printf(" * Chip Type: "); + switch (CTC & 0xf0) { + case 0x00: + printf("(Multiple) Virtual Cards\n"); + break; + case 0x10: + printf("Mifare DESFire\n"); + break; + case 0x20: + printf("Mifare Plus\n"); + break; + default: + printf("RFU\n"); + break; + } + printf(" * Memory size: "); + switch (CTC & 0x0f) { + case 0x00: + printf("<1 kbyte\n"); + break; + case 0x01: + printf("1 kbyte\n"); + break; + case 0x02: + printf("2 kbyte\n"); + break; + case 0x03: + printf("4 kbyte\n"); + break; + case 0x04: + printf("8 kbyte\n"); + break; + case 0x0f: + printf("Unspecified\n"); + break; + default: + printf("RFU\n"); + break; + } + } + if ((nai.szAtsLen - offset) > 0) { // Omit 2 CRC bytes + byte_t CVC = nai.abtAts[offset]; + offset++; + printf(" * Chip Status: "); + switch (CVC & 0xf0) { + case 0x00: + printf("Engineering sample\n"); + break; + case 0x20: + printf("Released\n"); + break; + default: + printf("RFU\n"); + break; + } + printf(" * Chip Generation: "); + switch (CVC & 0x0f) { + case 0x00: + printf("Generation 1\n"); + break; + case 0x01: + printf("Generation 2\n"); + break; + case 0x02: + printf("Generation 3\n"); + break; + case 0x0f: + printf("Unspecified\n"); + break; + default: + printf("RFU\n"); + break; + } + } + if ((nai.szAtsLen - offset) > 0) { // Omit 2 CRC bytes + byte_t VCS = nai.abtAts[offset]; + offset++; + printf(" * Specifics (Virtual Card Selection):\n"); + if ((VCS & 0x09) == 0x00) { + printf(" * Only VCSL supported\n"); + } else if ((VCS & 0x09) == 0x01) { + printf(" * VCS, VCSL and SVC supported\n"); + } + if ((VCS & 0x0e) == 0x00) { + printf(" * SL1, SL2(?), SL3 supported\n"); + } else if ((VCS & 0x0e) == 0x02) { + printf(" * SL3 only card\n"); + } else if ((VCS & 0x0f) == 0x0e) { + printf(" * No VCS command supported\n"); + } else if ((VCS & 0x0f) == 0x0f) { + printf(" * Unspecified\n"); + } else { + printf(" * RFU\n"); + } + } + } + } else { + if (CIB == 0x00) { + printf(" * Tk after 0x00 consist of optional consecutive COMPACT-TLV data objects\n"); + printf(" followed by a mandatory status indicator (the last three bytes, not in TLV)\n"); + printf(" See ISO/IEC 7816-4 8.1.1.3 for more info\n"); + } + if (CIB == 0x10) { + printf(" * DIR data reference: %02x\n", nai.abtAts[offset]); + } + if (CIB == 0x80) { + if (nai.szAtsLen == offset) { + printf(" * No COMPACT-TLV objects found, no status found\n"); + } else { + printf(" * Tk after 0x80 consist of optional consecutive COMPACT-TLV data objects;\n"); + printf(" the last data object may carry a status indicator of one, two or three bytes.\n"); + printf(" See ISO/IEC 7816-4 8.1.1.3 for more info\n"); + } + } + } + } + } + if (verbose) { + printf("Fingerprinting based on ATQA & SAK values:\n"); + uint32_t atqasak = 0; + atqasak += (((uint32_t)nai.abtAtqa[0] & 0xff)<<16); + atqasak += (((uint32_t)nai.abtAtqa[1] & 0xff)<<8); + atqasak += ((uint32_t)nai.btSak & 0xff); + bool found_possible_match = false; + switch (atqasak) { + case 0x000218: + printf("* Mifare Classic 4K\n"); + found_possible_match = true; + break; + case 0x000408: + printf("* Mifare Classic 1K\n"); + printf("* Mifare Plus (4-byte UID) 2K SL1\n"); + found_possible_match = true; + break; + case 0x000409: + printf("* Mifare MINI\n"); + found_possible_match = true; + break; + case 0x000410: + printf("* Mifare Plus (4-byte UID) 2K SL2\n"); + found_possible_match = true; + break; + case 0x000411: + printf("* Mifare Plus (4-byte UID) 4K SL2\n"); + found_possible_match = true; + break; + case 0x000418: + printf("* Mifare Plus (4-byte UID) 4K SL1\n"); + found_possible_match = true; + break; + case 0x000420: + printf("* Mifare Plus (4-byte UID) 2K/4K SL3\n"); + found_possible_match = true; + break; + case 0x004400: + printf("* Mifare Ultralight\n"); + printf("* Mifare UltralightC\n"); + found_possible_match = true; + break; + case 0x004208: + case 0x004408: + printf("* Mifare Plus (7-byte UID) 2K SL1\n"); + found_possible_match = true; + break; + case 0x004218: + case 0x004418: + printf("* Mifare Plus (7-byte UID) 4K SL1\n"); + found_possible_match = true; + break; + case 0x004210: + case 0x004410: + printf("* Mifare Plus (7-byte UID) 2K SL2\n"); + found_possible_match = true; + break; + case 0x004211: + case 0x004411: + printf("* Mifare Plus (7-byte UID) 4K SL2\n"); + found_possible_match = true; + break; + case 0x004220: + case 0x004420: + printf("* Mifare Plus (7-byte UID) 2K/4K SL3\n"); + found_possible_match = true; + break; + case 0x034420: + printf("* Mifare DESFire / Desfire EV1\n"); + found_possible_match = true; + break; + } + + // Other matches not described in + // AN MIFARE Type Identification Procedure + // but seen in the field: + switch (atqasak) { + case 0x000488: + printf("* Mifare Classic 1K Infineon\n"); + found_possible_match = true; + break; + case 0x000298: + printf("* Gemplus MPCOS\n"); + found_possible_match = true; + break; + case 0x030428: + printf("* JCOP31\n"); + found_possible_match = true; + break; + case 0x004820: + printf("* JCOP31 v2.4.1\n"); + printf("* JCOP31 v2.2\n"); + found_possible_match = true; + break; + case 0x000428: + printf("* JCOP31 v2.3.1\n"); + found_possible_match = true; + break; + case 0x000453: + printf("* Fudan FM1208SH01\n"); + found_possible_match = true; + break; + case 0x000820: + printf("* Fudan FM1208\n"); + found_possible_match = true; + break; + case 0x000238: + printf("* MFC 4K emulated by Nokia 6212 Classic\n"); + found_possible_match = true; + break; + case 0x000838: + printf("* MFC 4K emulated by Nokia 6131 NFC\n"); + found_possible_match = true; + break; + } + if ((nai.abtAtqa[0] & 0xf0) == 0) { + switch (nai.abtAtqa[1]) { + case 0x02: + printf("* SmartMX with Mifare 4K emulation\n"); + found_possible_match = true; + break; + case 0x04: + printf("* SmartMX with Mifare 1K emulation\n"); + found_possible_match = true; + break; + case 0x48: + printf("* SmartMX with 7-byte UID\n"); + found_possible_match = true; + break; + } + } + if (! found_possible_match) { + printf("* Unknown card, sorry\n"); + } } } -void print_nfc_felica_info(const nfc_felica_info_t nfi) + +void +print_nfc_felica_info (const nfc_felica_info_t nfi, bool verbose) { - printf(" ID (NFCID2): "); print_hex(nfi.abtId,8); - printf(" Parameter (PAD): "); print_hex(nfi.abtPad,8); + (void) verbose; + printf (" ID (NFCID2): "); + print_hex (nfi.abtId, 8); + printf (" Parameter (PAD): "); + print_hex (nfi.abtPad, 8); } -void print_nfc_iso14443b_info(const nfc_iso14443b_info_t nbi) +void +print_nfc_jewel_info (const nfc_jewel_info_t nji, bool verbose) { + (void) verbose; + printf (" ATQA (SENS_RES): "); + print_hex (nji.btSensRes, 2); + printf (" 4-LSB JEWELID: "); + print_hex (nji.btId, 4); +} + #define PI_ISO14443_4_SUPPORTED 0x01 #define PI_NAD_SUPPORTED 0x01 #define PI_CID_SUPPORTED 0x02 - //copied from libnfc r963 - bool verbose = true; +void +print_nfc_iso14443b_info (const nfc_iso14443b_info_t nbi, bool verbose) +{ const int iMaxFrameSizes[] = { 16, 24, 32, 40, 48, 64, 96, 128, 256 }; printf (" PUPI: "); print_hex (nbi.abtPupi, 4); @@ -183,44 +607,115 @@ void print_nfc_iso14443b_info(const nfc_iso14443b_info_t nbi) } } +void +print_nfc_dep_info (const nfc_dep_info_t ndi, bool verbose) +{ + (void) verbose; + printf (" NFCID3: "); + print_hex (ndi.abtNFCID3, 10); + printf (" BS: %02x\n", ndi.btBS); + printf (" BR: %02x\n", ndi.btBR); + printf (" TO: %02x\n", ndi.btTO); + printf (" PP: %02x\n", ndi.btPP); + if (ndi.szGB) { + printf ("General Bytes: "); + print_hex (ndi.abtGB, ndi.szGB); + } +} + /** * @brief Tries to parse arguments to find device descriptions. * @return Returns the list of found device descriptions. */ -nfc_device_desc_t* parse_device_desc(int argc, const char *argv[], size_t* szFound) +nfc_device_desc_t * +parse_args (int argc, const char *argv[], size_t * szFound, bool * verbose) { - nfc_device_desc_t* pndd = 0; - int arg; + nfc_device_desc_t *pndd = 0; + int arg; *szFound = 0; // Get commandline options - for (arg=1;arg arg+1) { - char buffer[256]; + if (0 == strcmp (argv[arg], "--device")) { + // FIXME: this device selection by command line options is terrible & does not support USB/PCSC drivers + if (argc > arg + 1) { + char buffer[256]; - pndd = malloc(sizeof(nfc_device_desc_t)); + pndd = malloc (sizeof (nfc_device_desc_t)); - strncpy(buffer, argv[++arg], 256); + strncpy (buffer, argv[++arg], 256); // Driver. - pndd->pcDriver = (char *)malloc(256); - strcpy(pndd->pcDriver, strtok(buffer, ":")); + pndd->pcDriver = (char *) malloc (256); + strcpy (pndd->pcDriver, strtok (buffer, ":")); // Port. - strcpy(pndd->acPort, strtok(NULL, ":")); + pndd->pcPort = (char *) malloc (256); + strcpy (pndd->pcPort, strtok (NULL, ":")); // Speed. - sscanf(strtok(NULL, ":"), "%u", &pndd->uiSpeed); + sscanf (strtok (NULL, ":"), "%u", &pndd->uiSpeed); *szFound = 1; + } else { + errx (1, "usage: %s [--device driver:port:speed]", argv[0]); } - break; + } + if ((0 == strcmp (argv[arg], "-v")) || (0 == strcmp (argv[arg], "--verbose"))) { + *verbose = true; } } - return pndd; } +const char * +str_nfc_baud_rate (const nfc_baud_rate_t nbr) +{ + switch(nbr) { + case NBR_UNDEFINED: + return "undefined baud rate"; + break; + case NBR_106: + return "106 kbps"; + break; + case NBR_212: + return "212 kbps"; + break; + case NBR_424: + return "424 kbps"; + break; + case NBR_847: + return "847 kbps"; + break; + } + return ""; +} + +void +print_nfc_target (const nfc_target_t nt, bool verbose) +{ + switch(nt.nm.nmt) { + case NMT_ISO14443A: + printf ("ISO/IEC 14443A (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr)); + print_nfc_iso14443a_info (nt.nti.nai, verbose); + break; + case NMT_JEWEL: + printf ("Innovision Jewel (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr)); + print_nfc_jewel_info (nt.nti.nji, verbose); + break; + case NMT_FELICA: + printf ("FeliCa (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr)); + print_nfc_felica_info (nt.nti.nfi, verbose); + break; + case NMT_ISO14443B: + printf ("ISO/IEC 14443-4B (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr)); + print_nfc_iso14443b_info (nt.nti.nbi, verbose); + break; + case NMT_DEP: + printf ("D.E.P. (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr)); + print_nfc_dep_info (nt.nti.ndi, verbose); + break; + } +} + diff --git a/src/nfc-utils.h b/src/nfc-utils.h index c0c6f68..018193c 100644 --- a/src/nfc-utils.h +++ b/src/nfc-utils.h @@ -1,43 +1,99 @@ -/** - * Public platform independent Near Field Communication (NFC) library - * - * Copyright (C) 2010, Romuald Conty +/*- + * Public platform independent Near Field Communication (NFC) library examples * - * 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. + * Copyright (C) 2009, Roel Verdult + * Copyright (C) 2010, Romuald Conty, Romain Tartière * - * 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. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1) Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2 )Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see - * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. * + * Note that this license only applies on the examples, NFC library itself is under LGPL + * + */ + +/** * @file nfc-utils.h * @brief Provide some examples shared functions like print, parity calculation, options parsing. */ #ifndef _EXAMPLES_NFC_UTILS_H_ -#define _EXAMPLES_NFC_UTILS_H_ +# define _EXAMPLES_NFC_UTILS_H_ + +# include +# include +# include + +/** + * @macro DBG + * @brief Print a message of standard output only in DEBUG mode + */ +#ifdef DEBUG +# define DBG(...) do { \ + warnx ("DBG %s:%d", __FILE__, __LINE__); \ + warnx (" " __VA_ARGS__ ); \ + } while (0) +#else +# define DBG(...) {} +#endif + +/** + * @macro WARN + * @brief Print a warn message + */ +#ifdef DEBUG +# define WARN(...) do { \ + warnx ("WARNING %s:%d", __FILE__, __LINE__); \ + warnx (" " __VA_ARGS__ ); \ + } while (0) +#else +# define WARN(...) warnx ("WARNING: " __VA_ARGS__ ) +#endif + +/** + * @macro ERR + * @brief Print a error message + */ +#ifdef DEBUG +# define ERR(...) do { \ + warnx ("ERROR %s:%d", __FILE__, __LINE__); \ + warnx (" " __VA_ARGS__ ); \ + } while (0) +#else +# define ERR(...) warnx ("ERROR: " __VA_ARGS__ ) +#endif -#include -#include +byte_t oddparity (const byte_t bt); +void oddparity_byte_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar); -byte_t oddparity(const byte_t bt); -void oddparity_byte_ts(const byte_t* pbtData, const size_t szLen, byte_t* pbtPar); +void print_hex (const byte_t * pbtData, const size_t szLen); +void print_hex_bits (const byte_t * pbtData, const size_t szBits); +void print_hex_par (const byte_t * pbtData, const size_t szBits, const byte_t * pbtDataPar); -void print_hex(const byte_t* pbtData, const size_t szLen); -void print_hex_bits(const byte_t* pbtData, const size_t szBits); -void print_hex_par(const byte_t* pbtData, const size_t szBits, const byte_t* pbtDataPar); +void print_nfc_iso14443a_info (const nfc_iso14443a_info_t nai, bool verbose); +void print_nfc_iso14443b_info (const nfc_iso14443b_info_t nbi, bool verbose); +void print_nfc_felica_info (const nfc_felica_info_t nfi, bool verbose); +void print_nfc_jewel_info (const nfc_jewel_info_t nji, bool verbose); +void print_nfc_dep_info (const nfc_dep_info_t ndi, bool verbose); -void print_nfc_iso14443a_info(const nfc_iso14443a_info_t nai); -void print_nfc_iso14443b_info(const nfc_iso14443b_info_t nbi); -void print_nfc_felica_info(const nfc_felica_info_t nfi); +void print_nfc_target (const nfc_target_t nt, bool verbose); -nfc_device_desc_t* parse_device_desc(int argc, const char *argv[], size_t* szFound); +nfc_device_desc_t *parse_args (int argc, const char *argv[], size_t * szFound, bool * verbose); #endif