mirror of
https://github.com/nfc-tools/mfcuk.git
synced 2026-02-18 02:55:49 +00:00
Attempt to make it work with libnfc 1.3.9
This commit is contained in:
parent
b628fa2e6e
commit
26006db05e
@ -1,7 +1,17 @@
|
|||||||
bin_PROGRAMS = mfcuk_keyrecovery_darkside
|
bin_PROGRAMS = mfcuk_keyrecovery_darkside
|
||||||
|
|
||||||
# set the include path found by configure
|
# set the include path found by configure
|
||||||
mfcuk_keyrecovery_darkside_SOURCES = mfcuk_keyrecovery_darkside.c mfcuk_mifare.c mfcuk_utils.c mfcuk_finger.c crapto1.c crypto1.c
|
mfcuk_keyrecovery_darkside_SOURCES = \
|
||||||
|
crapto1.c \
|
||||||
|
crypto1.c \
|
||||||
|
mfcuk_finger.c \
|
||||||
|
mfcuk_keyrecovery_darkside.c \
|
||||||
|
mfcuk_mifare.c \
|
||||||
|
mfcuk_utils.c \
|
||||||
|
mifare.c \
|
||||||
|
mirror-subr.c \
|
||||||
|
nfc-utils.c
|
||||||
|
|
||||||
mfcuk_keyrecovery_darkside_LDADD = -lnfc -lusb -lpcsclite
|
mfcuk_keyrecovery_darkside_LDADD = -lnfc -lusb -lpcsclite
|
||||||
|
|
||||||
# dist_man_MANS = mfcuk_keyrecovery_darkside.1
|
# dist_man_MANS = mfcuk_keyrecovery_darkside.1
|
||||||
|
|||||||
@ -47,7 +47,7 @@ mfcuk_finger_tmpl_entry mfcuk_finger_db[] =
|
|||||||
|
|
||||||
int mfcuk_finger_db_entries = sizeof(mfcuk_finger_db)/sizeof(mfcuk_finger_db[0]);
|
int mfcuk_finger_db_entries = sizeof(mfcuk_finger_db)/sizeof(mfcuk_finger_db[0]);
|
||||||
|
|
||||||
int mfcuk_finger_default_decoder(mifare_tag *dump)
|
int mfcuk_finger_default_decoder(mifare_classic_tag *dump)
|
||||||
{
|
{
|
||||||
if (!dump)
|
if (!dump)
|
||||||
{
|
{
|
||||||
@ -62,7 +62,7 @@ int mfcuk_finger_default_decoder(mifare_tag *dump)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Yes, I know C++ class inheritance would perfectly fit the decoders/comparators... Though C is more to my heart. Anyone to rewrite in C++?
|
// Yes, I know C++ class inheritance would perfectly fit the decoders/comparators... Though C is more to my heart. Anyone to rewrite in C++?
|
||||||
int mfcuk_finger_skgt_decoder(mifare_tag *dump)
|
int mfcuk_finger_skgt_decoder(mifare_classic_tag *dump)
|
||||||
{
|
{
|
||||||
unsigned char *dump_ptr = NULL;
|
unsigned char *dump_ptr = NULL;
|
||||||
unsigned short car_number = 0;
|
unsigned short car_number = 0;
|
||||||
@ -85,7 +85,7 @@ int mfcuk_finger_skgt_decoder(mifare_tag *dump)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mfcuk_finger_default_comparator(mifare_tag *dump, mfcuk_finger_template *tmpl, float *score)
|
int mfcuk_finger_default_comparator(mifare_classic_tag *dump, mfcuk_finger_template *tmpl, float *score)
|
||||||
{
|
{
|
||||||
int max_bytes = 0;
|
int max_bytes = 0;
|
||||||
int i;
|
int i;
|
||||||
@ -140,8 +140,8 @@ int mfcuk_finger_default_comparator(mifare_tag *dump, mfcuk_finger_template *tmp
|
|||||||
int mfcuk_finger_load()
|
int mfcuk_finger_load()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
mifare_tag mask;
|
mifare_classic_tag mask;
|
||||||
mifare_tag values;
|
mifare_classic_tag values;
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
size_t result = 0;
|
size_t result = 0;
|
||||||
mfcuk_finger_template *tmpl_new = NULL;
|
mfcuk_finger_template *tmpl_new = NULL;
|
||||||
|
|||||||
@ -47,13 +47,13 @@
|
|||||||
// Wrapping an ugly template into an externally pleasant name. To implement proper template later.
|
// Wrapping an ugly template into an externally pleasant name. To implement proper template later.
|
||||||
typedef struct _mfcuk_finger_template_
|
typedef struct _mfcuk_finger_template_
|
||||||
{
|
{
|
||||||
mifare_tag mask;
|
mifare_classic_tag mask;
|
||||||
mifare_tag values;
|
mifare_classic_tag values;
|
||||||
} mfcuk_finger_template;
|
} mfcuk_finger_template;
|
||||||
|
|
||||||
// Function type definition, to be used for custom decoders/comparators
|
// Function type definition, to be used for custom decoders/comparators
|
||||||
typedef int (*mfcuk_finger_comparator) (mifare_tag *dump, mfcuk_finger_template *tmpl, float *score);
|
typedef int (*mfcuk_finger_comparator) (mifare_classic_tag *dump, mfcuk_finger_template *tmpl, float *score);
|
||||||
typedef int (*mfcuk_finger_decoder) (mifare_tag *dump);
|
typedef int (*mfcuk_finger_decoder) (mifare_classic_tag *dump);
|
||||||
|
|
||||||
// Naive implementation of a self-contained fingerprint database entry
|
// Naive implementation of a self-contained fingerprint database entry
|
||||||
typedef struct _mfcuk_finger_tmpl_entry_
|
typedef struct _mfcuk_finger_tmpl_entry_
|
||||||
@ -65,9 +65,9 @@ typedef struct _mfcuk_finger_tmpl_entry_
|
|||||||
mfcuk_finger_template *tmpl_data;
|
mfcuk_finger_template *tmpl_data;
|
||||||
} mfcuk_finger_tmpl_entry;
|
} mfcuk_finger_tmpl_entry;
|
||||||
|
|
||||||
int mfcuk_finger_default_comparator(mifare_tag *dump, mfcuk_finger_template *tmpl, float *score);
|
int mfcuk_finger_default_comparator(mifare_classic_tag *dump, mfcuk_finger_template *tmpl, float *score);
|
||||||
int mfcuk_finger_default_decoder(mifare_tag *dump);
|
int mfcuk_finger_default_decoder(mifare_classic_tag *dump);
|
||||||
int mfcuk_finger_skgt_decoder(mifare_tag *dump);
|
int mfcuk_finger_skgt_decoder(mifare_classic_tag *dump);
|
||||||
|
|
||||||
// "Housekeeping" functions
|
// "Housekeeping" functions
|
||||||
int mfcuk_finger_load();
|
int mfcuk_finger_load();
|
||||||
|
|||||||
@ -131,13 +131,23 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// NFC
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
#include <nfc/nfc-types.h>
|
||||||
|
|
||||||
|
// Crapto1
|
||||||
#include "crapto1.h"
|
#include "crapto1.h"
|
||||||
// FIXME: For some reason (reason=I am dumb perhaps), these two prototypes are not visible form crapto1.h, so I put them here
|
// FIXME: For some reason (reason=I am dumb perhaps), these two prototypes are not visible form crapto1.h, so I put them here
|
||||||
struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]);
|
struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]);
|
||||||
uint32_t lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb);
|
uint32_t lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb);
|
||||||
// :FIXME
|
// :FIXME
|
||||||
#include <nfc/mifaretag.h>
|
|
||||||
|
// imported from libnfc's examples
|
||||||
|
#include "mifare.h"
|
||||||
|
#include "nfc-utils.h"
|
||||||
|
#include "mirror-subr.h"
|
||||||
|
|
||||||
|
// internal
|
||||||
#include "mfcuk_mifare.h"
|
#include "mfcuk_mifare.h"
|
||||||
#include "mfcuk_utils.h"
|
#include "mfcuk_utils.h"
|
||||||
#include "mfcuk_finger.h"
|
#include "mfcuk_finger.h"
|
||||||
@ -215,6 +225,9 @@ uint32_t mfcuk_verify_key_block(nfc_device_t* pnd, uint32_t uiUID, uint64_t ui64
|
|||||||
return MFCUK_FAIL_COMM;
|
return MFCUK_FAIL_COMM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We need to disable EASY_FRAMING feature to talk in "raw" mode
|
||||||
|
nfc_configure (pnd, NDO_EASY_FRAMING, false);
|
||||||
|
|
||||||
// Request plain tag-nonce
|
// Request plain tag-nonce
|
||||||
if (!nfc_initiator_transceive_bytes(pnd,abtAuth,4,abtRx,&szRx))
|
if (!nfc_initiator_transceive_bytes(pnd,abtAuth,4,abtRx,&szRx))
|
||||||
{
|
{
|
||||||
@ -222,7 +235,7 @@ uint32_t mfcuk_verify_key_block(nfc_device_t* pnd, uint32_t uiUID, uint64_t ui64
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save the tag nonce (nt)
|
// Save the tag nonce (nt)
|
||||||
nt = swap_endian32(abtRx);
|
nt = mirror_bytes(abtRx, 4);
|
||||||
nt_orig = nt;
|
nt_orig = nt;
|
||||||
|
|
||||||
// Init cipher with key
|
// Init cipher with key
|
||||||
@ -372,7 +385,7 @@ uint32_t mfcuk_key_recovery_block(nfc_device_t* pnd, uint32_t uiUID, uint64_t ui
|
|||||||
//print_hex(abtRx,4);
|
//print_hex(abtRx,4);
|
||||||
|
|
||||||
// Save the tag nonce (nt)
|
// Save the tag nonce (nt)
|
||||||
nt = swap_endian32(abtRx);
|
nt = mirror_bytes(abtRx, 4);
|
||||||
|
|
||||||
// zveriu
|
// zveriu
|
||||||
//printf("INFO - Nonce distance %d (from 0x%08x, to 0x%08x)\n", nonce_distance(nt, nt_orig), nt, nt_orig);
|
//printf("INFO - Nonce distance %d (from 0x%08x, to 0x%08x)\n", nonce_distance(nt, nt_orig), nt, nt_orig);
|
||||||
@ -672,9 +685,9 @@ void print_usage(FILE *fp)
|
|||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
fprintf(fp, "Usage:\n");
|
fprintf(fp, "Usage:\n");
|
||||||
fprintf(fp, "-C - require explicit connection to the reader. Without this option, the connection is not made and recovery will not occur\n");
|
fprintf(fp, "-C - require explicit connection to the reader. Without this option, the connection is not made and recovery will not occur\n");
|
||||||
fprintf(fp, "-i mifare.dmp - load input mifare_tag type dump\n");
|
fprintf(fp, "-i mifare.dmp - load input mifare_classic_tag type dump\n");
|
||||||
fprintf(fp, "-I mifare_ext.dmp - load input extended dump specific to this tool, has several more fields on top of mifare_tag type dump\n");
|
fprintf(fp, "-I mifare_ext.dmp - load input extended dump specific to this tool, has several more fields on top of mifare_classic_tag type dump\n");
|
||||||
fprintf(fp, "-o mifare.dmp - output the resulting mifare_tag dump to a given file\n");
|
fprintf(fp, "-o mifare.dmp - output the resulting mifare_classic_tag dump to a given file\n");
|
||||||
fprintf(fp, "-O mifare_ext.dmp - output the resulting extended dump to a given file\n");
|
fprintf(fp, "-O mifare_ext.dmp - output the resulting extended dump to a given file\n");
|
||||||
fprintf(fp, "-V sector[:A/B/any_other_alphanum[:fullkey]] - verify key for specified sector, -1 means all sectors\n");
|
fprintf(fp, "-V sector[:A/B/any_other_alphanum[:fullkey]] - verify key for specified sector, -1 means all sectors\n");
|
||||||
fprintf(fp, "\tAfter first semicolon key-type can specified: A verifies only keyA, B verifies only keyB, anything else verifies both keys\n");
|
fprintf(fp, "\tAfter first semicolon key-type can specified: A verifies only keyA, B verifies only keyB, anything else verifies both keys\n");
|
||||||
@ -707,11 +720,11 @@ void print_identification()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void print_mifare_tag_actions(const char *title, mifare_tag *tag)
|
void print_mifare_classic_tag_actions(const char *title, mifare_classic_tag *tag)
|
||||||
{
|
{
|
||||||
uint32_t i, max_blocks, trailer_block;
|
uint32_t i, max_blocks, trailer_block;
|
||||||
byte_t bTagType;
|
byte_t bTagType;
|
||||||
mifare_block_trailer *ptr_trailer = NULL;
|
mifare_classic_block_trailer *ptr_trailer = NULL;
|
||||||
|
|
||||||
if (!tag)
|
if (!tag)
|
||||||
{
|
{
|
||||||
@ -751,7 +764,7 @@ void print_mifare_tag_actions(const char *title, mifare_tag *tag)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr_trailer = (mifare_block_trailer *) ((char *)tag + (trailer_block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
ptr_trailer = (mifare_classic_block_trailer *) ((char *)tag + (trailer_block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
||||||
|
|
||||||
printf("%d\t| %02x%02x%02x%02x%02x%02x\t| %c %c | %c %c\t| %02x%02x%02x%02x%02x%02x\t| %c %c | %c %c\n",
|
printf("%d\t| %02x%02x%02x%02x%02x%02x\t| %c %c | %c %c\t| %02x%02x%02x%02x%02x%02x\t| %c %c | %c %c\n",
|
||||||
get_sector_for_block(bTagType, trailer_block),
|
get_sector_for_block(bTagType, trailer_block),
|
||||||
@ -846,7 +859,7 @@ bool mfcuk_darkside_select_tag(nfc_device_t* pnd, int iSleepAtFieldOFF, int iSle
|
|||||||
sleep(iSleepAfterFieldON);
|
sleep(iSleepAfterFieldON);
|
||||||
|
|
||||||
// Poll for a ISO14443A (MIFARE) tag
|
// Poll for a ISO14443A (MIFARE) tag
|
||||||
if (!nfc_initiator_select_tag(pnd,NM_ISO14443A_106,NULL,0,&ti_tmp))
|
if (!nfc_initiator_select_passive_target(pnd,NM_ISO14443A_106,NULL,0,&ti_tmp))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "ERROR: connecting to MIFARE Classic tag\n");
|
fprintf(stderr, "ERROR: connecting to MIFARE Classic tag\n");
|
||||||
//nfc_disconnect(pnd);
|
//nfc_disconnect(pnd);
|
||||||
@ -866,8 +879,8 @@ int main(int argc, char* argv[])
|
|||||||
//char extendedDescription[MFCUK_EXTENDED_DESCRIPTION_LENGTH] = {0}; // Initialize with '\0' character
|
//char extendedDescription[MFCUK_EXTENDED_DESCRIPTION_LENGTH] = {0}; // Initialize with '\0' character
|
||||||
byte_t keyOpt[MIFARE_CLASSIC_KEY_BYTELENGTH] = {0};
|
byte_t keyOpt[MIFARE_CLASSIC_KEY_BYTELENGTH] = {0};
|
||||||
byte_t uidOpt[MIFARE_CLASSIC_UID_BYTELENGTH] = {0};
|
byte_t uidOpt[MIFARE_CLASSIC_UID_BYTELENGTH] = {0};
|
||||||
mifare_block_trailer *ptr_trailer = NULL;
|
mifare_classic_block_trailer *ptr_trailer = NULL;
|
||||||
mifare_block_trailer *ptr_trailer_dump = NULL;
|
mifare_classic_block_trailer *ptr_trailer_dump = NULL;
|
||||||
int sector = 0;
|
int sector = 0;
|
||||||
uint32_t block = 0;
|
uint32_t block = 0;
|
||||||
byte_t action = 0;
|
byte_t action = 0;
|
||||||
@ -891,13 +904,13 @@ int main(int argc, char* argv[])
|
|||||||
uint64_t ui64Key = 0xc1e51c63b8f5;//0xffffffffffff;
|
uint64_t ui64Key = 0xc1e51c63b8f5;//0xffffffffffff;
|
||||||
uint32_t uiErrCode = MFCUK_SUCCESS;
|
uint32_t uiErrCode = MFCUK_SUCCESS;
|
||||||
uint64_t ui64KeyRecovered;
|
uint64_t ui64KeyRecovered;
|
||||||
mifare_tag_ext dump_loaded_tag;
|
mifare_classic_tag_ext dump_loaded_tag;
|
||||||
mifare_tag_ext tag_on_reader;
|
mifare_classic_tag_ext tag_on_reader;
|
||||||
mifare_tag_ext tag_recover_verify;
|
mifare_classic_tag_ext tag_recover_verify;
|
||||||
mifare_key_type bKeyType = keyA;
|
mifare_key_type bKeyType = keyA;
|
||||||
|
|
||||||
// fingerprint options related
|
// fingerprint options related
|
||||||
mifare_tag finger_tag;
|
mifare_classic_tag finger_tag;
|
||||||
float finger_score;
|
float finger_score;
|
||||||
float finger_score_highest;
|
float finger_score_highest;
|
||||||
int finger_index_highest;
|
int finger_index_highest;
|
||||||
@ -1059,7 +1072,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
if (st >= MIFARE_CLASSIC_UID_BYTELENGTH)
|
if (st >= MIFARE_CLASSIC_UID_BYTELENGTH)
|
||||||
{
|
{
|
||||||
tag_recover_verify.uid = swap_endian32(uidOpt);
|
tag_recover_verify.uid = mirror_bytes(uidOpt, 4);
|
||||||
memcpy( tag_recover_verify.tag_basic.amb[0].mbm.abtUID, uidOpt, MIFARE_CLASSIC_UID_BYTELENGTH );
|
memcpy( tag_recover_verify.tag_basic.amb[0].mbm.abtUID, uidOpt, MIFARE_CLASSIC_UID_BYTELENGTH );
|
||||||
bfOpts[ch] = true;
|
bfOpts[ch] = true;
|
||||||
}
|
}
|
||||||
@ -1125,7 +1138,7 @@ int main(int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
// TODO: proper error handling for block and ptr_trailer
|
// TODO: proper error handling for block and ptr_trailer
|
||||||
block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i);
|
block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i);
|
||||||
ptr_trailer = (mifare_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
ptr_trailer = (mifare_classic_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
||||||
|
|
||||||
ptr_trailer->abtAccessBits[ACTIONS_KEY_A] |= action;
|
ptr_trailer->abtAccessBits[ACTIONS_KEY_A] |= action;
|
||||||
ptr_trailer->abtAccessBits[ACTIONS_KEY_B] |= action;
|
ptr_trailer->abtAccessBits[ACTIONS_KEY_B] |= action;
|
||||||
@ -1146,7 +1159,7 @@ int main(int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
// TODO: proper error handling for block and ptr_trailer
|
// TODO: proper error handling for block and ptr_trailer
|
||||||
block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i);
|
block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i);
|
||||||
ptr_trailer = (mifare_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
ptr_trailer = (mifare_classic_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
||||||
|
|
||||||
ptr_trailer->abtAccessBits[ACTIONS_KEY_B * (1 - (token[0]-'A'))] &= (~action);
|
ptr_trailer->abtAccessBits[ACTIONS_KEY_B * (1 - (token[0]-'A'))] &= (~action);
|
||||||
}
|
}
|
||||||
@ -1159,7 +1172,7 @@ int main(int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
// TODO: proper error handling for block and ptr_trailer
|
// TODO: proper error handling for block and ptr_trailer
|
||||||
block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i);
|
block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i);
|
||||||
ptr_trailer = (mifare_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
ptr_trailer = (mifare_classic_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
||||||
|
|
||||||
ptr_trailer->abtAccessBits[ACTIONS_KEY_A] |= action;
|
ptr_trailer->abtAccessBits[ACTIONS_KEY_A] |= action;
|
||||||
ptr_trailer->abtAccessBits[ACTIONS_KEY_B] |= action;
|
ptr_trailer->abtAccessBits[ACTIONS_KEY_B] |= action;
|
||||||
@ -1200,7 +1213,7 @@ int main(int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
// TODO: proper error handling for block and ptr_trailer
|
// TODO: proper error handling for block and ptr_trailer
|
||||||
block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i);
|
block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i);
|
||||||
ptr_trailer = (mifare_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
ptr_trailer = (mifare_classic_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
||||||
|
|
||||||
if ( !specific_key_type || specific_key_type == keyA )
|
if ( !specific_key_type || specific_key_type == keyA )
|
||||||
{
|
{
|
||||||
@ -1224,7 +1237,7 @@ int main(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
// Input simple dump file of type mifare_tag, Options i and I are autoexclusive
|
// Input simple dump file of type mifare_classic_tag, Options i and I are autoexclusive
|
||||||
if (!bfOpts['i'] && !bfOpts['I'])
|
if (!bfOpts['i'] && !bfOpts['I'])
|
||||||
{
|
{
|
||||||
if ( !mfcuk_load_tag_dump(optarg, &(dump_loaded_tag.tag_basic)) )
|
if ( !mfcuk_load_tag_dump(optarg, &(dump_loaded_tag.tag_basic)) )
|
||||||
@ -1238,7 +1251,7 @@ int main(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
// // Input extended dump file of type mifare_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 (!bfOpts['i'] && !bfOpts['I'])
|
||||||
{
|
{
|
||||||
if ( !mfcuk_load_tag_dump_ext(optarg, &(dump_loaded_tag)) )
|
if ( !mfcuk_load_tag_dump_ext(optarg, &(dump_loaded_tag)) )
|
||||||
@ -1405,7 +1418,7 @@ int main(int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
if (bfOpts['v'] && (verboseLevel > 0))
|
if (bfOpts['v'] && (verboseLevel > 0))
|
||||||
{
|
{
|
||||||
print_mifare_tag_keys("LOADED TAG DUMP", &(dump_loaded_tag.tag_basic));
|
print_mifare_classic_tag_keys("LOADED TAG DUMP", &(dump_loaded_tag.tag_basic));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overwrite from the loaded dump only the keys for sectors and keys which were not specified on command line
|
// Overwrite from the loaded dump only the keys for sectors and keys which were not specified on command line
|
||||||
@ -1413,8 +1426,8 @@ int main(int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
// TODO: proper error handling for block and ptr_trailer
|
// TODO: proper error handling for block and ptr_trailer
|
||||||
block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i);
|
block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i);
|
||||||
ptr_trailer = (mifare_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
ptr_trailer = (mifare_classic_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
||||||
ptr_trailer_dump = (mifare_block_trailer *) ((char *)(&dump_loaded_tag.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
ptr_trailer_dump = (mifare_classic_block_trailer *) ((char *)(&dump_loaded_tag.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
||||||
|
|
||||||
// If no command line keyA is set, copy from loaded dump
|
// If no command line keyA is set, copy from loaded dump
|
||||||
if ( !(ptr_trailer->abtAccessBits[ACTIONS_KEY_A] & ACTIONS_KEYSET) )
|
if ( !(ptr_trailer->abtAccessBits[ACTIONS_KEY_A] & ACTIONS_KEYSET) )
|
||||||
@ -1434,12 +1447,12 @@ int main(int argc, char* argv[])
|
|||||||
// If no command line UID supplied and not tag-type specified, copy the manufacturer block from the loaded dump
|
// If no command line UID supplied and not tag-type specified, copy the manufacturer block from the loaded dump
|
||||||
if ( !bfOpts['U'] && !bfOpts['M'] )
|
if ( !bfOpts['U'] && !bfOpts['M'] )
|
||||||
{
|
{
|
||||||
ptr_trailer = (mifare_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (0 * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
ptr_trailer = (mifare_classic_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (0 * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
||||||
ptr_trailer_dump = (mifare_block_trailer *) ((char *)(&dump_loaded_tag.tag_basic) + (0 * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
ptr_trailer_dump = (mifare_classic_block_trailer *) ((char *)(&dump_loaded_tag.tag_basic) + (0 * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
||||||
|
|
||||||
memcpy( ptr_trailer, ptr_trailer_dump, sizeof(*ptr_trailer) );
|
memcpy( ptr_trailer, ptr_trailer_dump, sizeof(*ptr_trailer) );
|
||||||
tag_recover_verify.type = tag_recover_verify.tag_basic.amb[0].mbm.btUnknown;
|
tag_recover_verify.type = tag_recover_verify.tag_basic.amb[0].mbm.btUnknown;
|
||||||
tag_recover_verify.uid = swap_endian32(tag_recover_verify.tag_basic.amb[0].mbm.abtUID);
|
tag_recover_verify.uid = mirror_bytes(tag_recover_verify.tag_basic.amb[0].mbm.abtUID, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1490,19 +1503,19 @@ int main(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tag on the reader UID
|
// Tag on the reader UID
|
||||||
tag_on_reader.uid = swap_endian32(ti.nai.abtUid);
|
tag_on_reader.uid = mirror_bytes(ti.nai.abtUid, 4);
|
||||||
memcpy( tag_on_reader.tag_basic.amb[0].mbm.abtUID, ti.nai.abtUid, MIFARE_CLASSIC_UID_BYTELENGTH);
|
memcpy( tag_on_reader.tag_basic.amb[0].mbm.abtUID, ti.nai.abtUid, MIFARE_CLASSIC_UID_BYTELENGTH);
|
||||||
|
|
||||||
// No command line tag UID specified, take it from the tag on the reader
|
// No command line tag UID specified, take it from the tag on the reader
|
||||||
if ( !bfOpts['U'] )
|
if ( !bfOpts['U'] )
|
||||||
{
|
{
|
||||||
tag_recover_verify.uid = swap_endian32(ti.nai.abtUid);
|
tag_recover_verify.uid = mirror_bytes(ti.nai.abtUid, 4);
|
||||||
memcpy( tag_recover_verify.tag_basic.amb[0].mbm.abtUID, ti.nai.abtUid, MIFARE_CLASSIC_UID_BYTELENGTH);
|
memcpy( tag_recover_verify.tag_basic.amb[0].mbm.abtUID, ti.nai.abtUid, MIFARE_CLASSIC_UID_BYTELENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bfOpts['v'] && (verboseLevel > 0))
|
if (bfOpts['v'] && (verboseLevel > 0))
|
||||||
{
|
{
|
||||||
print_mifare_tag_actions("\n\nINITIAL ACTIONS MATRIX", &(tag_recover_verify.tag_basic));
|
print_mifare_classic_tag_actions("\n\nINITIAL ACTIONS MATRIX", &(tag_recover_verify.tag_basic));
|
||||||
}
|
}
|
||||||
|
|
||||||
max_sectors = (IS_MIFARE_CLASSIC_1K(tag_recover_verify.type)?MIFARE_CLASSIC_1K_MAX_SECTORS:MIFARE_CLASSIC_4K_MAX_SECTORS);
|
max_sectors = (IS_MIFARE_CLASSIC_1K(tag_recover_verify.type)?MIFARE_CLASSIC_1K_MAX_SECTORS:MIFARE_CLASSIC_4K_MAX_SECTORS);
|
||||||
@ -1531,7 +1544,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// TODO: proper error handling
|
// TODO: proper error handling
|
||||||
block = get_trailer_block_for_sector(crntVerifTagType, i);
|
block = get_trailer_block_for_sector(crntVerifTagType, i);
|
||||||
ptr_trailer = (mifare_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
ptr_trailer = (mifare_classic_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
||||||
|
|
||||||
// If DEFAULT KEYS option was specified, crntNumVerifKeys is already taking care of them
|
// If DEFAULT KEYS option was specified, crntNumVerifKeys is already taking care of them
|
||||||
// Also, perform verification ontly if the sector has been marked for verification of key and not valid verification yet occured in the loop
|
// Also, perform verification ontly if the sector has been marked for verification of key and not valid verification yet occured in the loop
|
||||||
@ -1552,7 +1565,7 @@ int main(int argc, char* argv[])
|
|||||||
fprintf(stderr, "WARN: mfcuk_key_arr_to_uint64() failed, verification key will be %012llx\n", crntVerifKey);
|
fprintf(stderr, "WARN: mfcuk_key_arr_to_uint64() failed, verification key will be %012llx\n", crntVerifKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// TODO: make this kind of key verification as part of option -a - advanced verification of keys with crapto1 rollback for double verification
|
// TODO: make this kind of key verification as part of option -a - advanced verification of keys with crapto1 rollback for double verification
|
||||||
// TEST
|
// TEST
|
||||||
nfc_disconnect(pnd);
|
nfc_disconnect(pnd);
|
||||||
@ -1591,12 +1604,11 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// Reset advanced settings
|
// Reset advanced settings
|
||||||
mfcuk_darkside_reset_advanced(pnd);
|
mfcuk_darkside_reset_advanced(pnd);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
memcpy(mp.mpa.abtUid, tag_recover_verify.tag_basic.amb[0].mbm.abtUID, MIFARE_CLASSIC_UID_BYTELENGTH);
|
memcpy(mp.mpa.abtUid, tag_recover_verify.tag_basic.amb[0].mbm.abtUID, MIFARE_CLASSIC_UID_BYTELENGTH);
|
||||||
memcpy(mp.mpa.abtKey, &(current_default_keys[j][0]), MIFARE_CLASSIC_KEY_BYTELENGTH);
|
memcpy(mp.mpa.abtKey, &(current_default_keys[j][0]), MIFARE_CLASSIC_KEY_BYTELENGTH);
|
||||||
|
|
||||||
if ( !nfc_initiator_select_tag(pnd, NM_ISO14443A_106, NULL, 0, &ti) )
|
if ( !nfc_initiator_select_passive_target(pnd, NM_ISO14443A_106, NULL, 0, &ti) )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "ERROR: tag was removed or cannot be selected\n");
|
fprintf(stderr, "ERROR: tag was removed or cannot be selected\n");
|
||||||
}
|
}
|
||||||
@ -1621,7 +1633,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
if ( bfOpts['v'] && (verboseLevel > 0) )
|
if ( bfOpts['v'] && (verboseLevel > 0) )
|
||||||
{
|
{
|
||||||
print_mifare_tag_actions("\n\nACTION RESULTS MATRIX AFTER VERIFY", &(tag_recover_verify.tag_basic));
|
print_mifare_classic_tag_actions("\n\nACTION RESULTS MATRIX AFTER VERIFY", &(tag_recover_verify.tag_basic));
|
||||||
}
|
}
|
||||||
|
|
||||||
// RECOVER KEYS CODE-BLOCK
|
// RECOVER KEYS CODE-BLOCK
|
||||||
@ -1632,7 +1644,7 @@ int main(int argc, char* argv[])
|
|||||||
ui64KeyRecovered = 0;
|
ui64KeyRecovered = 0;
|
||||||
|
|
||||||
block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i);
|
block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i);
|
||||||
ptr_trailer = (mifare_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
ptr_trailer = (mifare_classic_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
||||||
|
|
||||||
printf(" %x", i);
|
printf(" %x", i);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
@ -1723,7 +1735,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
if ( bfOpts['v'] && (verboseLevel > 0) )
|
if ( bfOpts['v'] && (verboseLevel > 0) )
|
||||||
{
|
{
|
||||||
print_mifare_tag_actions("\n\nACTION RESULTS MATRIX AFTER RECOVER", &(tag_recover_verify.tag_basic));
|
print_mifare_classic_tag_actions("\n\nACTION RESULTS MATRIX AFTER RECOVER", &(tag_recover_verify.tag_basic));
|
||||||
}
|
}
|
||||||
|
|
||||||
// DUMP DATA CODE-BLOCK
|
// DUMP DATA CODE-BLOCK
|
||||||
@ -1732,7 +1744,7 @@ int main(int argc, char* argv[])
|
|||||||
for (i=0; i<max_sectors; i++)
|
for (i=0; i<max_sectors; i++)
|
||||||
{
|
{
|
||||||
block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i);
|
block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i);
|
||||||
ptr_trailer = (mifare_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
ptr_trailer = (mifare_classic_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
||||||
|
|
||||||
//nfc_initiator_mifare_cmd()
|
//nfc_initiator_mifare_cmd()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -357,7 +357,7 @@ void test_mifare_classic_blocks_sectors_functions(byte_t bTagType)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mfcuk_save_tag_dump(char *filename, mifare_tag *tag)
|
bool mfcuk_save_tag_dump(char *filename, mifare_classic_tag *tag)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
size_t result;
|
size_t result;
|
||||||
@ -382,7 +382,7 @@ bool mfcuk_save_tag_dump(char *filename, mifare_tag *tag)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mfcuk_save_tag_dump_ext(char *filename, mifare_tag_ext *tag_ext)
|
bool mfcuk_save_tag_dump_ext(char *filename, mifare_classic_tag_ext *tag_ext)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
size_t result;
|
size_t result;
|
||||||
@ -407,7 +407,7 @@ bool mfcuk_save_tag_dump_ext(char *filename, mifare_tag_ext *tag_ext)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mfcuk_load_tag_dump(char *filename, mifare_tag *tag)
|
bool mfcuk_load_tag_dump(char *filename, mifare_classic_tag *tag)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
size_t result;
|
size_t result;
|
||||||
@ -432,7 +432,7 @@ bool mfcuk_load_tag_dump(char *filename, mifare_tag *tag)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mfcuk_load_tag_dump_ext(char *filename, mifare_tag_ext *tag_ext)
|
bool mfcuk_load_tag_dump_ext(char *filename, mifare_classic_tag_ext *tag_ext)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
size_t result;
|
size_t result;
|
||||||
@ -457,11 +457,11 @@ bool mfcuk_load_tag_dump_ext(char *filename, mifare_tag_ext *tag_ext)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_mifare_tag_keys(const char *title, mifare_tag *tag)
|
void print_mifare_classic_tag_keys(const char *title, mifare_classic_tag *tag)
|
||||||
{
|
{
|
||||||
uint32_t i, max_blocks, trailer_block;
|
uint32_t i, max_blocks, trailer_block;
|
||||||
byte_t bTagType;
|
byte_t bTagType;
|
||||||
mifare_block_trailer *ptr_trailer = NULL;
|
mifare_classic_block_trailer *ptr_trailer = NULL;
|
||||||
|
|
||||||
if (!tag)
|
if (!tag)
|
||||||
{
|
{
|
||||||
@ -501,7 +501,7 @@ void print_mifare_tag_keys(const char *title, mifare_tag *tag)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr_trailer = (mifare_block_trailer *) ((char *)tag + (trailer_block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
ptr_trailer = (mifare_classic_block_trailer *) ((char *)tag + (trailer_block * MIFARE_CLASSIC_BYTES_PER_BLOCK) );
|
||||||
|
|
||||||
printf("%d\t| %02x%02x%02x%02x%02x%02x\t| %02x%02x%02x%02x\t| %02x%02x%02x%02x%02x%02x\n",
|
printf("%d\t| %02x%02x%02x%02x%02x%02x\t| %02x%02x%02x%02x\t| %02x%02x%02x%02x%02x%02x\n",
|
||||||
get_sector_for_block(bTagType, trailer_block),
|
get_sector_for_block(bTagType, trailer_block),
|
||||||
|
|||||||
@ -57,7 +57,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
#include <nfc/mifaretag.h>
|
#include "mifare.h"
|
||||||
|
|
||||||
#define MIFARE_CLASSIC_UID_BYTELENGTH 4 // Length of a Mifare Classic UID in bytes
|
#define MIFARE_CLASSIC_UID_BYTELENGTH 4 // Length of a Mifare Classic UID in bytes
|
||||||
#define MIFARE_CLASSIC_KEY_BYTELENGTH 6 // Length of a Mifare Classic key in bytes
|
#define MIFARE_CLASSIC_KEY_BYTELENGTH 6 // Length of a Mifare Classic key in bytes
|
||||||
@ -104,8 +104,8 @@ typedef struct {
|
|||||||
byte_t type; // ATS/SAK from ti.tia.btSak, example 0x08h for Mifare 1K, 0x18h for Mifare 4K
|
byte_t type; // ATS/SAK from ti.tia.btSak, example 0x08h for Mifare 1K, 0x18h for Mifare 4K
|
||||||
char datetime[14]; // non-zero-terminated date-time of dump in format YYYYMMDDH24MISS, example 20091114231541 - 14 Nov 2009, 11:15:41 PM
|
char datetime[14]; // non-zero-terminated date-time of dump in format YYYYMMDDH24MISS, example 20091114231541 - 14 Nov 2009, 11:15:41 PM
|
||||||
char description[MFCUK_EXTENDED_DESCRIPTION_LENGTH]; // a description of the tag dump, example "RATB_DUMP_BEFORE_PAY"
|
char description[MFCUK_EXTENDED_DESCRIPTION_LENGTH]; // a description of the tag dump, example "RATB_DUMP_BEFORE_PAY"
|
||||||
mifare_tag tag_basic;
|
mifare_classic_tag tag_basic;
|
||||||
} mifare_tag_ext;
|
} mifare_classic_tag_ext;
|
||||||
|
|
||||||
// Define type of keys (A or B) in NXP notation
|
// Define type of keys (A or B) in NXP notation
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -134,11 +134,11 @@ bool is_last_sector(byte_t bTagType, uint32_t uiSector);
|
|||||||
bool is_last_big_sector(byte_t bTagType, uint32_t uiSector);
|
bool is_last_big_sector(byte_t bTagType, uint32_t uiSector);
|
||||||
bool is_last_small_sector(byte_t bTagType, uint32_t uiSector);
|
bool is_last_small_sector(byte_t bTagType, uint32_t uiSector);
|
||||||
void test_mifare_classic_blocks_sectors_functions(byte_t bTagType);
|
void test_mifare_classic_blocks_sectors_functions(byte_t bTagType);
|
||||||
bool mfcuk_save_tag_dump(char *filename, mifare_tag *tag);
|
bool mfcuk_save_tag_dump(char *filename, mifare_classic_tag *tag);
|
||||||
bool mfcuk_save_tag_dump_ext(char *filename, mifare_tag_ext *tag_ext);
|
bool mfcuk_save_tag_dump_ext(char *filename, mifare_classic_tag_ext *tag_ext);
|
||||||
bool mfcuk_load_tag_dump(char *filename, mifare_tag *tag);
|
bool mfcuk_load_tag_dump(char *filename, mifare_classic_tag *tag);
|
||||||
bool mfcuk_load_tag_dump_ext(char *filename, mifare_tag_ext *tag_ext);
|
bool mfcuk_load_tag_dump_ext(char *filename, mifare_classic_tag_ext *tag_ext);
|
||||||
void print_mifare_tag_keys(const char *title, mifare_tag *tag);
|
void print_mifare_classic_tag_keys(const char *title, mifare_classic_tag *tag);
|
||||||
bool mfcuk_key_uint64_to_arr(const uint64_t *ui64Key, byte_t *arr6Key);
|
bool mfcuk_key_uint64_to_arr(const uint64_t *ui64Key, byte_t *arr6Key);
|
||||||
bool mfcuk_key_arr_to_uint64(const byte_t *arr6Key, uint64_t *ui64Key);
|
bool mfcuk_key_arr_to_uint64(const byte_t *arr6Key, uint64_t *ui64Key);
|
||||||
|
|
||||||
|
|||||||
85
src/mifare.c
Normal file
85
src/mifare.c
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#include "mifare.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Execute a MIFARE Classic Command
|
||||||
|
* @return Returns true if action was successfully performed; otherwise returns false.
|
||||||
|
* @param pmp Some commands need additional information. This information should be supplied in the mifare_param union.
|
||||||
|
*
|
||||||
|
* The specified MIFARE command will be executed on the tag. There are different commands possible, they all require the destination block number.
|
||||||
|
* @note There are three different types of information (Authenticate, Data and Value).
|
||||||
|
*
|
||||||
|
* First an authentication must take place using Key A or B. It requires a 48 bit Key (6 bytes) and the UID.
|
||||||
|
* They are both used to initialize the internal cipher-state of the PN53X chip (http://libnfc.org/hardware/pn53x-chip).
|
||||||
|
* After a successful authentication it will be possible to execute other commands (e.g. Read/Write).
|
||||||
|
* The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process.
|
||||||
|
*/
|
||||||
|
bool nfc_initiator_mifare_cmd(nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp)
|
||||||
|
{
|
||||||
|
byte_t abtRx[265];
|
||||||
|
size_t szRxLen;
|
||||||
|
size_t szParamLen;
|
||||||
|
byte_t abtCmd[265];
|
||||||
|
|
||||||
|
// Make sure we are dealing with a active device
|
||||||
|
if (!pnd->bActive) return false;
|
||||||
|
|
||||||
|
abtCmd[0] = mc; // The MIFARE Classic command
|
||||||
|
abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
|
||||||
|
|
||||||
|
switch (mc)
|
||||||
|
{
|
||||||
|
// Read and store command have no parameter
|
||||||
|
case MC_READ:
|
||||||
|
case MC_STORE:
|
||||||
|
szParamLen = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Authenticate command
|
||||||
|
case MC_AUTH_A:
|
||||||
|
case MC_AUTH_B:
|
||||||
|
szParamLen = sizeof(mifare_param_auth);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Data command
|
||||||
|
case MC_WRITE:
|
||||||
|
szParamLen = sizeof(mifare_param_data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Value command
|
||||||
|
case MC_DECREMENT:
|
||||||
|
case MC_INCREMENT:
|
||||||
|
case MC_TRANSFER:
|
||||||
|
szParamLen = sizeof(mifare_param_value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Please fix your code, you never should reach this statement
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When available, copy the parameter bytes
|
||||||
|
if (szParamLen) memcpy(abtCmd+2,(byte_t*)pmp,szParamLen);
|
||||||
|
|
||||||
|
// Fire the mifare command
|
||||||
|
if (!nfc_initiator_transceive_bytes(pnd,abtCmd,2+szParamLen,abtRx,&szRxLen)) {
|
||||||
|
nfc_perror (pnd, "nfc_initiator_transceive_bytes");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When we have executed a read command, copy the received bytes into the param
|
||||||
|
if (mc == MC_READ) {
|
||||||
|
if(szRxLen == 16) {
|
||||||
|
memcpy(pmp->mpd.abtData,abtRx,16);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command succesfully executed
|
||||||
|
return true;
|
||||||
|
}
|
||||||
127
src/mifare.h
Normal file
127
src/mifare.h
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/**
|
||||||
|
* Public platform independent Near Field Communication (NFC) library
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009, Roel Verdult, 2010, Romuald Conty
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @file mifaretag.h
|
||||||
|
* @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LIBNFC_MIFARE_H_
|
||||||
|
#define _LIBNFC_MIFARE_H_
|
||||||
|
|
||||||
|
#include <nfc/nfc-types.h>
|
||||||
|
|
||||||
|
// Compiler directive, set struct alignment to 1 byte_t for compatibility
|
||||||
|
#pragma pack(1)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MC_AUTH_A = 0x60,
|
||||||
|
MC_AUTH_B = 0x61,
|
||||||
|
MC_READ = 0x30,
|
||||||
|
MC_WRITE = 0xA0,
|
||||||
|
MC_TRANSFER = 0xB0,
|
||||||
|
MC_DECREMENT = 0xC0,
|
||||||
|
MC_INCREMENT = 0xC1,
|
||||||
|
MC_STORE = 0xC2
|
||||||
|
} mifare_cmd;
|
||||||
|
|
||||||
|
// MIFARE command params
|
||||||
|
typedef struct {
|
||||||
|
byte_t abtKey[6];
|
||||||
|
byte_t abtUid[4];
|
||||||
|
} mifare_param_auth;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
byte_t abtData[16];
|
||||||
|
} mifare_param_data;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
byte_t abtValue[4];
|
||||||
|
} mifare_param_value;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
mifare_param_auth mpa;
|
||||||
|
mifare_param_data mpd;
|
||||||
|
mifare_param_value mpv;
|
||||||
|
} mifare_param;
|
||||||
|
|
||||||
|
// Reset struct alignment to default
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
bool nfc_initiator_mifare_cmd(nfc_device_t* pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param* pmp);
|
||||||
|
|
||||||
|
// Compiler directive, set struct alignment to 1 byte_t for compatibility
|
||||||
|
#pragma pack(1)
|
||||||
|
|
||||||
|
// MIFARE Classic
|
||||||
|
typedef struct {
|
||||||
|
byte_t abtUID[4];
|
||||||
|
byte_t btBCC;
|
||||||
|
byte_t btUnknown;
|
||||||
|
byte_t abtATQA[2];
|
||||||
|
byte_t abtUnknown[8];
|
||||||
|
} mifare_classic_block_manufacturer;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
byte_t abtData[16];
|
||||||
|
} mifare_classic_block_data;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
byte_t abtKeyA[6];
|
||||||
|
byte_t abtAccessBits[4];
|
||||||
|
byte_t abtKeyB[6];
|
||||||
|
} mifare_classic_block_trailer;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
mifare_classic_block_manufacturer mbm;
|
||||||
|
mifare_classic_block_data mbd;
|
||||||
|
mifare_classic_block_trailer mbt;
|
||||||
|
} mifare_classic_block;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mifare_classic_block amb[256];
|
||||||
|
} mifare_classic_tag;
|
||||||
|
|
||||||
|
// MIFARE Ultralight
|
||||||
|
typedef struct {
|
||||||
|
byte_t sn0[3];
|
||||||
|
byte_t btBCC0;
|
||||||
|
byte_t sn1[4];
|
||||||
|
byte_t btBCC1;
|
||||||
|
byte_t internal;
|
||||||
|
byte_t lock[2];
|
||||||
|
byte_t otp[4];
|
||||||
|
} mifareul_block_manufacturer;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
byte_t abtData[16];
|
||||||
|
} mifareul_block_data;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
mifareul_block_manufacturer mbm;
|
||||||
|
mifareul_block_data mbd;
|
||||||
|
} mifareul_block;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mifareul_block amb[4];
|
||||||
|
} mifareul_tag;
|
||||||
|
|
||||||
|
// Reset struct alignment to default
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
#endif // _LIBNFC_MIFARE_H_
|
||||||
82
src/mirror-subr.c
Normal file
82
src/mirror-subr.c
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*-
|
||||||
|
* Public platform independent Near Field Communication (NFC) library
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009, Roel Verdult
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file mirror-subr.c
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "mirror-subr.h"
|
||||||
|
|
||||||
|
static const byte_t ByteMirror[256] = {
|
||||||
|
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30,
|
||||||
|
0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98,
|
||||||
|
0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64,
|
||||||
|
0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc,
|
||||||
|
0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02,
|
||||||
|
0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2,
|
||||||
|
0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a,
|
||||||
|
0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
|
||||||
|
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e,
|
||||||
|
0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81,
|
||||||
|
0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71,
|
||||||
|
0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9,
|
||||||
|
0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15,
|
||||||
|
0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad,
|
||||||
|
0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43,
|
||||||
|
0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
|
||||||
|
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b,
|
||||||
|
0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97,
|
||||||
|
0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f,
|
||||||
|
0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
|
||||||
|
};
|
||||||
|
|
||||||
|
byte_t mirror(byte_t bt)
|
||||||
|
{
|
||||||
|
return ByteMirror[bt];
|
||||||
|
}
|
||||||
|
|
||||||
|
void mirror_bytes(byte_t *pbts, size_t szLen)
|
||||||
|
{
|
||||||
|
size_t szByteNr;
|
||||||
|
|
||||||
|
for (szByteNr=0; szByteNr<szLen; szByteNr++)
|
||||||
|
{
|
||||||
|
*pbts = ByteMirror[*pbts];
|
||||||
|
pbts++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t mirror32(uint32_t ui32Bits)
|
||||||
|
{
|
||||||
|
mirror_bytes((byte_t*)&ui32Bits,4);
|
||||||
|
return ui32Bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t mirror64(uint64_t ui64Bits)
|
||||||
|
{
|
||||||
|
mirror_bytes((byte_t*)&ui64Bits,8);
|
||||||
|
return ui64Bits;
|
||||||
|
}
|
||||||
37
src/mirror-subr.h
Normal file
37
src/mirror-subr.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* Public platform independent Near Field Communication (NFC) library
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009, Roel Verdult
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @file mirror-subr.h
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LIBNFC_MIRROR_SUBR_H_
|
||||||
|
#define _LIBNFC_MIRROR_SUBR_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <nfc/nfc-types.h>
|
||||||
|
|
||||||
|
|
||||||
|
byte_t mirror(byte_t bt);
|
||||||
|
uint32_t mirror32(uint32_t ui32Bits);
|
||||||
|
uint64_t mirror64(uint64_t ui64Bits);
|
||||||
|
void mirror_byte_ts(byte_t *pbts, size_t szLen);
|
||||||
|
|
||||||
|
#endif // _LIBNFC_MIRROR_SUBR_H_
|
||||||
179
src/nfc-utils.c
Normal file
179
src/nfc-utils.c
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
|
#include "nfc-utils.h"
|
||||||
|
|
||||||
|
static const byte_t OddParity[256] = {
|
||||||
|
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,
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
void oddparity_bytes_ts(const byte_t* pbtData, const size_t szLen, byte_t* pbtPar)
|
||||||
|
{
|
||||||
|
size_t szByteNr;
|
||||||
|
// Calculate the parity bits for the command
|
||||||
|
for (szByteNr=0; szByteNr<szLen; szByteNr++)
|
||||||
|
{
|
||||||
|
pbtPar[szByteNr] = OddParity[pbtData[szByteNr]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_hex(const byte_t* pbtData, const size_t szBytes)
|
||||||
|
{
|
||||||
|
size_t szPos;
|
||||||
|
|
||||||
|
for (szPos=0; szPos < szBytes; szPos++)
|
||||||
|
{
|
||||||
|
printf("%02x ",pbtData[szPos]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_hex_bits(const byte_t* pbtData, const size_t szBits)
|
||||||
|
{
|
||||||
|
uint8_t uRemainder;
|
||||||
|
size_t szPos;
|
||||||
|
size_t szBytes = szBits/8;
|
||||||
|
|
||||||
|
for (szPos=0; szPos < szBytes; szPos++)
|
||||||
|
{
|
||||||
|
printf("%02x ",pbtData[szPos]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uRemainder = szBits % 8;
|
||||||
|
// Print the rest bits
|
||||||
|
if (uRemainder != 0)
|
||||||
|
{
|
||||||
|
if (uRemainder < 5)
|
||||||
|
printf("%01x (%d bits)",pbtData[szBytes], uRemainder);
|
||||||
|
else
|
||||||
|
printf("%02x (%d bits)",pbtData[szBytes], uRemainder);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_hex_par(const byte_t* pbtData, const size_t szBits, const byte_t* pbtDataPar)
|
||||||
|
{
|
||||||
|
uint8_t uRemainder;
|
||||||
|
size_t szPos;
|
||||||
|
size_t szBytes = szBits/8;
|
||||||
|
|
||||||
|
for (szPos=0; szPos < szBytes; szPos++)
|
||||||
|
{
|
||||||
|
printf("%02x",pbtData[szPos]);
|
||||||
|
if (OddParity[pbtData[szPos]] != pbtDataPar[szPos])
|
||||||
|
{
|
||||||
|
printf("! ");
|
||||||
|
} else {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uRemainder = szBits % 8;
|
||||||
|
// Print the rest bits, these cannot have parity bit
|
||||||
|
if (uRemainder != 0)
|
||||||
|
{
|
||||||
|
if (uRemainder < 5)
|
||||||
|
printf("%01x (%d bits)",pbtData[szBytes], uRemainder);
|
||||||
|
else
|
||||||
|
printf("%02x (%d bits)",pbtData[szBytes], uRemainder);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SAK_ISO14443_4_COMPLIANT 0x20
|
||||||
|
#define SAK_ISO18092_COMPLIANT 0x40
|
||||||
|
|
||||||
|
void print_nfc_iso14443a_info(const nfc_iso14443a_info_t nai)
|
||||||
|
{
|
||||||
|
printf(" ATQA (SENS_RES): "); print_hex(nai.abtAtqa,2);
|
||||||
|
printf(" UID (NFCID%c): ",(nai.abtUid[0]==0x08?'3':'1')); print_hex(nai.abtUid, nai.szUidLen);
|
||||||
|
printf(" SAK (SEL_RES): "); print_hex(&nai.btSak,1);
|
||||||
|
if (nai.szAtsLen) {
|
||||||
|
printf(" ATS (ATR): ");
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void print_nfc_felica_info(const nfc_felica_info_t nfi)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
printf(" ATQB: "); print_hex(nbi.abtAtqb,12);
|
||||||
|
printf(" ID: "); print_hex(nbi.abtId,4);
|
||||||
|
printf(" CID: %02x\n",nbi.btCid);
|
||||||
|
if (nbi.szInfLen>0) {
|
||||||
|
printf(" INF: "); print_hex(nbi.abtInf,nbi.szInfLen);
|
||||||
|
}
|
||||||
|
printf(" PARAMS: %02x %02x %02x %02x\n",nbi.btParam1,nbi.btParam2,nbi.btParam3,nbi.btParam4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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* pndd = 0;
|
||||||
|
int arg;
|
||||||
|
*szFound = 0;
|
||||||
|
|
||||||
|
// Get commandline options
|
||||||
|
for (arg=1;arg<argc;arg++) {
|
||||||
|
|
||||||
|
if (0 == strcmp(argv[arg], "--device")) {
|
||||||
|
|
||||||
|
if (argc > arg+1) {
|
||||||
|
char buffer[256];
|
||||||
|
|
||||||
|
pndd = malloc(sizeof(nfc_device_desc_t));
|
||||||
|
|
||||||
|
strncpy(buffer, argv[++arg], 256);
|
||||||
|
|
||||||
|
// Driver.
|
||||||
|
pndd->pcDriver = (char *)malloc(256);
|
||||||
|
strcpy(pndd->pcDriver, strtok(buffer, ":"));
|
||||||
|
|
||||||
|
// Port.
|
||||||
|
pndd->pcPort = (char *)malloc(256);
|
||||||
|
strcpy(pndd->pcPort, strtok(NULL, ":"));
|
||||||
|
|
||||||
|
// Speed.
|
||||||
|
sscanf(strtok(NULL, ":"), "%u", &pndd->uiSpeed);
|
||||||
|
|
||||||
|
*szFound = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pndd;
|
||||||
|
}
|
||||||
|
|
||||||
43
src/nfc-utils.h
Normal file
43
src/nfc-utils.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* Public platform independent Near Field Communication (NFC) library
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010, Romuald Conty
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @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_
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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_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);
|
||||||
|
|
||||||
|
nfc_device_desc_t* parse_device_desc(int argc, const char *argv[], size_t* szFound);
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
x
Reference in New Issue
Block a user