Rework tag allocation.

Split Mifare Classic 1 and 4K tag allocation.
Rely on new tasting functions.
This commit is contained in:
Romain Tartière 2016-01-18 16:55:47 +01:00
parent 0279361873
commit ee628f7ec5
11 changed files with 162 additions and 109 deletions

View file

@ -58,9 +58,19 @@ felica_taste (nfc_device *device, nfc_target target)
} }
FreefareTag FreefareTag
felica_tag_new (void) felica_tag_new (nfc_device *device, nfc_target target)
{ {
return malloc (sizeof (struct felica_tag)); FreefareTag tag;
if ((tag = malloc (sizeof (struct felica_tag)))) {
tag->type = FELICA;
tag->free_tag = felica_tag_free;
tag->device = device;
tag->info = target;
tag->active = 0;
}
return tag;
} }
void void

View file

@ -49,68 +49,22 @@ struct supported_tag supported_tags[] = {
FreefareTag FreefareTag
freefare_tag_new (nfc_device *device, nfc_target target) freefare_tag_new (nfc_device *device, nfc_target target)
{ {
bool found = false; FreefareTag tag = NULL;
struct supported_tag *tag_info;
FreefareTag tag;
/* Ensure the target is supported */ if (felica_taste (device, target)) {
for (size_t i = 0; i < sizeof (supported_tags) / sizeof (struct supported_tag); i++) { tag = felica_tag_new (device, target);
if (target.nm.nmt != supported_tags[i].modulation_type) } else if (mifare_classic1k_taste (device, target)) {
continue; tag = mifare_classic1k_tag_new (device, target);
} else if (mifare_classic4k_taste (device, target)) {
if (target.nm.nmt == NMT_FELICA) { tag = mifare_classic4k_tag_new (device, target);
tag_info = &(supported_tags[i]); } else if (mifare_desfire_taste (device, target)) {
found = true; tag = mifare_desfire_tag_new (device, target);
break; } else if (mifare_ultralightc_taste (device, target)) {
} tag = mifare_ultralightc_tag_new (device, target);
if ((target.nm.nmt == NMT_ISO14443A) && ((target.nti.nai.szUidLen == 4) || (target.nti.nai.abtUid[0] == NXP_MANUFACTURER_CODE)) && } else if (mifare_ultralight_taste (device, target)) {
(target.nti.nai.btSak == supported_tags[i].SAK) && tag = mifare_ultralight_tag_new (device, target);
(!supported_tags[i].ATS_min_length || ((target.nti.nai.szAtsLen >= supported_tags[i].ATS_min_length) &&
(0 == memcmp (target.nti.nai.abtAts, supported_tags[i].ATS, supported_tags[i].ATS_compare_length)))) &&
((supported_tags[i].check_tag_on_reader == NULL) ||
supported_tags[i].check_tag_on_reader(device, target.nti.nai))) {
tag_info = &(supported_tags[i]);
found = true;
break;
}
} }
if (!found)
return NULL;
/* Allocate memory for the found MIFARE target */
switch (tag_info->type) {
case FELICA:
tag = felica_tag_new ();
break;
case MIFARE_CLASSIC_1K:
case MIFARE_CLASSIC_4K:
tag = mifare_classic_tag_new ();
break;
case MIFARE_DESFIRE:
tag = mifare_desfire_tag_new ();
break;
case MIFARE_ULTRALIGHT:
tag = mifare_ultralight_tag_new ();
break;
case MIFARE_ULTRALIGHT_C:
tag = mifare_ultralightc_tag_new ();
break;
}
if (!tag)
return NULL;
/*
* Initialize common fields
* (Target specific fields are initialized in mifare_*_tag_new())
*/
tag->device = device;
tag->info = target;
tag->active = 0;
tag->tag_info = tag_info;
return tag; return tag;
} }
@ -204,7 +158,7 @@ freefare_get_tags (nfc_device *device)
enum freefare_tag_type enum freefare_tag_type
freefare_get_tag_type (FreefareTag tag) freefare_get_tag_type (FreefareTag tag)
{ {
return tag->tag_info->type; return tag->type;
} }
/* /*
@ -213,7 +167,22 @@ freefare_get_tag_type (FreefareTag tag)
const char * const char *
freefare_get_tag_friendly_name (FreefareTag tag) freefare_get_tag_friendly_name (FreefareTag tag)
{ {
return tag->tag_info->friendly_name; switch (tag->type) {
case FELICA:
return "FeliCA";
case MIFARE_CLASSIC_1K:
return "Mifare Classic 1k";
case MIFARE_CLASSIC_4K:
return "Mifare Classic 4k";
case MIFARE_DESFIRE:
return "Mifare DESFire";
case MIFARE_ULTRALIGHT_C:
return "Mifare UltraLightC";
case MIFARE_ULTRALIGHT:
return "Mifare UltraLight";
default:
return "UNKNOWN";
}
} }
/* /*
@ -262,22 +231,7 @@ void
freefare_free_tag (FreefareTag tag) freefare_free_tag (FreefareTag tag)
{ {
if (tag) { if (tag) {
switch (tag->tag_info->type) { tag->free_tag (tag);
case FELICA:
felica_tag_free (tag);
break;
case MIFARE_CLASSIC_1K:
case MIFARE_CLASSIC_4K:
mifare_classic_tag_free (tag);
break;
case MIFARE_DESFIRE:
mifare_desfire_tag_free (tag);
break;
case MIFARE_ULTRALIGHT:
case MIFARE_ULTRALIGHT_C:
mifare_ultralight_tag_free (tag);
break;
}
} }
} }
@ -288,7 +242,7 @@ freefare_strerror (FreefareTag tag)
if (nfc_device_get_last_error (tag->device) < 0) { if (nfc_device_get_last_error (tag->device) < 0) {
p = nfc_strerror (tag->device); p = nfc_strerror (tag->device);
} else { } else {
if (tag->tag_info->type == MIFARE_DESFIRE) { if (tag->type == MIFARE_DESFIRE) {
if (MIFARE_DESFIRE (tag)->last_pcd_error) { if (MIFARE_DESFIRE (tag)->last_pcd_error) {
p = mifare_desfire_error_lookup (MIFARE_DESFIRE (tag)->last_pcd_error); p = mifare_desfire_error_lookup (MIFARE_DESFIRE (tag)->last_pcd_error);
} else if (MIFARE_DESFIRE (tag)->last_picc_error) { } else if (MIFARE_DESFIRE (tag)->last_picc_error) {

View file

@ -97,7 +97,8 @@ bool is_mifare_ultralightc_on_reader (nfc_device *device, nfc_iso14443a_info n
bool mifare_classic_taste (nfc_device *device, nfc_target target); bool mifare_classic1k_taste (nfc_device *device, nfc_target target);
bool mifare_classic4k_taste (nfc_device *device, nfc_target target);
typedef unsigned char MifareClassicBlock[16]; typedef unsigned char MifareClassicBlock[16];

View file

@ -102,15 +102,16 @@ struct mad_sector_0x00;
struct mad_sector_0x10; struct mad_sector_0x10;
void nxp_crc (uint8_t *crc, const uint8_t value); void nxp_crc (uint8_t *crc, const uint8_t value);
FreefareTag felica_tag_new (void); FreefareTag felica_tag_new (nfc_device *device, nfc_target target);
void felica_tag_free (FreefareTag tag); void felica_tag_free (FreefareTag tag);
FreefareTag mifare_classic_tag_new (void); FreefareTag mifare_classic1k_tag_new (nfc_device *device, nfc_target target);
FreefareTag mifare_classic4k_tag_new (nfc_device *device, nfc_target target);
void mifare_classic_tag_free (FreefareTag tag); void mifare_classic_tag_free (FreefareTag tag);
FreefareTag mifare_desfire_tag_new (void); FreefareTag mifare_desfire_tag_new (nfc_device *device, nfc_target target);
void mifare_desfire_tag_free (FreefareTag tags); void mifare_desfire_tag_free (FreefareTag tags);
FreefareTag mifare_ultralight_tag_new (void); FreefareTag mifare_ultralight_tag_new (nfc_device *device, nfc_target target);
void mifare_ultralight_tag_free (FreefareTag tag); void mifare_ultralight_tag_free (FreefareTag tag);
FreefareTag mifare_ultralightc_tag_new (void); FreefareTag mifare_ultralightc_tag_new (nfc_device *device, nfc_target target);
void mifare_ultralightc_tag_free (FreefareTag tag); void mifare_ultralightc_tag_free (FreefareTag tag);
uint8_t sector_0x00_crc8 (Mad mad); uint8_t sector_0x00_crc8 (Mad mad);
uint8_t sector_0x10_crc8 (Mad mad); uint8_t sector_0x10_crc8 (Mad mad);
@ -189,8 +190,9 @@ struct supported_tag {
struct freefare_tag { struct freefare_tag {
nfc_device *device; nfc_device *device;
nfc_target info; nfc_target info;
const struct supported_tag *tag_info; int type;
int active; int active;
void (*free_tag) (FreefareTag tag);
}; };
struct felica_tag { struct felica_tag {

View file

@ -194,7 +194,7 @@ int get_block_access_bits (FreefareTag tag, const MifareClassicBlockNumber blo
*/ */
bool bool
mifare_classic_taste (nfc_device *device, nfc_target target) mifare_classic1k_taste (nfc_device *device, nfc_target target)
{ {
(void) device; (void) device;
return target.nm.nmt == NMT_ISO14443A && return target.nm.nmt == NMT_ISO14443A &&
@ -202,8 +202,18 @@ mifare_classic_taste (nfc_device *device, nfc_target target)
target.nti.nai.btSak == 0x08 || target.nti.nai.btSak == 0x08 ||
target.nti.nai.btSak == 0x28 || target.nti.nai.btSak == 0x28 ||
target.nti.nai.btSak == 0x68 || target.nti.nai.btSak == 0x68 ||
target.nti.nai.btSak == 0x88 || target.nti.nai.btSak == 0x88
target.nti.nai.btSak == 0x18 );
}
bool
mifare_classic4k_taste (nfc_device *device, nfc_target target)
{
(void) device;
return target.nm.nmt == NMT_ISO14443A &&
(
target.nti.nai.btSak == 0x18 ||
target.nti.nai.btSak == 0x38
); );
} }
@ -211,10 +221,32 @@ mifare_classic_taste (nfc_device *device, nfc_target target)
* Allocates and initialize a MIFARE Classic tag. * Allocates and initialize a MIFARE Classic tag.
*/ */
FreefareTag static FreefareTag
mifare_classic_tag_new (void) _mifare_classic_tag_new (nfc_device *device, nfc_target target, int tag_type)
{ {
return malloc (sizeof (struct mifare_classic_tag)); FreefareTag tag;
if ((tag = malloc (sizeof (struct mifare_classic_tag)))) {
tag->type = tag_type;
tag->free_tag = mifare_classic_tag_free;
tag->device = device;
tag->info = target;
tag->active = 0;
}
return tag;
}
FreefareTag
mifare_classic1k_tag_new (nfc_device *device, nfc_target target)
{
return _mifare_classic_tag_new (device, target, MIFARE_CLASSIC_1K);
}
FreefareTag
mifare_classic4k_tag_new (nfc_device *device, nfc_target target)
{
return _mifare_classic_tag_new (device, target, MIFARE_CLASSIC_4K);
} }
/* /*

View file

@ -239,6 +239,16 @@ le24toh (uint8_t data[3])
return (data[2] << 16) | (data[1] << 8) | data[0]; return (data[2] << 16) | (data[1] << 8) | data[0];
} }
bool
mifare_desfire_taste (nfc_device *device, nfc_target target)
{
(void) device;
return target.nm.nmt == NMT_ISO14443A &&
target.nti.nai.btSak == 0x20 &&
target.nti.nai.szAtsLen >= 5 &&
memcmp (target.nti.nai.abtAts, "\x75\x77\x81\x02", 4) == 0;
}
/* /*
* Memory management functions. * Memory management functions.
@ -248,7 +258,7 @@ le24toh (uint8_t data[3])
* Allocates and initialize a MIFARE DESFire tag. * Allocates and initialize a MIFARE DESFire tag.
*/ */
FreefareTag FreefareTag
mifare_desfire_tag_new (void) mifare_desfire_tag_new (nfc_device *device, nfc_target target)
{ {
FreefareTag tag; FreefareTag tag;
if ((tag= malloc (sizeof (struct mifare_desfire_tag)))) { if ((tag= malloc (sizeof (struct mifare_desfire_tag)))) {
@ -257,6 +267,11 @@ mifare_desfire_tag_new (void)
MIFARE_DESFIRE (tag)->session_key = NULL; MIFARE_DESFIRE (tag)->session_key = NULL;
MIFARE_DESFIRE (tag)->crypto_buffer = NULL; MIFARE_DESFIRE (tag)->crypto_buffer = NULL;
MIFARE_DESFIRE (tag)->crypto_buffer_size = 0; MIFARE_DESFIRE (tag)->crypto_buffer_size = 0;
tag->type = MIFARE_DESFIRE;
tag->free_tag = mifare_desfire_tag_free;
tag->device = device;
tag->info = target;
tag->active = 0;
} }
return tag; return tag;
} }

