Skip to content

Commit

Permalink
Fix issues for NTAG21x tags
Browse files Browse the repository at this point in the history
- Change default tag from NTAG_213 to NTAG_UNKNOWN so unknown tags can
  be detected.  ntag_get_info() MUST be called after connect;
- Fix reuse function which used to reset all tag info;
- Introduce ntag21x error reporting through freefare_error(3);
  • Loading branch information
SloCompTech authored and smortex committed Mar 9, 2018
1 parent 75f08d3 commit c18f702
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 20 deletions.
2 changes: 2 additions & 0 deletions HACKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions examples/mifare-desfire-ev1-configure-random-uid.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions libfreefare/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ set(LIBRARY_SOURCES
mifare_key_deriver
mifare_ultralight
ntag21x
ntag21x_error
tlv
../contrib/libutil/hexdump
)
Expand Down
1 change: 1 addition & 0 deletions libfreefare/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ libfreefare_la_SOURCES = felica.c \
mad.c \
mifare_application.c \
ntag21x.c \
ntag21x_error.c \
tlv.c
libfreefare_la_LIBADD =

Expand Down
2 changes: 2 additions & 0 deletions libfreefare/freefare.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions libfreefare/freefare.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions libfreefare/freefare_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,17 @@ struct ntag21x_tag {
uint8_t minor_product_version;
uint8_t storage_size;
uint8_t protocol_type;

uint8_t last_error;
};

struct ntag21x_key {
uint8_t data[4]; // 4B key
uint8_t pack[2]; // 2B Password Acknowlege
};

const char *ntag21x_error_lookup(uint8_t code);

/*
* FreefareTag assertion macros
*
Expand Down
76 changes: 60 additions & 16 deletions libfreefare/ntag21x.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,17 @@
{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;} \
else if(NTAG_21x(tag)->subtype == NTAG_215&&page>0x86) \
{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)

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
}
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down
41 changes: 41 additions & 0 deletions libfreefare/ntag21x_error.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <sys/types.h>

#include <stdlib.h>

#include <freefare.h>

#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;
}
4 changes: 2 additions & 2 deletions test/fixture.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#ifndef _FIXTURE_H
#define _FIXTURE_H
#define _FIXTURE_H

extern FreefareTag tag;
extern FreefareTag tag;

#endif /* _FIXTURE_H */

0 comments on commit c18f702

Please sign in to comment.