diff --git a/HACKING.md b/HACKING.md index e35a047..e458456 100644 --- a/HACKING.md +++ b/HACKING.md @@ -37,6 +37,8 @@ that you don't have to care about indentation anymore. For more details, please read the [style(9) man page from FreeBSD's website](http://www.freebsd.org/cgi/man.cgi?query=style). +For style correction install package `astyle`. Then run `make style`. + ## Write tests I already told you cutter is lovely, so you really should use it! If you want diff --git a/examples/mifare-desfire-ev1-configure-random-uid.c b/examples/mifare-desfire-ev1-configure-random-uid.c index ad777b7..f19a61f 100644 --- a/examples/mifare-desfire-ev1-configure-random-uid.c +++ b/examples/mifare-desfire-ev1-configure-random-uid.c @@ -153,8 +153,8 @@ main(int argc, char *argv[]) } } break; - case 4: // Random UID - {} // Compilation fails if label is directly followed by the declaration rather than a statement + case 4: { // Random UID + } // Compilation fails if label is directly followed by the declaration rather than a statement MifareDESFireKey key_picc = mifare_desfire_des_key_new_with_version(key_data_picc); res = mifare_desfire_authenticate(tags[i], 0, key_picc); if (res < 0) { diff --git a/libfreefare/CMakeLists.txt b/libfreefare/CMakeLists.txt index 2015f22..871fef7 100644 --- a/libfreefare/CMakeLists.txt +++ b/libfreefare/CMakeLists.txt @@ -13,6 +13,7 @@ set(LIBRARY_SOURCES mifare_key_deriver mifare_ultralight ntag21x + ntag21x_error tlv ../contrib/libutil/hexdump ) diff --git a/libfreefare/Makefile.am b/libfreefare/Makefile.am index 5238c4b..fbd6faa 100644 --- a/libfreefare/Makefile.am +++ b/libfreefare/Makefile.am @@ -16,6 +16,7 @@ libfreefare_la_SOURCES = felica.c \ mad.c \ mifare_application.c \ ntag21x.c \ + ntag21x_error.c \ tlv.c libfreefare_la_LIBADD = diff --git a/libfreefare/freefare.c b/libfreefare/freefare.c index d46446f..86dcb5e 100644 --- a/libfreefare/freefare.c +++ b/libfreefare/freefare.c @@ -225,6 +225,8 @@ freefare_strerror(FreefareTag tag) } else if (MIFARE_DESFIRE(tag)->last_picc_error) { p = mifare_desfire_error_lookup(MIFARE_DESFIRE(tag)->last_picc_error); } + } else if (tag->type == NTAG_21x) { + p = ntag21x_error_lookup(NTAG_21x(tag)->last_error); } } return p; diff --git a/libfreefare/freefare.h b/libfreefare/freefare.h index 914ab87..9a4154d 100644 --- a/libfreefare/freefare.h +++ b/libfreefare/freefare.h @@ -93,6 +93,7 @@ bool is_mifare_ultralightc_on_reader(nfc_device *device, nfc_iso14443a_info na bool ntag21x_taste(nfc_device *device, nfc_target target); +uint8_t ntag21x_last_error(FreefareTag tag); /* NTAG21x access features */ #define NTAG_PROT 0x80 @@ -102,6 +103,7 @@ bool ntag21x_taste(nfc_device *device, nfc_target target); #define NTAG_AUTHLIM 0x07 enum ntag_tag_subtype { + NTAG_UNKNOWN, NTAG_213, NTAG_215, NTAG_216 @@ -367,6 +369,8 @@ bit 0: PICC master key frozen (reversible with configuration change or when form /* Error code managed by the library */ #define CRYPTO_ERROR 0x01 +#define TAG_INFO_MISSING_ERROR 0xBA +#define UNKNOWN_TAG_TYPE_ERROR 0xBB struct mifare_desfire_aid; typedef struct mifare_desfire_aid *MifareDESFireAID; diff --git a/libfreefare/freefare_internal.h b/libfreefare/freefare_internal.h index 5f966b0..25c9f3a 100644 --- a/libfreefare/freefare_internal.h +++ b/libfreefare/freefare_internal.h @@ -243,6 +243,8 @@ struct ntag21x_tag { uint8_t minor_product_version; uint8_t storage_size; uint8_t protocol_type; + + uint8_t last_error; }; struct ntag21x_key { @@ -250,6 +252,8 @@ struct ntag21x_key { uint8_t pack[2]; // 2B Password Acknowlege }; +const char *ntag21x_error_lookup(uint8_t code); + /* * FreefareTag assertion macros * diff --git a/libfreefare/ntag21x.c b/libfreefare/ntag21x.c index 3b68843..5abd4fb 100644 --- a/libfreefare/ntag21x.c +++ b/libfreefare/ntag21x.c @@ -44,6 +44,8 @@ {return errno = EINVAL, -1;} \ else if(NTAG_21x(tag)->subtype == NTAG_216&&page>0xE6) \ {return errno = EINVAL, -1;} \ + else if(NTAG_21x(tag)->subtype == NTAG_UNKNOWN) \ + {return errno = EINVAL, -1;} \ } else { \ if(NTAG_21x(tag)->subtype == NTAG_213&&page>0x2C) \ {return errno = EINVAL, -1;} \ @@ -51,6 +53,8 @@ {return errno = EINVAL, -1;} \ else if(NTAG_21x(tag)->subtype == NTAG_216&&page>0xE6) \ {return errno = EINVAL, -1;} \ + else if(NTAG_21x(tag)->subtype == NTAG_UNKNOWN) \ + {return errno = EINVAL, -1;} \ } \ } while (0) @@ -113,14 +117,15 @@ _ntag21x_tag_new(nfc_device *device, nfc_target target) tag->device = device; tag->info = target; tag->active = 0; - NTAG_21x(tag)->subtype = NTAG_213; // Set tag subtype - NTAG_21x(tag)->vendor_id = 0x04; - NTAG_21x(tag)->product_type = 0x04; - NTAG_21x(tag)->product_subtype = 0x02; - NTAG_21x(tag)->major_product_version = 0x01; + NTAG_21x(tag)->subtype = NTAG_UNKNOWN; + NTAG_21x(tag)->vendor_id = 0x00; + NTAG_21x(tag)->product_type = 0x00; + NTAG_21x(tag)->product_subtype = 0x00; + NTAG_21x(tag)->major_product_version = 0x00; NTAG_21x(tag)->minor_product_version = 0x00; - NTAG_21x(tag)->storage_size = 0x0f; - NTAG_21x(tag)->protocol_type = 0x03; + NTAG_21x(tag)->storage_size = 0x00; + NTAG_21x(tag)->protocol_type = 0x00; + NTAG_21x(tag)->last_error = OPERATION_OK; } return tag; @@ -137,14 +142,15 @@ _ntag21x_tag_reuse(FreefareTag old_tag) tag->device = old_tag->device; tag->info = old_tag->info; tag->active = 0; - NTAG_21x(tag)->subtype = NTAG_213; // Set tag subtype - NTAG_21x(tag)->vendor_id = 0x04; - NTAG_21x(tag)->product_type = 0x04; - NTAG_21x(tag)->product_subtype = 0x02; - NTAG_21x(tag)->major_product_version = 0x01; - NTAG_21x(tag)->minor_product_version = 0x00; - NTAG_21x(tag)->storage_size = 0x0f; - NTAG_21x(tag)->protocol_type = 0x03; + NTAG_21x(tag)->subtype = NTAG_21x(old_tag)->subtype; + NTAG_21x(tag)->vendor_id = NTAG_21x(old_tag)->vendor_id; + NTAG_21x(tag)->product_type = NTAG_21x(old_tag)->product_type; + NTAG_21x(tag)->product_subtype = NTAG_21x(old_tag)->product_subtype; + NTAG_21x(tag)->major_product_version = NTAG_21x(old_tag)->major_product_version; + NTAG_21x(tag)->minor_product_version = NTAG_21x(old_tag)->minor_product_version; + NTAG_21x(tag)->storage_size = NTAG_21x(old_tag)->storage_size; + NTAG_21x(tag)->protocol_type = NTAG_21x(old_tag)->protocol_type; + NTAG_21x(tag)->last_error = NTAG_21x(old_tag)->last_error; } return tag; @@ -282,7 +288,8 @@ ntag21x_get_info(FreefareTag tag) NTAG_21x(tag)->subtype = NTAG_216; break; default: - NTAG_21x(tag)->subtype = NTAG_213; + NTAG_21x(tag)->last_error = UNKNOWN_TAG_TYPE_ERROR; + return -1; } return 0; } @@ -309,6 +316,7 @@ ntag21x_get_last_page(FreefareTag tag) case NTAG_216: return 0xE6; default: + NTAG_21x(tag)->last_error = TAG_INFO_MISSING_ERROR; return 0x00; } } @@ -348,6 +356,10 @@ ntag21x_read_signature(FreefareTag tag, uint8_t *data) int ntag21x_set_pwd(FreefareTag tag, uint8_t data[4]) // Set password { + if (NTAG_21x(tag)->subtype == NTAG_UNKNOWN) { + NTAG_21x(tag)->last_error = TAG_INFO_MISSING_ERROR; + return -1; + } uint8_t page = ntag21x_get_last_page(tag) - 1; // PWD page is located 1 before last page int res = ntag21x_write(tag, page, data); return res; @@ -356,6 +368,10 @@ ntag21x_set_pwd(FreefareTag tag, uint8_t data[4]) // Set password int ntag21x_set_pack(FreefareTag tag, uint8_t data[2]) // Set pack { + if (NTAG_21x(tag)->subtype == NTAG_UNKNOWN) { + NTAG_21x(tag)->last_error = TAG_INFO_MISSING_ERROR; + return -1; + } BUFFER_INIT(buff, 4); BUFFER_APPEND_BYTES(buff, data, 2); BUFFER_APPEND(buff, 0x00); @@ -382,6 +398,10 @@ ntag21x_set_key(FreefareTag tag, const NTAG21xKey key) // Set key int ntag21x_set_auth(FreefareTag tag, uint8_t byte) // Set AUTH0 byte (from which page starts password protection) { + if (NTAG_21x(tag)->subtype == NTAG_UNKNOWN) { + NTAG_21x(tag)->last_error = TAG_INFO_MISSING_ERROR; + return -1; + } BUFFER_INIT(cdata, 4); int page = ntag21x_get_last_page(tag) - 3; // AUTH0 byte is on 4th page from back int res; @@ -396,6 +416,10 @@ ntag21x_set_auth(FreefareTag tag, uint8_t byte) // Set AUTH0 byte (from which pa int ntag21x_get_auth(FreefareTag tag, uint8_t *byte) // Get AUTH0 byte { + if (NTAG_21x(tag)->subtype == NTAG_UNKNOWN) { + NTAG_21x(tag)->last_error = TAG_INFO_MISSING_ERROR; + return -1; + } BUFFER_INIT(cdata, 4); int page = ntag21x_get_last_page(tag) - 3; // AUTH0 byte is on 4th page from back int res; @@ -409,6 +433,10 @@ ntag21x_get_auth(FreefareTag tag, uint8_t *byte) // Get AUTH0 byte int ntag21x_access_enable(FreefareTag tag, uint8_t byte) // Enable access feature in ACCESS byte { + if (NTAG_21x(tag)->subtype == NTAG_UNKNOWN) { + NTAG_21x(tag)->last_error = TAG_INFO_MISSING_ERROR; + return -1; + } BUFFER_INIT(cdata, 4); int page = ntag21x_get_last_page(tag) - 2; // ACCESS byte is on 3th page from back int res; @@ -423,6 +451,10 @@ ntag21x_access_enable(FreefareTag tag, uint8_t byte) // Enable access feature in int ntag21x_access_disable(FreefareTag tag, uint8_t byte) // Disable access feature in ACCESS byte { + if (NTAG_21x(tag)->subtype == NTAG_UNKNOWN) { + NTAG_21x(tag)->last_error = TAG_INFO_MISSING_ERROR; + return -1; + } BUFFER_INIT(cdata, 4); int page = ntag21x_get_last_page(tag) - 2; // ACCESS byte is on 3th page from back int res; @@ -437,6 +469,10 @@ ntag21x_access_disable(FreefareTag tag, uint8_t byte) // Disable access feature int ntag21x_get_access(FreefareTag tag, uint8_t *byte) // Get ACCESS byte { + if (NTAG_21x(tag)->subtype == NTAG_UNKNOWN) { + NTAG_21x(tag)->last_error = TAG_INFO_MISSING_ERROR; + return -1; + } BUFFER_INIT(cdata, 4); uint8_t page = ntag21x_get_last_page(tag) - 2; // ACCESS byte is on 3th page from back int res; @@ -464,6 +500,10 @@ ntag21x_check_access(FreefareTag tag, uint8_t byte, bool *result) // Check if ac int ntag21x_get_authentication_limit(FreefareTag tag, uint8_t *byte) // Get authentication limit { + if (NTAG_21x(tag)->subtype == NTAG_UNKNOWN) { + NTAG_21x(tag)->last_error = TAG_INFO_MISSING_ERROR; + return -1; + } BUFFER_INIT(cdata, 4); uint8_t page = ntag21x_get_last_page(tag) - 2; // ACCESS byte is on 3th page from back int res; @@ -480,6 +520,10 @@ ntag21x_set_authentication_limit(FreefareTag tag, uint8_t byte) // Set authentic { if (byte > 7) // Check for invalid range of auth limit return -1; + if (NTAG_21x(tag)->subtype == NTAG_UNKNOWN) { + NTAG_21x(tag)->last_error = TAG_INFO_MISSING_ERROR; + return -1; + } BUFFER_INIT(cdata, 4); int page = ntag21x_get_last_page(tag) - 2; // ACCESS byte is on 3th page from back diff --git a/libfreefare/ntag21x_error.c b/libfreefare/ntag21x_error.c new file mode 100644 index 0000000..c11c227 --- /dev/null +++ b/libfreefare/ntag21x_error.c @@ -0,0 +1,41 @@ +#include + +#include + +#include + +#include "freefare_internal.h" + +#define EM(e) { e, #e } + +static struct ntag21x_error_message { + uint8_t code; + const char *message; +} ntag21x_error_messages[] = { + EM(OPERATION_OK), + EM(TAG_INFO_MISSING_ERROR), + EM(UNKNOWN_TAG_TYPE_ERROR), + { 0, NULL } +}; + +const char * +ntag21x_error_lookup(uint8_t code) +{ + struct ntag21x_error_message *e = ntag21x_error_messages; + while (e->message) { + if (e->code == code) + return (e->message); + e++; + } + + return "Invalid error code"; +} + +uint8_t +ntag21x_last_error(FreefareTag tag) +{ + if (tag->type != NTAG_21x) + return 0; + + return NTAG_21x(tag)->last_error; +} diff --git a/test/fixture.h b/test/fixture.h index 31d7922..e08e27f 100644 --- a/test/fixture.h +++ b/test/fixture.h @@ -1,6 +1,6 @@ #ifndef _FIXTURE_H -#define _FIXTURE_H + #define _FIXTURE_H -extern FreefareTag tag; + extern FreefareTag tag; #endif /* _FIXTURE_H */