diff --git a/libfreefare/felica.c b/libfreefare/felica.c index 4259f62..40b8f47 100644 --- a/libfreefare/felica.c +++ b/libfreefare/felica.c @@ -58,9 +58,19 @@ felica_taste (nfc_device *device, nfc_target target) } 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 diff --git a/libfreefare/freefare.c b/libfreefare/freefare.c index ef312f4..930c2cb 100644 --- a/libfreefare/freefare.c +++ b/libfreefare/freefare.c @@ -49,68 +49,22 @@ struct supported_tag supported_tags[] = { FreefareTag freefare_tag_new (nfc_device *device, nfc_target target) { - bool found = false; - struct supported_tag *tag_info; - FreefareTag tag; + FreefareTag tag = NULL; - /* Ensure the target is supported */ - for (size_t i = 0; i < sizeof (supported_tags) / sizeof (struct supported_tag); i++) { - if (target.nm.nmt != supported_tags[i].modulation_type) - continue; - - if (target.nm.nmt == NMT_FELICA) { - tag_info = &(supported_tags[i]); - found = true; - break; - } - if ((target.nm.nmt == NMT_ISO14443A) && ((target.nti.nai.szUidLen == 4) || (target.nti.nai.abtUid[0] == NXP_MANUFACTURER_CODE)) && - (target.nti.nai.btSak == supported_tags[i].SAK) && - (!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 (felica_taste (device, target)) { + tag = felica_tag_new (device, target); + } else if (mifare_classic1k_taste (device, target)) { + tag = mifare_classic1k_tag_new (device, target); + } else if (mifare_classic4k_taste (device, target)) { + tag = mifare_classic4k_tag_new (device, target); + } else if (mifare_desfire_taste (device, target)) { + tag = mifare_desfire_tag_new (device, target); + } else if (mifare_ultralightc_taste (device, target)) { + tag = mifare_ultralightc_tag_new (device, target); + } else if (mifare_ultralight_taste (device, target)) { + tag = mifare_ultralight_tag_new (device, target); } - 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; } @@ -204,7 +158,7 @@ freefare_get_tags (nfc_device *device) enum freefare_tag_type 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 * 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) { if (tag) { - switch (tag->tag_info->type) { - 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; - } + tag->free_tag (tag); } } @@ -288,7 +242,7 @@ freefare_strerror (FreefareTag tag) if (nfc_device_get_last_error (tag->device) < 0) { p = nfc_strerror (tag->device); } else { - if (tag->tag_info->type == MIFARE_DESFIRE) { + if (tag->type == MIFARE_DESFIRE) { if (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) { diff --git a/libfreefare/freefare.h b/libfreefare/freefare.h index 8bf8838..fc707d7 100644 --- a/libfreefare/freefare.h +++ b/libfreefare/freefare.h @@ -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]; diff --git a/libfreefare/freefare_internal.h b/libfreefare/freefare_internal.h index 1befa31..b67a1ef 100644 --- a/libfreefare/freefare_internal.h +++ b/libfreefare/freefare_internal.h @@ -102,15 +102,16 @@ struct mad_sector_0x00; struct mad_sector_0x10; 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); -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); -FreefareTag mifare_desfire_tag_new (void); +FreefareTag mifare_desfire_tag_new (nfc_device *device, nfc_target target); 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); -FreefareTag mifare_ultralightc_tag_new (void); +FreefareTag mifare_ultralightc_tag_new (nfc_device *device, nfc_target target); void mifare_ultralightc_tag_free (FreefareTag tag); uint8_t sector_0x00_crc8 (Mad mad); uint8_t sector_0x10_crc8 (Mad mad); @@ -189,8 +190,9 @@ struct supported_tag { struct freefare_tag { nfc_device *device; nfc_target info; - const struct supported_tag *tag_info; + int type; int active; + void (*free_tag) (FreefareTag tag); }; struct felica_tag { diff --git a/libfreefare/mifare_classic.c b/libfreefare/mifare_classic.c index 5fe672d..7789ff9 100644 --- a/libfreefare/mifare_classic.c +++ b/libfreefare/mifare_classic.c @@ -194,7 +194,7 @@ int get_block_access_bits (FreefareTag tag, const MifareClassicBlockNumber blo */ bool -mifare_classic_taste (nfc_device *device, nfc_target target) +mifare_classic1k_taste (nfc_device *device, nfc_target target) { (void) device; 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 == 0x28 || target.nti.nai.btSak == 0x68 || - target.nti.nai.btSak == 0x88 || - target.nti.nai.btSak == 0x18 + target.nti.nai.btSak == 0x88 + ); +} + +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. */ -FreefareTag -mifare_classic_tag_new (void) +static FreefareTag +_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); } /* diff --git a/libfreefare/mifare_desfire.c b/libfreefare/mifare_desfire.c index 7f370a0..4be12ac 100644 --- a/libfreefare/mifare_desfire.c +++ b/libfreefare/mifare_desfire.c @@ -239,6 +239,16 @@ le24toh (uint8_t data[3]) 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. @@ -248,7 +258,7 @@ le24toh (uint8_t data[3]) * Allocates and initialize a MIFARE DESFire tag. */ FreefareTag -mifare_desfire_tag_new (void) +mifare_desfire_tag_new (nfc_device *device, nfc_target target) { FreefareTag 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)->crypto_buffer = NULL; 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; } diff --git a/libfreefare/mifare_desfire_error.c b/libfreefare/mifare_desfire_error.c index ae53fa1..7dbb7a3 100644 --- a/libfreefare/mifare_desfire_error.c +++ b/libfreefare/mifare_desfire_error.c @@ -72,7 +72,7 @@ mifare_desfire_error_lookup (uint8_t code) uint8_t mifare_desfire_last_pcd_error (FreefareTag tag) { - if (tag->tag_info->type != MIFARE_DESFIRE) + if (tag->type != MIFARE_DESFIRE) return 0; return MIFARE_DESFIRE (tag)->last_pcd_error; @@ -81,7 +81,7 @@ mifare_desfire_last_pcd_error (FreefareTag tag) uint8_t mifare_desfire_last_picc_error (FreefareTag tag) { - if (tag->tag_info->type != MIFARE_DESFIRE) + if (tag->type != MIFARE_DESFIRE) return 0; return MIFARE_DESFIRE (tag)->last_picc_error; diff --git a/libfreefare/mifare_ultralight.c b/libfreefare/mifare_ultralight.c index a60a770..b0bd95a 100644 --- a/libfreefare/mifare_ultralight.c +++ b/libfreefare/mifare_ultralight.c @@ -115,24 +115,33 @@ mifare_ultralightc_taste (nfc_device *device, nfc_target target) /* * Allocates and initialize a MIFARE UltraLight tag. */ -FreefareTag -mifare_ultralight_tag_new (void) +static FreefareTag +_mifare_ultralightc_tag_new (nfc_device *device, nfc_target target, bool is_ultralightc) { - FreefareTag res; - if ((res = malloc (sizeof (struct mifare_ultralight_tag)))) { - MIFARE_ULTRALIGHT(res)->is_ultralightc = false; + FreefareTag tag; + + 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 -mifare_ultralightc_tag_new (void) +mifare_ultralight_tag_new (nfc_device *device, nfc_target target) { - FreefareTag res; - if ((res = malloc (sizeof (struct mifare_ultralight_tag)))) { - MIFARE_ULTRALIGHT(res)->is_ultralightc = true; - } - return res; + return _mifare_ultralightc_tag_new (device, target, false); +} + +FreefareTag +mifare_ultralightc_tag_new (nfc_device *device, nfc_target target) +{ + return _mifare_ultralightc_tag_new (device, target, true); } /* diff --git a/test/Makefile.am b/test/Makefile.am index 56a2d04..096a4d5 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -12,6 +12,7 @@ TESTS_ENVIRONMENT = NO_MAKE=yes CUTTER="$(CUTTER)" cutter_unit_test_libs = \ test_felica.la \ + test_freefare.la \ test_mad.la \ test_mifare_application.la \ test_mifare_classic.la \ @@ -39,6 +40,9 @@ test_felica_la_SOURCES = test_felica.c \ felica_fixture.h 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_LIBADD = $(top_builddir)/libfreefare/libfreefare.la diff --git a/test/test_freefare.c b/test/test_freefare.c new file mode 100644 index 0000000..6d153f3 --- /dev/null +++ b/test/test_freefare.c @@ -0,0 +1,26 @@ +#include + +#include +#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); +} diff --git a/test/test_mifare_ultralight.c b/test/test_mifare_ultralight.c index 361dcf1..b154631 100644 --- a/test/test_mifare_ultralight.c +++ b/test/test_mifare_ultralight.c @@ -178,7 +178,7 @@ test_mifare_ultralightc_authenticate (void) int res; 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 }; key = mifare_desfire_3des_key_new (key1_3des_data); res = mifare_ultralightc_authenticate (tag, key);