mirror of
https://github.com/nfc-tools/mfcuk.git
synced 2026-02-18 02:55:49 +00:00
Sync nfc-utils.* and mifare.* with current libnfc devel version
This commit is contained in:
parent
1b6d022668
commit
1026af5d3f
104
src/mifare.c
104
src/mifare.c
@ -1,13 +1,13 @@
|
|||||||
/*-
|
/*-
|
||||||
* Public platform independent Near Field Communication (NFC) library examples
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009, Roel Verdult
|
* Copyright (C) 2009, Roel Verdult
|
||||||
* Copyright (C) 2010, Romuald Conty, Romain Tartière
|
* Copyright (C) 2010, Romuald Conty, Romain Tartière
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* 1) Redistributions of source code must retain the above copyright notice,
|
* 1) Redistributions of source code must retain the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer.
|
* this list of conditions and the following disclaimer.
|
||||||
* 2 )Redistributions in binary form must reproduce the above copyright
|
* 2 )Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
@ -23,11 +23,14 @@
|
|||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
* 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
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* Note that this license only applies on the examples, NFC library itself is under LGPL
|
* Note that this license only applies on the examples, NFC library itself is under LGPL
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* @file mifare.c
|
||||||
|
* @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc
|
||||||
|
*/
|
||||||
#include "mifare.h"
|
#include "mifare.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -42,85 +45,88 @@
|
|||||||
* The specified MIFARE command will be executed on the tag. There are different commands possible, they all require the destination block number.
|
* 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).
|
* @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.
|
* 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).
|
* 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).
|
* 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.
|
* The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param * pmp)
|
nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param *pmp)
|
||||||
{
|
{
|
||||||
byte_t abtRx[265];
|
uint8_t abtRx[265];
|
||||||
size_t szRx = sizeof(abtRx);
|
|
||||||
size_t szParamLen;
|
size_t szParamLen;
|
||||||
byte_t abtCmd[265];
|
uint8_t abtCmd[265];
|
||||||
bool bEasyFraming;
|
//bool bEasyFraming;
|
||||||
|
|
||||||
abtCmd[0] = mc; // The MIFARE Classic command
|
abtCmd[0] = mc; // The MIFARE Classic command
|
||||||
abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
|
abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
|
||||||
|
|
||||||
switch (mc) {
|
switch (mc) {
|
||||||
// Read and store command have no parameter
|
// Read and store command have no parameter
|
||||||
case MC_READ:
|
case MC_READ:
|
||||||
case MC_STORE:
|
case MC_STORE:
|
||||||
szParamLen = 0;
|
szParamLen = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Authenticate command
|
// Authenticate command
|
||||||
case MC_AUTH_A:
|
case MC_AUTH_A:
|
||||||
case MC_AUTH_B:
|
case MC_AUTH_B:
|
||||||
szParamLen = sizeof (mifare_param_auth);
|
szParamLen = sizeof(struct mifare_param_auth);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Data command
|
// Data command
|
||||||
case MC_WRITE:
|
case MC_WRITE:
|
||||||
szParamLen = sizeof (mifare_param_data);
|
szParamLen = sizeof(struct mifare_param_data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Value command
|
// Value command
|
||||||
case MC_DECREMENT:
|
case MC_DECREMENT:
|
||||||
case MC_INCREMENT:
|
case MC_INCREMENT:
|
||||||
case MC_TRANSFER:
|
case MC_TRANSFER:
|
||||||
szParamLen = sizeof (mifare_param_value);
|
szParamLen = sizeof(struct mifare_param_value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Please fix your code, you never should reach this statement
|
// Please fix your code, you never should reach this statement
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When available, copy the parameter bytes
|
// When available, copy the parameter bytes
|
||||||
if (szParamLen)
|
if (szParamLen)
|
||||||
memcpy (abtCmd + 2, (byte_t *) pmp, szParamLen);
|
memcpy(abtCmd + 2, (uint8_t *) pmp, szParamLen);
|
||||||
|
|
||||||
bEasyFraming = pnd->bEasyFraming;
|
// FIXME: Save and restore bEasyFraming
|
||||||
if (!nfc_configure (pnd, NDO_EASY_FRAMING, true)) {
|
// bEasyFraming = nfc_device_get_property_bool (pnd, NP_EASY_FRAMING, &bEasyFraming);
|
||||||
nfc_perror (pnd, "nfc_configure");
|
if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true) < 0) {
|
||||||
|
nfc_perror(pnd, "nfc_device_set_property_bool");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Fire the mifare command
|
// Fire the mifare command
|
||||||
if (!nfc_initiator_transceive_bytes (pnd, abtCmd, 2 + szParamLen, abtRx, &szRx, NULL)) {
|
int res;
|
||||||
if (pnd->iLastError == EINVRXFRAM) {
|
if ((res = nfc_initiator_transceive_bytes(pnd, abtCmd, 2 + szParamLen, abtRx, sizeof(abtRx), -1)) < 0) {
|
||||||
// "Invalid received frame" AKA EINVRXFRAM, usual means we are
|
if (res == NFC_ERFTRANS) {
|
||||||
|
// "Invalid received frame", usual means we are
|
||||||
// authenticated on a sector but the requested MIFARE cmd (read, write)
|
// authenticated on a sector but the requested MIFARE cmd (read, write)
|
||||||
// is not permitted by current acces bytes;
|
// is not permitted by current acces bytes;
|
||||||
// So there is nothing to do here.
|
// So there is nothing to do here.
|
||||||
} else {
|
} else {
|
||||||
nfc_perror (pnd, "nfc_initiator_transceive_bytes");
|
nfc_perror(pnd, "nfc_initiator_transceive_bytes");
|
||||||
}
|
}
|
||||||
nfc_configure (pnd, NDO_EASY_FRAMING, bEasyFraming);
|
// XXX nfc_device_set_property_bool (pnd, NP_EASY_FRAMING, bEasyFraming);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!nfc_configure (pnd, NDO_EASY_FRAMING, bEasyFraming)) {
|
/* XXX
|
||||||
nfc_perror (pnd, "nfc_configure");
|
if (nfc_device_set_property_bool (pnd, NP_EASY_FRAMING, bEasyFraming) < 0) {
|
||||||
|
nfc_perror (pnd, "nfc_device_set_property_bool");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// When we have executed a read command, copy the received bytes into the param
|
// When we have executed a read command, copy the received bytes into the param
|
||||||
if (mc == MC_READ) {
|
if (mc == MC_READ) {
|
||||||
if (szRx == 16) {
|
if (res == 16) {
|
||||||
memcpy (pmp->mpd.abtData, abtRx, 16);
|
memcpy(pmp->mpd.abtData, abtRx, 16);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
76
src/mifare.h
76
src/mifare.h
@ -1,13 +1,13 @@
|
|||||||
/*-
|
/*-
|
||||||
* Public platform independent Near Field Communication (NFC) library examples
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009, Roel Verdult
|
* Copyright (C) 2009, Roel Verdult
|
||||||
* Copyright (C) 2010, Romuald Conty, Romain Tartière
|
* Copyright (C) 2010, Romuald Conty, Romain Tartière
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* 1) Redistributions of source code must retain the above copyright notice,
|
* 1) Redistributions of source code must retain the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer.
|
* this list of conditions and the following disclaimer.
|
||||||
* 2 )Redistributions in binary form must reproduce the above copyright
|
* 2 )Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
@ -23,13 +23,13 @@
|
|||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
* 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
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* Note that this license only applies on the examples, NFC library itself is under LGPL
|
* Note that this license only applies on the examples, NFC library itself is under LGPL
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file mifaretag.h
|
* @file mifare.h
|
||||||
* @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc
|
* @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
# include <nfc/nfc-types.h>
|
# include <nfc/nfc-types.h>
|
||||||
|
|
||||||
// Compiler directive, set struct alignment to 1 byte_t for compatibility
|
// Compiler directive, set struct alignment to 1 uint8_t for compatibility
|
||||||
# pragma pack(1)
|
# pragma pack(1)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -53,50 +53,50 @@ typedef enum {
|
|||||||
} mifare_cmd;
|
} mifare_cmd;
|
||||||
|
|
||||||
// MIFARE command params
|
// MIFARE command params
|
||||||
typedef struct {
|
struct mifare_param_auth {
|
||||||
byte_t abtKey[6];
|
uint8_t abtKey[6];
|
||||||
byte_t abtUid[4];
|
uint8_t abtAuthUid[4];
|
||||||
} mifare_param_auth;
|
};
|
||||||
|
|
||||||
typedef struct {
|
struct mifare_param_data {
|
||||||
byte_t abtData[16];
|
uint8_t abtData[16];
|
||||||
} mifare_param_data;
|
};
|
||||||
|
|
||||||
typedef struct {
|
struct mifare_param_value {
|
||||||
byte_t abtValue[4];
|
uint8_t abtValue[4];
|
||||||
} mifare_param_value;
|
};
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
mifare_param_auth mpa;
|
struct mifare_param_auth mpa;
|
||||||
mifare_param_data mpd;
|
struct mifare_param_data mpd;
|
||||||
mifare_param_value mpv;
|
struct mifare_param_value mpv;
|
||||||
} mifare_param;
|
} mifare_param;
|
||||||
|
|
||||||
// Reset struct alignment to default
|
// 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 *pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param *pmp);
|
||||||
|
|
||||||
// Compiler directive, set struct alignment to 1 byte_t for compatibility
|
// Compiler directive, set struct alignment to 1 uint8_t for compatibility
|
||||||
# pragma pack(1)
|
# pragma pack(1)
|
||||||
|
|
||||||
// MIFARE Classic
|
// MIFARE Classic
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtUID[4];
|
uint8_t abtUID[4];
|
||||||
byte_t btBCC;
|
uint8_t btBCC;
|
||||||
byte_t btUnknown;
|
uint8_t btUnknown;
|
||||||
byte_t abtATQA[2];
|
uint8_t abtATQA[2];
|
||||||
byte_t abtUnknown[8];
|
uint8_t abtUnknown[8];
|
||||||
} mifare_classic_block_manufacturer;
|
} mifare_classic_block_manufacturer;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtData[16];
|
uint8_t abtData[16];
|
||||||
} mifare_classic_block_data;
|
} mifare_classic_block_data;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtKeyA[6];
|
uint8_t abtKeyA[6];
|
||||||
byte_t abtAccessBits[4];
|
uint8_t abtAccessBits[4];
|
||||||
byte_t abtKeyB[6];
|
uint8_t abtKeyB[6];
|
||||||
} mifare_classic_block_trailer;
|
} mifare_classic_block_trailer;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
@ -111,17 +111,17 @@ typedef struct {
|
|||||||
|
|
||||||
// MIFARE Ultralight
|
// MIFARE Ultralight
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t sn0[3];
|
uint8_t sn0[3];
|
||||||
byte_t btBCC0;
|
uint8_t btBCC0;
|
||||||
byte_t sn1[4];
|
uint8_t sn1[4];
|
||||||
byte_t btBCC1;
|
uint8_t btBCC1;
|
||||||
byte_t internal;
|
uint8_t internal;
|
||||||
byte_t lock[2];
|
uint8_t lock[2];
|
||||||
byte_t otp[4];
|
uint8_t otp[4];
|
||||||
} mifareul_block_manufacturer;
|
} mifareul_block_manufacturer;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtData[16];
|
uint8_t abtData[16];
|
||||||
} mifareul_block_data;
|
} mifareul_block_data;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
|
|||||||
684
src/nfc-utils.c
684
src/nfc-utils.c
@ -1,13 +1,14 @@
|
|||||||
/*-
|
/*-
|
||||||
* Public platform independent Near Field Communication (NFC) library examples
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009, Roel Verdult
|
* Copyright (C) 2009, Roel Verdult
|
||||||
* Copyright (C) 2010, Romuald Conty, Romain Tartière
|
* Copyright (C) 2010-2011, Romain Tartière
|
||||||
*
|
* Copyright (C) 2009-2012, Romuald Conty
|
||||||
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* 1) Redistributions of source code must retain the above copyright notice,
|
* 1) Redistributions of source code must retain the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer.
|
* this list of conditions and the following disclaimer.
|
||||||
* 2 )Redistributions in binary form must reproduce the above copyright
|
* 2 )Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
@ -23,97 +24,82 @@
|
|||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
* 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
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* Note that this license only applies on the examples, NFC library itself is under LGPL
|
* Note that this license only applies on the examples, NFC library itself is under LGPL
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* @file nfc-utils.c
|
||||||
|
* @brief Provide some examples shared functions like print, parity calculation, options parsing.
|
||||||
|
*/
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
|
||||||
#include "nfc-utils.h"
|
#include "nfc-utils.h"
|
||||||
|
|
||||||
static const byte_t OddParity[256] = {
|
uint8_t
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
oddparity(const uint8_t bt)
|
||||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
|
||||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
|
||||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
|
||||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
|
||||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
|
||||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
|
||||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
|
||||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
|
|
||||||
};
|
|
||||||
|
|
||||||
byte_t
|
|
||||||
oddparity (const byte_t bt)
|
|
||||||
{
|
{
|
||||||
return OddParity[bt];
|
// cf http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel
|
||||||
|
return (0x9669 >> ((bt ^(bt >> 4)) & 0xF)) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
oddparity_bytes_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar)
|
oddparity_bytes_ts(const uint8_t *pbtData, const size_t szLen, uint8_t *pbtPar)
|
||||||
{
|
{
|
||||||
size_t szByteNr;
|
size_t szByteNr;
|
||||||
// Calculate the parity bits for the command
|
// Calculate the parity bits for the command
|
||||||
for (szByteNr = 0; szByteNr < szLen; szByteNr++) {
|
for (szByteNr = 0; szByteNr < szLen; szByteNr++) {
|
||||||
pbtPar[szByteNr] = OddParity[pbtData[szByteNr]];
|
pbtPar[szByteNr] = oddparity(pbtData[szByteNr]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
print_hex (const byte_t * pbtData, const size_t szBytes)
|
print_hex(const uint8_t *pbtData, const size_t szBytes)
|
||||||
{
|
{
|
||||||
size_t szPos;
|
size_t szPos;
|
||||||
|
|
||||||
for (szPos = 0; szPos < szBytes; szPos++) {
|
for (szPos = 0; szPos < szBytes; szPos++) {
|
||||||
printf ("%02x ", pbtData[szPos]);
|
printf("%02x ", pbtData[szPos]);
|
||||||
}
|
}
|
||||||
printf ("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
print_hex_bits (const byte_t * pbtData, const size_t szBits)
|
print_hex_bits(const uint8_t *pbtData, const size_t szBits)
|
||||||
{
|
{
|
||||||
uint8_t uRemainder;
|
uint8_t uRemainder;
|
||||||
size_t szPos;
|
size_t szPos;
|
||||||
size_t szBytes = szBits / 8;
|
size_t szBytes = szBits / 8;
|
||||||
|
|
||||||
for (szPos = 0; szPos < szBytes; szPos++) {
|
for (szPos = 0; szPos < szBytes; szPos++) {
|
||||||
printf ("%02x ", pbtData[szPos]);
|
printf("%02x ", pbtData[szPos]);
|
||||||
}
|
}
|
||||||
|
|
||||||
uRemainder = szBits % 8;
|
uRemainder = szBits % 8;
|
||||||
// Print the rest bits
|
// Print the rest bits
|
||||||
if (uRemainder != 0) {
|
if (uRemainder != 0) {
|
||||||
if (uRemainder < 5)
|
if (uRemainder < 5)
|
||||||
printf ("%01x (%d bits)", pbtData[szBytes], uRemainder);
|
printf("%01x (%d bits)", pbtData[szBytes], uRemainder);
|
||||||
else
|
else
|
||||||
printf ("%02x (%d bits)", pbtData[szBytes], uRemainder);
|
printf("%02x (%d bits)", pbtData[szBytes], uRemainder);
|
||||||
}
|
}
|
||||||
printf ("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
print_hex_par (const byte_t * pbtData, const size_t szBits, const byte_t * pbtDataPar)
|
print_hex_par(const uint8_t *pbtData, const size_t szBits, const uint8_t *pbtDataPar)
|
||||||
{
|
{
|
||||||
uint8_t uRemainder;
|
uint8_t uRemainder;
|
||||||
size_t szPos;
|
size_t szPos;
|
||||||
size_t szBytes = szBits / 8;
|
size_t szBytes = szBits / 8;
|
||||||
|
|
||||||
for (szPos = 0; szPos < szBytes; szPos++) {
|
for (szPos = 0; szPos < szBytes; szPos++) {
|
||||||
printf ("%02x", pbtData[szPos]);
|
printf("%02x", pbtData[szPos]);
|
||||||
if (OddParity[pbtData[szPos]] != pbtDataPar[szPos]) {
|
if (oddparity(pbtData[szPos]) != pbtDataPar[szPos]) {
|
||||||
printf ("! ");
|
printf("! ");
|
||||||
} else {
|
} else {
|
||||||
printf (" ");
|
printf(" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,614 +107,18 @@ print_hex_par (const byte_t * pbtData, const size_t szBits, const byte_t * pbtDa
|
|||||||
// Print the rest bits, these cannot have parity bit
|
// Print the rest bits, these cannot have parity bit
|
||||||
if (uRemainder != 0) {
|
if (uRemainder != 0) {
|
||||||
if (uRemainder < 5)
|
if (uRemainder < 5)
|
||||||
printf ("%01x (%d bits)", pbtData[szBytes], uRemainder);
|
printf("%01x (%d bits)", pbtData[szBytes], uRemainder);
|
||||||
else
|
else
|
||||||
printf ("%02x (%d bits)", pbtData[szBytes], uRemainder);
|
printf("%02x (%d bits)", pbtData[szBytes], uRemainder);
|
||||||
}
|
|
||||||
printf ("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SAK_UID_NOT_COMPLETE 0x04
|
|
||||||
#define SAK_ISO14443_4_COMPLIANT 0x20
|
|
||||||
#define SAK_ISO18092_COMPLIANT 0x40
|
|
||||||
|
|
||||||
void
|
|
||||||
print_nfc_iso14443a_info (const nfc_iso14443a_info_t nai, bool verbose)
|
|
||||||
{
|
|
||||||
printf (" ATQA (SENS_RES): ");
|
|
||||||
print_hex (nai.abtAtqa, 2);
|
|
||||||
if (verbose) {
|
|
||||||
printf("* UID size: ");
|
|
||||||
switch ((nai.abtAtqa[1] & 0xc0)>>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: ");
|
|
||||||
print_hex (nai.abtAts, nai.szAtsLen);
|
|
||||||
}
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
print_nfc_felica_info (const nfc_felica_info_t nfi, bool verbose)
|
print_nfc_target(const nfc_target nt, bool verbose)
|
||||||
{
|
{
|
||||||
(void) verbose;
|
char *s;
|
||||||
printf (" ID (NFCID2): ");
|
str_nfc_target(&s, nt, verbose);
|
||||||
print_hex (nfi.abtId, 8);
|
printf("%s", s);
|
||||||
printf (" Parameter (PAD): ");
|
free(s);
|
||||||
print_hex (nfi.abtPad, 8);
|
|
||||||
printf (" System Code (SC): ");
|
|
||||||
print_hex (nfi.abtSysCode, 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
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);
|
|
||||||
printf (" Application Data: ");
|
|
||||||
print_hex (nbi.abtApplicationData, 4);
|
|
||||||
printf (" Protocol Info: ");
|
|
||||||
print_hex (nbi.abtProtocolInfo, 3);
|
|
||||||
if (verbose) {
|
|
||||||
printf ("* Bit Rate Capability:\n");
|
|
||||||
if (nbi.abtProtocolInfo[0] == 0) {
|
|
||||||
printf (" * PICC supports only 106 kbits/s in both directions\n");
|
|
||||||
}
|
|
||||||
if (nbi.abtProtocolInfo[0] & 1<<7) {
|
|
||||||
printf (" * Same bitrate in both directions mandatory\n");
|
|
||||||
}
|
|
||||||
if (nbi.abtProtocolInfo[0] & 1<<4) {
|
|
||||||
printf (" * PICC to PCD, 1etu=64/fc, bitrate 212 kbits/s supported\n");
|
|
||||||
}
|
|
||||||
if (nbi.abtProtocolInfo[0] & 1<<5) {
|
|
||||||
printf (" * PICC to PCD, 1etu=32/fc, bitrate 424 kbits/s supported\n");
|
|
||||||
}
|
|
||||||
if (nbi.abtProtocolInfo[0] & 1<<6) {
|
|
||||||
printf (" * PICC to PCD, 1etu=16/fc, bitrate 847 kbits/s supported\n");
|
|
||||||
}
|
|
||||||
if (nbi.abtProtocolInfo[0] & 1<<0) {
|
|
||||||
printf (" * PCD to PICC, 1etu=64/fc, bitrate 212 kbits/s supported\n");
|
|
||||||
}
|
|
||||||
if (nbi.abtProtocolInfo[0] & 1<<1) {
|
|
||||||
printf (" * PCD to PICC, 1etu=32/fc, bitrate 424 kbits/s supported\n");
|
|
||||||
}
|
|
||||||
if (nbi.abtProtocolInfo[0] & 1<<2) {
|
|
||||||
printf (" * PCD to PICC, 1etu=16/fc, bitrate 847 kbits/s supported\n");
|
|
||||||
}
|
|
||||||
if (nbi.abtProtocolInfo[0] & 1<<3) {
|
|
||||||
printf (" * ERROR unknown value\n");
|
|
||||||
}
|
|
||||||
if( (nbi.abtProtocolInfo[1] & 0xf0) <= 0x80 ) {
|
|
||||||
printf ("* Maximum frame sizes: %d bytes\n", iMaxFrameSizes[((nbi.abtProtocolInfo[1] & 0xf0) >> 4)]);
|
|
||||||
}
|
|
||||||
if((nbi.abtProtocolInfo[1] & 0x0f) == PI_ISO14443_4_SUPPORTED) {
|
|
||||||
printf ("* Protocol types supported: ISO/IEC 14443-4\n");
|
|
||||||
}
|
|
||||||
printf ("* Frame Waiting Time: %.4g ms\n",256.0*16.0*(1<<((nbi.abtProtocolInfo[2] & 0xf0) >> 4))/13560.0);
|
|
||||||
if((nbi.abtProtocolInfo[2] & (PI_NAD_SUPPORTED|PI_CID_SUPPORTED)) != 0) {
|
|
||||||
printf ("* Frame options supported: ");
|
|
||||||
if ((nbi.abtProtocolInfo[2] & PI_NAD_SUPPORTED) != 0) printf ("NAD ");
|
|
||||||
if ((nbi.abtProtocolInfo[2] & PI_CID_SUPPORTED) != 0) printf ("CID ");
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
print_nfc_iso14443bi_info (const nfc_iso14443bi_info_t nii, bool verbose)
|
|
||||||
{
|
|
||||||
printf (" DIV: ");
|
|
||||||
print_hex (nii.abtDIV, 4);
|
|
||||||
if (verbose) {
|
|
||||||
int version = (nii.btVerLog & 0x1e)>>1;
|
|
||||||
printf (" Software Version: ");
|
|
||||||
if (version == 15) {
|
|
||||||
printf ("Undefined\n");
|
|
||||||
} else {
|
|
||||||
printf ("%i\n", version);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((nii.btVerLog & 0x80) && (nii.btConfig & 0x80)){
|
|
||||||
printf (" Wait Enable: yes");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((nii.btVerLog & 0x80) && (nii.btConfig & 0x40)) {
|
|
||||||
printf (" ATS: ");
|
|
||||||
print_hex (nii.abtAtr, nii.szAtrLen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
print_nfc_iso14443b2sr_info (const nfc_iso14443b2sr_info_t nsi, bool verbose)
|
|
||||||
{
|
|
||||||
(void) verbose;
|
|
||||||
printf (" UID: ");
|
|
||||||
print_hex (nsi.abtUID, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
print_nfc_iso14443b2ct_info (const nfc_iso14443b2ct_info_t nci, bool verbose)
|
|
||||||
{
|
|
||||||
(void) verbose;
|
|
||||||
uint32_t uid;
|
|
||||||
uid = (nci.abtUID[3] << 24) + (nci.abtUID[2] << 16) + (nci.abtUID[1] << 8) + nci.abtUID[0];
|
|
||||||
printf (" UID: ");
|
|
||||||
print_hex (nci.abtUID, sizeof(nci.abtUID));
|
|
||||||
printf (" UID (decimal): %010u\n", uid);
|
|
||||||
printf (" Product Code: %02X\n", nci.btProdCode);
|
|
||||||
printf (" Fab Code: %02X\n", nci.btFabCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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_ISO14443BI:
|
|
||||||
printf ("ISO/IEC 14443-4B' (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
|
|
||||||
print_nfc_iso14443bi_info (nt.nti.nii, verbose);
|
|
||||||
break;
|
|
||||||
case NMT_ISO14443B2SR:
|
|
||||||
printf ("ISO/IEC 14443-2B ST SRx (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
|
|
||||||
print_nfc_iso14443b2sr_info (nt.nti.nsi, verbose);
|
|
||||||
break;
|
|
||||||
case NMT_ISO14443B2CT:
|
|
||||||
printf ("ISO/IEC 14443-2B ASK CTx (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr));
|
|
||||||
print_nfc_iso14443b2ct_info (nt.nti.nci, 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
/*-
|
/*-
|
||||||
* Public platform independent Near Field Communication (NFC) library examples
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009, Roel Verdult
|
* Copyright (C) 2009, Roel Verdult
|
||||||
* Copyright (C) 2010, Romuald Conty, Romain Tartière
|
* Copyright (C) 2010, Romuald Conty, Romain Tartière
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
* 1) Redistributions of source code must retain the above copyright notice,
|
* 1) Redistributions of source code must retain the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer.
|
* this list of conditions and the following disclaimer.
|
||||||
* 2 )Redistributions in binary form must reproduce the above copyright
|
* 2 )Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
@ -23,7 +23,7 @@
|
|||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
* 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
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* Note that this license only applies on the examples, NFC library itself is under LGPL
|
* Note that this license only applies on the examples, NFC library itself is under LGPL
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -79,22 +79,20 @@
|
|||||||
# define ERR(...) warnx ("ERROR: " __VA_ARGS__ )
|
# define ERR(...) warnx ("ERROR: " __VA_ARGS__ )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
byte_t oddparity (const byte_t bt);
|
#ifndef MIN
|
||||||
void oddparity_byte_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar);
|
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
#ifndef MAX
|
||||||
|
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
void print_hex (const byte_t * pbtData, const size_t szLen);
|
uint8_t oddparity(const uint8_t bt);
|
||||||
void print_hex_bits (const byte_t * pbtData, const size_t szBits);
|
void oddparity_bytes_ts(const uint8_t *pbtData, const size_t szLen, uint8_t *pbtPar);
|
||||||
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_hex(const uint8_t *pbtData, const size_t szLen);
|
||||||
void print_nfc_iso14443b_info (const nfc_iso14443b_info_t nbi, bool verbose);
|
void print_hex_bits(const uint8_t *pbtData, const size_t szBits);
|
||||||
void print_nfc_iso14443bi_info (const nfc_iso14443bi_info_t nii, bool verbose);
|
void print_hex_par(const uint8_t *pbtData, const size_t szBits, const uint8_t *pbtDataPar);
|
||||||
void print_nfc_iso14443b2sr_info (const nfc_iso14443b2sr_info_t nsi, bool verbose);
|
|
||||||
void print_nfc_iso14443b2ct_info (const nfc_iso14443b2ct_info_t nci, 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_target (const nfc_target_t nt, bool verbose);
|
void print_nfc_target(const nfc_target nt, bool verbose);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user