View file

@ -72,7 +72,7 @@ mifare_desfire_error_lookup (uint8_t code)
uint8_t uint8_t
mifare_desfire_last_pcd_error (FreefareTag tag) mifare_desfire_last_pcd_error (FreefareTag tag)
{ {
if (tag->tag_info->type != MIFARE_DESFIRE) if (tag->type != MIFARE_DESFIRE)
return 0; return 0;
return MIFARE_DESFIRE (tag)->last_pcd_error; return MIFARE_DESFIRE (tag)->last_pcd_error;
@ -81,7 +81,7 @@ mifare_desfire_last_pcd_error (FreefareTag tag)
uint8_t uint8_t
mifare_desfire_last_picc_error (FreefareTag tag) mifare_desfire_last_picc_error (FreefareTag tag)
{ {
if (tag->tag_info->type != MIFARE_DESFIRE) if (tag->type != MIFARE_DESFIRE)
return 0; return 0;
return MIFARE_DESFIRE (tag)->last_picc_error; return MIFARE_DESFIRE (tag)->last_picc_error;

View file

@ -115,24 +115,33 @@ mifare_ultralightc_taste (nfc_device *device, nfc_target target)
/* /*
* Allocates and initialize a MIFARE UltraLight tag. * Allocates and initialize a MIFARE UltraLight tag.
*/ */
FreefareTag static FreefareTag
mifare_ultralight_tag_new (void) _mifare_ultralightc_tag_new (nfc_device *device, nfc_target target, bool is_ultralightc)
{ {
FreefareTag res; FreefareTag tag;
if ((res = malloc (sizeof (struct mifare_ultralight_tag)))) {
MIFARE_ULTRALIGHT(res)->is_ultralightc = false; if ((tag = malloc (sizeof (struct mifare_ultralight_tag)))) {
MIFARE_ULTRALIGHT(tag)->is_ultralightc = is_ultralightc;
tag->type = (is_ultralightc) ? MIFARE_ULTRALIGHT_C : MIFARE_ULTRALIGHT;
tag->free_tag = mifare_ultralightc_tag_free;
tag->device = device;
tag->info = target;
tag->active = 0;
} }
return res;
return tag;
} }
FreefareTag FreefareTag
mifare_ultralightc_tag_new (void) mifare_ultralight_tag_new (nfc_device *device, nfc_target target)
{ {
FreefareTag res; return _mifare_ultralightc_tag_new (device, target, false);
if ((res = malloc (sizeof (struct mifare_ultralight_tag)))) { }
MIFARE_ULTRALIGHT(res)->is_ultralightc = true;
} FreefareTag
return res; mifare_ultralightc_tag_new (nfc_device *device, nfc_target target)
{
return _mifare_ultralightc_tag_new (device, target, true);
} }
/* /*

View file

@ -12,6 +12,7 @@ TESTS_ENVIRONMENT = NO_MAKE=yes CUTTER="$(CUTTER)"
cutter_unit_test_libs = \ cutter_unit_test_libs = \
test_felica.la \ test_felica.la \
test_freefare.la \
test_mad.la \ test_mad.la \
test_mifare_application.la \ test_mifare_application.la \
test_mifare_classic.la \ test_mifare_classic.la \
@ -39,6 +40,9 @@ test_felica_la_SOURCES = test_felica.c \
felica_fixture.h felica_fixture.h
test_felica_la_LIBADD = $(top_builddir)/libfreefare/libfreefare.la test_felica_la_LIBADD = $(top_builddir)/libfreefare/libfreefare.la
test_freefare_la_SOURCES = test_freefare.c
test_freefare_la_LIBADD = $(top_builddir)/libfreefare/libfreefare.la
test_mad_la_SOURCES = test_mad.c test_mad_la_SOURCES = test_mad.c
test_mad_la_LIBADD = $(top_builddir)/libfreefare/libfreefare.la test_mad_la_LIBADD = $(top_builddir)/libfreefare/libfreefare.la

26
test/test_freefare.c Normal file
View file

@ -0,0 +1,26 @@
#include <cutter.h>
#include <freefare.h>
#include "freefare_internal.h"
void
test_is_mifare_ultralight (void)
{
FreefareTag tag;
nfc_target target;
tag = mifare_ultralight_tag_new (NULL, target);
cut_assert_true (is_mifare_ultralight (tag));
mifare_ultralight_tag_free (tag);
}
void
test_is_mifare_ultralightc (void)
{
FreefareTag tag;
nfc_target target;
tag = mifare_ultralightc_tag_new (NULL, target);
cut_assert_true (is_mifare_ultralightc (tag));
mifare_ultralightc_tag_free (tag);
}

View file

@ -178,7 +178,7 @@ test_mifare_ultralightc_authenticate (void)
int res; int res;
MifareDESFireKey key; MifareDESFireKey key;
if (tag->tag_info->type == MIFARE_ULTRALIGHT_C) { if (is_mifare_ultralightc (tag)) {
uint8_t key1_3des_data[16] = { 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46 }; uint8_t key1_3des_data[16] = { 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46 };
key = mifare_desfire_3des_key_new (key1_3des_data); key = mifare_desfire_3des_key_new (key1_3des_data);
res = mifare_ultralightc_authenticate (tag, key); res = mifare_ultralightc_authenticate (tag, key);