diff --git a/libfreefare/felica.c b/libfreefare/felica.c index 4c3f34a..40b8f47 100644 --- a/libfreefare/felica.c +++ b/libfreefare/felica.c @@ -50,10 +50,27 @@ ssize_t felica_transceive (FreefareTag tag, uint8_t *data_in, uint8_t *data_out, return res; } -FreefareTag -felica_tag_new (void) +bool +felica_taste (nfc_device *device, nfc_target target) { - return malloc (sizeof (struct felica_tag)); + (void) device; + return target.nm.nmt == NMT_FELICA; +} + +FreefareTag +felica_tag_new (nfc_device *device, nfc_target target) +{ + 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 @@ -67,8 +84,6 @@ felica_tag_free (FreefareTag tag) ssize_t felica_read_ex (FreefareTag tag, uint16_t service, uint8_t block_count, uint8_t blocks[], uint8_t *data, size_t length) { - ASSERT_FELICA (tag); - assert (block_count <= MAX_BLOCK_COUNT); assert (length == 16 * block_count); @@ -120,8 +135,6 @@ felica_read (FreefareTag tag, uint16_t service, uint8_t block, uint8_t *data, si ssize_t felica_write_ex (FreefareTag tag, uint16_t service, uint8_t block_count, uint8_t blocks[], uint8_t *data, size_t length) { - ASSERT_FELICA (tag); - DEBUG_FUNCTION(); assert (block_count <= MAX_BLOCK_COUNT); diff --git a/libfreefare/freefare.c b/libfreefare/freefare.c index 8ee79dd..b7c2fb5 100644 --- a/libfreefare/freefare.c +++ b/libfreefare/freefare.c @@ -28,87 +28,28 @@ #define NXP_MANUFACTURER_CODE 0x04 -struct supported_tag supported_tags[] = { - { FELICA, "FeliCA", NMT_FELICA, 0x00, 0, 0, { 0x00 }, NULL }, - { MIFARE_CLASSIC_1K, "Mifare Classic 1k", NMT_ISO14443A, 0x08, 0, 0, { 0x00 }, NULL }, - { MIFARE_CLASSIC_1K, "Mifare Classic 1k (Emulated)", NMT_ISO14443A, 0x28, 0, 0, { 0x00 }, NULL }, - { MIFARE_CLASSIC_1K, "Mifare Classic 1k (Emulated)", NMT_ISO14443A, 0x68, 0, 0, { 0x00 }, NULL }, - { MIFARE_CLASSIC_1K, "Infineon Mifare Classic 1k", NMT_ISO14443A, 0x88, 0, 0, { 0x00 }, NULL }, - { MIFARE_CLASSIC_4K, "Mifare Classic 4k", NMT_ISO14443A, 0x18, 0, 0, { 0x00 }, NULL }, - { MIFARE_CLASSIC_4K, "Mifare Classic 4k (Emulated)", NMT_ISO14443A, 0x38, 0, 0, { 0x00 }, NULL }, - { MIFARE_DESFIRE, "Mifare DESFire", NMT_ISO14443A, 0x20, 5, 4, { 0x75, 0x77, 0x81, 0x02 /*, 0xXX */ }, NULL}, - { MIFARE_DESFIRE, "Cyanogenmod card emulation", NMT_ISO14443A, 0x60, 4, 3, { 0x78, 0x33, 0x88 /*, 0xXX */ }, NULL}, - { MIFARE_DESFIRE, "Android HCE", NMT_ISO14443A, 0x60, 4, 3, { 0x78, 0x80, 0x70 /*, 0xXX */ }, NULL}, - { MIFARE_ULTRALIGHT_C, "Mifare UltraLightC", NMT_ISO14443A, 0x00, 0, 0, { 0x00 }, is_mifare_ultralightc_on_reader }, - { MIFARE_ULTRALIGHT, "Mifare UltraLight", NMT_ISO14443A, 0x00, 0, 0, { 0x00 }, NULL }, -}; - /* * Automagically allocate a FreefareTag given a device and target info. */ 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: - case MIFARE_ULTRALIGHT_C: - tag = mifare_ultralight_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; } @@ -202,7 +143,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; } /* @@ -211,7 +152,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"; + } } /* @@ -260,22 +216,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); } } @@ -286,7 +227,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 f0ca291..8d02e41 100644 --- a/libfreefare/freefare.h +++ b/libfreefare/freefare.h @@ -67,14 +67,30 @@ const char *freefare_strerror (FreefareTag tag); int freefare_strerror_r (FreefareTag tag, char *buffer, size_t len); void freefare_perror (FreefareTag tag, const char *string); + + +bool felica_taste (nfc_device *device, nfc_target target); + #define FELICA_SC_RW 0x0009 #define FELICA_SC_RO 0x000b +FreefareTag felica_tag_new (nfc_device *device, nfc_target target); +void felica_tag_free (FreefareTag tag); + ssize_t felica_read (FreefareTag tag, uint16_t service, uint8_t block, uint8_t *data, size_t length); ssize_t felica_read_ex (FreefareTag tag, uint16_t service, uint8_t block_count, uint8_t blocks[], uint8_t *data, size_t length); ssize_t felica_write (FreefareTag tag, uint16_t service, uint8_t block, uint8_t *data, size_t length); ssize_t felica_write_ex (FreefareTag tag, uint16_t service, uint8_t block_count, uint8_t blocks[], uint8_t *data, size_t length); + + +bool mifare_ultralight_taste (nfc_device *device, nfc_target target); +bool mifare_ultralightc_taste (nfc_device *device, nfc_target target); +FreefareTag mifare_ultralight_tag_new (nfc_device *device, nfc_target target); +FreefareTag mifare_ultralightc_tag_new (nfc_device *device, nfc_target target); +void mifare_ultralight_tag_free (FreefareTag tag); +void mifare_ultralightc_tag_free (FreefareTag tag); + int mifare_ultralight_connect (FreefareTag tag); int mifare_ultralight_disconnect (FreefareTag tag); @@ -82,8 +98,18 @@ int mifare_ultralight_read (FreefareTag tag, const MifareUltralightPageNumber int mifare_ultralight_write (FreefareTag tag, const MifareUltralightPageNumber page, const MifareUltralightPage data); int mifare_ultralightc_authenticate (FreefareTag tag, const MifareDESFireKey key); +bool is_mifare_ultralight (FreefareTag tag); +bool is_mifare_ultralightc (FreefareTag tag); bool is_mifare_ultralightc_on_reader (nfc_device *device, nfc_iso14443a_info nai); + + +bool mifare_classic1k_taste (nfc_device *device, nfc_target target); +bool mifare_classic4k_taste (nfc_device *device, nfc_target target); +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); + typedef unsigned char MifareClassicBlock[16]; typedef uint8_t MifareClassicSectorNumber; @@ -185,6 +211,10 @@ int mifare_application_free (Mad mad, const MadAid aid); MifareClassicSectorNumber *mifare_application_find (Mad mad, const MadAid aid); + + +bool mifare_desfire_taste (nfc_device *device, nfc_target target); + /* File types */ enum mifare_desfire_file_types { @@ -334,6 +364,9 @@ struct mifare_desfire_file_settings { } settings; }; +FreefareTag mifare_desfire_tag_new (nfc_device *device, nfc_target target); +void mifare_desfire_tag_free (FreefareTag tags); + int mifare_desfire_connect (FreefareTag tag); int mifare_desfire_disconnect (FreefareTag tag); diff --git a/libfreefare/freefare_internal.h b/libfreefare/freefare_internal.h index b7779a2..b792ced 100644 --- a/libfreefare/freefare_internal.h +++ b/libfreefare/freefare_internal.h @@ -102,14 +102,6 @@ struct mad_sector_0x00; struct mad_sector_0x10; void nxp_crc (uint8_t *crc, const uint8_t value); -FreefareTag felica_tag_new (void); -void felica_tag_free (FreefareTag tag); -FreefareTag mifare_classic_tag_new (void); -void mifare_classic_tag_free (FreefareTag tag); -FreefareTag mifare_desfire_tag_new (void); -void mifare_desfire_tag_free (FreefareTag tags); -FreefareTag mifare_ultralight_tag_new (void); -void mifare_ultralight_tag_free (FreefareTag tag); uint8_t sector_0x00_crc8 (Mad mad); uint8_t sector_0x10_crc8 (Mad mad); @@ -165,17 +157,6 @@ void *assert_crypto_buffer_size (FreefareTag tag, size_t nbytes); // Max PAGE_COUNT of the Ultralight Family: #define MIFARE_ULTRALIGHT_MAX_PAGE_COUNT 0x30 -struct supported_tag { - enum freefare_tag_type type; - const char *friendly_name; - uint8_t modulation_type; - uint8_t SAK; - uint8_t ATS_min_length; - uint8_t ATS_compare_length; - uint8_t ATS[5]; - bool (*check_tag_on_reader) (nfc_device *, nfc_iso14443a_info); -}; - /* * This structure is common to all supported MIFARE targets but shall not be * used directly (it's some kind of abstract class). All members in this @@ -187,8 +168,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 { @@ -268,13 +250,6 @@ struct mifare_ultralight_tag { #define ASSERT_ACTIVE(tag) do { if (!tag->active) return errno = ENXIO, -1; } while (0) #define ASSERT_INACTIVE(tag) do { if (tag->active) return errno = ENXIO, -1; } while (0) -#define ASSERT_FELICA(tag) do { if (tag->tag_info->type != FELICA) return errno = ENODEV, -1; } while (0) -#define ASSERT_MIFARE_CLASSIC(tag) do { if ((tag->tag_info->type != MIFARE_CLASSIC_1K) && (tag->tag_info->type != MIFARE_CLASSIC_4K)) return errno = ENODEV, -1; } while (0) -#define ASSERT_MIFARE_DESFIRE(tag) do { if (tag->tag_info->type != MIFARE_DESFIRE) return errno = ENODEV, -1; } while (0) -#define IS_MIFARE_ULTRALIGHT_C(tag) (tag->tag_info->type == MIFARE_ULTRALIGHT_C) -#define ASSERT_MIFARE_ULTRALIGHT(tag) do { if ((tag->tag_info->type != MIFARE_ULTRALIGHT) && (! IS_MIFARE_ULTRALIGHT_C(tag))) return errno = ENODEV, -1; } while (0) -#define ASSERT_MIFARE_ULTRALIGHT_C(tag) do { if (! IS_MIFARE_ULTRALIGHT_C(tag)) return errno = ENODEV, -1; } while (0) - /* * FreefareTag cast macros * diff --git a/libfreefare/mifare_classic.c b/libfreefare/mifare_classic.c index 71e7a32..7789ff9 100644 --- a/libfreefare/mifare_classic.c +++ b/libfreefare/mifare_classic.c @@ -193,14 +193,60 @@ int get_block_access_bits (FreefareTag tag, const MifareClassicBlockNumber blo * Memory management functions. */ +bool +mifare_classic1k_taste (nfc_device *device, nfc_target target) +{ + (void) device; + return target.nm.nmt == NMT_ISO14443A && + ( + target.nti.nai.btSak == 0x08 || + target.nti.nai.btSak == 0x28 || + target.nti.nai.btSak == 0x68 || + 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 + ); +} + /* * 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); } /* @@ -228,7 +274,6 @@ int mifare_classic_connect (FreefareTag tag) { ASSERT_INACTIVE (tag); - ASSERT_MIFARE_CLASSIC (tag); nfc_target pnti; nfc_modulation modulation = { @@ -251,7 +296,6 @@ int mifare_classic_disconnect (FreefareTag tag) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_CLASSIC (tag); if (nfc_initiator_deselect_target (tag->device) >= 0) { tag->active = 0; @@ -277,7 +321,6 @@ int mifare_classic_authenticate (FreefareTag tag, const MifareClassicBlockNumber block, const MifareClassicKey key, const MifareClassicKeyType key_type) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_CLASSIC (tag); BUFFER_INIT (cmd, 12); BUFFER_INIT (res, 1); @@ -308,7 +351,6 @@ int mifare_classic_read (FreefareTag tag, const MifareClassicBlockNumber block, MifareClassicBlock *data) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_CLASSIC (tag); BUFFER_INIT (cmd, 2); BUFFER_ALIAS (res, data, sizeof(MifareClassicBlock)); @@ -377,7 +419,6 @@ int mifare_classic_write (FreefareTag tag, const MifareClassicBlockNumber block, const MifareClassicBlock data) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_CLASSIC (tag); BUFFER_INIT (cmd, 2 + sizeof (MifareClassicBlock)); BUFFER_INIT (res, 1); @@ -399,7 +440,6 @@ int mifare_classic_increment (FreefareTag tag, const MifareClassicBlockNumber block, const uint32_t amount) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_CLASSIC (tag); BUFFER_INIT (cmd, 6); BUFFER_INIT (res, 1); @@ -421,7 +461,6 @@ int mifare_classic_decrement (FreefareTag tag, const MifareClassicBlockNumber block, const uint32_t amount) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_CLASSIC (tag); BUFFER_INIT (cmd, 6); BUFFER_INIT (res, 1); @@ -442,7 +481,6 @@ int mifare_classic_restore (FreefareTag tag, const MifareClassicBlockNumber block) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_CLASSIC (tag); /* * Same length as the increment and decrement commands but only the first @@ -471,7 +509,6 @@ int mifare_classic_transfer (FreefareTag tag, const MifareClassicBlockNumber block) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_CLASSIC (tag); BUFFER_INIT (cmd, 2); BUFFER_INIT (res, 1); diff --git a/libfreefare/mifare_desfire.c b/libfreefare/mifare_desfire.c index d7e531d..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; } @@ -288,7 +303,6 @@ int mifare_desfire_connect (FreefareTag tag) { ASSERT_INACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); nfc_target pnti; nfc_modulation modulation = { @@ -332,7 +346,6 @@ int mifare_desfire_disconnect (FreefareTag tag) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); free (MIFARE_DESFIRE (tag)->session_key); MIFARE_DESFIRE(tag)->session_key = NULL; @@ -353,7 +366,6 @@ static int authenticate (FreefareTag tag, uint8_t cmd, uint8_t key_no, MifareDESFireKey key) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); memset (MIFARE_DESFIRE (tag)->ivect, 0, MAX_CRYPTO_BLOCK_SIZE); @@ -471,7 +483,6 @@ int mifare_desfire_change_key_settings (FreefareTag tag, uint8_t settings) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); ASSERT_AUTHENTICATED (tag); BUFFER_INIT (cmd, 9 + CMAC_LENGTH); @@ -497,7 +508,6 @@ int mifare_desfire_get_key_settings (FreefareTag tag, uint8_t *settings, uint8_t *max_keys) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); BUFFER_INIT (cmd, 1); BUFFER_INIT (res, 3 + CMAC_LENGTH); @@ -526,7 +536,6 @@ int mifare_desfire_change_key (FreefareTag tag, uint8_t key_no, MifareDESFireKey new_key, MifareDESFireKey old_key) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); ASSERT_AUTHENTICATED (tag); BUFFER_INIT (cmd, 42); @@ -640,7 +649,6 @@ int mifare_desfire_get_key_version (FreefareTag tag, uint8_t key_no, uint8_t *version) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); ASSERT_NOT_NULL (version); @@ -671,7 +679,6 @@ static int create_application (FreefareTag tag, MifareDESFireAID aid, uint8_t settings1, uint8_t settings2, int want_iso_application, int want_iso_file_identifiers, uint16_t iso_file_id, uint8_t *iso_file_name, size_t iso_file_name_len) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); BUFFER_INIT (cmd, 22); BUFFER_INIT (res, 1 + CMAC_LENGTH); @@ -743,7 +750,6 @@ int mifare_desfire_delete_application (FreefareTag tag, MifareDESFireAID aid) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); BUFFER_INIT (cmd, 4 + CMAC_LENGTH); BUFFER_INIT (res, 1 + CMAC_LENGTH); @@ -778,7 +784,6 @@ int mifare_desfire_get_application_ids (FreefareTag tag, MifareDESFireAID *aids[], size_t *count) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); BUFFER_INIT (cmd, 1); BUFFER_INIT (res, MAX_RAPDU_SIZE); @@ -833,7 +838,6 @@ int mifare_desfire_get_df_names (FreefareTag tag, MifareDESFireDF *dfs[], size_t *count) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); *count = 0; *dfs = NULL; @@ -882,7 +886,6 @@ int mifare_desfire_select_application (FreefareTag tag, MifareDESFireAID aid) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); struct mifare_desfire_aid null_aid = { .data = { 0x00, 0x00, 0x00 } }; @@ -921,7 +924,6 @@ int mifare_desfire_format_picc (FreefareTag tag) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); ASSERT_AUTHENTICATED (tag); BUFFER_INIT (cmd, 1 + CMAC_LENGTH); @@ -953,7 +955,6 @@ int mifare_desfire_get_version (FreefareTag tag, struct mifare_desfire_version_info *version_info) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); ASSERT_NOT_NULL (version_info); @@ -991,7 +992,6 @@ int mifare_desfire_free_mem (FreefareTag tag, uint32_t *size) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); ASSERT_NOT_NULL (size); @@ -1019,7 +1019,6 @@ int mifare_desfire_set_configuration (FreefareTag tag, bool disable_format, bool enable_random_uid) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); BUFFER_INIT (cmd, 10); BUFFER_INIT (res, 1 + CMAC_LENGTH); @@ -1045,7 +1044,6 @@ int mifare_desfire_set_default_key (FreefareTag tag, MifareDESFireKey key) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); BUFFER_INIT (cmd, 34); BUFFER_INIT (res, 1 + CMAC_LENGTH); @@ -1085,7 +1083,6 @@ int mifare_desfire_set_ats (FreefareTag tag, uint8_t *ats) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); BUFFER_INIT (cmd, 34); BUFFER_INIT (res, 1 + CMAC_LENGTH); @@ -1122,7 +1119,6 @@ int mifare_desfire_get_card_uid (FreefareTag tag, char **uid) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); ASSERT_NOT_NULL (uid); @@ -1160,7 +1156,6 @@ int mifare_desfire_get_file_ids (FreefareTag tag, uint8_t **files, size_t *count) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); BUFFER_INIT (cmd, 1 + CMAC_LENGTH); BUFFER_INIT (res, 16 + CMAC_LENGTH); @@ -1193,7 +1188,6 @@ int mifare_desfire_get_iso_file_ids (FreefareTag tag, uint16_t **files, size_t *count) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); BUFFER_INIT (cmd, 1); BUFFER_INIT (res, 2*27 + 1); @@ -1241,7 +1235,6 @@ int mifare_desfire_get_file_settings (FreefareTag tag, uint8_t file_no, struct mifare_desfire_file_settings *settings) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); if (cached_file_settings_current[file_no]) { *settings = cached_file_settings[file_no]; @@ -1300,7 +1293,6 @@ int mifare_desfire_change_file_settings (FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); struct mifare_desfire_file_settings settings; int res = mifare_desfire_get_file_settings (tag, file_no, &settings); @@ -1353,7 +1345,6 @@ static int create_file1 (FreefareTag tag, uint8_t command, uint8_t file_no, int has_iso_file_id, uint16_t iso_file_id, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); BUFFER_INIT (cmd, 10 + CMAC_LENGTH); BUFFER_INIT (res, 1 + CMAC_LENGTH); @@ -1409,7 +1400,6 @@ int mifare_desfire_create_value_file (FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, int32_t lower_limit, int32_t upper_limit, int32_t value, uint8_t limited_credit_enable) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); BUFFER_INIT (cmd, 18 + CMAC_LENGTH); BUFFER_INIT (res, 1 + CMAC_LENGTH); @@ -1442,7 +1432,6 @@ static int create_file2 (FreefareTag tag, uint8_t command, uint8_t file_no, int has_iso_file_id, uint16_t iso_file_id, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); BUFFER_INIT (cmd, 11 + CMAC_LENGTH); BUFFER_INIT (res, 1 + CMAC_LENGTH); @@ -1499,7 +1488,6 @@ int mifare_desfire_delete_file (FreefareTag tag, uint8_t file_no) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); BUFFER_INIT (cmd, 2 + CMAC_LENGTH); BUFFER_INIT (res, 1 + CMAC_LENGTH); @@ -1531,7 +1519,6 @@ read_data (FreefareTag tag, uint8_t command, uint8_t file_no, off_t offset, size size_t bytes_received = 0; ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); ASSERT_CS (cs); BUFFER_INIT (cmd, 8); @@ -1654,7 +1641,6 @@ write_data (FreefareTag tag, uint8_t command, uint8_t file_no, off_t offset, siz size_t bytes_send = 0; ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); ASSERT_CS (cs); BUFFER_INIT (cmd, 8 + length + CMAC_LENGTH); @@ -1734,7 +1720,6 @@ mifare_desfire_get_value_ex (FreefareTag tag, uint8_t file_no, int32_t *value, i return errno = EINVAL, -1; ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); ASSERT_CS (cs); BUFFER_INIT (cmd, 2 + CMAC_LENGTH); @@ -1768,7 +1753,6 @@ int mifare_desfire_credit_ex (FreefareTag tag, uint8_t file_no, int32_t amount, int cs) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); ASSERT_CS (cs); BUFFER_INIT (cmd, 10 + CMAC_LENGTH); @@ -1801,7 +1785,6 @@ int mifare_desfire_debit_ex (FreefareTag tag, uint8_t file_no, int32_t amount, int cs) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); ASSERT_CS (cs); BUFFER_INIT (cmd, 10 + CMAC_LENGTH); @@ -1834,7 +1817,6 @@ int mifare_desfire_limited_credit_ex (FreefareTag tag, uint8_t file_no, int32_t amount, int cs) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); ASSERT_CS (cs); BUFFER_INIT (cmd, 10 + CMAC_LENGTH); @@ -1885,7 +1867,6 @@ int mifare_desfire_clear_record_file (FreefareTag tag, uint8_t file_no) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); BUFFER_INIT (cmd, 2 + CMAC_LENGTH); BUFFER_INIT (res, 1 + CMAC_LENGTH); @@ -1912,7 +1893,6 @@ int mifare_desfire_commit_transaction (FreefareTag tag) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); BUFFER_INIT (cmd, 1 + CMAC_LENGTH); BUFFER_INIT (res, 1 + CMAC_LENGTH); @@ -1936,7 +1916,6 @@ int mifare_desfire_abort_transaction (FreefareTag tag) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_DESFIRE (tag); BUFFER_INIT (cmd, 1 + CMAC_LENGTH); BUFFER_INIT (res, 1 + CMAC_LENGTH); 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 c486a4b..2afb212 100644 --- a/libfreefare/mifare_ultralight.c +++ b/libfreefare/mifare_ultralight.c @@ -45,7 +45,7 @@ #define ASSERT_VALID_PAGE(tag, page, mode_write) \ do { \ - if (IS_MIFARE_ULTRALIGHT_C(tag)) { \ + if (is_mifare_ultralightc (tag)) { \ if (mode_write) { \ if (page >= MIFARE_ULTRALIGHT_C_PAGE_COUNT) return errno = EINVAL, -1; \ } else { \ @@ -89,6 +89,24 @@ } \ } while (0) +static bool +taste (nfc_target target) +{ + return target.nm.nmt == NMT_ISO14443A && target.nti.nai.btSak == 0x00; +} + +bool +mifare_ultralight_taste (nfc_device *device, nfc_target target) +{ + return taste (target) && !is_mifare_ultralightc_on_reader (device, target.nti.nai); +} + +bool +mifare_ultralightc_taste (nfc_device *device, nfc_target target) +{ + return taste (target) && is_mifare_ultralightc_on_reader (device, target.nti.nai); +} + /* * Memory management functions. @@ -97,10 +115,32 @@ /* * 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) { - return malloc (sizeof (struct mifare_ultralight_tag)); + FreefareTag tag; + + if ((tag = malloc (sizeof (struct mifare_ultralight_tag)))) { + 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 tag; +} + +FreefareTag +mifare_ultralight_tag_new (nfc_device *device, nfc_target target) +{ + 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); } /* @@ -112,6 +152,12 @@ mifare_ultralight_tag_free (FreefareTag tag) free (tag); } +void +mifare_ultralightc_tag_free (FreefareTag tag) +{ + mifare_ultralight_tag_free (tag); +} + /* * MIFARE card communication preparation functions @@ -129,7 +175,6 @@ int mifare_ultralight_connect (FreefareTag tag) { ASSERT_INACTIVE (tag); - ASSERT_MIFARE_ULTRALIGHT (tag); nfc_target pnti; nfc_modulation modulation = { @@ -154,7 +199,6 @@ int mifare_ultralight_disconnect (FreefareTag tag) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_ULTRALIGHT (tag); if (nfc_initiator_deselect_target (tag->device) >= 0) { tag->active = 0; @@ -180,7 +224,6 @@ int mifare_ultralight_read (FreefareTag tag, MifareUltralightPageNumber page, MifareUltralightPage *data) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_ULTRALIGHT (tag); ASSERT_VALID_PAGE (tag, page, false); if (!MIFARE_ULTRALIGHT(tag)->cached_pages[page]) { @@ -194,7 +237,7 @@ mifare_ultralight_read (FreefareTag tag, MifareUltralightPageNumber page, Mifare /* Handle wrapped pages */ int iPageCount; - if (IS_MIFARE_ULTRALIGHT_C(tag)) { + if (is_mifare_ultralightc (tag)) { iPageCount = MIFARE_ULTRALIGHT_C_PAGE_COUNT_READ; } else { iPageCount = MIFARE_ULTRALIGHT_PAGE_COUNT; @@ -220,7 +263,6 @@ int mifare_ultralight_write (FreefareTag tag, const MifareUltralightPageNumber page, const MifareUltralightPage data) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_ULTRALIGHT (tag); ASSERT_VALID_PAGE (tag, page, true); BUFFER_INIT (cmd, 6); @@ -245,7 +287,6 @@ int mifare_ultralightc_authenticate (FreefareTag tag, const MifareDESFireKey key) { ASSERT_ACTIVE (tag); - ASSERT_MIFARE_ULTRALIGHT_C (tag); BUFFER_INIT (cmd1, 2); BUFFER_INIT (res, 9); @@ -306,6 +347,18 @@ mifare_ultralightc_authenticate (FreefareTag tag, const MifareDESFireKey key) return 0; } +bool +is_mifare_ultralight (FreefareTag tag) +{ + return tag->type == MIFARE_ULTRALIGHT; +} + +bool +is_mifare_ultralightc (FreefareTag tag) +{ + return tag->type == MIFARE_ULTRALIGHT_C; +} + /* * Callback for freefare_tag_new to test presence of a MIFARE UltralightC on the reader. */ 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 09d46f2..b154631 100644 --- a/test/test_mifare_ultralight.c +++ b/test/test_mifare_ultralight.c @@ -75,7 +75,7 @@ test_mifare_ultralight_invalid_page (void) MifareUltralightPage page = { 0x00, 0x00, 0x00, 0x00 }; int invalid_page; - if (IS_MIFARE_ULTRALIGHT_C (tag)) { + if (is_mifare_ultralightc (tag)) { invalid_page = MIFARE_ULTRALIGHT_C_PAGE_COUNT; } else { invalid_page = MIFARE_ULTRALIGHT_PAGE_COUNT; @@ -130,7 +130,7 @@ test_mifare_ultralight_cache_wrap (void) int res; MifareUltralightPage page; int last_page; - if (IS_MIFARE_ULTRALIGHT_C (tag)) { + if (is_mifare_ultralightc (tag)) { // Last 4 blocks are for 3DES key and cannot be read, read will wrap from 0x2b last_page = MIFARE_ULTRALIGHT_C_PAGE_COUNT_READ -1; // Actually engineering samples require auth to read above page 0x28 so we skip the test entirely @@ -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);