Add debug capabilities for Mifare Classic and Mifare UltraLight targets.
This commit is contained in:
parent
28b6ab7196
commit
02897e1b69
3 changed files with 104 additions and 83 deletions
|
@ -231,6 +231,14 @@ struct mifare_ultralight_tag {
|
||||||
uint8_t buffer_name[size]; \
|
uint8_t buffer_name[size]; \
|
||||||
size_t __##buffer_name##_n = 0
|
size_t __##buffer_name##_n = 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a wrapper for an existing buffer.
|
||||||
|
* BEWARE! It eats children!
|
||||||
|
*/
|
||||||
|
#define BUFFER_ALIAS(buffer_name, origin) \
|
||||||
|
uint8_t *buffer_name = (void *)origin; \
|
||||||
|
size_t __##buffer_name##_n = 0;
|
||||||
|
|
||||||
#define BUFFER_SIZE(buffer_name) (__##buffer_name##_n)
|
#define BUFFER_SIZE(buffer_name) (__##buffer_name##_n)
|
||||||
|
|
||||||
#define BUFFER_CLEAR(buffer_name) (__##buffer_name##_n = 0)
|
#define BUFFER_CLEAR(buffer_name) (__##buffer_name##_n = 0)
|
||||||
|
|
|
@ -61,7 +61,9 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
#ifdef WITH_DEBUG
|
||||||
|
# include <libutil.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <freefare.h>
|
#include <freefare.h>
|
||||||
#include "freefare_internal.h"
|
#include "freefare_internal.h"
|
||||||
|
@ -75,6 +77,20 @@
|
||||||
#define MC_INCREMENT 0xC1
|
#define MC_INCREMENT 0xC1
|
||||||
#define MC_RESTORE 0xC2
|
#define MC_RESTORE 0xC2
|
||||||
|
|
||||||
|
#define CLASSIC_TRANSCEIVE(tag, msg, res) CLASSIC_TRANSCEIVE_EX(tag, msg, res, 0)
|
||||||
|
|
||||||
|
#define CLASSIC_TRANSCEIVE_EX(tag, msg, res, disconnect) \
|
||||||
|
do { \
|
||||||
|
errno = 0; \
|
||||||
|
DEBUG_XFER (msg, __##msg##_n, "===> "); \
|
||||||
|
if (!(nfc_initiator_transceive_dep_bytes (tag->device, msg, __##msg##_n, res, &__##res##_n))) { \
|
||||||
|
if (disconnect) \
|
||||||
|
tag->active = false; \
|
||||||
|
return errno = EIO, -1; \
|
||||||
|
} \
|
||||||
|
DEBUG_XFER (res, __##res##_n, "<=== "); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/* Public Key A value of NFC Forum sectors */
|
/* Public Key A value of NFC Forum sectors */
|
||||||
const MifareClassicKey mifare_classic_nfcforum_public_key_a = {
|
const MifareClassicKey mifare_classic_nfcforum_public_key_a = {
|
||||||
0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7
|
0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7
|
||||||
|
@ -249,19 +265,19 @@ mifare_classic_authenticate (MifareTag tag, const MifareClassicBlockNumber block
|
||||||
ASSERT_ACTIVE (tag);
|
ASSERT_ACTIVE (tag);
|
||||||
ASSERT_MIFARE_CLASSIC (tag);
|
ASSERT_MIFARE_CLASSIC (tag);
|
||||||
|
|
||||||
unsigned char command[12];
|
BUFFER_INIT (cmd, 12);
|
||||||
command[0] = (key_type == MFC_KEY_A) ? MC_AUTH_A : MC_AUTH_B;
|
BUFFER_INIT (res, 1);
|
||||||
command[1] = block;
|
|
||||||
memcpy (&(command[2]), key, 6);
|
|
||||||
memcpy (&(command[8]), tag->info.abtUid, 4);
|
|
||||||
|
|
||||||
// Send command
|
if (key_type == MFC_KEY_A)
|
||||||
size_t n;
|
BUFFER_APPEND (cmd, MC_AUTH_A);
|
||||||
if (!(nfc_initiator_transceive_dep_bytes (tag->device, command, sizeof (command), NULL, &n))) {
|
else
|
||||||
tag->active = false; /* Tag is no more active if authentication failed. */
|
BUFFER_APPEND (cmd, MC_AUTH_B);
|
||||||
errno = EIO;
|
|
||||||
return -1;
|
BUFFER_APPEND(cmd, block);
|
||||||
}
|
BUFFER_APPEND_BYTES (cmd, key, 6);
|
||||||
|
BUFFER_APPEND_BYTES (cmd, tag->info.abtUid, 4);
|
||||||
|
|
||||||
|
CLASSIC_TRANSCEIVE_EX (tag, cmd, res, 1);
|
||||||
|
|
||||||
MIFARE_CLASSIC(tag)->cached_access_bits.sector_trailer_block_number = -1;
|
MIFARE_CLASSIC(tag)->cached_access_bits.sector_trailer_block_number = -1;
|
||||||
MIFARE_CLASSIC(tag)->cached_access_bits.sector_access_bits = 0x00;
|
MIFARE_CLASSIC(tag)->cached_access_bits.sector_access_bits = 0x00;
|
||||||
|
@ -280,16 +296,13 @@ mifare_classic_read (MifareTag tag, const MifareClassicBlockNumber block, Mifare
|
||||||
ASSERT_ACTIVE (tag);
|
ASSERT_ACTIVE (tag);
|
||||||
ASSERT_MIFARE_CLASSIC (tag);
|
ASSERT_MIFARE_CLASSIC (tag);
|
||||||
|
|
||||||
unsigned char command[2];
|
BUFFER_INIT (cmd, 2);
|
||||||
command[0] = MC_READ;
|
BUFFER_ALIAS (res, data);
|
||||||
command[1] = block;
|
|
||||||
|
|
||||||
// Send command
|
BUFFER_APPEND (cmd, MC_READ);
|
||||||
size_t n;
|
BUFFER_APPEND (cmd, block);
|
||||||
if (!(nfc_initiator_transceive_dep_bytes (tag->device, command, sizeof (command), *data, &n))) {
|
|
||||||
errno = EIO;
|
CLASSIC_TRANSCEIVE (tag, cmd, res);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -354,17 +367,14 @@ mifare_classic_write (MifareTag tag, const MifareClassicBlockNumber block, const
|
||||||
ASSERT_ACTIVE (tag);
|
ASSERT_ACTIVE (tag);
|
||||||
ASSERT_MIFARE_CLASSIC (tag);
|
ASSERT_MIFARE_CLASSIC (tag);
|
||||||
|
|
||||||
unsigned char command[2 + sizeof (MifareClassicBlock)];
|
BUFFER_INIT (cmd, 2 + sizeof (MifareClassicBlock));
|
||||||
command[0] = MC_WRITE;
|
BUFFER_INIT (res, 1);
|
||||||
command[1] = block;
|
|
||||||
memcpy (&(command[2]), data, sizeof (MifareClassicBlock));
|
|
||||||
|
|
||||||
// Send command
|
BUFFER_APPEND (cmd, MC_WRITE);
|
||||||
size_t n;
|
BUFFER_APPEND (cmd, block);
|
||||||
if (!(nfc_initiator_transceive_dep_bytes (tag->device, command, sizeof (command), NULL, &n))) {
|
BUFFER_APPEND_BYTES (cmd, data, sizeof (MifareClassicBlock));
|
||||||
errno = EIO;
|
|
||||||
return -1;
|
CLASSIC_TRANSCEIVE (tag, cmd, res);
|
||||||
}
|
|
||||||
|
|
||||||
// No result. The MIFARE tag just ACKed.
|
// No result. The MIFARE tag just ACKed.
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -380,18 +390,14 @@ mifare_classic_increment (MifareTag tag, const MifareClassicBlockNumber block, c
|
||||||
ASSERT_ACTIVE (tag);
|
ASSERT_ACTIVE (tag);
|
||||||
ASSERT_MIFARE_CLASSIC (tag);
|
ASSERT_MIFARE_CLASSIC (tag);
|
||||||
|
|
||||||
unsigned char command[6];
|
BUFFER_INIT (cmd, 6);
|
||||||
command[0] = MC_INCREMENT;
|
BUFFER_INIT (res, 1);
|
||||||
command[1] = block;
|
|
||||||
uint32_t le_amount = htole32 (amount);
|
|
||||||
memcpy(&(command[2]), &le_amount, sizeof (le_amount));
|
|
||||||
|
|
||||||
// Send command
|
BUFFER_APPEND (cmd, MC_INCREMENT);
|
||||||
size_t n;
|
BUFFER_APPEND (cmd, block);
|
||||||
if (!(nfc_initiator_transceive_dep_bytes (tag->device, command, sizeof (command), NULL, &n))) {
|
BUFFER_APPEND_LE (cmd, amount, 4, sizeof (amount));
|
||||||
errno = EIO;
|
|
||||||
return -1;
|
CLASSIC_TRANSCEIVE (tag, cmd, res);
|
||||||
}
|
|
||||||
|
|
||||||
// No result. The MIFARE tag just ACKed.
|
// No result. The MIFARE tag just ACKed.
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -407,18 +413,14 @@ mifare_classic_decrement (MifareTag tag, const MifareClassicBlockNumber block, c
|
||||||
ASSERT_ACTIVE (tag);
|
ASSERT_ACTIVE (tag);
|
||||||
ASSERT_MIFARE_CLASSIC (tag);
|
ASSERT_MIFARE_CLASSIC (tag);
|
||||||
|
|
||||||
unsigned char command[6];
|
BUFFER_INIT (cmd, 6);
|
||||||
command[0] = MC_DECREMENT;
|
BUFFER_INIT (res, 1);
|
||||||
command[1] = block;
|
|
||||||
uint32_t le_amount = htole32 (amount);
|
|
||||||
memcpy(&(command[2]), &le_amount, sizeof (le_amount));
|
|
||||||
|
|
||||||
// Send command
|
BUFFER_APPEND (cmd, MC_DECREMENT);
|
||||||
size_t n;
|
BUFFER_APPEND (cmd, block);
|
||||||
if (!(nfc_initiator_transceive_dep_bytes (tag->device, command, sizeof (command), NULL, &n))) {
|
BUFFER_APPEND_LE (cmd, amount, 4, sizeof (amount));
|
||||||
errno = EIO;
|
|
||||||
return -1;
|
CLASSIC_TRANSCEIVE (tag, cmd, res);
|
||||||
}
|
|
||||||
|
|
||||||
// No result. The MIFARE tag just ACKed.
|
// No result. The MIFARE tag just ACKed.
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -436,18 +438,19 @@ mifare_classic_restore (MifareTag tag, const MifareClassicBlockNumber block)
|
||||||
/*
|
/*
|
||||||
* Same length as the increment and decrement commands but only the first
|
* Same length as the increment and decrement commands but only the first
|
||||||
* two bytes are actually used. The 4 bytes after the block number are
|
* two bytes are actually used. The 4 bytes after the block number are
|
||||||
* meaningless but required (thus left uninitialized).
|
* meaningless but required (NULL-filled).
|
||||||
*/
|
*/
|
||||||
unsigned char command[6];
|
BUFFER_INIT (cmd, 6);
|
||||||
command[0] = MC_RESTORE;
|
BUFFER_INIT (res, 1);
|
||||||
command[1] = block;
|
|
||||||
|
|
||||||
// Send command
|
BUFFER_APPEND (cmd, MC_RESTORE);
|
||||||
size_t n;
|
BUFFER_APPEND (cmd, block);
|
||||||
if (!(nfc_initiator_transceive_dep_bytes (tag->device, command, sizeof (command), NULL, &n))) {
|
BUFFER_APPEND (cmd, 0x00);
|
||||||
errno = EIO;
|
BUFFER_APPEND (cmd, 0x00);
|
||||||
return -1;
|
BUFFER_APPEND (cmd, 0x00);
|
||||||
}
|
BUFFER_APPEND (cmd, 0x00);
|
||||||
|
|
||||||
|
CLASSIC_TRANSCEIVE (tag, cmd, res);
|
||||||
|
|
||||||
// No result. The MIFARE tag just ACKed.
|
// No result. The MIFARE tag just ACKed.
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -462,17 +465,13 @@ mifare_classic_transfer (MifareTag tag, const MifareClassicBlockNumber block)
|
||||||
ASSERT_ACTIVE (tag);
|
ASSERT_ACTIVE (tag);
|
||||||
ASSERT_MIFARE_CLASSIC (tag);
|
ASSERT_MIFARE_CLASSIC (tag);
|
||||||
|
|
||||||
unsigned char command[2];
|
BUFFER_INIT (cmd, 2);
|
||||||
command[0] = MC_TRANSFER;
|
BUFFER_INIT (res, 1);
|
||||||
command[1] = block;
|
|
||||||
|
|
||||||
// Send command
|
BUFFER_APPEND (cmd, MC_TRANSFER);
|
||||||
size_t n;
|
BUFFER_APPEND (cmd, block);
|
||||||
unsigned char buffer[1];
|
|
||||||
if (!(nfc_initiator_transceive_dep_bytes (tag->device, command, sizeof (command), buffer, &n))) {
|
CLASSIC_TRANSCEIVE (tag, cmd, res);
|
||||||
errno = EIO;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: The receive command returns data. Should be checked.
|
// FIXME: The receive command returns data. Should be checked.
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -30,17 +30,33 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#if defined(HAVE_SYS_TYPES_H)
|
||||||
|
# include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
#ifdef WITH_DEBUG
|
||||||
|
# include <libutil.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <freefare.h>
|
#include <freefare.h>
|
||||||
#include "freefare_internal.h"
|
#include "freefare_internal.h"
|
||||||
|
|
||||||
#define ASSERT_VALID_PAGE(page) do { if (page >= MIFARE_ULTRALIGHT_PAGE_COUNT) return errno = EINVAL, -1; } while (0)
|
#define ASSERT_VALID_PAGE(page) do { if (page >= MIFARE_ULTRALIGHT_PAGE_COUNT) return errno = EINVAL, -1; } while (0)
|
||||||
|
|
||||||
|
#define ULTRALIGHT_TRANSCEIVE(tag, msg, res) \
|
||||||
|
do { \
|
||||||
|
errno = 0; \
|
||||||
|
DEBUG_XFER (msg, __##msg##_n, "===> "); \
|
||||||
|
if (!(nfc_initiator_transceive_dep_bytes (tag->device, msg, __##msg##_n, res, &__##res##_n))) { \
|
||||||
|
return errno = EIO, -1; \
|
||||||
|
} \
|
||||||
|
DEBUG_XFER (res, __##res##_n, "<=== "); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Memory management functions.
|
* Memory management functions.
|
||||||
|
@ -132,15 +148,13 @@ mifare_ultralight_read (MifareTag tag, MifareUltralightPageNumber page, MifareUl
|
||||||
ASSERT_VALID_PAGE (page);
|
ASSERT_VALID_PAGE (page);
|
||||||
|
|
||||||
if (!MIFARE_ULTRALIGHT(tag)->cached_pages[page]) {
|
if (!MIFARE_ULTRALIGHT(tag)->cached_pages[page]) {
|
||||||
uint8_t cmd[2];
|
BUFFER_INIT (cmd, 2);
|
||||||
cmd[0] = 0x30;
|
BUFFER_ALIAS (res, MIFARE_ULTRALIGHT(tag)->cache[page]);
|
||||||
cmd[1] = page;
|
|
||||||
|
|
||||||
size_t n;
|
BUFFER_APPEND (cmd, 0x30);
|
||||||
if (!(nfc_initiator_transceive_dep_bytes (tag->device, cmd, sizeof (cmd), MIFARE_ULTRALIGHT(tag)->cache[page], &n))) {
|
BUFFER_APPEND (cmd, page);
|
||||||
errno = EIO;
|
|
||||||
return -1;
|
ULTRALIGHT_TRANSCEIVE (tag, cmd, res);
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle wrapped pages */
|
/* Handle wrapped pages */
|
||||||
for (int i = MIFARE_ULTRALIGHT_PAGE_COUNT; i <= page + 3; i++) {
|
for (int i = MIFARE_ULTRALIGHT_PAGE_COUNT; i <= page + 3; i++) {
|
||||||
|
|
Loading…
Reference in a new issue