Merge pull request #64 from nfc-tools/style
Use astyle(1) to make style consistent
This commit is contained in:
commit
b49692848e
68 changed files with 5956 additions and 5950 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -36,6 +36,10 @@ examples/mifare-desfire-info
|
|||
examples/mifare-desfire-read-ndef
|
||||
examples/mifare-desfire-write-ndef
|
||||
examples/mifare-ultralight-info
|
||||
examples/ntag-detect
|
||||
examples/ntag-removeauth
|
||||
examples/ntag-setauth
|
||||
examples/ntag-write
|
||||
test/test-suite.log
|
||||
test/run-test.sh.log
|
||||
test/run-test.sh.trs
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
SUBDIRS = contrib libfreefare test examples
|
||||
libfreefare_subdirs = libfreefare test examples
|
||||
|
||||
SUBDIRS = contrib $(libfreefare_subdirs)
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libfreefare.pc
|
||||
|
@ -39,3 +41,7 @@ svn-keywords:
|
|||
svn-keywords-check:
|
||||
@echo "Files missing a '$$"Id"$$' vcs keyword:"
|
||||
@$(SVN_KEYWORDS_FILES_LIST_CMD) | xargs grep -L '\$$Id[^$$]*\$$'
|
||||
|
||||
style:
|
||||
find ${libfreefare_subdirs} -name '*.[ch]' -exec perl -pi -e 's/[ \t]+$$//' {} \;
|
||||
find ${libfreefare_subdirs} -name '*.[ch]' -exec astyle --style=linux --indent=force-tab-x --lineend=linux '{}' ';'
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2015, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -23,56 +23,56 @@
|
|||
#include <freefare.h>
|
||||
|
||||
int
|
||||
main (void)
|
||||
main(void)
|
||||
{
|
||||
nfc_device *device = NULL;
|
||||
FreefareTag *tags = NULL;
|
||||
nfc_connstring devices[8];
|
||||
|
||||
nfc_context *context;
|
||||
nfc_init (&context);
|
||||
nfc_init(&context);
|
||||
if (context == NULL)
|
||||
errx (EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
size_t device_count = nfc_list_devices (context, devices, 8);
|
||||
size_t device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
errx (EXIT_FAILURE, "No NFC device found.");
|
||||
errx(EXIT_FAILURE, "No NFC device found.");
|
||||
|
||||
for (size_t d = 0; d < device_count; d++) {
|
||||
device = nfc_open (context, devices[d]);
|
||||
device = nfc_open(context, devices[d]);
|
||||
if (!device) {
|
||||
errx (EXIT_FAILURE, "nfc_open() failed.");
|
||||
errx(EXIT_FAILURE, "nfc_open() failed.");
|
||||
}
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
tags = freefare_get_tags(device);
|
||||
if (!tags) {
|
||||
nfc_close (device);
|
||||
errx (EXIT_FAILURE, "Error listing FeliCa tag.");
|
||||
nfc_close(device);
|
||||
errx(EXIT_FAILURE, "Error listing FeliCa tag.");
|
||||
}
|
||||
|
||||
for (int i = 0; tags[i]; i++) {
|
||||
if (FELICA != freefare_get_tag_type (tags[i]))
|
||||
if (FELICA != freefare_get_tag_type(tags[i]))
|
||||
continue;
|
||||
|
||||
char *uid = freefare_get_tag_uid (tags[i]);
|
||||
printf ("Dumping %s tag %s\n", freefare_get_tag_friendly_name (tags[i]), uid);
|
||||
free (uid);
|
||||
printf ("Number\tName\tData\n");
|
||||
char *uid = freefare_get_tag_uid(tags[i]);
|
||||
printf("Dumping %s tag %s\n", freefare_get_tag_friendly_name(tags[i]), uid);
|
||||
free(uid);
|
||||
printf("Number\tName\tData\n");
|
||||
|
||||
for (int block = 0x00; block < 0x0f; block++) {
|
||||
uint8_t buffer[16];
|
||||
|
||||
if (felica_read (tags[i], FELICA_SC_RO, block, buffer, sizeof (buffer)) < 0)
|
||||
errx (EXIT_FAILURE, "Error reading block %d", block);
|
||||
if (felica_read(tags[i], FELICA_SC_RO, block, buffer, sizeof(buffer)) < 0)
|
||||
errx(EXIT_FAILURE, "Error reading block %d", block);
|
||||
|
||||
if (block < 0x0e)
|
||||
printf ("0x%02x\tS_PAD%d\t", block, block);
|
||||
printf("0x%02x\tS_PAD%d\t", block, block);
|
||||
else
|
||||
printf ("0x%02x\tREG\t", block);
|
||||
printf("0x%02x\tREG\t", block);
|
||||
for (int j = 0; j < 16; j++) {
|
||||
printf ("%02x ", buffer[j]);
|
||||
printf("%02x ", buffer[j]);
|
||||
}
|
||||
printf ("\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
char *block_names[] = {
|
||||
|
@ -84,19 +84,19 @@ main (void)
|
|||
for (int block = 0x80; block < 0x89; block++) {
|
||||
uint8_t buffer[16];
|
||||
|
||||
if (felica_read (tags[i], FELICA_SC_RO, block, buffer, sizeof (buffer)) < 0)
|
||||
errx (EXIT_FAILURE, "Error reading block %d", block);
|
||||
if (felica_read(tags[i], FELICA_SC_RO, block, buffer, sizeof(buffer)) < 0)
|
||||
errx(EXIT_FAILURE, "Error reading block %d", block);
|
||||
|
||||
printf ("0x%02x\t%s\t", block, block_names[block - 0x80]);
|
||||
printf("0x%02x\t%s\t", block, block_names[block - 0x80]);
|
||||
for (int j = 0; j < valid_bytes[block - 0x80]; j++) {
|
||||
printf ("%02x ", buffer[j]);
|
||||
printf("%02x ", buffer[j]);
|
||||
}
|
||||
printf ("\n");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
freefare_free_tags (tags);
|
||||
nfc_close (device);
|
||||
freefare_free_tags(tags);
|
||||
nfc_close(device);
|
||||
}
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2015, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -44,15 +44,15 @@
|
|||
#define NDEF_BUFFER_SIZE 512
|
||||
|
||||
void
|
||||
usage (char *progname)
|
||||
usage(char *progname)
|
||||
{
|
||||
fprintf (stderr, "usage: %s [options]\n", progname);
|
||||
fprintf (stderr, "\nAvailable options:\n");
|
||||
fprintf (stderr, " -o FILE Write NDEF message to FILE\n");
|
||||
fprintf(stderr, "usage: %s [options]\n", progname);
|
||||
fprintf(stderr, "\nAvailable options:\n");
|
||||
fprintf(stderr, " -o FILE Write NDEF message to FILE\n");
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int error = EXIT_SUCCESS;
|
||||
nfc_device *device = NULL;
|
||||
|
@ -60,14 +60,14 @@ main (int argc, char *argv[])
|
|||
|
||||
int ch;
|
||||
char *ndef_file = NULL;
|
||||
while ((ch = getopt (argc, argv, "o:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "o:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'o':
|
||||
ndef_file = optarg;
|
||||
break;
|
||||
case '?':
|
||||
usage (argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,26 +76,26 @@ main (int argc, char *argv[])
|
|||
size_t device_count;
|
||||
|
||||
nfc_context *context;
|
||||
nfc_init (&context);
|
||||
nfc_init(&context);
|
||||
if (context == NULL)
|
||||
errx (EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
errx (EXIT_FAILURE, "No NFC device found.");
|
||||
errx(EXIT_FAILURE, "No NFC device found.");
|
||||
|
||||
for (size_t d = 0; d < device_count; d++) {
|
||||
device = nfc_open (context, devices[d]);
|
||||
device = nfc_open(context, devices[d]);
|
||||
if (!device) {
|
||||
warnx ("nfc_open() failed.");
|
||||
warnx("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
tags = freefare_get_tags(device);
|
||||
if (!tags) {
|
||||
nfc_close (device);
|
||||
errx (EXIT_FAILURE, "Error listing FeliCa tag.");
|
||||
nfc_close(device);
|
||||
errx(EXIT_FAILURE, "Error listing FeliCa tag.");
|
||||
}
|
||||
|
||||
for (int i = 0; (!error) && tags[i]; i++) {
|
||||
|
@ -106,7 +106,7 @@ main (int argc, char *argv[])
|
|||
ssize_t s;
|
||||
|
||||
// FIXME Instead of reading as much as we can, we should read until end of NDEF record (if any is found).
|
||||
while ((ndef_space_left >= 16) && (s = felica_read (tags[i], FELICA_SC_RO, block++, p, 16)) > 0) {
|
||||
while ((ndef_space_left >= 16) && (s = felica_read(tags[i], FELICA_SC_RO, block++, p, 16)) > 0) {
|
||||
p += s;
|
||||
ndef_space_left -= s;
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ main (int argc, char *argv[])
|
|||
payload_length = ndef_record[2];
|
||||
payload_length_length = 1;
|
||||
} else {
|
||||
payload_length = be32toh (*(uint32_t *)(ndef_record + 2));
|
||||
payload_length = be32toh(*(uint32_t *)(ndef_record + 2));
|
||||
payload_length_length = 4;
|
||||
}
|
||||
ndef_record_length += payload_length_length;
|
||||
|
@ -139,28 +139,28 @@ main (int argc, char *argv[])
|
|||
|
||||
ndef_message_length += ndef_record_length;
|
||||
if (ndef_message_length > NDEF_BUFFER_SIZE)
|
||||
errx (EXIT_FAILURE, "NDEF message truncated");
|
||||
errx(EXIT_FAILURE, "NDEF message truncated");
|
||||
|
||||
} while ((ndef_record[0] & 0x40) != 0x40);
|
||||
}
|
||||
|
||||
if (ndef_message_length == 0)
|
||||
errx (EXIT_FAILURE, "No NDEF message found");
|
||||
errx(EXIT_FAILURE, "No NDEF message found");
|
||||
|
||||
FILE *f;
|
||||
if (ndef_file)
|
||||
f = fopen (ndef_file, "w");
|
||||
f = fopen(ndef_file, "w");
|
||||
else
|
||||
f = stdout;
|
||||
|
||||
if (fwrite (ndef_message, ndef_message_length, 1, f) != 1)
|
||||
err (EXIT_FAILURE, "Can't write NDEF message");
|
||||
if (fwrite(ndef_message, ndef_message_length, 1, f) != 1)
|
||||
err(EXIT_FAILURE, "Can't write NDEF message");
|
||||
|
||||
fclose (f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
freefare_free_tags (tags);
|
||||
nfc_close (device);
|
||||
freefare_free_tags(tags);
|
||||
nfc_close(device);
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere, Romuald Conty.
|
||||
* Copyright (C) 2012, Romuald Conty.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -35,18 +35,18 @@
|
|||
|
||||
MifareClassicKey default_keys[40];
|
||||
MifareClassicKey default_keys_int[] = {
|
||||
{ 0xff,0xff,0xff,0xff,0xff,0xff },
|
||||
{ 0xd3,0xf7,0xd3,0xf7,0xd3,0xf7 },
|
||||
{ 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5 },
|
||||
{ 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5 },
|
||||
{ 0x4d,0x3a,0x99,0xc3,0x51,0xdd },
|
||||
{ 0x1a,0x98,0x2c,0x7e,0x45,0x9a },
|
||||
{ 0xaa,0xbb,0xcc,0xdd,0xee,0xff },
|
||||
{ 0x00,0x00,0x00,0x00,0x00,0x00 }
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
|
||||
{ 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7 },
|
||||
{ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5 },
|
||||
{ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5 },
|
||||
{ 0x4d, 0x3a, 0x99, 0xc3, 0x51, 0xdd },
|
||||
{ 0x1a, 0x98, 0x2c, 0x7e, 0x45, 0x9a },
|
||||
{ 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
|
||||
};
|
||||
int format_mifare_classic_1k (FreefareTag tag);
|
||||
int format_mifare_classic_4k (FreefareTag tag);
|
||||
int try_format_sector (FreefareTag tag, MifareClassicSectorNumber sector);
|
||||
int format_mifare_classic_1k(FreefareTag tag);
|
||||
int format_mifare_classic_4k(FreefareTag tag);
|
||||
int try_format_sector(FreefareTag tag, MifareClassicSectorNumber sector);
|
||||
|
||||
static int at_block = 0;
|
||||
static int mod_block = 10;
|
||||
|
@ -60,81 +60,81 @@ struct {
|
|||
};
|
||||
|
||||
static void
|
||||
display_progress (void)
|
||||
display_progress(void)
|
||||
{
|
||||
at_block++;
|
||||
if (0 == (at_block % mod_block)) {
|
||||
printf ("%d", at_block);
|
||||
fflush (stdout);
|
||||
printf("%d", at_block);
|
||||
fflush(stdout);
|
||||
} else {
|
||||
printf (".");
|
||||
fflush (stdout);
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
format_mifare_classic_1k (FreefareTag tag)
|
||||
format_mifare_classic_1k(FreefareTag tag)
|
||||
{
|
||||
printf (START_FORMAT_N, 16);
|
||||
printf(START_FORMAT_N, 16);
|
||||
for (int sector = 0; sector < 16; sector++) {
|
||||
if (!try_format_sector (tag, sector))
|
||||
if (!try_format_sector(tag, sector))
|
||||
return 0;
|
||||
}
|
||||
printf (DONE_FORMAT);
|
||||
printf(DONE_FORMAT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
format_mifare_classic_4k (FreefareTag tag)
|
||||
format_mifare_classic_4k(FreefareTag tag)
|
||||
{
|
||||
printf (START_FORMAT_N, 32 + 8);
|
||||
printf(START_FORMAT_N, 32 + 8);
|
||||
for (int sector = 0; sector < (32 + 8); sector++) {
|
||||
if (!try_format_sector (tag, sector))
|
||||
if (!try_format_sector(tag, sector))
|
||||
return 0;
|
||||
}
|
||||
printf (DONE_FORMAT);
|
||||
printf(DONE_FORMAT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
try_format_sector (FreefareTag tag, MifareClassicSectorNumber sector)
|
||||
try_format_sector(FreefareTag tag, MifareClassicSectorNumber sector)
|
||||
{
|
||||
display_progress ();
|
||||
for (size_t i = 0; i < (sizeof (default_keys) / sizeof (MifareClassicKey)); i++) {
|
||||
MifareClassicBlockNumber block = mifare_classic_sector_last_block (sector);
|
||||
if ((0 == mifare_classic_connect (tag)) && (0 == mifare_classic_authenticate (tag, block, default_keys[i], MFC_KEY_A))) {
|
||||
if (0 == mifare_classic_format_sector (tag, sector)) {
|
||||
mifare_classic_disconnect (tag);
|
||||
display_progress();
|
||||
for (size_t i = 0; i < (sizeof(default_keys) / sizeof(MifareClassicKey)); i++) {
|
||||
MifareClassicBlockNumber block = mifare_classic_sector_last_block(sector);
|
||||
if ((0 == mifare_classic_connect(tag)) && (0 == mifare_classic_authenticate(tag, block, default_keys[i], MFC_KEY_A))) {
|
||||
if (0 == mifare_classic_format_sector(tag, sector)) {
|
||||
mifare_classic_disconnect(tag);
|
||||
return 1;
|
||||
} else if (EIO == errno) {
|
||||
err (EXIT_FAILURE, "sector %d", sector);
|
||||
err(EXIT_FAILURE, "sector %d", sector);
|
||||
}
|
||||
mifare_classic_disconnect (tag);
|
||||
mifare_classic_disconnect(tag);
|
||||
}
|
||||
|
||||
if ((0 == mifare_classic_connect (tag)) && (0 == mifare_classic_authenticate (tag, block, default_keys[i], MFC_KEY_B))) {
|
||||
if (0 == mifare_classic_format_sector (tag, sector)) {
|
||||
mifare_classic_disconnect (tag);
|
||||
if ((0 == mifare_classic_connect(tag)) && (0 == mifare_classic_authenticate(tag, block, default_keys[i], MFC_KEY_B))) {
|
||||
if (0 == mifare_classic_format_sector(tag, sector)) {
|
||||
mifare_classic_disconnect(tag);
|
||||
return 1;
|
||||
} else if (EIO == errno) {
|
||||
err (EXIT_FAILURE, "sector %d", sector);
|
||||
err(EXIT_FAILURE, "sector %d", sector);
|
||||
}
|
||||
mifare_classic_disconnect (tag);
|
||||
mifare_classic_disconnect(tag);
|
||||
}
|
||||
}
|
||||
|
||||
warnx ("No known authentication key for sector %d", sector);
|
||||
warnx("No known authentication key for sector %d", sector);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
usage(char *progname)
|
||||
{
|
||||
fprintf (stderr, "usage: %s [-fy] [keyfile]\n", progname);
|
||||
fprintf (stderr, "\nOptions:\n");
|
||||
fprintf (stderr, " -f Fast format (only erase MAD)\n");
|
||||
fprintf (stderr, " -y Do not ask for confirmation (dangerous)\n");
|
||||
fprintf (stderr, " keyfile Use keys from dump in addition to internal default keys\n");
|
||||
fprintf(stderr, "usage: %s [-fy] [keyfile]\n", progname);
|
||||
fprintf(stderr, "\nOptions:\n");
|
||||
fprintf(stderr, " -f Fast format (only erase MAD)\n");
|
||||
fprintf(stderr, " -y Do not ask for confirmation (dangerous)\n");
|
||||
fprintf(stderr, " keyfile Use keys from dump in addition to internal default keys\n");
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -145,47 +145,45 @@ main(int argc, char *argv[])
|
|||
nfc_device *device = NULL;
|
||||
FreefareTag *tags = NULL;
|
||||
|
||||
while ((ch = getopt (argc, argv, "fhy")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "fhy")) != -1) {
|
||||
switch (ch) {
|
||||
case 'f':
|
||||
format_options.fast = true;
|
||||
break;
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
exit (EXIT_SUCCESS);
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'y':
|
||||
format_options.interactive = false;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
// Remaining args, if any, are in argv[optind .. (argc-1)]
|
||||
|
||||
memcpy(default_keys, default_keys_int, sizeof(default_keys_int));
|
||||
|
||||
if ((argc - optind) > 0)
|
||||
{
|
||||
int i, rc;
|
||||
char kbuffer[1024] = {0};
|
||||
memset ( kbuffer, 0, sizeof kbuffer);
|
||||
FILE *fp = fopen(argv[optind], "rb");
|
||||
if (fp == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to open file");
|
||||
for (i = 0; (rc = getc(fp)) != EOF && i < 1024; kbuffer[i++] = rc) { }
|
||||
fclose(fp);
|
||||
if ((argc - optind) > 0) {
|
||||
int i, rc;
|
||||
char kbuffer[1024] = {0};
|
||||
memset(kbuffer, 0, sizeof kbuffer);
|
||||
FILE *fp = fopen(argv[optind], "rb");
|
||||
if (fp == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to open file");
|
||||
for (i = 0; (rc = getc(fp)) != EOF && i < 1024; kbuffer[i++] = rc) { }
|
||||
fclose(fp);
|
||||
|
||||
i = sizeof(default_keys_int) / 6;
|
||||
for(int s = 0; s<16; s++)
|
||||
{
|
||||
int startblock = s * 4;
|
||||
int pos_a = (startblock + 3) * 16;
|
||||
int pos_b = (startblock + 3) * 16 + 10;
|
||||
memcpy((default_keys + i++), kbuffer + pos_a, 6);
|
||||
memcpy((default_keys + i++), kbuffer + pos_b, 6);
|
||||
}
|
||||
i = sizeof(default_keys_int) / 6;
|
||||
for (int s = 0; s < 16; s++) {
|
||||
int startblock = s * 4;
|
||||
int pos_a = (startblock + 3) * 16;
|
||||
int pos_b = (startblock + 3) * 16 + 10;
|
||||
memcpy((default_keys + i++), kbuffer + pos_a, 6);
|
||||
memcpy((default_keys + i++), kbuffer + pos_b, 6);
|
||||
}
|
||||
}
|
||||
|
||||
nfc_connstring devices[8];
|
||||
|
@ -193,30 +191,30 @@ main(int argc, char *argv[])
|
|||
size_t device_count;
|
||||
|
||||
nfc_context *context;
|
||||
nfc_init (&context);
|
||||
nfc_init(&context);
|
||||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
errx (EXIT_FAILURE, "No NFC device found.");
|
||||
errx(EXIT_FAILURE, "No NFC device found.");
|
||||
|
||||
for (size_t d = 0; d < device_count; d++) {
|
||||
device = nfc_open (context, devices[d]);
|
||||
device = nfc_open(context, devices[d]);
|
||||
if (!device) {
|
||||
warnx ("nfc_open() failed.");
|
||||
warnx("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
tags = freefare_get_tags(device);
|
||||
if (!tags) {
|
||||
nfc_close (device);
|
||||
errx (EXIT_FAILURE, "Error listing Mifare Classic tag.");
|
||||
nfc_close(device);
|
||||
errx(EXIT_FAILURE, "Error listing Mifare Classic tag.");
|
||||
}
|
||||
|
||||
for (int i = 0; (!error) && tags[i]; i++) {
|
||||
switch (freefare_get_tag_type (tags[i])) {
|
||||
switch (freefare_get_tag_type(tags[i])) {
|
||||
case MIFARE_CLASSIC_1K:
|
||||
case MIFARE_CLASSIC_4K:
|
||||
break;
|
||||
|
@ -224,44 +222,44 @@ main(int argc, char *argv[])
|
|||
continue;
|
||||
}
|
||||
|
||||
char *tag_uid = freefare_get_tag_uid (tags[i]);
|
||||
char *tag_uid = freefare_get_tag_uid(tags[i]);
|
||||
char buffer[BUFSIZ];
|
||||
|
||||
printf ("Found %s with UID %s. ", freefare_get_tag_friendly_name (tags[i]), tag_uid);
|
||||
printf("Found %s with UID %s. ", freefare_get_tag_friendly_name(tags[i]), tag_uid);
|
||||
bool format = true;
|
||||
if (format_options.interactive) {
|
||||
printf ("Format [yN] ");
|
||||
fgets (buffer, BUFSIZ, stdin);
|
||||
printf("Format [yN] ");
|
||||
fgets(buffer, BUFSIZ, stdin);
|
||||
format = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
|
||||
} else {
|
||||
printf ("\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (format) {
|
||||
enum freefare_tag_type tt = freefare_get_tag_type (tags[i]);
|
||||
enum freefare_tag_type tt = freefare_get_tag_type(tags[i]);
|
||||
at_block = 0;
|
||||
|
||||
if (format_options.fast) {
|
||||
printf (START_FORMAT_N, (tt == MIFARE_CLASSIC_1K) ? 1 : 2);
|
||||
if (!try_format_sector (tags[i], 0x00))
|
||||
printf(START_FORMAT_N, (tt == MIFARE_CLASSIC_1K) ? 1 : 2);
|
||||
if (!try_format_sector(tags[i], 0x00))
|
||||
break;
|
||||
|
||||
if (tt == MIFARE_CLASSIC_4K)
|
||||
if (!try_format_sector (tags[i], 0x10))
|
||||
if (!try_format_sector(tags[i], 0x10))
|
||||
break;
|
||||
|
||||
printf (DONE_FORMAT);
|
||||
printf(DONE_FORMAT);
|
||||
continue;
|
||||
}
|
||||
switch (tt) {
|
||||
case MIFARE_CLASSIC_1K:
|
||||
mod_block = 4;
|
||||
if (!format_mifare_classic_1k (tags[i]))
|
||||
if (!format_mifare_classic_1k(tags[i]))
|
||||
error = 1;
|
||||
break;
|
||||
case MIFARE_CLASSIC_4K:
|
||||
mod_block = 10;
|
||||
if (!format_mifare_classic_4k (tags[i]))
|
||||
if (!format_mifare_classic_4k(tags[i]))
|
||||
error = 1;
|
||||
break;
|
||||
default:
|
||||
|
@ -270,13 +268,13 @@ main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
free (tag_uid);
|
||||
free(tag_uid);
|
||||
}
|
||||
|
||||
freefare_free_tags (tags);
|
||||
nfc_close (device);
|
||||
freefare_free_tags(tags);
|
||||
nfc_close(device);
|
||||
}
|
||||
|
||||
nfc_exit (context);
|
||||
exit (error);
|
||||
nfc_exit(context);
|
||||
exit(error);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2011, Romain Tartiere, Romuald Conty.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -56,10 +56,10 @@ struct {
|
|||
static void
|
||||
usage(char *progname)
|
||||
{
|
||||
fprintf (stderr, "usage: %s -o FILE\n", progname);
|
||||
fprintf (stderr, "\nOptions:\n");
|
||||
fprintf (stderr, " -y Do not ask for confirmation\n");
|
||||
fprintf (stderr, " -o Extract NDEF message if available in FILE\n");
|
||||
fprintf(stderr, "usage: %s -o FILE\n", progname);
|
||||
fprintf(stderr, "\nOptions:\n");
|
||||
fprintf(stderr, " -y Do not ask for confirmation\n");
|
||||
fprintf(stderr, " -o Extract NDEF message if available in FILE\n");
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -72,11 +72,11 @@ main(int argc, char *argv[])
|
|||
|
||||
int ch;
|
||||
char *ndef_output = NULL;
|
||||
while ((ch = getopt (argc, argv, "hyo:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "hyo:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
exit (EXIT_SUCCESS);
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'y':
|
||||
read_options.interactive = false;
|
||||
|
@ -86,30 +86,30 @@ main(int argc, char *argv[])
|
|||
break;
|
||||
case '?':
|
||||
if (optopt == 'o')
|
||||
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
|
||||
/* FALLTHROUGH */
|
||||
fprintf(stderr, "Option -%c requires an argument.\n", optopt);
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
usage (argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (ndef_output == NULL) {
|
||||
usage (argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
FILE* message_stream = NULL;
|
||||
FILE* ndef_stream = NULL;
|
||||
FILE *message_stream = NULL;
|
||||
FILE *ndef_stream = NULL;
|
||||
|
||||
if ((strlen (ndef_output) == 1) && (ndef_output[0] == '-')) {
|
||||
if ((strlen(ndef_output) == 1) && (ndef_output[0] == '-')) {
|
||||
message_stream = stderr;
|
||||
ndef_stream = stdout;
|
||||
} else {
|
||||
message_stream = stdout;
|
||||
ndef_stream = fopen(ndef_output, "wb");
|
||||
if (!ndef_stream) {
|
||||
fprintf (stderr, "Could not open file %s.\n", ndef_output);
|
||||
exit (EXIT_FAILURE);
|
||||
fprintf(stderr, "Could not open file %s.\n", ndef_output);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,30 +117,30 @@ main(int argc, char *argv[])
|
|||
size_t device_count;
|
||||
|
||||
nfc_context *context;
|
||||
nfc_init (&context);
|
||||
nfc_init(&context);
|
||||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count= nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
errx (EXIT_FAILURE, "No NFC device found.");
|
||||
errx(EXIT_FAILURE, "No NFC device found.");
|
||||
|
||||
for (size_t d = 0; d < device_count; d++) {
|
||||
device = nfc_open (context, devices[d]);
|
||||
if (!device) {
|
||||
warnx ("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
device = nfc_open(context, devices[d]);
|
||||
if (!device) {
|
||||
warnx("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
tags = freefare_get_tags(device);
|
||||
if (!tags) {
|
||||
nfc_close (device);
|
||||
errx (EXIT_FAILURE, "Error listing MIFARE classic tag.");
|
||||
nfc_close(device);
|
||||
errx(EXIT_FAILURE, "Error listing MIFARE classic tag.");
|
||||
}
|
||||
|
||||
for (int i = 0; (!error) && tags[i]; i++) {
|
||||
switch (freefare_get_tag_type (tags[i])) {
|
||||
switch (freefare_get_tag_type(tags[i])) {
|
||||
case MIFARE_CLASSIC_1K:
|
||||
case MIFARE_CLASSIC_4K:
|
||||
break;
|
||||
|
@ -148,100 +148,100 @@ main(int argc, char *argv[])
|
|||
continue;
|
||||
}
|
||||
|
||||
char *tag_uid = freefare_get_tag_uid (tags[i]);
|
||||
char *tag_uid = freefare_get_tag_uid(tags[i]);
|
||||
char buffer[BUFSIZ];
|
||||
|
||||
fprintf (message_stream, "Found %s with UID %s. ", freefare_get_tag_friendly_name (tags[i]), tag_uid);
|
||||
fprintf(message_stream, "Found %s with UID %s. ", freefare_get_tag_friendly_name(tags[i]), tag_uid);
|
||||
|
||||
bool read_ndef = true;
|
||||
if (read_options.interactive) {
|
||||
fprintf (message_stream, "Read NDEF [yN] ");
|
||||
fgets (buffer, BUFSIZ, stdin);
|
||||
fprintf(message_stream, "Read NDEF [yN] ");
|
||||
fgets(buffer, BUFSIZ, stdin);
|
||||
read_ndef = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
|
||||
} else {
|
||||
fprintf (message_stream, "\n");
|
||||
fprintf(message_stream, "\n");
|
||||
}
|
||||
|
||||
if (read_ndef) {
|
||||
// NFCForum card has a MAD, load it.
|
||||
if (0 == mifare_classic_connect (tags[i])) {
|
||||
if (0 == mifare_classic_connect(tags[i])) {
|
||||
} else {
|
||||
nfc_perror (device, "mifare_classic_connect");
|
||||
nfc_perror(device, "mifare_classic_connect");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((mad = mad_read (tags[i]))) {
|
||||
if ((mad = mad_read(tags[i]))) {
|
||||
// Dump the NFCForum application using MAD information
|
||||
uint8_t buffer[4096];
|
||||
ssize_t len;
|
||||
if ((len = mifare_application_read (tags[i], mad, mad_nfcforum_aid, buffer, sizeof(buffer), mifare_classic_nfcforum_public_key_a, MFC_KEY_A)) != -1) {
|
||||
if ((len = mifare_application_read(tags[i], mad, mad_nfcforum_aid, buffer, sizeof(buffer), mifare_classic_nfcforum_public_key_a, MFC_KEY_A)) != -1) {
|
||||
uint8_t tlv_type;
|
||||
uint16_t tlv_data_len;
|
||||
uint8_t * tlv_data;
|
||||
uint8_t * pbuffer = buffer;
|
||||
uint8_t *tlv_data;
|
||||
uint8_t *pbuffer = buffer;
|
||||
decode_tlv:
|
||||
tlv_data = tlv_decode (pbuffer, &tlv_type, &tlv_data_len);
|
||||
tlv_data = tlv_decode(pbuffer, &tlv_type, &tlv_data_len);
|
||||
switch (tlv_type) {
|
||||
case 0x00:
|
||||
fprintf (message_stream, "NFC Forum application contains a \"NULL TLV\", Skipping...\n"); // According to [ANNFC1K4K], we skip this Tag to read further TLV blocks.
|
||||
pbuffer += tlv_record_length(pbuffer, NULL, NULL);
|
||||
if (pbuffer >= buffer + sizeof(buffer)) {
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
goto decode_tlv;
|
||||
break;
|
||||
case 0x03:
|
||||
fprintf (message_stream, "NFC Forum application contains a \"NDEF Message TLV\".\n");
|
||||
break;
|
||||
case 0xFD:
|
||||
fprintf (message_stream, "NFC Forum application contains a \"Proprietary TLV\", Skipping...\n"); // According to [ANNFC1K4K], we can skip this TLV to read further TLV blocks.
|
||||
pbuffer += tlv_record_length(pbuffer, NULL, NULL);
|
||||
if (pbuffer >= buffer + sizeof(buffer)) {
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
goto decode_tlv;
|
||||
break;
|
||||
case 0xFE:
|
||||
fprintf (stderr, "NFC Forum application contains a \"Terminator TLV\", no available data.\n");
|
||||
case 0x00:
|
||||
fprintf(message_stream, "NFC Forum application contains a \"NULL TLV\", Skipping...\n"); // According to [ANNFC1K4K], we skip this Tag to read further TLV blocks.
|
||||
pbuffer += tlv_record_length(pbuffer, NULL, NULL);
|
||||
if (pbuffer >= buffer + sizeof(buffer)) {
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "NFC Forum application contains an invalid TLV.\n");
|
||||
}
|
||||
goto decode_tlv;
|
||||
break;
|
||||
case 0x03:
|
||||
fprintf(message_stream, "NFC Forum application contains a \"NDEF Message TLV\".\n");
|
||||
break;
|
||||
case 0xFD:
|
||||
fprintf(message_stream, "NFC Forum application contains a \"Proprietary TLV\", Skipping...\n"); // According to [ANNFC1K4K], we can skip this TLV to read further TLV blocks.
|
||||
pbuffer += tlv_record_length(pbuffer, NULL, NULL);
|
||||
if (pbuffer >= buffer + sizeof(buffer)) {
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
break;
|
||||
}
|
||||
goto decode_tlv;
|
||||
break;
|
||||
case 0xFE:
|
||||
fprintf(stderr, "NFC Forum application contains a \"Terminator TLV\", no available data.\n");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "NFC Forum application contains an invalid TLV.\n");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
break;
|
||||
}
|
||||
if (fwrite (tlv_data, 1, tlv_data_len, ndef_stream) != tlv_data_len) {
|
||||
fprintf (stderr, "Could not write to file.\n");
|
||||
if (fwrite(tlv_data, 1, tlv_data_len, ndef_stream) != tlv_data_len) {
|
||||
fprintf(stderr, "Could not write to file.\n");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
free (tlv_data);
|
||||
free(tlv_data);
|
||||
} else {
|
||||
fprintf (stderr, "No NFC Forum application.\n");
|
||||
fprintf(stderr, "No NFC Forum application.\n");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
fprintf (stderr, "No MAD detected.\n");
|
||||
fprintf(stderr, "No MAD detected.\n");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
free (mad);
|
||||
free(mad);
|
||||
}
|
||||
|
||||
error:
|
||||
free (tag_uid);
|
||||
free(tag_uid);
|
||||
}
|
||||
fclose (ndef_stream);
|
||||
freefare_free_tags (tags);
|
||||
nfc_close (device);
|
||||
fclose(ndef_stream);
|
||||
freefare_free_tags(tags);
|
||||
nfc_close(device);
|
||||
}
|
||||
|
||||
nfc_exit (context);
|
||||
exit (error);
|
||||
nfc_exit(context);
|
||||
exit(error);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere, Romuald Conty.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -33,14 +33,14 @@
|
|||
#define MIN(a,b) ((a < b) ? a: b)
|
||||
|
||||
MifareClassicKey default_keys[] = {
|
||||
{ 0xff,0xff,0xff,0xff,0xff,0xff },
|
||||
{ 0xd3,0xf7,0xd3,0xf7,0xd3,0xf7 },
|
||||
{ 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5 },
|
||||
{ 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5 },
|
||||
{ 0x4d,0x3a,0x99,0xc3,0x51,0xdd },
|
||||
{ 0x1a,0x98,0x2c,0x7e,0x45,0x9a },
|
||||
{ 0xaa,0xbb,0xcc,0xdd,0xee,0xff },
|
||||
{ 0x00,0x00,0x00,0x00,0x00,0x00 }
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
|
||||
{ 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7 },
|
||||
{ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5 },
|
||||
{ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5 },
|
||||
{ 0x4d, 0x3a, 0x99, 0xc3, 0x51, 0xdd },
|
||||
{ 0x1a, 0x98, 0x2c, 0x7e, 0x45, 0x9a },
|
||||
{ 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
|
||||
};
|
||||
|
||||
struct mifare_classic_key_and_type {
|
||||
|
@ -69,54 +69,54 @@ uint8_t *ndef_msg;
|
|||
size_t ndef_msg_len;
|
||||
|
||||
static int
|
||||
search_sector_key (FreefareTag tag, MifareClassicSectorNumber sector, MifareClassicKey *key, MifareClassicKeyType *key_type)
|
||||
search_sector_key(FreefareTag tag, MifareClassicSectorNumber sector, MifareClassicKey *key, MifareClassicKeyType *key_type)
|
||||
{
|
||||
MifareClassicBlockNumber block = mifare_classic_sector_last_block (sector);
|
||||
MifareClassicBlockNumber block = mifare_classic_sector_last_block(sector);
|
||||
|
||||
/*
|
||||
* FIXME: We should not assume that if we have full access to trailer block
|
||||
* we also have a full access to data blocks.
|
||||
*/
|
||||
mifare_classic_disconnect (tag);
|
||||
for (size_t i = 0; i < (sizeof (default_keys) / sizeof (MifareClassicKey)); i++) {
|
||||
if ((0 == mifare_classic_connect (tag)) && (0 == mifare_classic_authenticate (tag, block, default_keys[i], MFC_KEY_A))) {
|
||||
if ((1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_KEYA, MFC_KEY_A)) &&
|
||||
(1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_ACCESS_BITS, MFC_KEY_A)) &&
|
||||
(1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_KEYB, MFC_KEY_A))) {
|
||||
memcpy (key, &default_keys[i], sizeof (MifareClassicKey));
|
||||
mifare_classic_disconnect(tag);
|
||||
for (size_t i = 0; i < (sizeof(default_keys) / sizeof(MifareClassicKey)); i++) {
|
||||
if ((0 == mifare_classic_connect(tag)) && (0 == mifare_classic_authenticate(tag, block, default_keys[i], MFC_KEY_A))) {
|
||||
if ((1 == mifare_classic_get_trailer_block_permission(tag, block, MCAB_WRITE_KEYA, MFC_KEY_A)) &&
|
||||
(1 == mifare_classic_get_trailer_block_permission(tag, block, MCAB_WRITE_ACCESS_BITS, MFC_KEY_A)) &&
|
||||
(1 == mifare_classic_get_trailer_block_permission(tag, block, MCAB_WRITE_KEYB, MFC_KEY_A))) {
|
||||
memcpy(key, &default_keys[i], sizeof(MifareClassicKey));
|
||||
*key_type = MFC_KEY_A;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
mifare_classic_disconnect (tag);
|
||||
mifare_classic_disconnect(tag);
|
||||
|
||||
if ((0 == mifare_classic_connect (tag)) && (0 == mifare_classic_authenticate (tag, block, default_keys[i], MFC_KEY_B))) {
|
||||
if ((1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_KEYA, MFC_KEY_B)) &&
|
||||
(1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_ACCESS_BITS, MFC_KEY_B)) &&
|
||||
(1 == mifare_classic_get_trailer_block_permission (tag, block, MCAB_WRITE_KEYB, MFC_KEY_B))) {
|
||||
memcpy (key, &default_keys[i], sizeof (MifareClassicKey));
|
||||
if ((0 == mifare_classic_connect(tag)) && (0 == mifare_classic_authenticate(tag, block, default_keys[i], MFC_KEY_B))) {
|
||||
if ((1 == mifare_classic_get_trailer_block_permission(tag, block, MCAB_WRITE_KEYA, MFC_KEY_B)) &&
|
||||
(1 == mifare_classic_get_trailer_block_permission(tag, block, MCAB_WRITE_ACCESS_BITS, MFC_KEY_B)) &&
|
||||
(1 == mifare_classic_get_trailer_block_permission(tag, block, MCAB_WRITE_KEYB, MFC_KEY_B))) {
|
||||
memcpy(key, &default_keys[i], sizeof(MifareClassicKey));
|
||||
*key_type = MFC_KEY_B;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
mifare_classic_disconnect (tag);
|
||||
mifare_classic_disconnect(tag);
|
||||
}
|
||||
|
||||
warnx ("No known authentication key for sector 0x%02x\n", sector);
|
||||
warnx("No known authentication key for sector 0x%02x\n", sector);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fix_mad_trailer_block (nfc_device *device, FreefareTag tag, MifareClassicSectorNumber sector, MifareClassicKey key, MifareClassicKeyType key_type)
|
||||
fix_mad_trailer_block(nfc_device *device, FreefareTag tag, MifareClassicSectorNumber sector, MifareClassicKey key, MifareClassicKeyType key_type)
|
||||
{
|
||||
MifareClassicBlock block;
|
||||
mifare_classic_trailer_block (&block, mad_public_key_a, 0x0, 0x1, 0x1, 0x6, 0x00, default_keyb);
|
||||
if (mifare_classic_authenticate (tag, mifare_classic_sector_last_block (sector), key, key_type) < 0) {
|
||||
nfc_perror (device, "fix_mad_trailer_block mifare_classic_authenticate");
|
||||
mifare_classic_trailer_block(&block, mad_public_key_a, 0x0, 0x1, 0x1, 0x6, 0x00, default_keyb);
|
||||
if (mifare_classic_authenticate(tag, mifare_classic_sector_last_block(sector), key, key_type) < 0) {
|
||||
nfc_perror(device, "fix_mad_trailer_block mifare_classic_authenticate");
|
||||
return -1;
|
||||
}
|
||||
if (mifare_classic_write (tag, mifare_classic_sector_last_block (sector), block) < 0) {
|
||||
nfc_perror (device, "mifare_classic_write");
|
||||
if (mifare_classic_write(tag, mifare_classic_sector_last_block(sector), block) < 0) {
|
||||
nfc_perror(device, "mifare_classic_write");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -125,10 +125,10 @@ fix_mad_trailer_block (nfc_device *device, FreefareTag tag, MifareClassicSectorN
|
|||
static void
|
||||
usage(char *progname)
|
||||
{
|
||||
fprintf (stderr, "usage: %s -i FILE\n", progname);
|
||||
fprintf (stderr, "\nOptions:\n");
|
||||
fprintf (stderr, " -y Do not ask for confirmation\n");
|
||||
fprintf (stderr, " -i Use FILE as NDEF message to write on card (\"-\" = stdin)\n");
|
||||
fprintf(stderr, "usage: %s -i FILE\n", progname);
|
||||
fprintf(stderr, "\nOptions:\n");
|
||||
fprintf(stderr, " -y Do not ask for confirmation\n");
|
||||
fprintf(stderr, " -i Use FILE as NDEF message to write on card (\"-\" = stdin)\n");
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -142,11 +142,11 @@ main(int argc, char *argv[])
|
|||
|
||||
int ch;
|
||||
char *ndef_input = NULL;
|
||||
while ((ch = getopt (argc, argv, "hyi:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "hyi:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
exit (EXIT_SUCCESS);
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'y':
|
||||
write_options.interactive = false;
|
||||
|
@ -156,81 +156,81 @@ main(int argc, char *argv[])
|
|||
break;
|
||||
case '?':
|
||||
if (optopt == 'i')
|
||||
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
|
||||
/* FALLTHROUGH */
|
||||
fprintf(stderr, "Option -%c requires an argument.\n", optopt);
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
usage (argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (ndef_input == NULL) {
|
||||
ndef_msg = (uint8_t*)ndef_default_msg;
|
||||
ndef_msg_len = sizeof(ndef_default_msg);
|
||||
ndef_msg = (uint8_t *)ndef_default_msg;
|
||||
ndef_msg_len = sizeof(ndef_default_msg);
|
||||
} else {
|
||||
FILE* ndef_stream = NULL;
|
||||
if ((strlen (ndef_input) == 1) && (ndef_input[0] == '-')) {
|
||||
// FIXME stdin as input have to be readed and buffered in ndef_msg
|
||||
FILE *ndef_stream = NULL;
|
||||
if ((strlen(ndef_input) == 1) && (ndef_input[0] == '-')) {
|
||||
// FIXME stdin as input have to be readed and buffered in ndef_msg
|
||||
ndef_stream = stdin;
|
||||
fprintf (stderr, "stdin as NDEF is not implemented");
|
||||
exit (EXIT_FAILURE);
|
||||
fprintf(stderr, "stdin as NDEF is not implemented");
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
ndef_stream = fopen(ndef_input, "rb");
|
||||
if (!ndef_stream) {
|
||||
fprintf (stderr, "Could not open file %s.\n", ndef_input);
|
||||
exit (EXIT_FAILURE);
|
||||
fprintf(stderr, "Could not open file %s.\n", ndef_input);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
fseek(ndef_stream, 0L, SEEK_END);
|
||||
ndef_msg_len = ftell(ndef_stream);
|
||||
fseek(ndef_stream, 0L, SEEK_SET);
|
||||
fseek(ndef_stream, 0L, SEEK_SET);
|
||||
|
||||
if (!(ndef_msg = malloc (ndef_msg_len))) {
|
||||
err (EXIT_FAILURE, "malloc");
|
||||
if (!(ndef_msg = malloc(ndef_msg_len))) {
|
||||
err(EXIT_FAILURE, "malloc");
|
||||
}
|
||||
if (fread (ndef_msg, 1, ndef_msg_len, ndef_stream) != ndef_msg_len) {
|
||||
fprintf (stderr, "Could not read NDEF from file: %s\n", ndef_input);
|
||||
fclose (ndef_stream);
|
||||
free (ndef_msg);
|
||||
exit (EXIT_FAILURE);
|
||||
if (fread(ndef_msg, 1, ndef_msg_len, ndef_stream) != ndef_msg_len) {
|
||||
fprintf(stderr, "Could not read NDEF from file: %s\n", ndef_input);
|
||||
fclose(ndef_stream);
|
||||
free(ndef_msg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
fclose (ndef_stream);
|
||||
fclose(ndef_stream);
|
||||
}
|
||||
}
|
||||
printf ("NDEF file is %zu bytes long.\n", ndef_msg_len);
|
||||
printf("NDEF file is %zu bytes long.\n", ndef_msg_len);
|
||||
|
||||
struct mifare_classic_key_and_type *card_write_keys;
|
||||
if (!(card_write_keys = malloc (40 * sizeof (*card_write_keys)))) {
|
||||
err (EXIT_FAILURE, "malloc");
|
||||
if (!(card_write_keys = malloc(40 * sizeof(*card_write_keys)))) {
|
||||
err(EXIT_FAILURE, "malloc");
|
||||
}
|
||||
|
||||
nfc_connstring devices[8];
|
||||
size_t device_count;
|
||||
|
||||
nfc_context *context;
|
||||
nfc_init (&context);
|
||||
nfc_init(&context);
|
||||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
errx (EXIT_FAILURE, "No NFC device found.");
|
||||
errx(EXIT_FAILURE, "No NFC device found.");
|
||||
|
||||
for (size_t d = 0; d < device_count; d++) {
|
||||
device = nfc_open (context, devices[d]);
|
||||
if (!device) {
|
||||
warnx ("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
device = nfc_open(context, devices[d]);
|
||||
if (!device) {
|
||||
warnx("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
tags = freefare_get_tags(device);
|
||||
if (!tags) {
|
||||
nfc_close (device);
|
||||
errx (EXIT_FAILURE, "Error listing MIFARE classic tag.");
|
||||
nfc_close(device);
|
||||
errx(EXIT_FAILURE, "Error listing MIFARE classic tag.");
|
||||
}
|
||||
|
||||
for (int i = 0; (!error) && tags[i]; i++) {
|
||||
switch (freefare_get_tag_type (tags[i])) {
|
||||
switch (freefare_get_tag_type(tags[i])) {
|
||||
case MIFARE_CLASSIC_1K:
|
||||
case MIFARE_CLASSIC_4K:
|
||||
break;
|
||||
|
@ -238,35 +238,35 @@ main(int argc, char *argv[])
|
|||
continue;
|
||||
}
|
||||
|
||||
char *tag_uid = freefare_get_tag_uid (tags[i]);
|
||||
char *tag_uid = freefare_get_tag_uid(tags[i]);
|
||||
char buffer[BUFSIZ];
|
||||
|
||||
printf ("Found %s with UID %s. ", freefare_get_tag_friendly_name (tags[i]), tag_uid);
|
||||
printf("Found %s with UID %s. ", freefare_get_tag_friendly_name(tags[i]), tag_uid);
|
||||
|
||||
bool write_ndef = true;
|
||||
if (write_options.interactive) {
|
||||
printf ("Write NDEF [yN] ");
|
||||
fgets (buffer, BUFSIZ, stdin);
|
||||
printf("Write NDEF [yN] ");
|
||||
fgets(buffer, BUFSIZ, stdin);
|
||||
write_ndef = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
|
||||
} else {
|
||||
printf ("\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
for (int n = 0; n < 40; n++) {
|
||||
memcpy(card_write_keys[n].key, transport_key, sizeof (transport_key));
|
||||
memcpy(card_write_keys[n].key, transport_key, sizeof(transport_key));
|
||||
card_write_keys[n].type = MFC_KEY_A;
|
||||
}
|
||||
|
||||
if (write_ndef) {
|
||||
switch (freefare_get_tag_type (tags[i])) {
|
||||
switch (freefare_get_tag_type(tags[i])) {
|
||||
case MIFARE_CLASSIC_4K:
|
||||
if (!search_sector_key (tags[i], 0x10, &(card_write_keys[0x10].key), &(card_write_keys[0x10].type))) {
|
||||
if (!search_sector_key(tags[i], 0x10, &(card_write_keys[0x10].key), &(card_write_keys[0x10].type))) {
|
||||
error = 1;
|
||||
goto error;
|
||||
}
|
||||
/* fallthrough */
|
||||
/* fallthrough */
|
||||
case MIFARE_CLASSIC_1K:
|
||||
if (!search_sector_key (tags[i], 0x00, &(card_write_keys[0x00].key), &(card_write_keys[0x00].type))) {
|
||||
if (!search_sector_key(tags[i], 0x00, &(card_write_keys[0x00].key), &(card_write_keys[0x00].type))) {
|
||||
error = 1;
|
||||
goto error;
|
||||
}
|
||||
|
@ -278,24 +278,24 @@ main(int argc, char *argv[])
|
|||
|
||||
if (!error) {
|
||||
/* Ensure the auth key is always a B one. If not, change it! */
|
||||
switch (freefare_get_tag_type (tags[i])) {
|
||||
switch (freefare_get_tag_type(tags[i])) {
|
||||
case MIFARE_CLASSIC_4K:
|
||||
if (card_write_keys[0x10].type != MFC_KEY_B) {
|
||||
if( 0 != fix_mad_trailer_block (device, tags[i], 0x10, card_write_keys[0x10].key, card_write_keys[0x10].type)) {
|
||||
if (0 != fix_mad_trailer_block(device, tags[i], 0x10, card_write_keys[0x10].key, card_write_keys[0x10].type)) {
|
||||
error = 1;
|
||||
goto error;
|
||||
}
|
||||
memcpy (&(card_write_keys[0x10].key), &default_keyb, sizeof (MifareClassicKey));
|
||||
memcpy(&(card_write_keys[0x10].key), &default_keyb, sizeof(MifareClassicKey));
|
||||
card_write_keys[0x10].type = MFC_KEY_B;
|
||||
}
|
||||
/* fallthrough */
|
||||
/* fallthrough */
|
||||
case MIFARE_CLASSIC_1K:
|
||||
if (card_write_keys[0x00].type != MFC_KEY_B) {
|
||||
if( 0 != fix_mad_trailer_block (device, tags[i], 0x00, card_write_keys[0x00].key, card_write_keys[0x00].type)) {
|
||||
if (0 != fix_mad_trailer_block(device, tags[i], 0x00, card_write_keys[0x00].key, card_write_keys[0x00].type)) {
|
||||
error = 1;
|
||||
goto error;
|
||||
}
|
||||
memcpy (&(card_write_keys[0x00].key), &default_keyb, sizeof (MifareClassicKey));
|
||||
memcpy(&(card_write_keys[0x00].key), &default_keyb, sizeof(MifareClassicKey));
|
||||
card_write_keys[0x00].type = MFC_KEY_B;
|
||||
}
|
||||
break;
|
||||
|
@ -306,7 +306,7 @@ main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
size_t encoded_size;
|
||||
uint8_t *tlv_data = tlv_encode (3, ndef_msg, ndef_msg_len, &encoded_size);
|
||||
uint8_t *tlv_data = tlv_encode(3, ndef_msg, ndef_msg_len, &encoded_size);
|
||||
|
||||
/*
|
||||
* At his point, we should have collected all information needed to
|
||||
|
@ -314,38 +314,38 @@ main(int argc, char *argv[])
|
|||
*/
|
||||
|
||||
// If the card already has a MAD, load it.
|
||||
if ((mad = mad_read (tags[i]))) {
|
||||
if ((mad = mad_read(tags[i]))) {
|
||||
// If our application already exists, erase it.
|
||||
MifareClassicSectorNumber *sectors, *p;
|
||||
sectors = p = mifare_application_find (mad, mad_nfcforum_aid);
|
||||
sectors = p = mifare_application_find(mad, mad_nfcforum_aid);
|
||||
if (sectors) {
|
||||
while (*p) {
|
||||
if (mifare_classic_authenticate (tags[i], mifare_classic_sector_last_block(*p), default_keyb, MFC_KEY_B) < 0) {
|
||||
nfc_perror (device, "mifare_classic_authenticate");
|
||||
if (mifare_classic_authenticate(tags[i], mifare_classic_sector_last_block(*p), default_keyb, MFC_KEY_B) < 0) {
|
||||
nfc_perror(device, "mifare_classic_authenticate");
|
||||
error = 1;
|
||||
goto error;
|
||||
}
|
||||
if (mifare_classic_format_sector (tags[i], *p) < 0) {
|
||||
nfc_perror (device, "mifare_classic_format_sector");
|
||||
if (mifare_classic_format_sector(tags[i], *p) < 0) {
|
||||
nfc_perror(device, "mifare_classic_format_sector");
|
||||
error = 1;
|
||||
goto error;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
free (sectors);
|
||||
mifare_application_free (mad, mad_nfcforum_aid);
|
||||
free(sectors);
|
||||
mifare_application_free(mad, mad_nfcforum_aid);
|
||||
} else {
|
||||
|
||||
// Create a MAD and mark unaccessible sectors in the card
|
||||
if (!(mad = mad_new ((freefare_get_tag_type (tags[i]) == MIFARE_CLASSIC_4K) ? 2 : 1))) {
|
||||
perror ("mad_new");
|
||||
if (!(mad = mad_new((freefare_get_tag_type(tags[i]) == MIFARE_CLASSIC_4K) ? 2 : 1))) {
|
||||
perror("mad_new");
|
||||
error = 1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
MifareClassicSectorNumber max_s = 0;
|
||||
switch (freefare_get_tag_type (tags[i])) {
|
||||
switch (freefare_get_tag_type(tags[i])) {
|
||||
case MIFARE_CLASSIC_1K:
|
||||
max_s = 15;
|
||||
break;
|
||||
|
@ -360,13 +360,13 @@ main(int argc, char *argv[])
|
|||
// Mark unusable sectors as so
|
||||
for (size_t s = max_s; s; s--) {
|
||||
if (s == 0x10) continue;
|
||||
if (!search_sector_key (tags[i], s, &(card_write_keys[s].key), &(card_write_keys[s].type))) {
|
||||
mad_set_aid (mad, s, mad_defect_aid);
|
||||
} else if ((memcmp (card_write_keys[s].key, transport_key, sizeof (transport_key)) != 0) &&
|
||||
if (!search_sector_key(tags[i], s, &(card_write_keys[s].key), &(card_write_keys[s].type))) {
|
||||
mad_set_aid(mad, s, mad_defect_aid);
|
||||
} else if ((memcmp(card_write_keys[s].key, transport_key, sizeof(transport_key)) != 0) &&
|
||||
(card_write_keys[s].type != MFC_KEY_A)) {
|
||||
// Revert to transport configuration
|
||||
if (mifare_classic_format_sector (tags[i], s) < 0) {
|
||||
nfc_perror (device, "mifare_classic_format_sector");
|
||||
if (mifare_classic_format_sector(tags[i], s) < 0) {
|
||||
nfc_perror(device, "mifare_classic_format_sector");
|
||||
error = 1;
|
||||
goto error;
|
||||
}
|
||||
|
@ -374,61 +374,61 @@ main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
MifareClassicSectorNumber *sectors = mifare_application_alloc (mad, mad_nfcforum_aid, encoded_size);
|
||||
MifareClassicSectorNumber *sectors = mifare_application_alloc(mad, mad_nfcforum_aid, encoded_size);
|
||||
if (!sectors) {
|
||||
nfc_perror (device, "mifare_application_alloc");
|
||||
nfc_perror(device, "mifare_application_alloc");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (mad_write (tags[i], mad, card_write_keys[0x00].key, card_write_keys[0x10].key) < 0) {
|
||||
nfc_perror (device, "mad_write");
|
||||
if (mad_write(tags[i], mad, card_write_keys[0x00].key, card_write_keys[0x10].key) < 0) {
|
||||
nfc_perror(device, "mad_write");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
int s = 0;
|
||||
while (sectors[s]) {
|
||||
MifareClassicBlockNumber block = mifare_classic_sector_last_block (sectors[s]);
|
||||
MifareClassicBlockNumber block = mifare_classic_sector_last_block(sectors[s]);
|
||||
MifareClassicBlock block_data;
|
||||
mifare_classic_trailer_block (&block_data, mifare_classic_nfcforum_public_key_a, 0x0, 0x0, 0x0, 0x6, 0x40, default_keyb);
|
||||
if (mifare_classic_authenticate (tags[i], block, card_write_keys[sectors[s]].key, card_write_keys[sectors[s]].type) < 0) {
|
||||
nfc_perror (device, "mifare_classic_authenticate");
|
||||
mifare_classic_trailer_block(&block_data, mifare_classic_nfcforum_public_key_a, 0x0, 0x0, 0x0, 0x6, 0x40, default_keyb);
|
||||
if (mifare_classic_authenticate(tags[i], block, card_write_keys[sectors[s]].key, card_write_keys[sectors[s]].type) < 0) {
|
||||
nfc_perror(device, "mifare_classic_authenticate");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
if (mifare_classic_write (tags[i], block, block_data) < 0) {
|
||||
nfc_perror (device, "mifare_classic_write");
|
||||
if (mifare_classic_write(tags[i], block, block_data) < 0) {
|
||||
nfc_perror(device, "mifare_classic_write");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
|
||||
if ((ssize_t) encoded_size != mifare_application_write (tags[i], mad, mad_nfcforum_aid, tlv_data, encoded_size, default_keyb, MCAB_WRITE_KEYB)) {
|
||||
nfc_perror (device, "mifare_application_write");
|
||||
if ((ssize_t) encoded_size != mifare_application_write(tags[i], mad, mad_nfcforum_aid, tlv_data, encoded_size, default_keyb, MCAB_WRITE_KEYB)) {
|
||||
nfc_perror(device, "mifare_application_write");
|
||||
error = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
free (sectors);
|
||||
free(sectors);
|
||||
|
||||
free (tlv_data);
|
||||
free(tlv_data);
|
||||
|
||||
free (mad);
|
||||
free(mad);
|
||||
}
|
||||
|
||||
error:
|
||||
free (tag_uid);
|
||||
free(tag_uid);
|
||||
}
|
||||
|
||||
if (ndef_msg != ndef_default_msg)
|
||||
free (ndef_msg);
|
||||
freefare_free_tags (tags);
|
||||
nfc_close (device);
|
||||
free(ndef_msg);
|
||||
freefare_free_tags(tags);
|
||||
nfc_close(device);
|
||||
}
|
||||
|
||||
free (card_write_keys);
|
||||
nfc_exit (context);
|
||||
exit (error);
|
||||
free(card_write_keys);
|
||||
nfc_exit(context);
|
||||
exit(error);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -34,105 +34,105 @@ main(int argc, char *argv[])
|
|||
FreefareTag *tags = NULL;
|
||||
|
||||
if (argc > 1)
|
||||
errx (EXIT_FAILURE, "usage: %s", argv[0]);
|
||||
errx(EXIT_FAILURE, "usage: %s", argv[0]);
|
||||
|
||||
nfc_connstring devices[8];
|
||||
size_t device_count;
|
||||
|
||||
nfc_context *context;
|
||||
nfc_init (&context);
|
||||
nfc_init(&context);
|
||||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
errx (EXIT_FAILURE, "No NFC device found.");
|
||||
errx(EXIT_FAILURE, "No NFC device found.");
|
||||
|
||||
for (size_t d = 0; d < device_count; d++) {
|
||||
device = nfc_open (context, devices[d]);
|
||||
if (!device) {
|
||||
warnx ("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
device = nfc_open(context, devices[d]);
|
||||
if (!device) {
|
||||
warnx("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
tags = freefare_get_tags(device);
|
||||
if (!tags) {
|
||||
nfc_close (device);
|
||||
errx (EXIT_FAILURE, "Error listing tags.");
|
||||
nfc_close(device);
|
||||
errx(EXIT_FAILURE, "Error listing tags.");
|
||||
}
|
||||
|
||||
for (int i = 0; (!error) && tags[i]; i++) {
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type (tags[i]))
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type(tags[i]))
|
||||
continue;
|
||||
|
||||
int res;
|
||||
char *tag_uid = freefare_get_tag_uid (tags[i]);
|
||||
char *tag_uid = freefare_get_tag_uid(tags[i]);
|
||||
|
||||
res = mifare_desfire_connect (tags[i]);
|
||||
res = mifare_desfire_connect(tags[i]);
|
||||
if (res < 0) {
|
||||
warnx ("Can't connect to Mifare DESFire target.");
|
||||
warnx("Can't connect to Mifare DESFire target.");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
MifareDESFireKey key = mifare_desfire_des_key_new_with_version (key_data_null);
|
||||
res = mifare_desfire_authenticate (tags[i], 0, key);
|
||||
MifareDESFireKey key = mifare_desfire_des_key_new_with_version(key_data_null);
|
||||
res = mifare_desfire_authenticate(tags[i], 0, key);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Authentication on master application failed");
|
||||
errx(EXIT_FAILURE, "Authentication on master application failed");
|
||||
|
||||
MadAid mad_aid = { 0x12, 0x34 };
|
||||
MifareDESFireAID aid = mifare_desfire_aid_new_with_mad_aid (mad_aid, 0x5);
|
||||
res = mifare_desfire_create_application (tags[i], aid, 0xFF, 0x1);
|
||||
MifareDESFireAID aid = mifare_desfire_aid_new_with_mad_aid(mad_aid, 0x5);
|
||||
res = mifare_desfire_create_application(tags[i], aid, 0xFF, 0x1);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Application creation failed");
|
||||
errx(EXIT_FAILURE, "Application creation failed");
|
||||
|
||||
res = mifare_desfire_select_application (tags[i], aid);
|
||||
res = mifare_desfire_select_application(tags[i], aid);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Application selection failed");
|
||||
errx(EXIT_FAILURE, "Application selection failed");
|
||||
|
||||
res = mifare_desfire_authenticate (tags[i], 0, key);
|
||||
res = mifare_desfire_authenticate(tags[i], 0, key);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Authentication on application failed");
|
||||
errx(EXIT_FAILURE, "Authentication on application failed");
|
||||
|
||||
res = mifare_desfire_create_std_data_file (tags[i], 1, MDCM_ENCIPHERED, 0x0000, 20);
|
||||
res = mifare_desfire_create_std_data_file(tags[i], 1, MDCM_ENCIPHERED, 0x0000, 20);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "File creation failed");
|
||||
errx(EXIT_FAILURE, "File creation failed");
|
||||
|
||||
const char *s= "Hello World";
|
||||
res = mifare_desfire_write_data (tags[i], 1, 0, strlen (s), s);
|
||||
const char *s = "Hello World";
|
||||
res = mifare_desfire_write_data(tags[i], 1, 0, strlen(s), s);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "File write failed");
|
||||
errx(EXIT_FAILURE, "File write failed");
|
||||
|
||||
char buffer[20];
|
||||
res = mifare_desfire_read_data (tags[i], 1, 0, 0, buffer);
|
||||
res = mifare_desfire_read_data(tags[i], 1, 0, 0, buffer);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "File read failed");
|
||||
errx(EXIT_FAILURE, "File read failed");
|
||||
|
||||
res = mifare_desfire_select_application (tags[i], NULL);
|
||||
res = mifare_desfire_select_application(tags[i], NULL);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Master application selection failed");
|
||||
errx(EXIT_FAILURE, "Master application selection failed");
|
||||
|
||||
res = mifare_desfire_authenticate (tags[i], 0, key);
|
||||
res = mifare_desfire_authenticate(tags[i], 0, key);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Authentication on master application failed");
|
||||
errx(EXIT_FAILURE, "Authentication on master application failed");
|
||||
|
||||
res = mifare_desfire_format_picc (tags[i]);
|
||||
res = mifare_desfire_format_picc(tags[i]);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "PICC format failed");
|
||||
errx(EXIT_FAILURE, "PICC format failed");
|
||||
|
||||
mifare_desfire_key_free (key);
|
||||
free (tag_uid);
|
||||
free (aid);
|
||||
mifare_desfire_key_free(key);
|
||||
free(tag_uid);
|
||||
free(aid);
|
||||
|
||||
mifare_desfire_disconnect (tags[i]);
|
||||
mifare_desfire_disconnect(tags[i]);
|
||||
}
|
||||
|
||||
freefare_free_tags (tags);
|
||||
nfc_close (device);
|
||||
freefare_free_tags(tags);
|
||||
nfc_close(device);
|
||||
}
|
||||
nfc_exit (context);
|
||||
exit (error);
|
||||
nfc_exit(context);
|
||||
exit(error);
|
||||
} /* main() */
|
||||
|
||||
|
|
|
@ -50,11 +50,11 @@ struct {
|
|||
static void
|
||||
usage(char *progname)
|
||||
{
|
||||
fprintf (stderr, "This application turns Mifare DESFire targets into NFC Forum Type 4 Tags.\n");
|
||||
fprintf (stderr, "usage: %s [-y] [-K 11223344AABBCCDD]\n", progname);
|
||||
fprintf (stderr, "\nOptions:\n");
|
||||
fprintf (stderr, " -y Do not ask for confirmation\n");
|
||||
fprintf (stderr, " -K Provide another PICC key than the default one\n");
|
||||
fprintf(stderr, "This application turns Mifare DESFire targets into NFC Forum Type 4 Tags.\n");
|
||||
fprintf(stderr, "usage: %s [-y] [-K 11223344AABBCCDD]\n", progname);
|
||||
fprintf(stderr, "\nOptions:\n");
|
||||
fprintf(stderr, " -y Do not ask for confirmation\n");
|
||||
fprintf(stderr, " -K Provide another PICC key than the default one\n");
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -65,31 +65,31 @@ main(int argc, char *argv[])
|
|||
nfc_device *device = NULL;
|
||||
FreefareTag *tags = NULL;
|
||||
|
||||
while ((ch = getopt (argc, argv, "hyK:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
exit (EXIT_SUCCESS);
|
||||
break;
|
||||
case 'y':
|
||||
create_options.interactive = false;
|
||||
break;
|
||||
case 'K':
|
||||
if (strlen(optarg) != 16) {
|
||||
usage(argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
uint64_t n = strtoull(optarg, NULL, 16);
|
||||
int i;
|
||||
for (i=7; i>=0; i--) {
|
||||
key_data_picc[i] = (uint8_t) n;
|
||||
n >>= 8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
while ((ch = getopt(argc, argv, "hyK:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'y':
|
||||
create_options.interactive = false;
|
||||
break;
|
||||
case 'K':
|
||||
if (strlen(optarg) != 16) {
|
||||
usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
uint64_t n = strtoull(optarg, NULL, 16);
|
||||
int i;
|
||||
for (i = 7; i >= 0; i--) {
|
||||
key_data_picc[i] = (uint8_t) n;
|
||||
n >>= 8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
// Remaining args, if any, are in argv[optind .. (argc-1)]
|
||||
|
||||
|
@ -97,54 +97,54 @@ main(int argc, char *argv[])
|
|||
size_t device_count;
|
||||
|
||||
nfc_context *context;
|
||||
nfc_init (&context);
|
||||
nfc_init(&context);
|
||||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
errx (EXIT_FAILURE, "No NFC device found.");
|
||||
errx(EXIT_FAILURE, "No NFC device found.");
|
||||
|
||||
for (size_t d = 0; d < device_count; d++) {
|
||||
device = nfc_open (context, devices[d]);
|
||||
device = nfc_open(context, devices[d]);
|
||||
|
||||
if (!device) {
|
||||
warnx ("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
if (!device) {
|
||||
warnx("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
tags = freefare_get_tags(device);
|
||||
if (!tags) {
|
||||
nfc_close (device);
|
||||
errx (EXIT_FAILURE, "Error listing tags.");
|
||||
nfc_close(device);
|
||||
errx(EXIT_FAILURE, "Error listing tags.");
|
||||
}
|
||||
|
||||
for (int i = 0; (!error) && tags[i]; i++) {
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type (tags[i]))
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type(tags[i]))
|
||||
continue;
|
||||
|
||||
char *tag_uid = freefare_get_tag_uid (tags[i]);
|
||||
char *tag_uid = freefare_get_tag_uid(tags[i]);
|
||||
char buffer[BUFSIZ];
|
||||
int res;
|
||||
|
||||
res = mifare_desfire_connect (tags[i]);
|
||||
res = mifare_desfire_connect(tags[i]);
|
||||
if (res < 0) {
|
||||
warnx ("Can't connect to Mifare DESFire target.");
|
||||
warnx("Can't connect to Mifare DESFire target.");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
// We've to track DESFire version as NDEF mapping is different
|
||||
struct mifare_desfire_version_info info;
|
||||
res = mifare_desfire_get_version (tags[i], &info);
|
||||
res = mifare_desfire_get_version(tags[i], &info);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_get_version");
|
||||
freefare_perror(tags[i], "mifare_desfire_get_version");
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
printf ("Found %s with UID %s and software v%d.%d\n", freefare_get_tag_friendly_name (tags[i]), tag_uid, info.software.version_major, info.software.version_minor);
|
||||
printf("Found %s with UID %s and software v%d.%d\n", freefare_get_tag_friendly_name(tags[i]), tag_uid, info.software.version_major, info.software.version_minor);
|
||||
bool create_ndef = true;
|
||||
int ndef_mapping;
|
||||
switch (info.software.version_major) {
|
||||
|
@ -159,11 +159,11 @@ main(int argc, char *argv[])
|
|||
ndef_mapping = 2;
|
||||
}
|
||||
if (create_options.interactive) {
|
||||
printf ("Create NDEF app v%d [yN] ", ndef_mapping);
|
||||
fgets (buffer, BUFSIZ, stdin);
|
||||
printf("Create NDEF app v%d [yN] ", ndef_mapping);
|
||||
fgets(buffer, BUFSIZ, stdin);
|
||||
create_ndef = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
|
||||
} else {
|
||||
printf ("\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (create_ndef) {
|
||||
|
@ -172,24 +172,24 @@ main(int argc, char *argv[])
|
|||
// Send Mifare DESFire Select Application with AID equal to 000000h to select the PICC level
|
||||
res = mifare_desfire_select_application(tags[i], NULL);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Application selection failed");
|
||||
errx(EXIT_FAILURE, "Application selection failed");
|
||||
|
||||
MifareDESFireKey key_picc;
|
||||
MifareDESFireKey key_app;
|
||||
key_picc = mifare_desfire_des_key_new_with_version (key_data_picc);
|
||||
key_app = mifare_desfire_des_key_new_with_version (key_data_app);
|
||||
key_picc = mifare_desfire_des_key_new_with_version(key_data_picc);
|
||||
key_app = mifare_desfire_des_key_new_with_version(key_data_app);
|
||||
|
||||
// Authentication with PICC master key MAY be needed to issue ChangeKeySettings command
|
||||
res = mifare_desfire_authenticate (tags[i], 0, key_picc);
|
||||
res = mifare_desfire_authenticate(tags[i], 0, key_picc);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Authentication with PICC master key failed");
|
||||
errx(EXIT_FAILURE, "Authentication with PICC master key failed");
|
||||
|
||||
MifareDESFireAID aid;
|
||||
if (ndef_mapping == 1) {
|
||||
uint8_t key_settings;
|
||||
uint8_t max_keys;
|
||||
mifare_desfire_get_key_settings(tags[i], &key_settings,&max_keys);
|
||||
if ((key_settings & 0x08) == 0x08){
|
||||
mifare_desfire_get_key_settings(tags[i], &key_settings, &max_keys);
|
||||
if ((key_settings & 0x08) == 0x08) {
|
||||
|
||||
// Send Mifare DESFire ChangeKeySetting to change the PICC master key settings into :
|
||||
// bit7-bit4 equal to 0000b
|
||||
|
@ -197,33 +197,33 @@ main(int argc, char *argv[])
|
|||
// bit2 equal to 0b, CreateApplication and DeleteApplication commands are allowed with PICC master key authentication
|
||||
// bit1 equal to 0b, GetApplicationIDs, and GetKeySettings are allowed with PICC master key authentication
|
||||
// bit0 equal to Xb, PICC masterkey MAY be frozen or changeable
|
||||
res = mifare_desfire_change_key_settings (tags[i],0x09);
|
||||
res = mifare_desfire_change_key_settings(tags[i], 0x09);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "ChangeKeySettings failed");
|
||||
errx(EXIT_FAILURE, "ChangeKeySettings failed");
|
||||
}
|
||||
// Mifare DESFire Create Application with AID equal to EEEE10h, key settings equal to 0x09, NumOfKeys equal to 01h
|
||||
aid = mifare_desfire_aid_new(0xEEEE10);
|
||||
res = mifare_desfire_create_application (tags[i], aid, 0x09, 1);
|
||||
res = mifare_desfire_create_application(tags[i], aid, 0x09, 1);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Application creation failed. Try mifare-desfire-format before running %s.", argv[0]);
|
||||
errx(EXIT_FAILURE, "Application creation failed. Try mifare-desfire-format before running %s.", argv[0]);
|
||||
// Mifare DESFire SelectApplication (Select previously creates application)
|
||||
res = mifare_desfire_select_application(tags[i], aid);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Application selection failed");
|
||||
free (aid);
|
||||
errx(EXIT_FAILURE, "Application selection failed");
|
||||
free(aid);
|
||||
// Authentication with NDEF Tag Application master key (Authentication with key 0)
|
||||
res = mifare_desfire_authenticate (tags[i], 0, key_app);
|
||||
res = mifare_desfire_authenticate(tags[i], 0, key_app);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Authentication with NDEF Tag Application master key failed");
|
||||
errx(EXIT_FAILURE, "Authentication with NDEF Tag Application master key failed");
|
||||
// Mifare DESFire ChangeKeySetting with key settings equal to 00001001b
|
||||
res = mifare_desfire_change_key_settings (tags[i],0x09);
|
||||
res = mifare_desfire_change_key_settings(tags[i], 0x09);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "ChangeKeySettings failed");
|
||||
errx(EXIT_FAILURE, "ChangeKeySettings failed");
|
||||
// Mifare DESFire CreateStdDataFile with FileNo equal to 03h (CC File DESFire FID), ComSet equal to 00h,
|
||||
// AccesRights equal to E000h, File Size bigger equal to 00000Fh
|
||||
res = mifare_desfire_create_std_data_file(tags[i],0x03,MDCM_PLAIN,0xE000,0x00000F);
|
||||
res = mifare_desfire_create_std_data_file(tags[i], 0x03, MDCM_PLAIN, 0xE000, 0x00000F);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "CreateStdDataFile failed");
|
||||
errx(EXIT_FAILURE, "CreateStdDataFile failed");
|
||||
// Mifare DESFire WriteData to write the content of the CC File with CClEN equal to 000Fh,
|
||||
// Mapping Version equal to 10h,MLe equal to 003Bh, MLc equal to 0034h, and NDEF File Control TLV
|
||||
// equal to T =04h, L=06h, V=E1 04 (NDEF ISO FID=E104h) 0E E0 (NDEF File size =3808 Bytes) 00 (free read access)
|
||||
|
@ -239,39 +239,38 @@ main(int argc, char *argv[])
|
|||
0x00, // free read access
|
||||
0x00 // free write acces
|
||||
};
|
||||
res = mifare_desfire_write_data(tags[i],0x03,0,sizeof(capability_container_file_content),capability_container_file_content);
|
||||
if (res>0){
|
||||
res = mifare_desfire_write_data(tags[i], 0x03, 0, sizeof(capability_container_file_content), capability_container_file_content);
|
||||
if (res > 0) {
|
||||
// Mifare DESFire CreateStdDataFile with FileNo equal to 04h (NDEF FileDESFire FID), CmmSet equal to 00h, AccessRigths
|
||||
// equal to EEE0h, FileSize equal to 000EE0h (3808 Bytes)
|
||||
res = mifare_desfire_create_std_data_file(tags[i],0x04,MDCM_PLAIN,0xEEE0,0x000EE0);
|
||||
res = mifare_desfire_create_std_data_file(tags[i], 0x04, MDCM_PLAIN, 0xEEE0, 0x000EE0);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "CreateStdDataFile failed");
|
||||
errx(EXIT_FAILURE, "CreateStdDataFile failed");
|
||||
} else {
|
||||
errx (EXIT_FAILURE, "Write CC file content failed");
|
||||
errx(EXIT_FAILURE, "Write CC file content failed");
|
||||
}
|
||||
}
|
||||
else if (ndef_mapping == 2) {
|
||||
} else if (ndef_mapping == 2) {
|
||||
// Mifare DESFire Create Application with AID equal to 000001h, key settings equal to 0x0F, NumOfKeys equal to 01h,
|
||||
// 2 bytes File Identifiers supported, File-ID equal to E110h
|
||||
aid = mifare_desfire_aid_new(0x000001);
|
||||
uint8_t app[] = {0xd2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01};
|
||||
res = mifare_desfire_create_application_iso (tags[i], aid, 0x0F, 0x21, 0, 0xE110, app, sizeof (app));
|
||||
res = mifare_desfire_create_application_iso(tags[i], aid, 0x0F, 0x21, 0, 0xE110, app, sizeof(app));
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Application creation failed. Try mifare-desfire-format before running %s.", argv[0]);
|
||||
errx(EXIT_FAILURE, "Application creation failed. Try mifare-desfire-format before running %s.", argv[0]);
|
||||
// Mifare DESFire SelectApplication (Select previously creates application)
|
||||
res = mifare_desfire_select_application(tags[i], aid);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Application selection failed");
|
||||
free (aid);
|
||||
errx(EXIT_FAILURE, "Application selection failed");
|
||||
free(aid);
|
||||
// Authentication with NDEF Tag Application master key (Authentication with key 0)
|
||||
res = mifare_desfire_authenticate (tags[i], 0, key_app);
|
||||
res = mifare_desfire_authenticate(tags[i], 0, key_app);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Authentication with NDEF Tag Application master key failed");
|
||||
errx(EXIT_FAILURE, "Authentication with NDEF Tag Application master key failed");
|
||||
// Mifare DESFire CreateStdDataFile with FileNo equal to 01h (DESFire FID), ComSet equal to 00h,
|
||||
// AccesRights equal to E000h, File Size bigger equal to 00000Fh, ISO File ID equal to E103h
|
||||
res = mifare_desfire_create_std_data_file_iso(tags[i],0x01,MDCM_PLAIN,0xE000,0x00000F,0xE103);
|
||||
res = mifare_desfire_create_std_data_file_iso(tags[i], 0x01, MDCM_PLAIN, 0xE000, 0x00000F, 0xE103);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "CreateStdDataFileIso failed");
|
||||
errx(EXIT_FAILURE, "CreateStdDataFileIso failed");
|
||||
// Mifare DESFire WriteData to write the content of the CC File with CClEN equal to 000Fh,
|
||||
// Mapping Version equal to 20h,MLe equal to 003Bh, MLc equal to 0034h, and NDEF File Control TLV
|
||||
// equal to T =04h, L=06h, V=E1 04 (NDEF ISO FID=E104h) 0xNNNN (NDEF File size = 0x0800/0x1000/0x1E00 bytes)
|
||||
|
@ -295,26 +294,26 @@ main(int argc, char *argv[])
|
|||
ndefmaxsize = 0x1E00;
|
||||
capability_container_file_content[11] = ndefmaxsize >> 8;
|
||||
capability_container_file_content[12] = ndefmaxsize & 0xFF;
|
||||
res = mifare_desfire_write_data(tags[i],0x01,0,sizeof(capability_container_file_content),capability_container_file_content);
|
||||
if (res>0){
|
||||
res = mifare_desfire_write_data(tags[i], 0x01, 0, sizeof(capability_container_file_content), capability_container_file_content);
|
||||
if (res > 0) {
|
||||
// Mifare DESFire CreateStdDataFile with FileNo equal to 02h (DESFire FID), CmmSet equal to 00h, AccessRigths
|
||||
// equal to EEE0h, FileSize equal to ndefmaxsize (0x000800, 0x001000 or 0x001E00)
|
||||
res = mifare_desfire_create_std_data_file_iso(tags[i],0x02,MDCM_PLAIN,0xEEE0,ndefmaxsize, 0xE104);
|
||||
res = mifare_desfire_create_std_data_file_iso(tags[i], 0x02, MDCM_PLAIN, 0xEEE0, ndefmaxsize, 0xE104);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "CreateStdDataFileIso failed");
|
||||
errx(EXIT_FAILURE, "CreateStdDataFileIso failed");
|
||||
} else {
|
||||
errx (EXIT_FAILURE, "Write CC file content failed");
|
||||
errx(EXIT_FAILURE, "Write CC file content failed");
|
||||
}
|
||||
}
|
||||
mifare_desfire_key_free (key_picc);
|
||||
mifare_desfire_key_free (key_app);
|
||||
mifare_desfire_key_free(key_picc);
|
||||
mifare_desfire_key_free(key_app);
|
||||
}
|
||||
mifare_desfire_disconnect (tags[i]);
|
||||
free (tag_uid);
|
||||
mifare_desfire_disconnect(tags[i]);
|
||||
free(tag_uid);
|
||||
}
|
||||
freefare_free_tags (tags);
|
||||
nfc_close (device);
|
||||
freefare_free_tags(tags);
|
||||
nfc_close(device);
|
||||
}
|
||||
nfc_exit (context);
|
||||
exit (error);
|
||||
nfc_exit(context);
|
||||
exit(error);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -44,10 +44,10 @@ struct {
|
|||
static void
|
||||
usage(char *progname)
|
||||
{
|
||||
fprintf (stderr, "usage: %s [-y] [-K 11223344AABBCCDD]\n", progname);
|
||||
fprintf (stderr, "\nOptions:\n");
|
||||
fprintf (stderr, " -y Do not ask for confirmation (dangerous)\n");
|
||||
fprintf (stderr, " -K Provide another PICC key than the default one\n");
|
||||
fprintf(stderr, "usage: %s [-y] [-K 11223344AABBCCDD]\n", progname);
|
||||
fprintf(stderr, "\nOptions:\n");
|
||||
fprintf(stderr, " -y Do not ask for confirmation (dangerous)\n");
|
||||
fprintf(stderr, " -K Provide another PICC key than the default one\n");
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -58,11 +58,11 @@ main(int argc, char *argv[])
|
|||
nfc_device *device = NULL;
|
||||
FreefareTag *tags = NULL;
|
||||
|
||||
while ((ch = getopt (argc, argv, "hyK:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "hyK:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
exit (EXIT_SUCCESS);
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'y':
|
||||
configure_options.interactive = false;
|
||||
|
@ -70,18 +70,18 @@ main(int argc, char *argv[])
|
|||
case 'K':
|
||||
if (strlen(optarg) != 16) {
|
||||
usage(argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
uint64_t n = strtoull(optarg, NULL, 16);
|
||||
int i;
|
||||
for (i=7; i>=0; i--) {
|
||||
for (i = 7; i >= 0; i--) {
|
||||
key_data_picc[i] = (uint8_t) n;
|
||||
n >>= 8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
// Remaining args, if any, are in argv[optind .. (argc-1)]
|
||||
|
@ -90,94 +90,94 @@ main(int argc, char *argv[])
|
|||
size_t device_count;
|
||||
|
||||
nfc_context *context;
|
||||
nfc_init (&context);
|
||||
nfc_init(&context);
|
||||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
errx (EXIT_FAILURE, "No NFC device found.");
|
||||
errx(EXIT_FAILURE, "No NFC device found.");
|
||||
|
||||
for (size_t d = 0; (!error) && (d < device_count); d++) {
|
||||
device = nfc_open (context, devices[d]);
|
||||
if (!device) {
|
||||
warnx ("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
device = nfc_open(context, devices[d]);
|
||||
if (!device) {
|
||||
warnx("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
tags = freefare_get_tags(device);
|
||||
if (!tags) {
|
||||
nfc_close (device);
|
||||
errx (EXIT_FAILURE, "Error listing Mifare DESFire tags.");
|
||||
nfc_close(device);
|
||||
errx(EXIT_FAILURE, "Error listing Mifare DESFire tags.");
|
||||
}
|
||||
|
||||
for (int i = 0; (!error) && tags[i]; i++) {
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type (tags[i]))
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type(tags[i]))
|
||||
continue;
|
||||
|
||||
char *tag_uid = freefare_get_tag_uid (tags[i]);
|
||||
char *tag_uid = freefare_get_tag_uid(tags[i]);
|
||||
char buffer[BUFSIZ];
|
||||
int res;
|
||||
|
||||
res = mifare_desfire_connect (tags[i]);
|
||||
res = mifare_desfire_connect(tags[i]);
|
||||
if (res < 0) {
|
||||
warnx ("Can't connect to Mifare DESFire target.");
|
||||
warnx("Can't connect to Mifare DESFire target.");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure we've at least an EV1 version
|
||||
struct mifare_desfire_version_info info;
|
||||
res = mifare_desfire_get_version (tags[i], &info);
|
||||
res = mifare_desfire_get_version(tags[i], &info);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_get_version");
|
||||
freefare_perror(tags[i], "mifare_desfire_get_version");
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (info.software.version_major < 1) {
|
||||
warnx ("Found old DESFire, skipping");
|
||||
warnx("Found old DESFire, skipping");
|
||||
continue;
|
||||
}
|
||||
printf ("Found %s with UID %s. ", freefare_get_tag_friendly_name (tags[i]), tag_uid);
|
||||
printf("Found %s with UID %s. ", freefare_get_tag_friendly_name(tags[i]), tag_uid);
|
||||
bool do_it = true;
|
||||
|
||||
if (configure_options.interactive) {
|
||||
printf ("Change ATS? [yN] ");
|
||||
fgets (buffer, BUFSIZ, stdin);
|
||||
printf("Change ATS? [yN] ");
|
||||
fgets(buffer, BUFSIZ, stdin);
|
||||
do_it = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
|
||||
} else {
|
||||
printf ("\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (do_it) {
|
||||
|
||||
MifareDESFireKey key_picc = mifare_desfire_des_key_new_with_version (key_data_picc);
|
||||
res = mifare_desfire_authenticate (tags[i], 0, key_picc);
|
||||
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) {
|
||||
freefare_perror (tags[i], "mifare_desfire_authenticate");
|
||||
freefare_perror(tags[i], "mifare_desfire_authenticate");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
mifare_desfire_key_free (key_picc);
|
||||
mifare_desfire_key_free(key_picc);
|
||||
|
||||
res = mifare_desfire_set_ats (tags[i], new_ats);
|
||||
res = mifare_desfire_set_ats(tags[i], new_ats);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_set_ats");
|
||||
freefare_perror(tags[i], "mifare_desfire_set_ats");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mifare_desfire_disconnect (tags[i]);
|
||||
free (tag_uid);
|
||||
mifare_desfire_disconnect(tags[i]);
|
||||
free(tag_uid);
|
||||
}
|
||||
|
||||
freefare_free_tags (tags);
|
||||
nfc_close (device);
|
||||
freefare_free_tags(tags);
|
||||
nfc_close(device);
|
||||
}
|
||||
nfc_exit (context);
|
||||
exit (error);
|
||||
nfc_exit(context);
|
||||
exit(error);
|
||||
} /* main() */
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -43,9 +43,9 @@ struct {
|
|||
static void
|
||||
usage(char *progname)
|
||||
{
|
||||
fprintf (stderr, "usage: %s [-y]\n", progname);
|
||||
fprintf (stderr, "\nOptions:\n");
|
||||
fprintf (stderr, " -y Do not ask for confirmation\n");
|
||||
fprintf(stderr, "usage: %s [-y]\n", progname);
|
||||
fprintf(stderr, "\nOptions:\n");
|
||||
fprintf(stderr, " -y Do not ask for confirmation\n");
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -56,18 +56,18 @@ main(int argc, char *argv[])
|
|||
nfc_device *device = NULL;
|
||||
FreefareTag *tags = NULL;
|
||||
|
||||
while ((ch = getopt (argc, argv, "hy")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "hy")) != -1) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
exit (EXIT_SUCCESS);
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'y':
|
||||
configure_options.interactive = false;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
// Remaining args, if any, are in argv[optind .. (argc-1)]
|
||||
|
@ -76,85 +76,85 @@ main(int argc, char *argv[])
|
|||
size_t device_count;
|
||||
|
||||
nfc_context *context;
|
||||
nfc_init (&context);
|
||||
nfc_init(&context);
|
||||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
errx (EXIT_FAILURE, "No NFC device found.");
|
||||
errx(EXIT_FAILURE, "No NFC device found.");
|
||||
|
||||
for (size_t d = 0; (!error) && (d < device_count); d++) {
|
||||
device = nfc_open (context, devices[d]);
|
||||
if (!device) {
|
||||
warnx ("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
device = nfc_open(context, devices[d]);
|
||||
if (!device) {
|
||||
warnx("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
tags = freefare_get_tags(device);
|
||||
if (!tags) {
|
||||
nfc_close (device);
|
||||
errx (EXIT_FAILURE, "Error listing Mifare DESFire tags.");
|
||||
nfc_close(device);
|
||||
errx(EXIT_FAILURE, "Error listing Mifare DESFire tags.");
|
||||
}
|
||||
|
||||
for (int i = 0; (!error) && tags[i]; i++) {
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type (tags[i]))
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type(tags[i]))
|
||||
continue;
|
||||
|
||||
char *tag_uid = freefare_get_tag_uid (tags[i]);
|
||||
char *tag_uid = freefare_get_tag_uid(tags[i]);
|
||||
char buffer[BUFSIZ];
|
||||
|
||||
int res;
|
||||
|
||||
res = mifare_desfire_connect (tags[i]);
|
||||
res = mifare_desfire_connect(tags[i]);
|
||||
if (res < 0) {
|
||||
warnx ("Can't connect to Mifare DESFire target.");
|
||||
warnx("Can't connect to Mifare DESFire target.");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure we've at least an EV1 version
|
||||
struct mifare_desfire_version_info info;
|
||||
res = mifare_desfire_get_version (tags[i], &info);
|
||||
res = mifare_desfire_get_version(tags[i], &info);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_get_version");
|
||||
freefare_perror(tags[i], "mifare_desfire_get_version");
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (info.software.version_major < 1) {
|
||||
warnx ("Found old DESFire, skipping");
|
||||
warnx("Found old DESFire, skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
printf ("Found %s with UID %s. ", freefare_get_tag_friendly_name (tags[i]), tag_uid);
|
||||
printf("Found %s with UID %s. ", freefare_get_tag_friendly_name(tags[i]), tag_uid);
|
||||
bool do_it = true;
|
||||
|
||||
if (configure_options.interactive) {
|
||||
printf ("Change default key? [yN] ");
|
||||
fgets (buffer, BUFSIZ, stdin);
|
||||
printf("Change default key? [yN] ");
|
||||
fgets(buffer, BUFSIZ, stdin);
|
||||
do_it = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
|
||||
} else {
|
||||
printf ("\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (do_it) {
|
||||
|
||||
MifareDESFireKey default_key = mifare_desfire_des_key_new_with_version (null_key_data);
|
||||
res = mifare_desfire_authenticate (tags[i], 0, default_key);
|
||||
MifareDESFireKey default_key = mifare_desfire_des_key_new_with_version(null_key_data);
|
||||
res = mifare_desfire_authenticate(tags[i], 0, default_key);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_authenticate");
|
||||
freefare_perror(tags[i], "mifare_desfire_authenticate");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
mifare_desfire_key_free (default_key);
|
||||
mifare_desfire_key_free(default_key);
|
||||
|
||||
MifareDESFireKey new_key = mifare_desfire_des_key_new (new_key_data);
|
||||
mifare_desfire_key_set_version (new_key, NEW_KEY_VERSION);
|
||||
res = mifare_desfire_set_default_key (tags[i], new_key);
|
||||
free (new_key);
|
||||
MifareDESFireKey new_key = mifare_desfire_des_key_new(new_key_data);
|
||||
mifare_desfire_key_set_version(new_key, NEW_KEY_VERSION);
|
||||
res = mifare_desfire_set_default_key(tags[i], new_key);
|
||||
free(new_key);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_set_default_key");
|
||||
freefare_perror(tags[i], "mifare_desfire_set_default_key");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
@ -164,92 +164,92 @@ main(int argc, char *argv[])
|
|||
* (it's hard to create a unit-test to do so).
|
||||
*/
|
||||
|
||||
MifareDESFireAID aid = mifare_desfire_aid_new (0x112233);
|
||||
res = mifare_desfire_create_application (tags[i], aid, 0xFF, 1);
|
||||
MifareDESFireAID aid = mifare_desfire_aid_new(0x112233);
|
||||
res = mifare_desfire_create_application(tags[i], aid, 0xFF, 1);
|
||||
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_create_application");
|
||||
freefare_perror(tags[i], "mifare_desfire_create_application");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
res = mifare_desfire_select_application (tags[i], aid);
|
||||
res = mifare_desfire_select_application(tags[i], aid);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_select_application");
|
||||
freefare_perror(tags[i], "mifare_desfire_select_application");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t version;
|
||||
res = mifare_desfire_get_key_version (tags[i], 0, &version);
|
||||
res = mifare_desfire_get_key_version(tags[i], 0, &version);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_get_key_version");
|
||||
freefare_perror(tags[i], "mifare_desfire_get_key_version");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (version != NEW_KEY_VERSION) {
|
||||
fprintf (stderr, "Wrong key version: %02x (expected %02x).\n", version, NEW_KEY_VERSION);
|
||||
fprintf(stderr, "Wrong key version: %02x (expected %02x).\n", version, NEW_KEY_VERSION);
|
||||
error = EXIT_FAILURE;
|
||||
/* continue */
|
||||
}
|
||||
|
||||
new_key = mifare_desfire_des_key_new (new_key_data);
|
||||
res = mifare_desfire_authenticate (tags[i], 0, new_key);
|
||||
free (new_key);
|
||||
new_key = mifare_desfire_des_key_new(new_key_data);
|
||||
res = mifare_desfire_authenticate(tags[i], 0, new_key);
|
||||
free(new_key);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_authenticate");
|
||||
freefare_perror(tags[i], "mifare_desfire_authenticate");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
free (aid);
|
||||
free(aid);
|
||||
|
||||
/* Resetdefault settings */
|
||||
|
||||
res = mifare_desfire_select_application (tags[i], NULL);
|
||||
res = mifare_desfire_select_application(tags[i], NULL);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_select_application");
|
||||
freefare_perror(tags[i], "mifare_desfire_select_application");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
default_key = mifare_desfire_des_key_new (null_key_data);
|
||||
default_key = mifare_desfire_des_key_new(null_key_data);
|
||||
|
||||
res = mifare_desfire_authenticate (tags[i], 0, default_key);
|
||||
res = mifare_desfire_authenticate(tags[i], 0, default_key);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_authenticate");
|
||||
freefare_perror(tags[i], "mifare_desfire_authenticate");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
res = mifare_desfire_set_default_key (tags[i], default_key);
|
||||
res = mifare_desfire_set_default_key(tags[i], default_key);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_set_default_key");
|
||||
freefare_perror(tags[i], "mifare_desfire_set_default_key");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
mifare_desfire_key_free (default_key);
|
||||
mifare_desfire_key_free(default_key);
|
||||
|
||||
/* Wipeout the card */
|
||||
|
||||
res = mifare_desfire_format_picc (tags[i]);
|
||||
res = mifare_desfire_format_picc(tags[i]);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_format_picc");
|
||||
freefare_perror(tags[i], "mifare_desfire_format_picc");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mifare_desfire_disconnect (tags[i]);
|
||||
free (tag_uid);
|
||||
mifare_desfire_disconnect(tags[i]);
|
||||
free(tag_uid);
|
||||
}
|
||||
|
||||
freefare_free_tags (tags);
|
||||
nfc_close (device);
|
||||
freefare_free_tags(tags);
|
||||
nfc_close(device);
|
||||
}
|
||||
nfc_exit (context);
|
||||
exit (error);
|
||||
nfc_exit(context);
|
||||
exit(error);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -40,10 +40,10 @@ struct {
|
|||
static void
|
||||
usage(char *progname)
|
||||
{
|
||||
fprintf (stderr, "usage: %s [-y] [-K 11223344AABBCCDD]\n", progname);
|
||||
fprintf (stderr, "\nOptions:\n");
|
||||
fprintf (stderr, " -y Do not ask for confirmation (dangerous)\n");
|
||||
fprintf (stderr, " -K Provide another PICC key than the default one\n");
|
||||
fprintf(stderr, "usage: %s [-y] [-K 11223344AABBCCDD]\n", progname);
|
||||
fprintf(stderr, "\nOptions:\n");
|
||||
fprintf(stderr, " -y Do not ask for confirmation (dangerous)\n");
|
||||
fprintf(stderr, " -K Provide another PICC key than the default one\n");
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -54,11 +54,11 @@ main(int argc, char *argv[])
|
|||
nfc_device *device = NULL;
|
||||
FreefareTag *tags = NULL;
|
||||
|
||||
while ((ch = getopt (argc, argv, "hyK:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "hyK:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
exit (EXIT_SUCCESS);
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'y':
|
||||
configure_options.interactive = false;
|
||||
|
@ -66,18 +66,18 @@ main(int argc, char *argv[])
|
|||
case 'K':
|
||||
if (strlen(optarg) != 16) {
|
||||
usage(argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
uint64_t n = strtoull(optarg, NULL, 16);
|
||||
int i;
|
||||
for (i=7; i>=0; i--) {
|
||||
for (i = 7; i >= 0; i--) {
|
||||
key_data_picc[i] = (uint8_t) n;
|
||||
n >>= 8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
// Remaining args, if any, are in argv[optind .. (argc-1)]
|
||||
|
@ -86,127 +86,127 @@ main(int argc, char *argv[])
|
|||
size_t device_count;
|
||||
|
||||
nfc_context *context;
|
||||
nfc_init (&context);
|
||||
nfc_init(&context);
|
||||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
errx (EXIT_FAILURE, "No NFC device found.");
|
||||
errx(EXIT_FAILURE, "No NFC device found.");
|
||||
|
||||
for (size_t d = 0; (!error) && (d < device_count); d++) {
|
||||
device = nfc_open (context, devices[d]);
|
||||
if (!device) {
|
||||
warnx ("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
device = nfc_open(context, devices[d]);
|
||||
if (!device) {
|
||||
warnx("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
tags = freefare_get_tags(device);
|
||||
if (!tags) {
|
||||
nfc_close (device);
|
||||
errx (EXIT_FAILURE, "Error listing Mifare DESFire tags.");
|
||||
nfc_close(device);
|
||||
errx(EXIT_FAILURE, "Error listing Mifare DESFire tags.");
|
||||
}
|
||||
|
||||
for (int i = 0; (!error) && tags[i]; i++) {
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type (tags[i]))
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type(tags[i]))
|
||||
continue;
|
||||
|
||||
char *tag_uid = freefare_get_tag_uid (tags[i]);
|
||||
char *tag_uid = freefare_get_tag_uid(tags[i]);
|
||||
char buffer[BUFSIZ];
|
||||
|
||||
int res;
|
||||
|
||||
res = mifare_desfire_connect (tags[i]);
|
||||
res = mifare_desfire_connect(tags[i]);
|
||||
if (res < 0) {
|
||||
warnx ("Can't connect to Mifare DESFire target.");
|
||||
warnx("Can't connect to Mifare DESFire target.");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure we've at least an EV1 version
|
||||
struct mifare_desfire_version_info info;
|
||||
res = mifare_desfire_get_version (tags[i], &info);
|
||||
res = mifare_desfire_get_version(tags[i], &info);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_get_version");
|
||||
freefare_perror(tags[i], "mifare_desfire_get_version");
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (info.software.version_major < 1) {
|
||||
warnx ("Found old DESFire, skipping");
|
||||
warnx("Found old DESFire, skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
printf ("Found %s with UID %s. ", freefare_get_tag_friendly_name (tags[i]), tag_uid);
|
||||
printf("Found %s with UID %s. ", freefare_get_tag_friendly_name(tags[i]), tag_uid);
|
||||
bool do_it = true;
|
||||
|
||||
size_t tag_uid_len = strlen (tag_uid) / 2;
|
||||
size_t tag_uid_len = strlen(tag_uid) / 2;
|
||||
switch (tag_uid_len) {
|
||||
case 7: // Regular UID
|
||||
if (configure_options.interactive) {
|
||||
printf ("Configure random UID (this cannot be undone) [yN] ");
|
||||
fgets (buffer, BUFSIZ, stdin);
|
||||
printf("Configure random UID (this cannot be undone) [yN] ");
|
||||
fgets(buffer, BUFSIZ, stdin);
|
||||
do_it = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
|
||||
} else {
|
||||
printf ("\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (do_it) {
|
||||
|
||||
MifareDESFireKey key_picc = mifare_desfire_des_key_new_with_version (key_data_picc);
|
||||
res = mifare_desfire_authenticate (tags[i], 0, key_picc);
|
||||
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) {
|
||||
freefare_perror (tags[i], "mifare_desfire_authenticate");
|
||||
freefare_perror(tags[i], "mifare_desfire_authenticate");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
mifare_desfire_key_free (key_picc);
|
||||
mifare_desfire_key_free(key_picc);
|
||||
|
||||
res = mifare_desfire_set_configuration (tags[i], false, true);
|
||||
res = mifare_desfire_set_configuration(tags[i], false, true);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_set_configuration");
|
||||
freefare_perror(tags[i], "mifare_desfire_set_configuration");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
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) {
|
||||
freefare_perror (tags[i], "mifare_desfire_authenticate");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
mifare_desfire_key_free (key_picc);
|
||||
|
||||
char *old_tag_uid;
|
||||
res = mifare_desfire_get_card_uid (tags[i], &old_tag_uid);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_get_card_uid");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
printf ("Old card UID: %s\n", old_tag_uid);
|
||||
free (old_tag_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) {
|
||||
freefare_perror(tags[i], "mifare_desfire_authenticate");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
default: // Should not happen
|
||||
warnx ("Unsupported UID length %d.", (int) tag_uid_len);
|
||||
}
|
||||
mifare_desfire_key_free(key_picc);
|
||||
|
||||
char *old_tag_uid;
|
||||
res = mifare_desfire_get_card_uid(tags[i], &old_tag_uid);
|
||||
if (res < 0) {
|
||||
freefare_perror(tags[i], "mifare_desfire_get_card_uid");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
mifare_desfire_disconnect (tags[i]);
|
||||
free (tag_uid);
|
||||
printf("Old card UID: %s\n", old_tag_uid);
|
||||
free(old_tag_uid);
|
||||
|
||||
break;
|
||||
default: // Should not happen
|
||||
warnx("Unsupported UID length %d.", (int) tag_uid_len);
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
mifare_desfire_disconnect(tags[i]);
|
||||
free(tag_uid);
|
||||
}
|
||||
|
||||
freefare_free_tags (tags);
|
||||
nfc_close (device);
|
||||
freefare_free_tags(tags);
|
||||
nfc_close(device);
|
||||
}
|
||||
nfc_exit (context);
|
||||
exit (error);
|
||||
nfc_exit(context);
|
||||
exit(error);
|
||||
} /* main() */
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -40,10 +40,10 @@ struct {
|
|||
static void
|
||||
usage(char *progname)
|
||||
{
|
||||
fprintf (stderr, "usage: %s [-y] [-K 11223344AABBCCDD]\n", progname);
|
||||
fprintf (stderr, "\nOptions:\n");
|
||||
fprintf (stderr, " -y Do not ask for confirmation (dangerous)\n");
|
||||
fprintf (stderr, " -K Provide another PICC key than the default one\n");
|
||||
fprintf(stderr, "usage: %s [-y] [-K 11223344AABBCCDD]\n", progname);
|
||||
fprintf(stderr, "\nOptions:\n");
|
||||
fprintf(stderr, " -y Do not ask for confirmation (dangerous)\n");
|
||||
fprintf(stderr, " -K Provide another PICC key than the default one\n");
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -54,30 +54,30 @@ main(int argc, char *argv[])
|
|||
nfc_device *device = NULL;
|
||||
FreefareTag *tags = NULL;
|
||||
|
||||
while ((ch = getopt (argc, argv, "hyK:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "hyK:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'y':
|
||||
format_options.interactive = false;
|
||||
break;
|
||||
case 'K':
|
||||
if (strlen(optarg) != 16) {
|
||||
usage(argv[0]);
|
||||
exit (EXIT_SUCCESS);
|
||||
break;
|
||||
case 'y':
|
||||
format_options.interactive = false;
|
||||
break;
|
||||
case 'K':
|
||||
if (strlen(optarg) != 16) {
|
||||
usage(argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
uint64_t n = strtoull(optarg, NULL, 16);
|
||||
int i;
|
||||
for (i=7; i>=0; i--) {
|
||||
key_data_picc[i] = (uint8_t) n;
|
||||
n >>= 8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
uint64_t n = strtoull(optarg, NULL, 16);
|
||||
int i;
|
||||
for (i = 7; i >= 0; i--) {
|
||||
key_data_picc[i] = (uint8_t) n;
|
||||
n >>= 8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
// Remaining args, if any, are in argv[optind .. (argc-1)]
|
||||
|
@ -86,63 +86,63 @@ main(int argc, char *argv[])
|
|||
size_t device_count;
|
||||
|
||||
nfc_context *context;
|
||||
nfc_init (&context);
|
||||
nfc_init(&context);
|
||||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
errx (EXIT_FAILURE, "No NFC device found.");
|
||||
errx(EXIT_FAILURE, "No NFC device found.");
|
||||
|
||||
for (size_t d = 0; (!error) && (d < device_count); d++) {
|
||||
device = nfc_open (context, devices[d]);
|
||||
if (!device) {
|
||||
warnx ("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
device = nfc_open(context, devices[d]);
|
||||
if (!device) {
|
||||
warnx("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
tags = freefare_get_tags(device);
|
||||
if (!tags) {
|
||||
nfc_close (device);
|
||||
errx (EXIT_FAILURE, "Error listing Mifare DESFire tags.");
|
||||
nfc_close(device);
|
||||
errx(EXIT_FAILURE, "Error listing Mifare DESFire tags.");
|
||||
}
|
||||
|
||||
for (int i = 0; (!error) && tags[i]; i++) {
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type (tags[i]))
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type(tags[i]))
|
||||
continue;
|
||||
|
||||
char *tag_uid = freefare_get_tag_uid (tags[i]);
|
||||
char *tag_uid = freefare_get_tag_uid(tags[i]);
|
||||
char buffer[BUFSIZ];
|
||||
|
||||
printf ("Found %s with UID %s. ", freefare_get_tag_friendly_name (tags[i]), tag_uid);
|
||||
printf("Found %s with UID %s. ", freefare_get_tag_friendly_name(tags[i]), tag_uid);
|
||||
bool format = true;
|
||||
if (format_options.interactive) {
|
||||
printf ("Format [yN] ");
|
||||
fgets (buffer, BUFSIZ, stdin);
|
||||
printf("Format [yN] ");
|
||||
fgets(buffer, BUFSIZ, stdin);
|
||||
format = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
|
||||
} else {
|
||||
printf ("\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (format) {
|
||||
int res;
|
||||
|
||||
res = mifare_desfire_connect (tags[i]);
|
||||
res = mifare_desfire_connect(tags[i]);
|
||||
if (res < 0) {
|
||||
warnx ("Can't connect to Mifare DESFire target.");
|
||||
warnx("Can't connect to Mifare DESFire target.");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
MifareDESFireKey key_picc = mifare_desfire_des_key_new_with_version (key_data_picc);
|
||||
res = mifare_desfire_authenticate (tags[i], 0, key_picc);
|
||||
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) {
|
||||
warnx ("Can't authenticate on Mifare DESFire target.");
|
||||
warnx("Can't authenticate on Mifare DESFire target.");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
mifare_desfire_key_free (key_picc);
|
||||
mifare_desfire_key_free(key_picc);
|
||||
|
||||
// Send Mifare DESFire ChangeKeySetting to change the PICC master key settings into :
|
||||
// bit7-bit4 equal to 0000b
|
||||
|
@ -150,26 +150,26 @@ main(int argc, char *argv[])
|
|||
// bit2 equal to 1b, CreateApplication and DeleteApplication commands are allowed without PICC master key authentication
|
||||
// bit1 equal to 1b, GetApplicationIDs, and GetKeySettings are allowed without PICC master key authentication
|
||||
// bit0 equal to 1b, PICC masterkey MAY be frozen or changeable
|
||||
res = mifare_desfire_change_key_settings (tags[i],0x0F);
|
||||
res = mifare_desfire_change_key_settings(tags[i], 0x0F);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "ChangeKeySettings failed");
|
||||
res = mifare_desfire_format_picc (tags[i]);
|
||||
errx(EXIT_FAILURE, "ChangeKeySettings failed");
|
||||
res = mifare_desfire_format_picc(tags[i]);
|
||||
if (res < 0) {
|
||||
warn ("Can't format PICC.");
|
||||
warn("Can't format PICC.");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
mifare_desfire_disconnect (tags[i]);
|
||||
mifare_desfire_disconnect(tags[i]);
|
||||
}
|
||||
|
||||
free (tag_uid);
|
||||
free(tag_uid);
|
||||
}
|
||||
|
||||
freefare_free_tags (tags);
|
||||
nfc_close (device);
|
||||
freefare_free_tags(tags);
|
||||
nfc_close(device);
|
||||
}
|
||||
nfc_exit (context);
|
||||
exit (error);
|
||||
nfc_exit(context);
|
||||
exit(error);
|
||||
} /* main() */
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -32,117 +32,117 @@ main(int argc, char *argv[])
|
|||
FreefareTag *tags = NULL;
|
||||
|
||||
if (argc > 1)
|
||||
errx (EXIT_FAILURE, "usage: %s", argv[0]);
|
||||
errx(EXIT_FAILURE, "usage: %s", argv[0]);
|
||||
|
||||
nfc_connstring devices[8];
|
||||
size_t device_count;
|
||||
|
||||
nfc_context *context;
|
||||
nfc_init (&context);
|
||||
nfc_init(&context);
|
||||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
errx (EXIT_FAILURE, "No NFC device found.");
|
||||
errx(EXIT_FAILURE, "No NFC device found.");
|
||||
|
||||
for (size_t d = 0; d < device_count; d++) {
|
||||
device = nfc_open (context, devices[d]);
|
||||
if (!device) {
|
||||
warnx ("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
device = nfc_open(context, devices[d]);
|
||||
if (!device) {
|
||||
warnx("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
tags = freefare_get_tags(device);
|
||||
if (!tags) {
|
||||
nfc_close (device);
|
||||
errx (EXIT_FAILURE, "Error listing tags.");
|
||||
nfc_close(device);
|
||||
errx(EXIT_FAILURE, "Error listing tags.");
|
||||
}
|
||||
|
||||
for (int i = 0; (!error) && tags[i]; i++) {
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type (tags[i]))
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type(tags[i]))
|
||||
continue;
|
||||
|
||||
int res;
|
||||
char *tag_uid = freefare_get_tag_uid (tags[i]);
|
||||
char *tag_uid = freefare_get_tag_uid(tags[i]);
|
||||
|
||||
struct mifare_desfire_version_info info;
|
||||
|
||||
res = mifare_desfire_connect (tags[i]);
|
||||
res = mifare_desfire_connect(tags[i]);
|
||||
if (res < 0) {
|
||||
warnx ("Can't connect to Mifare DESFire target.");
|
||||
warnx("Can't connect to Mifare DESFire target.");
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
res = mifare_desfire_get_version (tags[i], &info);
|
||||
res = mifare_desfire_get_version(tags[i], &info);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_get_version");
|
||||
freefare_perror(tags[i], "mifare_desfire_get_version");
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
printf ("===> Version information for tag %s:\n", tag_uid);
|
||||
printf ("UID: 0x%02x%02x%02x%02x%02x%02x%02x\n", info.uid[0], info.uid[1], info.uid[2], info.uid[3], info.uid[4], info.uid[5], info.uid[6]);
|
||||
printf ("Batch number: 0x%02x%02x%02x%02x%02x\n", info.batch_number[0], info.batch_number[1], info.batch_number[2], info.batch_number[3], info.batch_number[4]);
|
||||
printf ("Production date: week %x, 20%02x\n", info.production_week, info.production_year);
|
||||
printf ("Hardware Information:\n");
|
||||
printf (" Vendor ID: 0x%02x\n", info.hardware.vendor_id);
|
||||
printf (" Type: 0x%02x\n", info.hardware.type);
|
||||
printf (" Subtype: 0x%02x\n", info.hardware.subtype);
|
||||
printf (" Version: %d.%d\n", info.hardware.version_major, info.hardware.version_minor);
|
||||
printf (" Storage size: 0x%02x (%s%d bytes)\n", info.hardware.storage_size, (info.hardware.storage_size & 1) ? ">" : "=", 1 << (info.hardware.storage_size >> 1));
|
||||
printf (" Protocol: 0x%02x\n", info.hardware.protocol);
|
||||
printf ("Software Information:\n");
|
||||
printf (" Vendor ID: 0x%02x\n", info.software.vendor_id);
|
||||
printf (" Type: 0x%02x\n", info.software.type);
|
||||
printf (" Subtype: 0x%02x\n", info.software.subtype);
|
||||
printf (" Version: %d.%d\n", info.software.version_major, info.software.version_minor);
|
||||
printf (" Storage size: 0x%02x (%s%d bytes)\n", info.software.storage_size, (info.software.storage_size & 1) ? ">" : "=", 1 << (info.software.storage_size >> 1));
|
||||
printf (" Protocol: 0x%02x\n", info.software.protocol);
|
||||
printf("===> Version information for tag %s:\n", tag_uid);
|
||||
printf("UID: 0x%02x%02x%02x%02x%02x%02x%02x\n", info.uid[0], info.uid[1], info.uid[2], info.uid[3], info.uid[4], info.uid[5], info.uid[6]);
|
||||
printf("Batch number: 0x%02x%02x%02x%02x%02x\n", info.batch_number[0], info.batch_number[1], info.batch_number[2], info.batch_number[3], info.batch_number[4]);
|
||||
printf("Production date: week %x, 20%02x\n", info.production_week, info.production_year);
|
||||
printf("Hardware Information:\n");
|
||||
printf(" Vendor ID: 0x%02x\n", info.hardware.vendor_id);
|
||||
printf(" Type: 0x%02x\n", info.hardware.type);
|
||||
printf(" Subtype: 0x%02x\n", info.hardware.subtype);
|
||||
printf(" Version: %d.%d\n", info.hardware.version_major, info.hardware.version_minor);
|
||||
printf(" Storage size: 0x%02x (%s%d bytes)\n", info.hardware.storage_size, (info.hardware.storage_size & 1) ? ">" : "=", 1 << (info.hardware.storage_size >> 1));
|
||||
printf(" Protocol: 0x%02x\n", info.hardware.protocol);
|
||||
printf("Software Information:\n");
|
||||
printf(" Vendor ID: 0x%02x\n", info.software.vendor_id);
|
||||
printf(" Type: 0x%02x\n", info.software.type);
|
||||
printf(" Subtype: 0x%02x\n", info.software.subtype);
|
||||
printf(" Version: %d.%d\n", info.software.version_major, info.software.version_minor);
|
||||
printf(" Storage size: 0x%02x (%s%d bytes)\n", info.software.storage_size, (info.software.storage_size & 1) ? ">" : "=", 1 << (info.software.storage_size >> 1));
|
||||
printf(" Protocol: 0x%02x\n", info.software.protocol);
|
||||
|
||||
uint8_t settings;
|
||||
uint8_t max_keys;
|
||||
res = mifare_desfire_get_key_settings (tags[i], &settings, &max_keys);
|
||||
res = mifare_desfire_get_key_settings(tags[i], &settings, &max_keys);
|
||||
if (res == 0) {
|
||||
printf ("Master Key settings (0x%02x):\n", settings);
|
||||
printf (" 0x%02x configuration changeable;\n", settings & 0x08);
|
||||
printf (" 0x%02x PICC Master Key not required for create / delete;\n", settings & 0x04);
|
||||
printf (" 0x%02x Free directory list access without PICC Master Key;\n", settings & 0x02);
|
||||
printf (" 0x%02x Allow changing the Master Key;\n", settings & 0x01);
|
||||
} else if (AUTHENTICATION_ERROR == mifare_desfire_last_picc_error (tags[i])) {
|
||||
printf ("Master Key settings: LOCKED\n");
|
||||
printf("Master Key settings (0x%02x):\n", settings);
|
||||
printf(" 0x%02x configuration changeable;\n", settings & 0x08);
|
||||
printf(" 0x%02x PICC Master Key not required for create / delete;\n", settings & 0x04);
|
||||
printf(" 0x%02x Free directory list access without PICC Master Key;\n", settings & 0x02);
|
||||
printf(" 0x%02x Allow changing the Master Key;\n", settings & 0x01);
|
||||
} else if (AUTHENTICATION_ERROR == mifare_desfire_last_picc_error(tags[i])) {
|
||||
printf("Master Key settings: LOCKED\n");
|
||||
} else {
|
||||
freefare_perror (tags[i], "mifare_desfire_get_key_settings");
|
||||
freefare_perror(tags[i], "mifare_desfire_get_key_settings");
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t version;
|
||||
mifare_desfire_get_key_version (tags[i], 0, &version);
|
||||
printf ("Master Key version: %d (0x%02x)\n", version, version);
|
||||
mifare_desfire_get_key_version(tags[i], 0, &version);
|
||||
printf("Master Key version: %d (0x%02x)\n", version, version);
|
||||
|
||||
uint32_t size;
|
||||
res = mifare_desfire_free_mem (tags[i], &size);
|
||||
printf ("Free memory: ");
|
||||
res = mifare_desfire_free_mem(tags[i], &size);
|
||||
printf("Free memory: ");
|
||||
if (0 == res) {
|
||||
printf ("%d bytes\n", size);
|
||||
printf("%d bytes\n", size);
|
||||
} else {
|
||||
printf ("unknown\n");
|
||||
printf("unknown\n");
|
||||
}
|
||||
|
||||
printf ("Use random UID: %s\n", (strlen (tag_uid) / 2 == 4) ? "yes" : "no");
|
||||
printf("Use random UID: %s\n", (strlen(tag_uid) / 2 == 4) ? "yes" : "no");
|
||||
|
||||
free (tag_uid);
|
||||
free(tag_uid);
|
||||
|
||||
mifare_desfire_disconnect (tags[i]);
|
||||
mifare_desfire_disconnect(tags[i]);
|
||||
}
|
||||
|
||||
freefare_free_tags (tags);
|
||||
nfc_close (device);
|
||||
freefare_free_tags(tags);
|
||||
nfc_close(device);
|
||||
}
|
||||
nfc_exit (context);
|
||||
exit (error);
|
||||
nfc_exit(context);
|
||||
exit(error);
|
||||
} /* main() */
|
||||
|
||||
|
|
|
@ -54,12 +54,12 @@ struct {
|
|||
static void
|
||||
usage(char *progname)
|
||||
{
|
||||
fprintf (stderr, "This application reads a NDEF payload from a Mifare DESFire formatted as NFC Forum Type 4 Tag.\n");
|
||||
fprintf (stderr, "usage: %s [-y] -o FILE [-k 11223344AABBCCDD]\n", progname);
|
||||
fprintf (stderr, "\nOptions:\n");
|
||||
fprintf (stderr, " -y Do not ask for confirmation\n");
|
||||
fprintf (stderr, " -o Extract NDEF message if available in FILE\n");
|
||||
fprintf (stderr, " -k Provide another NDEF Tag Application key than the default one\n");
|
||||
fprintf(stderr, "This application reads a NDEF payload from a Mifare DESFire formatted as NFC Forum Type 4 Tag.\n");
|
||||
fprintf(stderr, "usage: %s [-y] -o FILE [-k 11223344AABBCCDD]\n", progname);
|
||||
fprintf(stderr, "\nOptions:\n");
|
||||
fprintf(stderr, " -y Do not ask for confirmation\n");
|
||||
fprintf(stderr, " -o Extract NDEF message if available in FILE\n");
|
||||
fprintf(stderr, " -k Provide another NDEF Tag Application key than the default one\n");
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -71,53 +71,53 @@ main(int argc, char *argv[])
|
|||
FreefareTag *tags = NULL;
|
||||
|
||||
char *ndef_output = NULL;
|
||||
while ((ch = getopt (argc, argv, "hyo:k:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
exit (EXIT_SUCCESS);
|
||||
break;
|
||||
case 'y':
|
||||
read_options.interactive = false;
|
||||
break;
|
||||
case 'o':
|
||||
ndef_output = optarg;
|
||||
break;
|
||||
case 'k':
|
||||
if (strlen(optarg) != 16) {
|
||||
usage(argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
uint64_t n = strtoull(optarg, NULL, 16);
|
||||
int i;
|
||||
for (i=7; i>=0; i--) {
|
||||
key_data_app[i] = (uint8_t) n;
|
||||
n >>= 8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
while ((ch = getopt(argc, argv, "hyo:k:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'y':
|
||||
read_options.interactive = false;
|
||||
break;
|
||||
case 'o':
|
||||
ndef_output = optarg;
|
||||
break;
|
||||
case 'k':
|
||||
if (strlen(optarg) != 16) {
|
||||
usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
uint64_t n = strtoull(optarg, NULL, 16);
|
||||
int i;
|
||||
for (i = 7; i >= 0; i--) {
|
||||
key_data_app[i] = (uint8_t) n;
|
||||
n >>= 8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
// Remaining args, if any, are in argv[optind .. (argc-1)]
|
||||
|
||||
if (ndef_output == NULL) {
|
||||
usage (argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
FILE* message_stream = NULL;
|
||||
FILE* ndef_stream = NULL;
|
||||
FILE *message_stream = NULL;
|
||||
FILE *ndef_stream = NULL;
|
||||
|
||||
if ((strlen (ndef_output) == 1) && (ndef_output[0] == '-')) {
|
||||
if ((strlen(ndef_output) == 1) && (ndef_output[0] == '-')) {
|
||||
message_stream = stderr;
|
||||
ndef_stream = stdout;
|
||||
} else {
|
||||
message_stream = stdout;
|
||||
ndef_stream = fopen(ndef_output, "wb");
|
||||
if (!ndef_stream) {
|
||||
fprintf (stderr, "Could not open file %s.\n", ndef_output);
|
||||
exit (EXIT_FAILURE);
|
||||
fprintf(stderr, "Could not open file %s.\n", ndef_output);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,72 +125,72 @@ main(int argc, char *argv[])
|
|||
size_t device_count;
|
||||
|
||||
nfc_context *context;
|
||||
nfc_init (&context);
|
||||
nfc_init(&context);
|
||||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
errx (EXIT_FAILURE, "No NFC device found.");
|
||||
errx(EXIT_FAILURE, "No NFC device found.");
|
||||
|
||||
for (size_t d = 0; d < device_count; d++) {
|
||||
device = nfc_open (context, devices[d]);
|
||||
device = nfc_open(context, devices[d]);
|
||||
|
||||
if (!device) {
|
||||
warnx ("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
if (!device) {
|
||||
warnx("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
tags = freefare_get_tags(device);
|
||||
if (!tags) {
|
||||
nfc_close (device);
|
||||
errx (EXIT_FAILURE, "Error listing tags.");
|
||||
nfc_close(device);
|
||||
errx(EXIT_FAILURE, "Error listing tags.");
|
||||
}
|
||||
|
||||
for (int i = 0; (!error) && tags[i]; i++) {
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type (tags[i]))
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type(tags[i]))
|
||||
continue;
|
||||
|
||||
char *tag_uid = freefare_get_tag_uid (tags[i]);
|
||||
char *tag_uid = freefare_get_tag_uid(tags[i]);
|
||||
char buffer[BUFSIZ];
|
||||
|
||||
fprintf (message_stream, "Found %s with UID %s. ", freefare_get_tag_friendly_name (tags[i]), tag_uid);
|
||||
fprintf(message_stream, "Found %s with UID %s. ", freefare_get_tag_friendly_name(tags[i]), tag_uid);
|
||||
|
||||
bool read_ndef = true;
|
||||
if (read_options.interactive) {
|
||||
fprintf (message_stream, "Read NDEF [yN] ");
|
||||
fgets (buffer, BUFSIZ, stdin);
|
||||
fprintf(message_stream, "Read NDEF [yN] ");
|
||||
fgets(buffer, BUFSIZ, stdin);
|
||||
read_ndef = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
|
||||
} else {
|
||||
fprintf (message_stream, "\n");
|
||||
fprintf(message_stream, "\n");
|
||||
}
|
||||
|
||||
if (read_ndef) {
|
||||
int res;
|
||||
|
||||
res = mifare_desfire_connect (tags[i]);
|
||||
res = mifare_desfire_connect(tags[i]);
|
||||
if (res < 0) {
|
||||
warnx ("Can't connect to Mifare DESFire target.");
|
||||
warnx("Can't connect to Mifare DESFire target.");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
// We've to track DESFire version as NDEF mapping is different
|
||||
struct mifare_desfire_version_info info;
|
||||
res = mifare_desfire_get_version (tags[i], &info);
|
||||
res = mifare_desfire_get_version(tags[i], &info);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_get_version");
|
||||
freefare_perror(tags[i], "mifare_desfire_get_version");
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
MifareDESFireKey key_app;
|
||||
key_app = mifare_desfire_des_key_new_with_version (key_data_app);
|
||||
key_app = mifare_desfire_des_key_new_with_version(key_data_app);
|
||||
|
||||
// Mifare DESFire SelectApplication (Select application)
|
||||
MifareDESFireAID aid;
|
||||
if (info.software.version_major==0)
|
||||
if (info.software.version_major == 0)
|
||||
aid = mifare_desfire_aid_new(0xEEEE10);
|
||||
else
|
||||
// There is no more relationship between DESFire AID and ISO AID...
|
||||
|
@ -198,80 +198,80 @@ main(int argc, char *argv[])
|
|||
aid = mifare_desfire_aid_new(0x000001);
|
||||
res = mifare_desfire_select_application(tags[i], aid);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Application selection failed. Try mifare-desfire-create-ndef before running %s.", argv[0]);
|
||||
free (aid);
|
||||
errx(EXIT_FAILURE, "Application selection failed. Try mifare-desfire-create-ndef before running %s.", argv[0]);
|
||||
free(aid);
|
||||
|
||||
// Authentication with NDEF Tag Application master key (Authentication with key 0)
|
||||
res = mifare_desfire_authenticate (tags[i], 0, key_app);
|
||||
res = mifare_desfire_authenticate(tags[i], 0, key_app);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Authentication with NDEF Tag Application master key failed");
|
||||
errx(EXIT_FAILURE, "Authentication with NDEF Tag Application master key failed");
|
||||
|
||||
// Read Capability Container file E103
|
||||
uint8_t lendata[20]; // cf FIXME in mifare_desfire.c read_data()
|
||||
if (info.software.version_major==0)
|
||||
res = mifare_desfire_read_data (tags[i], 0x03, 0, 2, lendata);
|
||||
if (info.software.version_major == 0)
|
||||
res = mifare_desfire_read_data(tags[i], 0x03, 0, 2, lendata);
|
||||
else
|
||||
// There is no more relationship between DESFire FID and ISO FileID...
|
||||
// Let's assume it's in FID 01h as proposed in the spec
|
||||
res = mifare_desfire_read_data (tags[i], 0x01, 0, 2, lendata);
|
||||
res = mifare_desfire_read_data(tags[i], 0x01, 0, 2, lendata);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Read CC len failed");
|
||||
errx(EXIT_FAILURE, "Read CC len failed");
|
||||
uint16_t cclen = (((uint16_t) lendata[0]) << 8) + ((uint16_t) lendata[1]);
|
||||
if (cclen < 15)
|
||||
errx (EXIT_FAILURE, "CC too short IMHO");
|
||||
if (!(cc_data = malloc(cclen+20))) // cf FIXME in mifare_desfire.c read_data()
|
||||
errx (EXIT_FAILURE, "malloc");
|
||||
if (info.software.version_major==0)
|
||||
res = mifare_desfire_read_data (tags[i], 0x03, 0, cclen, cc_data);
|
||||
errx(EXIT_FAILURE, "CC too short IMHO");
|
||||
if (!(cc_data = malloc(cclen + 20))) // cf FIXME in mifare_desfire.c read_data()
|
||||
errx(EXIT_FAILURE, "malloc");
|
||||
if (info.software.version_major == 0)
|
||||
res = mifare_desfire_read_data(tags[i], 0x03, 0, cclen, cc_data);
|
||||
else
|
||||
res = mifare_desfire_read_data (tags[i], 0x01, 0, cclen, cc_data);
|
||||
res = mifare_desfire_read_data(tags[i], 0x01, 0, cclen, cc_data);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Read CC data failed");
|
||||
errx(EXIT_FAILURE, "Read CC data failed");
|
||||
// Search NDEF File Control TLV
|
||||
uint8_t off = 7;
|
||||
while (((off+7) < cclen) && (cc_data[off] != 0x04)) {
|
||||
while (((off + 7) < cclen) && (cc_data[off] != 0x04)) {
|
||||
// Skip TLV
|
||||
off += cc_data[off+1] + 2;
|
||||
off += cc_data[off + 1] + 2;
|
||||
}
|
||||
if (off+7 >= cclen)
|
||||
errx (EXIT_FAILURE, "CC does not contain expected NDEF File Control TLV");
|
||||
if (cc_data[off+2] != 0xE1)
|
||||
errx (EXIT_FAILURE, "Unknown NDEF File reference in CC");
|
||||
if (off + 7 >= cclen)
|
||||
errx(EXIT_FAILURE, "CC does not contain expected NDEF File Control TLV");
|
||||
if (cc_data[off + 2] != 0xE1)
|
||||
errx(EXIT_FAILURE, "Unknown NDEF File reference in CC");
|
||||
uint8_t file_no;
|
||||
if (info.software.version_major==0)
|
||||
file_no = cc_data[off+3];
|
||||
if (info.software.version_major == 0)
|
||||
file_no = cc_data[off + 3];
|
||||
else
|
||||
// There is no more relationship between DESFire FID and ISO FileID...
|
||||
// Let's assume it's in FID 02h as proposed in the spec
|
||||
file_no = 2;
|
||||
uint16_t ndefmaxlen = (((uint16_t) cc_data[off+4]) << 8) + ((uint16_t) cc_data[off+5]);
|
||||
fprintf (message_stream, "Max NDEF size: %i bytes\n", ndefmaxlen);
|
||||
if (!(ndef_msg = malloc(ndefmaxlen+20))) // cf FIXME in mifare_desfire.c read_data()
|
||||
errx (EXIT_FAILURE, "malloc");
|
||||
uint16_t ndefmaxlen = (((uint16_t) cc_data[off + 4]) << 8) + ((uint16_t) cc_data[off + 5]);
|
||||
fprintf(message_stream, "Max NDEF size: %i bytes\n", ndefmaxlen);
|
||||
if (!(ndef_msg = malloc(ndefmaxlen + 20))) // cf FIXME in mifare_desfire.c read_data()
|
||||
errx(EXIT_FAILURE, "malloc");
|
||||
|
||||
res = mifare_desfire_read_data (tags[i], file_no, 0, 2, lendata);
|
||||
res = mifare_desfire_read_data(tags[i], file_no, 0, 2, lendata);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Read NDEF len failed");
|
||||
errx(EXIT_FAILURE, "Read NDEF len failed");
|
||||
ndef_msg_len = (((uint16_t) lendata[0]) << 8) + ((uint16_t) lendata[1]);
|
||||
fprintf (message_stream, "NDEF size: %i bytes\n", ndef_msg_len);
|
||||
fprintf(message_stream, "NDEF size: %i bytes\n", ndef_msg_len);
|
||||
if (ndef_msg_len + 2 > ndefmaxlen)
|
||||
errx (EXIT_FAILURE, "Declared NDEF size larger than max NDEF size");
|
||||
res = mifare_desfire_read_data (tags[i], file_no, 2, ndef_msg_len, ndef_msg);
|
||||
errx(EXIT_FAILURE, "Declared NDEF size larger than max NDEF size");
|
||||
res = mifare_desfire_read_data(tags[i], file_no, 2, ndef_msg_len, ndef_msg);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Read data failed");
|
||||
if (fwrite (ndef_msg, 1, ndef_msg_len, ndef_stream) != ndef_msg_len)
|
||||
errx (EXIT_FAILURE, "Write to file failed");
|
||||
free (cc_data);
|
||||
free (ndef_msg);
|
||||
mifare_desfire_key_free (key_app);
|
||||
errx(EXIT_FAILURE, "Read data failed");
|
||||
if (fwrite(ndef_msg, 1, ndef_msg_len, ndef_stream) != ndef_msg_len)
|
||||
errx(EXIT_FAILURE, "Write to file failed");
|
||||
free(cc_data);
|
||||
free(ndef_msg);
|
||||
mifare_desfire_key_free(key_app);
|
||||
|
||||
mifare_desfire_disconnect (tags[i]);
|
||||
mifare_desfire_disconnect(tags[i]);
|
||||
}
|
||||
free (tag_uid);
|
||||
free(tag_uid);
|
||||
}
|
||||
freefare_free_tags (tags);
|
||||
nfc_close (device);
|
||||
freefare_free_tags(tags);
|
||||
nfc_close(device);
|
||||
}
|
||||
nfc_exit (context);
|
||||
exit (error);
|
||||
nfc_exit(context);
|
||||
exit(error);
|
||||
}
|
||||
|
|
|
@ -62,12 +62,12 @@ struct {
|
|||
static void
|
||||
usage(char *progname)
|
||||
{
|
||||
fprintf (stderr, "This application writes a NDEF payload into a Mifare DESFire formatted as NFC Forum Type 4 Tag.\n");
|
||||
fprintf (stderr, "usage: %s [-y] -i FILE [-k 11223344AABBCCDD]\n", progname);
|
||||
fprintf (stderr, "\nOptions:\n");
|
||||
fprintf (stderr, " -y Do not ask for confirmation\n");
|
||||
fprintf (stderr, " -i Use FILE as NDEF message to write on card (\"-\" = stdin)\n");
|
||||
fprintf (stderr, " -k Provide another NDEF Tag Application key than the default one\n");
|
||||
fprintf(stderr, "This application writes a NDEF payload into a Mifare DESFire formatted as NFC Forum Type 4 Tag.\n");
|
||||
fprintf(stderr, "usage: %s [-y] -i FILE [-k 11223344AABBCCDD]\n", progname);
|
||||
fprintf(stderr, "\nOptions:\n");
|
||||
fprintf(stderr, " -y Do not ask for confirmation\n");
|
||||
fprintf(stderr, " -i Use FILE as NDEF message to write on card (\"-\" = stdin)\n");
|
||||
fprintf(stderr, " -k Provide another NDEF Tag Application key than the default one\n");
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -79,146 +79,146 @@ main(int argc, char *argv[])
|
|||
FreefareTag *tags = NULL;
|
||||
|
||||
char *ndef_input = NULL;
|
||||
while ((ch = getopt (argc, argv, "hyi:k:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
exit (EXIT_SUCCESS);
|
||||
break;
|
||||
case 'y':
|
||||
write_options.interactive = false;
|
||||
break;
|
||||
case 'i':
|
||||
ndef_input = optarg;
|
||||
break;
|
||||
case 'k':
|
||||
if (strlen(optarg) != 16) {
|
||||
usage(argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
uint64_t n = strtoull(optarg, NULL, 16);
|
||||
int i;
|
||||
for (i=7; i>=0; i--) {
|
||||
key_data_app[i] = (uint8_t) n;
|
||||
n >>= 8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
while ((ch = getopt(argc, argv, "hyi:k:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'y':
|
||||
write_options.interactive = false;
|
||||
break;
|
||||
case 'i':
|
||||
ndef_input = optarg;
|
||||
break;
|
||||
case 'k':
|
||||
if (strlen(optarg) != 16) {
|
||||
usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
uint64_t n = strtoull(optarg, NULL, 16);
|
||||
int i;
|
||||
for (i = 7; i >= 0; i--) {
|
||||
key_data_app[i] = (uint8_t) n;
|
||||
n >>= 8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
// Remaining args, if any, are in argv[optind .. (argc-1)]
|
||||
|
||||
if (ndef_input == NULL) {
|
||||
ndef_msg_len = sizeof(ndef_default_msg) + 2;
|
||||
if (!(ndef_msg = malloc (ndef_msg_len))) {
|
||||
err (EXIT_FAILURE, "malloc");
|
||||
}
|
||||
ndef_msg[0] = (uint8_t) ((ndef_msg_len - 2) >> 8);
|
||||
ndef_msg[1] = (uint8_t) (ndef_msg_len - 2);
|
||||
memcpy(ndef_msg + 2, ndef_default_msg, ndef_msg_len - 2);
|
||||
ndef_msg_len = sizeof(ndef_default_msg) + 2;
|
||||
if (!(ndef_msg = malloc(ndef_msg_len))) {
|
||||
err(EXIT_FAILURE, "malloc");
|
||||
}
|
||||
ndef_msg[0] = (uint8_t)((ndef_msg_len - 2) >> 8);
|
||||
ndef_msg[1] = (uint8_t)(ndef_msg_len - 2);
|
||||
memcpy(ndef_msg + 2, ndef_default_msg, ndef_msg_len - 2);
|
||||
} else {
|
||||
FILE* ndef_stream = NULL;
|
||||
if ((strlen (ndef_input) == 1) && (ndef_input[0] == '-')) {
|
||||
// FIXME stdin as input have to be readed and buffered in ndef_msg
|
||||
FILE *ndef_stream = NULL;
|
||||
if ((strlen(ndef_input) == 1) && (ndef_input[0] == '-')) {
|
||||
// FIXME stdin as input have to be readed and buffered in ndef_msg
|
||||
ndef_stream = stdin;
|
||||
fprintf (stderr, "stdin as NDEF is not implemented");
|
||||
exit (EXIT_FAILURE);
|
||||
fprintf(stderr, "stdin as NDEF is not implemented");
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
ndef_stream = fopen(ndef_input, "rb");
|
||||
if (!ndef_stream) {
|
||||
fprintf (stderr, "Could not open file %s.\n", ndef_input);
|
||||
exit (EXIT_FAILURE);
|
||||
fprintf(stderr, "Could not open file %s.\n", ndef_input);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
fseek(ndef_stream, 0L, SEEK_END);
|
||||
ndef_msg_len = ftell(ndef_stream) + 2;
|
||||
fseek(ndef_stream, 0L, SEEK_SET);
|
||||
fseek(ndef_stream, 0L, SEEK_SET);
|
||||
|
||||
if (!(ndef_msg = malloc (ndef_msg_len))) {
|
||||
err (EXIT_FAILURE, "malloc");
|
||||
if (!(ndef_msg = malloc(ndef_msg_len))) {
|
||||
err(EXIT_FAILURE, "malloc");
|
||||
}
|
||||
ndef_msg[0] = (uint8_t) ((ndef_msg_len - 2) >> 8);
|
||||
ndef_msg[1] = (uint8_t) (ndef_msg_len - 2);
|
||||
if (fread (ndef_msg + 2, 1, ndef_msg_len - 2, ndef_stream) != ndef_msg_len - 2) {
|
||||
fprintf (stderr, "Could not read NDEF from file: %s\n", ndef_input);
|
||||
fclose (ndef_stream);
|
||||
exit (EXIT_FAILURE);
|
||||
ndef_msg[0] = (uint8_t)((ndef_msg_len - 2) >> 8);
|
||||
ndef_msg[1] = (uint8_t)(ndef_msg_len - 2);
|
||||
if (fread(ndef_msg + 2, 1, ndef_msg_len - 2, ndef_stream) != ndef_msg_len - 2) {
|
||||
fprintf(stderr, "Could not read NDEF from file: %s\n", ndef_input);
|
||||
fclose(ndef_stream);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
fclose (ndef_stream);
|
||||
fclose(ndef_stream);
|
||||
}
|
||||
}
|
||||
printf ("NDEF file is %zu bytes long.\n", ndef_msg_len);
|
||||
printf("NDEF file is %zu bytes long.\n", ndef_msg_len);
|
||||
|
||||
nfc_connstring devices[8];
|
||||
size_t device_count;
|
||||
|
||||
nfc_context *context;
|
||||
nfc_init (&context);
|
||||
nfc_init(&context);
|
||||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
errx (EXIT_FAILURE, "No NFC device found.");
|
||||
errx(EXIT_FAILURE, "No NFC device found.");
|
||||
|
||||
for (size_t d = 0; d < device_count; d++) {
|
||||
device = nfc_open (context, devices[d]);
|
||||
device = nfc_open(context, devices[d]);
|
||||
|
||||
if (!device) {
|
||||
warnx ("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
if (!device) {
|
||||
warnx("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
tags = freefare_get_tags(device);
|
||||
if (!tags) {
|
||||
nfc_close (device);
|
||||
errx (EXIT_FAILURE, "Error listing tags.");
|
||||
nfc_close(device);
|
||||
errx(EXIT_FAILURE, "Error listing tags.");
|
||||
}
|
||||
|
||||
for (int i = 0; (!error) && tags[i]; i++) {
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type (tags[i]))
|
||||
if (MIFARE_DESFIRE != freefare_get_tag_type(tags[i]))
|
||||
continue;
|
||||
|
||||
char *tag_uid = freefare_get_tag_uid (tags[i]);
|
||||
char *tag_uid = freefare_get_tag_uid(tags[i]);
|
||||
char buffer[BUFSIZ];
|
||||
|
||||
printf ("Found %s with UID %s. ", freefare_get_tag_friendly_name (tags[i]), tag_uid);
|
||||
printf("Found %s with UID %s. ", freefare_get_tag_friendly_name(tags[i]), tag_uid);
|
||||
bool write_ndef = true;
|
||||
if (write_options.interactive) {
|
||||
printf ("Write NDEF [yN] ");
|
||||
fgets (buffer, BUFSIZ, stdin);
|
||||
printf("Write NDEF [yN] ");
|
||||
fgets(buffer, BUFSIZ, stdin);
|
||||
write_ndef = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
|
||||
} else {
|
||||
printf ("\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (write_ndef) {
|
||||
int res;
|
||||
|
||||
res = mifare_desfire_connect (tags[i]);
|
||||
res = mifare_desfire_connect(tags[i]);
|
||||
if (res < 0) {
|
||||
warnx ("Can't connect to Mifare DESFire target.");
|
||||
warnx("Can't connect to Mifare DESFire target.");
|
||||
error = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
// We've to track DESFire version as NDEF mapping is different
|
||||
struct mifare_desfire_version_info info;
|
||||
res = mifare_desfire_get_version (tags[i], &info);
|
||||
res = mifare_desfire_get_version(tags[i], &info);
|
||||
if (res < 0) {
|
||||
freefare_perror (tags[i], "mifare_desfire_get_version");
|
||||
freefare_perror(tags[i], "mifare_desfire_get_version");
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
MifareDESFireKey key_app;
|
||||
key_app = mifare_desfire_des_key_new_with_version (key_data_app);
|
||||
key_app = mifare_desfire_des_key_new_with_version(key_data_app);
|
||||
|
||||
// Mifare DESFire SelectApplication (Select application)
|
||||
MifareDESFireAID aid;
|
||||
if (info.software.version_major==0)
|
||||
if (info.software.version_major == 0)
|
||||
aid = mifare_desfire_aid_new(0xEEEE10);
|
||||
else
|
||||
// There is no more relationship between DESFire AID and ISO AID...
|
||||
|
@ -227,74 +227,74 @@ main(int argc, char *argv[])
|
|||
|
||||
res = mifare_desfire_select_application(tags[i], aid);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Application selection failed. Try mifare-desfire-create-ndef before running %s.", argv[0]);
|
||||
free (aid);
|
||||
errx(EXIT_FAILURE, "Application selection failed. Try mifare-desfire-create-ndef before running %s.", argv[0]);
|
||||
free(aid);
|
||||
|
||||
// Authentication with NDEF Tag Application master key (Authentication with key 0)
|
||||
res = mifare_desfire_authenticate (tags[i], 0, key_app);
|
||||
res = mifare_desfire_authenticate(tags[i], 0, key_app);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Authentication with NDEF Tag Application master key failed");
|
||||
errx(EXIT_FAILURE, "Authentication with NDEF Tag Application master key failed");
|
||||
|
||||
// Read Capability Container file E103
|
||||
uint8_t lendata[20]; // cf FIXME in mifare_desfire.c read_data()
|
||||
|
||||
if (info.software.version_major==0)
|
||||
res = mifare_desfire_read_data (tags[i], 0x03, 0, 2, lendata);
|
||||
if (info.software.version_major == 0)
|
||||
res = mifare_desfire_read_data(tags[i], 0x03, 0, 2, lendata);
|
||||
else
|
||||
// There is no more relationship between DESFire FID and ISO FileID...
|
||||
// Let's assume it's in FID 01h as proposed in the spec
|
||||
res = mifare_desfire_read_data (tags[i], 0x01, 0, 2, lendata);
|
||||
res = mifare_desfire_read_data(tags[i], 0x01, 0, 2, lendata);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Read CC len failed");
|
||||
errx(EXIT_FAILURE, "Read CC len failed");
|
||||
uint16_t cclen = (((uint16_t) lendata[0]) << 8) + ((uint16_t) lendata[1]);
|
||||
if (cclen < 15)
|
||||
errx (EXIT_FAILURE, "CC too short IMHO");
|
||||
errx(EXIT_FAILURE, "CC too short IMHO");
|
||||
if (!(cc_data = malloc(cclen + 20))) // cf FIXME in mifare_desfire.c read_data()
|
||||
errx (EXIT_FAILURE, "malloc");
|
||||
if (info.software.version_major==0)
|
||||
res = mifare_desfire_read_data (tags[i], 0x03, 0, cclen, cc_data);
|
||||
errx(EXIT_FAILURE, "malloc");
|
||||
if (info.software.version_major == 0)
|
||||
res = mifare_desfire_read_data(tags[i], 0x03, 0, cclen, cc_data);
|
||||
else
|
||||
res = mifare_desfire_read_data (tags[i], 0x01, 0, cclen, cc_data);
|
||||
res = mifare_desfire_read_data(tags[i], 0x01, 0, cclen, cc_data);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, "Read CC data failed");
|
||||
errx(EXIT_FAILURE, "Read CC data failed");
|
||||
// Search NDEF File Control TLV
|
||||
uint8_t off = 7;
|
||||
while (((off+7) < cclen) && (cc_data[off] != 0x04)) {
|
||||
while (((off + 7) < cclen) && (cc_data[off] != 0x04)) {
|
||||
// Skip TLV
|
||||
off += cc_data[off+1] + 2;
|
||||
off += cc_data[off + 1] + 2;
|
||||
}
|
||||
if (off+7 >= cclen)
|
||||
errx (EXIT_FAILURE, "CC does not contain expected NDEF File Control TLV");
|
||||
if (cc_data[off+2] != 0xE1)
|
||||
errx (EXIT_FAILURE, "Unknown NDEF File reference in CC");
|
||||
if (off + 7 >= cclen)
|
||||
errx(EXIT_FAILURE, "CC does not contain expected NDEF File Control TLV");
|
||||
if (cc_data[off + 2] != 0xE1)
|
||||
errx(EXIT_FAILURE, "Unknown NDEF File reference in CC");
|
||||
uint8_t file_no;
|
||||
if (info.software.version_major==0)
|
||||
file_no = cc_data[off+3];
|
||||
if (info.software.version_major == 0)
|
||||
file_no = cc_data[off + 3];
|
||||
else
|
||||
// There is no more relationship between DESFire FID and ISO FileID...
|
||||
// Let's assume it's in FID 02h as proposed in the spec
|
||||
file_no = 2;
|
||||
uint16_t ndefmaxlen = (((uint16_t) cc_data[off+4]) << 8) + ((uint16_t) cc_data[off+5]);
|
||||
fprintf (stdout, "Max NDEF size: %i bytes\n", ndefmaxlen);
|
||||
uint16_t ndefmaxlen = (((uint16_t) cc_data[off + 4]) << 8) + ((uint16_t) cc_data[off + 5]);
|
||||
fprintf(stdout, "Max NDEF size: %i bytes\n", ndefmaxlen);
|
||||
if (ndef_msg_len > ndefmaxlen)
|
||||
errx (EXIT_FAILURE, "Supplied NDEF larger than max NDEF size");
|
||||
errx(EXIT_FAILURE, "Supplied NDEF larger than max NDEF size");
|
||||
|
||||
//Mifare DESFire WriteData to write the content of the NDEF File with NLEN equal to NDEF Message length and NDEF Message
|
||||
res = mifare_desfire_write_data(tags[i], file_no, 0, ndef_msg_len, (uint8_t *) ndef_msg);
|
||||
if (res < 0)
|
||||
errx (EXIT_FAILURE, " Write data failed");
|
||||
errx(EXIT_FAILURE, " Write data failed");
|
||||
|
||||
free(cc_data);
|
||||
mifare_desfire_key_free (key_app);
|
||||
mifare_desfire_key_free(key_app);
|
||||
|
||||
mifare_desfire_disconnect (tags[i]);
|
||||
mifare_desfire_disconnect(tags[i]);
|
||||
}
|
||||
free (tag_uid);
|
||||
free(tag_uid);
|
||||
}
|
||||
free (ndef_msg);
|
||||
freefare_free_tags (tags);
|
||||
nfc_close (device);
|
||||
free(ndef_msg);
|
||||
freefare_free_tags(tags);
|
||||
nfc_close(device);
|
||||
}
|
||||
nfc_exit (context);
|
||||
exit (error);
|
||||
nfc_exit(context);
|
||||
exit(error);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2012, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -22,41 +22,41 @@
|
|||
#include <freefare.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int error = EXIT_SUCCESS;
|
||||
nfc_device *device = NULL;
|
||||
FreefareTag *tags = NULL;
|
||||
|
||||
if (argc > 1)
|
||||
errx (EXIT_FAILURE, "usage: %s", argv[0]);
|
||||
errx(EXIT_FAILURE, "usage: %s", argv[0]);
|
||||
|
||||
nfc_connstring devices[8];
|
||||
size_t device_count;
|
||||
|
||||
nfc_context *context;
|
||||
nfc_init (&context);
|
||||
nfc_init(&context);
|
||||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices (context, devices, sizeof (devices) / sizeof (*devices));
|
||||
device_count = nfc_list_devices(context, devices, sizeof(devices) / sizeof(*devices));
|
||||
if (device_count <= 0)
|
||||
errx (EXIT_FAILURE, "No NFC device found");
|
||||
errx(EXIT_FAILURE, "No NFC device found");
|
||||
|
||||
for (size_t d = 0; d < device_count; d++) {
|
||||
if (!(device = nfc_open (context, devices[d]))) {
|
||||
warnx ("nfc_open() failed.");
|
||||
if (!(device = nfc_open(context, devices[d]))) {
|
||||
warnx("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(tags = freefare_get_tags (device))) {
|
||||
nfc_close (device);
|
||||
errx (EXIT_FAILURE, "Error listing tags.");
|
||||
if (!(tags = freefare_get_tags(device))) {
|
||||
nfc_close(device);
|
||||
errx(EXIT_FAILURE, "Error listing tags.");
|
||||
}
|
||||
|
||||
for (int i = 0; (!error) && tags[i]; i++) {
|
||||
switch (freefare_get_tag_type (tags[i])) {
|
||||
switch (freefare_get_tag_type(tags[i])) {
|
||||
case MIFARE_ULTRALIGHT:
|
||||
case MIFARE_ULTRALIGHT_C:
|
||||
break;
|
||||
|
@ -64,28 +64,28 @@ main (int argc, char *argv[])
|
|||
continue;
|
||||
}
|
||||
|
||||
char *tag_uid = freefare_get_tag_uid (tags[i]);
|
||||
printf ("Tag with UID %s is a %s\n", tag_uid, freefare_get_tag_friendly_name (tags[i]));
|
||||
if (freefare_get_tag_type (tags[i]) == MIFARE_ULTRALIGHT_C) {
|
||||
char *tag_uid = freefare_get_tag_uid(tags[i]);
|
||||
printf("Tag with UID %s is a %s\n", tag_uid, freefare_get_tag_friendly_name(tags[i]));
|
||||
if (freefare_get_tag_type(tags[i]) == MIFARE_ULTRALIGHT_C) {
|
||||
FreefareTag tag = tags[i];
|
||||
int res;
|
||||
MifareDESFireKey key;
|
||||
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);
|
||||
if (mifare_ultralight_connect (tag) < 0)
|
||||
errx (EXIT_FAILURE, "Error connecting to tag.");
|
||||
res = mifare_ultralightc_authenticate (tag, key);
|
||||
printf ("Authentication with default key: %s\n", res ? "fail" : "success");
|
||||
mifare_desfire_key_free (key);
|
||||
mifare_ultralight_disconnect (tag);
|
||||
}
|
||||
free (tag_uid);
|
||||
key = mifare_desfire_3des_key_new(key1_3des_data);
|
||||
if (mifare_ultralight_connect(tag) < 0)
|
||||
errx(EXIT_FAILURE, "Error connecting to tag.");
|
||||
res = mifare_ultralightc_authenticate(tag, key);
|
||||
printf("Authentication with default key: %s\n", res ? "fail" : "success");
|
||||
mifare_desfire_key_free(key);
|
||||
mifare_ultralight_disconnect(tag);
|
||||
}
|
||||
free(tag_uid);
|
||||
}
|
||||
|
||||
freefare_free_tags (tags);
|
||||
nfc_close (device);
|
||||
freefare_free_tags(tags);
|
||||
nfc_close(device);
|
||||
}
|
||||
|
||||
nfc_exit (context);
|
||||
nfc_exit(context);
|
||||
exit(error);
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ main(int argc, char *argv[])
|
|||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices (context, devices, sizeof (devices) / sizeof (*devices));
|
||||
device_count = nfc_list_devices(context, devices, sizeof(devices) / sizeof(*devices));
|
||||
if (device_count <= 0)
|
||||
errx(EXIT_FAILURE, "No NFC device found");
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ main(int argc, char *argv[])
|
|||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices(context, devices, sizeof (devices) / sizeof (*devices));
|
||||
device_count = nfc_list_devices(context, devices, sizeof(devices) / sizeof(*devices));
|
||||
if (device_count <= 0)
|
||||
errx(EXIT_FAILURE, "No NFC device found");
|
||||
|
||||
|
@ -71,14 +71,14 @@ main(int argc, char *argv[])
|
|||
if (ntag21x_connect(tag) < 0)
|
||||
errx(EXIT_FAILURE, "Error connecting to tag.");
|
||||
|
||||
uint8_t pwd[4] = {0xff,0xff,0xff,0xff};
|
||||
uint8_t pack[2] = {0xaa,0xaa};
|
||||
uint8_t pack_old[2] = {0x00,0x00};
|
||||
uint8_t pwd[4] = {0xff, 0xff, 0xff, 0xff};
|
||||
uint8_t pack[2] = {0xaa, 0xaa};
|
||||
uint8_t pack_old[2] = {0x00, 0x00};
|
||||
|
||||
NTAG21xKey key;
|
||||
NTAG21xKey key_old;
|
||||
key = ntag21x_key_new(pwd,pack); // Creating key
|
||||
key_old = ntag21x_key_new(pwd,pack_old); // Creating key
|
||||
key = ntag21x_key_new(pwd, pack); // Creating key
|
||||
key_old = ntag21x_key_new(pwd, pack_old); // Creating key
|
||||
|
||||
uint8_t auth0 = 0x00; // Buffer for auth0 byte
|
||||
|
||||
|
@ -89,48 +89,48 @@ main(int argc, char *argv[])
|
|||
MUST do, because here we are recognizing tag subtype (NTAG213,NTAG215,NTAG216), and gathering all parameters
|
||||
*/
|
||||
res = ntag21x_get_info(tag);
|
||||
if(res < 0) {
|
||||
if (res < 0) {
|
||||
printf("Error getting info from tag\n");
|
||||
break;
|
||||
}
|
||||
// Authenticate with tag
|
||||
res = ntag21x_authenticate(tag,key);
|
||||
if(res < 0) {
|
||||
res = ntag21x_authenticate(tag, key);
|
||||
if (res < 0) {
|
||||
printf("Error getting info from tag\n");
|
||||
break;
|
||||
}
|
||||
// Get auth byte from tag
|
||||
res = ntag21x_get_auth(tag,&auth0);
|
||||
if(res < 0) {
|
||||
res = ntag21x_get_auth(tag, &auth0);
|
||||
if (res < 0) {
|
||||
printf("Error getting auth0 byte from tag\n");
|
||||
break;
|
||||
}
|
||||
printf("Old auth0: %#02x\n",auth0);
|
||||
printf("Old auth0: %#02x\n", auth0);
|
||||
// Set old key
|
||||
res = ntag21x_set_key(tag,key_old);
|
||||
if(res < 0) {
|
||||
res = ntag21x_set_key(tag, key_old);
|
||||
if (res < 0) {
|
||||
printf("Error setting key tag\n");
|
||||
break;
|
||||
}
|
||||
// Disable password protection (when auth0 byte > last page)
|
||||
res = ntag21x_set_auth(tag,0xff);
|
||||
if(res<0) {
|
||||
res = ntag21x_set_auth(tag, 0xff);
|
||||
if (res < 0) {
|
||||
printf("Error setting auth0 byte \n");
|
||||
break;
|
||||
}
|
||||
// Disable read & write pwd protection -> (default: write only protection)
|
||||
res = ntag21x_access_disable(tag,NTAG_PROT);
|
||||
if(res < 0) {
|
||||
res = ntag21x_access_disable(tag, NTAG_PROT);
|
||||
if (res < 0) {
|
||||
printf("Error setting access byte \n");
|
||||
break;
|
||||
}
|
||||
// Get auth byte from tag
|
||||
res = ntag21x_get_auth(tag,&auth0);
|
||||
if(res < 0) {
|
||||
res = ntag21x_get_auth(tag, &auth0);
|
||||
if (res < 0) {
|
||||
printf("Error getting auth0 byte from tag\n");
|
||||
break;
|
||||
}
|
||||
printf("New auth0: %#02x\n",auth0);
|
||||
printf("New auth0: %#02x\n", auth0);
|
||||
}
|
||||
|
||||
ntag21x_disconnect(tag);
|
||||
|
|
|
@ -36,22 +36,22 @@ main(int argc, char *argv[])
|
|||
size_t device_count;
|
||||
|
||||
nfc_context *context;
|
||||
nfc_init (&context);
|
||||
nfc_init(&context);
|
||||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices (context, devices, sizeof (devices) / sizeof (*devices));
|
||||
device_count = nfc_list_devices(context, devices, sizeof(devices) / sizeof(*devices));
|
||||
if (device_count <= 0)
|
||||
errx(EXIT_FAILURE, "No NFC device found");
|
||||
|
||||
for (size_t d = 0; d < device_count; d++) {
|
||||
if (!(device = nfc_open (context, devices[d]))) {
|
||||
if (!(device = nfc_open(context, devices[d]))) {
|
||||
warnx("nfc_open() failed.");
|
||||
error = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(tags = freefare_get_tags (device))) {
|
||||
if (!(tags = freefare_get_tags(device))) {
|
||||
nfc_close(device);
|
||||
errx(EXIT_FAILURE, "Error listing tags.");
|
||||
}
|
||||
|
@ -68,14 +68,14 @@ main(int argc, char *argv[])
|
|||
printf("Tag with UID %s is a %s\n", tag_uid, freefare_get_tag_friendly_name(tags[i]));
|
||||
FreefareTag tag = tags[i];
|
||||
int res;
|
||||
if (ntag21x_connect (tag) < 0)
|
||||
if (ntag21x_connect(tag) < 0)
|
||||
errx(EXIT_FAILURE, "Error connecting to tag.");
|
||||
|
||||
uint8_t pwd[4] = {0xff,0xff,0xff,0xff};
|
||||
uint8_t pack[2] = {0xaa,0xaa};
|
||||
uint8_t pwd[4] = {0xff, 0xff, 0xff, 0xff};
|
||||
uint8_t pack[2] = {0xaa, 0xaa};
|
||||
|
||||
NTAG21xKey key;
|
||||
key = ntag21x_key_new(pwd,pack); // Creating key
|
||||
key = ntag21x_key_new(pwd, pack); // Creating key
|
||||
|
||||
uint8_t auth0 = 0x00; // Buffer for auth0 byte
|
||||
uint8_t authlim = 0x00;
|
||||
|
@ -86,57 +86,57 @@ main(int argc, char *argv[])
|
|||
MUST do, because here we are recognizing tag subtype (NTAG213,NTAG215,NTAG216), and gathering all parameters
|
||||
*/
|
||||
res = ntag21x_get_info(tag);
|
||||
if(res < 0) {
|
||||
if (res < 0) {
|
||||
printf("Error getting info from tag\n");
|
||||
break;
|
||||
}
|
||||
// Get auth byte from tag
|
||||
res = ntag21x_get_auth(tag,&auth0);
|
||||
if(res < 0) {
|
||||
res = ntag21x_get_auth(tag, &auth0);
|
||||
if (res < 0) {
|
||||
printf("Error getting auth0 byte from tag\n");
|
||||
break;
|
||||
}
|
||||
printf("Old auth0: %#02x\n",auth0);
|
||||
res = ntag21x_get_authentication_limit(tag,&authlim);
|
||||
if(res < 0) {
|
||||
printf("Old auth0: %#02x\n", auth0);
|
||||
res = ntag21x_get_authentication_limit(tag, &authlim);
|
||||
if (res < 0) {
|
||||
printf("Error getting auth0 byte from tag\n");
|
||||
break;
|
||||
}
|
||||
printf("Authlim: %#02x\n",authlim);
|
||||
printf("Authlim: %#02x\n", authlim);
|
||||
// Check if auth is required to set pwd and pack
|
||||
if(auth0 < ntag21x_get_last_page(tag) - 2) { // Check if last 2 pages are protected
|
||||
if (auth0 < ntag21x_get_last_page(tag) - 2) { // Check if last 2 pages are protected
|
||||
printf("Error: pwd and PACK sections are protected with unknown password\n");
|
||||
break;
|
||||
}
|
||||
// Set key
|
||||
res = ntag21x_set_key(tag,key);
|
||||
if(res < 0) {
|
||||
res = ntag21x_set_key(tag, key);
|
||||
if (res < 0) {
|
||||
printf("Error setting key tag\n");
|
||||
break;
|
||||
}
|
||||
// Protect last 6 pages !! It can be hacked if you don't protect last 4 pages where auth0 byte is located
|
||||
res = ntag21x_set_auth(tag,ntag21x_get_last_page(tag)-5);
|
||||
if(res < 0) {
|
||||
res = ntag21x_set_auth(tag, ntag21x_get_last_page(tag) - 5);
|
||||
if (res < 0) {
|
||||
printf("Error setting auth0 byte \n");
|
||||
break;
|
||||
}
|
||||
// Enable read & write pwd protection (default: write only protection)
|
||||
res = ntag21x_access_enable(tag,NTAG_PROT);
|
||||
if(res < 0) {
|
||||
res = ntag21x_access_enable(tag, NTAG_PROT);
|
||||
if (res < 0) {
|
||||
printf("Error setting access byte \n");
|
||||
break;
|
||||
}
|
||||
// Get auth byte from tag
|
||||
res = ntag21x_get_auth(tag,&auth0);
|
||||
if(res < 0) {
|
||||
res = ntag21x_get_auth(tag, &auth0);
|
||||
if (res < 0) {
|
||||
printf("Error getting auth0 byte from tag\n");
|
||||
break;
|
||||
}
|
||||
printf("New auth0: %#02x\n",auth0);
|
||||
printf("New auth0: %#02x\n", auth0);
|
||||
}
|
||||
ntag21x_disconnect (tag);
|
||||
ntag21x_disconnect(tag);
|
||||
ntag21x_key_free(key); // Delete key
|
||||
free (tag_uid);
|
||||
free(tag_uid);
|
||||
}
|
||||
freefare_free_tags(tags);
|
||||
nfc_close(device);
|
||||
|
|
|
@ -40,7 +40,7 @@ main(int argc, char *argv[])
|
|||
if (context == NULL)
|
||||
errx(EXIT_FAILURE, "Unable to init libnfc (malloc)");
|
||||
|
||||
device_count = nfc_list_devices(context, devices, sizeof (devices) / sizeof (*devices));
|
||||
device_count = nfc_list_devices(context, devices, sizeof(devices) / sizeof(*devices));
|
||||
if (device_count <= 0)
|
||||
errx(EXIT_FAILURE, "No NFC device found");
|
||||
|
||||
|
@ -65,13 +65,13 @@ main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
char *tag_uid = freefare_get_tag_uid(tags[i]);
|
||||
printf("Tag with UID %s is a %s\n", tag_uid, freefare_get_tag_friendly_name (tags[i]));
|
||||
printf("Tag with UID %s is a %s\n", tag_uid, freefare_get_tag_friendly_name(tags[i]));
|
||||
FreefareTag tag = tags[i];
|
||||
int res;
|
||||
if (ntag21x_connect(tag) < 0)
|
||||
errx(EXIT_FAILURE, "Error connecting to tag.");
|
||||
|
||||
uint8_t data [4] = {0xfa,0xca,0xac,0xad}; // Data to write on tag
|
||||
uint8_t data [4] = {0xfa, 0xca, 0xac, 0xad}; // Data to write on tag
|
||||
uint8_t read[4]; // Buffer for reading data from tag
|
||||
|
||||
bool flag_match = true;
|
||||
|
@ -82,28 +82,28 @@ main(int argc, char *argv[])
|
|||
MUST do, because here we are recognizing tag subtype (NTAG213,NTAG215,NTAG216), and gathering all parameters
|
||||
*/
|
||||
res = ntag21x_get_info(tag);
|
||||
if(res < 0) {
|
||||
if (res < 0) {
|
||||
printf("Error getting info from tag\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// writing to tag 4 bytes on page 0x27 (check specs for NTAG21x before changing page number !!!)
|
||||
res = ntag21x_write(tag,0x27,data);
|
||||
if(res < 0) {
|
||||
res = ntag21x_write(tag, 0x27, data);
|
||||
if (res < 0) {
|
||||
printf("Error writing to tag\n");
|
||||
break;
|
||||
}
|
||||
res = ntag21x_fast_read4(tag,0x27,read); // Reading page from tag (4 bytes), you can also use ntag21x_read4 or ntag21x_read (16 bytes) or ntag21x_fast_read (start_page to end_page)
|
||||
if(res < 0) {
|
||||
res = ntag21x_fast_read4(tag, 0x27, read); // Reading page from tag (4 bytes), you can also use ntag21x_read4 or ntag21x_read (16 bytes) or ntag21x_fast_read (start_page to end_page)
|
||||
if (res < 0) {
|
||||
printf("Error reading tag\n");
|
||||
break;
|
||||
}
|
||||
for(int i=0;i < 4;i++) // Checking if we can read what we have written earlyer
|
||||
if(data[i] != read[i]) {
|
||||
for (int i = 0; i < 4; i++) // Checking if we can read what we have written earlyer
|
||||
if (data[i] != read[i]) {
|
||||
flag_match = false;
|
||||
break;
|
||||
}
|
||||
if(!flag_match)
|
||||
if (!flag_match)
|
||||
printf("Data don't match\n");
|
||||
else
|
||||
printf("Data match\n");
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2015, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -44,27 +44,27 @@
|
|||
#define MAX_BLOCK_COUNT 8
|
||||
|
||||
inline static
|
||||
ssize_t felica_transceive (FreefareTag tag, uint8_t *data_in, uint8_t *data_out, size_t data_out_length)
|
||||
ssize_t felica_transceive(FreefareTag tag, uint8_t *data_in, uint8_t *data_out, size_t data_out_length)
|
||||
{
|
||||
DEBUG_XFER (data_in, data_in[0], "===> ");
|
||||
ssize_t res = nfc_initiator_transceive_bytes (tag->device, data_in, data_in[0], data_out, data_out_length, 0);
|
||||
DEBUG_XFER (data_out, res, "<=== ");
|
||||
DEBUG_XFER(data_in, data_in[0], "===> ");
|
||||
ssize_t res = nfc_initiator_transceive_bytes(tag->device, data_in, data_in[0], data_out, data_out_length, 0);
|
||||
DEBUG_XFER(data_out, res, "<=== ");
|
||||
return res;
|
||||
}
|
||||
|
||||
bool
|
||||
felica_taste (nfc_device *device, nfc_target target)
|
||||
felica_taste(nfc_device *device, nfc_target target)
|
||||
{
|
||||
(void) device;
|
||||
return target.nm.nmt == NMT_FELICA;
|
||||
}
|
||||
|
||||
FreefareTag
|
||||
felica_tag_new (nfc_device *device, nfc_target target)
|
||||
felica_tag_new(nfc_device *device, nfc_target target)
|
||||
{
|
||||
FreefareTag tag;
|
||||
|
||||
if ((tag = malloc (sizeof (struct felica_tag)))) {
|
||||
if ((tag = malloc(sizeof(struct felica_tag)))) {
|
||||
tag->type = FELICA;
|
||||
tag->free_tag = felica_tag_free;
|
||||
tag->device = device;
|
||||
|
@ -76,18 +76,18 @@ felica_tag_new (nfc_device *device, nfc_target target)
|
|||
}
|
||||
|
||||
void
|
||||
felica_tag_free (FreefareTag tag)
|
||||
felica_tag_free(FreefareTag tag)
|
||||
{
|
||||
free (tag);
|
||||
free(tag);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ssize_t
|
||||
felica_read_ex (FreefareTag tag, uint16_t service, uint8_t block_count, uint8_t blocks[], uint8_t *data, size_t length)
|
||||
felica_read_ex(FreefareTag tag, uint16_t service, uint8_t block_count, uint8_t blocks[], uint8_t *data, size_t length)
|
||||
{
|
||||
assert (block_count <= MAX_BLOCK_COUNT);
|
||||
assert (length == 16 * block_count);
|
||||
assert(block_count <= MAX_BLOCK_COUNT);
|
||||
assert(length == 16 * block_count);
|
||||
|
||||
DEBUG_FUNCTION();
|
||||
|
||||
|
@ -104,43 +104,43 @@ felica_read_ex (FreefareTag tag, uint16_t service, uint8_t block_count, uint8_t
|
|||
uint8_t res[100];
|
||||
|
||||
cmd[0] = 14 + 2 * block_count;
|
||||
memcpy (cmd + 2, tag->info.nti.nfi.abtId, 8);
|
||||
memcpy(cmd + 2, tag->info.nti.nfi.abtId, 8);
|
||||
cmd[11] = service;
|
||||
cmd[12] = service >> 8;
|
||||
cmd[13] = block_count;
|
||||
|
||||
for (int i = 0; i < block_count; i++) {
|
||||
cmd[14 + 2*i] = 0x80;
|
||||
cmd[14 + 2*i + 1] = blocks[i];
|
||||
cmd[14 + 2 * i] = 0x80;
|
||||
cmd[14 + 2 * i + 1] = blocks[i];
|
||||
}
|
||||
|
||||
int cnt = felica_transceive (tag, cmd, res, sizeof (res));
|
||||
int cnt = felica_transceive(tag, cmd, res, sizeof(res));
|
||||
if (cnt != 1 + 1 + 8 + 1 + 1 + 1 + 16 * block_count) {
|
||||
return -1;
|
||||
}
|
||||
size_t len = MIN(res[12] * 16, length);
|
||||
memcpy (data, res + 13, len);
|
||||
memcpy(data, res + 13, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
felica_read (FreefareTag tag, uint16_t service, uint8_t block, uint8_t *data, size_t length)
|
||||
felica_read(FreefareTag tag, uint16_t service, uint8_t block, uint8_t *data, size_t length)
|
||||
{
|
||||
uint8_t blocks[] = {
|
||||
block
|
||||
};
|
||||
|
||||
return felica_read_ex (tag, service, 1, blocks, data, length);
|
||||
return felica_read_ex(tag, service, 1, blocks, data, length);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
felica_write_ex (FreefareTag tag, uint16_t service, uint8_t block_count, uint8_t blocks[], uint8_t *data, size_t length)
|
||||
felica_write_ex(FreefareTag tag, uint16_t service, uint8_t block_count, uint8_t blocks[], uint8_t *data, size_t length)
|
||||
{
|
||||
DEBUG_FUNCTION();
|
||||
|
||||
assert (block_count <= MAX_BLOCK_COUNT);
|
||||
assert (length == 16 * block_count);
|
||||
assert(block_count <= MAX_BLOCK_COUNT);
|
||||
assert(length == 16 * block_count);
|
||||
|
||||
uint8_t cmd[1 + 1 + 8 + 1 + 2 + 1 + 2 + 16 * MAX_BLOCK_COUNT] = {
|
||||
0x00, /* Length */
|
||||
|
@ -156,32 +156,32 @@ felica_write_ex (FreefareTag tag, uint16_t service, uint8_t block_count, uint8_t
|
|||
uint8_t res[12];
|
||||
|
||||
cmd[0] = 1 + 1 + 8 + 1 + 2 * 1 + 1 + 2 * 1 + 16 * block_count;
|
||||
memcpy (cmd + 2, tag->info.nti.nfi.abtId, 8);
|
||||
memcpy(cmd + 2, tag->info.nti.nfi.abtId, 8);
|
||||
cmd[11] = service;
|
||||
cmd[12] = service >> 8;
|
||||
cmd[13] = block_count;
|
||||
|
||||
for (int i = 0; i < block_count; i++) {
|
||||
cmd[14 + 2*i] = 0x80;
|
||||
cmd[14 + 2*i + 1] = blocks[i];
|
||||
cmd[14 + 2 * i] = 0x80;
|
||||
cmd[14 + 2 * i + 1] = blocks[i];
|
||||
}
|
||||
|
||||
memcpy (cmd + 14 + 2 * block_count, data, length);
|
||||
memcpy(cmd + 14 + 2 * block_count, data, length);
|
||||
|
||||
ssize_t cnt = felica_transceive (tag, cmd, res, sizeof (res));
|
||||
ssize_t cnt = felica_transceive(tag, cmd, res, sizeof(res));
|
||||
|
||||
if (cnt != sizeof (res))
|
||||
if (cnt != sizeof(res))
|
||||
return -1;
|
||||
|
||||
return res[10] == 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
felica_write (FreefareTag tag, uint16_t service, uint8_t block, uint8_t *data, size_t length)
|
||||
felica_write(FreefareTag tag, uint16_t service, uint8_t block, uint8_t *data, size_t length)
|
||||
{
|
||||
uint8_t blocks[] = {
|
||||
block
|
||||
};
|
||||
|
||||
return felica_write_ex (tag, service, 1, blocks, data, length);
|
||||
return felica_write_ex(tag, service, 1, blocks, data, length);
|
||||
}
|
||||
|
|
|
@ -34,26 +34,26 @@
|
|||
* Automagically allocate a FreefareTag given a device and target info.
|
||||
*/
|
||||
FreefareTag
|
||||
freefare_tag_new (nfc_device *device, nfc_target target)
|
||||
freefare_tag_new(nfc_device *device, nfc_target target)
|
||||
{
|
||||
FreefareTag tag = NULL;
|
||||
|
||||
if (felica_taste (device, target)) {
|
||||
tag = felica_tag_new (device, target);
|
||||
} else if (mifare_mini_taste (device, target)) {
|
||||
tag = mifare_mini_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 (ntag21x_taste (device, target)) {
|
||||
tag = ntag21x_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 (felica_taste(device, target)) {
|
||||
tag = felica_tag_new(device, target);
|
||||
} else if (mifare_mini_taste(device, target)) {
|
||||
tag = mifare_mini_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 (ntag21x_taste(device, target)) {
|
||||
tag = ntag21x_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);
|
||||
}
|
||||
|
||||
return tag;
|
||||
|
@ -74,7 +74,7 @@ freefare_tag_new (nfc_device *device, nfc_target target)
|
|||
* The list has to be freed using the freefare_free_tags() function.
|
||||
*/
|
||||
FreefareTag *
|
||||
freefare_get_tags (nfc_device *device)
|
||||
freefare_get_tags(nfc_device *device)
|
||||
{
|
||||
FreefareTag *tags = NULL;
|
||||
int tag_count = 0;
|
||||
|
@ -82,15 +82,15 @@ freefare_get_tags (nfc_device *device)
|
|||
nfc_initiator_init(device);
|
||||
|
||||
// Drop the field for a while
|
||||
nfc_device_set_property_bool(device,NP_ACTIVATE_FIELD,false);
|
||||
nfc_device_set_property_bool(device, NP_ACTIVATE_FIELD, false);
|
||||
|
||||
// Configure the CRC and Parity settings
|
||||
nfc_device_set_property_bool(device,NP_HANDLE_CRC,true);
|
||||
nfc_device_set_property_bool(device,NP_HANDLE_PARITY,true);
|
||||
nfc_device_set_property_bool(device,NP_AUTO_ISO14443_4,true);
|
||||
nfc_device_set_property_bool(device, NP_HANDLE_CRC, true);
|
||||
nfc_device_set_property_bool(device, NP_HANDLE_PARITY, true);
|
||||
nfc_device_set_property_bool(device, NP_AUTO_ISO14443_4, true);
|
||||
|
||||
// Enable field so more power consuming cards can power themselves up
|
||||
nfc_device_set_property_bool(device,NP_ACTIVATE_FIELD,true);
|
||||
nfc_device_set_property_bool(device, NP_ACTIVATE_FIELD, true);
|
||||
|
||||
// Poll for a ISO14443A (MIFARE) tag
|
||||
nfc_target candidates[MAX_CANDIDATES];
|
||||
|
@ -102,15 +102,15 @@ freefare_get_tags (nfc_device *device)
|
|||
if ((candidates_count = nfc_initiator_list_passive_targets(device, modulation, candidates, MAX_CANDIDATES)) < 0)
|
||||
return NULL;
|
||||
|
||||
tags = malloc(sizeof (void *));
|
||||
if(!tags) return NULL;
|
||||
tags = malloc(sizeof(void *));
|
||||
if (!tags) return NULL;
|
||||
tags[0] = NULL;
|
||||
|
||||
for (int c = 0; c < candidates_count; c++) {
|
||||
FreefareTag t;
|
||||
if ((t = freefare_tag_new(device, candidates[c]))) {
|
||||
/* (Re)Allocate memory for the found MIFARE targets array */
|
||||
FreefareTag *p = realloc (tags, (tag_count + 2) * sizeof (FreefareTag));
|
||||
FreefareTag *p = realloc(tags, (tag_count + 2) * sizeof(FreefareTag));
|
||||
if (p)
|
||||
tags = p;
|
||||
else
|
||||
|
@ -130,7 +130,7 @@ freefare_get_tags (nfc_device *device)
|
|||
FreefareTag t;
|
||||
if ((t = freefare_tag_new(device, candidates[c]))) {
|
||||
/* (Re)Allocate memory for the found FELICA targets array */
|
||||
FreefareTag *p = realloc (tags, (tag_count + 2) * sizeof (FreefareTag));
|
||||
FreefareTag *p = realloc(tags, (tag_count + 2) * sizeof(FreefareTag));
|
||||
if (p)
|
||||
tags = p;
|
||||
else
|
||||
|
@ -147,8 +147,7 @@ freefare_get_tags (nfc_device *device)
|
|||
* Returns the type of the provided tag.
|
||||
*/
|
||||
enum freefare_tag_type
|
||||
freefare_get_tag_type (FreefareTag tag)
|
||||
{
|
||||
freefare_get_tag_type(FreefareTag tag) {
|
||||
return tag->type;
|
||||
}
|
||||
|
||||
|
@ -156,13 +155,13 @@ freefare_get_tag_type (FreefareTag tag)
|
|||
* Returns the friendly name of the provided tag.
|
||||
*/
|
||||
const char *
|
||||
freefare_get_tag_friendly_name (FreefareTag tag)
|
||||
freefare_get_tag_friendly_name(FreefareTag tag)
|
||||
{
|
||||
switch (tag->type) {
|
||||
case FELICA:
|
||||
return "FeliCA";
|
||||
case MIFARE_MINI:
|
||||
return "Mifare Mini 0.3k";
|
||||
return "Mifare Mini 0.3k";
|
||||
case MIFARE_CLASSIC_1K:
|
||||
return "Mifare Classic 1k";
|
||||
case MIFARE_CLASSIC_4K:
|
||||
|
@ -184,20 +183,20 @@ freefare_get_tag_friendly_name (FreefareTag tag)
|
|||
* Returns the UID of the provided tag.
|
||||
*/
|
||||
char *
|
||||
freefare_get_tag_uid (FreefareTag tag)
|
||||
freefare_get_tag_uid(FreefareTag tag)
|
||||
{
|
||||
char *res = NULL;
|
||||
switch (tag->info.nm.nmt) {
|
||||
case NMT_FELICA:
|
||||
if ((res = malloc (17))) {
|
||||
if ((res = malloc(17))) {
|
||||
for (size_t i = 0; i < 8; i++)
|
||||
snprintf (res + 2*i, 3, "%02x", tag->info.nti.nfi.abtId[i]);
|
||||
snprintf(res + 2 * i, 3, "%02x", tag->info.nti.nfi.abtId[i]);
|
||||
}
|
||||
break;
|
||||
case NMT_ISO14443A:
|
||||
if ((res = malloc (2 * tag->info.nti.nai.szUidLen + 1))) {
|
||||
if ((res = malloc(2 * tag->info.nti.nai.szUidLen + 1))) {
|
||||
for (size_t i = 0; i < tag->info.nti.nai.szUidLen; i++)
|
||||
snprintf (res + 2*i, 3, "%02x", tag->info.nti.nai.abtUid[i]);
|
||||
snprintf(res + 2 * i, 3, "%02x", tag->info.nti.nai.abtUid[i]);
|
||||
}
|
||||
break;
|
||||
case NMT_DEP:
|
||||
|
@ -206,7 +205,7 @@ freefare_get_tag_uid (FreefareTag tag)
|
|||
case NMT_ISO14443B:
|
||||
case NMT_ISO14443BI:
|
||||
case NMT_JEWEL:
|
||||
res = strdup ("UNKNOWN");
|
||||
res = strdup("UNKNOWN");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -223,54 +222,54 @@ bool freefare_selected_tag_is_present(nfc_device *device)
|
|||
* Free the provided tag.
|
||||
*/
|
||||
void
|
||||
freefare_free_tag (FreefareTag tag)
|
||||
freefare_free_tag(FreefareTag tag)
|
||||
{
|
||||
if (tag) {
|
||||
tag->free_tag (tag);
|
||||
tag->free_tag(tag);
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
freefare_strerror (FreefareTag tag)
|
||||
freefare_strerror(FreefareTag tag)
|
||||
{
|
||||
const char *p = "Unknown error";
|
||||
if (nfc_device_get_last_error (tag->device) < 0) {
|
||||
p = nfc_strerror (tag->device);
|
||||
if (nfc_device_get_last_error(tag->device) < 0) {
|
||||
p = nfc_strerror(tag->device);
|
||||
} else {
|
||||
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) {
|
||||
p = mifare_desfire_error_lookup (MIFARE_DESFIRE (tag)->last_picc_error);
|
||||
}
|
||||
}
|
||||
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) {
|
||||
p = mifare_desfire_error_lookup(MIFARE_DESFIRE(tag)->last_picc_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
int
|
||||
freefare_strerror_r (FreefareTag tag, char *buffer, size_t len)
|
||||
freefare_strerror_r(FreefareTag tag, char *buffer, size_t len)
|
||||
{
|
||||
return (snprintf (buffer, len, "%s", freefare_strerror (tag)) < 0) ? -1 : 0;
|
||||
return (snprintf(buffer, len, "%s", freefare_strerror(tag)) < 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
void
|
||||
freefare_perror (FreefareTag tag, const char *string)
|
||||
freefare_perror(FreefareTag tag, const char *string)
|
||||
{
|
||||
fprintf (stderr, "%s: %s\n", string, freefare_strerror (tag));
|
||||
fprintf(stderr, "%s: %s\n", string, freefare_strerror(tag));
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the provided tag list.
|
||||
*/
|
||||
void
|
||||
freefare_free_tags (FreefareTag *tags)
|
||||
freefare_free_tags(FreefareTag *tags)
|
||||
{
|
||||
if (tags) {
|
||||
for (int i=0; tags[i]; i++) {
|
||||
for (int i = 0; tags[i]; i++) {
|
||||
freefare_free_tag(tags[i]);
|
||||
}
|
||||
free (tags);
|
||||
free(tags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,11 +279,11 @@ freefare_free_tags (FreefareTag *tags)
|
|||
*/
|
||||
|
||||
void *
|
||||
memdup (const void *p, const size_t n)
|
||||
memdup(const void *p, const size_t n)
|
||||
{
|
||||
void *res;
|
||||
if ((res = malloc (n))) {
|
||||
memcpy (res, p, n);
|
||||
if ((res = malloc(n))) {
|
||||
memcpy(res, p, n);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2009, 2010, Romain Tartiere, Romuald Conty.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -25,7 +25,7 @@
|
|||
#include <nfc/nfc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
enum freefare_tag_type {
|
||||
|
@ -47,7 +47,7 @@ struct freefare_tag;
|
|||
typedef struct freefare_tag *FreefareTag;
|
||||
|
||||
/* Replace any MifareTag by the generic FreefareTag. */
|
||||
typedef struct freefare_tag *MifareTag __attribute__ ((deprecated));
|
||||
typedef struct freefare_tag *MifareTag __attribute__((deprecated));
|
||||
|
||||
struct mifare_desfire_key;
|
||||
typedef struct mifare_desfire_key *MifareDESFireKey;
|
||||
|
@ -58,57 +58,57 @@ typedef struct ntag21x_key *NTAG21xKey;
|
|||
typedef uint8_t MifareUltralightPageNumber;
|
||||
typedef unsigned char MifareUltralightPage[4];
|
||||
|
||||
FreefareTag *freefare_get_tags (nfc_device *device);
|
||||
FreefareTag freefare_tag_new (nfc_device *device, nfc_target target);
|
||||
enum freefare_tag_type freefare_get_tag_type (FreefareTag tag);
|
||||
const char *freefare_get_tag_friendly_name (FreefareTag tag);
|
||||
char *freefare_get_tag_uid (FreefareTag tag);
|
||||
void freefare_free_tag (FreefareTag tag);
|
||||
void freefare_free_tags (FreefareTag *tags);
|
||||
FreefareTag *freefare_get_tags(nfc_device *device);
|
||||
FreefareTag freefare_tag_new(nfc_device *device, nfc_target target);
|
||||
enum freefare_tag_type freefare_get_tag_type(FreefareTag tag);
|
||||
const char *freefare_get_tag_friendly_name(FreefareTag tag);
|
||||
char *freefare_get_tag_uid(FreefareTag tag);
|
||||
void freefare_free_tag(FreefareTag tag);
|
||||
void freefare_free_tags(FreefareTag *tags);
|
||||
bool freefare_selected_tag_is_present(nfc_device *device);
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
int mifare_ultralight_connect(FreefareTag tag);
|
||||
int mifare_ultralight_disconnect(FreefareTag tag);
|
||||
|
||||
int mifare_ultralight_read (FreefareTag tag, const MifareUltralightPageNumber page, MifareUltralightPage *data);
|
||||
int mifare_ultralight_write (FreefareTag tag, const MifareUltralightPageNumber page, const MifareUltralightPage data);
|
||||
int mifare_ultralight_read(FreefareTag tag, const MifareUltralightPageNumber page, MifareUltralightPage *data);
|
||||
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);
|
||||
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 ntag21x_taste (nfc_device *device, nfc_target target);
|
||||
bool ntag21x_taste(nfc_device *device, nfc_target target);
|
||||
|
||||
/* NTAG21x access features */
|
||||
#define NTAG_PROT 0x80
|
||||
|
@ -123,48 +123,48 @@ enum ntag_tag_subtype {
|
|||
NTAG_216
|
||||
};
|
||||
|
||||
FreefareTag ntag21x_tag_new (nfc_device *device, nfc_target target);
|
||||
FreefareTag ntag21x_tag_reuse (FreefareTag tag); /* Copy data from Ultralight tag to new NTAG21x, don't forget to free your old tag */
|
||||
NTAG21xKey ntag21x_key_new (const uint8_t data[4],const uint8_t pack[2]); /* Create new key */
|
||||
void ntag21x_key_free (NTAG21xKey key); /* Clear key from memory */
|
||||
void ntag21x_tag_free (FreefareTag tag);
|
||||
int ntag21x_connect (FreefareTag tag);
|
||||
int ntag21x_disconnect (FreefareTag tag);
|
||||
int ntag21x_get_info (FreefareTag tag); /* Get all information about tag (size,vendor ...) */
|
||||
enum ntag_tag_subtype ntag21x_get_subtype (FreefareTag tag); /* Get subtype of tag */
|
||||
uint8_t ntag21x_get_last_page (FreefareTag tag); /* Get last page address based on gathered info from function above */
|
||||
int ntag21x_read_signature (FreefareTag tag,uint8_t *data); /* Get tag signature */
|
||||
int ntag21x_set_pwd (FreefareTag tag, uint8_t data[4]); /* Set password */
|
||||
int ntag21x_set_pack (FreefareTag tag, uint8_t data[2]); /* Set pack */
|
||||
int 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) */
|
||||
int 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 */
|
||||
int ntag21x_access_disable (FreefareTag tag,uint8_t byte); /* Disable access feature in ACCESS byte */
|
||||
int ntag21x_get_access (FreefareTag tag,uint8_t *byte); /* Get ACCESS byte */
|
||||
int ntag21x_check_access (FreefareTag tag,uint8_t byte,bool *result); /* Check if access feature is enabled */
|
||||
int ntag21x_get_authentication_limit (FreefareTag tag,uint8_t *byte); /* Get authentication limit */
|
||||
int ntag21x_set_authentication_limit (FreefareTag tag,uint8_t byte); /* Set authentication limit (0x00 = disabled, [0x01,0x07] = valid range, > 0x07 invalid range) */
|
||||
int ntag21x_read (FreefareTag tag, uint8_t page,uint8_t *data); /* Read 16 bytes starting from page */
|
||||
int ntag21x_read4 (FreefareTag tag,uint8_t page,uint8_t *data); /* Read 4 bytes on page */
|
||||
int ntag21x_fast_read (FreefareTag tag, uint8_t start_page,uint8_t end_page, uint8_t *data); /* Read n*4 bytes from range [start_page,end_page] */
|
||||
int ntag21x_fast_read4 (FreefareTag tag,uint8_t page,uint8_t *data); /* Fast read certain page */
|
||||
int ntag21x_read_cnt (FreefareTag tag, uint8_t *data); /* Read 3-byte NFC counter if enabled else it returns error */
|
||||
int ntag21x_write (FreefareTag tag, uint8_t page, uint8_t data[4]); /* Write 4 bytes to page */
|
||||
int ntag21x_compatibility_write (FreefareTag tag, uint8_t page, uint8_t data[4]); /* Writes 4 bytes to page with mifare classic write */
|
||||
int ntag21x_authenticate (FreefareTag tag, const NTAG21xKey key); /* Authenticate with tag */
|
||||
bool is_ntag21x (FreefareTag tag); /* Check if tag type is NTAG21x */
|
||||
bool ntag21x_is_auth_supported (nfc_device *device, nfc_iso14443a_info nai); /* Check if tag supports 21x commands */
|
||||
FreefareTag ntag21x_tag_new(nfc_device *device, nfc_target target);
|
||||
FreefareTag ntag21x_tag_reuse(FreefareTag tag); /* Copy data from Ultralight tag to new NTAG21x, don't forget to free your old tag */
|
||||
NTAG21xKey ntag21x_key_new(const uint8_t data[4], const uint8_t pack[2]); /* Create new key */
|
||||
void ntag21x_key_free(NTAG21xKey key); /* Clear key from memory */
|
||||
void ntag21x_tag_free(FreefareTag tag);
|
||||
int ntag21x_connect(FreefareTag tag);
|
||||
int ntag21x_disconnect(FreefareTag tag);
|
||||
int ntag21x_get_info(FreefareTag tag); /* Get all information about tag (size,vendor ...) */
|
||||
enum ntag_tag_subtype ntag21x_get_subtype(FreefareTag tag); /* Get subtype of tag */
|
||||
uint8_t ntag21x_get_last_page(FreefareTag tag); /* Get last page address based on gathered info from function above */
|
||||
int ntag21x_read_signature(FreefareTag tag, uint8_t *data); /* Get tag signature */
|
||||
int ntag21x_set_pwd(FreefareTag tag, uint8_t data[4]); /* Set password */
|
||||
int ntag21x_set_pack(FreefareTag tag, uint8_t data[2]); /* Set pack */
|
||||
int 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) */
|
||||
int 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 */
|
||||
int ntag21x_access_disable(FreefareTag tag, uint8_t byte); /* Disable access feature in ACCESS byte */
|
||||
int ntag21x_get_access(FreefareTag tag, uint8_t *byte); /* Get ACCESS byte */
|
||||
int ntag21x_check_access(FreefareTag tag, uint8_t byte, bool *result); /* Check if access feature is enabled */
|
||||
int ntag21x_get_authentication_limit(FreefareTag tag, uint8_t *byte); /* Get authentication limit */
|
||||
int ntag21x_set_authentication_limit(FreefareTag tag, uint8_t byte); /* Set authentication limit (0x00 = disabled, [0x01,0x07] = valid range, > 0x07 invalid range) */
|
||||
int ntag21x_read(FreefareTag tag, uint8_t page, uint8_t *data); /* Read 16 bytes starting from page */
|
||||
int ntag21x_read4(FreefareTag tag, uint8_t page, uint8_t *data); /* Read 4 bytes on page */
|
||||
int ntag21x_fast_read(FreefareTag tag, uint8_t start_page, uint8_t end_page, uint8_t *data); /* Read n*4 bytes from range [start_page,end_page] */
|
||||
int ntag21x_fast_read4(FreefareTag tag, uint8_t page, uint8_t *data); /* Fast read certain page */
|
||||
int ntag21x_read_cnt(FreefareTag tag, uint8_t *data); /* Read 3-byte NFC counter if enabled else it returns error */
|
||||
int ntag21x_write(FreefareTag tag, uint8_t page, uint8_t data[4]); /* Write 4 bytes to page */
|
||||
int ntag21x_compatibility_write(FreefareTag tag, uint8_t page, uint8_t data[4]); /* Writes 4 bytes to page with mifare classic write */
|
||||
int ntag21x_authenticate(FreefareTag tag, const NTAG21xKey key); /* Authenticate with tag */
|
||||
bool is_ntag21x(FreefareTag tag); /* Check if tag type is NTAG21x */
|
||||
bool ntag21x_is_auth_supported(nfc_device *device, nfc_iso14443a_info nai); /* Check if tag supports 21x commands */
|
||||
|
||||
|
||||
|
||||
bool mifare_mini_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);
|
||||
FreefareTag mifare_mini_tag_new (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);
|
||||
bool mifare_mini_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);
|
||||
FreefareTag mifare_mini_tag_new(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];
|
||||
|
||||
|
@ -177,31 +177,31 @@ typedef unsigned char MifareClassicKey[6];
|
|||
/* NFC Forum public key */
|
||||
extern const MifareClassicKey mifare_classic_nfcforum_public_key_a;
|
||||
|
||||
int mifare_classic_connect (FreefareTag tag);
|
||||
int mifare_classic_disconnect (FreefareTag tag);
|
||||
int mifare_classic_connect(FreefareTag tag);
|
||||
int mifare_classic_disconnect(FreefareTag tag);
|
||||
|
||||
int mifare_classic_authenticate (FreefareTag tag, const MifareClassicBlockNumber block, const MifareClassicKey key, const MifareClassicKeyType key_type);
|
||||
int mifare_classic_read (FreefareTag tag, const MifareClassicBlockNumber block, MifareClassicBlock *data);
|
||||
int mifare_classic_init_value (FreefareTag tag, const MifareClassicBlockNumber block, const int32_t value, const MifareClassicBlockNumber adr);
|
||||
int mifare_classic_read_value (FreefareTag tag, const MifareClassicBlockNumber block, int32_t *value, MifareClassicBlockNumber *adr);
|
||||
int mifare_classic_write (FreefareTag tag, const MifareClassicBlockNumber block, const MifareClassicBlock data);
|
||||
int mifare_classic_authenticate(FreefareTag tag, const MifareClassicBlockNumber block, const MifareClassicKey key, const MifareClassicKeyType key_type);
|
||||
int mifare_classic_read(FreefareTag tag, const MifareClassicBlockNumber block, MifareClassicBlock *data);
|
||||
int mifare_classic_init_value(FreefareTag tag, const MifareClassicBlockNumber block, const int32_t value, const MifareClassicBlockNumber adr);
|
||||
int mifare_classic_read_value(FreefareTag tag, const MifareClassicBlockNumber block, int32_t *value, MifareClassicBlockNumber *adr);
|
||||
int mifare_classic_write(FreefareTag tag, const MifareClassicBlockNumber block, const MifareClassicBlock data);
|
||||
|
||||
int mifare_classic_increment (FreefareTag tag, const MifareClassicBlockNumber block, const uint32_t amount);
|
||||
int mifare_classic_decrement (FreefareTag tag, const MifareClassicBlockNumber block, const uint32_t amount);
|
||||
int mifare_classic_restore (FreefareTag tag, const MifareClassicBlockNumber block);
|
||||
int mifare_classic_transfer (FreefareTag tag, const MifareClassicBlockNumber block);
|
||||
int mifare_classic_increment(FreefareTag tag, const MifareClassicBlockNumber block, const uint32_t amount);
|
||||
int mifare_classic_decrement(FreefareTag tag, const MifareClassicBlockNumber block, const uint32_t amount);
|
||||
int mifare_classic_restore(FreefareTag tag, const MifareClassicBlockNumber block);
|
||||
int mifare_classic_transfer(FreefareTag tag, const MifareClassicBlockNumber block);
|
||||
|
||||
int mifare_classic_get_trailer_block_permission (FreefareTag tag, const MifareClassicBlockNumber block, const uint16_t permission, const MifareClassicKeyType key_type);
|
||||
int mifare_classic_get_data_block_permission (FreefareTag tag, const MifareClassicBlockNumber block, const unsigned char permission, const MifareClassicKeyType key_type);
|
||||
int mifare_classic_get_trailer_block_permission(FreefareTag tag, const MifareClassicBlockNumber block, const uint16_t permission, const MifareClassicKeyType key_type);
|
||||
int mifare_classic_get_data_block_permission(FreefareTag tag, const MifareClassicBlockNumber block, const unsigned char permission, const MifareClassicKeyType key_type);
|
||||
|
||||
int mifare_classic_format_sector (FreefareTag tag, const MifareClassicSectorNumber sector);
|
||||
int mifare_classic_format_sector(FreefareTag tag, const MifareClassicSectorNumber sector);
|
||||
|
||||
void mifare_classic_trailer_block (MifareClassicBlock *block, const MifareClassicKey key_a, uint8_t ab_0, uint8_t ab_1, uint8_t ab_2, uint8_t ab_tb, const uint8_t gpb, const MifareClassicKey key_b);
|
||||
void mifare_classic_trailer_block(MifareClassicBlock *block, const MifareClassicKey key_a, uint8_t ab_0, uint8_t ab_1, uint8_t ab_2, uint8_t ab_tb, const uint8_t gpb, const MifareClassicKey key_b);
|
||||
|
||||
MifareClassicSectorNumber mifare_classic_block_sector (MifareClassicBlockNumber block);
|
||||
MifareClassicBlockNumber mifare_classic_sector_first_block (MifareClassicSectorNumber sector);
|
||||
size_t mifare_classic_sector_block_count (MifareClassicSectorNumber sector);
|
||||
MifareClassicBlockNumber mifare_classic_sector_last_block (MifareClassicSectorNumber sector);
|
||||
MifareClassicSectorNumber mifare_classic_block_sector(MifareClassicBlockNumber block);
|
||||
MifareClassicBlockNumber mifare_classic_sector_first_block(MifareClassicSectorNumber sector);
|
||||
size_t mifare_classic_sector_block_count(MifareClassicSectorNumber sector);
|
||||
MifareClassicBlockNumber mifare_classic_sector_last_block(MifareClassicSectorNumber sector);
|
||||
|
||||
#define C_000 0
|
||||
#define C_001 1
|
||||
|
@ -248,28 +248,28 @@ extern const MadAid mad_not_applicable_aid;
|
|||
/* NFC Forum AID */
|
||||
extern const MadAid mad_nfcforum_aid;
|
||||
|
||||
Mad mad_new (const uint8_t version);
|
||||
Mad mad_read (FreefareTag tag);
|
||||
int mad_write (FreefareTag tag, Mad mad, const MifareClassicKey key_b_sector_00, const MifareClassicKey key_b_sector_10);
|
||||
int mad_get_version (Mad mad);
|
||||
void mad_set_version (Mad mad, const uint8_t version);
|
||||
MifareClassicSectorNumber mad_get_card_publisher_sector (Mad mad);
|
||||
int mad_set_card_publisher_sector (Mad mad, const MifareClassicSectorNumber cps);
|
||||
int mad_get_aid (Mad mad, const MifareClassicSectorNumber sector, MadAid *aid);
|
||||
int mad_set_aid (Mad mad, const MifareClassicSectorNumber sector, MadAid aid);
|
||||
bool mad_sector_reserved (const MifareClassicSectorNumber sector);
|
||||
void mad_free (Mad mad);
|
||||
Mad mad_new(const uint8_t version);
|
||||
Mad mad_read(FreefareTag tag);
|
||||
int mad_write(FreefareTag tag, Mad mad, const MifareClassicKey key_b_sector_00, const MifareClassicKey key_b_sector_10);
|
||||
int mad_get_version(Mad mad);
|
||||
void mad_set_version(Mad mad, const uint8_t version);
|
||||
MifareClassicSectorNumber mad_get_card_publisher_sector(Mad mad);
|
||||
int mad_set_card_publisher_sector(Mad mad, const MifareClassicSectorNumber cps);
|
||||
int mad_get_aid(Mad mad, const MifareClassicSectorNumber sector, MadAid *aid);
|
||||
int mad_set_aid(Mad mad, const MifareClassicSectorNumber sector, MadAid aid);
|
||||
bool mad_sector_reserved(const MifareClassicSectorNumber sector);
|
||||
void mad_free(Mad mad);
|
||||
|
||||
MifareClassicSectorNumber *mifare_application_alloc (Mad mad, const MadAid aid, const size_t size);
|
||||
ssize_t mifare_application_read (FreefareTag tag, Mad mad, const MadAid aid, void *buf, size_t nbytes, const MifareClassicKey key, const MifareClassicKeyType key_type);
|
||||
ssize_t mifare_application_write (FreefareTag tag, Mad mad, const MadAid aid, const void *buf, size_t nbytes, const MifareClassicKey key, const MifareClassicKeyType key_type);
|
||||
int mifare_application_free (Mad mad, const MadAid aid);
|
||||
MifareClassicSectorNumber *mifare_application_alloc(Mad mad, const MadAid aid, const size_t size);
|
||||
ssize_t mifare_application_read(FreefareTag tag, Mad mad, const MadAid aid, void *buf, size_t nbytes, const MifareClassicKey key, const MifareClassicKeyType key_type);
|
||||
ssize_t mifare_application_write(FreefareTag tag, Mad mad, const MadAid aid, const void *buf, size_t nbytes, const MifareClassicKey key, const MifareClassicKeyType key_type);
|
||||
int mifare_application_free(Mad mad, const MadAid aid);
|
||||
|
||||
MifareClassicSectorNumber *mifare_application_find (Mad mad, const MadAid aid);
|
||||
MifareClassicSectorNumber *mifare_application_find(Mad mad, const MadAid aid);
|
||||
|
||||
|
||||
|
||||
bool mifare_desfire_taste (nfc_device *device, nfc_target target);
|
||||
bool mifare_desfire_taste(nfc_device *device, nfc_target target);
|
||||
|
||||
/* File types */
|
||||
|
||||
|
@ -302,21 +302,21 @@ enum mifare_desfire_file_types {
|
|||
*/
|
||||
|
||||
#define MDAPP_SETTINGS(key_no_for_key_changing,config_changeable,free_create_delete_files,free_listing_contents,app_master_key_changeable) ( \
|
||||
(key_no_for_key_changing << 4) | \
|
||||
(config_changeable << 3) | \
|
||||
(free_listing_contents << 1) | \
|
||||
(app_master_key_changeable) \
|
||||
)
|
||||
(key_no_for_key_changing << 4) | \
|
||||
(config_changeable << 3) | \
|
||||
(free_listing_contents << 1) | \
|
||||
(app_master_key_changeable) \
|
||||
)
|
||||
|
||||
|
||||
/* Access right */
|
||||
|
||||
#define MDAR(read,write,read_write,change_access_rights) ( \
|
||||
(read << 12) | \
|
||||
(write << 8) | \
|
||||
(read_write << 4) | \
|
||||
(change_access_rights) \
|
||||
)
|
||||
(read << 12) | \
|
||||
(write << 8) | \
|
||||
(read_write << 4) | \
|
||||
(change_access_rights) \
|
||||
)
|
||||
#define MDAR_READ(ar) (((ar) >> 12) & 0x0f)
|
||||
#define MDAR_WRITE(ar) (((ar) >> 8) & 0x0f)
|
||||
#define MDAR_READ_WRITE(ar) (((ar) >> 4) & 0x0f)
|
||||
|
@ -379,12 +379,12 @@ struct mifare_desfire_df {
|
|||
};
|
||||
typedef struct mifare_desfire_df MifareDESFireDF;
|
||||
|
||||
MifareDESFireAID mifare_desfire_aid_new (uint32_t aid);
|
||||
MifareDESFireAID mifare_desfire_aid_new_with_mad_aid (MadAid mad_aid, uint8_t n);
|
||||
uint32_t mifare_desfire_aid_get_aid (MifareDESFireAID aid);
|
||||
MifareDESFireAID mifare_desfire_aid_new(uint32_t aid);
|
||||
MifareDESFireAID mifare_desfire_aid_new_with_mad_aid(MadAid mad_aid, uint8_t n);
|
||||
uint32_t mifare_desfire_aid_get_aid(MifareDESFireAID aid);
|
||||
|
||||
uint8_t mifare_desfire_last_pcd_error (FreefareTag tag);
|
||||
uint8_t mifare_desfire_last_picc_error (FreefareTag tag);
|
||||
uint8_t mifare_desfire_last_pcd_error(FreefareTag tag);
|
||||
uint8_t mifare_desfire_last_picc_error(FreefareTag tag);
|
||||
|
||||
#pragma pack (push)
|
||||
#pragma pack (1)
|
||||
|
@ -436,93 +436,93 @@ struct mifare_desfire_file_settings {
|
|||
} settings;
|
||||
};
|
||||
|
||||
FreefareTag mifare_desfire_tag_new (nfc_device *device, nfc_target target);
|
||||
void mifare_desfire_tag_free (FreefareTag tags);
|
||||
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);
|
||||
int mifare_desfire_connect(FreefareTag tag);
|
||||
int mifare_desfire_disconnect(FreefareTag tag);
|
||||
|
||||
int mifare_desfire_authenticate (FreefareTag tag, uint8_t key_no, MifareDESFireKey key);
|
||||
int mifare_desfire_authenticate_iso (FreefareTag tag, uint8_t key_no, MifareDESFireKey key);
|
||||
int mifare_desfire_authenticate_aes (FreefareTag tag, uint8_t key_no, MifareDESFireKey key);
|
||||
int mifare_desfire_change_key_settings (FreefareTag tag, uint8_t settings);
|
||||
int mifare_desfire_get_key_settings (FreefareTag tag, uint8_t *settings, uint8_t *max_keys);
|
||||
int mifare_desfire_change_key (FreefareTag tag, uint8_t key_no, MifareDESFireKey new_key, MifareDESFireKey old_key);
|
||||
int mifare_desfire_get_key_version (FreefareTag tag, uint8_t key_no, uint8_t *version);
|
||||
int mifare_desfire_create_application (FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no);
|
||||
int mifare_desfire_create_application_3k3des (FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no);
|
||||
int mifare_desfire_create_application_aes (FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no);
|
||||
int mifare_desfire_authenticate(FreefareTag tag, uint8_t key_no, MifareDESFireKey key);
|
||||
int mifare_desfire_authenticate_iso(FreefareTag tag, uint8_t key_no, MifareDESFireKey key);
|
||||
int mifare_desfire_authenticate_aes(FreefareTag tag, uint8_t key_no, MifareDESFireKey key);
|
||||
int mifare_desfire_change_key_settings(FreefareTag tag, uint8_t settings);
|
||||
int mifare_desfire_get_key_settings(FreefareTag tag, uint8_t *settings, uint8_t *max_keys);
|
||||
int mifare_desfire_change_key(FreefareTag tag, uint8_t key_no, MifareDESFireKey new_key, MifareDESFireKey old_key);
|
||||
int mifare_desfire_get_key_version(FreefareTag tag, uint8_t key_no, uint8_t *version);
|
||||
int mifare_desfire_create_application(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no);
|
||||
int mifare_desfire_create_application_3k3des(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no);
|
||||
int mifare_desfire_create_application_aes(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no);
|
||||
|
||||
int mifare_desfire_create_application_iso (FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no, int want_iso_file_identifiers, uint16_t iso_file_id, uint8_t *iso_file_name, size_t iso_file_name_len);
|
||||
int mifare_desfire_create_application_3k3des_iso (FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no, int want_iso_file_identifiers, uint16_t iso_file_id, uint8_t *iso_file_name, size_t iso_file_name_len);
|
||||
int mifare_desfire_create_application_aes_iso (FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no, int want_iso_file_identifiers, uint16_t iso_file_id, uint8_t *iso_file_name, size_t iso_file_name_len);
|
||||
int mifare_desfire_create_application_iso(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no, int want_iso_file_identifiers, uint16_t iso_file_id, uint8_t *iso_file_name, size_t iso_file_name_len);
|
||||
int mifare_desfire_create_application_3k3des_iso(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no, int want_iso_file_identifiers, uint16_t iso_file_id, uint8_t *iso_file_name, size_t iso_file_name_len);
|
||||
int mifare_desfire_create_application_aes_iso(FreefareTag tag, MifareDESFireAID aid, uint8_t settings, uint8_t key_no, int want_iso_file_identifiers, uint16_t iso_file_id, uint8_t *iso_file_name, size_t iso_file_name_len);
|
||||
|
||||
int mifare_desfire_delete_application (FreefareTag tag, MifareDESFireAID aid);
|
||||
int mifare_desfire_get_application_ids (FreefareTag tag, MifareDESFireAID *aids[], size_t *count);
|
||||
int mifare_desfire_get_df_names (FreefareTag tag, MifareDESFireDF *dfs[], size_t *count);
|
||||
void mifare_desfire_free_application_ids (MifareDESFireAID aids[]);
|
||||
int mifare_desfire_select_application (FreefareTag tag, MifareDESFireAID aid);
|
||||
int mifare_desfire_format_picc (FreefareTag tag);
|
||||
int mifare_desfire_get_version (FreefareTag tag, struct mifare_desfire_version_info *version_info);
|
||||
int mifare_desfire_free_mem (FreefareTag tag, uint32_t *size);
|
||||
int mifare_desfire_set_configuration (FreefareTag tag, bool disable_format, bool enable_random_uid);
|
||||
int mifare_desfire_set_default_key (FreefareTag tag, MifareDESFireKey key);
|
||||
int mifare_desfire_set_ats (FreefareTag tag, uint8_t *ats);
|
||||
int mifare_desfire_get_card_uid (FreefareTag tag, char **uid);
|
||||
int mifare_desfire_get_file_ids (FreefareTag tag, uint8_t **files, size_t *count);
|
||||
int mifare_desfire_get_iso_file_ids (FreefareTag tag, uint16_t **files, size_t *count);
|
||||
int mifare_desfire_get_file_settings (FreefareTag tag, uint8_t file_no, struct mifare_desfire_file_settings *settings);
|
||||
int mifare_desfire_change_file_settings (FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights);
|
||||
int mifare_desfire_create_std_data_file (FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size);
|
||||
int mifare_desfire_create_std_data_file_iso (FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size, uint16_t iso_file_id);
|
||||
int mifare_desfire_create_backup_data_file (FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size);
|
||||
int mifare_desfire_create_backup_data_file_iso (FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size, uint16_t iso_file_id);
|
||||
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);
|
||||
int mifare_desfire_create_linear_record_file (FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records);
|
||||
int mifare_desfire_create_linear_record_file_iso (FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records, uint16_t iso_file_id);
|
||||
int mifare_desfire_create_cyclic_record_file (FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records);
|
||||
int mifare_desfire_create_cyclic_record_file_iso (FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records, uint16_t iso_file_id);
|
||||
int mifare_desfire_delete_file (FreefareTag tag, uint8_t file_no);
|
||||
int mifare_desfire_delete_application(FreefareTag tag, MifareDESFireAID aid);
|
||||
int mifare_desfire_get_application_ids(FreefareTag tag, MifareDESFireAID *aids[], size_t *count);
|
||||
int mifare_desfire_get_df_names(FreefareTag tag, MifareDESFireDF *dfs[], size_t *count);
|
||||
void mifare_desfire_free_application_ids(MifareDESFireAID aids[]);
|
||||
int mifare_desfire_select_application(FreefareTag tag, MifareDESFireAID aid);
|
||||
int mifare_desfire_format_picc(FreefareTag tag);
|
||||
int mifare_desfire_get_version(FreefareTag tag, struct mifare_desfire_version_info *version_info);
|
||||
int mifare_desfire_free_mem(FreefareTag tag, uint32_t *size);
|
||||
int mifare_desfire_set_configuration(FreefareTag tag, bool disable_format, bool enable_random_uid);
|
||||
int mifare_desfire_set_default_key(FreefareTag tag, MifareDESFireKey key);
|
||||
int mifare_desfire_set_ats(FreefareTag tag, uint8_t *ats);
|
||||
int mifare_desfire_get_card_uid(FreefareTag tag, char **uid);
|
||||
int mifare_desfire_get_file_ids(FreefareTag tag, uint8_t **files, size_t *count);
|
||||
int mifare_desfire_get_iso_file_ids(FreefareTag tag, uint16_t **files, size_t *count);
|
||||
int mifare_desfire_get_file_settings(FreefareTag tag, uint8_t file_no, struct mifare_desfire_file_settings *settings);
|
||||
int mifare_desfire_change_file_settings(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights);
|
||||
int mifare_desfire_create_std_data_file(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size);
|
||||
int mifare_desfire_create_std_data_file_iso(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size, uint16_t iso_file_id);
|
||||
int mifare_desfire_create_backup_data_file(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size);
|
||||
int mifare_desfire_create_backup_data_file_iso(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t file_size, uint16_t iso_file_id);
|
||||
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);
|
||||
int mifare_desfire_create_linear_record_file(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records);
|
||||
int mifare_desfire_create_linear_record_file_iso(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records, uint16_t iso_file_id);
|
||||
int mifare_desfire_create_cyclic_record_file(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records);
|
||||
int mifare_desfire_create_cyclic_record_file_iso(FreefareTag tag, uint8_t file_no, uint8_t communication_settings, uint16_t access_rights, uint32_t record_size, uint32_t max_number_of_records, uint16_t iso_file_id);
|
||||
int mifare_desfire_delete_file(FreefareTag tag, uint8_t file_no);
|
||||
|
||||
ssize_t mifare_desfire_read_data (FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data);
|
||||
ssize_t mifare_desfire_read_data_ex (FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data, int cs);
|
||||
ssize_t mifare_desfire_write_data (FreefareTag tag, uint8_t file_no, off_t offset, size_t length, const void *data);
|
||||
ssize_t mifare_desfire_write_data_ex (FreefareTag tag, uint8_t file_no, off_t offset, size_t length, const void *data, int cs);
|
||||
int mifare_desfire_get_value (FreefareTag tag, uint8_t file_no, int32_t *value);
|
||||
int mifare_desfire_get_value_ex (FreefareTag tag, uint8_t file_no, int32_t *value, int cs);
|
||||
int mifare_desfire_credit (FreefareTag tag, uint8_t file_no, int32_t amount);
|
||||
int mifare_desfire_credit_ex (FreefareTag tag, uint8_t file_no, int32_t amount, int cs);
|
||||
int mifare_desfire_debit (FreefareTag tag, uint8_t file_no, int32_t amount);
|
||||
int mifare_desfire_debit_ex (FreefareTag tag, uint8_t file_no, int32_t amount, int cs);
|
||||
int mifare_desfire_limited_credit (FreefareTag tag, uint8_t file_no, int32_t amount);
|
||||
int mifare_desfire_limited_credit_ex (FreefareTag tag, uint8_t file_no, int32_t amount, int cs);
|
||||
ssize_t mifare_desfire_write_record (FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data);
|
||||
ssize_t mifare_desfire_write_record_ex (FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data, int cs);
|
||||
ssize_t mifare_desfire_read_records (FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data);
|
||||
ssize_t mifare_desfire_read_records_ex (FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data, int cs);
|
||||
int mifare_desfire_clear_record_file (FreefareTag tag, uint8_t file_no);
|
||||
int mifare_desfire_commit_transaction (FreefareTag tag);
|
||||
int mifare_desfire_abort_transaction (FreefareTag tag);
|
||||
ssize_t mifare_desfire_read_data(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data);
|
||||
ssize_t mifare_desfire_read_data_ex(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data, int cs);
|
||||
ssize_t mifare_desfire_write_data(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, const void *data);
|
||||
ssize_t mifare_desfire_write_data_ex(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, const void *data, int cs);
|
||||
int mifare_desfire_get_value(FreefareTag tag, uint8_t file_no, int32_t *value);
|
||||
int mifare_desfire_get_value_ex(FreefareTag tag, uint8_t file_no, int32_t *value, int cs);
|
||||
int mifare_desfire_credit(FreefareTag tag, uint8_t file_no, int32_t amount);
|
||||
int mifare_desfire_credit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int cs);
|
||||
int mifare_desfire_debit(FreefareTag tag, uint8_t file_no, int32_t amount);
|
||||
int mifare_desfire_debit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int cs);
|
||||
int mifare_desfire_limited_credit(FreefareTag tag, uint8_t file_no, int32_t amount);
|
||||
int mifare_desfire_limited_credit_ex(FreefareTag tag, uint8_t file_no, int32_t amount, int cs);
|
||||
ssize_t mifare_desfire_write_record(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data);
|
||||
ssize_t mifare_desfire_write_record_ex(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data, int cs);
|
||||
ssize_t mifare_desfire_read_records(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data);
|
||||
ssize_t mifare_desfire_read_records_ex(FreefareTag tag, uint8_t file_no, off_t offset, size_t length, void *data, int cs);
|
||||
int mifare_desfire_clear_record_file(FreefareTag tag, uint8_t file_no);
|
||||
int mifare_desfire_commit_transaction(FreefareTag tag);
|
||||
int mifare_desfire_abort_transaction(FreefareTag tag);
|
||||
|
||||
MifareDESFireKey mifare_desfire_des_key_new (const uint8_t value[8]);
|
||||
MifareDESFireKey mifare_desfire_3des_key_new (const uint8_t value[16]);
|
||||
MifareDESFireKey mifare_desfire_des_key_new_with_version (const uint8_t value[8]);
|
||||
MifareDESFireKey mifare_desfire_3des_key_new_with_version (const uint8_t value[16]);
|
||||
MifareDESFireKey mifare_desfire_3k3des_key_new (const uint8_t value[24]);
|
||||
MifareDESFireKey mifare_desfire_3k3des_key_new_with_version (const uint8_t value[24]);
|
||||
MifareDESFireKey mifare_desfire_aes_key_new (const uint8_t value[16]);
|
||||
MifareDESFireKey mifare_desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version);
|
||||
uint8_t mifare_desfire_key_get_version (MifareDESFireKey key);
|
||||
void mifare_desfire_key_set_version (MifareDESFireKey key, uint8_t version);
|
||||
void mifare_desfire_key_free (MifareDESFireKey key);
|
||||
MifareDESFireKey mifare_desfire_des_key_new(const uint8_t value[8]);
|
||||
MifareDESFireKey mifare_desfire_3des_key_new(const uint8_t value[16]);
|
||||
MifareDESFireKey mifare_desfire_des_key_new_with_version(const uint8_t value[8]);
|
||||
MifareDESFireKey mifare_desfire_3des_key_new_with_version(const uint8_t value[16]);
|
||||
MifareDESFireKey mifare_desfire_3k3des_key_new(const uint8_t value[24]);
|
||||
MifareDESFireKey mifare_desfire_3k3des_key_new_with_version(const uint8_t value[24]);
|
||||
MifareDESFireKey mifare_desfire_aes_key_new(const uint8_t value[16]);
|
||||
MifareDESFireKey mifare_desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version);
|
||||
uint8_t mifare_desfire_key_get_version(MifareDESFireKey key);
|
||||
void mifare_desfire_key_set_version(MifareDESFireKey key, uint8_t version);
|
||||
void mifare_desfire_key_free(MifareDESFireKey key);
|
||||
|
||||
uint8_t *tlv_encode (const uint8_t type, const uint8_t *istream, uint16_t isize, size_t *osize);
|
||||
uint8_t *tlv_decode (const uint8_t *istream, uint8_t *type, uint16_t *size);
|
||||
size_t tlv_record_length (const uint8_t *istream, size_t *field_length_size, size_t *field_value_size);
|
||||
uint8_t *tlv_append (uint8_t *a, uint8_t *b);
|
||||
uint8_t *tlv_encode(const uint8_t type, const uint8_t *istream, uint16_t isize, size_t *osize);
|
||||
uint8_t *tlv_decode(const uint8_t *istream, uint8_t *type, uint16_t *size);
|
||||
size_t tlv_record_length(const uint8_t *istream, size_t *field_length_size, size_t *field_value_size);
|
||||
uint8_t *tlv_append(uint8_t *a, uint8_t *b);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif /* !__FREEFARE_H__ */
|
||||
|
|
|
@ -98,14 +98,14 @@
|
|||
|
||||
#define MAX_CRYPTO_BLOCK_SIZE 16
|
||||
|
||||
void *memdup (const void *p, const size_t n);
|
||||
void *memdup(const void *p, const size_t n);
|
||||
|
||||
struct mad_sector_0x00;
|
||||
struct mad_sector_0x10;
|
||||
|
||||
void nxp_crc (uint8_t *crc, const uint8_t value);
|
||||
uint8_t sector_0x00_crc8 (Mad mad);
|
||||
uint8_t sector_0x10_crc8 (Mad mad);
|
||||
void nxp_crc(uint8_t *crc, const uint8_t value);
|
||||
uint8_t sector_0x00_crc8(Mad mad);
|
||||
uint8_t sector_0x10_crc8(Mad mad);
|
||||
|
||||
typedef enum {
|
||||
MCD_SEND,
|
||||
|
@ -137,21 +137,21 @@ typedef enum {
|
|||
#define MAC_MASK 0x0F0
|
||||
#define CMAC_MACK 0xF00
|
||||
|
||||
void *mifare_cryto_preprocess_data (FreefareTag tag, void *data, size_t *nbytes, off_t offset, int communication_settings);
|
||||
void *mifare_cryto_postprocess_data (FreefareTag tag, void *data, ssize_t *nbytes, int communication_settings);
|
||||
void mifare_cypher_single_block (MifareDESFireKey key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size);
|
||||
void mifare_cypher_blocks_chained (FreefareTag tag, MifareDESFireKey key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation);
|
||||
void rol (uint8_t *data, const size_t len);
|
||||
void desfire_crc32 (const uint8_t *data, const size_t len, uint8_t *crc);
|
||||
void desfire_crc32_append (uint8_t *data, const size_t len);
|
||||
size_t key_block_size (const MifareDESFireKey key);
|
||||
size_t padded_data_length (const size_t nbytes, const size_t block_size);
|
||||
size_t maced_data_length (const MifareDESFireKey key, const size_t nbytes);
|
||||
size_t enciphered_data_length (const FreefareTag tag, const size_t nbytes, int communication_settings);
|
||||
void *mifare_cryto_preprocess_data(FreefareTag tag, void *data, size_t *nbytes, off_t offset, int communication_settings);
|
||||
void *mifare_cryto_postprocess_data(FreefareTag tag, void *data, ssize_t *nbytes, int communication_settings);
|
||||
void mifare_cypher_single_block(MifareDESFireKey key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size);
|
||||
void mifare_cypher_blocks_chained(FreefareTag tag, MifareDESFireKey key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation);
|
||||
void rol(uint8_t *data, const size_t len);
|
||||
void desfire_crc32(const uint8_t *data, const size_t len, uint8_t *crc);
|
||||
void desfire_crc32_append(uint8_t *data, const size_t len);
|
||||
size_t key_block_size(const MifareDESFireKey key);
|
||||
size_t padded_data_length(const size_t nbytes, const size_t block_size);
|
||||
size_t maced_data_length(const MifareDESFireKey key, const size_t nbytes);
|
||||
size_t enciphered_data_length(const FreefareTag tag, const size_t nbytes, int communication_settings);
|
||||
|
||||
void cmac_generate_subkeys (MifareDESFireKey key);
|
||||
void cmac (const MifareDESFireKey key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
|
||||
void *assert_crypto_buffer_size (FreefareTag tag, size_t nbytes);
|
||||
void cmac_generate_subkeys(MifareDESFireKey key);
|
||||
void cmac(const MifareDESFireKey key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
|
||||
void *assert_crypto_buffer_size(FreefareTag tag, size_t nbytes);
|
||||
|
||||
#define MIFARE_ULTRALIGHT_PAGE_COUNT 0x10
|
||||
#define MIFARE_ULTRALIGHT_C_PAGE_COUNT 0x30
|
||||
|
@ -172,7 +172,7 @@ struct freefare_tag {
|
|||
nfc_target info;
|
||||
int type;
|
||||
int active;
|
||||
void (*free_tag) (FreefareTag tag);
|
||||
void (*free_tag)(FreefareTag tag);
|
||||
};
|
||||
|
||||
struct felica_tag {
|
||||
|
@ -189,10 +189,10 @@ struct mifare_classic_tag {
|
|||
* address and avoid false cache hit with inconsistent data.
|
||||
*/
|
||||
struct {
|
||||
int16_t sector_trailer_block_number;
|
||||
uint16_t sector_access_bits;
|
||||
int16_t block_number;
|
||||
uint8_t block_access_bits;
|
||||
int16_t sector_trailer_block_number;
|
||||
uint16_t sector_access_bits;
|
||||
int16_t block_number;
|
||||
uint8_t block_access_bits;
|
||||
} cached_access_bits;
|
||||
};
|
||||
|
||||
|
@ -232,8 +232,8 @@ struct mifare_desfire_tag {
|
|||
uint32_t selected_application;
|
||||
};
|
||||
|
||||
MifareDESFireKey mifare_desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], MifareDESFireKey authentication_key);
|
||||
const char *mifare_desfire_error_lookup (uint8_t error);
|
||||
MifareDESFireKey mifare_desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], MifareDESFireKey authentication_key);
|
||||
const char *mifare_desfire_error_lookup(uint8_t error);
|
||||
|
||||
struct mifare_ultralight_tag {
|
||||
struct freefare_tag __tag;
|
||||
|
@ -274,7 +274,7 @@ struct ntag21x_key {
|
|||
#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)
|
||||
|
||||
/*
|
||||
/*
|
||||
* FreefareTag cast macros
|
||||
*
|
||||
* This macros are intended to provide a convenient way to cast abstract
|
||||
|
@ -303,7 +303,7 @@ struct ntag21x_key {
|
|||
|
||||
/*
|
||||
* Buffer management macros.
|
||||
*
|
||||
*
|
||||
* The following macros ease setting-up and using buffers:
|
||||
* BUFFER_INIT (data, 5); // data -> [ xx, xx, xx, xx, xx ]
|
||||
* BUFFER_SIZE (data); // size -> 0
|
||||
|
@ -345,7 +345,7 @@ struct ntag21x_key {
|
|||
*/
|
||||
#define BUFFER_APPEND(buffer_name, data) \
|
||||
do { \
|
||||
buffer_name[__##buffer_name##_n++] = data; \
|
||||
buffer_name[__##buffer_name##_n++] = data; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
|
@ -353,10 +353,10 @@ struct ntag21x_key {
|
|||
*/
|
||||
#define BUFFER_APPEND_BYTES(buffer_name, data, size) \
|
||||
do { \
|
||||
size_t __n = 0; \
|
||||
while (__n < size) { \
|
||||
buffer_name[__##buffer_name##_n++] = ((uint8_t *)data)[__n++]; \
|
||||
} \
|
||||
size_t __n = 0; \
|
||||
while (__n < size) { \
|
||||
buffer_name[__##buffer_name##_n++] = ((uint8_t *)data)[__n++]; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
|
@ -371,17 +371,17 @@ struct ntag21x_key {
|
|||
#if defined(_BYTE_ORDER) && (_BYTE_ORDER != _LITTLE_ENDIAN)
|
||||
#define BUFFER_APPEND_LE(buffer, data, data_size, field_size) \
|
||||
do { \
|
||||
size_t __data_size = data_size; \
|
||||
size_t __field_size = field_size; \
|
||||
while (__field_size--, __data_size--) { \
|
||||
buffer[__##buffer##_n++] = ((uint8_t *)&data)[__field_size]; \
|
||||
} \
|
||||
size_t __data_size = data_size; \
|
||||
size_t __field_size = field_size; \
|
||||
while (__field_size--, __data_size--) { \
|
||||
buffer[__##buffer##_n++] = ((uint8_t *)&data)[__field_size]; \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define BUFFER_APPEND_LE(buffer, data, data_size, field_size) \
|
||||
do { \
|
||||
memcpy (buffer + __##buffer##_n, &data, data_size); \
|
||||
__##buffer##_n += data_size; \
|
||||
memcpy (buffer + __##buffer##_n, &data, data_size); \
|
||||
__##buffer##_n += data_size; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -110,16 +110,16 @@ const MadAid mad_nfcforum_aid = {
|
|||
* Allocate an empty new MAD.
|
||||
*/
|
||||
Mad
|
||||
mad_new (uint8_t version)
|
||||
mad_new(uint8_t version)
|
||||
{
|
||||
Mad mad = malloc (sizeof (*mad));
|
||||
Mad mad = malloc(sizeof(*mad));
|
||||
|
||||
if (!mad)
|
||||
return NULL;
|
||||
|
||||
mad->version = version;
|
||||
memset (&(mad->sector_0x00), 0, sizeof (mad->sector_0x00));
|
||||
memset (&(mad->sector_0x10), 0, sizeof (mad->sector_0x10));
|
||||
memset(&(mad->sector_0x00), 0, sizeof(mad->sector_0x00));
|
||||
memset(&(mad->sector_0x10), 0, sizeof(mad->sector_0x10));
|
||||
|
||||
return mad;
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ mad_new (uint8_t version)
|
|||
* Compute CRC.
|
||||
*/
|
||||
void
|
||||
nxp_crc (uint8_t *crc, const uint8_t value)
|
||||
nxp_crc(uint8_t *crc, const uint8_t value)
|
||||
{
|
||||
/* x^8 + x^4 + x^3 + x^2 + 1 => 0x11d */
|
||||
const uint8_t poly = 0x1d;
|
||||
|
@ -144,30 +144,30 @@ nxp_crc (uint8_t *crc, const uint8_t value)
|
|||
}
|
||||
|
||||
uint8_t
|
||||
sector_0x00_crc8 (Mad mad)
|
||||
sector_0x00_crc8(Mad mad)
|
||||
{
|
||||
uint8_t crc = CRC_PRESET;
|
||||
|
||||
nxp_crc (&crc, mad->sector_0x00.info);
|
||||
nxp_crc(&crc, mad->sector_0x00.info);
|
||||
|
||||
for (int n = 0; n < SECTOR_0X00_AIDS; n++) {
|
||||
nxp_crc (&crc, mad->sector_0x00.aids[n].application_code);
|
||||
nxp_crc (&crc, mad->sector_0x00.aids[n].function_cluster_code);
|
||||
nxp_crc(&crc, mad->sector_0x00.aids[n].application_code);
|
||||
nxp_crc(&crc, mad->sector_0x00.aids[n].function_cluster_code);
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
sector_0x10_crc8 (Mad mad)
|
||||
sector_0x10_crc8(Mad mad)
|
||||
{
|
||||
uint8_t crc = CRC_PRESET;
|
||||
|
||||
nxp_crc (&crc, mad->sector_0x10.info);
|
||||
nxp_crc(&crc, mad->sector_0x10.info);
|
||||
|
||||
for (int n = 0; n < SECTOR_0X10_AIDS; n++) {
|
||||
nxp_crc (&crc, mad->sector_0x10.aids[n].application_code);
|
||||
nxp_crc (&crc, mad->sector_0x10.aids[n].function_cluster_code);
|
||||
nxp_crc(&crc, mad->sector_0x10.aids[n].application_code);
|
||||
nxp_crc(&crc, mad->sector_0x10.aids[n].function_cluster_code);
|
||||
}
|
||||
|
||||
return crc;
|
||||
|
@ -177,21 +177,21 @@ sector_0x10_crc8 (Mad mad)
|
|||
* Read a MAD from the provided MIFARE tag.
|
||||
*/
|
||||
Mad
|
||||
mad_read (FreefareTag tag)
|
||||
mad_read(FreefareTag tag)
|
||||
{
|
||||
Mad mad = malloc (sizeof (*mad));
|
||||
Mad mad = malloc(sizeof(*mad));
|
||||
|
||||
if (!mad)
|
||||
goto error;
|
||||
|
||||
/* Authenticate using MAD key A */
|
||||
if (mifare_classic_authenticate (tag, 0x03, mad_public_key_a, MFC_KEY_A) < 0) {
|
||||
if (mifare_classic_authenticate(tag, 0x03, mad_public_key_a, MFC_KEY_A) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Read first sector trailer block */
|
||||
MifareClassicBlock data;
|
||||
if (mifare_classic_read (tag, 0x03, &data) < 0) {
|
||||
if (mifare_classic_read(tag, 0x03, &data) < 0) {
|
||||
goto error;
|
||||
}
|
||||
uint8_t gpb = data[9];
|
||||
|
@ -216,20 +216,20 @@ mad_read (FreefareTag tag)
|
|||
}
|
||||
|
||||
/* Read MAD data at 0x00 (MAD1, MAD2) */
|
||||
if (mifare_classic_read (tag, 0x01, &data) < 0)
|
||||
if (mifare_classic_read(tag, 0x01, &data) < 0)
|
||||
goto error;
|
||||
|
||||
uint8_t *p = (uint8_t *) &(mad->sector_0x00);
|
||||
memcpy (p, data, sizeof (data));
|
||||
uint8_t *p = (uint8_t *) & (mad->sector_0x00);
|
||||
memcpy(p, data, sizeof(data));
|
||||
|
||||
p+= sizeof (data);
|
||||
p += sizeof(data);
|
||||
|
||||
if (mifare_classic_read (tag, 0x02, &data) < 0)
|
||||
if (mifare_classic_read(tag, 0x02, &data) < 0)
|
||||
goto error;
|
||||
memcpy (p, data, sizeof (data));
|
||||
memcpy(p, data, sizeof(data));
|
||||
|
||||
uint8_t crc = mad->sector_0x00.crc;
|
||||
uint8_t computed_crc = sector_0x00_crc8 (mad);
|
||||
uint8_t computed_crc = sector_0x00_crc8(mad);
|
||||
if (crc != computed_crc)
|
||||
goto error;
|
||||
|
||||
|
@ -237,30 +237,30 @@ mad_read (FreefareTag tag)
|
|||
if (mad->version == 2) {
|
||||
|
||||
/* Authenticate using MAD key A */
|
||||
if (mifare_classic_authenticate (tag, 0x43, mad_public_key_a, MFC_KEY_A) < 0) {
|
||||
if (mifare_classic_authenticate(tag, 0x43, mad_public_key_a, MFC_KEY_A) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
p = (uint8_t *) &(mad->sector_0x10);
|
||||
p = (uint8_t *) & (mad->sector_0x10);
|
||||
|
||||
if (mifare_classic_read (tag, 0x40, &data) < 0)
|
||||
if (mifare_classic_read(tag, 0x40, &data) < 0)
|
||||
goto error;
|
||||
memcpy (p, data, sizeof (data));
|
||||
memcpy(p, data, sizeof(data));
|
||||
|
||||
p += sizeof (data);
|
||||
p += sizeof(data);
|
||||
|
||||
if (mifare_classic_read (tag, 0x41, &data) < 0)
|
||||
if (mifare_classic_read(tag, 0x41, &data) < 0)
|
||||
goto error;
|
||||
memcpy (p, data, sizeof (data));
|
||||
memcpy(p, data, sizeof(data));
|
||||
|
||||
p += sizeof (data);
|
||||
p += sizeof(data);
|
||||
|
||||
if (mifare_classic_read (tag, 0x42, &data) < 0)
|
||||
if (mifare_classic_read(tag, 0x42, &data) < 0)
|
||||
goto error;
|
||||
memcpy (p, data, sizeof (data));
|
||||
memcpy(p, data, sizeof(data));
|
||||
|
||||
crc = mad->sector_0x10.crc;
|
||||
computed_crc = sector_0x10_crc8 (mad);
|
||||
computed_crc = sector_0x10_crc8(mad);
|
||||
if (crc != computed_crc)
|
||||
goto error;
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ mad_read (FreefareTag tag)
|
|||
return mad;
|
||||
|
||||
error:
|
||||
free (mad);
|
||||
free(mad);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -276,17 +276,17 @@ error:
|
|||
* Write the mad to the provided MIFARE tad using the provided Key-B keys.
|
||||
*/
|
||||
int
|
||||
mad_write (FreefareTag tag, Mad mad, const MifareClassicKey key_b_sector_00, const MifareClassicKey key_b_sector_10)
|
||||
mad_write(FreefareTag tag, Mad mad, const MifareClassicKey key_b_sector_00, const MifareClassicKey key_b_sector_10)
|
||||
{
|
||||
MifareClassicBlock data;
|
||||
|
||||
if (mifare_classic_authenticate (tag, 0x00, key_b_sector_00, MFC_KEY_B) < 0)
|
||||
if (mifare_classic_authenticate(tag, 0x00, key_b_sector_00, MFC_KEY_B) < 0)
|
||||
return -1;
|
||||
|
||||
if ((1 != mifare_classic_get_data_block_permission (tag, 0x01, MCAB_W, MFC_KEY_B)) ||
|
||||
(1 != mifare_classic_get_data_block_permission (tag, 0x02, MCAB_W, MFC_KEY_B)) ||
|
||||
(1 != mifare_classic_get_trailer_block_permission (tag, 0x03, MCAB_WRITE_KEYA, MFC_KEY_B)) ||
|
||||
(1 != mifare_classic_get_trailer_block_permission (tag, 0x03, MCAB_WRITE_ACCESS_BITS, MFC_KEY_B))) {
|
||||
if ((1 != mifare_classic_get_data_block_permission(tag, 0x01, MCAB_W, MFC_KEY_B)) ||
|
||||
(1 != mifare_classic_get_data_block_permission(tag, 0x02, MCAB_W, MFC_KEY_B)) ||
|
||||
(1 != mifare_classic_get_trailer_block_permission(tag, 0x03, MCAB_WRITE_KEYA, MFC_KEY_B)) ||
|
||||
(1 != mifare_classic_get_trailer_block_permission(tag, 0x03, MCAB_WRITE_ACCESS_BITS, MFC_KEY_B))) {
|
||||
errno = EPERM;
|
||||
return -1;
|
||||
}
|
||||
|
@ -309,42 +309,42 @@ mad_write (FreefareTag tag, Mad mad, const MifareClassicKey key_b_sector_00, con
|
|||
}
|
||||
|
||||
if (2 == mad->version) {
|
||||
if (mifare_classic_authenticate (tag, 0x40, key_b_sector_10, MFC_KEY_B) < 0)
|
||||
if (mifare_classic_authenticate(tag, 0x40, key_b_sector_10, MFC_KEY_B) < 0)
|
||||
return -1;
|
||||
|
||||
if ((1 != mifare_classic_get_data_block_permission (tag, 0x40, MCAB_W, MFC_KEY_B)) ||
|
||||
(1 != mifare_classic_get_data_block_permission (tag, 0x41, MCAB_W, MFC_KEY_B)) ||
|
||||
(1 != mifare_classic_get_data_block_permission (tag, 0x42, MCAB_W, MFC_KEY_B)) ||
|
||||
(1 != mifare_classic_get_trailer_block_permission (tag, 0x43, MCAB_WRITE_KEYA, MFC_KEY_B)) ||
|
||||
(1 != mifare_classic_get_trailer_block_permission (tag, 0x43, MCAB_WRITE_ACCESS_BITS, MFC_KEY_B))) {
|
||||
if ((1 != mifare_classic_get_data_block_permission(tag, 0x40, MCAB_W, MFC_KEY_B)) ||
|
||||
(1 != mifare_classic_get_data_block_permission(tag, 0x41, MCAB_W, MFC_KEY_B)) ||
|
||||
(1 != mifare_classic_get_data_block_permission(tag, 0x42, MCAB_W, MFC_KEY_B)) ||
|
||||
(1 != mifare_classic_get_trailer_block_permission(tag, 0x43, MCAB_WRITE_KEYA, MFC_KEY_B)) ||
|
||||
(1 != mifare_classic_get_trailer_block_permission(tag, 0x43, MCAB_WRITE_ACCESS_BITS, MFC_KEY_B))) {
|
||||
errno = EPERM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
mad->sector_0x10.crc = sector_0x10_crc8 (mad);
|
||||
mad->sector_0x10.crc = sector_0x10_crc8(mad);
|
||||
|
||||
memcpy (data, (uint8_t *)&(mad->sector_0x10), sizeof (data));
|
||||
if (mifare_classic_write (tag, 0x40, data) < 0) return -1;
|
||||
memcpy (data, (uint8_t *)&(mad->sector_0x10) + sizeof (data), sizeof (data));
|
||||
if (mifare_classic_write (tag, 0x41, data) < 0) return -1;
|
||||
memcpy (data, (uint8_t *)&(mad->sector_0x10) + sizeof (data) * 2, sizeof (data));
|
||||
if (mifare_classic_write (tag, 0x42, data) < 0) return -1;
|
||||
memcpy(data, (uint8_t *) & (mad->sector_0x10), sizeof(data));
|
||||
if (mifare_classic_write(tag, 0x40, data) < 0) return -1;
|
||||
memcpy(data, (uint8_t *) & (mad->sector_0x10) + sizeof(data), sizeof(data));
|
||||
if (mifare_classic_write(tag, 0x41, data) < 0) return -1;
|
||||
memcpy(data, (uint8_t *) & (mad->sector_0x10) + sizeof(data) * 2, sizeof(data));
|
||||
if (mifare_classic_write(tag, 0x42, data) < 0) return -1;
|
||||
|
||||
mifare_classic_trailer_block (&data, mad_public_key_a, 0x0, 0x1, 0x1, 0x6, 0x00, key_b_sector_10);
|
||||
if (mifare_classic_write (tag, 0x43, data) < 0) return -1;
|
||||
mifare_classic_trailer_block(&data, mad_public_key_a, 0x0, 0x1, 0x1, 0x6, 0x00, key_b_sector_10);
|
||||
if (mifare_classic_write(tag, 0x43, data) < 0) return -1;
|
||||
|
||||
}
|
||||
|
||||
mad->sector_0x00.crc = sector_0x00_crc8 (mad);
|
||||
mad->sector_0x00.crc = sector_0x00_crc8(mad);
|
||||
|
||||
if (mifare_classic_authenticate (tag, 0x00, key_b_sector_00, MFC_KEY_B) < 0) return -1;
|
||||
memcpy (data, (uint8_t *)&(mad->sector_0x00), sizeof (data));
|
||||
if (mifare_classic_write (tag, 0x01, data) < 0) return -1;
|
||||
memcpy (data, (uint8_t *)&(mad->sector_0x00) + sizeof (data), sizeof (data));
|
||||
if (mifare_classic_write (tag, 0x02, data) < 0) return -1;
|
||||
if (mifare_classic_authenticate(tag, 0x00, key_b_sector_00, MFC_KEY_B) < 0) return -1;
|
||||
memcpy(data, (uint8_t *) & (mad->sector_0x00), sizeof(data));
|
||||
if (mifare_classic_write(tag, 0x01, data) < 0) return -1;
|
||||
memcpy(data, (uint8_t *) & (mad->sector_0x00) + sizeof(data), sizeof(data));
|
||||
if (mifare_classic_write(tag, 0x02, data) < 0) return -1;
|
||||
|
||||
mifare_classic_trailer_block (&data, mad_public_key_a, 0x0, 0x1, 0x1, 0x6, gpb, key_b_sector_00);
|
||||
if (mifare_classic_write (tag, 0x03, data) < 0) return -1;
|
||||
mifare_classic_trailer_block(&data, mad_public_key_a, 0x0, 0x1, 0x1, 0x6, gpb, key_b_sector_00);
|
||||
if (mifare_classic_write(tag, 0x03, data) < 0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -353,7 +353,7 @@ mad_write (FreefareTag tag, Mad mad, const MifareClassicKey key_b_sector_00, con
|
|||
* Return a MAD version.
|
||||
*/
|
||||
int
|
||||
mad_get_version (Mad mad)
|
||||
mad_get_version(Mad mad)
|
||||
{
|
||||
return mad->version;
|
||||
}
|
||||
|
@ -362,11 +362,11 @@ mad_get_version (Mad mad)
|
|||
* Set a MAD version.
|
||||
*/
|
||||
void
|
||||
mad_set_version (Mad mad, const uint8_t version)
|
||||
mad_set_version(Mad mad, const uint8_t version)
|
||||
{
|
||||
if ((version == 2) && (mad->version == 1)) {
|
||||
/* We use a larger MAD so initialise the new blocks */
|
||||
memset (&(mad->sector_0x10), 0, sizeof (mad->sector_0x10));
|
||||
memset(&(mad->sector_0x10), 0, sizeof(mad->sector_0x10));
|
||||
}
|
||||
mad->version = version;
|
||||
}
|
||||
|
@ -449,7 +449,7 @@ mad_set_aid(Mad mad, const MifareClassicSectorNumber sector, MadAid aid)
|
|||
}
|
||||
|
||||
bool
|
||||
mad_sector_reserved (const MifareClassicSectorNumber sector)
|
||||
mad_sector_reserved(const MifareClassicSectorNumber sector)
|
||||
{
|
||||
return ((0x00 == sector) || (0x10 == sector));
|
||||
}
|
||||
|
@ -458,7 +458,7 @@ mad_sector_reserved (const MifareClassicSectorNumber sector)
|
|||
* Free memory allocated by mad_new() and mad_read().
|
||||
*/
|
||||
void
|
||||
mad_free (Mad mad)
|
||||
mad_free(Mad mad)
|
||||
{
|
||||
free (mad);
|
||||
free(mad);
|
||||
}
|
||||
|
|
|
@ -35,24 +35,24 @@
|
|||
|
||||
#define FIRST_SECTOR 1
|
||||
|
||||
int aidcmp (const MadAid left, const MadAid right);
|
||||
size_t count_aids (const Mad mad, const MadAid aid);
|
||||
int aidcmp(const MadAid left, const MadAid right);
|
||||
size_t count_aids(const Mad mad, const MadAid aid);
|
||||
|
||||
/*
|
||||
* Get the number of sectors allocated in the MAD for the provided application.
|
||||
*/
|
||||
size_t
|
||||
count_aids (const Mad mad, const MadAid aid)
|
||||
count_aids(const Mad mad, const MadAid aid)
|
||||
{
|
||||
size_t result = 0;
|
||||
|
||||
MifareClassicSectorNumber s_max = (mad_get_version (mad) == 1) ? 0x0f : 0x27;
|
||||
MifareClassicSectorNumber s_max = (mad_get_version(mad) == 1) ? 0x0f : 0x27;
|
||||
|
||||
/* Count application sectors */
|
||||
MadAid c_aid;
|
||||
for (MifareClassicSectorNumber s = FIRST_SECTOR; s <= s_max; s++) {
|
||||
mad_get_aid (mad, s, &c_aid);
|
||||
if (0 == aidcmp (aid, c_aid)) {
|
||||
mad_get_aid(mad, s, &c_aid);
|
||||
if (0 == aidcmp(aid, c_aid)) {
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ count_aids (const Mad mad, const MadAid aid)
|
|||
* Compare two application identifiers.
|
||||
*/
|
||||
inline int
|
||||
aidcmp (const MadAid left, const MadAid right)
|
||||
aidcmp(const MadAid left, const MadAid right)
|
||||
{
|
||||
return ((left.function_cluster_code - right.function_cluster_code) << 8) | (left.application_code - right.application_code);
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ aidcmp (const MadAid left, const MadAid right)
|
|||
* Allocates a new application into a MAD.
|
||||
*/
|
||||
MifareClassicSectorNumber *
|
||||
mifare_application_alloc (Mad mad, MadAid aid, size_t size)
|
||||
mifare_application_alloc(Mad mad, MadAid aid, size_t size)
|
||||
{
|
||||
uint8_t sector_map[40];
|
||||
MifareClassicSectorNumber sector;
|
||||
|
@ -90,12 +90,12 @@ mifare_application_alloc (Mad mad, MadAid aid, size_t size)
|
|||
* Ensure the card does not already have the application registered.
|
||||
*/
|
||||
MifareClassicSectorNumber *found;
|
||||
if ((found = mifare_application_find (mad, aid))) {
|
||||
free (found);
|
||||
if ((found = mifare_application_find(mad, aid))) {
|
||||
free(found);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sizeof (sector_map); i++)
|
||||
for (size_t i = 0; i < sizeof(sector_map); i++)
|
||||
sector_map[i] = 0;
|
||||
|
||||
/*
|
||||
|
@ -103,27 +103,27 @@ mifare_application_alloc (Mad mad, MadAid aid, size_t size)
|
|||
* when the target is a Mifare Classic 4k.
|
||||
*/
|
||||
MadAid free_aid = { 0x00, 0x00 };
|
||||
if (mad_get_version (mad) == 2) {
|
||||
if (mad_get_version(mad) == 2) {
|
||||
sector = 32;
|
||||
while ((s >= 12*16) && sector < 40) {
|
||||
mad_get_aid (mad, sector, §or_aid);
|
||||
if (0 == aidcmp (sector_aid, free_aid)) {
|
||||
while ((s >= 12 * 16) && sector < 40) {
|
||||
mad_get_aid(mad, sector, §or_aid);
|
||||
if (0 == aidcmp(sector_aid, free_aid)) {
|
||||
sector_map[sector] = 1;
|
||||
s -= 15*16;
|
||||
s -= 15 * 16;
|
||||
}
|
||||
sector++;
|
||||
}
|
||||
}
|
||||
|
||||
sector = FIRST_SECTOR;
|
||||
MifareClassicSectorNumber s_max = (mad_get_version (mad) == 1) ? 15 : 31;
|
||||
MifareClassicSectorNumber s_max = (mad_get_version(mad) == 1) ? 15 : 31;
|
||||
while ((s > 0) && (sector <= s_max)) {
|
||||
if (mad_sector_reserved (sector))
|
||||
if (mad_sector_reserved(sector))
|
||||
continue;
|
||||
mad_get_aid (mad, sector, §or_aid);
|
||||
if (0 == aidcmp (sector_aid, free_aid)) {
|
||||
mad_get_aid(mad, sector, §or_aid);
|
||||
if (0 == aidcmp(sector_aid, free_aid)) {
|
||||
sector_map[sector] = 1;
|
||||
s -= 3*16;
|
||||
s -= 3 * 16;
|
||||
}
|
||||
sector++;
|
||||
}
|
||||
|
@ -135,18 +135,18 @@ mifare_application_alloc (Mad mad, MadAid aid, size_t size)
|
|||
return NULL;
|
||||
|
||||
int n = 0;
|
||||
for (size_t i = FIRST_SECTOR; i < sizeof (sector_map); i++)
|
||||
for (size_t i = FIRST_SECTOR; i < sizeof(sector_map); i++)
|
||||
if (sector_map[i])
|
||||
n++;
|
||||
|
||||
if (!(res = malloc (sizeof (*res) * (n+1))))
|
||||
if (!(res = malloc(sizeof(*res) * (n + 1))))
|
||||
return NULL;
|
||||
|
||||
n = 0;
|
||||
for (size_t i = FIRST_SECTOR; i < sizeof (sector_map); i++)
|
||||
for (size_t i = FIRST_SECTOR; i < sizeof(sector_map); i++)
|
||||
if (sector_map[i]) {
|
||||
res[n] = i;
|
||||
mad_set_aid (mad, i, aid);
|
||||
mad_set_aid(mad, i, aid);
|
||||
n++;
|
||||
}
|
||||
|
||||
|
@ -160,21 +160,21 @@ mifare_application_alloc (Mad mad, MadAid aid, size_t size)
|
|||
* Remove an application from a MAD.
|
||||
*/
|
||||
int
|
||||
mifare_application_free (Mad mad, MadAid aid)
|
||||
mifare_application_free(Mad mad, MadAid aid)
|
||||
{
|
||||
MifareClassicSectorNumber *sectors = mifare_application_find (mad, aid);
|
||||
MifareClassicSectorNumber *sectors = mifare_application_find(mad, aid);
|
||||
MifareClassicSectorNumber *p = sectors;
|
||||
MadAid free_aid = { 0x00, 0x00 };
|
||||
|
||||
/* figure out if malloc() in mifare_application_find() failed */
|
||||
if (sectors == NULL) return count_aids (mad, aid) ? -1 : 0;
|
||||
if (sectors == NULL) return count_aids(mad, aid) ? -1 : 0;
|
||||
|
||||
while (*p) {
|
||||
mad_set_aid (mad, *p, free_aid);
|
||||
mad_set_aid(mad, *p, free_aid);
|
||||
p++;
|
||||
}
|
||||
|
||||
free (sectors);
|
||||
free(sectors);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -188,21 +188,21 @@ mifare_application_free (Mad mad, MadAid aid)
|
|||
* Get all sector numbers of an application from the provided MAD.
|
||||
*/
|
||||
MifareClassicSectorNumber *
|
||||
mifare_application_find (Mad mad, MadAid aid)
|
||||
mifare_application_find(Mad mad, MadAid aid)
|
||||
{
|
||||
MifareClassicSectorNumber *res = NULL;
|
||||
size_t res_count = count_aids (mad, aid);
|
||||
size_t res_count = count_aids(mad, aid);
|
||||
|
||||
if (res_count)
|
||||
res = malloc (sizeof (*res) * (res_count + 1));
|
||||
res = malloc(sizeof(*res) * (res_count + 1));
|
||||
|
||||
size_t r = FIRST_SECTOR, w = 0;
|
||||
if (res) {
|
||||
/* Fill in the result */
|
||||
MadAid c_aid;
|
||||
while (w < res_count) {
|
||||
mad_get_aid (mad, r, &c_aid);
|
||||
if (0 == aidcmp (c_aid, aid)) {
|
||||
mad_get_aid(mad, r, &c_aid);
|
||||
if (0 == aidcmp(c_aid, aid)) {
|
||||
res[w++] = r;
|
||||
}
|
||||
r++;
|
||||
|
@ -214,36 +214,36 @@ mifare_application_find (Mad mad, MadAid aid)
|
|||
}
|
||||
|
||||
ssize_t
|
||||
mifare_application_read (FreefareTag tag, Mad mad, const MadAid aid, void *buf, size_t nbytes, const MifareClassicKey key, const MifareClassicKeyType key_type)
|
||||
mifare_application_read(FreefareTag tag, Mad mad, const MadAid aid, void *buf, size_t nbytes, const MifareClassicKey key, const MifareClassicKeyType key_type)
|
||||
{
|
||||
ssize_t res = 0;
|
||||
|
||||
MifareClassicSectorNumber *sectors = mifare_application_find (mad, aid);
|
||||
MifareClassicSectorNumber *sectors = mifare_application_find(mad, aid);
|
||||
MifareClassicSectorNumber *s = sectors;
|
||||
|
||||
if (!sectors)
|
||||
return errno = EBADF, -1;
|
||||
|
||||
while (*s && nbytes && (res >= 0)) {
|
||||
MifareClassicBlockNumber first_block = mifare_classic_sector_first_block (*s);
|
||||
MifareClassicBlockNumber last_block = mifare_classic_sector_last_block (*s);
|
||||
MifareClassicBlockNumber first_block = mifare_classic_sector_first_block(*s);
|
||||
MifareClassicBlockNumber last_block = mifare_classic_sector_last_block(*s);
|
||||
|
||||
MifareClassicBlockNumber b = first_block;
|
||||
MifareClassicBlock block;
|
||||
|
||||
if (mifare_classic_authenticate (tag, first_block, key, key_type) < 0) {
|
||||
if (mifare_classic_authenticate(tag, first_block, key, key_type) < 0) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
while ((b < last_block) && nbytes) {
|
||||
size_t n = MIN (nbytes, 16);
|
||||
size_t n = MIN(nbytes, 16);
|
||||
|
||||
if (mifare_classic_read (tag, b, &block) < 0) {
|
||||
if (mifare_classic_read(tag, b, &block) < 0) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
memcpy ((uint8_t *)buf + res, &block, n);
|
||||
memcpy((uint8_t *)buf + res, &block, n);
|
||||
|
||||
nbytes -= n;
|
||||
res += n;
|
||||
|
@ -254,16 +254,16 @@ mifare_application_read (FreefareTag tag, Mad mad, const MadAid aid, void *buf,
|
|||
s++;
|
||||
}
|
||||
|
||||
free (sectors);
|
||||
free(sectors);
|
||||
return res;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
mifare_application_write (FreefareTag tag, Mad mad, const MadAid aid, const void *buf, size_t nbytes, const MifareClassicKey key, const MifareClassicKeyType key_type)
|
||||
mifare_application_write(FreefareTag tag, Mad mad, const MadAid aid, const void *buf, size_t nbytes, const MifareClassicKey key, const MifareClassicKeyType key_type)
|
||||
{
|
||||
ssize_t res = 0;
|
||||
|
||||
MifareClassicSectorNumber *sectors = mifare_application_find (mad, aid);
|
||||
MifareClassicSectorNumber *sectors = mifare_application_find(mad, aid);
|
||||
MifareClassicSectorNumber *s = sectors;
|
||||
|
||||
if (!sectors) {
|
||||
|
@ -273,29 +273,29 @@ mifare_application_write (FreefareTag tag, Mad mad, const MadAid aid, const void
|
|||
}
|
||||
|
||||
while (*s && nbytes && (res >= 0)) {
|
||||
MifareClassicBlockNumber first_block = mifare_classic_sector_first_block (*s);
|
||||
MifareClassicBlockNumber last_block = mifare_classic_sector_last_block (*s);
|
||||
MifareClassicBlockNumber first_block = mifare_classic_sector_first_block(*s);
|
||||
MifareClassicBlockNumber last_block = mifare_classic_sector_last_block(*s);
|
||||
|
||||
MifareClassicBlockNumber b = first_block;
|
||||
MifareClassicBlock block;
|
||||
|
||||
if (mifare_classic_authenticate (tag, first_block, key, key_type) < 0) {
|
||||
if (mifare_classic_authenticate(tag, first_block, key, key_type) < 0) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
while ((b < last_block) && nbytes) {
|
||||
size_t n = MIN (nbytes, 16);
|
||||
size_t n = MIN(nbytes, 16);
|
||||
// Avoid overwriting existing data with uninitialized memory.
|
||||
if (n < 16) {
|
||||
if (mifare_classic_read (tag, b, &block) < 0) {
|
||||
if (mifare_classic_read(tag, b, &block) < 0) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (&block, (uint8_t *)buf + res, n);
|
||||
if (mifare_classic_write (tag, b, block) < 0) {
|
||||
memcpy(&block, (uint8_t *)buf + res, n);
|
||||
if (mifare_classic_write(tag, b, block) < 0) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ mifare_application_write (FreefareTag tag, Mad mad, const MadAid aid, const void
|
|||
s++;
|
||||
}
|
||||
|
||||
free (sectors);
|
||||
free(sectors);
|
||||
return res;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2009, 2010, Romain Tartiere, Romuald Conty.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -87,19 +87,19 @@
|
|||
|
||||
#define CLASSIC_TRANSCEIVE_EX(tag, msg, res, disconnect) \
|
||||
do { \
|
||||
errno = 0; \
|
||||
DEBUG_XFER (msg, __##msg##_n, "===> "); \
|
||||
int _res; \
|
||||
if ((_res = nfc_initiator_transceive_bytes (tag->device, msg, __##msg##_n, res, __##res##_size, 0)) < 0) { \
|
||||
if (disconnect) { \
|
||||
tag->active = false; \
|
||||
} \
|
||||
if (_res == NFC_EMFCAUTHFAIL) \
|
||||
return errno = EACCES, -1; \
|
||||
return errno = EIO, -1; \
|
||||
} \
|
||||
__##res##_n = _res; \
|
||||
DEBUG_XFER (res, __##res##_n, "<=== "); \
|
||||
errno = 0; \
|
||||
DEBUG_XFER (msg, __##msg##_n, "===> "); \
|
||||
int _res; \
|
||||
if ((_res = nfc_initiator_transceive_bytes (tag->device, msg, __##msg##_n, res, __##res##_size, 0)) < 0) { \
|
||||
if (disconnect) { \
|
||||
tag->active = false; \
|
||||
} \
|
||||
if (_res == NFC_EMFCAUTHFAIL) \
|
||||
return errno = EACCES, -1; \
|
||||
return errno = EIO, -1; \
|
||||
} \
|
||||
__##res##_n = _res; \
|
||||
DEBUG_XFER (res, __##res##_n, "<=== "); \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
@ -187,8 +187,8 @@ uint16_t mifare_trailer_access_permissions[] = {
|
|||
* Private functions
|
||||
*/
|
||||
|
||||
int get_block_access_bits_shift (MifareClassicBlockNumber block, MifareClassicBlockNumber trailer);
|
||||
int get_block_access_bits (FreefareTag tag, const MifareClassicBlockNumber block, MifareClassicAccessBits *block_access_bits);
|
||||
int get_block_access_bits_shift(MifareClassicBlockNumber block, MifareClassicBlockNumber trailer);
|
||||
int get_block_access_bits(FreefareTag tag, const MifareClassicBlockNumber block, MifareClassicAccessBits *block_access_bits);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -196,37 +196,37 @@ int get_block_access_bits (FreefareTag tag, const MifareClassicBlockNumber blo
|
|||
*/
|
||||
|
||||
bool
|
||||
mifare_mini_taste (nfc_device *device, nfc_target target)
|
||||
mifare_mini_taste(nfc_device *device, nfc_target target)
|
||||
{
|
||||
(void) device;
|
||||
return target.nm.nmt == NMT_ISO14443A &&
|
||||
(
|
||||
target.nti.nai.btSak == 0x09
|
||||
);
|
||||
(
|
||||
target.nti.nai.btSak == 0x09
|
||||
);
|
||||
}
|
||||
|
||||
bool
|
||||
mifare_classic1k_taste (nfc_device *device, nfc_target target)
|
||||
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
|
||||
);
|
||||
(
|
||||
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)
|
||||
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
|
||||
);
|
||||
(
|
||||
target.nti.nai.btSak == 0x18 ||
|
||||
target.nti.nai.btSak == 0x38
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -234,11 +234,11 @@ mifare_classic4k_taste (nfc_device *device, nfc_target target)
|
|||
*/
|
||||
|
||||
static FreefareTag
|
||||
_mifare_classic_tag_new (nfc_device *device, nfc_target target, int tag_type)
|
||||
_mifare_classic_tag_new(nfc_device *device, nfc_target target, int tag_type)
|
||||
{
|
||||
FreefareTag tag;
|
||||
|
||||
if ((tag = malloc (sizeof (struct mifare_classic_tag)))) {
|
||||
if ((tag = malloc(sizeof(struct mifare_classic_tag)))) {
|
||||
tag->type = tag_type;
|
||||
tag->free_tag = mifare_classic_tag_free;
|
||||
tag->device = device;
|
||||
|
@ -251,30 +251,30 @@ _mifare_classic_tag_new (nfc_device *device, nfc_target target, int tag_type)
|
|||
|
||||
|
||||
FreefareTag
|
||||
mifare_mini_tag_new (nfc_device *device, nfc_target target)
|
||||
mifare_mini_tag_new(nfc_device *device, nfc_target target)
|
||||
{
|
||||
return _mifare_classic_tag_new (device, target, MIFARE_MINI);
|
||||
return _mifare_classic_tag_new(device, target, MIFARE_MINI);
|
||||
}
|
||||
|
||||
FreefareTag
|
||||
mifare_classic1k_tag_new (nfc_device *device, nfc_target target)
|
||||
mifare_classic1k_tag_new(nfc_device *device, nfc_target target)
|
||||
{
|
||||
return _mifare_classic_tag_new (device, target, MIFARE_CLASSIC_1K);
|
||||
return _mifare_classic_tag_new(device, target, MIFARE_CLASSIC_1K);
|
||||
}
|
||||
|
||||
FreefareTag
|
||||
mifare_classic4k_tag_new (nfc_device *device, nfc_target target)
|
||||
mifare_classic4k_tag_new(nfc_device *device, nfc_target target)
|
||||
{
|
||||
return _mifare_classic_tag_new (device, target, MIFARE_CLASSIC_4K);
|
||||
return _mifare_classic_tag_new(device, target, MIFARE_CLASSIC_4K);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the provided tag.
|
||||
*/
|
||||
void
|
||||
mifare_classic_tag_free (FreefareTag tag)
|
||||
mifare_classic_tag_free(FreefareTag tag)
|
||||
{
|
||||
free (tag);
|
||||
free(tag);
|
||||
}
|
||||
|
||||
|
||||
|
@ -290,16 +290,16 @@ mifare_classic_tag_free (FreefareTag tag)
|
|||
* Establish connection to the provided tag.
|
||||
*/
|
||||
int
|
||||
mifare_classic_connect (FreefareTag tag)
|
||||
mifare_classic_connect(FreefareTag tag)
|
||||
{
|
||||
ASSERT_INACTIVE (tag);
|
||||
ASSERT_INACTIVE(tag);
|
||||
|
||||
nfc_target pnti;
|
||||
nfc_modulation modulation = {
|
||||
.nmt = NMT_ISO14443A,
|
||||
.nbr = NBR_106
|
||||
};
|
||||
if (nfc_initiator_select_passive_target (tag->device, modulation, tag->info.nti.nai.abtUid, tag->info.nti.nai.szUidLen, &pnti) >= 0) {
|
||||
if (nfc_initiator_select_passive_target(tag->device, modulation, tag->info.nti.nai.abtUid, tag->info.nti.nai.szUidLen, &pnti) >= 0) {
|
||||
tag->active = 1;
|
||||
} else {
|
||||
errno = EIO;
|
||||
|
@ -312,11 +312,11 @@ mifare_classic_connect (FreefareTag tag)
|
|||
* Terminate connection with the provided tag.
|
||||
*/
|
||||
int
|
||||
mifare_classic_disconnect (FreefareTag tag)
|
||||
mifare_classic_disconnect(FreefareTag tag)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
ASSERT_ACTIVE(tag);
|
||||
|
||||
if (nfc_initiator_deselect_target (tag->device) >= 0) {
|
||||
if (nfc_initiator_deselect_target(tag->device) >= 0) {
|
||||
tag->active = 0;
|
||||
} else {
|
||||
errno = EIO;
|
||||
|
@ -337,57 +337,57 @@ mifare_classic_disconnect (FreefareTag tag)
|
|||
* Send an authentification command to the provided MIFARE target.
|
||||
*/
|
||||
int
|
||||
mifare_classic_authenticate (FreefareTag tag, const MifareClassicBlockNumber block, const MifareClassicKey key, const MifareClassicKeyType key_type)
|
||||
mifare_classic_authenticate(FreefareTag tag, const MifareClassicBlockNumber block, const MifareClassicKey key, const MifareClassicKeyType key_type)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
ASSERT_ACTIVE(tag);
|
||||
|
||||
BUFFER_INIT (cmd, 12);
|
||||
BUFFER_INIT (res, 1);
|
||||
BUFFER_INIT(cmd, 12);
|
||||
BUFFER_INIT(res, 1);
|
||||
|
||||
if (key_type == MFC_KEY_A)
|
||||
BUFFER_APPEND (cmd, MC_AUTH_A);
|
||||
BUFFER_APPEND(cmd, MC_AUTH_A);
|
||||
else
|
||||
BUFFER_APPEND (cmd, MC_AUTH_B);
|
||||
BUFFER_APPEND(cmd, MC_AUTH_B);
|
||||
|
||||
BUFFER_APPEND(cmd, block);
|
||||
BUFFER_APPEND_BYTES (cmd, key, 6);
|
||||
BUFFER_APPEND_BYTES(cmd, key, 6);
|
||||
// To support both 4-byte & 7-byte UID cards:
|
||||
BUFFER_APPEND_BYTES (cmd, tag->info.nti.nai.abtUid + tag->info.nti.nai.szUidLen - 4, 4);
|
||||
BUFFER_APPEND_BYTES(cmd, tag->info.nti.nai.abtUid + tag->info.nti.nai.szUidLen - 4, 4);
|
||||
|
||||
CLASSIC_TRANSCEIVE_EX (tag, cmd, res, 1);
|
||||
CLASSIC_TRANSCEIVE_EX(tag, cmd, res, 1);
|
||||
|
||||
MIFARE_CLASSIC(tag)->cached_access_bits.sector_trailer_block_number = -1;
|
||||
MIFARE_CLASSIC(tag)->cached_access_bits.sector_access_bits = 0x00;
|
||||
MIFARE_CLASSIC(tag)->last_authentication_key_type = key_type;
|
||||
|
||||
return (BUFFER_SIZE (res) == 0) ? 0 : res[0];
|
||||
return (BUFFER_SIZE(res) == 0) ? 0 : res[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* Read data from the provided MIFARE target.
|
||||
*/
|
||||
int
|
||||
mifare_classic_read (FreefareTag tag, const MifareClassicBlockNumber block, MifareClassicBlock *data)
|
||||
mifare_classic_read(FreefareTag tag, const MifareClassicBlockNumber block, MifareClassicBlock *data)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
ASSERT_ACTIVE(tag);
|
||||
|
||||
BUFFER_INIT (cmd, 2);
|
||||
BUFFER_ALIAS (res, data, sizeof(MifareClassicBlock));
|
||||
BUFFER_INIT(cmd, 2);
|
||||
BUFFER_ALIAS(res, data, sizeof(MifareClassicBlock));
|
||||
|
||||
BUFFER_APPEND (cmd, MC_READ);
|
||||
BUFFER_APPEND (cmd, block);
|
||||
BUFFER_APPEND(cmd, MC_READ);
|
||||
BUFFER_APPEND(cmd, block);
|
||||
|
||||
CLASSIC_TRANSCEIVE (tag, cmd, res);
|
||||
CLASSIC_TRANSCEIVE(tag, cmd, res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mifare_classic_init_value (FreefareTag tag, const MifareClassicBlockNumber block, const int32_t value, const MifareClassicBlockNumber adr)
|
||||
mifare_classic_init_value(FreefareTag tag, const MifareClassicBlockNumber block, const int32_t value, const MifareClassicBlockNumber adr)
|
||||
{
|
||||
union mifare_classic_block b;
|
||||
|
||||
uint32_t le_value = htole32 ((uint32_t)value);
|
||||
uint32_t le_value = htole32((uint32_t)value);
|
||||
|
||||
b.value.value = le_value;
|
||||
b.value.value_ = ~le_value;
|
||||
|
@ -398,18 +398,18 @@ mifare_classic_init_value (FreefareTag tag, const MifareClassicBlockNumber block
|
|||
b.value.address__ = adr;
|
||||
b.value.address___ = ~adr;
|
||||
|
||||
if (mifare_classic_write (tag, block, b.data) < 0)
|
||||
if (mifare_classic_write(tag, block, b.data) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mifare_classic_read_value (FreefareTag tag, const MifareClassicBlockNumber block, int32_t *value, MifareClassicBlockNumber *adr)
|
||||
mifare_classic_read_value(FreefareTag tag, const MifareClassicBlockNumber block, int32_t *value, MifareClassicBlockNumber *adr)
|
||||
{
|
||||
union mifare_classic_block b;
|
||||
|
||||
if (mifare_classic_read (tag, block, &b.data) < 0)
|
||||
if (mifare_classic_read(tag, block, &b.data) < 0)
|
||||
return -1;
|
||||
|
||||
if ((b.value.value ^ (uint32_t)~b.value.value_) || (b.value.value != b.value.value__)) {
|
||||
|
@ -423,7 +423,7 @@ mifare_classic_read_value (FreefareTag tag, const MifareClassicBlockNumber block
|
|||
}
|
||||
|
||||
if (value)
|
||||
*value = le32toh (b.value.value);
|
||||
*value = le32toh(b.value.value);
|
||||
|
||||
if (adr)
|
||||
*adr = b.value.address;
|
||||
|
@ -435,20 +435,20 @@ mifare_classic_read_value (FreefareTag tag, const MifareClassicBlockNumber block
|
|||
* Write data to the provided MIFARE target.
|
||||
*/
|
||||
int
|
||||
mifare_classic_write (FreefareTag tag, const MifareClassicBlockNumber block, const MifareClassicBlock data)
|
||||
mifare_classic_write(FreefareTag tag, const MifareClassicBlockNumber block, const MifareClassicBlock data)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
ASSERT_ACTIVE(tag);
|
||||
|
||||
BUFFER_INIT (cmd, 2 + sizeof (MifareClassicBlock));
|
||||
BUFFER_INIT (res, 1);
|
||||
BUFFER_INIT(cmd, 2 + sizeof(MifareClassicBlock));
|
||||
BUFFER_INIT(res, 1);
|
||||
|
||||
BUFFER_APPEND (cmd, MC_WRITE);
|
||||
BUFFER_APPEND (cmd, block);
|
||||
BUFFER_APPEND_BYTES (cmd, data, sizeof (MifareClassicBlock));
|
||||
BUFFER_APPEND(cmd, MC_WRITE);
|
||||
BUFFER_APPEND(cmd, block);
|
||||
BUFFER_APPEND_BYTES(cmd, data, sizeof(MifareClassicBlock));
|
||||
|
||||
CLASSIC_TRANSCEIVE (tag, cmd, res);
|
||||
CLASSIC_TRANSCEIVE(tag, cmd, res);
|
||||
|
||||
return (BUFFER_SIZE (res) == 0) ? 0 : res[0];
|
||||
return (BUFFER_SIZE(res) == 0) ? 0 : res[0];
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -456,20 +456,20 @@ mifare_classic_write (FreefareTag tag, const MifareClassicBlockNumber block, con
|
|||
* data register.
|
||||
*/
|
||||
int
|
||||
mifare_classic_increment (FreefareTag tag, const MifareClassicBlockNumber block, const uint32_t amount)
|
||||
mifare_classic_increment(FreefareTag tag, const MifareClassicBlockNumber block, const uint32_t amount)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
ASSERT_ACTIVE(tag);
|
||||
|
||||
BUFFER_INIT (cmd, 6);
|
||||
BUFFER_INIT (res, 1);
|
||||
BUFFER_INIT(cmd, 6);
|
||||
BUFFER_INIT(res, 1);
|
||||
|
||||
BUFFER_APPEND (cmd, MC_INCREMENT);
|
||||
BUFFER_APPEND (cmd, block);
|
||||
BUFFER_APPEND_LE (cmd, amount, 4, sizeof (amount));
|
||||
BUFFER_APPEND(cmd, MC_INCREMENT);
|
||||
BUFFER_APPEND(cmd, block);
|
||||
BUFFER_APPEND_LE(cmd, amount, 4, sizeof(amount));
|
||||
|
||||
CLASSIC_TRANSCEIVE (tag, cmd, res);
|
||||
CLASSIC_TRANSCEIVE(tag, cmd, res);
|
||||
|
||||
return (BUFFER_SIZE (res) == 0) ? 0 : res[0];
|
||||
return (BUFFER_SIZE(res) == 0) ? 0 : res[0];
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -477,65 +477,65 @@ mifare_classic_increment (FreefareTag tag, const MifareClassicBlockNumber block,
|
|||
* data register.
|
||||
*/
|
||||
int
|
||||
mifare_classic_decrement (FreefareTag tag, const MifareClassicBlockNumber block, const uint32_t amount)
|
||||
mifare_classic_decrement(FreefareTag tag, const MifareClassicBlockNumber block, const uint32_t amount)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
ASSERT_ACTIVE(tag);
|
||||
|
||||
BUFFER_INIT (cmd, 6);
|
||||
BUFFER_INIT (res, 1);
|
||||
BUFFER_INIT(cmd, 6);
|
||||
BUFFER_INIT(res, 1);
|
||||
|
||||
BUFFER_APPEND (cmd, MC_DECREMENT);
|
||||
BUFFER_APPEND (cmd, block);
|
||||
BUFFER_APPEND_LE (cmd, amount, 4, sizeof (amount));
|
||||
BUFFER_APPEND(cmd, MC_DECREMENT);
|
||||
BUFFER_APPEND(cmd, block);
|
||||
BUFFER_APPEND_LE(cmd, amount, 4, sizeof(amount));
|
||||
|
||||
CLASSIC_TRANSCEIVE (tag, cmd, res);
|
||||
CLASSIC_TRANSCEIVE(tag, cmd, res);
|
||||
|
||||
return (BUFFER_SIZE (res) == 0) ? 0 : res[0];
|
||||
return (BUFFER_SIZE(res) == 0) ? 0 : res[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the provided block to the internal data register.
|
||||
*/
|
||||
int
|
||||
mifare_classic_restore (FreefareTag tag, const MifareClassicBlockNumber block)
|
||||
mifare_classic_restore(FreefareTag tag, const MifareClassicBlockNumber block)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
ASSERT_ACTIVE(tag);
|
||||
|
||||
/*
|
||||
* Same length as the increment and decrement commands but only the first
|
||||
* two bytes are actually used. The 4 bytes after the block number are
|
||||
* meaningless but required (NULL-filled).
|
||||
*/
|
||||
BUFFER_INIT (cmd, 6);
|
||||
BUFFER_INIT (res, 1);
|
||||
BUFFER_INIT(cmd, 6);
|
||||
BUFFER_INIT(res, 1);
|
||||
|
||||
BUFFER_APPEND (cmd, MC_RESTORE);
|
||||
BUFFER_APPEND (cmd, block);
|
||||
BUFFER_APPEND (cmd, 0x00);
|
||||
BUFFER_APPEND (cmd, 0x00);
|
||||
BUFFER_APPEND (cmd, 0x00);
|
||||
BUFFER_APPEND (cmd, 0x00);
|
||||
BUFFER_APPEND(cmd, MC_RESTORE);
|
||||
BUFFER_APPEND(cmd, block);
|
||||
BUFFER_APPEND(cmd, 0x00);
|
||||
BUFFER_APPEND(cmd, 0x00);
|
||||
BUFFER_APPEND(cmd, 0x00);
|
||||
BUFFER_APPEND(cmd, 0x00);
|
||||
|
||||
CLASSIC_TRANSCEIVE (tag, cmd, res);
|
||||
CLASSIC_TRANSCEIVE(tag, cmd, res);
|
||||
|
||||
return (BUFFER_SIZE (res) == 0) ? 0 : res[0];
|
||||
return (BUFFER_SIZE(res) == 0) ? 0 : res[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the internal data register to the provided block.
|
||||
*/
|
||||
int
|
||||
mifare_classic_transfer (FreefareTag tag, const MifareClassicBlockNumber block)
|
||||
mifare_classic_transfer(FreefareTag tag, const MifareClassicBlockNumber block)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
ASSERT_ACTIVE(tag);
|
||||
|
||||
BUFFER_INIT (cmd, 2);
|
||||
BUFFER_INIT (res, 1);
|
||||
BUFFER_INIT(cmd, 2);
|
||||
BUFFER_INIT(res, 1);
|
||||
|
||||
BUFFER_APPEND (cmd, MC_TRANSFER);
|
||||
BUFFER_APPEND (cmd, block);
|
||||
BUFFER_APPEND(cmd, MC_TRANSFER);
|
||||
BUFFER_APPEND(cmd, block);
|
||||
|
||||
CLASSIC_TRANSCEIVE (tag, cmd, res);
|
||||
CLASSIC_TRANSCEIVE(tag, cmd, res);
|
||||
|
||||
/*
|
||||
* Depending on the device we are using, on success, the TRANSFER command
|
||||
|
@ -543,7 +543,7 @@ mifare_classic_transfer (FreefareTag tag, const MifareClassicBlockNumber block)
|
|||
* meaning that the action was performed correctly (e.g. Snapper Feeder,
|
||||
* SCL 3711).
|
||||
*/
|
||||
if (!BUFFER_SIZE (res) || ((BUFFER_SIZE (res) == 1) && (res[0] = MC_OK)))
|
||||
if (!BUFFER_SIZE(res) || ((BUFFER_SIZE(res) == 1) && (res[0] = MC_OK)))
|
||||
return 0;
|
||||
else
|
||||
return res[0];
|
||||
|
@ -576,7 +576,7 @@ mifare_classic_transfer (FreefareTag tag, const MifareClassicBlockNumber block)
|
|||
*
|
||||
*/
|
||||
int
|
||||
get_block_access_bits_shift (MifareClassicBlockNumber block, MifareClassicBlockNumber trailer)
|
||||
get_block_access_bits_shift(MifareClassicBlockNumber block, MifareClassicBlockNumber trailer)
|
||||
{
|
||||
if (block == trailer) {
|
||||
return 3;
|
||||
|
@ -593,7 +593,7 @@ get_block_access_bits_shift (MifareClassicBlockNumber block, MifareClassicBlockN
|
|||
* block.
|
||||
*/
|
||||
int
|
||||
get_block_access_bits (FreefareTag tag, const MifareClassicBlockNumber block, MifareClassicAccessBits *block_access_bits)
|
||||
get_block_access_bits(FreefareTag tag, const MifareClassicBlockNumber block, MifareClassicAccessBits *block_access_bits)
|
||||
{
|
||||
/*
|
||||
* The first block which holds the manufacturer block seems to have
|
||||
|
@ -606,7 +606,7 @@ get_block_access_bits (FreefareTag tag, const MifareClassicBlockNumber block, Mi
|
|||
|
||||
uint16_t sector_access_bits, sector_access_bits_;
|
||||
|
||||
MifareClassicBlockNumber trailer = mifare_classic_sector_last_block (mifare_classic_block_sector (block));
|
||||
MifareClassicBlockNumber trailer = mifare_classic_sector_last_block(mifare_classic_block_sector(block));
|
||||
|
||||
/*
|
||||
* The trailer block contains access bits for the whole sector in a 3 bytes
|
||||
|
@ -623,7 +623,7 @@ get_block_access_bits (FreefareTag tag, const MifareClassicBlockNumber block, Mi
|
|||
} else {
|
||||
|
||||
MifareClassicBlock trailer_data;
|
||||
if (mifare_classic_read (tag, trailer, &trailer_data) < 0) {
|
||||
if (mifare_classic_read(tag, trailer, &trailer_data) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -653,7 +653,7 @@ get_block_access_bits (FreefareTag tag, const MifareClassicBlockNumber block, Mi
|
|||
* |,------C2
|
||||
* ||,---- C1
|
||||
* ||| */
|
||||
uint16_t block_access_bits_mask = 0x0111 << get_block_access_bits_shift (block, trailer);
|
||||
uint16_t block_access_bits_mask = 0x0111 << get_block_access_bits_shift(block, trailer);
|
||||
/* |||
|
||||
* ||`---------------.
|
||||
* |`---------------.|
|
||||
|
@ -674,10 +674,10 @@ get_block_access_bits (FreefareTag tag, const MifareClassicBlockNumber block, Mi
|
|||
* Get information about the trailer block.
|
||||
*/
|
||||
int
|
||||
mifare_classic_get_trailer_block_permission (FreefareTag tag, const MifareClassicBlockNumber block, const uint16_t permission, const MifareClassicKeyType key_type)
|
||||
mifare_classic_get_trailer_block_permission(FreefareTag tag, const MifareClassicBlockNumber block, const uint16_t permission, const MifareClassicKeyType key_type)
|
||||
{
|
||||
MifareClassicAccessBits access_bits;
|
||||
if (get_block_access_bits (tag, block, &access_bits) < 0) {
|
||||
if (get_block_access_bits(tag, block, &access_bits) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -693,15 +693,15 @@ mifare_classic_get_trailer_block_permission (FreefareTag tag, const MifareClassi
|
|||
* Get information about data blocks.
|
||||
*/
|
||||
int
|
||||
mifare_classic_get_data_block_permission (FreefareTag tag, const MifareClassicBlockNumber block, const unsigned char permission, const MifareClassicKeyType key_type)
|
||||
mifare_classic_get_data_block_permission(FreefareTag tag, const MifareClassicBlockNumber block, const unsigned char permission, const MifareClassicKeyType key_type)
|
||||
{
|
||||
MifareClassicAccessBits access_bits;
|
||||
if (get_block_access_bits (tag, block, &access_bits) < 0) {
|
||||
if (get_block_access_bits(tag, block, &access_bits) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (MIFARE_CLASSIC(tag)->cached_access_bits.sector_trailer_block_number != block) {
|
||||
return ((mifare_data_access_permissions[access_bits] & (permission << ( (key_type == MFC_KEY_A) ? 4 : 0 ))) ? 1 : 0);
|
||||
return ((mifare_data_access_permissions[access_bits] & (permission << ((key_type == MFC_KEY_A) ? 4 : 0))) ? 1 : 0);
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
|
@ -717,12 +717,12 @@ mifare_classic_get_data_block_permission (FreefareTag tag, const MifareClassicBl
|
|||
* Reset a MIFARE target sector to factory default.
|
||||
*/
|
||||
int
|
||||
mifare_classic_format_sector (FreefareTag tag, const MifareClassicSectorNumber sector)
|
||||
mifare_classic_format_sector(FreefareTag tag, const MifareClassicSectorNumber sector)
|
||||
{
|
||||
MifareClassicBlockNumber first_sector_block = mifare_classic_sector_first_block (sector);
|
||||
MifareClassicBlockNumber last_sector_block = mifare_classic_sector_last_block (sector);
|
||||
MifareClassicBlockNumber first_sector_block = mifare_classic_sector_first_block(sector);
|
||||
MifareClassicBlockNumber last_sector_block = mifare_classic_sector_last_block(sector);
|
||||
|
||||
/*
|
||||
/*
|
||||
* Check that the current key allow us to rewrite data and trailer blocks.
|
||||
*/
|
||||
|
||||
|
@ -743,7 +743,7 @@ mifare_classic_format_sector (FreefareTag tag, const MifareClassicSectorNumber s
|
|||
}
|
||||
|
||||
MifareClassicBlock empty_data_block;
|
||||
memset (empty_data_block, 0, sizeof (empty_data_block));
|
||||
memset(empty_data_block, 0, sizeof(empty_data_block));
|
||||
|
||||
MifareClassicBlock default_trailer_block = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* Key A */
|
||||
|
@ -753,11 +753,11 @@ mifare_classic_format_sector (FreefareTag tag, const MifareClassicSectorNumber s
|
|||
};
|
||||
|
||||
for (int n = first_sector_block; n < last_sector_block; n++) {
|
||||
if (mifare_classic_write (tag, n, empty_data_block) < 0) {
|
||||
if (mifare_classic_write(tag, n, empty_data_block) < 0) {
|
||||
return errno = EIO, -1;
|
||||
}
|
||||
}
|
||||
if (mifare_classic_write (tag, last_sector_block, default_trailer_block) < 0) {
|
||||
if (mifare_classic_write(tag, last_sector_block, default_trailer_block) < 0) {
|
||||
return errno = EIO, -1;
|
||||
}
|
||||
|
||||
|
@ -765,14 +765,14 @@ mifare_classic_format_sector (FreefareTag tag, const MifareClassicSectorNumber s
|
|||
}
|
||||
|
||||
MifareClassicSectorNumber
|
||||
mifare_classic_block_sector (MifareClassicBlockNumber block)
|
||||
mifare_classic_block_sector(MifareClassicBlockNumber block)
|
||||
{
|
||||
MifareClassicSectorNumber res;
|
||||
|
||||
if (block < 32 * 4)
|
||||
res = block / 4;
|
||||
else
|
||||
res = 32 + ( (block - (32 * 4)) / 16 );
|
||||
res = 32 + ((block - (32 * 4)) / 16);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -781,7 +781,7 @@ mifare_classic_block_sector (MifareClassicBlockNumber block)
|
|||
* Get the sector's first block number
|
||||
*/
|
||||
MifareClassicBlockNumber
|
||||
mifare_classic_sector_first_block (MifareClassicSectorNumber sector)
|
||||
mifare_classic_sector_first_block(MifareClassicSectorNumber sector)
|
||||
{
|
||||
int res;
|
||||
if (sector < 32) {
|
||||
|
@ -794,7 +794,7 @@ mifare_classic_sector_first_block (MifareClassicSectorNumber sector)
|
|||
}
|
||||
|
||||
size_t
|
||||
mifare_classic_sector_block_count (MifareClassicSectorNumber sector)
|
||||
mifare_classic_sector_block_count(MifareClassicSectorNumber sector)
|
||||
{
|
||||
return (sector < 32) ? 4 : 16 ;
|
||||
}
|
||||
|
@ -803,17 +803,17 @@ mifare_classic_sector_block_count (MifareClassicSectorNumber sector)
|
|||
* Get the sector's last block number (aka trailer block)
|
||||
*/
|
||||
MifareClassicBlockNumber
|
||||
mifare_classic_sector_last_block (MifareClassicSectorNumber sector)
|
||||
mifare_classic_sector_last_block(MifareClassicSectorNumber sector)
|
||||
{
|
||||
return mifare_classic_sector_first_block (sector) +
|
||||
mifare_classic_sector_block_count (sector) - 1;
|
||||
return mifare_classic_sector_first_block(sector) +
|
||||
mifare_classic_sector_block_count(sector) - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates a MIFARE trailer block.
|
||||
*/
|
||||
void
|
||||
mifare_classic_trailer_block (MifareClassicBlock *block, const MifareClassicKey key_a, uint8_t ab_0, uint8_t ab_1, uint8_t ab_2, uint8_t ab_tb, const uint8_t gpb, const MifareClassicKey key_b)
|
||||
mifare_classic_trailer_block(MifareClassicBlock *block, const MifareClassicKey key_a, uint8_t ab_0, uint8_t ab_1, uint8_t ab_2, uint8_t ab_tb, const uint8_t gpb, const MifareClassicKey key_b)
|
||||
{
|
||||
union mifare_classic_block *b = (union mifare_classic_block *)block; // *((union mifare_classic_block *)(&block));
|
||||
|
||||
|
@ -822,9 +822,9 @@ mifare_classic_trailer_block (MifareClassicBlock *block, const MifareClassicKey
|
|||
ab_2 = DB_AB(ab_2);
|
||||
ab_tb = TB_AB(ab_tb);
|
||||
|
||||
memcpy (b->trailer.key_a, key_a, sizeof (MifareClassicKey));
|
||||
memcpy(b->trailer.key_a, key_a, sizeof(MifareClassicKey));
|
||||
|
||||
uint32_t access_bits = ((((( ab_0 & 0x4) >> 2) << 8) | (((ab_0 & 0x2) >> 1) << 4) | (ab_0 & 0x1)) |
|
||||
uint32_t access_bits = (((((ab_0 & 0x4) >> 2) << 8) | (((ab_0 & 0x2) >> 1) << 4) | (ab_0 & 0x1)) |
|
||||
(((((ab_1 & 0x4) >> 2) << 8) | (((ab_1 & 0x2) >> 1) << 4) | (ab_1 & 0x1)) << 1) |
|
||||
(((((ab_2 & 0x4) >> 2) << 8) | (((ab_2 & 0x2) >> 1) << 4) | (ab_2 & 0x1)) << 2) |
|
||||
(((((ab_tb & 0x4) >> 2) << 8) | (((ab_tb & 0x2) >> 1) << 4) | (ab_tb & 0x1)) << 3));
|
||||
|
@ -832,8 +832,8 @@ mifare_classic_trailer_block (MifareClassicBlock *block, const MifareClassicKey
|
|||
uint32_t access_bits_ = ((~access_bits) & 0x00000fff);
|
||||
|
||||
uint32_t ab = htole32(((access_bits << 12) | access_bits_));
|
||||
memcpy (&(b->trailer.access_bits), &ab, 3);
|
||||
memcpy(&(b->trailer.access_bits), &ab, 3);
|
||||
b->trailer.gpb = gpb;
|
||||
|
||||
memcpy (b->trailer.key_b, key_b, sizeof (MifareClassicKey));
|
||||
memcpy(b->trailer.key_b, key_b, sizeof(MifareClassicKey));
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -57,16 +57,16 @@
|
|||
|
||||
// Theorically, it should be an uint24_t ...
|
||||
MifareDESFireAID
|
||||
mifare_desfire_aid_new (uint32_t aid)
|
||||
mifare_desfire_aid_new(uint32_t aid)
|
||||
{
|
||||
if (aid > 0x00ffffff)
|
||||
return errno = EINVAL, NULL;
|
||||
|
||||
MifareDESFireAID res;
|
||||
uint32_t aid_le = htole32 (aid);
|
||||
uint32_t aid_le = htole32(aid);
|
||||
|
||||
if ((res = malloc (sizeof (*res)))) {
|
||||
memcpy(res->data, ((uint8_t*)&aid_le), 3);
|
||||
if ((res = malloc(sizeof(*res)))) {
|
||||
memcpy(res->data, ((uint8_t *)&aid_le), 3);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -74,16 +74,16 @@ mifare_desfire_aid_new (uint32_t aid)
|
|||
|
||||
// This function ease the MifareDESFireAID creation using a Mifare Classic AID (see MIFARE Application Directory document - section 3.10 MAD and MIFARE DESFire)
|
||||
MifareDESFireAID
|
||||
mifare_desfire_aid_new_with_mad_aid (MadAid mad_aid, uint8_t n)
|
||||
mifare_desfire_aid_new_with_mad_aid(MadAid mad_aid, uint8_t n)
|
||||
{
|
||||
if (n > 0x0f)
|
||||
return errno = EINVAL, NULL;
|
||||
|
||||
return mifare_desfire_aid_new (0xf00000 | (mad_aid.function_cluster_code << 12) | (mad_aid.application_code << 4) | n);
|
||||
return mifare_desfire_aid_new(0xf00000 | (mad_aid.function_cluster_code << 12) | (mad_aid.application_code << 4) | n);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
mifare_desfire_aid_get_aid (MifareDESFireAID aid)
|
||||
mifare_desfire_aid_get_aid(MifareDESFireAID aid)
|
||||
{
|
||||
return aid->data[0] | (aid->data[1] << 8) | (aid->data[2] << 16);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -71,12 +71,12 @@
|
|||
#define MAC_LENGTH 4
|
||||
#define CMAC_LENGTH 8
|
||||
|
||||
static void xor (const uint8_t *ivect, uint8_t *data, const size_t len);
|
||||
static void desfire_crc32_byte (uint32_t *crc, const uint8_t value);
|
||||
static size_t key_macing_length (MifareDESFireKey key);
|
||||
static void xor(const uint8_t *ivect, uint8_t *data, const size_t len);
|
||||
static void desfire_crc32_byte(uint32_t *crc, const uint8_t value);
|
||||
static size_t key_macing_length(MifareDESFireKey key);
|
||||
|
||||
static void
|
||||
xor (const uint8_t *ivect, uint8_t *data, const size_t len)
|
||||
xor(const uint8_t *ivect, uint8_t *data, const size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
data[i] ^= ivect[i];
|
||||
|
@ -84,87 +84,87 @@ xor (const uint8_t *ivect, uint8_t *data, const size_t len)
|
|||
}
|
||||
|
||||
void
|
||||
rol (uint8_t *data, const size_t len)
|
||||
rol(uint8_t *data, const size_t len)
|
||||
{
|
||||
uint8_t first = data[0];
|
||||
for (size_t i = 0; i < len-1; i++) {
|
||||
data[i] = data[i+1];
|
||||
for (size_t i = 0; i < len - 1; i++) {
|
||||
data[i] = data[i + 1];
|
||||
}
|
||||
data[len-1] = first;
|
||||
data[len - 1] = first;
|
||||
}
|
||||
|
||||
void
|
||||
lsl (uint8_t *data, size_t len)
|
||||
lsl(uint8_t *data, size_t len)
|
||||
{
|
||||
for (size_t n = 0; n < len - 1; n++) {
|
||||
data[n] = (data[n] << 1) | (data[n+1] >> 7);
|
||||
data[n] = (data[n] << 1) | (data[n + 1] >> 7);
|
||||
}
|
||||
data[len - 1] <<= 1;
|
||||
}
|
||||
|
||||
void
|
||||
cmac_generate_subkeys (MifareDESFireKey key)
|
||||
cmac_generate_subkeys(MifareDESFireKey key)
|
||||
{
|
||||
int kbs = key_block_size (key);
|
||||
int kbs = key_block_size(key);
|
||||
const uint8_t R = (kbs == 8) ? 0x1B : 0x87;
|
||||
|
||||
uint8_t l[kbs];
|
||||
memset (l, 0, kbs);
|
||||
memset(l, 0, kbs);
|
||||
|
||||
uint8_t ivect[kbs];
|
||||
memset (ivect, 0, kbs);
|
||||
memset(ivect, 0, kbs);
|
||||
|
||||
mifare_cypher_blocks_chained (NULL, key, ivect, l, kbs, MCD_RECEIVE, MCO_ENCYPHER);
|
||||
mifare_cypher_blocks_chained(NULL, key, ivect, l, kbs, MCD_RECEIVE, MCO_ENCYPHER);
|
||||
|
||||
bool xor = false;
|
||||
|
||||
// Used to compute CMAC on complete blocks
|
||||
memcpy (key->cmac_sk1, l, kbs);
|
||||
memcpy(key->cmac_sk1, l, kbs);
|
||||
xor = l[0] & 0x80;
|
||||
lsl (key->cmac_sk1, kbs);
|
||||
lsl(key->cmac_sk1, kbs);
|
||||
if (xor)
|
||||
key->cmac_sk1[kbs-1] ^= R;
|
||||
key->cmac_sk1[kbs - 1] ^= R;
|
||||
|
||||
// Used to compute CMAC on the last block if non-complete
|
||||
memcpy (key->cmac_sk2, key->cmac_sk1, kbs);
|
||||
memcpy(key->cmac_sk2, key->cmac_sk1, kbs);
|
||||
xor = key->cmac_sk1[0] & 0x80;
|
||||
lsl (key->cmac_sk2, kbs);
|
||||
lsl(key->cmac_sk2, kbs);
|
||||
if (xor)
|
||||
key->cmac_sk2[kbs-1] ^= R;
|
||||
key->cmac_sk2[kbs - 1] ^= R;
|
||||
}
|
||||
|
||||
void
|
||||
cmac (const MifareDESFireKey key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac)
|
||||
cmac(const MifareDESFireKey key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac)
|
||||
{
|
||||
int kbs = key_block_size (key);
|
||||
uint8_t *buffer = malloc (padded_data_length (len, kbs));
|
||||
int kbs = key_block_size(key);
|
||||
uint8_t *buffer = malloc(padded_data_length(len, kbs));
|
||||
|
||||
if (!buffer)
|
||||
abort();
|
||||
|
||||
memcpy (buffer, data, len);
|
||||
memcpy(buffer, data, len);
|
||||
|
||||
if ((!len) || (len % kbs)) {
|
||||
buffer[len++] = 0x80;
|
||||
while (len % kbs) {
|
||||
buffer[len++] = 0x00;
|
||||
}
|
||||
xor (key->cmac_sk2, buffer + len - kbs, kbs);
|
||||
xor(key->cmac_sk2, buffer + len - kbs, kbs);
|
||||
} else {
|
||||
xor (key->cmac_sk1, buffer + len - kbs, kbs);
|
||||
xor(key->cmac_sk1, buffer + len - kbs, kbs);
|
||||
}
|
||||
|
||||
mifare_cypher_blocks_chained (NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER);
|
||||
mifare_cypher_blocks_chained(NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER);
|
||||
|
||||
memcpy (cmac, ivect, kbs);
|
||||
memcpy(cmac, ivect, kbs);
|
||||
|
||||
free (buffer);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
#define CRC32_PRESET 0xFFFFFFFF
|
||||
|
||||
static void
|
||||
desfire_crc32_byte (uint32_t *crc, const uint8_t value)
|
||||
desfire_crc32_byte(uint32_t *crc, const uint8_t value)
|
||||
{
|
||||
/* x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 */
|
||||
const uint32_t poly = 0xEDB88320;
|
||||
|
@ -179,24 +179,24 @@ desfire_crc32_byte (uint32_t *crc, const uint8_t value)
|
|||
}
|
||||
|
||||
void
|
||||
desfire_crc32 (const uint8_t *data, const size_t len, uint8_t *crc)
|
||||
desfire_crc32(const uint8_t *data, const size_t len, uint8_t *crc)
|
||||
{
|
||||
uint32_t desfire_crc = CRC32_PRESET;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
desfire_crc32_byte (&desfire_crc, data[i]);
|
||||
desfire_crc32_byte(&desfire_crc, data[i]);
|
||||
}
|
||||
|
||||
*((uint32_t *)(crc)) = htole32 (desfire_crc);
|
||||
*((uint32_t *)(crc)) = htole32(desfire_crc);
|
||||
}
|
||||
|
||||
void
|
||||
desfire_crc32_append (uint8_t *data, const size_t len)
|
||||
desfire_crc32_append(uint8_t *data, const size_t len)
|
||||
{
|
||||
desfire_crc32 (data, len, data + len);
|
||||
desfire_crc32(data, len, data + len);
|
||||
}
|
||||
|
||||
size_t
|
||||
key_block_size (const MifareDESFireKey key)
|
||||
key_block_size(const MifareDESFireKey key)
|
||||
{
|
||||
size_t block_size;
|
||||
|
||||
|
@ -218,7 +218,7 @@ key_block_size (const MifareDESFireKey key)
|
|||
* Size of MACing produced with the key.
|
||||
*/
|
||||
static size_t
|
||||
key_macing_length (const MifareDESFireKey key)
|
||||
key_macing_length(const MifareDESFireKey key)
|
||||
{
|
||||
size_t mac_length;
|
||||
|
||||
|
@ -240,7 +240,7 @@ key_macing_length (const MifareDESFireKey key)
|
|||
* Size required to store nbytes of data in a buffer of size n*block_size.
|
||||
*/
|
||||
size_t
|
||||
padded_data_length (const size_t nbytes, const size_t block_size)
|
||||
padded_data_length(const size_t nbytes, const size_t block_size)
|
||||
{
|
||||
if ((!nbytes) || (nbytes % block_size))
|
||||
return ((nbytes / block_size) + 1) * block_size;
|
||||
|
@ -252,19 +252,19 @@ padded_data_length (const size_t nbytes, const size_t block_size)
|
|||
* Buffer size required to MAC nbytes of data
|
||||
*/
|
||||
size_t
|
||||
maced_data_length (const MifareDESFireKey key, const size_t nbytes)
|
||||
maced_data_length(const MifareDESFireKey key, const size_t nbytes)
|
||||
{
|
||||
return nbytes + key_macing_length (key);
|
||||
return nbytes + key_macing_length(key);
|
||||
}
|
||||
/*
|
||||
* Buffer size required to encipher nbytes of data and a two bytes CRC.
|
||||
*/
|
||||
size_t
|
||||
enciphered_data_length (const FreefareTag tag, const size_t nbytes, int communication_settings)
|
||||
enciphered_data_length(const FreefareTag tag, const size_t nbytes, int communication_settings)
|
||||
{
|
||||
size_t crc_length = 0;
|
||||
if (!(communication_settings & NO_CRC)) {
|
||||
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||
switch (MIFARE_DESFIRE(tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
crc_length = 2;
|
||||
break;
|
||||
|
@ -274,9 +274,9 @@ enciphered_data_length (const FreefareTag tag, const size_t nbytes, int communic
|
|||
}
|
||||
}
|
||||
|
||||
size_t block_size = MIFARE_DESFIRE(tag)->session_key ? key_block_size (MIFARE_DESFIRE (tag)->session_key) : 1;
|
||||
size_t block_size = MIFARE_DESFIRE(tag)->session_key ? key_block_size(MIFARE_DESFIRE(tag)->session_key) : 1;
|
||||
|
||||
return padded_data_length (nbytes + crc_length, block_size);
|
||||
return padded_data_length(nbytes + crc_length, block_size);
|
||||
}
|
||||
|
||||
|
||||
|
@ -284,33 +284,33 @@ enciphered_data_length (const FreefareTag tag, const size_t nbytes, int communic
|
|||
* Ensure that tag's crypto buffer is large enough to store nbytes of data.
|
||||
*/
|
||||
void *
|
||||
assert_crypto_buffer_size (FreefareTag tag, size_t nbytes)
|
||||
assert_crypto_buffer_size(FreefareTag tag, size_t nbytes)
|
||||
{
|
||||
void *res = MIFARE_DESFIRE (tag)->crypto_buffer;
|
||||
if (MIFARE_DESFIRE (tag)->crypto_buffer_size < nbytes) {
|
||||
if ((res = realloc (MIFARE_DESFIRE (tag)->crypto_buffer, nbytes))) {
|
||||
MIFARE_DESFIRE (tag)->crypto_buffer = res;
|
||||
MIFARE_DESFIRE (tag)->crypto_buffer_size = nbytes;
|
||||
void *res = MIFARE_DESFIRE(tag)->crypto_buffer;
|
||||
if (MIFARE_DESFIRE(tag)->crypto_buffer_size < nbytes) {
|
||||
if ((res = realloc(MIFARE_DESFIRE(tag)->crypto_buffer, nbytes))) {
|
||||
MIFARE_DESFIRE(tag)->crypto_buffer = res;
|
||||
MIFARE_DESFIRE(tag)->crypto_buffer_size = nbytes;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void *
|
||||
mifare_cryto_preprocess_data (FreefareTag tag, void *data, size_t *nbytes, off_t offset, int communication_settings)
|
||||
mifare_cryto_preprocess_data(FreefareTag tag, void *data, size_t *nbytes, off_t offset, int communication_settings)
|
||||
{
|
||||
uint8_t *res = data;
|
||||
uint8_t mac[4];
|
||||
size_t edl, mdl;
|
||||
bool append_mac = true;
|
||||
MifareDESFireKey key = MIFARE_DESFIRE (tag)->session_key;
|
||||
MifareDESFireKey key = MIFARE_DESFIRE(tag)->session_key;
|
||||
|
||||
if (!key)
|
||||
return data;
|
||||
|
||||
switch (communication_settings & MDCM_MASK) {
|
||||
case MDCM_PLAIN:
|
||||
if (AS_LEGACY == MIFARE_DESFIRE (tag)->authentication_scheme)
|
||||
if (AS_LEGACY == MIFARE_DESFIRE(tag)->authentication_scheme)
|
||||
break;
|
||||
|
||||
/*
|
||||
|
@ -325,53 +325,53 @@ mifare_cryto_preprocess_data (FreefareTag tag, void *data, size_t *nbytes, off_t
|
|||
|
||||
append_mac = false;
|
||||
|
||||
/* pass through */
|
||||
/* pass through */
|
||||
case MDCM_MACED:
|
||||
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||
switch (MIFARE_DESFIRE(tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
if (!(communication_settings & MAC_COMMAND))
|
||||
break;
|
||||
|
||||
/* pass through */
|
||||
edl = padded_data_length (*nbytes - offset, key_block_size (MIFARE_DESFIRE (tag)->session_key)) + offset;
|
||||
if (!(res = assert_crypto_buffer_size (tag, edl)))
|
||||
edl = padded_data_length(*nbytes - offset, key_block_size(MIFARE_DESFIRE(tag)->session_key)) + offset;
|
||||
if (!(res = assert_crypto_buffer_size(tag, edl)))
|
||||
abort();
|
||||
|
||||
// Fill in the crypto buffer with data ...
|
||||
memcpy (res, data, *nbytes);
|
||||
memcpy(res, data, *nbytes);
|
||||
// ... and 0 padding
|
||||
memset (res + *nbytes, 0, edl - *nbytes);
|
||||
memset(res + *nbytes, 0, edl - *nbytes);
|
||||
|
||||
mifare_cypher_blocks_chained (tag, NULL, NULL, res + offset, edl - offset, MCD_SEND, MCO_ENCYPHER);
|
||||
mifare_cypher_blocks_chained(tag, NULL, NULL, res + offset, edl - offset, MCD_SEND, MCO_ENCYPHER);
|
||||
|
||||
memcpy (mac, res + edl - 8, 4);
|
||||
memcpy(mac, res + edl - 8, 4);
|
||||
|
||||
// Copy again provided data (was overwritten by mifare_cypher_blocks_chained)
|
||||
memcpy (res, data, *nbytes);
|
||||
memcpy(res, data, *nbytes);
|
||||
|
||||
if (!(communication_settings & MAC_COMMAND))
|
||||
break;
|
||||
// Append MAC
|
||||
mdl = maced_data_length (MIFARE_DESFIRE (tag)->session_key, *nbytes - offset) + offset;
|
||||
if (!(res = assert_crypto_buffer_size (tag, mdl)))
|
||||
mdl = maced_data_length(MIFARE_DESFIRE(tag)->session_key, *nbytes - offset) + offset;
|
||||
if (!(res = assert_crypto_buffer_size(tag, mdl)))
|
||||
abort();
|
||||
|
||||
memcpy (res + *nbytes, mac, 4);
|
||||
memcpy(res + *nbytes, mac, 4);
|
||||
|
||||
*nbytes += 4;
|
||||
break;
|
||||
case AS_NEW:
|
||||
if (!(communication_settings & CMAC_COMMAND))
|
||||
break;
|
||||
cmac (key, MIFARE_DESFIRE (tag)->ivect, res, *nbytes, MIFARE_DESFIRE (tag)->cmac);
|
||||
cmac(key, MIFARE_DESFIRE(tag)->ivect, res, *nbytes, MIFARE_DESFIRE(tag)->cmac);
|
||||
|
||||
if (append_mac) {
|
||||
mdl = maced_data_length (key, *nbytes);
|
||||
if (!(res = assert_crypto_buffer_size (tag, mdl)))
|
||||
mdl = maced_data_length(key, *nbytes);
|
||||
if (!(res = assert_crypto_buffer_size(tag, mdl)))
|
||||
abort();
|
||||
|
||||
memcpy (res, data, *nbytes);
|
||||
memcpy (res + *nbytes, MIFARE_DESFIRE (tag)->cmac, CMAC_LENGTH);
|
||||
memcpy(res, data, *nbytes);
|
||||
memcpy(res + *nbytes, MIFARE_DESFIRE(tag)->cmac, CMAC_LENGTH);
|
||||
*nbytes += CMAC_LENGTH;
|
||||
}
|
||||
break;
|
||||
|
@ -394,41 +394,41 @@ mifare_cryto_preprocess_data (FreefareTag tag, void *data, size_t *nbytes, off_t
|
|||
* encypher()/decypher()
|
||||
*/
|
||||
|
||||
if (!(communication_settings & ENC_COMMAND))
|
||||
if (!(communication_settings & ENC_COMMAND))
|
||||
break;
|
||||
edl = enciphered_data_length(tag, *nbytes - offset, communication_settings) + offset;
|
||||
if (!(res = assert_crypto_buffer_size(tag, edl)))
|
||||
abort();
|
||||
|
||||
// Fill in the crypto buffer with data ...
|
||||
memcpy(res, data, *nbytes);
|
||||
if (!(communication_settings & NO_CRC)) {
|
||||
// ... CRC ...
|
||||
switch (MIFARE_DESFIRE(tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
iso14443a_crc_append(res + offset, *nbytes - offset);
|
||||
*nbytes += 2;
|
||||
break;
|
||||
case AS_NEW:
|
||||
desfire_crc32_append(res, *nbytes);
|
||||
*nbytes += 4;
|
||||
break;
|
||||
edl = enciphered_data_length (tag, *nbytes - offset, communication_settings) + offset;
|
||||
if (!(res = assert_crypto_buffer_size (tag, edl)))
|
||||
abort();
|
||||
|
||||
// Fill in the crypto buffer with data ...
|
||||
memcpy (res, data, *nbytes);
|
||||
if (!(communication_settings & NO_CRC)) {
|
||||
// ... CRC ...
|
||||
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
iso14443a_crc_append (res + offset, *nbytes - offset);
|
||||
*nbytes += 2;
|
||||
break;
|
||||
case AS_NEW:
|
||||
desfire_crc32_append (res, *nbytes);
|
||||
*nbytes += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// ... and padding
|
||||
memset (res + *nbytes, 0, edl - *nbytes);
|
||||
}
|
||||
// ... and padding
|
||||
memset(res + *nbytes, 0, edl - *nbytes);
|
||||
|
||||
*nbytes = edl;
|
||||
*nbytes = edl;
|
||||
|
||||
mifare_cypher_blocks_chained (tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == MIFARE_DESFIRE (tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER);
|
||||
mifare_cypher_blocks_chained(tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == MIFARE_DESFIRE(tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER);
|
||||
break;
|
||||
default:
|
||||
MIFARE_DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
MIFARE_DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
*nbytes = -1;
|
||||
res = NULL;
|
||||
#ifdef WITH_DEBUG
|
||||
warnx ("Unknown communication settings");
|
||||
abort ();
|
||||
warnx("Unknown communication settings");
|
||||
abort();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -437,14 +437,14 @@ mifare_cryto_preprocess_data (FreefareTag tag, void *data, size_t *nbytes, off_t
|
|||
}
|
||||
|
||||
void *
|
||||
mifare_cryto_postprocess_data (FreefareTag tag, void *data, ssize_t *nbytes, int communication_settings)
|
||||
mifare_cryto_postprocess_data(FreefareTag tag, void *data, ssize_t *nbytes, int communication_settings)
|
||||
{
|
||||
void *res = data;
|
||||
size_t edl;
|
||||
void *edata = NULL;
|
||||
uint8_t first_cmac_byte;
|
||||
|
||||
MifareDESFireKey key = MIFARE_DESFIRE (tag)->session_key;
|
||||
MifareDESFireKey key = MIFARE_DESFIRE(tag)->session_key;
|
||||
|
||||
if (!key)
|
||||
return data;
|
||||
|
@ -456,42 +456,42 @@ mifare_cryto_postprocess_data (FreefareTag tag, void *data, ssize_t *nbytes, int
|
|||
switch (communication_settings & MDCM_MASK) {
|
||||
case MDCM_PLAIN:
|
||||
|
||||
if (AS_LEGACY == MIFARE_DESFIRE (tag)->authentication_scheme)
|
||||
if (AS_LEGACY == MIFARE_DESFIRE(tag)->authentication_scheme)
|
||||
break;
|
||||
|
||||
/* pass through */
|
||||
/* pass through */
|
||||
case MDCM_MACED:
|
||||
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||
switch (MIFARE_DESFIRE(tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
if (communication_settings & MAC_VERIFY) {
|
||||
*nbytes -= key_macing_length (key);
|
||||
*nbytes -= key_macing_length(key);
|
||||
if (*nbytes <= 0) {
|
||||
MIFARE_DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
MIFARE_DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
*nbytes = -1;
|
||||
res = NULL;
|
||||
#ifdef WITH_DEBUG
|
||||
warnx ("No room for MAC!");
|
||||
abort ();
|
||||
warnx("No room for MAC!");
|
||||
abort();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
edl = enciphered_data_length (tag, *nbytes - 1, communication_settings);
|
||||
if (!(edata = malloc (edl)))
|
||||
abort ();
|
||||
edl = enciphered_data_length(tag, *nbytes - 1, communication_settings);
|
||||
if (!(edata = malloc(edl)))
|
||||
abort();
|
||||
|
||||
memcpy (edata, data, *nbytes - 1);
|
||||
memset ((uint8_t *)edata + *nbytes - 1, 0, edl - *nbytes + 1);
|
||||
memcpy(edata, data, *nbytes - 1);
|
||||
memset((uint8_t *)edata + *nbytes - 1, 0, edl - *nbytes + 1);
|
||||
|
||||
mifare_cypher_blocks_chained (tag, NULL, NULL, edata, edl, MCD_SEND, MCO_ENCYPHER);
|
||||
mifare_cypher_blocks_chained(tag, NULL, NULL, edata, edl, MCD_SEND, MCO_ENCYPHER);
|
||||
|
||||
if (0 != memcmp ((uint8_t *)data + *nbytes - 1, (uint8_t *)edata + edl - 8, 4)) {
|
||||
if (0 != memcmp((uint8_t *)data + *nbytes - 1, (uint8_t *)edata + edl - 8, 4)) {
|
||||
#ifdef WITH_DEBUG
|
||||
warnx ("MACing not verified");
|
||||
hexdump ((uint8_t *)data + *nbytes - 1, key_macing_length (key), "Expect ", 0);
|
||||
hexdump ((uint8_t *)edata + edl - 8, key_macing_length (key), "Actual ", 0);
|
||||
warnx("MACing not verified");
|
||||
hexdump((uint8_t *)data + *nbytes - 1, key_macing_length(key), "Expect ", 0);
|
||||
hexdump((uint8_t *)edata + edl - 8, key_macing_length(key), "Actual ", 0);
|
||||
#endif
|
||||
MIFARE_DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
MIFARE_DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
*nbytes = -1;
|
||||
res = NULL;
|
||||
}
|
||||
|
@ -502,31 +502,31 @@ mifare_cryto_postprocess_data (FreefareTag tag, void *data, ssize_t *nbytes, int
|
|||
break;
|
||||
if (communication_settings & CMAC_VERIFY) {
|
||||
if (*nbytes < 9) {
|
||||
MIFARE_DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
MIFARE_DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
*nbytes = -1;
|
||||
res = NULL;
|
||||
#ifdef WITH_DEBUG
|
||||
warnx ("No room for CMAC!");
|
||||
abort ();
|
||||
warnx("No room for CMAC!");
|
||||
abort();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
first_cmac_byte = ((uint8_t *)data)[*nbytes - 9];
|
||||
((uint8_t *)data)[*nbytes - 9] = ((uint8_t *)data)[*nbytes-1];
|
||||
((uint8_t *)data)[*nbytes - 9] = ((uint8_t *)data)[*nbytes - 1];
|
||||
}
|
||||
|
||||
int n = (communication_settings & CMAC_VERIFY) ? 8 : 0;
|
||||
cmac (key, MIFARE_DESFIRE (tag)->ivect, ((uint8_t *)data), *nbytes - n, MIFARE_DESFIRE (tag)->cmac);
|
||||
cmac(key, MIFARE_DESFIRE(tag)->ivect, ((uint8_t *)data), *nbytes - n, MIFARE_DESFIRE(tag)->cmac);
|
||||
|
||||
if (communication_settings & CMAC_VERIFY) {
|
||||
((uint8_t *)data)[*nbytes - 9] = first_cmac_byte;
|
||||
if (0 != memcmp (MIFARE_DESFIRE (tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) {
|
||||
if (0 != memcmp(MIFARE_DESFIRE(tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) {
|
||||
#ifdef WITH_DEBUG
|
||||
warnx ("CMAC NOT verified :-(");
|
||||
hexdump ((uint8_t *)data + *nbytes - 9, 8, "Expect ", 0);
|
||||
hexdump (MIFARE_DESFIRE (tag)->cmac, 8, "Actual ", 0);
|
||||
warnx("CMAC NOT verified :-(");
|
||||
hexdump((uint8_t *)data + *nbytes - 9, 8, "Expect ", 0);
|
||||
hexdump(MIFARE_DESFIRE(tag)->cmac, 8, "Actual ", 0);
|
||||
#endif
|
||||
MIFARE_DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
MIFARE_DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
*nbytes = -1;
|
||||
res = NULL;
|
||||
} else {
|
||||
|
@ -536,7 +536,7 @@ mifare_cryto_postprocess_data (FreefareTag tag, void *data, ssize_t *nbytes, int
|
|||
break;
|
||||
}
|
||||
|
||||
free (edata);
|
||||
free(edata);
|
||||
|
||||
break;
|
||||
case MDCM_ENCIPHERED:
|
||||
|
@ -568,14 +568,14 @@ mifare_cryto_postprocess_data (FreefareTag tag, void *data, ssize_t *nbytes, int
|
|||
* `------------------'
|
||||
*/
|
||||
|
||||
mifare_cypher_blocks_chained (tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER);
|
||||
mifare_cypher_blocks_chained(tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER);
|
||||
|
||||
/*
|
||||
* Look for the CRC and ensure it is followed by NULL padding. We
|
||||
* can't start by the end because the CRC is supposed to be 0 when
|
||||
* verified, and accumulating 0's in it should not change it.
|
||||
*/
|
||||
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||
switch (MIFARE_DESFIRE(tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks
|
||||
if (crc_pos < 0) {
|
||||
|
@ -585,15 +585,15 @@ mifare_cryto_postprocess_data (FreefareTag tag, void *data, ssize_t *nbytes, int
|
|||
break;
|
||||
case AS_NEW:
|
||||
/* Move status between payload and CRC */
|
||||
res = assert_crypto_buffer_size (tag, (*nbytes) + 1);
|
||||
memcpy (res, data, *nbytes);
|
||||
res = assert_crypto_buffer_size(tag, (*nbytes) + 1);
|
||||
memcpy(res, data, *nbytes);
|
||||
|
||||
crc_pos = (*nbytes) - 16 - 3;
|
||||
if (crc_pos < 0) {
|
||||
/* Single block */
|
||||
crc_pos = 0;
|
||||
}
|
||||
memmove ((uint8_t *)res + crc_pos + 1, (uint8_t *)res + crc_pos, *nbytes - crc_pos);
|
||||
memmove((uint8_t *)res + crc_pos + 1, (uint8_t *)res + crc_pos, *nbytes - crc_pos);
|
||||
((uint8_t *)res)[crc_pos] = 0x00;
|
||||
crc_pos++;
|
||||
*nbytes += 1;
|
||||
|
@ -603,28 +603,28 @@ mifare_cryto_postprocess_data (FreefareTag tag, void *data, ssize_t *nbytes, int
|
|||
do {
|
||||
uint16_t crc16;
|
||||
uint32_t crc;
|
||||
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||
switch (MIFARE_DESFIRE(tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
end_crc_pos = crc_pos + 2;
|
||||
iso14443a_crc (res, end_crc_pos, (uint8_t *)&crc16);
|
||||
iso14443a_crc(res, end_crc_pos, (uint8_t *)&crc16);
|
||||
crc = crc16;
|
||||
break;
|
||||
case AS_NEW:
|
||||
end_crc_pos = crc_pos + 4;
|
||||
desfire_crc32 (res, end_crc_pos, (uint8_t *)&crc);
|
||||
desfire_crc32(res, end_crc_pos, (uint8_t *)&crc);
|
||||
break;
|
||||
}
|
||||
if (!crc) {
|
||||
verified = true;
|
||||
for (int n = end_crc_pos; n < *nbytes - 1; n++) {
|
||||
uint8_t byte = ((uint8_t *)res)[n];
|
||||
if (!( (0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos)) ))
|
||||
if (!((0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos))))
|
||||
verified = false;
|
||||
}
|
||||
}
|
||||
if (verified) {
|
||||
*nbytes = crc_pos;
|
||||
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||
switch (MIFARE_DESFIRE(tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
((uint8_t *)data)[(*nbytes)++] = 0x00;
|
||||
break;
|
||||
|
@ -633,7 +633,7 @@ mifare_cryto_postprocess_data (FreefareTag tag, void *data, ssize_t *nbytes, int
|
|||
break;
|
||||
}
|
||||
} else {
|
||||
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||
switch (MIFARE_DESFIRE(tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
break;
|
||||
case AS_NEW:
|
||||
|
@ -649,21 +649,21 @@ mifare_cryto_postprocess_data (FreefareTag tag, void *data, ssize_t *nbytes, int
|
|||
if (!verified) {
|
||||
#ifdef WITH_DEBUG
|
||||
/* FIXME In some configurations, the file is transmitted PLAIN */
|
||||
warnx ("CRC not verified in decyphered stream");
|
||||
warnx("CRC not verified in decyphered stream");
|
||||
#endif
|
||||
MIFARE_DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
MIFARE_DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
*nbytes = -1;
|
||||
res = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
MIFARE_DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
MIFARE_DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
|
||||
*nbytes = -1;
|
||||
res = NULL;
|
||||
#ifdef WITH_DEBUG
|
||||
warnx ("Unknown communication settings");
|
||||
abort ();
|
||||
warnx("Unknown communication settings");
|
||||
abort();
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
@ -672,15 +672,15 @@ mifare_cryto_postprocess_data (FreefareTag tag, void *data, ssize_t *nbytes, int
|
|||
}
|
||||
|
||||
void
|
||||
mifare_cypher_single_block (MifareDESFireKey key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size)
|
||||
mifare_cypher_single_block(MifareDESFireKey key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size)
|
||||
{
|
||||
AES_KEY k;
|
||||
uint8_t ovect[MAX_CRYPTO_BLOCK_SIZE];
|
||||
|
||||
if (direction == MCD_SEND) {
|
||||
xor (ivect, data, block_size);
|
||||
xor(ivect, data, block_size);
|
||||
} else {
|
||||
memcpy (ovect, data, block_size);
|
||||
memcpy(ovect, data, block_size);
|
||||
}
|
||||
|
||||
uint8_t edata[MAX_CRYPTO_BLOCK_SIZE];
|
||||
|
@ -689,62 +689,62 @@ mifare_cypher_single_block (MifareDESFireKey key, uint8_t *data, uint8_t *ivect,
|
|||
case T_DES:
|
||||
switch (operation) {
|
||||
case MCO_ENCYPHER:
|
||||
DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
|
||||
DES_ecb_encrypt((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
|
||||
break;
|
||||
case MCO_DECYPHER:
|
||||
DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
||||
DES_ecb_encrypt((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case T_3DES:
|
||||
switch (operation) {
|
||||
case MCO_ENCYPHER:
|
||||
DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
|
||||
DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
|
||||
DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
|
||||
DES_ecb_encrypt((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
|
||||
DES_ecb_encrypt((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
|
||||
DES_ecb_encrypt((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
|
||||
break;
|
||||
case MCO_DECYPHER:
|
||||
DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
||||
DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
|
||||
DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
||||
DES_ecb_encrypt((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
||||
DES_ecb_encrypt((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
|
||||
DES_ecb_encrypt((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case T_3K3DES:
|
||||
switch (operation) {
|
||||
case MCO_ENCYPHER:
|
||||
DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
|
||||
DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
|
||||
DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT);
|
||||
DES_ecb_encrypt((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
|
||||
DES_ecb_encrypt((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
|
||||
DES_ecb_encrypt((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT);
|
||||
break;
|
||||
case MCO_DECYPHER:
|
||||
DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_DECRYPT);
|
||||
DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
|
||||
DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
||||
DES_ecb_encrypt((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_DECRYPT);
|
||||
DES_ecb_encrypt((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
|
||||
DES_ecb_encrypt((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case T_AES:
|
||||
switch (operation) {
|
||||
case MCO_ENCYPHER:
|
||||
AES_set_encrypt_key (key->data, 8*16, &k);
|
||||
AES_encrypt (data, edata, &k);
|
||||
AES_set_encrypt_key(key->data, 8 * 16, &k);
|
||||
AES_encrypt(data, edata, &k);
|
||||
break;
|
||||
case MCO_DECYPHER:
|
||||
AES_set_decrypt_key (key->data, 8*16, &k);
|
||||
AES_decrypt (data, edata, &k);
|
||||
AES_set_decrypt_key(key->data, 8 * 16, &k);
|
||||
AES_decrypt(data, edata, &k);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy (data, edata, block_size);
|
||||
memcpy(data, edata, block_size);
|
||||
|
||||
if (direction == MCD_SEND) {
|
||||
memcpy (ivect, data, block_size);
|
||||
memcpy(ivect, data, block_size);
|
||||
} else {
|
||||
xor (ivect, data, block_size);
|
||||
memcpy (ivect, ovect, block_size);
|
||||
xor(ivect, data, block_size);
|
||||
memcpy(ivect, ovect, block_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -759,19 +759,19 @@ mifare_cypher_single_block (MifareDESFireKey key, uint8_t *data, uint8_t *ivect,
|
|||
* function with tag, key and ivect defined.
|
||||
*/
|
||||
void
|
||||
mifare_cypher_blocks_chained (FreefareTag tag, MifareDESFireKey key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation)
|
||||
mifare_cypher_blocks_chained(FreefareTag tag, MifareDESFireKey key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation)
|
||||
{
|
||||
size_t block_size;
|
||||
|
||||
if (tag) {
|
||||
if (!key)
|
||||
key = MIFARE_DESFIRE (tag)->session_key;
|
||||
key = MIFARE_DESFIRE(tag)->session_key;
|
||||
if (!ivect)
|
||||
ivect = MIFARE_DESFIRE (tag)->ivect;
|
||||
ivect = MIFARE_DESFIRE(tag)->ivect;
|
||||
|
||||
switch (MIFARE_DESFIRE (tag)->authentication_scheme) {
|
||||
switch (MIFARE_DESFIRE(tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
memset (ivect, 0, MAX_CRYPTO_BLOCK_SIZE);
|
||||
memset(ivect, 0, MAX_CRYPTO_BLOCK_SIZE);
|
||||
break;
|
||||
case AS_NEW:
|
||||
break;
|
||||
|
@ -781,11 +781,11 @@ mifare_cypher_blocks_chained (FreefareTag tag, MifareDESFireKey key, uint8_t *iv
|
|||
if (!key || !ivect)
|
||||
abort();
|
||||
|
||||
block_size = key_block_size (key);
|
||||
block_size = key_block_size(key);
|
||||
|
||||
size_t offset = 0;
|
||||
while (offset < data_size) {
|
||||
mifare_cypher_single_block (key, data + offset, ivect, direction, operation, block_size);
|
||||
mifare_cypher_single_block(key, data + offset, ivect, direction, operation, block_size);
|
||||
offset += block_size;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere, Romuald Conty.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -57,7 +57,7 @@ static struct error_message {
|
|||
};
|
||||
|
||||
const char *
|
||||
mifare_desfire_error_lookup (uint8_t code)
|
||||
mifare_desfire_error_lookup(uint8_t code)
|
||||
{
|
||||
struct error_message *e = error_messages;
|
||||
while (e->message) {
|
||||
|
@ -70,19 +70,19 @@ mifare_desfire_error_lookup (uint8_t code)
|
|||
}
|
||||
|
||||
uint8_t
|
||||
mifare_desfire_last_pcd_error (FreefareTag tag)
|
||||
mifare_desfire_last_pcd_error(FreefareTag tag)
|
||||
{
|
||||
if (tag->type != MIFARE_DESFIRE)
|
||||
return 0;
|
||||
|
||||
return MIFARE_DESFIRE (tag)->last_pcd_error;
|
||||
return MIFARE_DESFIRE(tag)->last_pcd_error;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
mifare_desfire_last_picc_error (FreefareTag tag)
|
||||
mifare_desfire_last_picc_error(FreefareTag tag)
|
||||
{
|
||||
if (tag->type != MIFARE_DESFIRE)
|
||||
return 0;
|
||||
|
||||
return MIFARE_DESFIRE (tag)->last_picc_error;
|
||||
return MIFARE_DESFIRE(tag)->last_picc_error;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -23,103 +23,103 @@
|
|||
#include <freefare.h>
|
||||
#include "freefare_internal.h"
|
||||
|
||||
static inline void update_key_schedules (MifareDESFireKey key);
|
||||
static inline void update_key_schedules(MifareDESFireKey key);
|
||||
|
||||
static inline void
|
||||
update_key_schedules (MifareDESFireKey key)
|
||||
update_key_schedules(MifareDESFireKey key)
|
||||
{
|
||||
DES_set_key ((DES_cblock *)key->data, &(key->ks1));
|
||||
DES_set_key ((DES_cblock *)(key->data + 8), &(key->ks2));
|
||||
DES_set_key((DES_cblock *)key->data, &(key->ks1));
|
||||
DES_set_key((DES_cblock *)(key->data + 8), &(key->ks2));
|
||||
if (T_3K3DES == key->type) {
|
||||
DES_set_key ((DES_cblock *)(key->data + 16), &(key->ks3));
|
||||
DES_set_key((DES_cblock *)(key->data + 16), &(key->ks3));
|
||||
}
|
||||
}
|
||||
|
||||
MifareDESFireKey
|
||||
mifare_desfire_des_key_new (const uint8_t value[8])
|
||||
mifare_desfire_des_key_new(const uint8_t value[8])
|
||||
{
|
||||
uint8_t data[8];
|
||||
memcpy (data, value, 8);
|
||||
for (int n=0; n < 8; n++)
|
||||
memcpy(data, value, 8);
|
||||
for (int n = 0; n < 8; n++)
|
||||
data[n] &= 0xfe;
|
||||
return mifare_desfire_des_key_new_with_version (data);
|
||||
return mifare_desfire_des_key_new_with_version(data);
|
||||
}
|
||||
|
||||
MifareDESFireKey
|
||||
mifare_desfire_des_key_new_with_version (const uint8_t value[8])
|
||||
mifare_desfire_des_key_new_with_version(const uint8_t value[8])
|
||||
{
|
||||
MifareDESFireKey key;
|
||||
|
||||
if ((key = malloc (sizeof (struct mifare_desfire_key)))) {
|
||||
if ((key = malloc(sizeof(struct mifare_desfire_key)))) {
|
||||
key->type = T_DES;
|
||||
memcpy (key->data, value, 8);
|
||||
memcpy (key->data+8, value, 8);
|
||||
update_key_schedules (key);
|
||||
memcpy(key->data, value, 8);
|
||||
memcpy(key->data + 8, value, 8);
|
||||
update_key_schedules(key);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
MifareDESFireKey
|
||||
mifare_desfire_3des_key_new (const uint8_t value[16])
|
||||
mifare_desfire_3des_key_new(const uint8_t value[16])
|
||||
{
|
||||
uint8_t data[16];
|
||||
memcpy (data, value, 16);
|
||||
for (int n=0; n < 8; n++)
|
||||
memcpy(data, value, 16);
|
||||
for (int n = 0; n < 8; n++)
|
||||
data[n] &= 0xfe;
|
||||
for (int n=8; n < 16; n++)
|
||||
for (int n = 8; n < 16; n++)
|
||||
data[n] |= 0x01;
|
||||
return mifare_desfire_3des_key_new_with_version (data);
|
||||
return mifare_desfire_3des_key_new_with_version(data);
|
||||
}
|
||||
|
||||
MifareDESFireKey
|
||||
mifare_desfire_3des_key_new_with_version (const uint8_t value[16])
|
||||
mifare_desfire_3des_key_new_with_version(const uint8_t value[16])
|
||||
{
|
||||
MifareDESFireKey key;
|
||||
|
||||
if ((key = malloc (sizeof (struct mifare_desfire_key)))) {
|
||||
if ((key = malloc(sizeof(struct mifare_desfire_key)))) {
|
||||
key->type = T_3DES;
|
||||
memcpy (key->data, value, 16);
|
||||
update_key_schedules (key);
|
||||
memcpy(key->data, value, 16);
|
||||
update_key_schedules(key);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
MifareDESFireKey
|
||||
mifare_desfire_3k3des_key_new (const uint8_t value[24])
|
||||
mifare_desfire_3k3des_key_new(const uint8_t value[24])
|
||||
{
|
||||
uint8_t data[24];
|
||||
memcpy (data, value, 24);
|
||||
for (int n=0; n < 8; n++)
|
||||
memcpy(data, value, 24);
|
||||
for (int n = 0; n < 8; n++)
|
||||
data[n] &= 0xfe;
|
||||
return mifare_desfire_3k3des_key_new_with_version (data);
|
||||
return mifare_desfire_3k3des_key_new_with_version(data);
|
||||
}
|
||||
|
||||
MifareDESFireKey
|
||||
mifare_desfire_3k3des_key_new_with_version (const uint8_t value[24])
|
||||
mifare_desfire_3k3des_key_new_with_version(const uint8_t value[24])
|
||||
{
|
||||
MifareDESFireKey key;
|
||||
|
||||
if ((key = malloc (sizeof (struct mifare_desfire_key)))) {
|
||||
if ((key = malloc(sizeof(struct mifare_desfire_key)))) {
|
||||
key->type = T_3K3DES;
|
||||
memcpy (key->data, value, 24);
|
||||
update_key_schedules (key);
|
||||
memcpy(key->data, value, 24);
|
||||
update_key_schedules(key);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
MifareDESFireKey
|
||||
mifare_desfire_aes_key_new (const uint8_t value[16])
|
||||
mifare_desfire_aes_key_new(const uint8_t value[16])
|
||||
{
|
||||
return mifare_desfire_aes_key_new_with_version (value, 0);
|
||||
return mifare_desfire_aes_key_new_with_version(value, 0);
|
||||
}
|
||||
|
||||
MifareDESFireKey
|
||||
mifare_desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version)
|
||||
mifare_desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version)
|
||||
{
|
||||
MifareDESFireKey key;
|
||||
|
||||
if ((key = malloc (sizeof (struct mifare_desfire_key)))) {
|
||||
memcpy (key->data, value, 16);
|
||||
if ((key = malloc(sizeof(struct mifare_desfire_key)))) {
|
||||
memcpy(key->data, value, 16);
|
||||
key->type = T_AES;
|
||||
key->aes_version = version;
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ mifare_desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t versio
|
|||
}
|
||||
|
||||
uint8_t
|
||||
mifare_desfire_key_get_version (MifareDESFireKey key)
|
||||
mifare_desfire_key_get_version(MifareDESFireKey key)
|
||||
{
|
||||
uint8_t version = 0;
|
||||
|
||||
|
@ -139,24 +139,24 @@ mifare_desfire_key_get_version (MifareDESFireKey key)
|
|||
}
|
||||
|
||||
void
|
||||
mifare_desfire_key_set_version (MifareDESFireKey key, uint8_t version)
|
||||
mifare_desfire_key_set_version(MifareDESFireKey key, uint8_t version)
|
||||
{
|
||||
for (int n = 0; n < 8; n++) {
|
||||
uint8_t version_bit = ((version & (1 << (7-n))) >> (7-n));
|
||||
uint8_t version_bit = ((version & (1 << (7 - n))) >> (7 - n));
|
||||
key->data[n] &= 0xfe;
|
||||
key->data[n] |= version_bit;
|
||||
if (key->type == T_DES) {
|
||||
key->data[n+8] = key->data[n];
|
||||
key->data[n + 8] = key->data[n];
|
||||
} else {
|
||||
// Write ~version to avoid turning a 3DES key into a DES key
|
||||
key->data[n+8] &= 0xfe;
|
||||
key->data[n+8] |= ~version_bit;
|
||||
key->data[n + 8] &= 0xfe;
|
||||
key->data[n + 8] |= ~version_bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MifareDESFireKey
|
||||
mifare_desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], MifareDESFireKey authentication_key)
|
||||
mifare_desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], MifareDESFireKey authentication_key)
|
||||
{
|
||||
MifareDESFireKey key = NULL;
|
||||
|
||||
|
@ -164,32 +164,32 @@ mifare_desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], Mifa
|
|||
|
||||
switch (authentication_key->type) {
|
||||
case T_DES:
|
||||
memcpy (buffer, rnda, 4);
|
||||
memcpy (buffer+4, rndb, 4);
|
||||
key = mifare_desfire_des_key_new_with_version (buffer);
|
||||
memcpy(buffer, rnda, 4);
|
||||
memcpy(buffer + 4, rndb, 4);
|
||||
key = mifare_desfire_des_key_new_with_version(buffer);
|
||||
break;
|
||||
case T_3DES:
|
||||
memcpy (buffer, rnda, 4);
|
||||
memcpy (buffer+4, rndb, 4);
|
||||
memcpy (buffer+8, rnda+4, 4);
|
||||
memcpy (buffer+12, rndb+4, 4);
|
||||
key = mifare_desfire_3des_key_new_with_version (buffer);
|
||||
memcpy(buffer, rnda, 4);
|
||||
memcpy(buffer + 4, rndb, 4);
|
||||
memcpy(buffer + 8, rnda + 4, 4);
|
||||
memcpy(buffer + 12, rndb + 4, 4);
|
||||
key = mifare_desfire_3des_key_new_with_version(buffer);
|
||||
break;
|
||||
case T_3K3DES:
|
||||
memcpy (buffer, rnda, 4);
|
||||
memcpy (buffer+4, rndb, 4);
|
||||
memcpy (buffer+8, rnda+6, 4);
|
||||
memcpy (buffer+12, rndb+6, 4);
|
||||
memcpy (buffer+16, rnda+12, 4);
|
||||
memcpy (buffer+20, rndb+12, 4);
|
||||
key = mifare_desfire_3k3des_key_new (buffer);
|
||||
memcpy(buffer, rnda, 4);
|
||||
memcpy(buffer + 4, rndb, 4);
|
||||
memcpy(buffer + 8, rnda + 6, 4);
|
||||
memcpy(buffer + 12, rndb + 6, 4);
|
||||
memcpy(buffer + 16, rnda + 12, 4);
|
||||
memcpy(buffer + 20, rndb + 12, 4);
|
||||
key = mifare_desfire_3k3des_key_new(buffer);
|
||||
break;
|
||||
case T_AES:
|
||||
memcpy (buffer, rnda, 4);
|
||||
memcpy (buffer+4, rndb, 4);
|
||||
memcpy (buffer+8, rnda+12, 4);
|
||||
memcpy (buffer+12, rndb+12, 4);
|
||||
key = mifare_desfire_aes_key_new (buffer);
|
||||
memcpy(buffer, rnda, 4);
|
||||
memcpy(buffer + 4, rndb, 4);
|
||||
memcpy(buffer + 8, rnda + 12, 4);
|
||||
memcpy(buffer + 12, rndb + 12, 4);
|
||||
key = mifare_desfire_aes_key_new(buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -197,7 +197,7 @@ mifare_desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], Mifa
|
|||
}
|
||||
|
||||
void
|
||||
mifare_desfire_key_free (MifareDESFireKey key)
|
||||
mifare_desfire_key_free(MifareDESFireKey key)
|
||||
{
|
||||
free (key);
|
||||
free(key);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -47,66 +47,66 @@
|
|||
|
||||
#define ASSERT_VALID_PAGE(tag, page, mode_write) \
|
||||
do { \
|
||||
if (is_mifare_ultralightc (tag)) { \
|
||||
if (mode_write) { \
|
||||
if (page >= MIFARE_ULTRALIGHT_C_PAGE_COUNT) return errno = EINVAL, -1; \
|
||||
} else { \
|
||||
if (page >= MIFARE_ULTRALIGHT_C_PAGE_COUNT_READ) return errno = EINVAL, -1; \
|
||||
} \
|
||||
} else { \
|
||||
if (page >= MIFARE_ULTRALIGHT_PAGE_COUNT) return errno = EINVAL, -1; \
|
||||
} \
|
||||
if (is_mifare_ultralightc (tag)) { \
|
||||
if (mode_write) { \
|
||||
if (page >= MIFARE_ULTRALIGHT_C_PAGE_COUNT) return errno = EINVAL, -1; \
|
||||
} else { \
|
||||
if (page >= MIFARE_ULTRALIGHT_C_PAGE_COUNT_READ) return errno = EINVAL, -1; \
|
||||
} \
|
||||
} else { \
|
||||
if (page >= MIFARE_ULTRALIGHT_PAGE_COUNT) return errno = EINVAL, -1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ULTRALIGHT_TRANSCEIVE(tag, msg, res) \
|
||||
do { \
|
||||
errno = 0; \
|
||||
DEBUG_XFER (msg, __##msg##_n, "===> "); \
|
||||
int _res; \
|
||||
if ((_res = nfc_initiator_transceive_bytes (tag->device, msg, __##msg##_n, res, __##res##_size, 0)) < 0) { \
|
||||
return errno = EIO, -1; \
|
||||
} \
|
||||
__##res##_n = _res; \
|
||||
DEBUG_XFER (res, __##res##_n, "<=== "); \
|
||||
errno = 0; \
|
||||
DEBUG_XFER (msg, __##msg##_n, "===> "); \
|
||||
int _res; \
|
||||
if ((_res = nfc_initiator_transceive_bytes (tag->device, msg, __##msg##_n, res, __##res##_size, 0)) < 0) { \
|
||||
return errno = EIO, -1; \
|
||||
} \
|
||||
__##res##_n = _res; \
|
||||
DEBUG_XFER (res, __##res##_n, "<=== "); \
|
||||
} while (0)
|
||||
|
||||
#define ULTRALIGHT_TRANSCEIVE_RAW(tag, msg, res) \
|
||||
do { \
|
||||
errno = 0; \
|
||||
if (nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, false) < 0) { \
|
||||
errno = EIO; \
|
||||
return -1; \
|
||||
} \
|
||||
DEBUG_XFER (msg, __##msg##_n, "===> "); \
|
||||
int _res; \
|
||||
if ((_res = nfc_initiator_transceive_bytes (tag->device, msg, __##msg##_n, res, __##res##_size, 0)) < 0) { \
|
||||
nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, true); \
|
||||
return errno = EIO, -1; \
|
||||
} \
|
||||
__##res##_n = _res; \
|
||||
DEBUG_XFER (res, __##res##_n, "<=== "); \
|
||||
if (nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, true) < 0) { \
|
||||
errno = EIO; \
|
||||
return -1; \
|
||||
} \
|
||||
errno = 0; \
|
||||
if (nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, false) < 0) { \
|
||||
errno = EIO; \
|
||||
return -1; \
|
||||
} \
|
||||
DEBUG_XFER (msg, __##msg##_n, "===> "); \
|
||||
int _res; \
|
||||
if ((_res = nfc_initiator_transceive_bytes (tag->device, msg, __##msg##_n, res, __##res##_size, 0)) < 0) { \
|
||||
nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, true); \
|
||||
return errno = EIO, -1; \
|
||||
} \
|
||||
__##res##_n = _res; \
|
||||
DEBUG_XFER (res, __##res##_n, "<=== "); \
|
||||
if (nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, true) < 0) { \
|
||||
errno = EIO; \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static bool
|
||||
taste (nfc_target target)
|
||||
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)
|
||||
mifare_ultralight_taste(nfc_device *device, nfc_target target)
|
||||
{
|
||||
return taste (target) && !is_mifare_ultralightc_on_reader (device, target.nti.nai);
|
||||
return taste(target) && !is_mifare_ultralightc_on_reader(device, target.nti.nai);
|
||||
}
|
||||
|
||||
bool
|
||||
mifare_ultralightc_taste (nfc_device *device, nfc_target target)
|
||||
mifare_ultralightc_taste(nfc_device *device, nfc_target target)
|
||||
{
|
||||
return taste (target) && is_mifare_ultralightc_on_reader (device, target.nti.nai);
|
||||
return taste(target) && is_mifare_ultralightc_on_reader(device, target.nti.nai);
|
||||
}
|
||||
|
||||
|
||||
|
@ -118,11 +118,11 @@ mifare_ultralightc_taste (nfc_device *device, nfc_target target)
|
|||
* Allocates and initialize a MIFARE UltraLight tag.
|
||||
*/
|
||||
static FreefareTag
|
||||
_mifare_ultralightc_tag_new (nfc_device *device, nfc_target target, bool is_ultralightc)
|
||||
_mifare_ultralightc_tag_new(nfc_device *device, nfc_target target, bool is_ultralightc)
|
||||
{
|
||||
FreefareTag tag;
|
||||
|
||||
if ((tag = malloc (sizeof (struct mifare_ultralight_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;
|
||||
|
@ -134,30 +134,30 @@ _mifare_ultralightc_tag_new (nfc_device *device, nfc_target target, bool is_ultr
|
|||
}
|
||||
|
||||
FreefareTag
|
||||
mifare_ultralight_tag_new (nfc_device *device, nfc_target target)
|
||||
mifare_ultralight_tag_new(nfc_device *device, nfc_target target)
|
||||
{
|
||||
return _mifare_ultralightc_tag_new (device, target, false);
|
||||
return _mifare_ultralightc_tag_new(device, target, false);
|
||||
}
|
||||
|
||||
FreefareTag
|
||||
mifare_ultralightc_tag_new (nfc_device *device, nfc_target target)
|
||||
mifare_ultralightc_tag_new(nfc_device *device, nfc_target target)
|
||||
{
|
||||
return _mifare_ultralightc_tag_new (device, target, true);
|
||||
return _mifare_ultralightc_tag_new(device, target, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the provided tag.
|
||||
*/
|
||||
void
|
||||
mifare_ultralight_tag_free (FreefareTag tag)
|
||||
mifare_ultralight_tag_free(FreefareTag tag)
|
||||
{
|
||||
free (tag);
|
||||
free(tag);
|
||||
}
|
||||
|
||||
void
|
||||
mifare_ultralightc_tag_free (FreefareTag tag)
|
||||
mifare_ultralightc_tag_free(FreefareTag tag)
|
||||
{
|
||||
mifare_ultralight_tag_free (tag);
|
||||
mifare_ultralight_tag_free(tag);
|
||||
}
|
||||
|
||||
|
||||
|
@ -174,16 +174,16 @@ mifare_ultralightc_tag_free (FreefareTag tag)
|
|||
* Establish connection to the provided tag.
|
||||
*/
|
||||
int
|
||||
mifare_ultralight_connect (FreefareTag tag)
|
||||
mifare_ultralight_connect(FreefareTag tag)
|
||||
{
|
||||
ASSERT_INACTIVE (tag);
|
||||
ASSERT_INACTIVE(tag);
|
||||
|
||||
nfc_target pnti;
|
||||
nfc_modulation modulation = {
|
||||
.nmt = NMT_ISO14443A,
|
||||
.nbr = NBR_106
|
||||
};
|
||||
if (nfc_initiator_select_passive_target (tag->device, modulation, tag->info.nti.nai.abtUid, tag->info.nti.nai.szUidLen, &pnti) >= 0) {
|
||||
if (nfc_initiator_select_passive_target(tag->device, modulation, tag->info.nti.nai.abtUid, tag->info.nti.nai.szUidLen, &pnti) >= 0) {
|
||||
tag->active = 1;
|
||||
for (int i = 0; i < MIFARE_ULTRALIGHT_MAX_PAGE_COUNT; i++)
|
||||
MIFARE_ULTRALIGHT(tag)->cached_pages[i] = 0;
|
||||
|
@ -198,11 +198,11 @@ mifare_ultralight_connect (FreefareTag tag)
|
|||
* Terminate connection with the provided tag.
|
||||
*/
|
||||
int
|
||||
mifare_ultralight_disconnect (FreefareTag tag)
|
||||
mifare_ultralight_disconnect(FreefareTag tag)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
ASSERT_ACTIVE(tag);
|
||||
|
||||
if (nfc_initiator_deselect_target (tag->device) >= 0) {
|
||||
if (nfc_initiator_deselect_target(tag->device) >= 0) {
|
||||
tag->active = 0;
|
||||
} else {
|
||||
errno = EIO;
|
||||
|
@ -223,29 +223,29 @@ mifare_ultralight_disconnect (FreefareTag tag)
|
|||
* Read data from the provided MIFARE tag.
|
||||
*/
|
||||
int
|
||||
mifare_ultralight_read (FreefareTag tag, MifareUltralightPageNumber page, MifareUltralightPage *data)
|
||||
mifare_ultralight_read(FreefareTag tag, MifareUltralightPageNumber page, MifareUltralightPage *data)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
ASSERT_VALID_PAGE (tag, page, false);
|
||||
ASSERT_ACTIVE(tag);
|
||||
ASSERT_VALID_PAGE(tag, page, false);
|
||||
|
||||
if (!MIFARE_ULTRALIGHT(tag)->cached_pages[page]) {
|
||||
BUFFER_INIT (cmd, 2);
|
||||
BUFFER_ALIAS (res, MIFARE_ULTRALIGHT(tag)->cache[page], sizeof(MifareUltralightPage) * 4);
|
||||
BUFFER_INIT(cmd, 2);
|
||||
BUFFER_ALIAS(res, MIFARE_ULTRALIGHT(tag)->cache[page], sizeof(MifareUltralightPage) * 4);
|
||||
|
||||
BUFFER_APPEND (cmd, 0x30);
|
||||
BUFFER_APPEND (cmd, page);
|
||||
BUFFER_APPEND(cmd, 0x30);
|
||||
BUFFER_APPEND(cmd, page);
|
||||
|
||||
ULTRALIGHT_TRANSCEIVE (tag, cmd, res);
|
||||
ULTRALIGHT_TRANSCEIVE(tag, cmd, res);
|
||||
|
||||
/* Handle wrapped pages */
|
||||
int iPageCount;
|
||||
if (is_mifare_ultralightc (tag)) {
|
||||
if (is_mifare_ultralightc(tag)) {
|
||||
iPageCount = MIFARE_ULTRALIGHT_C_PAGE_COUNT_READ;
|
||||
} else {
|
||||
iPageCount = MIFARE_ULTRALIGHT_PAGE_COUNT;
|
||||
}
|
||||
for (int i = iPageCount; i <= page + 3; i++) {
|
||||
memcpy (MIFARE_ULTRALIGHT(tag)->cache[i % iPageCount], MIFARE_ULTRALIGHT(tag)->cache[i], sizeof (MifareUltralightPage));
|
||||
memcpy(MIFARE_ULTRALIGHT(tag)->cache[i % iPageCount], MIFARE_ULTRALIGHT(tag)->cache[i], sizeof(MifareUltralightPage));
|
||||
}
|
||||
|
||||
/* Mark pages as cached */
|
||||
|
@ -254,7 +254,7 @@ mifare_ultralight_read (FreefareTag tag, MifareUltralightPageNumber page, Mifare
|
|||
}
|
||||
}
|
||||
|
||||
memcpy (data, MIFARE_ULTRALIGHT(tag)->cache[page], sizeof (*data));
|
||||
memcpy(data, MIFARE_ULTRALIGHT(tag)->cache[page], sizeof(*data));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -262,19 +262,19 @@ mifare_ultralight_read (FreefareTag tag, MifareUltralightPageNumber page, Mifare
|
|||
* Read data to the provided MIFARE tag.
|
||||
*/
|
||||
int
|
||||
mifare_ultralight_write (FreefareTag tag, const MifareUltralightPageNumber page, const MifareUltralightPage data)
|
||||
mifare_ultralight_write(FreefareTag tag, const MifareUltralightPageNumber page, const MifareUltralightPage data)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
ASSERT_VALID_PAGE (tag, page, true);
|
||||
ASSERT_ACTIVE(tag);
|
||||
ASSERT_VALID_PAGE(tag, page, true);
|
||||
|
||||
BUFFER_INIT (cmd, 6);
|
||||
BUFFER_INIT (res, 1);
|
||||
BUFFER_INIT(cmd, 6);
|
||||
BUFFER_INIT(res, 1);
|
||||
|
||||
BUFFER_APPEND (cmd, 0xA2);
|
||||
BUFFER_APPEND (cmd, page);
|
||||
BUFFER_APPEND_BYTES (cmd, data, sizeof (MifareUltralightPage));
|
||||
BUFFER_APPEND(cmd, 0xA2);
|
||||
BUFFER_APPEND(cmd, page);
|
||||
BUFFER_APPEND_BYTES(cmd, data, sizeof(MifareUltralightPage));
|
||||
|
||||
ULTRALIGHT_TRANSCEIVE (tag, cmd, res);
|
||||
ULTRALIGHT_TRANSCEIVE(tag, cmd, res);
|
||||
|
||||
/* Invalidate page in cache */
|
||||
MIFARE_ULTRALIGHT(tag)->cached_pages[page] = 0;
|
||||
|
@ -286,62 +286,62 @@ mifare_ultralight_write (FreefareTag tag, const MifareUltralightPageNumber page,
|
|||
* Authenticate to the provided MIFARE tag.
|
||||
*/
|
||||
int
|
||||
mifare_ultralightc_authenticate (FreefareTag tag, const MifareDESFireKey key)
|
||||
mifare_ultralightc_authenticate(FreefareTag tag, const MifareDESFireKey key)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
ASSERT_ACTIVE(tag);
|
||||
|
||||
BUFFER_INIT (cmd1, 2);
|
||||
BUFFER_INIT (res, 9);
|
||||
BUFFER_APPEND (cmd1, 0x1A);
|
||||
BUFFER_APPEND (cmd1, 0x00);
|
||||
BUFFER_INIT(cmd1, 2);
|
||||
BUFFER_INIT(res, 9);
|
||||
BUFFER_APPEND(cmd1, 0x1A);
|
||||
BUFFER_APPEND(cmd1, 0x00);
|
||||
|
||||
ULTRALIGHT_TRANSCEIVE_RAW(tag, cmd1, res);
|
||||
|
||||
uint8_t PICC_E_RndB[8];
|
||||
memcpy (PICC_E_RndB, res+1, 8);
|
||||
memcpy(PICC_E_RndB, res + 1, 8);
|
||||
|
||||
uint8_t PICC_RndB[8];
|
||||
memcpy (PICC_RndB, PICC_E_RndB, 8);
|
||||
memcpy(PICC_RndB, PICC_E_RndB, 8);
|
||||
uint8_t ivect[8];
|
||||
memset (ivect, '\0', sizeof (ivect));
|
||||
mifare_cypher_single_block (key, PICC_RndB, ivect, MCD_RECEIVE, MCO_DECYPHER, 8);
|
||||
memset(ivect, '\0', sizeof(ivect));
|
||||
mifare_cypher_single_block(key, PICC_RndB, ivect, MCD_RECEIVE, MCO_DECYPHER, 8);
|
||||
|
||||
uint8_t PCD_RndA[8];
|
||||
DES_random_key ((DES_cblock*)&PCD_RndA);
|
||||
DES_random_key((DES_cblock *)&PCD_RndA);
|
||||
|
||||
uint8_t PCD_r_RndB[8];
|
||||
memcpy (PCD_r_RndB, PICC_RndB, 8);
|
||||
rol (PCD_r_RndB, 8);
|
||||
memcpy(PCD_r_RndB, PICC_RndB, 8);
|
||||
rol(PCD_r_RndB, 8);
|
||||
|
||||
uint8_t token[16];
|
||||
memcpy (token, PCD_RndA, 8);
|
||||
memcpy (token+8, PCD_r_RndB, 8);
|
||||
memcpy(token, PCD_RndA, 8);
|
||||
memcpy(token + 8, PCD_r_RndB, 8);
|
||||
size_t offset = 0;
|
||||
|
||||
while (offset < 16) {
|
||||
mifare_cypher_single_block (key, token + offset, ivect, MCD_SEND, MCO_ENCYPHER, 8);
|
||||
mifare_cypher_single_block(key, token + offset, ivect, MCD_SEND, MCO_ENCYPHER, 8);
|
||||
offset += 8;
|
||||
}
|
||||
|
||||
BUFFER_INIT (cmd2, 17);
|
||||
BUFFER_INIT(cmd2, 17);
|
||||
|
||||
BUFFER_APPEND (cmd2, 0xAF);
|
||||
BUFFER_APPEND_BYTES (cmd2, token, 16);
|
||||
BUFFER_APPEND(cmd2, 0xAF);
|
||||
BUFFER_APPEND_BYTES(cmd2, token, 16);
|
||||
|
||||
ULTRALIGHT_TRANSCEIVE_RAW(tag, cmd2, res);
|
||||
|
||||
uint8_t PICC_E_RndA_s[8];
|
||||
memcpy (PICC_E_RndA_s, res+1, 8);
|
||||
memcpy(PICC_E_RndA_s, res + 1, 8);
|
||||
|
||||
uint8_t PICC_RndA_s[8];
|
||||
memcpy (PICC_RndA_s, PICC_E_RndA_s, 8);
|
||||
mifare_cypher_single_block (key, PICC_RndA_s, ivect, MCD_RECEIVE, MCO_DECYPHER, 8);
|
||||
memcpy(PICC_RndA_s, PICC_E_RndA_s, 8);
|
||||
mifare_cypher_single_block(key, PICC_RndA_s, ivect, MCD_RECEIVE, MCO_DECYPHER, 8);
|
||||
|
||||
uint8_t PCD_RndA_s[8];
|
||||
memcpy (PCD_RndA_s, PCD_RndA, 8);
|
||||
rol (PCD_RndA_s, 8);
|
||||
memcpy(PCD_RndA_s, PCD_RndA, 8);
|
||||
rol(PCD_RndA_s, 8);
|
||||
|
||||
if (0 != memcmp (PCD_RndA_s, PICC_RndA_s, 8)) {
|
||||
if (0 != memcmp(PCD_RndA_s, PICC_RndA_s, 8)) {
|
||||
errno = EACCES;
|
||||
return -1;
|
||||
}
|
||||
|
@ -350,13 +350,13 @@ mifare_ultralightc_authenticate (FreefareTag tag, const MifareDESFireKey key)
|
|||
}
|
||||
|
||||
bool
|
||||
is_mifare_ultralight (FreefareTag tag)
|
||||
is_mifare_ultralight(FreefareTag tag)
|
||||
{
|
||||
return tag->type == MIFARE_ULTRALIGHT;
|
||||
}
|
||||
|
||||
bool
|
||||
is_mifare_ultralightc (FreefareTag tag)
|
||||
is_mifare_ultralightc(FreefareTag tag)
|
||||
{
|
||||
return tag->type == MIFARE_ULTRALIGHT_C;
|
||||
}
|
||||
|
@ -365,7 +365,7 @@ is_mifare_ultralightc (FreefareTag tag)
|
|||
* Callback for freefare_tag_new to test presence of a MIFARE UltralightC on the reader.
|
||||
*/
|
||||
bool
|
||||
is_mifare_ultralightc_on_reader (nfc_device *device, nfc_iso14443a_info nai)
|
||||
is_mifare_ultralightc_on_reader(nfc_device *device, nfc_iso14443a_info nai)
|
||||
{
|
||||
int ret;
|
||||
uint8_t cmd_step1[2];
|
||||
|
@ -378,10 +378,10 @@ is_mifare_ultralightc_on_reader (nfc_device *device, nfc_iso14443a_info nai)
|
|||
.nmt = NMT_ISO14443A,
|
||||
.nbr = NBR_106
|
||||
};
|
||||
nfc_initiator_select_passive_target (device, modulation, nai.abtUid, nai.szUidLen, &pnti);
|
||||
nfc_device_set_property_bool (device, NP_EASY_FRAMING, false);
|
||||
ret = nfc_initiator_transceive_bytes (device, cmd_step1, sizeof (cmd_step1), res_step1, sizeof(res_step1), 0);
|
||||
nfc_device_set_property_bool (device, NP_EASY_FRAMING, true);
|
||||
nfc_initiator_deselect_target (device);
|
||||
nfc_initiator_select_passive_target(device, modulation, nai.abtUid, nai.szUidLen, &pnti);
|
||||
nfc_device_set_property_bool(device, NP_EASY_FRAMING, false);
|
||||
ret = nfc_initiator_transceive_bytes(device, cmd_step1, sizeof(cmd_step1), res_step1, sizeof(res_step1), 0);
|
||||
nfc_device_set_property_bool(device, NP_EASY_FRAMING, true);
|
||||
nfc_initiator_deselect_target(device);
|
||||
return ret >= 0;
|
||||
}
|
||||
|
|
|
@ -50,63 +50,63 @@
|
|||
|
||||
#define NTAG_ASSERT_VALID_PAGE(tag, page, mode_write) \
|
||||
do { \
|
||||
if (mode_write) { \
|
||||
if (page<=0x02) \
|
||||
{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_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;} \
|
||||
} \
|
||||
if (mode_write) { \
|
||||
if (page<=0x02) \
|
||||
{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_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;} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define NTAG_TRANSCEIVE(tag, msg, res) \
|
||||
do { \
|
||||
errno = 0; \
|
||||
DEBUG_XFER (msg, __##msg##_n, "===> "); \
|
||||
int _res; \
|
||||
if ((_res = nfc_initiator_transceive_bytes (tag->device, msg, __##msg##_n, res, __##res##_size, 0)) < 0) { \
|
||||
return errno = EIO, -1; \
|
||||
} \
|
||||
__##res##_n = _res; \
|
||||
DEBUG_XFER (res, __##res##_n, "<=== "); \
|
||||
errno = 0; \
|
||||
DEBUG_XFER (msg, __##msg##_n, "===> "); \
|
||||
int _res; \
|
||||
if ((_res = nfc_initiator_transceive_bytes (tag->device, msg, __##msg##_n, res, __##res##_size, 0)) < 0) { \
|
||||
return errno = EIO, -1; \
|
||||
} \
|
||||
__##res##_n = _res; \
|
||||
DEBUG_XFER (res, __##res##_n, "<=== "); \
|
||||
} while (0)
|
||||
|
||||
#define NTAG_TRANSCEIVE_RAW(tag, msg, res) \
|
||||
do { \
|
||||
errno = 0; \
|
||||
if (nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, false) < 0) { \
|
||||
errno = EIO; \
|
||||
return -1; \
|
||||
} \
|
||||
DEBUG_XFER (msg, __##msg##_n, "===> "); \
|
||||
int _res; \
|
||||
if ((_res = nfc_initiator_transceive_bytes (tag->device, msg, __##msg##_n, res, __##res##_size, 0)) < 0) { \
|
||||
nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, true); \
|
||||
return errno = EIO, -1; \
|
||||
} \
|
||||
__##res##_n = _res; \
|
||||
DEBUG_XFER (res, __##res##_n, "<=== "); \
|
||||
if (nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, true) < 0) { \
|
||||
errno = EIO; \
|
||||
return -1; \
|
||||
} \
|
||||
errno = 0; \
|
||||
if (nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, false) < 0) { \
|
||||
errno = EIO; \
|
||||
return -1; \
|
||||
} \
|
||||
DEBUG_XFER (msg, __##msg##_n, "===> "); \
|
||||
int _res; \
|
||||
if ((_res = nfc_initiator_transceive_bytes (tag->device, msg, __##msg##_n, res, __##res##_size, 0)) < 0) { \
|
||||
nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, true); \
|
||||
return errno = EIO, -1; \
|
||||
} \
|
||||
__##res##_n = _res; \
|
||||
DEBUG_XFER (res, __##res##_n, "<=== "); \
|
||||
if (nfc_device_set_property_bool (tag->device, NP_EASY_FRAMING, true) < 0) { \
|
||||
errno = EIO; \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
bool
|
||||
ntag21x_taste(nfc_device *device, nfc_target target)
|
||||
{
|
||||
return target.nm.nmt == NMT_ISO14443A && target.nti.nai.btSak == 0x00 && ntag21x_is_auth_supported (device, target.nti.nai);
|
||||
return target.nm.nmt == NMT_ISO14443A && target.nti.nai.btSak == 0x00 && ntag21x_is_auth_supported(device, target.nti.nai);
|
||||
}
|
||||
|
||||
|
||||
|
@ -122,7 +122,7 @@ _ntag21x_tag_new(nfc_device *device, nfc_target target)
|
|||
{
|
||||
FreefareTag tag;
|
||||
|
||||
if ((tag = malloc (sizeof (struct ntag21x_tag)))) {
|
||||
if ((tag = malloc(sizeof(struct ntag21x_tag)))) {
|
||||
tag->type = NTAG_21x ;
|
||||
tag->free_tag = ntag21x_tag_free;
|
||||
tag->device = device;
|
||||
|
@ -146,7 +146,7 @@ _ntag21x_tag_reuse(FreefareTag old_tag)
|
|||
{
|
||||
FreefareTag tag;
|
||||
|
||||
if ((tag = malloc (sizeof (struct ntag21x_tag)))) {
|
||||
if ((tag = malloc(sizeof(struct ntag21x_tag)))) {
|
||||
tag->type = NTAG_21x ;
|
||||
tag->free_tag = ntag21x_tag_free;
|
||||
tag->device = old_tag->device;
|
||||
|
@ -168,25 +168,25 @@ _ntag21x_tag_reuse(FreefareTag old_tag)
|
|||
FreefareTag
|
||||
ntag21x_tag_new(nfc_device *device, nfc_target target)
|
||||
{
|
||||
return _ntag21x_tag_new (device, target);
|
||||
return _ntag21x_tag_new(device, target);
|
||||
}
|
||||
|
||||
FreefareTag
|
||||
ntag21x_tag_reuse(FreefareTag tag)
|
||||
{
|
||||
return _ntag21x_tag_reuse (tag);
|
||||
return _ntag21x_tag_reuse(tag);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create new key for NTAG
|
||||
*/
|
||||
NTAG21xKey
|
||||
ntag21x_key_new(const uint8_t data[4],const uint8_t pack[2])
|
||||
ntag21x_key_new(const uint8_t data[4], const uint8_t pack[2])
|
||||
{
|
||||
NTAG21xKey key;
|
||||
if ((key = malloc (sizeof (struct ntag21x_key)))) {
|
||||
memcpy(key->data,data,4);
|
||||
memcpy(key->pack,pack,2);
|
||||
if ((key = malloc(sizeof(struct ntag21x_key)))) {
|
||||
memcpy(key->data, data, 4);
|
||||
memcpy(key->pack, pack, 2);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
@ -206,7 +206,7 @@ ntag21x_key_free(NTAG21xKey key)
|
|||
void
|
||||
ntag21x_tag_free(FreefareTag tag)
|
||||
{
|
||||
free (tag);
|
||||
free(tag);
|
||||
}
|
||||
|
||||
|
||||
|
@ -226,14 +226,14 @@ ntag21x_tag_free(FreefareTag tag)
|
|||
int
|
||||
ntag21x_connect(FreefareTag tag)
|
||||
{
|
||||
ASSERT_INACTIVE (tag);
|
||||
ASSERT_INACTIVE(tag);
|
||||
|
||||
nfc_target pnti;
|
||||
nfc_modulation modulation = {
|
||||
.nmt = NMT_ISO14443A,
|
||||
.nbr = NBR_106
|
||||
};
|
||||
if (nfc_initiator_select_passive_target (tag->device, modulation, tag->info.nti.nai.abtUid, tag->info.nti.nai.szUidLen, &pnti) >= 0) {
|
||||
if (nfc_initiator_select_passive_target(tag->device, modulation, tag->info.nti.nai.abtUid, tag->info.nti.nai.szUidLen, &pnti) >= 0) {
|
||||
tag->active = 1;
|
||||
|
||||
} else {
|
||||
|
@ -249,9 +249,9 @@ ntag21x_connect(FreefareTag tag)
|
|||
int
|
||||
ntag21x_disconnect(FreefareTag tag)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
ASSERT_ACTIVE(tag);
|
||||
|
||||
if (nfc_initiator_deselect_target (tag->device) >= 0) {
|
||||
if (nfc_initiator_deselect_target(tag->device) >= 0) {
|
||||
tag->active = 0;
|
||||
} else {
|
||||
errno = EIO;
|
||||
|
@ -266,16 +266,16 @@ ntag21x_disconnect(FreefareTag tag)
|
|||
int
|
||||
ntag21x_get_info(FreefareTag tag)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
ASSERT_ACTIVE(tag);
|
||||
|
||||
// Init buffers
|
||||
BUFFER_INIT (cmd, 1);
|
||||
BUFFER_INIT (res,8);
|
||||
BUFFER_INIT(cmd, 1);
|
||||
BUFFER_INIT(res, 8);
|
||||
|
||||
// Append get version command to buffer
|
||||
BUFFER_APPEND (cmd, 0x60);
|
||||
BUFFER_APPEND(cmd, 0x60);
|
||||
|
||||
NTAG_TRANSCEIVE_RAW (tag, cmd, res); // Send & receive to & from tag
|
||||
NTAG_TRANSCEIVE_RAW(tag, cmd, res); // Send & receive to & from tag
|
||||
|
||||
NTAG_21x(tag)->vendor_id = res[1];
|
||||
NTAG_21x(tag)->product_type = res[2];
|
||||
|
@ -286,7 +286,7 @@ ntag21x_get_info(FreefareTag tag)
|
|||
NTAG_21x(tag)->protocol_type = res[7];
|
||||
|
||||
// Set ntag subtype based on storage size
|
||||
switch(NTAG_21x(tag)->storage_size) {
|
||||
switch (NTAG_21x(tag)->storage_size) {
|
||||
case 0x0f:
|
||||
NTAG_21x(tag)->subtype = NTAG_213;
|
||||
break;
|
||||
|
@ -306,8 +306,7 @@ ntag21x_get_info(FreefareTag tag)
|
|||
* Get subtype of tag
|
||||
*/
|
||||
enum ntag_tag_subtype
|
||||
ntag21x_get_subtype(FreefareTag tag)
|
||||
{
|
||||
ntag21x_get_subtype(FreefareTag tag) {
|
||||
return NTAG_21x(tag)->subtype;
|
||||
}
|
||||
|
||||
|
@ -333,21 +332,21 @@ ntag21x_get_last_page(FreefareTag tag)
|
|||
* Read signature
|
||||
*/
|
||||
int
|
||||
ntag21x_read_signature(FreefareTag tag,uint8_t *data)
|
||||
ntag21x_read_signature(FreefareTag tag, uint8_t *data)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
ASSERT_ACTIVE(tag);
|
||||
|
||||
// Init buffers
|
||||
BUFFER_INIT (cmd, 2);
|
||||
BUFFER_INIT (res,32);
|
||||
BUFFER_INIT(cmd, 2);
|
||||
BUFFER_INIT(res, 32);
|
||||
|
||||
// Append get version command to buffer
|
||||
BUFFER_APPEND (cmd, 0x3C);
|
||||
BUFFER_APPEND (cmd, 0x00);
|
||||
BUFFER_APPEND(cmd, 0x3C);
|
||||
BUFFER_APPEND(cmd, 0x00);
|
||||
|
||||
NTAG_TRANSCEIVE_RAW (tag, cmd, res); // Send & receive to & from tag
|
||||
NTAG_TRANSCEIVE_RAW(tag, cmd, res); // Send & receive to & from tag
|
||||
|
||||
memcpy(data,res,32); // Copy response to data output
|
||||
memcpy(data, res, 32); // Copy response to data output
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -365,147 +364,147 @@ int
|
|||
ntag21x_set_pwd(FreefareTag tag, uint8_t data[4]) // Set password
|
||||
{
|
||||
uint8_t page = ntag21x_get_last_page(tag) - 1; // PWD page is located 1 before last page
|
||||
int res = ntag21x_write(tag,page,data);
|
||||
int res = ntag21x_write(tag, page, data);
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
ntag21x_set_pack(FreefareTag tag, uint8_t data[2]) // Set pack
|
||||
{
|
||||
BUFFER_INIT(buff,4);
|
||||
BUFFER_APPEND_BYTES(buff,data,2);
|
||||
BUFFER_APPEND(buff,0x00);
|
||||
BUFFER_APPEND(buff,0x00);
|
||||
BUFFER_INIT(buff, 4);
|
||||
BUFFER_APPEND_BYTES(buff, data, 2);
|
||||
BUFFER_APPEND(buff, 0x00);
|
||||
BUFFER_APPEND(buff, 0x00);
|
||||
uint8_t page = ntag21x_get_last_page(tag); // PACK page is located on last page
|
||||
int res = ntag21x_write(tag,page,buff);
|
||||
int res = ntag21x_write(tag, page, buff);
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
ntag21x_set_key(FreefareTag tag,const NTAG21xKey key) // Set key
|
||||
ntag21x_set_key(FreefareTag tag, const NTAG21xKey key) // Set key
|
||||
{
|
||||
int res;
|
||||
// Set password
|
||||
res = ntag21x_set_pwd(tag,key->data);
|
||||
if(res < 0)
|
||||
res = ntag21x_set_pwd(tag, key->data);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
// Set pack
|
||||
res = ntag21x_set_pack(tag,key->pack);
|
||||
res = ntag21x_set_pack(tag, key->pack);
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
ntag21x_set_auth(FreefareTag tag,uint8_t byte) // Set AUTH0 byte (from which page starts password protection)
|
||||
ntag21x_set_auth(FreefareTag tag, uint8_t byte) // Set AUTH0 byte (from which page starts password protection)
|
||||
{
|
||||
BUFFER_INIT(cdata,4);
|
||||
BUFFER_INIT(cdata, 4);
|
||||
int page = ntag21x_get_last_page(tag) - 3; // AUTH0 byte is on 4th page from back
|
||||
int res;
|
||||
res = ntag21x_read4(tag,page,cdata); // Read current configuration from tag
|
||||
if(res < 0)
|
||||
res = ntag21x_read4(tag, page, cdata); // Read current configuration from tag
|
||||
if (res < 0)
|
||||
return res;
|
||||
cdata[3] = byte; // Set AUTH0 byte in buffer
|
||||
res = ntag21x_write(tag,page,cdata); // Write new configuration to tag
|
||||
res = ntag21x_write(tag, page, cdata); // Write new configuration to tag
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
ntag21x_get_auth(FreefareTag tag,uint8_t *byte) // Get AUTH0 byte
|
||||
ntag21x_get_auth(FreefareTag tag, uint8_t *byte) // Get AUTH0 byte
|
||||
{
|
||||
BUFFER_INIT(cdata,4);
|
||||
BUFFER_INIT(cdata, 4);
|
||||
int page = ntag21x_get_last_page(tag) - 3; // AUTH0 byte is on 4th page from back
|
||||
int res;
|
||||
res = ntag21x_read4(tag,page,cdata); // Read current configuration from tag
|
||||
if(res < 0)
|
||||
res = ntag21x_read4(tag, page, cdata); // Read current configuration from tag
|
||||
if (res < 0)
|
||||
return res;
|
||||
*byte = cdata[3]; // Get AUTH0 byte in buffer
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
ntag21x_access_enable(FreefareTag tag,uint8_t byte) // Enable access feature in ACCESS byte
|
||||
ntag21x_access_enable(FreefareTag tag, uint8_t byte) // Enable access feature in ACCESS byte
|
||||
{
|
||||
BUFFER_INIT(cdata,4);
|
||||
BUFFER_INIT(cdata, 4);
|
||||
int page = ntag21x_get_last_page(tag) - 2; // ACCESS byte is on 3th page from back
|
||||
int res;
|
||||
res = ntag21x_read4(tag,page,cdata); // Read current configuration from tag
|
||||
if(res < 0)
|
||||
res = ntag21x_read4(tag, page, cdata); // Read current configuration from tag
|
||||
if (res < 0)
|
||||
return res;
|
||||
cdata[0] |= byte; // Set bit to 1 in ACCESS byte
|
||||
res = ntag21x_write(tag,page,cdata); // Write new configuration to tag
|
||||
res = ntag21x_write(tag, page, cdata); // Write new configuration to tag
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
ntag21x_access_disable(FreefareTag tag,uint8_t byte) // Disable access feature in ACCESS byte
|
||||
ntag21x_access_disable(FreefareTag tag, uint8_t byte) // Disable access feature in ACCESS byte
|
||||
{
|
||||
BUFFER_INIT(cdata,4);
|
||||
BUFFER_INIT(cdata, 4);
|
||||
int page = ntag21x_get_last_page(tag) - 2; // ACCESS byte is on 3th page from back
|
||||
int res;
|
||||
res = ntag21x_read4(tag,page,cdata); // Read current configuration from tag
|
||||
if(res < 0)
|
||||
res = ntag21x_read4(tag, page, cdata); // Read current configuration from tag
|
||||
if (res < 0)
|
||||
return res;
|
||||
cdata[0] &= ~byte; // Set bit to 0 in ACCESS byte
|
||||
res = ntag21x_write(tag,page,cdata); // Write new configuration to tag
|
||||
res = ntag21x_write(tag, page, cdata); // Write new configuration to tag
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
ntag21x_get_access(FreefareTag tag,uint8_t *byte) // Get ACCESS byte
|
||||
ntag21x_get_access(FreefareTag tag, uint8_t *byte) // Get ACCESS byte
|
||||
{
|
||||
BUFFER_INIT(cdata,4);
|
||||
BUFFER_INIT(cdata, 4);
|
||||
uint8_t page = ntag21x_get_last_page(tag) - 2; // ACCESS byte is on 3th page from back
|
||||
int res;
|
||||
res = ntag21x_read4(tag,page,cdata); // Read current configuration from tag
|
||||
if(res < 0)
|
||||
res = ntag21x_read4(tag, page, cdata); // Read current configuration from tag
|
||||
if (res < 0)
|
||||
return res;
|
||||
memcpy(byte,cdata,1); // Return 1 byte of page
|
||||
memcpy(byte, cdata, 1); // Return 1 byte of page
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
ntag21x_check_access(FreefareTag tag,uint8_t byte,bool *result) // Check if access feature is enabled
|
||||
ntag21x_check_access(FreefareTag tag, uint8_t byte, bool *result) // Check if access feature is enabled
|
||||
{
|
||||
BUFFER_INIT(buff,1);
|
||||
BUFFER_INIT(buff, 1);
|
||||
int res;
|
||||
res = ntag21x_get_access(tag,buff);
|
||||
if(res<0)
|
||||
res = ntag21x_get_access(tag, buff);
|
||||
if (res < 0)
|
||||
return res; // Return error if can't get access byte
|
||||
|
||||
*result = (buff[0]&byte)>0; // Set result, check if bit is 1 in access byte
|
||||
*result = (buff[0] & byte) > 0; // Set result, check if bit is 1 in access byte
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
ntag21x_get_authentication_limit(FreefareTag tag,uint8_t *byte) // Get authentication limit
|
||||
ntag21x_get_authentication_limit(FreefareTag tag, uint8_t *byte) // Get authentication limit
|
||||
{
|
||||
BUFFER_INIT(cdata,4);
|
||||
BUFFER_INIT(cdata, 4);
|
||||
uint8_t page = ntag21x_get_last_page(tag) - 2; // ACCESS byte is on 3th page from back
|
||||
int res;
|
||||
res = ntag21x_read4(tag,page,cdata); // Read current configuration from tag
|
||||
if(res < 0)
|
||||
res = ntag21x_read4(tag, page, cdata); // Read current configuration from tag
|
||||
if (res < 0)
|
||||
return res;
|
||||
cdata[0]&=0x07; // Extract last 3 bits from access byte
|
||||
memcpy(byte,cdata,1); // Return 1 byte of page
|
||||
cdata[0] &= 0x07; // Extract last 3 bits from access byte
|
||||
memcpy(byte, cdata, 1); // Return 1 byte of page
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
ntag21x_set_authentication_limit(FreefareTag tag,uint8_t byte) // Set authentication limit (0x00 = disabled, [0x01,0x07] = valid range, > 0x07 invalid range)
|
||||
ntag21x_set_authentication_limit(FreefareTag tag, uint8_t byte) // Set authentication limit (0x00 = disabled, [0x01,0x07] = valid range, > 0x07 invalid range)
|
||||
{
|
||||
if(byte > 7) // Check for invalid range of auth limit
|
||||
if (byte > 7) // Check for invalid range of auth limit
|
||||
return -1;
|
||||
|
||||
BUFFER_INIT(cdata,4);
|
||||
BUFFER_INIT(cdata, 4);
|
||||
int page = ntag21x_get_last_page(tag) - 2; // ACCESS byte is on 3th page from back
|
||||
int res;
|
||||
res = ntag21x_read4(tag,page,cdata); // Read current configuration from tag
|
||||
if(res < 0)
|
||||
res = ntag21x_read4(tag, page, cdata); // Read current configuration from tag
|
||||
if (res < 0)
|
||||
return res;
|
||||
cdata[0] &= 0xf8; // Reset auth limit bits
|
||||
cdata[0] |= byte; // Set aut limit
|
||||
res = ntag21x_write(tag,page,cdata); // Write new configuration to tag
|
||||
res = ntag21x_write(tag, page, cdata); // Write new configuration to tag
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -513,21 +512,21 @@ ntag21x_set_authentication_limit(FreefareTag tag,uint8_t byte) // Set authentica
|
|||
* Read 16 bytes from NTAG.
|
||||
*/
|
||||
int
|
||||
ntag21x_read(FreefareTag tag, uint8_t page,uint8_t *data)
|
||||
ntag21x_read(FreefareTag tag, uint8_t page, uint8_t *data)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
NTAG_ASSERT_VALID_PAGE (tag, page, false);
|
||||
ASSERT_ACTIVE(tag);
|
||||
NTAG_ASSERT_VALID_PAGE(tag, page, false);
|
||||
|
||||
// Init buffers
|
||||
BUFFER_INIT (cmd, 2);
|
||||
BUFFER_INIT (res,16);
|
||||
BUFFER_INIT(cmd, 2);
|
||||
BUFFER_INIT(res, 16);
|
||||
|
||||
// Append read 16B command to buffer
|
||||
BUFFER_APPEND (cmd, 0x30);
|
||||
BUFFER_APPEND (cmd, page);
|
||||
BUFFER_APPEND(cmd, 0x30);
|
||||
BUFFER_APPEND(cmd, page);
|
||||
|
||||
NTAG_TRANSCEIVE (tag, cmd, res); // Send & receive to & from tag
|
||||
memcpy (data, res, 16); // Copy first 4 bytes (selected page) to data output
|
||||
NTAG_TRANSCEIVE(tag, cmd, res); // Send & receive to & from tag
|
||||
memcpy(data, res, 16); // Copy first 4 bytes (selected page) to data output
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -535,11 +534,11 @@ ntag21x_read(FreefareTag tag, uint8_t page,uint8_t *data)
|
|||
* Read 4 bytes from NTAG
|
||||
*/
|
||||
int
|
||||
ntag21x_read4(FreefareTag tag,uint8_t page,uint8_t *data)
|
||||
ntag21x_read4(FreefareTag tag, uint8_t page, uint8_t *data)
|
||||
{
|
||||
BUFFER_INIT (res,16);
|
||||
int re = ntag21x_read(tag,page,res);
|
||||
memcpy(data,res,4);
|
||||
BUFFER_INIT(res, 16);
|
||||
int re = ntag21x_read(tag, page, res);
|
||||
memcpy(data, res, 4);
|
||||
return re;
|
||||
}
|
||||
|
||||
|
@ -547,33 +546,33 @@ ntag21x_read4(FreefareTag tag,uint8_t page,uint8_t *data)
|
|||
* Read pages from [start,end] from NTAG
|
||||
*/
|
||||
int
|
||||
ntag21x_fast_read(FreefareTag tag, uint8_t start_page,uint8_t end_page, uint8_t *data)
|
||||
ntag21x_fast_read(FreefareTag tag, uint8_t start_page, uint8_t end_page, uint8_t *data)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
NTAG_ASSERT_VALID_PAGE (tag, start_page, false);
|
||||
NTAG_ASSERT_VALID_PAGE (tag, end_page, false);
|
||||
ASSERT_ACTIVE(tag);
|
||||
NTAG_ASSERT_VALID_PAGE(tag, start_page, false);
|
||||
NTAG_ASSERT_VALID_PAGE(tag, end_page, false);
|
||||
|
||||
// Init buffers
|
||||
BUFFER_INIT (cmd, 3);
|
||||
BUFFER_INIT (res,4*(end_page - start_page + 1));
|
||||
BUFFER_INIT(cmd, 3);
|
||||
BUFFER_INIT(res, 4 * (end_page - start_page + 1));
|
||||
|
||||
// Append read 16B command to buffer
|
||||
BUFFER_APPEND (cmd, 0x3A);
|
||||
BUFFER_APPEND (cmd, start_page);
|
||||
BUFFER_APPEND (cmd, end_page);
|
||||
BUFFER_APPEND(cmd, 0x3A);
|
||||
BUFFER_APPEND(cmd, start_page);
|
||||
BUFFER_APPEND(cmd, end_page);
|
||||
|
||||
NTAG_TRANSCEIVE_RAW (tag, cmd, res); // Send & receive to & from tag
|
||||
NTAG_TRANSCEIVE_RAW(tag, cmd, res); // Send & receive to & from tag
|
||||
|
||||
memcpy (data, res, 4*(end_page - start_page + 1)); // Copy first 4 bytes (selected page) to data output
|
||||
memcpy(data, res, 4 * (end_page - start_page + 1)); // Copy first 4 bytes (selected page) to data output
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ntag21x_fast_read4(FreefareTag tag,uint8_t page,uint8_t *data)
|
||||
ntag21x_fast_read4(FreefareTag tag, uint8_t page, uint8_t *data)
|
||||
{
|
||||
BUFFER_INIT (res,4);
|
||||
int re = ntag21x_fast_read(tag,page,page,res);
|
||||
memcpy(data,res,4);
|
||||
BUFFER_INIT(res, 4);
|
||||
int re = ntag21x_fast_read(tag, page, page, res);
|
||||
memcpy(data, res, 4);
|
||||
return re;
|
||||
}
|
||||
|
||||
|
@ -583,19 +582,19 @@ ntag21x_fast_read4(FreefareTag tag,uint8_t page,uint8_t *data)
|
|||
int
|
||||
ntag21x_read_cnt(FreefareTag tag, uint8_t *data)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
ASSERT_ACTIVE(tag);
|
||||
|
||||
// Init buffers
|
||||
BUFFER_INIT (cmd, 2);
|
||||
BUFFER_INIT (res,3);
|
||||
BUFFER_INIT(cmd, 2);
|
||||
BUFFER_INIT(res, 3);
|
||||
|
||||
// Append read cnt command to buffer
|
||||
BUFFER_APPEND (cmd, 0x39);
|
||||
BUFFER_APPEND (cmd, 0x02);
|
||||
BUFFER_APPEND(cmd, 0x39);
|
||||
BUFFER_APPEND(cmd, 0x02);
|
||||
|
||||
NTAG_TRANSCEIVE_RAW (tag, cmd, res); // Send & receive to & from tag
|
||||
NTAG_TRANSCEIVE_RAW(tag, cmd, res); // Send & receive to & from tag
|
||||
|
||||
memcpy (data, res, 3); // Copy first 3 bytes (selected page) to data output
|
||||
memcpy(data, res, 3); // Copy first 3 bytes (selected page) to data output
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -605,19 +604,19 @@ ntag21x_read_cnt(FreefareTag tag, uint8_t *data)
|
|||
int
|
||||
ntag21x_write(FreefareTag tag, uint8_t page, uint8_t data[4])
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
NTAG_ASSERT_VALID_PAGE (tag, page, true);
|
||||
ASSERT_ACTIVE(tag);
|
||||
NTAG_ASSERT_VALID_PAGE(tag, page, true);
|
||||
|
||||
// Init buffera
|
||||
BUFFER_INIT (cmd, 6);
|
||||
BUFFER_INIT (res, 1);
|
||||
BUFFER_INIT(cmd, 6);
|
||||
BUFFER_INIT(res, 1);
|
||||
|
||||
// Append write 4B command to buffer
|
||||
BUFFER_APPEND (cmd, 0xA2);
|
||||
BUFFER_APPEND (cmd, page);
|
||||
BUFFER_APPEND_BYTES (cmd, data, 4); // Copy data to last 4 bytes of buffer
|
||||
BUFFER_APPEND(cmd, 0xA2);
|
||||
BUFFER_APPEND(cmd, page);
|
||||
BUFFER_APPEND_BYTES(cmd, data, 4); // Copy data to last 4 bytes of buffer
|
||||
|
||||
NTAG_TRANSCEIVE (tag, cmd, res);
|
||||
NTAG_TRANSCEIVE(tag, cmd, res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -625,22 +624,22 @@ ntag21x_write(FreefareTag tag, uint8_t page, uint8_t data[4])
|
|||
int
|
||||
ntag21x_compatibility_write(FreefareTag tag, uint8_t page, uint8_t data[4])
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
NTAG_ASSERT_VALID_PAGE (tag, page, true);
|
||||
ASSERT_ACTIVE(tag);
|
||||
NTAG_ASSERT_VALID_PAGE(tag, page, true);
|
||||
|
||||
// Init buffera
|
||||
BUFFER_INIT (cmd, 18);
|
||||
BUFFER_INIT (res, 1);
|
||||
BUFFER_INIT(cmd, 18);
|
||||
BUFFER_INIT(res, 1);
|
||||
|
||||
// Append write 4B command to buffer
|
||||
BUFFER_APPEND (cmd, 0xA0);
|
||||
BUFFER_APPEND (cmd, page);
|
||||
BUFFER_APPEND_BYTES (cmd, data, 4); // Copy data to last 4 bytes of buffer
|
||||
for (int i=0;i<12;i++) {
|
||||
BUFFER_APPEND(cmd,0x00);
|
||||
BUFFER_APPEND(cmd, 0xA0);
|
||||
BUFFER_APPEND(cmd, page);
|
||||
BUFFER_APPEND_BYTES(cmd, data, 4); // Copy data to last 4 bytes of buffer
|
||||
for (int i = 0; i < 12; i++) {
|
||||
BUFFER_APPEND(cmd, 0x00);
|
||||
}
|
||||
|
||||
NTAG_TRANSCEIVE (tag, cmd, res);
|
||||
NTAG_TRANSCEIVE(tag, cmd, res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -650,22 +649,22 @@ ntag21x_compatibility_write(FreefareTag tag, uint8_t page, uint8_t data[4])
|
|||
int
|
||||
ntag21x_authenticate(FreefareTag tag, const NTAG21xKey key)
|
||||
{
|
||||
ASSERT_ACTIVE (tag);
|
||||
BUFFER_INIT (cmd1, 5);
|
||||
BUFFER_INIT (res, 2);
|
||||
BUFFER_APPEND (cmd1, 0x1B);
|
||||
BUFFER_APPEND_BYTES (cmd1, key->data,4); // Append key to command
|
||||
ASSERT_ACTIVE(tag);
|
||||
BUFFER_INIT(cmd1, 5);
|
||||
BUFFER_INIT(res, 2);
|
||||
BUFFER_APPEND(cmd1, 0x1B);
|
||||
BUFFER_APPEND_BYTES(cmd1, key->data, 4); // Append key to command
|
||||
NTAG_TRANSCEIVE_RAW(tag, cmd1, res);
|
||||
|
||||
//Check if authenticated (PACK must be as expected)
|
||||
bool flag_auth = true;
|
||||
for(int i=0;i<2;i++)
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (res[i] != key->pack[i]) {
|
||||
flag_auth = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flag_auth)
|
||||
if (!flag_auth)
|
||||
return -1;
|
||||
// XXX Should we store the state "authenticated" in the tag struct??
|
||||
return 0;
|
||||
|
@ -696,7 +695,7 @@ ntag21x_is_auth_supported(nfc_device *device, nfc_iso14443a_info nai)
|
|||
};
|
||||
nfc_initiator_select_passive_target(device, modulation, nai.abtUid, nai.szUidLen, &pnti);
|
||||
nfc_device_set_property_bool(device, NP_EASY_FRAMING, false);
|
||||
ret = nfc_initiator_transceive_bytes(device, cmd_step1, sizeof (cmd_step1), res_step1, sizeof(res_step1), 0);
|
||||
ret = nfc_initiator_transceive_bytes(device, cmd_step1, sizeof(cmd_step1), res_step1, sizeof(res_step1), 0);
|
||||
nfc_device_set_property_bool(device, NP_EASY_FRAMING, true);
|
||||
nfc_initiator_deselect_target(device);
|
||||
return ret >= 0;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere, Romuald Conty.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -57,9 +57,9 @@
|
|||
|
||||
#define TLV_TERMINATOR 0xFE
|
||||
|
||||
size_t tlv_record_length (const uint8_t *stream, size_t *field_length_size, size_t *field_value_size);
|
||||
uint8_t *tlv_next (uint8_t *stream);
|
||||
size_t tlv_sequence_length (uint8_t *stream);
|
||||
size_t tlv_record_length(const uint8_t *stream, size_t *field_length_size, size_t *field_value_size);
|
||||
uint8_t *tlv_next(uint8_t *stream);
|
||||
size_t tlv_sequence_length(uint8_t *stream);
|
||||
|
||||
/*
|
||||
* TLV (Type Length Value) Manipulation Functions.
|
||||
|
@ -69,7 +69,7 @@ size_t tlv_sequence_length (uint8_t *stream);
|
|||
* Encode data stream into TLV.
|
||||
*/
|
||||
uint8_t *
|
||||
tlv_encode (const uint8_t type, const uint8_t *istream, uint16_t isize, size_t *osize)
|
||||
tlv_encode(const uint8_t type, const uint8_t *istream, uint16_t isize, size_t *osize)
|
||||
{
|
||||
uint8_t *res;
|
||||
off_t n = 0;
|
||||
|
@ -80,20 +80,20 @@ tlv_encode (const uint8_t type, const uint8_t *istream, uint16_t isize, size_t *
|
|||
if (isize == 0xffff) /* RFU */
|
||||
return NULL;
|
||||
|
||||
if ((res = malloc (1 + ((isize > 254) ? 3 : 1) + isize + 1))) {
|
||||
if ((res = malloc(1 + ((isize > 254) ? 3 : 1) + isize + 1))) {
|
||||
/* type + size + payload + terminator */
|
||||
res[n++] = type;
|
||||
|
||||
if (isize > 254) {
|
||||
res[n++] = 0xff;
|
||||
uint16_t size_be = htobe16 (isize);
|
||||
memcpy (res + n, &size_be, sizeof (uint16_t));
|
||||
uint16_t size_be = htobe16(isize);
|
||||
memcpy(res + n, &size_be, sizeof(uint16_t));
|
||||
n += 2;
|
||||
} else {
|
||||
res[n++] = (uint8_t)isize;
|
||||
}
|
||||
|
||||
memcpy (res + n, istream, isize);
|
||||
memcpy(res + n, istream, isize);
|
||||
|
||||
n += isize;
|
||||
res[n++] = TLV_TERMINATOR;
|
||||
|
@ -108,7 +108,7 @@ tlv_encode (const uint8_t type, const uint8_t *istream, uint16_t isize, size_t *
|
|||
* Decode TLV from data stream.
|
||||
*/
|
||||
uint8_t *
|
||||
tlv_decode (const uint8_t *istream, uint8_t *type, uint16_t *size)
|
||||
tlv_decode(const uint8_t *istream, uint8_t *type, uint16_t *size)
|
||||
{
|
||||
size_t fls = 0;
|
||||
size_t fvs = 0;
|
||||
|
@ -117,14 +117,14 @@ tlv_decode (const uint8_t *istream, uint8_t *type, uint16_t *size)
|
|||
if (type)
|
||||
*type = istream[0];
|
||||
|
||||
tlv_record_length (istream, &fls, &fvs);
|
||||
tlv_record_length(istream, &fls, &fvs);
|
||||
|
||||
if (size) {
|
||||
*size = fvs;
|
||||
}
|
||||
|
||||
if ((res = malloc (fvs))) {
|
||||
memcpy (res, istream + 1 + fls, fvs);
|
||||
if ((res = malloc(fvs))) {
|
||||
memcpy(res, istream + 1 + fls, fvs);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ tlv_decode (const uint8_t *istream, uint8_t *type, uint16_t *size)
|
|||
* Length of a TLV field
|
||||
*/
|
||||
size_t
|
||||
tlv_record_length (const uint8_t *stream, size_t *field_length_size, size_t *field_value_size)
|
||||
tlv_record_length(const uint8_t *stream, size_t *field_length_size, size_t *field_value_size)
|
||||
{
|
||||
size_t fls = 0;
|
||||
size_t fvs = 0;
|
||||
|
@ -148,7 +148,7 @@ tlv_record_length (const uint8_t *stream, size_t *field_length_size, size_t *fie
|
|||
default: // FIXME Not supported.
|
||||
if (stream[1] == 0xff) {
|
||||
uint16_t be_size;
|
||||
memcpy (&be_size, stream + 2, sizeof (uint16_t));
|
||||
memcpy(&be_size, stream + 2, sizeof(uint16_t));
|
||||
fls = 3;
|
||||
fvs = be16toh(be_size);
|
||||
} else {
|
||||
|
@ -176,11 +176,11 @@ tlv_record_length (const uint8_t *stream, size_t *field_length_size, size_t *fie
|
|||
* Fourth call NULL
|
||||
*/
|
||||
uint8_t *
|
||||
tlv_next (uint8_t *stream)
|
||||
tlv_next(uint8_t *stream)
|
||||
{
|
||||
uint8_t *res = NULL;
|
||||
if (stream[0] != TLV_TERMINATOR)
|
||||
res = stream + tlv_record_length (stream, NULL, NULL);
|
||||
res = stream + tlv_record_length(stream, NULL, NULL);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -189,13 +189,13 @@ tlv_next (uint8_t *stream)
|
|||
* Full-length of all TLV fields.
|
||||
*/
|
||||
size_t
|
||||
tlv_sequence_length (uint8_t *stream)
|
||||
tlv_sequence_length(uint8_t *stream)
|
||||
{
|
||||
size_t res = 0;
|
||||
|
||||
do {
|
||||
res += tlv_record_length (stream, NULL, NULL);
|
||||
} while ((stream = tlv_next (stream)));
|
||||
res += tlv_record_length(stream, NULL, NULL);
|
||||
} while ((stream = tlv_next(stream)));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -205,14 +205,14 @@ tlv_sequence_length (uint8_t *stream)
|
|||
* Append two TLV. Acts like realloc(3).
|
||||
*/
|
||||
uint8_t *
|
||||
tlv_append (uint8_t *a, uint8_t *b)
|
||||
tlv_append(uint8_t *a, uint8_t *b)
|
||||
{
|
||||
size_t a_size = tlv_sequence_length (a);
|
||||
size_t b_size = tlv_sequence_length (b);
|
||||
size_t a_size = tlv_sequence_length(a);
|
||||
size_t b_size = tlv_sequence_length(b);
|
||||
size_t new_size = a_size + b_size - 1;
|
||||
|
||||
if ((a = realloc (a, new_size))) {
|
||||
memcpy (a + a_size - 1, b, b_size);
|
||||
if ((a = realloc(a, new_size))) {
|
||||
memcpy(a + a_size - 1, b, b_size);
|
||||
}
|
||||
|
||||
return a;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -26,57 +26,58 @@ uint8_t key_data_des[8] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' };
|
|||
uint8_t key_data_3des[16] = { 'C', 'a', 'r', 'd', ' ', 'M', 'a', 's', 't', 'e', 'r', ' ', 'K', 'e', 'y', '!' };
|
||||
uint8_t key_data_aes[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t key_data_3k3des[24] = { 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const uint8_t key_data_aes_version = 0x42;
|
||||
|
||||
void
|
||||
mifare_desfire_auto_authenticate (FreefareTag tag, uint8_t key_no)
|
||||
mifare_desfire_auto_authenticate(FreefareTag tag, uint8_t key_no)
|
||||
{
|
||||
/* Determine which key is currently the master one */
|
||||
uint8_t key_version;
|
||||
int res = mifare_desfire_get_key_version (tag, key_no, &key_version);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_desfire_get_key_version()"));
|
||||
int res = mifare_desfire_get_key_version(tag, key_no, &key_version);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_desfire_get_key_version()"));
|
||||
|
||||
MifareDESFireKey key;
|
||||
|
||||
switch (key_version) {
|
||||
case 0x00:
|
||||
key = mifare_desfire_des_key_new_with_version (key_data_null);
|
||||
key = mifare_desfire_des_key_new_with_version(key_data_null);
|
||||
break;
|
||||
case 0x42:
|
||||
key = mifare_desfire_aes_key_new_with_version (key_data_aes, key_data_aes_version);
|
||||
key = mifare_desfire_aes_key_new_with_version(key_data_aes, key_data_aes_version);
|
||||
break;
|
||||
case 0xAA:
|
||||
key = mifare_desfire_des_key_new_with_version (key_data_des);
|
||||
key = mifare_desfire_des_key_new_with_version(key_data_des);
|
||||
break;
|
||||
case 0xC7:
|
||||
key = mifare_desfire_3des_key_new_with_version (key_data_3des);
|
||||
key = mifare_desfire_3des_key_new_with_version(key_data_3des);
|
||||
break;
|
||||
case 0x55:
|
||||
key = mifare_desfire_3k3des_key_new_with_version (key_data_3k3des);
|
||||
key = mifare_desfire_3k3des_key_new_with_version(key_data_3k3des);
|
||||
break;
|
||||
default:
|
||||
cut_fail ("Unknown master key.");
|
||||
cut_fail("Unknown master key.");
|
||||
}
|
||||
|
||||
cut_assert_not_null (key, cut_message ("Cannot allocate key"));
|
||||
cut_assert_not_null(key, cut_message("Cannot allocate key"));
|
||||
|
||||
/* Authenticate with this key */
|
||||
switch (key_version) {
|
||||
case 0x00:
|
||||
case 0xAA:
|
||||
case 0xC7:
|
||||
res = mifare_desfire_authenticate (tag, key_no, key);
|
||||
res = mifare_desfire_authenticate(tag, key_no, key);
|
||||
break;
|
||||
case 0x55:
|
||||
res = mifare_desfire_authenticate_iso (tag, key_no, key);
|
||||
res = mifare_desfire_authenticate_iso(tag, key_no, key);
|
||||
break;
|
||||
case 0x42:
|
||||
res = mifare_desfire_authenticate_aes (tag, key_no, key);
|
||||
res = mifare_desfire_authenticate_aes(tag, key_no, key);
|
||||
break;
|
||||
}
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_desfire_authenticate()"));
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_desfire_authenticate()"));
|
||||
|
||||
mifare_desfire_key_free (key);
|
||||
mifare_desfire_key_free(key);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -25,6 +25,6 @@ extern uint8_t key_data_aes[16];
|
|||
extern uint8_t key_data_3k3des[24];
|
||||
extern const uint8_t key_data_aes_version;
|
||||
|
||||
void mifare_desfire_auto_authenticate (FreefareTag tag, uint8_t key_no);
|
||||
void mifare_desfire_auto_authenticate(FreefareTag tag, uint8_t key_no);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2015, Romain Tartiere
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -26,52 +26,52 @@ static FreefareTag *tags = NULL;
|
|||
FreefareTag tag = NULL;
|
||||
|
||||
void
|
||||
cut_setup (void)
|
||||
cut_setup(void)
|
||||
{
|
||||
int res;
|
||||
nfc_connstring devices[8];
|
||||
size_t device_count;
|
||||
|
||||
nfc_init (&context);
|
||||
cut_assert_not_null (context, cut_message ("Unable to init libnfc (malloc)"));
|
||||
nfc_init(&context);
|
||||
cut_assert_not_null(context, cut_message("Unable to init libnfc (malloc)"));
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
cut_omit ("No device found");
|
||||
cut_omit("No device found");
|
||||
|
||||
for (size_t i = 0; i < device_count; i++) {
|
||||
device = nfc_open (context, devices[i]);
|
||||
if (!device)
|
||||
cut_omit ("nfc_open() failed.");
|
||||
device = nfc_open(context, devices[i]);
|
||||
if (!device)
|
||||
cut_omit("nfc_open() failed.");
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
cut_assert_not_null (tags, cut_message ("freefare_get_tags() failed"));
|
||||
tags = freefare_get_tags(device);
|
||||
cut_assert_not_null(tags, cut_message("freefare_get_tags() failed"));
|
||||
|
||||
tag = NULL;
|
||||
for (int i=0; tags[i]; i++) {
|
||||
if (freefare_get_tag_type(tags[i]) == FELICA) {
|
||||
tag = tags[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
nfc_close (device);
|
||||
device = NULL;
|
||||
freefare_free_tags (tags);
|
||||
tags = NULL;
|
||||
tag = NULL;
|
||||
for (int i = 0; tags[i]; i++) {
|
||||
if (freefare_get_tag_type(tags[i]) == FELICA) {
|
||||
tag = tags[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
nfc_close(device);
|
||||
device = NULL;
|
||||
freefare_free_tags(tags);
|
||||
tags = NULL;
|
||||
}
|
||||
cut_omit ("No FeliCa tag on NFC device");
|
||||
cut_omit("No FeliCa tag on NFC device");
|
||||
}
|
||||
|
||||
void
|
||||
cut_teardown (void)
|
||||
cut_teardown(void)
|
||||
{
|
||||
if (tags) {
|
||||
freefare_free_tags (tags);
|
||||
tags = NULL;
|
||||
freefare_free_tags(tags);
|
||||
tags = NULL;
|
||||
}
|
||||
|
||||
if (device)
|
||||
nfc_close (device);
|
||||
nfc_close(device);
|
||||
|
||||
nfc_exit (context);
|
||||
nfc_exit(context);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2015, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere
|
||||
* Copyright (C) 2013, Romuald Conty
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -27,59 +27,59 @@ static FreefareTag *tags = NULL;
|
|||
FreefareTag tag = NULL;
|
||||
|
||||
void
|
||||
cut_setup (void)
|
||||
cut_setup(void)
|
||||
{
|
||||
int res;
|
||||
nfc_connstring devices[8];
|
||||
size_t device_count;
|
||||
|
||||
nfc_init (&context);
|
||||
cut_assert_not_null (context, cut_message ("Unable to init libnfc (malloc)"));
|
||||
nfc_init(&context);
|
||||
cut_assert_not_null(context, cut_message("Unable to init libnfc (malloc)"));
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
cut_omit ("No device found");
|
||||
cut_omit("No device found");
|
||||
|
||||
for (size_t i = 0; i < device_count; i++) {
|
||||
device = nfc_open (context, devices[i]);
|
||||
if (!device)
|
||||
cut_omit ("nfc_open() failed.");
|
||||
device = nfc_open(context, devices[i]);
|
||||
if (!device)
|
||||
cut_omit("nfc_open() failed.");
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
cut_assert_not_null (tags, cut_message ("freefare_get_tags() failed"));
|
||||
tags = freefare_get_tags(device);
|
||||
cut_assert_not_null(tags, cut_message("freefare_get_tags() failed"));
|
||||
|
||||
tag = NULL;
|
||||
for (int i=0; tags[i]; i++) {
|
||||
if ((freefare_get_tag_type(tags[i]) == MIFARE_CLASSIC_1K) ||
|
||||
(freefare_get_tag_type(tags[i]) == MIFARE_CLASSIC_4K)) {
|
||||
tag = tags[i];
|
||||
res = mifare_classic_connect (tag);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_connect() failed"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
nfc_close (device);
|
||||
device = NULL;
|
||||
freefare_free_tags (tags);
|
||||
tags = NULL;
|
||||
tag = NULL;
|
||||
for (int i = 0; tags[i]; i++) {
|
||||
if ((freefare_get_tag_type(tags[i]) == MIFARE_CLASSIC_1K) ||
|
||||
(freefare_get_tag_type(tags[i]) == MIFARE_CLASSIC_4K)) {
|
||||
tag = tags[i];
|
||||
res = mifare_classic_connect(tag);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_connect() failed"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
nfc_close(device);
|
||||
device = NULL;
|
||||
freefare_free_tags(tags);
|
||||
tags = NULL;
|
||||
}
|
||||
cut_omit ("No MIFARE Classic tag on NFC device");
|
||||
cut_omit("No MIFARE Classic tag on NFC device");
|
||||
}
|
||||
|
||||
void
|
||||
cut_teardown (void)
|
||||
cut_teardown(void)
|
||||
{
|
||||
if (tag)
|
||||
mifare_classic_disconnect (tag);
|
||||
mifare_classic_disconnect(tag);
|
||||
|
||||
if (tags) {
|
||||
freefare_free_tags (tags);
|
||||
tags = NULL;
|
||||
freefare_free_tags(tags);
|
||||
tags = NULL;
|
||||
}
|
||||
|
||||
if (device)
|
||||
nfc_close (device);
|
||||
nfc_close(device);
|
||||
|
||||
nfc_exit (context);
|
||||
nfc_exit(context);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere, Romuald Conty.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere
|
||||
* Copyright (C) 2013, Romuald Conty
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -27,73 +27,73 @@ static FreefareTag *tags = NULL;
|
|||
FreefareTag tag = NULL;
|
||||
|
||||
void
|
||||
cut_setup (void)
|
||||
cut_setup(void)
|
||||
{
|
||||
int res;
|
||||
nfc_connstring devices[8];
|
||||
size_t device_count;
|
||||
|
||||
nfc_init (&context);
|
||||
cut_assert_not_null (context, cut_message ("Unable to init libnfc (malloc)"));
|
||||
nfc_init(&context);
|
||||
cut_assert_not_null(context, cut_message("Unable to init libnfc (malloc)"));
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
cut_omit ("No device found");
|
||||
cut_omit("No device found");
|
||||
|
||||
for (size_t i = 0; i < device_count; i++) {
|
||||
|
||||
device = nfc_open (context, devices[i]);
|
||||
if (!device)
|
||||
cut_omit ("nfc_open() failed.");
|
||||
device = nfc_open(context, devices[i]);
|
||||
if (!device)
|
||||
cut_omit("nfc_open() failed.");
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
cut_assert_not_null (tags, cut_message ("freefare_get_tags() failed"));
|
||||
tags = freefare_get_tags(device);
|
||||
cut_assert_not_null(tags, cut_message("freefare_get_tags() failed"));
|
||||
|
||||
tag = NULL;
|
||||
for (int i=0; tags[i]; i++) {
|
||||
if (freefare_get_tag_type(tags[i]) == MIFARE_DESFIRE) {
|
||||
tag = tags[i];
|
||||
res = mifare_desfire_connect (tag);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_desfire_connect() failed"));
|
||||
tag = NULL;
|
||||
for (int i = 0; tags[i]; i++) {
|
||||
if (freefare_get_tag_type(tags[i]) == MIFARE_DESFIRE) {
|
||||
tag = tags[i];
|
||||
res = mifare_desfire_connect(tag);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_desfire_connect() failed"));
|
||||
|
||||
struct mifare_desfire_version_info version_info;
|
||||
res = mifare_desfire_get_version (tag, &version_info);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_desfire_get_version"));
|
||||
struct mifare_desfire_version_info version_info;
|
||||
res = mifare_desfire_get_version(tag, &version_info);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_desfire_get_version"));
|
||||
|
||||
if (version_info.hardware.storage_size < 0x18) {
|
||||
cut_omit ("DESFire EV1 tests require at least a 4K card");
|
||||
}
|
||||
if (version_info.hardware.storage_size < 0x18) {
|
||||
cut_omit("DESFire EV1 tests require at least a 4K card");
|
||||
}
|
||||
|
||||
if ((version_info.hardware.version_major >= 1) &&
|
||||
(version_info.software.version_major >= 1)) {
|
||||
return;
|
||||
}
|
||||
if ((version_info.hardware.version_major >= 1) &&
|
||||
(version_info.software.version_major >= 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mifare_desfire_disconnect (tag);
|
||||
}
|
||||
}
|
||||
nfc_close (device);
|
||||
device = NULL;
|
||||
freefare_free_tags (tags);
|
||||
tags = NULL;
|
||||
mifare_desfire_disconnect(tag);
|
||||
}
|
||||
}
|
||||
nfc_close(device);
|
||||
device = NULL;
|
||||
freefare_free_tags(tags);
|
||||
tags = NULL;
|
||||
}
|
||||
cut_omit ("No MIFARE DESFire EV1 tag on NFC device");
|
||||
cut_omit("No MIFARE DESFire EV1 tag on NFC device");
|
||||
}
|
||||
|
||||
void
|
||||
cut_teardown (void)
|
||||
cut_teardown(void)
|
||||
{
|
||||
if (tag)
|
||||
mifare_desfire_disconnect (tag);
|
||||
mifare_desfire_disconnect(tag);
|
||||
|
||||
if (tags) {
|
||||
freefare_free_tags (tags);
|
||||
tags = NULL;
|
||||
freefare_free_tags(tags);
|
||||
tags = NULL;
|
||||
}
|
||||
|
||||
if (device)
|
||||
nfc_close (device);
|
||||
nfc_close(device);
|
||||
|
||||
nfc_exit (context);
|
||||
nfc_exit(context);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere
|
||||
* Copyright (C) 2013, Romuald Conty
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -27,68 +27,68 @@ static FreefareTag *tags = NULL;
|
|||
FreefareTag tag = NULL;
|
||||
|
||||
void
|
||||
cut_setup (void)
|
||||
cut_setup(void)
|
||||
{
|
||||
int res;
|
||||
nfc_connstring devices[8];
|
||||
size_t device_count;
|
||||
int res;
|
||||
nfc_connstring devices[8];
|
||||
size_t device_count;
|
||||
|
||||
nfc_init (&context);
|
||||
cut_assert_not_null (context, cut_message ("Unable to init libnfc (malloc)"));
|
||||
nfc_init(&context);
|
||||
cut_assert_not_null(context, cut_message("Unable to init libnfc (malloc)"));
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
cut_omit ("No device found");
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
cut_omit("No device found");
|
||||
|
||||
for (size_t i = 0; i < device_count; i++) {
|
||||
for (size_t i = 0; i < device_count; i++) {
|
||||
|
||||
device = nfc_open (context, devices[i]);
|
||||
if (!device)
|
||||
cut_omit ("nfc_open() failed.");
|
||||
device = nfc_open(context, devices[i]);
|
||||
if (!device)
|
||||
cut_omit("nfc_open() failed.");
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
cut_assert_not_null (tags, cut_message ("freefare_get_tags() failed"));
|
||||
tags = freefare_get_tags(device);
|
||||
cut_assert_not_null(tags, cut_message("freefare_get_tags() failed"));
|
||||
|
||||
tag = NULL;
|
||||
for (int i=0; tags[i]; i++) {
|
||||
if (freefare_get_tag_type(tags[i]) == MIFARE_DESFIRE) {
|
||||
tag = tags[i];
|
||||
res = mifare_desfire_connect (tag);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_desfire_connect() failed"));
|
||||
tag = NULL;
|
||||
for (int i = 0; tags[i]; i++) {
|
||||
if (freefare_get_tag_type(tags[i]) == MIFARE_DESFIRE) {
|
||||
tag = tags[i];
|
||||
res = mifare_desfire_connect(tag);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_desfire_connect() failed"));
|
||||
|
||||
struct mifare_desfire_version_info version_info;
|
||||
res = mifare_desfire_get_version (tag, &version_info);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_desfire_get_version"));
|
||||
struct mifare_desfire_version_info version_info;
|
||||
res = mifare_desfire_get_version(tag, &version_info);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_desfire_get_version"));
|
||||
|
||||
if (version_info.hardware.storage_size < 0x18) {
|
||||
cut_omit ("DESFire tests require at least a 4K card");
|
||||
}
|
||||
if (version_info.hardware.storage_size < 0x18) {
|
||||
cut_omit("DESFire tests require at least a 4K card");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
nfc_close(device);
|
||||
device = NULL;
|
||||
freefare_free_tags(tags);
|
||||
tags = NULL;
|
||||
}
|
||||
nfc_close (device);
|
||||
device = NULL;
|
||||
freefare_free_tags (tags);
|
||||
tags = NULL;
|
||||
}
|
||||
cut_omit ("No MIFARE DESFire tag on NFC device");
|
||||
cut_omit("No MIFARE DESFire tag on NFC device");
|
||||
}
|
||||
|
||||
void
|
||||
cut_teardown (void)
|
||||
cut_teardown(void)
|
||||
{
|
||||
if (tag)
|
||||
mifare_desfire_disconnect (tag);
|
||||
if (tag)
|
||||
mifare_desfire_disconnect(tag);
|
||||
|
||||
if (tags) {
|
||||
freefare_free_tags (tags);
|
||||
tags = NULL;
|
||||
}
|
||||
if (tags) {
|
||||
freefare_free_tags(tags);
|
||||
tags = NULL;
|
||||
}
|
||||
|
||||
if (device)
|
||||
nfc_close (device);
|
||||
if (device)
|
||||
nfc_close(device);
|
||||
|
||||
nfc_exit (context);
|
||||
nfc_exit(context);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere
|
||||
* Copyright (C) 2013, Romuald Conty
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -27,61 +27,61 @@ static FreefareTag *tags = NULL;
|
|||
FreefareTag tag = NULL;
|
||||
|
||||
void
|
||||
cut_setup (void)
|
||||
cut_setup(void)
|
||||
{
|
||||
int res;
|
||||
nfc_connstring devices[8];
|
||||
size_t device_count;
|
||||
|
||||
nfc_init (&context);
|
||||
cut_assert_not_null (context, cut_message ("Unable to init libnfc (malloc)"));
|
||||
nfc_init(&context);
|
||||
cut_assert_not_null(context, cut_message("Unable to init libnfc (malloc)"));
|
||||
|
||||
device_count = nfc_list_devices (context, devices, 8);
|
||||
device_count = nfc_list_devices(context, devices, 8);
|
||||
if (device_count <= 0)
|
||||
cut_omit ("No device found");
|
||||
cut_omit("No device found");
|
||||
|
||||
for (size_t i = 0; i < device_count; i++) {
|
||||
|
||||
device = nfc_open (context, devices[i]);
|
||||
if (!device)
|
||||
cut_omit ("nfc_open() failed.");
|
||||
device = nfc_open(context, devices[i]);
|
||||
if (!device)
|
||||
cut_omit("nfc_open() failed.");
|
||||
|
||||
tags = freefare_get_tags (device);
|
||||
cut_assert_not_null (tags, cut_message ("freefare_get_tags() failed"));
|
||||
tags = freefare_get_tags(device);
|
||||
cut_assert_not_null(tags, cut_message("freefare_get_tags() failed"));
|
||||
|
||||
tag = NULL;
|
||||
for (int i=0; tags[i]; i++) {
|
||||
if ((freefare_get_tag_type(tags[i]) == MIFARE_ULTRALIGHT) ||
|
||||
(freefare_get_tag_type(tags[i]) == MIFARE_ULTRALIGHT_C)) {
|
||||
tag = tags[i];
|
||||
res = mifare_ultralight_connect (tag);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_ultralight_connect() failed"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
nfc_close (device);
|
||||
device = NULL;
|
||||
freefare_free_tags (tags);
|
||||
tags = NULL;
|
||||
tag = NULL;
|
||||
for (int i = 0; tags[i]; i++) {
|
||||
if ((freefare_get_tag_type(tags[i]) == MIFARE_ULTRALIGHT) ||
|
||||
(freefare_get_tag_type(tags[i]) == MIFARE_ULTRALIGHT_C)) {
|
||||
tag = tags[i];
|
||||
res = mifare_ultralight_connect(tag);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_connect() failed"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
nfc_close(device);
|
||||
device = NULL;
|
||||
freefare_free_tags(tags);
|
||||
tags = NULL;
|
||||
}
|
||||
|
||||
cut_omit ("No MIFARE UltraLight tag on NFC device");
|
||||
cut_omit("No MIFARE UltraLight tag on NFC device");
|
||||
}
|
||||
|
||||
void
|
||||
cut_teardown (void)
|
||||
cut_teardown(void)
|
||||
{
|
||||
if (tag)
|
||||
mifare_ultralight_disconnect (tag);
|
||||
mifare_ultralight_disconnect(tag);
|
||||
|
||||
if (tags) {
|
||||
freefare_free_tags (tags);
|
||||
tags = NULL;
|
||||
freefare_free_tags(tags);
|
||||
tags = NULL;
|
||||
}
|
||||
|
||||
if (device)
|
||||
nfc_close (device);
|
||||
nfc_close(device);
|
||||
|
||||
nfc_exit (context);
|
||||
nfc_exit(context);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
#include "felica_fixture.h"
|
||||
|
||||
void
|
||||
test_felica_read_without_encryption (void)
|
||||
test_felica_read_without_encryption(void)
|
||||
{
|
||||
uint8_t buffer[64];
|
||||
|
||||
int res = felica_read (tag, FELICA_SC_RO, 0x00, buffer, 16);
|
||||
cut_assert_equal_int (16, res);
|
||||
int res = felica_read(tag, FELICA_SC_RO, 0x00, buffer, 16);
|
||||
cut_assert_equal_int(16, res);
|
||||
|
||||
uint8_t blocks[] = {
|
||||
0x02,
|
||||
|
@ -18,12 +18,12 @@ test_felica_read_without_encryption (void)
|
|||
0x04,
|
||||
};
|
||||
|
||||
res = felica_read_ex (tag, FELICA_SC_RO, 3, blocks, buffer, 3 * 16);
|
||||
cut_assert_equal_int (3 * 16, res);
|
||||
res = felica_read_ex(tag, FELICA_SC_RO, 3, blocks, buffer, 3 * 16);
|
||||
cut_assert_equal_int(3 * 16, res);
|
||||
}
|
||||
|
||||
void
|
||||
test_felica_write_without_encryption (void)
|
||||
test_felica_write_without_encryption(void)
|
||||
{
|
||||
uint8_t buffer[16] = {
|
||||
0x00, 0x01, 0x02, 0x03,
|
||||
|
@ -32,7 +32,7 @@ test_felica_write_without_encryption (void)
|
|||
0x0b, 0x0c, 0x0d, 0x0e,
|
||||
};
|
||||
|
||||
int res = felica_write (tag, FELICA_SC_RW, 0x0a, buffer, sizeof (buffer));
|
||||
int res = felica_write(tag, FELICA_SC_RW, 0x0a, buffer, sizeof(buffer));
|
||||
|
||||
cut_assert_equal_int (0, res);
|
||||
cut_assert_equal_int(0, res);
|
||||
}
|
||||
|
|
|
@ -4,23 +4,23 @@
|
|||
#include "freefare_internal.h"
|
||||
|
||||
void
|
||||
test_is_mifare_ultralight (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);
|
||||
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)
|
||||
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);
|
||||
tag = mifare_ultralightc_tag_new(NULL, target);
|
||||
cut_assert_true(is_mifare_ultralightc(tag));
|
||||
mifare_ultralightc_tag_free(tag);
|
||||
}
|
||||
|
|
112
test/test_mad.c
112
test/test_mad.c
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2009, 2010, Romain Tartiere, Romuald Conty.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -21,54 +21,54 @@
|
|||
#include "freefare_internal.h"
|
||||
|
||||
void
|
||||
test_mad (void)
|
||||
test_mad(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
Mad mad = mad_new (1);
|
||||
cut_assert_not_null (mad, cut_message ("Can create a new MAD"));
|
||||
Mad mad = mad_new(1);
|
||||
cut_assert_not_null(mad, cut_message("Can create a new MAD"));
|
||||
|
||||
cut_assert_equal_int (1, mad_get_version (mad), cut_message ("Wrong default MAD version"));
|
||||
mad_set_version (mad, 2);
|
||||
cut_assert_equal_int (2, mad_get_version (mad), cut_message ("Can't change MAD version"));
|
||||
cut_assert_equal_int(1, mad_get_version(mad), cut_message("Wrong default MAD version"));
|
||||
mad_set_version(mad, 2);
|
||||
cut_assert_equal_int(2, mad_get_version(mad), cut_message("Can't change MAD version"));
|
||||
|
||||
cut_assert_equal_int (0, mad_get_card_publisher_sector (mad), cut_message ("Wrong default MAD publisher"));
|
||||
cut_assert_equal_int(0, mad_get_card_publisher_sector(mad), cut_message("Wrong default MAD publisher"));
|
||||
|
||||
res = mad_set_card_publisher_sector (mad, 13);
|
||||
cut_assert_equal_int (0, res, cut_message ("mad_set_card_publisher_sector() returned an error."));
|
||||
cut_assert_equal_int (13, mad_get_card_publisher_sector (mad), cut_message ("Wrong publisher sector"));
|
||||
res = mad_set_card_publisher_sector(mad, 13);
|
||||
cut_assert_equal_int(0, res, cut_message("mad_set_card_publisher_sector() returned an error."));
|
||||
cut_assert_equal_int(13, mad_get_card_publisher_sector(mad), cut_message("Wrong publisher sector"));
|
||||
|
||||
res = mad_set_card_publisher_sector (mad, 0xff);
|
||||
cut_assert_equal_int (-1, res, cut_message ("Invalid sector"));
|
||||
cut_assert_equal_int (13, mad_get_card_publisher_sector (mad), cut_message ("Previous publisher sector value"));
|
||||
res = mad_set_card_publisher_sector(mad, 0xff);
|
||||
cut_assert_equal_int(-1, res, cut_message("Invalid sector"));
|
||||
cut_assert_equal_int(13, mad_get_card_publisher_sector(mad), cut_message("Previous publisher sector value"));
|
||||
|
||||
MadAid aid = {
|
||||
.function_cluster_code = 0,
|
||||
.application_code = 0
|
||||
};
|
||||
|
||||
res = mad_get_aid (mad, 3, &aid);
|
||||
cut_assert_equal_int (0, res, cut_message ("mad_get_aid() failed"));
|
||||
cut_assert_equal_int (0, aid.function_cluster_code, cut_message ("Invalid default value"));
|
||||
cut_assert_equal_int (0, aid.application_code, cut_message ("Invalid default value"));
|
||||
res = mad_get_aid(mad, 3, &aid);
|
||||
cut_assert_equal_int(0, res, cut_message("mad_get_aid() failed"));
|
||||
cut_assert_equal_int(0, aid.function_cluster_code, cut_message("Invalid default value"));
|
||||
cut_assert_equal_int(0, aid.application_code, cut_message("Invalid default value"));
|
||||
|
||||
aid.function_cluster_code = 0xc0;
|
||||
aid.application_code = 0x42;
|
||||
res = mad_set_aid (mad, 3, aid);
|
||||
cut_assert_equal_int (0, res, cut_message ("mad_set_aid() failed"));
|
||||
res = mad_set_aid(mad, 3, aid);
|
||||
cut_assert_equal_int(0, res, cut_message("mad_set_aid() failed"));
|
||||
|
||||
res = mad_get_aid (mad, 3, &aid);
|
||||
cut_assert_equal_int (0, res, cut_message ("mad_get_aid() failed"));
|
||||
cut_assert_equal_int (0xC0, aid.function_cluster_code, cut_message ("Invalid value"));
|
||||
cut_assert_equal_int (0x42, aid.application_code, cut_message ("Invalid value"));
|
||||
res = mad_get_aid(mad, 3, &aid);
|
||||
cut_assert_equal_int(0, res, cut_message("mad_get_aid() failed"));
|
||||
cut_assert_equal_int(0xC0, aid.function_cluster_code, cut_message("Invalid value"));
|
||||
cut_assert_equal_int(0x42, aid.application_code, cut_message("Invalid value"));
|
||||
|
||||
mad_free (mad);
|
||||
mad_free(mad);
|
||||
}
|
||||
|
||||
#define CRC_PRESET 0xc7
|
||||
|
||||
void
|
||||
test_mad_crc8_basic (void)
|
||||
test_mad_crc8_basic(void)
|
||||
{
|
||||
uint8_t crc;
|
||||
const uint8_t crc_value = 0x42;
|
||||
|
@ -81,14 +81,14 @@ test_mad_crc8_basic (void)
|
|||
crc = CRC_PRESET;
|
||||
nxp_crc(&crc, crc_value);
|
||||
nxp_crc(&crc, save);
|
||||
cut_assert_equal_int (0x00, crc, cut_message ("CRC should verify crc(message + crc(message)) = 0"));
|
||||
cut_assert_equal_int(0x00, crc, cut_message("CRC should verify crc(message + crc(message)) = 0"));
|
||||
}
|
||||
|
||||
/*
|
||||
* The following MAD values where extracted from documentation.
|
||||
*/
|
||||
void
|
||||
test_mad_crc8_doc_example (void)
|
||||
test_mad_crc8_doc_example(void)
|
||||
{
|
||||
/* Preset */
|
||||
uint8_t crc = CRC_PRESET;
|
||||
|
@ -134,14 +134,14 @@ test_mad_crc8_doc_example (void)
|
|||
|
||||
/* Append zeros of augmented message */
|
||||
|
||||
cut_assert_equal_int (0x89, crc, cut_message ("Sample CRC should match"));
|
||||
cut_assert_equal_int(0x89, crc, cut_message("Sample CRC should match"));
|
||||
}
|
||||
|
||||
/*
|
||||
* The following MAD values where extracted from a MIFARE dump.
|
||||
*/
|
||||
void
|
||||
test_mad_crc8_real_example_1 (void)
|
||||
test_mad_crc8_real_example_1(void)
|
||||
{
|
||||
/* Preset */
|
||||
uint8_t crc = CRC_PRESET;
|
||||
|
@ -187,14 +187,14 @@ test_mad_crc8_real_example_1 (void)
|
|||
|
||||
/* Append zeros of augmented message */
|
||||
|
||||
cut_assert_equal_int (0xc4, crc, cut_message ("Read example 1 CRC should match"));
|
||||
cut_assert_equal_int(0xc4, crc, cut_message("Read example 1 CRC should match"));
|
||||
}
|
||||
|
||||
/*
|
||||
* The following MAD values where extracted from a MIFARE dump.
|
||||
*/
|
||||
void
|
||||
test_mad_crc8_real_example_2 (void)
|
||||
test_mad_crc8_real_example_2(void)
|
||||
{
|
||||
/* Preset */
|
||||
uint8_t crc = CRC_PRESET;
|
||||
|
@ -240,48 +240,48 @@ test_mad_crc8_real_example_2 (void)
|
|||
|
||||
/* Append zeros of augmented message */
|
||||
|
||||
cut_assert_equal_int (0xab, crc, cut_message ("Read example 1 CRC should match"));
|
||||
cut_assert_equal_int(0xab, crc, cut_message("Read example 1 CRC should match"));
|
||||
}
|
||||
|
||||
void
|
||||
test_mad_sector_0x00_crc8 (void)
|
||||
test_mad_sector_0x00_crc8(void)
|
||||
{
|
||||
int res;
|
||||
Mad mad = mad_new (1);
|
||||
cut_assert_not_null (mad, cut_message ("mad_new() failed"));
|
||||
Mad mad = mad_new(1);
|
||||
cut_assert_not_null(mad, cut_message("mad_new() failed"));
|
||||
|
||||
res = mad_set_card_publisher_sector (mad, 0x01);
|
||||
res = mad_set_card_publisher_sector(mad, 0x01);
|
||||
|
||||
/* Block 1 */
|
||||
MadAid aid1 = { 0x01, 0x08 };
|
||||
mad_set_aid (mad, 1, aid1);
|
||||
mad_set_aid (mad, 2, aid1);
|
||||
mad_set_aid (mad, 3, aid1);
|
||||
mad_set_aid(mad, 1, aid1);
|
||||
mad_set_aid(mad, 2, aid1);
|
||||
mad_set_aid(mad, 3, aid1);
|
||||
|
||||
/* Block 2 */
|
||||
MadAid empty_aid = { 0x00, 0x00 };
|
||||
mad_set_aid (mad, 4, empty_aid);
|
||||
mad_set_aid (mad, 5, empty_aid);
|
||||
mad_set_aid (mad, 6, empty_aid);
|
||||
mad_set_aid(mad, 4, empty_aid);
|
||||
mad_set_aid(mad, 5, empty_aid);
|
||||
mad_set_aid(mad, 6, empty_aid);
|
||||
MadAid aid2 = { 0x04, 0x00 };
|
||||
mad_set_aid (mad, 7, aid2);
|
||||
mad_set_aid(mad, 7, aid2);
|
||||
|
||||
/* Block 3 */
|
||||
MadAid aid3 = { 0x03, 0x10 };
|
||||
mad_set_aid (mad, 8, aid3);
|
||||
mad_set_aid (mad, 9, aid3);
|
||||
mad_set_aid(mad, 8, aid3);
|
||||
mad_set_aid(mad, 9, aid3);
|
||||
MadAid aid4 = { 0x02, 0x10 };
|
||||
mad_set_aid (mad, 10, aid4);
|
||||
mad_set_aid (mad, 11, aid4);
|
||||
mad_set_aid(mad, 10, aid4);
|
||||
mad_set_aid(mad, 11, aid4);
|
||||
|
||||
mad_set_aid (mad, 12, empty_aid);
|
||||
mad_set_aid (mad, 13, empty_aid);
|
||||
mad_set_aid (mad, 14, empty_aid);
|
||||
mad_set_aid(mad, 12, empty_aid);
|
||||
mad_set_aid(mad, 13, empty_aid);
|
||||
mad_set_aid(mad, 14, empty_aid);
|
||||
MadAid aid5 = { 0x11, 0x30 };
|
||||
mad_set_aid (mad, 15, aid5);
|
||||
mad_set_aid(mad, 15, aid5);
|
||||
|
||||
res = sector_0x00_crc8 (mad);
|
||||
cut_assert_equal_int(0x89, res, cut_message ("Sample CRC should match"));
|
||||
res = sector_0x00_crc8(mad);
|
||||
cut_assert_equal_int(0x89, res, cut_message("Sample CRC should match"));
|
||||
|
||||
mad_free (mad);
|
||||
mad_free(mad);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere, Romuald Conty.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -19,61 +19,61 @@
|
|||
#include <freefare.h>
|
||||
|
||||
void
|
||||
test_mifare_application (void)
|
||||
test_mifare_application(void)
|
||||
{
|
||||
/* Card publisher part */
|
||||
|
||||
MadAid aid = { 0x22, 0x42 };
|
||||
Mad mad = mad_new (2);
|
||||
Mad mad = mad_new(2);
|
||||
|
||||
int i;
|
||||
|
||||
cut_assert_not_null (mad, cut_message ("mad_new() failed"));
|
||||
cut_assert_not_null(mad, cut_message("mad_new() failed"));
|
||||
|
||||
MifareClassicSectorNumber *s_alloc = mifare_application_alloc (mad, aid, 3*3*16);
|
||||
cut_assert_not_null (s_alloc, cut_message ("mifare_application_alloc() failed"));
|
||||
MifareClassicSectorNumber *s_alloc = mifare_application_alloc(mad, aid, 3 * 3 * 16);
|
||||
cut_assert_not_null(s_alloc, cut_message("mifare_application_alloc() failed"));
|
||||
|
||||
MifareClassicSectorNumber *s_found = mifare_application_find (mad, aid);
|
||||
cut_assert_not_null (s_found, cut_message ("mifare_application_alloc() failed"));
|
||||
MifareClassicSectorNumber *s_found = mifare_application_find(mad, aid);
|
||||
cut_assert_not_null(s_found, cut_message("mifare_application_alloc() failed"));
|
||||
|
||||
for (i = 0; s_alloc[i]; i++) {
|
||||
cut_assert_equal_int (s_alloc[i], s_found[i], cut_message ("Allocated and found blocks don't match at position %d", i));
|
||||
cut_assert_equal_int(s_alloc[i], s_found[i], cut_message("Allocated and found blocks don't match at position %d", i));
|
||||
}
|
||||
|
||||
cut_assert_equal_int (0, s_alloc[i], cut_message ("Invalid size"));
|
||||
cut_assert_equal_int (0, s_found[i], cut_message ("Invalid size"));
|
||||
cut_assert_equal_int(0, s_alloc[i], cut_message("Invalid size"));
|
||||
cut_assert_equal_int(0, s_found[i], cut_message("Invalid size"));
|
||||
|
||||
mifare_application_free (mad, aid);
|
||||
mifare_application_free(mad, aid);
|
||||
|
||||
free (s_alloc);
|
||||
free (s_found);
|
||||
free(s_alloc);
|
||||
free(s_found);
|
||||
|
||||
s_found = mifare_application_find (mad, aid);
|
||||
cut_assert_null (s_found, cut_message ("mifare_application_free() failed"));
|
||||
s_found = mifare_application_find(mad, aid);
|
||||
cut_assert_null(s_found, cut_message("mifare_application_free() failed"));
|
||||
|
||||
s_alloc = mifare_application_alloc (mad, aid, 15*16 + 1*16 + 1);
|
||||
cut_assert_not_null (s_alloc, cut_message ("mifare_application_alloc() failed"));
|
||||
s_alloc = mifare_application_alloc(mad, aid, 15 * 16 + 1 * 16 + 1);
|
||||
cut_assert_not_null(s_alloc, cut_message("mifare_application_alloc() failed"));
|
||||
|
||||
s_found = mifare_application_find (mad, aid);
|
||||
cut_assert_not_null (s_found, cut_message ("mifare_application_alloc() failed"));
|
||||
s_found = mifare_application_find(mad, aid);
|
||||
cut_assert_not_null(s_found, cut_message("mifare_application_alloc() failed"));
|
||||
|
||||
|
||||
|
||||
for (i = 0; s_alloc[i]; i++) {
|
||||
cut_assert_equal_int (s_alloc[i], s_found[i], cut_message ("Allocated and found blocks don't match at position %d", i));
|
||||
cut_assert_equal_int(s_alloc[i], s_found[i], cut_message("Allocated and found blocks don't match at position %d", i));
|
||||
}
|
||||
|
||||
cut_assert_equal_int (0, s_alloc[i], cut_message ("Invalid size"));
|
||||
cut_assert_equal_int (0, s_found[i], cut_message ("Invalid size"));
|
||||
cut_assert_equal_int(0, s_alloc[i], cut_message("Invalid size"));
|
||||
cut_assert_equal_int(0, s_found[i], cut_message("Invalid size"));
|
||||
|
||||
|
||||
mifare_application_free (mad, aid);
|
||||
mifare_application_free(mad, aid);
|
||||
|
||||
free (s_alloc);
|
||||
free (s_found);
|
||||
free(s_alloc);
|
||||
free(s_found);
|
||||
|
||||
s_found = mifare_application_find (mad, aid);
|
||||
cut_assert_null (s_found, cut_message ("mifare_application_free() failed"));
|
||||
s_found = mifare_application_find(mad, aid);
|
||||
cut_assert_null(s_found, cut_message("mifare_application_free() failed"));
|
||||
|
||||
mad_free (mad);
|
||||
mad_free(mad);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere, Romuald Conty.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -25,86 +25,86 @@
|
|||
#include "mifare_classic_fixture.h"
|
||||
|
||||
void
|
||||
test_mifare_classic_authenticate (void)
|
||||
test_mifare_classic_authenticate(void)
|
||||
{
|
||||
int res;
|
||||
MifareClassicKey k = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
res = mifare_classic_authenticate (tag, 0x00, k, MFC_KEY_A);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_authenticate(tag, 0x00, k, MFC_KEY_A);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_classic_get_data_block_permission (void)
|
||||
test_mifare_classic_get_data_block_permission(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
MifareClassicKey k = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
res = mifare_classic_authenticate (tag, 0x04, k, MFC_KEY_A);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_authenticate(tag, 0x04, k, MFC_KEY_A);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
|
||||
cut_assert_equal_int (1, mifare_classic_get_data_block_permission(tag, 0x04, MCAB_R, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (1, mifare_classic_get_data_block_permission(tag, 0x04, MCAB_R, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (1, mifare_classic_get_data_block_permission(tag, 0x04, MCAB_W, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (1, mifare_classic_get_data_block_permission(tag, 0x04, MCAB_W, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (1, mifare_classic_get_data_block_permission(tag, 0x04, MCAB_D, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (1, mifare_classic_get_data_block_permission(tag, 0x04, MCAB_D, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (1, mifare_classic_get_data_block_permission(tag, 0x04, MCAB_I, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (1, mifare_classic_get_data_block_permission(tag, 0x04, MCAB_I, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int(1, mifare_classic_get_data_block_permission(tag, 0x04, MCAB_R, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(1, mifare_classic_get_data_block_permission(tag, 0x04, MCAB_R, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(1, mifare_classic_get_data_block_permission(tag, 0x04, MCAB_W, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(1, mifare_classic_get_data_block_permission(tag, 0x04, MCAB_W, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(1, mifare_classic_get_data_block_permission(tag, 0x04, MCAB_D, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(1, mifare_classic_get_data_block_permission(tag, 0x04, MCAB_D, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(1, mifare_classic_get_data_block_permission(tag, 0x04, MCAB_I, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(1, mifare_classic_get_data_block_permission(tag, 0x04, MCAB_I, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
|
||||
cut_assert_equal_int (-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_READ_KEYA, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_READ_KEYA, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_WRITE_KEYA, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_WRITE_KEYA, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_READ_ACCESS_BITS, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_READ_ACCESS_BITS, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_WRITE_ACCESS_BITS, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_WRITE_ACCESS_BITS, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_READ_KEYB, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_READ_KEYB, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_WRITE_KEYB, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_WRITE_KEYB, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_READ_KEYA, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_READ_KEYA, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_WRITE_KEYA, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_WRITE_KEYA, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_READ_ACCESS_BITS, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_READ_ACCESS_BITS, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_WRITE_ACCESS_BITS, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_WRITE_ACCESS_BITS, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_READ_KEYB, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_READ_KEYB, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_WRITE_KEYB, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_trailer_block_permission(tag, 0x04, MCAB_WRITE_KEYB, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_classic_get_trailer_permission (void)
|
||||
test_mifare_classic_get_trailer_permission(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
MifareClassicKey k = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
res = mifare_classic_authenticate (tag, 0x07, k, MFC_KEY_A);
|
||||
cut_assert_equal_int (res, 0, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_authenticate(tag, 0x07, k, MFC_KEY_A);
|
||||
cut_assert_equal_int(res, 0, cut_message("mifare_classic_authenticate() failed"));
|
||||
|
||||
cut_assert_equal_int (-1, mifare_classic_get_data_block_permission(tag, 0x07, MCAB_R, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_data_block_permission(tag, 0x07, MCAB_R, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_data_block_permission(tag, 0x07, MCAB_W, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_data_block_permission(tag, 0x07, MCAB_W, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_data_block_permission(tag, 0x07, MCAB_D, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_data_block_permission(tag, 0x07, MCAB_D, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_data_block_permission(tag, 0x07, MCAB_I, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (-1, mifare_classic_get_data_block_permission(tag, 0x07, MCAB_I, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_data_block_permission(tag, 0x07, MCAB_R, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_data_block_permission(tag, 0x07, MCAB_R, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_data_block_permission(tag, 0x07, MCAB_W, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_data_block_permission(tag, 0x07, MCAB_W, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_data_block_permission(tag, 0x07, MCAB_D, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_data_block_permission(tag, 0x07, MCAB_D, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_data_block_permission(tag, 0x07, MCAB_I, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(-1, mifare_classic_get_data_block_permission(tag, 0x07, MCAB_I, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
|
||||
cut_assert_equal_int (0, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_READ_KEYA, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (0, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_READ_KEYA, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (1, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_WRITE_KEYA, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (0, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_WRITE_KEYA, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (1, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_READ_ACCESS_BITS, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (0, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_READ_ACCESS_BITS, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (1, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_WRITE_ACCESS_BITS, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (0, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_WRITE_ACCESS_BITS, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (1, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_READ_KEYB, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (0, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_READ_KEYB, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (1, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_WRITE_KEYB, MFC_KEY_A), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int (0, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_WRITE_KEYB, MFC_KEY_B), cut_message ("Wrong permission"));
|
||||
cut_assert_equal_int(0, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_READ_KEYA, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(0, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_READ_KEYA, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(1, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_WRITE_KEYA, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(0, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_WRITE_KEYA, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(1, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_READ_ACCESS_BITS, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(0, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_READ_ACCESS_BITS, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(1, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_WRITE_ACCESS_BITS, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(0, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_WRITE_ACCESS_BITS, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(1, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_READ_KEYB, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(0, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_READ_KEYB, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(1, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_WRITE_KEYB, MFC_KEY_A), cut_message("Wrong permission"));
|
||||
cut_assert_equal_int(0, mifare_classic_get_trailer_block_permission(tag, 0x07, MCAB_WRITE_KEYB, MFC_KEY_B), cut_message("Wrong permission"));
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_classic_format_first_sector (void)
|
||||
test_mifare_classic_format_first_sector(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
MifareClassicKey k = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
res = mifare_classic_authenticate (tag, 0x00, k, MFC_KEY_A);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_authenticate(tag, 0x00, k, MFC_KEY_A);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
|
||||
MifareClassicBlock data = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
|
@ -112,54 +112,54 @@ test_mifare_classic_format_first_sector (void)
|
|||
};
|
||||
|
||||
MifareClassicBlock empty;
|
||||
memset (empty, '\x00', sizeof (empty));
|
||||
memset(empty, '\x00', sizeof(empty));
|
||||
|
||||
MifareClassicBlock b0;
|
||||
res = mifare_classic_read (tag, 0x00, &b0);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read() failed"));
|
||||
res = mifare_classic_read(tag, 0x00, &b0);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read() failed"));
|
||||
|
||||
res = mifare_classic_write (tag, 0x00, data);
|
||||
cut_assert_equal_int (-1, res, cut_message ("mifare_classic_write() succeeded"));
|
||||
res = mifare_classic_write(tag, 0x00, data);
|
||||
cut_assert_equal_int(-1, res, cut_message("mifare_classic_write() succeeded"));
|
||||
|
||||
res = mifare_classic_disconnect (tag);
|
||||
res = mifare_classic_connect (tag);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_connect() failed"));
|
||||
res = mifare_classic_authenticate (tag, 0x00, k, MFC_KEY_A);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_disconnect(tag);
|
||||
res = mifare_classic_connect(tag);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_connect() failed"));
|
||||
res = mifare_classic_authenticate(tag, 0x00, k, MFC_KEY_A);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
|
||||
res = mifare_classic_write (tag, 0x01, data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_write() failed"));
|
||||
res = mifare_classic_write (tag, 0x02, data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_write() failed"));
|
||||
res = mifare_classic_write(tag, 0x01, data);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_write() failed"));
|
||||
res = mifare_classic_write(tag, 0x02, data);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_write() failed"));
|
||||
|
||||
res = mifare_classic_format_sector (tag, 0x00);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_format_sector() failed"));
|
||||
res = mifare_classic_format_sector(tag, 0x00);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_format_sector() failed"));
|
||||
|
||||
res = mifare_classic_read (tag, 0x00, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory (data, sizeof (data), b0, sizeof (b0), cut_message ("Data changed in first block (block 1/3)"));
|
||||
res = mifare_classic_read(tag, 0x00, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory(data, sizeof(data), b0, sizeof(b0), cut_message("Data changed in first block (block 1/3)"));
|
||||
|
||||
res = mifare_classic_read (tag, 0x01, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory (data, sizeof (data), empty, sizeof (data), cut_message ("Wrong data in formatted sector (block 2/3)"));
|
||||
res = mifare_classic_read(tag, 0x01, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory(data, sizeof(data), empty, sizeof(data), cut_message("Wrong data in formatted sector (block 2/3)"));
|
||||
|
||||
res = mifare_classic_read (tag, 0x02, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory (data, sizeof (data), empty, sizeof (data), cut_message ("Wrong data in formatted sector (block 3/3)"));
|
||||
res = mifare_classic_read(tag, 0x02, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory(data, sizeof(data), empty, sizeof(data), cut_message("Wrong data in formatted sector (block 3/3)"));
|
||||
|
||||
res = mifare_classic_read (tag, 0x03, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory (data, sizeof (data), "\x00\x00\x00\x00\x00\x00\xff\x07\x80\x69\xff\xff\xff\xff\xff\xff", sizeof (data), cut_message ("Wrong permissions in formatted sector"));
|
||||
res = mifare_classic_read(tag, 0x03, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory(data, sizeof(data), "\x00\x00\x00\x00\x00\x00\xff\x07\x80\x69\xff\xff\xff\xff\xff\xff", sizeof(data), cut_message("Wrong permissions in formatted sector"));
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_classic_format (void)
|
||||
test_mifare_classic_format(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
MifareClassicKey k = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
res = mifare_classic_authenticate (tag, 0x3c, k, MFC_KEY_A);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_authenticate(tag, 0x3c, k, MFC_KEY_A);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
|
||||
MifareClassicBlock data = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
|
@ -167,140 +167,140 @@ test_mifare_classic_format (void)
|
|||
};
|
||||
|
||||
MifareClassicBlock empty;
|
||||
memset (empty, 0, sizeof (empty));
|
||||
memset(empty, 0, sizeof(empty));
|
||||
|
||||
res = mifare_classic_write (tag, 0x3c, data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_write() failed"));
|
||||
res = mifare_classic_write (tag, 0x3d, data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_write() failed"));
|
||||
res = mifare_classic_write (tag, 0x3e, data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_write() failed"));
|
||||
res = mifare_classic_write(tag, 0x3c, data);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_write() failed"));
|
||||
res = mifare_classic_write(tag, 0x3d, data);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_write() failed"));
|
||||
res = mifare_classic_write(tag, 0x3e, data);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_write() failed"));
|
||||
|
||||
res = mifare_classic_format_sector (tag, mifare_classic_block_sector (0x3c));
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_format_sector() failed"));
|
||||
res = mifare_classic_format_sector(tag, mifare_classic_block_sector(0x3c));
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_format_sector() failed"));
|
||||
|
||||
res = mifare_classic_read (tag, 0x3c, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory (data, sizeof (data), empty, sizeof (data), cut_message ("Wrong data in formatted sector (block 1/3)"));
|
||||
res = mifare_classic_read(tag, 0x3c, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory(data, sizeof(data), empty, sizeof(data), cut_message("Wrong data in formatted sector (block 1/3)"));
|
||||
|
||||
res = mifare_classic_read (tag, 0x3d, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory (data, sizeof (data), empty, sizeof (data), cut_message ("Wrong data in formatted sector (block 2/3)"));
|
||||
res = mifare_classic_read(tag, 0x3d, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory(data, sizeof(data), empty, sizeof(data), cut_message("Wrong data in formatted sector (block 2/3)"));
|
||||
|
||||
res = mifare_classic_read (tag, 0x3e, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory (data, sizeof (data), empty, sizeof (data), cut_message ("Wrong data in formatted sector (block 3/3)"));
|
||||
res = mifare_classic_read(tag, 0x3e, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory(data, sizeof(data), empty, sizeof(data), cut_message("Wrong data in formatted sector (block 3/3)"));
|
||||
|
||||
res = mifare_classic_read (tag, 0x3f, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory (data, sizeof (data), "\x00\x00\x00\x00\x00\x00\xff\x07\x80\x69\xff\xff\xff\xff\xff\xff", sizeof (data), cut_message ("Wrong permissions in formatted sector"));
|
||||
res = mifare_classic_read(tag, 0x3f, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory(data, sizeof(data), "\x00\x00\x00\x00\x00\x00\xff\x07\x80\x69\xff\xff\xff\xff\xff\xff", sizeof(data), cut_message("Wrong permissions in formatted sector"));
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_classic_value_block_increment (void)
|
||||
test_mifare_classic_value_block_increment(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
MifareClassicBlockNumber block = 0x04;
|
||||
MifareClassicKey k = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
res = mifare_classic_authenticate (tag, block, k, MFC_KEY_A);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_authenticate(tag, block, k, MFC_KEY_A);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
|
||||
res = mifare_classic_init_value (tag, block, 1000, 0x00);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_init_value() failed"));
|
||||
res = mifare_classic_init_value(tag, block, 1000, 0x00);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_init_value() failed"));
|
||||
|
||||
/* Initialize value block */
|
||||
|
||||
int32_t value;
|
||||
MifareClassicBlockNumber adr;
|
||||
res = mifare_classic_read_value (tag, block, &value, &adr);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read_value() failed"));
|
||||
cut_assert_equal_int (1000, value, cut_message ("Wrong value block value"));
|
||||
cut_assert_equal_int (0x00, adr, cut_message ("Wrong value block address"));
|
||||
res = mifare_classic_read_value(tag, block, &value, &adr);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read_value() failed"));
|
||||
cut_assert_equal_int(1000, value, cut_message("Wrong value block value"));
|
||||
cut_assert_equal_int(0x00, adr, cut_message("Wrong value block address"));
|
||||
|
||||
/* Increment by 1 */
|
||||
|
||||
res = mifare_classic_increment (tag, block, 1);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_increment() failed"));
|
||||
res = mifare_classic_increment(tag, block, 1);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_increment() failed"));
|
||||
|
||||
res = mifare_classic_transfer (tag, block);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_transfer() failed"));
|
||||
res = mifare_classic_transfer(tag, block);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_transfer() failed"));
|
||||
|
||||
res = mifare_classic_read_value (tag, block, &value, &adr);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read_value() failed"));
|
||||
cut_assert_equal_int (1001, value, cut_message ("Wrong value block value"));
|
||||
cut_assert_equal_int (0x00, adr, cut_message ("Wrong value block address"));
|
||||
res = mifare_classic_read_value(tag, block, &value, &adr);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read_value() failed"));
|
||||
cut_assert_equal_int(1001, value, cut_message("Wrong value block value"));
|
||||
cut_assert_equal_int(0x00, adr, cut_message("Wrong value block address"));
|
||||
|
||||
/* Increment by 10 */
|
||||
|
||||
res = mifare_classic_increment (tag, block, 10);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_increment() failed"));
|
||||
res = mifare_classic_increment(tag, block, 10);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_increment() failed"));
|
||||
|
||||
res = mifare_classic_transfer (tag, block);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_transfer() failed"));
|
||||
res = mifare_classic_transfer(tag, block);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_transfer() failed"));
|
||||
|
||||
res = mifare_classic_read_value (tag, block, &value, &adr);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read_value() failed"));
|
||||
cut_assert_equal_int (1011, value, cut_message ("Wrong value block value"));
|
||||
cut_assert_equal_int (0x00, adr, cut_message ("Wrong value block address"));
|
||||
res = mifare_classic_read_value(tag, block, &value, &adr);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read_value() failed"));
|
||||
cut_assert_equal_int(1011, value, cut_message("Wrong value block value"));
|
||||
cut_assert_equal_int(0x00, adr, cut_message("Wrong value block address"));
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_classic_value_block_decrement (void)
|
||||
test_mifare_classic_value_block_decrement(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
MifareClassicBlockNumber block = 0x04;
|
||||
MifareClassicKey k = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
res = mifare_classic_authenticate (tag, block, k, MFC_KEY_A);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_init_value (tag, block, 1000, 0x00);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_init_value() failed"));
|
||||
res = mifare_classic_authenticate(tag, block, k, MFC_KEY_A);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_init_value(tag, block, 1000, 0x00);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_init_value() failed"));
|
||||
|
||||
/* Initialize value block */
|
||||
|
||||
int32_t value;
|
||||
MifareClassicBlockNumber adr;
|
||||
res = mifare_classic_read_value (tag, block, &value, &adr);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read_value() failed"));
|
||||
cut_assert_equal_int (1000, value, cut_message ("Wrong value block value"));
|
||||
cut_assert_equal_int (0x00, adr, cut_message ("Wrong value block address"));
|
||||
res = mifare_classic_read_value(tag, block, &value, &adr);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read_value() failed"));
|
||||
cut_assert_equal_int(1000, value, cut_message("Wrong value block value"));
|
||||
cut_assert_equal_int(0x00, adr, cut_message("Wrong value block address"));
|
||||
|
||||
/* Decrement */
|
||||
|
||||
res = mifare_classic_decrement (tag, block, 1);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_decrement() failed"));
|
||||
res = mifare_classic_decrement(tag, block, 1);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_decrement() failed"));
|
||||
|
||||
res = mifare_classic_transfer (tag, block);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_transfer() failed"));
|
||||
res = mifare_classic_transfer(tag, block);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_transfer() failed"));
|
||||
|
||||
res = mifare_classic_read_value (tag, block, &value, &adr);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read_value() failed"));
|
||||
cut_assert_equal_int (999, value, cut_message ("Wrong value block value"));
|
||||
cut_assert_equal_int (0x00, adr, cut_message ("Wrong value block address"));
|
||||
res = mifare_classic_read_value(tag, block, &value, &adr);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read_value() failed"));
|
||||
cut_assert_equal_int(999, value, cut_message("Wrong value block value"));
|
||||
cut_assert_equal_int(0x00, adr, cut_message("Wrong value block address"));
|
||||
|
||||
res = mifare_classic_decrement (tag, block, 1000);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_decrement() failed"));
|
||||
res = mifare_classic_decrement(tag, block, 1000);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_decrement() failed"));
|
||||
|
||||
res = mifare_classic_transfer (tag, block);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_transfer() failed"));
|
||||
res = mifare_classic_transfer(tag, block);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_transfer() failed"));
|
||||
|
||||
res = mifare_classic_read_value (tag, block, &value, &adr);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read_value() failed"));
|
||||
cut_assert_equal_int (-1, value, cut_message ("Wrong value block value"));
|
||||
cut_assert_equal_int (0x00, adr, cut_message ("Wrong value block address"));
|
||||
res = mifare_classic_read_value(tag, block, &value, &adr);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read_value() failed"));
|
||||
cut_assert_equal_int(-1, value, cut_message("Wrong value block value"));
|
||||
cut_assert_equal_int(0x00, adr, cut_message("Wrong value block address"));
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_classic_value_block_restore (void)
|
||||
test_mifare_classic_value_block_restore(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
MifareClassicBlockNumber block = 0x04;
|
||||
MifareClassicKey k = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
res = mifare_classic_authenticate (tag, block, k, MFC_KEY_A);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_authenticate(tag, block, k, MFC_KEY_A);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
|
||||
/* Restore */
|
||||
|
||||
|
@ -326,49 +326,49 @@ test_mifare_classic_value_block_restore (void)
|
|||
0xff
|
||||
};
|
||||
|
||||
res = mifare_classic_write (tag, block, sample);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_write() failed"));
|
||||
res = mifare_classic_write(tag, block, sample);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_write() failed"));
|
||||
|
||||
res = mifare_classic_read (tag, block, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory (sample, sizeof (sample), data, sizeof (data), cut_message ("Wrong value block contents"));
|
||||
res = mifare_classic_read(tag, block, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory(sample, sizeof(sample), data, sizeof(data), cut_message("Wrong value block contents"));
|
||||
|
||||
res = mifare_classic_write (tag, block+1, nul);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_write() failed"));
|
||||
res = mifare_classic_write(tag, block + 1, nul);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_write() failed"));
|
||||
|
||||
res = mifare_classic_read (tag, block+1, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory (nul, sizeof (sample), data, sizeof (data), cut_message ("Wrong value block contents"));
|
||||
res = mifare_classic_read(tag, block + 1, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory(nul, sizeof(sample), data, sizeof(data), cut_message("Wrong value block contents"));
|
||||
|
||||
res = mifare_classic_restore (tag, block);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_restore() failed"));
|
||||
res = mifare_classic_restore(tag, block);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_restore() failed"));
|
||||
|
||||
res = mifare_classic_transfer (tag, block+1);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_transfer() failed"));
|
||||
res = mifare_classic_transfer(tag, block + 1);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_transfer() failed"));
|
||||
|
||||
res = mifare_classic_read (tag, block+1, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory (sample, sizeof (sample), data, sizeof (data), cut_message ("Wrong value block contents"));
|
||||
res = mifare_classic_read(tag, block + 1, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_read() failed"));
|
||||
cut_assert_equal_memory(sample, sizeof(sample), data, sizeof(data), cut_message("Wrong value block contents"));
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_classic_get_uid (void)
|
||||
test_mifare_classic_get_uid(void)
|
||||
{
|
||||
char *uid;
|
||||
|
||||
uid = freefare_get_tag_uid (tag);
|
||||
uid = freefare_get_tag_uid(tag);
|
||||
|
||||
cut_assert_not_null (uid, cut_message ("freefare_get_tag_uid() failed"));
|
||||
cut_assert (((strlen (uid) == 8)||(strlen (uid) == 14)), cut_message ("Wrong UID length"));
|
||||
cut_assert_not_null(uid, cut_message("freefare_get_tag_uid() failed"));
|
||||
cut_assert(((strlen(uid) == 8) || (strlen(uid) == 14)), cut_message("Wrong UID length"));
|
||||
|
||||
free (uid);
|
||||
free(uid);
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_classic_get_tag_friendly_name (void)
|
||||
test_mifare_classic_get_tag_friendly_name(void)
|
||||
{
|
||||
const char *name = freefare_get_tag_friendly_name (tag);
|
||||
const char *name = freefare_get_tag_friendly_name(tag);
|
||||
|
||||
cut_assert_not_null (name, cut_message ("freefare_get_tag_friendly_name() failed"));
|
||||
cut_assert_not_null(name, cut_message("freefare_get_tag_friendly_name() failed"));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere, Romuald Conty.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -20,15 +20,15 @@
|
|||
#include <freefare.h>
|
||||
|
||||
void
|
||||
test_mifare_classic_create_trailer_block (void)
|
||||
test_mifare_classic_create_trailer_block(void)
|
||||
{
|
||||
MifareClassicBlock data;
|
||||
|
||||
MifareClassicKey key_a = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
MifareClassicKey key_b = { 0xde, 0xad, 0xbe, 0xef, 0xff, 0xff };
|
||||
|
||||
mifare_classic_trailer_block (&data, key_a, 0, 0, 0, 4, 0x42, key_b);
|
||||
mifare_classic_trailer_block(&data, key_a, 0, 0, 0, 4, 0x42, key_b);
|
||||
|
||||
cut_assert_equal_memory (data, sizeof (data), "\xff\xff\xff\xff\xff\xff\xff\x07\x80\x42\xde\xad\xbe\xef\xff\xff", sizeof (data), cut_message ("Wrong generated block"));
|
||||
cut_assert_equal_memory(data, sizeof(data), "\xff\xff\xff\xff\xff\xff\xff\x07\x80\x42\xde\xad\xbe\xef\xff\xff", sizeof(data), cut_message("Wrong generated block"));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -22,11 +22,11 @@
|
|||
#include "mifare_classic_fixture.h"
|
||||
|
||||
void
|
||||
test_mifare_classic_mad (void)
|
||||
test_mifare_classic_mad(void)
|
||||
{
|
||||
MifareClassicKey key_a_transport = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
MifareClassicKey key_b_sector_00 = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
|
||||
MifareClassicKey key_b_sector_10 = { 0x1a, 0x98, 0x2c, 0x7e, 0x45 ,0x9a };
|
||||
MifareClassicKey key_b_sector_10 = { 0x1a, 0x98, 0x2c, 0x7e, 0x45, 0x9a };
|
||||
MifareClassicBlock tb;
|
||||
Mad mad;
|
||||
int res;
|
||||
|
@ -37,21 +37,21 @@ test_mifare_classic_mad (void)
|
|||
* |_| |_/_/ \_\___/ \_/|_|
|
||||
*/
|
||||
|
||||
mad = mad_new (1);
|
||||
cut_assert_not_null (mad, cut_message ("mad_new() failed"));
|
||||
mad = mad_new(1);
|
||||
cut_assert_not_null(mad, cut_message("mad_new() failed"));
|
||||
|
||||
// Prepare sector 0x00 for writing a MAD.
|
||||
res = mifare_classic_authenticate (tag, 0x00, key_a_transport, MFC_KEY_A);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_authenticate(tag, 0x00, key_a_transport, MFC_KEY_A);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
|
||||
mifare_classic_trailer_block (&tb, key_a_transport, 00, 00, 00, 06, 0x00, key_b_sector_00);
|
||||
mifare_classic_trailer_block(&tb, key_a_transport, 00, 00, 00, 06, 0x00, key_b_sector_00);
|
||||
|
||||
res = mifare_classic_write (tag, 0x03, tb);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_write() failed"));
|
||||
res = mifare_classic_write(tag, 0x03, tb);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_write() failed"));
|
||||
|
||||
// Write the empty MAD
|
||||
res = mad_write (tag, mad, key_b_sector_00, NULL);
|
||||
cut_assert_equal_int (0, res, cut_message ("mad_write() failed"));
|
||||
res = mad_write(tag, mad, key_b_sector_00, NULL);
|
||||
cut_assert_equal_int(0, res, cut_message("mad_write() failed"));
|
||||
|
||||
|
||||
// Check the empty MAD
|
||||
|
@ -65,27 +65,27 @@ test_mifare_classic_mad (void)
|
|||
};
|
||||
MifareClassicBlock data;
|
||||
|
||||
res = mifare_classic_authenticate (tag, 0x01, mad_public_key_a, MFC_KEY_A);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_authenticate(tag, 0x01, mad_public_key_a, MFC_KEY_A);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
|
||||
res = mifare_classic_read (tag, 0x01, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mad_read() failed"));
|
||||
cut_assert_equal_memory (ref_01, sizeof (ref_01), data, sizeof (data), cut_message ("Wrong data"));
|
||||
res = mifare_classic_read(tag, 0x01, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mad_read() failed"));
|
||||
cut_assert_equal_memory(ref_01, sizeof(ref_01), data, sizeof(data), cut_message("Wrong data"));
|
||||
|
||||
res = mifare_classic_read (tag, 0x02, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mad_read() failed"));
|
||||
cut_assert_equal_memory (ref_02, sizeof (ref_02), data, sizeof (data), cut_message ("Wrong data"));
|
||||
res = mifare_classic_read(tag, 0x02, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mad_read() failed"));
|
||||
cut_assert_equal_memory(ref_02, sizeof(ref_02), data, sizeof(data), cut_message("Wrong data"));
|
||||
|
||||
Mad mad2 = mad_read (tag);
|
||||
cut_assert_not_null (mad2, cut_message ("mad_read() failed"));
|
||||
cut_assert_equal_memory (mad, sizeof (mad), mad2, sizeof (mad2), cut_message ("Wrong MAD"));
|
||||
Mad mad2 = mad_read(tag);
|
||||
cut_assert_not_null(mad2, cut_message("mad_read() failed"));
|
||||
cut_assert_equal_memory(mad, sizeof(mad), mad2, sizeof(mad2), cut_message("Wrong MAD"));
|
||||
|
||||
const char application_data[] = "APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> " \
|
||||
"APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> " \
|
||||
"APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> " \
|
||||
"APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> " \
|
||||
"APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> " \
|
||||
"APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> ";
|
||||
"APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> " \
|
||||
"APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> " \
|
||||
"APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> " \
|
||||
"APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> " \
|
||||
"APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> ";
|
||||
|
||||
MadAid aid = {
|
||||
.function_cluster_code = 0x01,
|
||||
|
@ -93,78 +93,78 @@ test_mifare_classic_mad (void)
|
|||
};
|
||||
|
||||
// Write some data in the application
|
||||
MifareClassicSectorNumber *sectors = mifare_application_alloc (mad, aid, sizeof (application_data));
|
||||
cut_assert_not_null (sectors, cut_message ("mifare_application_alloc() failed"));
|
||||
free (sectors);
|
||||
MifareClassicSectorNumber *sectors = mifare_application_alloc(mad, aid, sizeof(application_data));
|
||||
cut_assert_not_null(sectors, cut_message("mifare_application_alloc() failed"));
|
||||
free(sectors);
|
||||
|
||||
res = mad_write (tag, mad, key_b_sector_00, NULL);
|
||||
cut_assert_equal_int (0, res, cut_message ("mad_write() failed"));
|
||||
res = mad_write(tag, mad, key_b_sector_00, NULL);
|
||||
cut_assert_equal_int(0, res, cut_message("mad_write() failed"));
|
||||
|
||||
ssize_t s = mifare_application_write (tag, mad, aid, &application_data, sizeof (application_data), key_a_transport, MFC_KEY_A);
|
||||
cut_assert_equal_int (sizeof (application_data), s, cut_message ("mifare_application_write() failed"));
|
||||
ssize_t s = mifare_application_write(tag, mad, aid, &application_data, sizeof(application_data), key_a_transport, MFC_KEY_A);
|
||||
cut_assert_equal_int(sizeof(application_data), s, cut_message("mifare_application_write() failed"));
|
||||
|
||||
char read_buf[500];
|
||||
|
||||
// Read it again
|
||||
s = mifare_application_read (tag, mad, aid, read_buf, sizeof (application_data), key_a_transport, MFC_KEY_A);
|
||||
cut_assert_equal_int (sizeof (application_data), s, cut_message ("mifare_application_read() failed"));
|
||||
cut_assert_equal_memory (application_data, sizeof (application_data), read_buf, s, cut_message ("Wrong application data"));
|
||||
s = mifare_application_read(tag, mad, aid, read_buf, sizeof(application_data), key_a_transport, MFC_KEY_A);
|
||||
cut_assert_equal_int(sizeof(application_data), s, cut_message("mifare_application_read() failed"));
|
||||
cut_assert_equal_memory(application_data, sizeof(application_data), read_buf, s, cut_message("Wrong application data"));
|
||||
|
||||
mad_free (mad);
|
||||
mad_free (mad2);
|
||||
mad_free(mad);
|
||||
mad_free(mad2);
|
||||
|
||||
// Revert to the transport configuration
|
||||
res = mifare_classic_authenticate (tag, 0x00, key_b_sector_00, MFC_KEY_B);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_format_sector (tag, 0x00);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_format_sector() failed"));
|
||||
res = mifare_classic_authenticate(tag, 0x00, key_b_sector_00, MFC_KEY_B);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_format_sector(tag, 0x00);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_format_sector() failed"));
|
||||
|
||||
/* __ __ _ ___ ___
|
||||
* | \/ | /_\ | \__ _|_ )
|
||||
* | |\/| |/ _ \| |) \ V // /
|
||||
* |_| |_/_/ \_\___/ \_//___|
|
||||
*/
|
||||
if (freefare_get_tag_type (tag) != MIFARE_CLASSIC_4K) {
|
||||
cut_omit ("MADv2 requires a MIFARE Classic 4K to be tested");
|
||||
if (freefare_get_tag_type(tag) != MIFARE_CLASSIC_4K) {
|
||||
cut_omit("MADv2 requires a MIFARE Classic 4K to be tested");
|
||||
}
|
||||
|
||||
mad = mad_new (2);
|
||||
cut_assert_not_null (mad, cut_message ("mad_new() failed"));
|
||||
mad = mad_new(2);
|
||||
cut_assert_not_null(mad, cut_message("mad_new() failed"));
|
||||
|
||||
// Prepare sector 0x00 for writing a MAD.
|
||||
res = mifare_classic_authenticate (tag, 0x00, key_a_transport, MFC_KEY_A);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_authenticate(tag, 0x00, key_a_transport, MFC_KEY_A);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
|
||||
mifare_classic_trailer_block (&tb, key_a_transport, 00, 00, 00, 06, 0x00, key_b_sector_00);
|
||||
mifare_classic_trailer_block(&tb, key_a_transport, 00, 00, 00, 06, 0x00, key_b_sector_00);
|
||||
|
||||
res = mifare_classic_write (tag, 0x03, tb);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_write() failed"));
|
||||
res = mifare_classic_write(tag, 0x03, tb);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_write() failed"));
|
||||
|
||||
// Prepare sector 0x10 for writing a MAD.
|
||||
res = mifare_classic_authenticate (tag, 0x40, key_a_transport, MFC_KEY_A);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_authenticate(tag, 0x40, key_a_transport, MFC_KEY_A);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
|
||||
mifare_classic_trailer_block (&tb, key_a_transport, 00, 00, 00, 06, 0x00, key_b_sector_10);
|
||||
mifare_classic_trailer_block(&tb, key_a_transport, 00, 00, 00, 06, 0x00, key_b_sector_10);
|
||||
|
||||
res = mifare_classic_write (tag, 0x43, tb);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_write() failed"));
|
||||
res = mifare_classic_write(tag, 0x43, tb);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_write() failed"));
|
||||
|
||||
// Write the empty MAD
|
||||
res = mad_write (tag, mad, key_b_sector_00, key_b_sector_10);
|
||||
cut_assert_equal_int (0, res, cut_message ("mad_write() failed"));
|
||||
res = mad_write(tag, mad, key_b_sector_00, key_b_sector_10);
|
||||
cut_assert_equal_int(0, res, cut_message("mad_write() failed"));
|
||||
|
||||
// Check the empty MAD
|
||||
|
||||
res = mifare_classic_authenticate (tag, 0x01, mad_public_key_a, MFC_KEY_A);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_authenticate(tag, 0x01, mad_public_key_a, MFC_KEY_A);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
|
||||
res = mifare_classic_read (tag, 0x01, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mad_read() failed"));
|
||||
cut_assert_equal_memory (ref_01, sizeof (ref_01), data, sizeof (data), cut_message ("Wrong data"));
|
||||
res = mifare_classic_read(tag, 0x01, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mad_read() failed"));
|
||||
cut_assert_equal_memory(ref_01, sizeof(ref_01), data, sizeof(data), cut_message("Wrong data"));
|
||||
|
||||
res = mifare_classic_read (tag, 0x02, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mad_read() failed"));
|
||||
cut_assert_equal_memory (ref_02, sizeof (ref_02), data, sizeof (data), cut_message ("Wrong data"));
|
||||
res = mifare_classic_read(tag, 0x02, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mad_read() failed"));
|
||||
cut_assert_equal_memory(ref_02, sizeof(ref_02), data, sizeof(data), cut_message("Wrong data"));
|
||||
|
||||
MifareClassicBlock ref_40 = {
|
||||
0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
@ -179,54 +179,54 @@ test_mifare_classic_mad (void)
|
|||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
res = mifare_classic_authenticate (tag, 0x40, mad_public_key_a, MFC_KEY_A);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_authenticate(tag, 0x40, mad_public_key_a, MFC_KEY_A);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
|
||||
res = mifare_classic_read (tag, 0x40, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mad_read() failed"));
|
||||
cut_assert_equal_memory (ref_40, sizeof (ref_01), data, sizeof (data), cut_message ("Wrong data"));
|
||||
res = mifare_classic_read(tag, 0x40, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mad_read() failed"));
|
||||
cut_assert_equal_memory(ref_40, sizeof(ref_01), data, sizeof(data), cut_message("Wrong data"));
|
||||
|
||||
res = mifare_classic_read (tag, 0x41, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mad_read() failed"));
|
||||
cut_assert_equal_memory (ref_41, sizeof (ref_02), data, sizeof (data), cut_message ("Wrong data"));
|
||||
res = mifare_classic_read(tag, 0x41, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mad_read() failed"));
|
||||
cut_assert_equal_memory(ref_41, sizeof(ref_02), data, sizeof(data), cut_message("Wrong data"));
|
||||
|
||||
res = mifare_classic_read (tag, 0x42, &data);
|
||||
cut_assert_equal_int (0, res, cut_message ("mad_read() failed"));
|
||||
cut_assert_equal_memory (ref_42, sizeof (ref_02), data, sizeof (data), cut_message ("Wrong data"));
|
||||
res = mifare_classic_read(tag, 0x42, &data);
|
||||
cut_assert_equal_int(0, res, cut_message("mad_read() failed"));
|
||||
cut_assert_equal_memory(ref_42, sizeof(ref_02), data, sizeof(data), cut_message("Wrong data"));
|
||||
|
||||
|
||||
mad2 = mad_read (tag);
|
||||
cut_assert_not_null (mad2, cut_message ("mad_read() failed"));
|
||||
cut_assert_equal_memory (mad, sizeof (mad), mad2, sizeof (mad2), cut_message ("Wrong MAD"));
|
||||
mad2 = mad_read(tag);
|
||||
cut_assert_not_null(mad2, cut_message("mad_read() failed"));
|
||||
cut_assert_equal_memory(mad, sizeof(mad), mad2, sizeof(mad2), cut_message("Wrong MAD"));
|
||||
|
||||
// Write some data in the application
|
||||
sectors = mifare_application_alloc (mad, aid, sizeof (application_data));
|
||||
cut_assert_not_null (sectors, cut_message ("mifare_application_alloc() failed"));
|
||||
free (sectors);
|
||||
sectors = mifare_application_alloc(mad, aid, sizeof(application_data));
|
||||
cut_assert_not_null(sectors, cut_message("mifare_application_alloc() failed"));
|
||||
free(sectors);
|
||||
|
||||
res = mad_write (tag, mad, key_b_sector_00, key_b_sector_10);
|
||||
cut_assert_equal_int (0, res, cut_message ("mad_write() failed"));
|
||||
res = mad_write(tag, mad, key_b_sector_00, key_b_sector_10);
|
||||
cut_assert_equal_int(0, res, cut_message("mad_write() failed"));
|
||||
|
||||
s = mifare_application_write (tag, mad, aid, &application_data, sizeof (application_data), key_a_transport, MFC_KEY_A);
|
||||
cut_assert_equal_int (sizeof (application_data), s, cut_message ("mifare_application_write() failed"));
|
||||
s = mifare_application_write(tag, mad, aid, &application_data, sizeof(application_data), key_a_transport, MFC_KEY_A);
|
||||
cut_assert_equal_int(sizeof(application_data), s, cut_message("mifare_application_write() failed"));
|
||||
|
||||
// Read it again
|
||||
s = mifare_application_read (tag, mad, aid, read_buf, sizeof (application_data), key_a_transport, MFC_KEY_A);
|
||||
cut_assert_equal_int (sizeof (application_data), s, cut_message ("mifare_application_read() failed"));
|
||||
cut_assert_equal_memory (application_data, sizeof (application_data), read_buf, s, cut_message ("Wrong application data"));
|
||||
s = mifare_application_read(tag, mad, aid, read_buf, sizeof(application_data), key_a_transport, MFC_KEY_A);
|
||||
cut_assert_equal_int(sizeof(application_data), s, cut_message("mifare_application_read() failed"));
|
||||
cut_assert_equal_memory(application_data, sizeof(application_data), read_buf, s, cut_message("Wrong application data"));
|
||||
|
||||
mad_free (mad);
|
||||
mad_free (mad2);
|
||||
mad_free(mad);
|
||||
mad_free(mad2);
|
||||
|
||||
// Revert to the transport configuration
|
||||
res = mifare_classic_authenticate (tag, 0x00, key_b_sector_00, MFC_KEY_B);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_format_sector (tag, 0x00);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_format_sector() failed"));
|
||||
res = mifare_classic_authenticate(tag, 0x00, key_b_sector_00, MFC_KEY_B);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_format_sector(tag, 0x00);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_format_sector() failed"));
|
||||
|
||||
res = mifare_classic_authenticate (tag, 0x40, key_b_sector_10, MFC_KEY_B);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_format_sector (tag, 0x10);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_classic_format_sector() failed"));
|
||||
res = mifare_classic_authenticate(tag, 0x40, key_b_sector_10, MFC_KEY_B);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_authenticate() failed"));
|
||||
res = mifare_classic_format_sector(tag, 0x10);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_classic_format_sector() failed"));
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere, Romuald Conty.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -21,19 +21,19 @@
|
|||
#include "freefare_internal.h"
|
||||
|
||||
void
|
||||
test_mifare_classic_sector_boundaries (void)
|
||||
test_mifare_classic_sector_boundaries(void)
|
||||
{
|
||||
for (int i=0; i < 32; i++) {
|
||||
for (int j=0; j < 4; j++) {
|
||||
cut_assert_equal_int (4 * i, mifare_classic_sector_first_block (mifare_classic_block_sector (4 * i)), cut_message ("Wrong first block number for block %d", i));
|
||||
cut_assert_equal_int (4 * i + 3, mifare_classic_sector_last_block (mifare_classic_block_sector (4 * i + j)), cut_message ("Wrong last block number for block %d", i));
|
||||
for (int i = 0; i < 32; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
cut_assert_equal_int(4 * i, mifare_classic_sector_first_block(mifare_classic_block_sector(4 * i)), cut_message("Wrong first block number for block %d", i));
|
||||
cut_assert_equal_int(4 * i + 3, mifare_classic_sector_last_block(mifare_classic_block_sector(4 * i + j)), cut_message("Wrong last block number for block %d", i));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i < 8; i++) {
|
||||
for (int j=0; j < 16; j++) {
|
||||
cut_assert_equal_int (128 + 16 * i, mifare_classic_sector_first_block (mifare_classic_block_sector (128 + 16 * i)), cut_message ("Wrong last block number for block %d", i));
|
||||
cut_assert_equal_int (128 + 16 * i + 15, mifare_classic_sector_last_block (mifare_classic_block_sector (128 + 16 * i + j)), cut_message ("Wrong last block number for block %d", i));
|
||||
for (int i = 0; i < 8; i++) {
|
||||
for (int j = 0; j < 16; j++) {
|
||||
cut_assert_equal_int(128 + 16 * i, mifare_classic_sector_first_block(mifare_classic_block_sector(128 + 16 * i)), cut_message("Wrong last block number for block %d", i));
|
||||
cut_assert_equal_int(128 + 16 * i + 15, mifare_classic_sector_last_block(mifare_classic_block_sector(128 + 16 * i + j)), cut_message("Wrong last block number for block %d", i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere, Romuald Conty.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -38,7 +38,7 @@ uint8_t key_data[] = {
|
|||
|
||||
|
||||
void
|
||||
test_mifare_desfire_aes_generate_subkeys (void)
|
||||
test_mifare_desfire_aes_generate_subkeys(void)
|
||||
{
|
||||
uint8_t sk1[] = {
|
||||
0xfb, 0xee, 0xd6, 0x18,
|
||||
|
@ -54,23 +54,23 @@ test_mifare_desfire_aes_generate_subkeys (void)
|
|||
0xe4, 0x6d, 0x51, 0x3b
|
||||
};
|
||||
|
||||
MifareDESFireKey key = mifare_desfire_aes_key_new (key_data);
|
||||
cmac_generate_subkeys (key);
|
||||
MifareDESFireKey key = mifare_desfire_aes_key_new(key_data);
|
||||
cmac_generate_subkeys(key);
|
||||
|
||||
cut_assert_equal_memory (sk1, 16, key->cmac_sk1, 16, cut_message ("Wrong sub-key 1"));
|
||||
cut_assert_equal_memory (sk2, 16, key->cmac_sk2, 16, cut_message ("Wrong sub-key 2"));
|
||||
cut_assert_equal_memory(sk1, 16, key->cmac_sk1, 16, cut_message("Wrong sub-key 1"));
|
||||
cut_assert_equal_memory(sk2, 16, key->cmac_sk2, 16, cut_message("Wrong sub-key 2"));
|
||||
|
||||
mifare_desfire_key_free (key);
|
||||
mifare_desfire_key_free(key);
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_desfire_aes_cmac_empty (void)
|
||||
test_mifare_desfire_aes_cmac_empty(void)
|
||||
{
|
||||
MifareDESFireKey key = mifare_desfire_aes_key_new (key_data);
|
||||
cmac_generate_subkeys (key);
|
||||
MifareDESFireKey key = mifare_desfire_aes_key_new(key_data);
|
||||
cmac_generate_subkeys(key);
|
||||
|
||||
uint8_t ivect[16];
|
||||
memset (ivect, 0, sizeof (ivect));
|
||||
memset(ivect, 0, sizeof(ivect));
|
||||
|
||||
uint8_t expected_cmac[] = {
|
||||
0xbb, 0x1d, 0x69, 0x29,
|
||||
|
@ -80,21 +80,21 @@ test_mifare_desfire_aes_cmac_empty (void)
|
|||
};
|
||||
|
||||
uint8_t my_cmac[16];
|
||||
cmac (key, ivect, NULL, 0, my_cmac);
|
||||
cmac(key, ivect, NULL, 0, my_cmac);
|
||||
|
||||
cut_assert_equal_memory (expected_cmac, 16, my_cmac, 16, cut_message ("Wrong CMAC"));
|
||||
cut_assert_equal_memory(expected_cmac, 16, my_cmac, 16, cut_message("Wrong CMAC"));
|
||||
|
||||
mifare_desfire_key_free (key);
|
||||
mifare_desfire_key_free(key);
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_desfire_aes_cmac_128 (void)
|
||||
test_mifare_desfire_aes_cmac_128(void)
|
||||
{
|
||||
MifareDESFireKey key = mifare_desfire_aes_key_new (key_data);
|
||||
cmac_generate_subkeys (key);
|
||||
MifareDESFireKey key = mifare_desfire_aes_key_new(key_data);
|
||||
cmac_generate_subkeys(key);
|
||||
|
||||
uint8_t ivect[16];
|
||||
memset (ivect, 0, sizeof (ivect));
|
||||
memset(ivect, 0, sizeof(ivect));
|
||||
|
||||
uint8_t message[] = {
|
||||
0x6b, 0xc1, 0xbe, 0xe2,
|
||||
|
@ -111,21 +111,21 @@ test_mifare_desfire_aes_cmac_128 (void)
|
|||
};
|
||||
|
||||
uint8_t my_cmac[16];
|
||||
cmac (key, ivect, message, 16, my_cmac);
|
||||
cmac(key, ivect, message, 16, my_cmac);
|
||||
|
||||
cut_assert_equal_memory (expected_cmac, 16, my_cmac, sizeof (message), cut_message ("Wrong CMAC"));
|
||||
cut_assert_equal_memory(expected_cmac, 16, my_cmac, sizeof(message), cut_message("Wrong CMAC"));
|
||||
|
||||
mifare_desfire_key_free (key);
|
||||
mifare_desfire_key_free(key);
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_desfire_aes_cmac_320 (void)
|
||||
test_mifare_desfire_aes_cmac_320(void)
|
||||
{
|
||||
MifareDESFireKey key = mifare_desfire_aes_key_new (key_data);
|
||||
cmac_generate_subkeys (key);
|
||||
MifareDESFireKey key = mifare_desfire_aes_key_new(key_data);
|
||||
cmac_generate_subkeys(key);
|
||||
|
||||
uint8_t ivect[16];
|
||||
memset (ivect, 0, sizeof (ivect));
|
||||
memset(ivect, 0, sizeof(ivect));
|
||||
|
||||
uint8_t message[] = {
|
||||
0x6b, 0xc1, 0xbe, 0xe2,
|
||||
|
@ -148,21 +148,21 @@ test_mifare_desfire_aes_cmac_320 (void)
|
|||
};
|
||||
|
||||
uint8_t my_cmac[16];
|
||||
cmac (key, ivect, message, sizeof (message), my_cmac);
|
||||
cmac(key, ivect, message, sizeof(message), my_cmac);
|
||||
|
||||
cut_assert_equal_memory (expected_cmac, 16, my_cmac, 16, cut_message ("Wrong CMAC"));
|
||||
cut_assert_equal_memory(expected_cmac, 16, my_cmac, 16, cut_message("Wrong CMAC"));
|
||||
|
||||
mifare_desfire_key_free (key);
|
||||
mifare_desfire_key_free(key);
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_desfire_aes_cmac_512 (void)
|
||||
test_mifare_desfire_aes_cmac_512(void)
|
||||
{
|
||||
MifareDESFireKey key = mifare_desfire_aes_key_new (key_data);
|
||||
cmac_generate_subkeys (key);
|
||||
MifareDESFireKey key = mifare_desfire_aes_key_new(key_data);
|
||||
cmac_generate_subkeys(key);
|
||||
|
||||
uint8_t ivect[16];
|
||||
memset (ivect, 0, sizeof (ivect));
|
||||
memset(ivect, 0, sizeof(ivect));
|
||||
|
||||
uint8_t message[] = {
|
||||
0x6b, 0xc1, 0xbe, 0xe2,
|
||||
|
@ -191,9 +191,9 @@ test_mifare_desfire_aes_cmac_512 (void)
|
|||
};
|
||||
|
||||
uint8_t my_cmac[16];
|
||||
cmac (key, ivect, message, sizeof (message), my_cmac);
|
||||
cmac(key, ivect, message, sizeof(message), my_cmac);
|
||||
|
||||
cut_assert_equal_memory (expected_cmac, 16, my_cmac, 16, cut_message ("Wrong CMAC"));
|
||||
cut_assert_equal_memory(expected_cmac, 16, my_cmac, 16, cut_message("Wrong CMAC"));
|
||||
|
||||
mifare_desfire_key_free (key);
|
||||
mifare_desfire_key_free(key);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere, Romuald Conty.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -21,7 +21,7 @@
|
|||
#include "freefare_internal.h"
|
||||
|
||||
void
|
||||
test_mifare_desfire_aid (void)
|
||||
test_mifare_desfire_aid(void)
|
||||
{
|
||||
/*
|
||||
* <-- LSB MSB -->
|
||||
|
@ -33,17 +33,17 @@ test_mifare_desfire_aid (void)
|
|||
*
|
||||
* 0xF21438 -> 0x83412F
|
||||
*/
|
||||
MifareDESFireAID desfire_aid = mifare_desfire_aid_new (0x00f12ab8);
|
||||
MifareDESFireAID desfire_aid = mifare_desfire_aid_new(0x00f12ab8);
|
||||
MadAid mad_aid = {
|
||||
.function_cluster_code = 0x12,
|
||||
.application_code = 0xab,
|
||||
};
|
||||
MifareDESFireAID desfire_aid2 = mifare_desfire_aid_new_with_mad_aid (mad_aid, 8);
|
||||
MifareDESFireAID desfire_aid2 = mifare_desfire_aid_new_with_mad_aid(mad_aid, 8);
|
||||
|
||||
cut_assert_equal_memory (desfire_aid->data,3, desfire_aid2->data, 3, cut_message ("wrong aid"));
|
||||
cut_assert_equal_memory(desfire_aid->data, 3, desfire_aid2->data, 3, cut_message("wrong aid"));
|
||||
|
||||
cut_assert_equal_int (mifare_desfire_aid_get_aid (desfire_aid), 0x00f12ab8, cut_message ("wrong aid"));
|
||||
cut_assert_equal_int(mifare_desfire_aid_get_aid(desfire_aid), 0x00f12ab8, cut_message("wrong aid"));
|
||||
|
||||
free (desfire_aid);
|
||||
free (desfire_aid2);
|
||||
free(desfire_aid);
|
||||
free(desfire_aid2);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -20,73 +20,73 @@
|
|||
#include "freefare_internal.h"
|
||||
|
||||
void
|
||||
test_mifare_rol (void)
|
||||
test_mifare_rol(void)
|
||||
{
|
||||
uint8_t data[8] = "01234567";
|
||||
rol (data, 8);
|
||||
cut_assert_equal_memory ("12345670", 8, data, 8, cut_message ("Wrong data"));
|
||||
rol(data, 8);
|
||||
cut_assert_equal_memory("12345670", 8, data, 8, cut_message("Wrong data"));
|
||||
|
||||
uint8_t data2[16] = "0123456789abcdef";
|
||||
rol (data2, 16);
|
||||
cut_assert_equal_memory (data2, 16, "123456789abcdef0", 16, cut_message ("Wrong data"));
|
||||
rol(data2, 16);
|
||||
cut_assert_equal_memory(data2, 16, "123456789abcdef0", 16, cut_message("Wrong data"));
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_desfire_des_receive (void)
|
||||
test_mifare_desfire_des_receive(void)
|
||||
{
|
||||
uint8_t null_ivect[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
uint8_t data[8] = { 0xd6, 0x59, 0xe1, 0x70, 0x43, 0xa8, 0x40, 0x68 };
|
||||
uint8_t key_data[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
MifareDESFireKey key = mifare_desfire_des_key_new_with_version (key_data);
|
||||
MifareDESFireKey key = mifare_desfire_des_key_new_with_version(key_data);
|
||||
|
||||
uint8_t expected_data[8] = { 0x73, 0x0d, 0xdf, 0xad, 0xa4, 0xd2, 0x07, 0x89 };
|
||||
uint8_t expected_key[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
|
||||
mifare_cypher_blocks_chained (NULL, key, null_ivect, data, 8, MCD_RECEIVE, MCO_DECYPHER);
|
||||
mifare_cypher_blocks_chained(NULL, key, null_ivect, data, 8, MCD_RECEIVE, MCO_DECYPHER);
|
||||
|
||||
cut_assert_equal_memory (&expected_data, 8, &data, 8, cut_message ("Wrong data"));
|
||||
cut_assert_equal_memory (&expected_key, 8, key->data, 8, cut_message ("Wrong key"));
|
||||
cut_assert_equal_memory(&expected_data, 8, &data, 8, cut_message("Wrong data"));
|
||||
cut_assert_equal_memory(&expected_key, 8, key->data, 8, cut_message("Wrong key"));
|
||||
|
||||
mifare_desfire_key_free (key);
|
||||
mifare_desfire_key_free(key);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
test_mifare_desfire_des_send (void)
|
||||
test_mifare_desfire_des_send(void)
|
||||
{
|
||||
uint8_t null_ivect[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
uint8_t data[8] = { 0x73, 0x0d, 0xdf, 0xad, 0xa4, 0xd2, 0x07, 0x89 };
|
||||
uint8_t key_data[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
MifareDESFireKey key = mifare_desfire_des_key_new_with_version (key_data);
|
||||
MifareDESFireKey key = mifare_desfire_des_key_new_with_version(key_data);
|
||||
|
||||
uint8_t expected_data[8] = { 0xd6, 0x59, 0xe1, 0x70, 0x43, 0xa8, 0x40, 0x68 };
|
||||
uint8_t expected_key[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
|
||||
mifare_cypher_blocks_chained (NULL, key, null_ivect, data, 8, MCD_SEND, MCO_DECYPHER);
|
||||
mifare_cypher_blocks_chained(NULL, key, null_ivect, data, 8, MCD_SEND, MCO_DECYPHER);
|
||||
|
||||
cut_assert_equal_memory (&expected_data, 8, &data, 8, cut_message ("Wrong data"));
|
||||
cut_assert_equal_memory (&expected_key, 8, key->data, 8, cut_message ("Wrong key"));
|
||||
cut_assert_equal_memory(&expected_data, 8, &data, 8, cut_message("Wrong data"));
|
||||
cut_assert_equal_memory(&expected_key, 8, key->data, 8, cut_message("Wrong key"));
|
||||
|
||||
mifare_desfire_key_free (key);
|
||||
mifare_desfire_key_free(key);
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_desfire_padded_data_length (void)
|
||||
test_mifare_desfire_padded_data_length(void)
|
||||
{
|
||||
size_t res;
|
||||
|
||||
res = padded_data_length (0, 8);
|
||||
cut_assert_equal_int (res, 8, cut_message ("Invalid size"));
|
||||
res = padded_data_length (1, 8);
|
||||
cut_assert_equal_int (res, 8, cut_message ("Invalid size"));
|
||||
res = padded_data_length (8, 8);
|
||||
cut_assert_equal_int (res, 8, cut_message ("Invalid size"));
|
||||
res = padded_data_length (9, 8);
|
||||
cut_assert_equal_int (res, 16, cut_message ("Invalid size"));
|
||||
res = padded_data_length (0, 16);
|
||||
cut_assert_equal_int (res, 16, cut_message ("Invalid size"));
|
||||
res = padded_data_length (33, 16);
|
||||
cut_assert_equal_int (res, 48, cut_message ("Invalid size"));
|
||||
res = padded_data_length(0, 8);
|
||||
cut_assert_equal_int(res, 8, cut_message("Invalid size"));
|
||||
res = padded_data_length(1, 8);
|
||||
cut_assert_equal_int(res, 8, cut_message("Invalid size"));
|
||||
res = padded_data_length(8, 8);
|
||||
cut_assert_equal_int(res, 8, cut_message("Invalid size"));
|
||||
res = padded_data_length(9, 8);
|
||||
cut_assert_equal_int(res, 16, cut_message("Invalid size"));
|
||||
res = padded_data_length(0, 16);
|
||||
cut_assert_equal_int(res, 16, cut_message("Invalid size"));
|
||||
res = padded_data_length(33, 16);
|
||||
cut_assert_equal_int(res, 48, cut_message("Invalid size"));
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -28,128 +28,128 @@
|
|||
|
||||
#define cut_assert_success(last_command) \
|
||||
do { \
|
||||
cut_assert_equal_int (OPERATION_OK, mifare_desfire_last_picc_error (tag), cut_message ("PICC replied %s", mifare_desfire_error_lookup (mifare_desfire_last_picc_error (tag)))); \
|
||||
cut_assert_not_equal_int (-1, res, cut_message ("Wrong return value")); \
|
||||
cut_assert_equal_int (OPERATION_OK, mifare_desfire_last_picc_error (tag), cut_message ("PICC replied %s", mifare_desfire_error_lookup (mifare_desfire_last_picc_error (tag)))); \
|
||||
cut_assert_not_equal_int (-1, res, cut_message ("Wrong return value")); \
|
||||
} while (0)
|
||||
|
||||
void
|
||||
test_mifare_desfire_ev1_aes2 (void)
|
||||
test_mifare_desfire_ev1_aes2(void)
|
||||
{
|
||||
int res;
|
||||
MifareDESFireKey key;
|
||||
|
||||
mifare_desfire_auto_authenticate (tag, 0);
|
||||
mifare_desfire_auto_authenticate(tag, 0);
|
||||
|
||||
// Setup the AES key
|
||||
key = mifare_desfire_aes_key_new_with_version (key_data_aes, key_data_aes_version);
|
||||
res = mifare_desfire_change_key (tag, 0x80, key, NULL);
|
||||
cut_assert_success ("mifare_desfire_change_key");
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_aes_key_new_with_version(key_data_aes, key_data_aes_version);
|
||||
res = mifare_desfire_change_key(tag, 0x80, key, NULL);
|
||||
cut_assert_success("mifare_desfire_change_key");
|
||||
mifare_desfire_key_free(key);
|
||||
|
||||
// Authenticate with the AES key
|
||||
key = mifare_desfire_aes_key_new_with_version (key_data_aes, key_data_aes_version);
|
||||
res = mifare_desfire_authenticate_aes (tag, 0, key);
|
||||
cut_assert_success ("mifare_desfire_authenticate");
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_aes_key_new_with_version(key_data_aes, key_data_aes_version);
|
||||
res = mifare_desfire_authenticate_aes(tag, 0, key);
|
||||
cut_assert_success("mifare_desfire_authenticate");
|
||||
mifare_desfire_key_free(key);
|
||||
|
||||
res = mifare_desfire_format_picc (tag);
|
||||
cut_assert_success ("mifare_desfire_format_picc()");
|
||||
res = mifare_desfire_format_picc(tag);
|
||||
cut_assert_success("mifare_desfire_format_picc()");
|
||||
|
||||
key = mifare_desfire_aes_key_new_with_version (key_data_aes, key_data_aes_version);
|
||||
res = mifare_desfire_authenticate_aes (tag, 0, key);
|
||||
cut_assert_success ("mifare_desfire_authenticate");
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_aes_key_new_with_version(key_data_aes, key_data_aes_version);
|
||||
res = mifare_desfire_authenticate_aes(tag, 0, key);
|
||||
cut_assert_success("mifare_desfire_authenticate");
|
||||
mifare_desfire_key_free(key);
|
||||
|
||||
uint32_t size;
|
||||
res = mifare_desfire_free_mem (tag, &size);
|
||||
cut_assert_success ("mifare_desfire_free_mem");
|
||||
res = mifare_desfire_free_mem(tag, &size);
|
||||
cut_assert_success("mifare_desfire_free_mem");
|
||||
|
||||
// Do some commands to check CMAC is properly handled
|
||||
res = mifare_desfire_free_mem (tag, &size);
|
||||
cut_assert_success ("mifare_desfire_free_mem");
|
||||
res = mifare_desfire_free_mem(tag, &size);
|
||||
cut_assert_success("mifare_desfire_free_mem");
|
||||
|
||||
struct mifare_desfire_version_info info;
|
||||
res = mifare_desfire_get_version (tag, &info);
|
||||
cut_assert_success ("mifare_desfire_get_version");
|
||||
res = mifare_desfire_get_version(tag, &info);
|
||||
cut_assert_success("mifare_desfire_get_version");
|
||||
|
||||
res = mifare_desfire_change_key_settings (tag, 0x0F);
|
||||
cut_assert_success ("mifare_desfire_change_key_settings");
|
||||
res = mifare_desfire_change_key_settings(tag, 0x0F);
|
||||
cut_assert_success("mifare_desfire_change_key_settings");
|
||||
|
||||
res = mifare_desfire_free_mem (tag, &size);
|
||||
cut_assert_success ("mifare_desfire_free_mem");
|
||||
res = mifare_desfire_free_mem(tag, &size);
|
||||
cut_assert_success("mifare_desfire_free_mem");
|
||||
|
||||
MifareDESFireAID aid = mifare_desfire_aid_new (0x112233);
|
||||
MifareDESFireAID aid = mifare_desfire_aid_new(0x112233);
|
||||
|
||||
mifare_desfire_delete_application (tag, aid);
|
||||
mifare_desfire_delete_application(tag, aid);
|
||||
|
||||
res = mifare_desfire_create_application (tag, aid, 0xff, 0x81);
|
||||
cut_assert_success ("mifare_desfire_create_application");
|
||||
res = mifare_desfire_create_application(tag, aid, 0xff, 0x81);
|
||||
cut_assert_success("mifare_desfire_create_application");
|
||||
|
||||
res = mifare_desfire_select_application (tag, aid);
|
||||
cut_assert_success ("mifare_desfire_select_application");
|
||||
res = mifare_desfire_select_application(tag, aid);
|
||||
cut_assert_success("mifare_desfire_select_application");
|
||||
|
||||
key = mifare_desfire_aes_key_new (key_data_aes);
|
||||
res = mifare_desfire_authenticate_aes (tag, 0, key);
|
||||
cut_assert_success ("mifare_desfire_authenticate");
|
||||
free (key);
|
||||
key = mifare_desfire_aes_key_new(key_data_aes);
|
||||
res = mifare_desfire_authenticate_aes(tag, 0, key);
|
||||
cut_assert_success("mifare_desfire_authenticate");
|
||||
free(key);
|
||||
|
||||
key = mifare_desfire_aes_key_new_with_version (key_data_aes, key_data_aes_version);
|
||||
res = mifare_desfire_change_key (tag, 0x00, key, NULL);
|
||||
cut_assert_success ("mifare_desfire_change_key");
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_aes_key_new_with_version(key_data_aes, key_data_aes_version);
|
||||
res = mifare_desfire_change_key(tag, 0x00, key, NULL);
|
||||
cut_assert_success("mifare_desfire_change_key");
|
||||
mifare_desfire_key_free(key);
|
||||
|
||||
key = mifare_desfire_aes_key_new (key_data_aes);
|
||||
res = mifare_desfire_authenticate_aes (tag, 0, key);
|
||||
cut_assert_success ("mifare_desfire_authenticate");
|
||||
free (key);
|
||||
key = mifare_desfire_aes_key_new(key_data_aes);
|
||||
res = mifare_desfire_authenticate_aes(tag, 0, key);
|
||||
cut_assert_success("mifare_desfire_authenticate");
|
||||
free(key);
|
||||
|
||||
res = mifare_desfire_create_std_data_file (tag, 1, MDCM_MACED, 0x0000, 512);
|
||||
if ((mifare_desfire_last_picc_error (tag) != DUPLICATE_ERROR) && (mifare_desfire_last_picc_error(tag) != OPERATION_OK))
|
||||
cut_assert_success ("mifare_desfire_create_std_data_file");
|
||||
res = mifare_desfire_create_std_data_file(tag, 1, MDCM_MACED, 0x0000, 512);
|
||||
if ((mifare_desfire_last_picc_error(tag) != DUPLICATE_ERROR) && (mifare_desfire_last_picc_error(tag) != OPERATION_OK))
|
||||
cut_assert_success("mifare_desfire_create_std_data_file");
|
||||
|
||||
char sample_data[] = "Hello World! I'm a string that is probably too long "
|
||||
"to feet in a single frame. For this reason, it will be split and like"
|
||||
"ly, some failure in the algorirthm should trigger an error in this uni"
|
||||
"t test.";
|
||||
res = mifare_desfire_write_data_ex (tag, 1, 0, strlen (sample_data), sample_data, MDCM_MACED);
|
||||
cut_assert_success ("mifare_desfire_write_data");
|
||||
"to feet in a single frame. For this reason, it will be split and like"
|
||||
"ly, some failure in the algorirthm should trigger an error in this uni"
|
||||
"t test.";
|
||||
res = mifare_desfire_write_data_ex(tag, 1, 0, strlen(sample_data), sample_data, MDCM_MACED);
|
||||
cut_assert_success("mifare_desfire_write_data");
|
||||
|
||||
char buffer[1024];
|
||||
|
||||
res = mifare_desfire_read_data_ex (tag, 1, 0, 27, buffer, MDCM_MACED);
|
||||
cut_assert_success ("mifare_desfire_read_data");
|
||||
cut_assert_equal_memory (buffer, res, sample_data, 27, cut_message ("AES crypto failed"));
|
||||
res = mifare_desfire_read_data_ex(tag, 1, 0, 27, buffer, MDCM_MACED);
|
||||
cut_assert_success("mifare_desfire_read_data");
|
||||
cut_assert_equal_memory(buffer, res, sample_data, 27, cut_message("AES crypto failed"));
|
||||
|
||||
char canaries[] = "Canaries Canaries Canaries Canaries Canaries";
|
||||
|
||||
res = mifare_desfire_read_data_ex (tag, 1, 0, 1, canaries, MDCM_MACED);
|
||||
cut_assert_success ("mifare_desfire_read_data");
|
||||
cut_assert_equal_int (1, res, cut_message ("Reading 1 byte should return 1 byte"));
|
||||
cut_assert_equal_memory (canaries, 44, "Hanaries Canaries Canaries Canaries Canaries", 44, cut_message ("Canaries got smashed!"));
|
||||
res = mifare_desfire_read_data_ex(tag, 1, 0, 1, canaries, MDCM_MACED);
|
||||
cut_assert_success("mifare_desfire_read_data");
|
||||
cut_assert_equal_int(1, res, cut_message("Reading 1 byte should return 1 byte"));
|
||||
cut_assert_equal_memory(canaries, 44, "Hanaries Canaries Canaries Canaries Canaries", 44, cut_message("Canaries got smashed!"));
|
||||
|
||||
uint8_t s, c;
|
||||
res = mifare_desfire_get_key_settings (tag, &s, &c);
|
||||
cut_assert_success ("mifare_desfire_get__key_settings");
|
||||
res = mifare_desfire_get_key_settings(tag, &s, &c);
|
||||
cut_assert_success("mifare_desfire_get__key_settings");
|
||||
|
||||
res = mifare_desfire_read_data_ex (tag, 1, 27, 27, buffer, MDCM_MACED);
|
||||
cut_assert_success ("mifare_desfire_read_data");
|
||||
cut_assert_equal_memory (buffer, res, sample_data + 27, 27, cut_message ("AES crypto failed"));
|
||||
res = mifare_desfire_read_data_ex(tag, 1, 27, 27, buffer, MDCM_MACED);
|
||||
cut_assert_success("mifare_desfire_read_data");
|
||||
cut_assert_equal_memory(buffer, res, sample_data + 27, 27, cut_message("AES crypto failed"));
|
||||
|
||||
res = mifare_desfire_read_data_ex (tag, 1, 0, 0, buffer, MDCM_MACED);
|
||||
cut_assert_success ("mifare_desfire_read_data");
|
||||
cut_assert_equal_memory (buffer, strlen (buffer), sample_data, strlen (sample_data), cut_message ("AES crypto failed"));
|
||||
res = mifare_desfire_read_data_ex(tag, 1, 0, 0, buffer, MDCM_MACED);
|
||||
cut_assert_success("mifare_desfire_read_data");
|
||||
cut_assert_equal_memory(buffer, strlen(buffer), sample_data, strlen(sample_data), cut_message("AES crypto failed"));
|
||||
|
||||
// Revert to the default DES key
|
||||
res = mifare_desfire_select_application (tag, NULL);
|
||||
cut_assert_success ("mifare_desfire_select_application");
|
||||
res = mifare_desfire_select_application(tag, NULL);
|
||||
cut_assert_success("mifare_desfire_select_application");
|
||||
|
||||
key = mifare_desfire_aes_key_new_with_version (key_data_aes, key_data_aes_version);
|
||||
res = mifare_desfire_authenticate_aes (tag, 0, key);
|
||||
cut_assert_success ("mifare_desfire_authenticate");
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_aes_key_new_with_version(key_data_aes, key_data_aes_version);
|
||||
res = mifare_desfire_authenticate_aes(tag, 0, key);
|
||||
cut_assert_success("mifare_desfire_authenticate");
|
||||
mifare_desfire_key_free(key);
|
||||
|
||||
key = mifare_desfire_des_key_new (key_data_null);
|
||||
res = mifare_desfire_change_key (tag, 0x00, key, NULL);
|
||||
cut_assert_success ("mifare_desfire_change_key");
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_des_key_new(key_data_null);
|
||||
res = mifare_desfire_change_key(tag, 0x00, key, NULL);
|
||||
cut_assert_success("mifare_desfire_change_key");
|
||||
mifare_desfire_key_free(key);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2011, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -25,105 +25,105 @@
|
|||
|
||||
#define cut_assert_success(last_command) \
|
||||
do { \
|
||||
cut_assert_equal_int (OPERATION_OK, mifare_desfire_last_picc_error (tag), cut_message ("PICC replied %s", mifare_desfire_error_lookup (mifare_desfire_last_picc_error (tag)))); \
|
||||
cut_assert_not_equal_int (-1, res, cut_message ("Wrong return value")); \
|
||||
cut_assert_equal_int (OPERATION_OK, mifare_desfire_last_picc_error (tag), cut_message ("PICC replied %s", mifare_desfire_error_lookup (mifare_desfire_last_picc_error (tag)))); \
|
||||
cut_assert_not_equal_int (-1, res, cut_message ("Wrong return value")); \
|
||||
} while (0)
|
||||
|
||||
void
|
||||
test_mifare_desfire_ev1_iso (void)
|
||||
test_mifare_desfire_ev1_iso(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
mifare_desfire_auto_authenticate (tag, 0);
|
||||
mifare_desfire_auto_authenticate(tag, 0);
|
||||
|
||||
res = mifare_desfire_format_picc (tag);
|
||||
cut_assert_equal_int (res, 0, cut_message ("mifare_desfire_format_picc()"));
|
||||
res = mifare_desfire_format_picc(tag);
|
||||
cut_assert_equal_int(res, 0, cut_message("mifare_desfire_format_picc()"));
|
||||
|
||||
MifareDESFireDF *dfs;
|
||||
size_t count;
|
||||
res = mifare_desfire_get_df_names (tag, &dfs, &count);
|
||||
cut_assert_equal_int (res, 0, cut_message ("mifare_desfire_get_df_names()"));
|
||||
cut_assert_equal_int (count, 0, cut_message ("Wrong DF count"));
|
||||
cut_assert_null (dfs, cut_message ("DF should be NULL"));
|
||||
res = mifare_desfire_get_df_names(tag, &dfs, &count);
|
||||
cut_assert_equal_int(res, 0, cut_message("mifare_desfire_get_df_names()"));
|
||||
cut_assert_equal_int(count, 0, cut_message("Wrong DF count"));
|
||||
cut_assert_null(dfs, cut_message("DF should be NULL"));
|
||||
|
||||
MifareDESFireAID aid = mifare_desfire_aid_new (0x111110);
|
||||
res = mifare_desfire_create_application_iso (tag, aid, 0xFF, 1, 0, 0x111F, NULL, 0);
|
||||
cut_assert_success ("mifare_desfire_create_application_iso");
|
||||
free (aid);
|
||||
MifareDESFireAID aid = mifare_desfire_aid_new(0x111110);
|
||||
res = mifare_desfire_create_application_iso(tag, aid, 0xFF, 1, 0, 0x111F, NULL, 0);
|
||||
cut_assert_success("mifare_desfire_create_application_iso");
|
||||
free(aid);
|
||||
|
||||
uint8_t app2[] = "App2";
|
||||
aid = mifare_desfire_aid_new (0x222220);
|
||||
res = mifare_desfire_create_application_iso (tag, aid, 0xFF, 1, 0, 0x222F, app2, sizeof (app2));
|
||||
cut_assert_success ("mifare_desfire_create_application_iso");
|
||||
free (aid);
|
||||
aid = mifare_desfire_aid_new(0x222220);
|
||||
res = mifare_desfire_create_application_iso(tag, aid, 0xFF, 1, 0, 0x222F, app2, sizeof(app2));
|
||||
cut_assert_success("mifare_desfire_create_application_iso");
|
||||
free(aid);
|
||||
|
||||
uint8_t app3[] = "App3";
|
||||
aid = mifare_desfire_aid_new (0x333330);
|
||||
res = mifare_desfire_create_application_iso (tag, aid, 0xFF, 1, 0, 0x333F, app3, sizeof (app3));
|
||||
cut_assert_success ("mifare_desfire_create_application_iso");
|
||||
free (aid);
|
||||
aid = mifare_desfire_aid_new(0x333330);
|
||||
res = mifare_desfire_create_application_iso(tag, aid, 0xFF, 1, 0, 0x333F, app3, sizeof(app3));
|
||||
cut_assert_success("mifare_desfire_create_application_iso");
|
||||
free(aid);
|
||||
|
||||
aid = mifare_desfire_aid_new (0x444440);
|
||||
res = mifare_desfire_create_application_iso (tag, aid, 0xFF, 1, 0, 0x111F, NULL, 0);
|
||||
cut_assert_equal_int (-1, res, cut_message ("Should fail"));
|
||||
cut_assert_equal_int (DUPLICATE_ERROR, mifare_desfire_last_picc_error (tag), cut_message ("Should be a duplicate error"));
|
||||
aid = mifare_desfire_aid_new(0x444440);
|
||||
res = mifare_desfire_create_application_iso(tag, aid, 0xFF, 1, 0, 0x111F, NULL, 0);
|
||||
cut_assert_equal_int(-1, res, cut_message("Should fail"));
|
||||
cut_assert_equal_int(DUPLICATE_ERROR, mifare_desfire_last_picc_error(tag), cut_message("Should be a duplicate error"));
|
||||
|
||||
res = mifare_desfire_create_application_iso (tag, aid, 0xFF, 1, 0, 0x444F, app2, sizeof (app2));
|
||||
cut_assert_equal_int (-1, res, cut_message ("Should fail"));
|
||||
cut_assert_equal_int (DUPLICATE_ERROR, mifare_desfire_last_picc_error (tag), cut_message ("Should be a duplicate error"));
|
||||
free (aid);
|
||||
res = mifare_desfire_create_application_iso(tag, aid, 0xFF, 1, 0, 0x444F, app2, sizeof(app2));
|
||||
cut_assert_equal_int(-1, res, cut_message("Should fail"));
|
||||
cut_assert_equal_int(DUPLICATE_ERROR, mifare_desfire_last_picc_error(tag), cut_message("Should be a duplicate error"));
|
||||
free(aid);
|
||||
|
||||
|
||||
res = mifare_desfire_get_df_names (tag, &dfs, &count);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_desfire_get_df_names()"));
|
||||
cut_assert_equal_int (3, count, cut_message ("Wrong DF count"));
|
||||
cut_assert_not_null (dfs, cut_message ("DF should not be NULL"));
|
||||
res = mifare_desfire_get_df_names(tag, &dfs, &count);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_desfire_get_df_names()"));
|
||||
cut_assert_equal_int(3, count, cut_message("Wrong DF count"));
|
||||
cut_assert_not_null(dfs, cut_message("DF should not be NULL"));
|
||||
|
||||
cut_assert_equal_int (0x111110, dfs[0].aid, cut_message ("Wrong value"));
|
||||
cut_assert_equal_int (0x111F, dfs[0].fid, cut_message ("Wrong value"));
|
||||
cut_assert_equal_int (0, dfs[0].df_name_len, cut_message ("Wrong value"));
|
||||
cut_assert_equal_int(0x111110, dfs[0].aid, cut_message("Wrong value"));
|
||||
cut_assert_equal_int(0x111F, dfs[0].fid, cut_message("Wrong value"));
|
||||
cut_assert_equal_int(0, dfs[0].df_name_len, cut_message("Wrong value"));
|
||||
|
||||
cut_assert_equal_int (0x222220, dfs[1].aid, cut_message ("Wrong value"));
|
||||
cut_assert_equal_int (0x222F, dfs[1].fid, cut_message ("Wrong value"));
|
||||
cut_assert_equal_int (sizeof (app2), dfs[1].df_name_len, cut_message ("Wrong value"));
|
||||
cut_assert_equal_memory (app2, sizeof (app2), dfs[1].df_name, dfs[1].df_name_len, cut_message ("Wrong value"));
|
||||
cut_assert_equal_int(0x222220, dfs[1].aid, cut_message("Wrong value"));
|
||||
cut_assert_equal_int(0x222F, dfs[1].fid, cut_message("Wrong value"));
|
||||
cut_assert_equal_int(sizeof(app2), dfs[1].df_name_len, cut_message("Wrong value"));
|
||||
cut_assert_equal_memory(app2, sizeof(app2), dfs[1].df_name, dfs[1].df_name_len, cut_message("Wrong value"));
|
||||
|
||||
cut_assert_equal_int (0x333330, dfs[2].aid, cut_message ("Wrong value"));
|
||||
cut_assert_equal_int (0x333F, dfs[2].fid, cut_message ("Wrong value"));
|
||||
cut_assert_equal_int (sizeof (app3), dfs[2].df_name_len, cut_message ("Wrong value"));
|
||||
cut_assert_equal_memory (app3, sizeof (app3), dfs[2].df_name, dfs[2].df_name_len, cut_message ("Wrong value"));
|
||||
free (dfs);
|
||||
cut_assert_equal_int(0x333330, dfs[2].aid, cut_message("Wrong value"));
|
||||
cut_assert_equal_int(0x333F, dfs[2].fid, cut_message("Wrong value"));
|
||||
cut_assert_equal_int(sizeof(app3), dfs[2].df_name_len, cut_message("Wrong value"));
|
||||
cut_assert_equal_memory(app3, sizeof(app3), dfs[2].df_name, dfs[2].df_name_len, cut_message("Wrong value"));
|
||||
free(dfs);
|
||||
|
||||
aid = mifare_desfire_aid_new (0x555550);
|
||||
res = mifare_desfire_create_application_iso (tag, aid, 0xff, 1, 1, 0x555F, NULL, 0);
|
||||
cut_assert_success ("mifare_desfire_create_application_iso");
|
||||
aid = mifare_desfire_aid_new(0x555550);
|
||||
res = mifare_desfire_create_application_iso(tag, aid, 0xff, 1, 1, 0x555F, NULL, 0);
|
||||
cut_assert_success("mifare_desfire_create_application_iso");
|
||||
|
||||
res = mifare_desfire_select_application (tag, aid);
|
||||
cut_assert_success ("mifare_desfire_select_application");
|
||||
res = mifare_desfire_select_application(tag, aid);
|
||||
cut_assert_success("mifare_desfire_select_application");
|
||||
|
||||
res = mifare_desfire_create_std_data_file_iso (tag, 1, MDCM_PLAIN, 0xEEEE, 32, 0x1234);
|
||||
cut_assert_success ("mifare_desfire_create_std_data_file_iso");
|
||||
res = mifare_desfire_create_std_data_file_iso(tag, 1, MDCM_PLAIN, 0xEEEE, 32, 0x1234);
|
||||
cut_assert_success("mifare_desfire_create_std_data_file_iso");
|
||||
|
||||
res = mifare_desfire_create_backup_data_file_iso (tag, 2, MDCM_PLAIN, 0xEEEE, 32, 0x2345);
|
||||
cut_assert_success ("mifare_desfire_create_std_data_file_iso");
|
||||
res = mifare_desfire_create_backup_data_file_iso(tag, 2, MDCM_PLAIN, 0xEEEE, 32, 0x2345);
|
||||
cut_assert_success("mifare_desfire_create_std_data_file_iso");
|
||||
|
||||
res = mifare_desfire_create_linear_record_file_iso (tag, 3, MDCM_PLAIN, 0xEEEE, 32, 10, 0x3456);
|
||||
cut_assert_success ("mifare_desfire_create_linear_record_file_iso");
|
||||
res = mifare_desfire_create_linear_record_file_iso(tag, 3, MDCM_PLAIN, 0xEEEE, 32, 10, 0x3456);
|
||||
cut_assert_success("mifare_desfire_create_linear_record_file_iso");
|
||||
|
||||
res = mifare_desfire_create_cyclic_record_file_iso (tag, 4, MDCM_PLAIN, 0xEEEE, 32, 10, 0x4567);
|
||||
cut_assert_success ("mifare_desfire_create_cyclic_record_file_iso");
|
||||
res = mifare_desfire_create_cyclic_record_file_iso(tag, 4, MDCM_PLAIN, 0xEEEE, 32, 10, 0x4567);
|
||||
cut_assert_success("mifare_desfire_create_cyclic_record_file_iso");
|
||||
|
||||
uint16_t *ids;
|
||||
res = mifare_desfire_get_iso_file_ids (tag, &ids, &count);
|
||||
cut_assert_success ("mifare_desfire_get_iso_file_ids");
|
||||
res = mifare_desfire_get_iso_file_ids(tag, &ids, &count);
|
||||
cut_assert_success("mifare_desfire_get_iso_file_ids");
|
||||
|
||||
cut_assert_equal_int (4, count, cut_message ("Invalid file count"));
|
||||
cut_assert_equal_int (0x1234, ids[0], cut_message ("Wrong file ID"));
|
||||
cut_assert_equal_int (0x2345, ids[1], cut_message ("Wrong file ID"));
|
||||
cut_assert_equal_int (0x3456, ids[2], cut_message ("Wrong file ID"));
|
||||
cut_assert_equal_int (0x4567, ids[3], cut_message ("Wrong file ID"));
|
||||
free (ids);
|
||||
cut_assert_equal_int(4, count, cut_message("Invalid file count"));
|
||||
cut_assert_equal_int(0x1234, ids[0], cut_message("Wrong file ID"));
|
||||
cut_assert_equal_int(0x2345, ids[1], cut_message("Wrong file ID"));
|
||||
cut_assert_equal_int(0x3456, ids[2], cut_message("Wrong file ID"));
|
||||
cut_assert_equal_int(0x4567, ids[3], cut_message("Wrong file ID"));
|
||||
free(ids);
|
||||
|
||||
free (aid);
|
||||
free(aid);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -21,76 +21,76 @@
|
|||
|
||||
|
||||
void
|
||||
test_mifare_desfire_key (void)
|
||||
test_mifare_desfire_key(void)
|
||||
{
|
||||
MifareDESFireKey key;
|
||||
int version;
|
||||
|
||||
uint8_t key1_des_data[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
|
||||
|
||||
key = mifare_desfire_des_key_new (key1_des_data);
|
||||
version = mifare_desfire_key_get_version (key);
|
||||
cut_assert_equal_int (0x00, version, cut_message ("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_des_key_new(key1_des_data);
|
||||
version = mifare_desfire_key_get_version(key);
|
||||
cut_assert_equal_int(0x00, version, cut_message("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free(key);
|
||||
|
||||
key = mifare_desfire_des_key_new_with_version (key1_des_data);
|
||||
version = mifare_desfire_key_get_version (key);
|
||||
cut_assert_equal_int (0x55, version, cut_message ("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_set_version (key, 0xaa);
|
||||
version = mifare_desfire_key_get_version (key);
|
||||
cut_assert_equal_int (0xaa, version, cut_message ("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_des_key_new_with_version(key1_des_data);
|
||||
version = mifare_desfire_key_get_version(key);
|
||||
cut_assert_equal_int(0x55, version, cut_message("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_set_version(key, 0xaa);
|
||||
version = mifare_desfire_key_get_version(key);
|
||||
cut_assert_equal_int(0xaa, version, cut_message("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free(key);
|
||||
|
||||
|
||||
uint8_t key2_des_data[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
key = mifare_desfire_des_key_new (key2_des_data);
|
||||
version = mifare_desfire_key_get_version (key);
|
||||
cut_assert_equal_int (0x00, version, cut_message ("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_des_key_new(key2_des_data);
|
||||
version = mifare_desfire_key_get_version(key);
|
||||
cut_assert_equal_int(0x00, version, cut_message("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free(key);
|
||||
|
||||
key = mifare_desfire_des_key_new_with_version (key2_des_data);
|
||||
version = mifare_desfire_key_get_version (key);
|
||||
cut_assert_equal_int (0x00, version, cut_message ("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_des_key_new_with_version(key2_des_data);
|
||||
version = mifare_desfire_key_get_version(key);
|
||||
cut_assert_equal_int(0x00, version, cut_message("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free(key);
|
||||
|
||||
|
||||
uint8_t key1_3des_data[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0XEE, 0xFF };
|
||||
|
||||
key = mifare_desfire_3des_key_new (key1_3des_data);
|
||||
version = mifare_desfire_key_get_version (key);
|
||||
cut_assert_equal_int (0x00, version, cut_message ("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_3des_key_new(key1_3des_data);
|
||||
version = mifare_desfire_key_get_version(key);
|
||||
cut_assert_equal_int(0x00, version, cut_message("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free(key);
|
||||
|
||||
key = mifare_desfire_3des_key_new_with_version (key1_3des_data);
|
||||
version = mifare_desfire_key_get_version (key);
|
||||
cut_assert_equal_int (0x55, version, cut_message ("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_set_version (key, 0xaa);
|
||||
version = mifare_desfire_key_get_version (key);
|
||||
cut_assert_equal_int (0xaa, version, cut_message ("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_3des_key_new_with_version(key1_3des_data);
|
||||
version = mifare_desfire_key_get_version(key);
|
||||
cut_assert_equal_int(0x55, version, cut_message("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_set_version(key, 0xaa);
|
||||
version = mifare_desfire_key_get_version(key);
|
||||
cut_assert_equal_int(0xaa, version, cut_message("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free(key);
|
||||
|
||||
uint8_t key2_3des_data[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0X01, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
|
||||
|
||||
key = mifare_desfire_3des_key_new (key2_3des_data);
|
||||
version = mifare_desfire_key_get_version (key);
|
||||
cut_assert_equal_int (0x00, version, cut_message ("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_3des_key_new(key2_3des_data);
|
||||
version = mifare_desfire_key_get_version(key);
|
||||
cut_assert_equal_int(0x00, version, cut_message("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free(key);
|
||||
|
||||
key = mifare_desfire_3des_key_new_with_version (key2_3des_data);
|
||||
version = mifare_desfire_key_get_version (key);
|
||||
cut_assert_equal_int (0x02, version, cut_message ("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_3des_key_new_with_version(key2_3des_data);
|
||||
version = mifare_desfire_key_get_version(key);
|
||||
cut_assert_equal_int(0x02, version, cut_message("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free(key);
|
||||
|
||||
uint8_t key3_3des_data[16] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0X00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77 };
|
||||
|
||||
key = mifare_desfire_3des_key_new (key3_3des_data);
|
||||
version = mifare_desfire_key_get_version (key);
|
||||
cut_assert_equal_int (0x00, version, cut_message ("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_3des_key_new(key3_3des_data);
|
||||
version = mifare_desfire_key_get_version(key);
|
||||
cut_assert_equal_int(0x00, version, cut_message("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free(key);
|
||||
|
||||
key = mifare_desfire_3des_key_new_with_version (key3_3des_data);
|
||||
version = mifare_desfire_key_get_version (key);
|
||||
cut_assert_equal_int (0x10, version, cut_message ("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_3des_key_new_with_version(key3_3des_data);
|
||||
version = mifare_desfire_key_get_version(key);
|
||||
cut_assert_equal_int(0x10, version, cut_message("Wrong MifareDESFireKey version"));
|
||||
mifare_desfire_key_free(key);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -25,7 +25,7 @@
|
|||
#include "mifare_ultralight_fixture.h"
|
||||
|
||||
void
|
||||
test_mifare_ultralight_write (void)
|
||||
test_mifare_ultralight_write(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
@ -37,158 +37,158 @@ test_mifare_ultralight_write (void)
|
|||
MifareUltralightPageNumber n = 7;
|
||||
|
||||
/* Read and save current value (should be { 0x00 0x00 0x00 0x00 }) */
|
||||
res = mifare_ultralight_read (tag, n, &initial);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_ultralight_read() failed"));
|
||||
res = mifare_ultralight_read(tag, n, &initial);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_read() failed"));
|
||||
|
||||
/* Write payload1 */
|
||||
res = mifare_ultralight_write (tag, n, payload1);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_ultralight_write() failed"));
|
||||
res = mifare_ultralight_write(tag, n, payload1);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_write() failed"));
|
||||
|
||||
/* Check it */
|
||||
res = mifare_ultralight_read (tag, n, &page);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_ultralight_read() failed"));
|
||||
cut_assert_equal_memory (payload1, sizeof (payload1), page, sizeof (page), cut_message ("Wrong data"));
|
||||
res = mifare_ultralight_read(tag, n, &page);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_read() failed"));
|
||||
cut_assert_equal_memory(payload1, sizeof(payload1), page, sizeof(page), cut_message("Wrong data"));
|
||||
|
||||
/* Write payload2 */
|
||||
res = mifare_ultralight_write (tag, n, payload2);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_ultralight_write() failed"));
|
||||
res = mifare_ultralight_write(tag, n, payload2);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_write() failed"));
|
||||
|
||||
/* Check it */
|
||||
res = mifare_ultralight_read (tag, n, &page);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_ultralight_read() failed"));
|
||||
cut_assert_equal_memory (payload2, sizeof (payload2), page, sizeof (page), cut_message ("Wrong data"));
|
||||
res = mifare_ultralight_read(tag, n, &page);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_read() failed"));
|
||||
cut_assert_equal_memory(payload2, sizeof(payload2), page, sizeof(page), cut_message("Wrong data"));
|
||||
|
||||
/* Write initial data */
|
||||
res = mifare_ultralight_write (tag, n, initial);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_ultralight_write() failed"));
|
||||
res = mifare_ultralight_write(tag, n, initial);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_write() failed"));
|
||||
|
||||
/* While here check it (no reason to fail since the rest of the test passed) */
|
||||
res = mifare_ultralight_read (tag, n, &page);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_ultralight_read() failed"));
|
||||
cut_assert_equal_memory (initial, sizeof (initial), page, sizeof (page), cut_message ("Wrong data"));
|
||||
res = mifare_ultralight_read(tag, n, &page);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_read() failed"));
|
||||
cut_assert_equal_memory(initial, sizeof(initial), page, sizeof(page), cut_message("Wrong data"));
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_ultralight_invalid_page (void)
|
||||
test_mifare_ultralight_invalid_page(void)
|
||||
{
|
||||
int res;
|
||||
MifareUltralightPage page = { 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
int invalid_page;
|
||||
if (is_mifare_ultralightc (tag)) {
|
||||
invalid_page = MIFARE_ULTRALIGHT_C_PAGE_COUNT;
|
||||
if (is_mifare_ultralightc(tag)) {
|
||||
invalid_page = MIFARE_ULTRALIGHT_C_PAGE_COUNT;
|
||||
} else {
|
||||
invalid_page = MIFARE_ULTRALIGHT_PAGE_COUNT;
|
||||
invalid_page = MIFARE_ULTRALIGHT_PAGE_COUNT;
|
||||
}
|
||||
res = mifare_ultralight_read (tag, invalid_page, &page);
|
||||
cut_assert_equal_int (-1, res, cut_message ("mifare_ultralight_read() succeeded"));
|
||||
cut_assert_equal_int (EINVAL, errno, cut_message ("Wrong errno value"));
|
||||
res = mifare_ultralight_read(tag, invalid_page, &page);
|
||||
cut_assert_equal_int(-1, res, cut_message("mifare_ultralight_read() succeeded"));
|
||||
cut_assert_equal_int(EINVAL, errno, cut_message("Wrong errno value"));
|
||||
|
||||
res = mifare_ultralight_write (tag, invalid_page, page);
|
||||
cut_assert_equal_int (-1, res, cut_message ("mifare_ultralight_write() succeeded"));
|
||||
cut_assert_equal_int (EINVAL, errno, cut_message ("Wrong errno value"));
|
||||
res = mifare_ultralight_write(tag, invalid_page, page);
|
||||
cut_assert_equal_int(-1, res, cut_message("mifare_ultralight_write() succeeded"));
|
||||
cut_assert_equal_int(EINVAL, errno, cut_message("Wrong errno value"));
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_ultralight_cache (void)
|
||||
test_mifare_ultralight_cache(void)
|
||||
{
|
||||
int res;
|
||||
MifareUltralightPage page;
|
||||
|
||||
res = mifare_ultralight_read (tag, 0, &page);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_ultralight_read() failed"));
|
||||
res = mifare_ultralight_read(tag, 0, &page);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_read() failed"));
|
||||
|
||||
/* Check cached pages consistency */
|
||||
for (int i = 0; i <= 3; i++) {
|
||||
cut_assert_equal_int (1, MIFARE_ULTRALIGHT(tag)->cached_pages[i], cut_message ("Wrong page cache value for tag->cached_pages[%d]", i));
|
||||
cut_assert_equal_int(1, MIFARE_ULTRALIGHT(tag)->cached_pages[i], cut_message("Wrong page cache value for tag->cached_pages[%d]", i));
|
||||
}
|
||||
for (int i = 4; i < MIFARE_ULTRALIGHT_PAGE_COUNT; i++) {
|
||||
cut_assert_equal_int (0, MIFARE_ULTRALIGHT(tag)->cached_pages[i], cut_message ("Wrong page cache value for tag->cached_pages[%d]", i));
|
||||
cut_assert_equal_int(0, MIFARE_ULTRALIGHT(tag)->cached_pages[i], cut_message("Wrong page cache value for tag->cached_pages[%d]", i));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_ultralight_cache_hit (void)
|
||||
test_mifare_ultralight_cache_hit(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
MifareUltralightPage page1;
|
||||
MifareUltralightPage page2;
|
||||
|
||||
res = mifare_ultralight_read (tag, 0, &page1);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_ultralight_read() failed"));
|
||||
res = mifare_ultralight_read(tag, 0, &page1);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_read() failed"));
|
||||
|
||||
res = mifare_ultralight_read (tag, 0, &page2);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_ultralight_read() failed"));
|
||||
cut_assert_equal_memory (page1, sizeof (page1), page2, sizeof (page2), cut_message ("Wrong cached data"));
|
||||
res = mifare_ultralight_read(tag, 0, &page2);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_read() failed"));
|
||||
cut_assert_equal_memory(page1, sizeof(page1), page2, sizeof(page2), cut_message("Wrong cached data"));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
test_mifare_ultralight_cache_wrap (void)
|
||||
test_mifare_ultralight_cache_wrap(void)
|
||||
{
|
||||
int res;
|
||||
MifareUltralightPage page;
|
||||
int last_page;
|
||||
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
|
||||
cut_omit("mifare_ultralight_read() on last page skipped on UltralightC");
|
||||
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
|
||||
cut_omit("mifare_ultralight_read() on last page skipped on UltralightC");
|
||||
} else {
|
||||
last_page = MIFARE_ULTRALIGHT_PAGE_COUNT -1;
|
||||
last_page = MIFARE_ULTRALIGHT_PAGE_COUNT - 1;
|
||||
}
|
||||
res = mifare_ultralight_read (tag, last_page, &page);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_ultralight_read() failed"));
|
||||
res = mifare_ultralight_read(tag, last_page, &page);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_read() failed"));
|
||||
|
||||
/* Check cached pages consistency */
|
||||
for (int i = 0; i <= 2; i++) {
|
||||
cut_assert_equal_int (1, MIFARE_ULTRALIGHT(tag)->cached_pages[i], cut_message ("Wrong page cache value for tag->cached_pages[%d]", i));
|
||||
cut_assert_equal_int(1, MIFARE_ULTRALIGHT(tag)->cached_pages[i], cut_message("Wrong page cache value for tag->cached_pages[%d]", i));
|
||||
}
|
||||
for (int i = 3; i < last_page; i++) {
|
||||
cut_assert_equal_int (0, MIFARE_ULTRALIGHT(tag)->cached_pages[i], cut_message ("Wrong page cache value for tag->cached_pages[%d]", i));
|
||||
cut_assert_equal_int(0, MIFARE_ULTRALIGHT(tag)->cached_pages[i], cut_message("Wrong page cache value for tag->cached_pages[%d]", i));
|
||||
}
|
||||
cut_assert_equal_int (1, MIFARE_ULTRALIGHT(tag)->cached_pages[last_page], cut_message ("Wrong page cache value for tag->cached_pages[%d]", last_page));
|
||||
cut_assert_equal_int(1, MIFARE_ULTRALIGHT(tag)->cached_pages[last_page], cut_message("Wrong page cache value for tag->cached_pages[%d]", last_page));
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_ultralight_get_uid (void)
|
||||
test_mifare_ultralight_get_uid(void)
|
||||
{
|
||||
char *uid;
|
||||
|
||||
uid = freefare_get_tag_uid (tag);
|
||||
uid = freefare_get_tag_uid(tag);
|
||||
|
||||
cut_assert_not_null (uid, cut_message ("mifare_ultralight_get_uid() failed"));
|
||||
cut_assert_equal_int (14, strlen (uid), cut_message ("Wrong UID length"));
|
||||
cut_assert_not_null(uid, cut_message("mifare_ultralight_get_uid() failed"));
|
||||
cut_assert_equal_int(14, strlen(uid), cut_message("Wrong UID length"));
|
||||
|
||||
free (uid);
|
||||
free(uid);
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_ultralight_tag_friendly_name (void)
|
||||
test_mifare_ultralight_tag_friendly_name(void)
|
||||
{
|
||||
const char *name = freefare_get_tag_friendly_name (tag);
|
||||
const char *name = freefare_get_tag_friendly_name(tag);
|
||||
|
||||
cut_assert_not_null (name, cut_message ("freefare_get_tag_friendly_name() failed"));
|
||||
cut_assert_not_null(name, cut_message("freefare_get_tag_friendly_name() failed"));
|
||||
}
|
||||
|
||||
void
|
||||
test_mifare_ultralightc_authenticate (void)
|
||||
test_mifare_ultralightc_authenticate(void)
|
||||
{
|
||||
int res;
|
||||
MifareDESFireKey key;
|
||||
|
||||
if (is_mifare_ultralightc (tag)) {
|
||||
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);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_ultralightc_authenticate() failed"));
|
||||
mifare_desfire_key_free (key);
|
||||
key = mifare_desfire_3des_key_new(key1_3des_data);
|
||||
res = mifare_ultralightc_authenticate(tag, key);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_ultralightc_authenticate() failed"));
|
||||
mifare_desfire_key_free(key);
|
||||
|
||||
MifareUltralightPage page;
|
||||
int last_page = MIFARE_ULTRALIGHT_C_PAGE_COUNT_READ -1;
|
||||
res = mifare_ultralight_read (tag, last_page, &page);
|
||||
cut_assert_equal_int (0, res, cut_message ("mifare_ultralight_read() failed"));
|
||||
int last_page = MIFARE_ULTRALIGHT_C_PAGE_COUNT_READ - 1;
|
||||
res = mifare_ultralight_read(tag, last_page, &page);
|
||||
cut_assert_equal_int(0, res, cut_message("mifare_ultralight_read() failed"));
|
||||
} else {
|
||||
cut_omit("mifare_ultralightc_authenticate() skipped on Ultralight");
|
||||
}
|
||||
|
|
142
test/test_tlv.c
142
test/test_tlv.c
|
@ -1,11 +1,11 @@
|
|||
/*-
|
||||
* Copyright (C) 2010, Romain Tartiere, Romuald Conty.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
|
@ -28,120 +28,120 @@ const uint8_t eshortdata[11] = "\x03" "\x08" "elephant" "\xfe";
|
|||
* OS / compiler does not support UTF-8 ;-)
|
||||
*/
|
||||
const uint8_t longdata[660] = "Dans une terre grasse et pleine d'escargots\n" \
|
||||
"Je veux creuser moi-même une fosse profonde,\n" \
|
||||
"Où je puisse à loisir étaler mes vieux os\n" \
|
||||
"Et dormir dans l'oubli comme un requin dans l'onde.\n" \
|
||||
"Je hais les testaments et je hais les tombeaux;\n" \
|
||||
"Plutôt que d'implorer une larme du monde,\n" \
|
||||
"Vivant, j'aimerais mieux inviter les corbeaux\n" \
|
||||
"À saigner tous les bouts de ma carcasse immonde.\n" \
|
||||
"Ô vers! noirs compagnons sans oreille et sans yeux,\n" \
|
||||
"Voyez venir à vous un mort libre et joyeux;\n" \
|
||||
"Philosophes viveurs, fils de la pourriture,\n" \
|
||||
"À travers ma ruine allez donc sans remords,\n" \
|
||||
"Et dites-moi s'il est encor quelque torture\n" \
|
||||
"Pour ce vieux corps sans âme et mort parmi les morts!\n";
|
||||
"Je veux creuser moi-même une fosse profonde,\n" \
|
||||
"Où je puisse à loisir étaler mes vieux os\n" \
|
||||
"Et dormir dans l'oubli comme un requin dans l'onde.\n" \
|
||||
"Je hais les testaments et je hais les tombeaux;\n" \
|
||||
"Plutôt que d'implorer une larme du monde,\n" \
|
||||
"Vivant, j'aimerais mieux inviter les corbeaux\n" \
|
||||
"À saigner tous les bouts de ma carcasse immonde.\n" \
|
||||
"Ô vers! noirs compagnons sans oreille et sans yeux,\n" \
|
||||
"Voyez venir à vous un mort libre et joyeux;\n" \
|
||||
"Philosophes viveurs, fils de la pourriture,\n" \
|
||||
"À travers ma ruine allez donc sans remords,\n" \
|
||||
"Et dites-moi s'il est encor quelque torture\n" \
|
||||
"Pour ce vieux corps sans âme et mort parmi les morts!\n";
|
||||
|
||||
const uint8_t elongdata[665] = "\x07" "\xff\x02\x94" \
|
||||
"Dans une terre grasse et pleine d'escargots\n" \
|
||||
"Je veux creuser moi-même une fosse profonde,\n" \
|
||||
"Où je puisse à loisir étaler mes vieux os\n" \
|
||||
"Et dormir dans l'oubli comme un requin dans l'onde.\n" \
|
||||
"Je hais les testaments et je hais les tombeaux;\n" \
|
||||
"Plutôt que d'implorer une larme du monde,\n" \
|
||||
"Vivant, j'aimerais mieux inviter les corbeaux\n" \
|
||||
"À saigner tous les bouts de ma carcasse immonde.\n" \
|
||||
"Ô vers! noirs compagnons sans oreille et sans yeux,\n" \
|
||||
"Voyez venir à vous un mort libre et joyeux;\n" \
|
||||
"Philosophes viveurs, fils de la pourriture,\n" \
|
||||
"À travers ma ruine allez donc sans remords,\n" \
|
||||
"Et dites-moi s'il est encor quelque torture\n" \
|
||||
"Pour ce vieux corps sans âme et mort parmi les morts!\n"
|
||||
"\xfe";
|
||||
"Dans une terre grasse et pleine d'escargots\n" \
|
||||
"Je veux creuser moi-même une fosse profonde,\n" \
|
||||
"Où je puisse à loisir étaler mes vieux os\n" \
|
||||
"Et dormir dans l'oubli comme un requin dans l'onde.\n" \
|
||||
"Je hais les testaments et je hais les tombeaux;\n" \
|
||||
"Plutôt que d'implorer une larme du monde,\n" \
|
||||
"Vivant, j'aimerais mieux inviter les corbeaux\n" \
|
||||
"À saigner tous les bouts de ma carcasse immonde.\n" \
|
||||
"Ô vers! noirs compagnons sans oreille et sans yeux,\n" \
|
||||
"Voyez venir à vous un mort libre et joyeux;\n" \
|
||||
"Philosophes viveurs, fils de la pourriture,\n" \
|
||||
"À travers ma ruine allez donc sans remords,\n" \
|
||||
"Et dites-moi s'il est encor quelque torture\n" \
|
||||
"Pour ce vieux corps sans âme et mort parmi les morts!\n"
|
||||
"\xfe";
|
||||
|
||||
void
|
||||
test_tlv_encode_short (void)
|
||||
test_tlv_encode_short(void)
|
||||
{
|
||||
uint8_t *res;
|
||||
size_t osize;
|
||||
|
||||
res = tlv_encode (3, shortdata, sizeof (shortdata), &osize);
|
||||
cut_assert_equal_int (sizeof (eshortdata), osize, cut_message ("Wrong encoded message length."));
|
||||
cut_assert_equal_int (3, res[0], cut_message ("Wrong type"));
|
||||
cut_assert_equal_int (sizeof (shortdata), res[1], cut_message ("Wrong value length"));
|
||||
cut_assert_equal_memory (eshortdata, sizeof (eshortdata), res, osize, cut_message ("Wrong encoded value"));
|
||||
free (res);
|
||||
res = tlv_encode(3, shortdata, sizeof(shortdata), &osize);
|
||||
cut_assert_equal_int(sizeof(eshortdata), osize, cut_message("Wrong encoded message length."));
|
||||
cut_assert_equal_int(3, res[0], cut_message("Wrong type"));
|
||||
cut_assert_equal_int(sizeof(shortdata), res[1], cut_message("Wrong value length"));
|
||||
cut_assert_equal_memory(eshortdata, sizeof(eshortdata), res, osize, cut_message("Wrong encoded value"));
|
||||
free(res);
|
||||
}
|
||||
|
||||
void
|
||||
test_tlv_encode_long (void)
|
||||
test_tlv_encode_long(void)
|
||||
{
|
||||
uint8_t *res;
|
||||
size_t osize;
|
||||
|
||||
res = tlv_encode (7, longdata, sizeof (longdata), &osize);
|
||||
cut_assert_equal_int (sizeof (elongdata), osize, cut_message ("Wrong encoded message length."));
|
||||
cut_assert_equal_int (7, res[0], cut_message ("Wrong type"));
|
||||
cut_assert_equal_int (0xff, res[1], cut_message ("Wrong value length"));
|
||||
cut_assert_equal_int (0x02, res[2], cut_message ("Wrong value length"));
|
||||
cut_assert_equal_int (0x94, res[3], cut_message ("Wrong value length"));
|
||||
cut_assert_equal_memory (elongdata, sizeof (elongdata), res, osize, cut_message ("Wrong encoded value"));
|
||||
free (res);
|
||||
res = tlv_encode(7, longdata, sizeof(longdata), &osize);
|
||||
cut_assert_equal_int(sizeof(elongdata), osize, cut_message("Wrong encoded message length."));
|
||||
cut_assert_equal_int(7, res[0], cut_message("Wrong type"));
|
||||
cut_assert_equal_int(0xff, res[1], cut_message("Wrong value length"));
|
||||
cut_assert_equal_int(0x02, res[2], cut_message("Wrong value length"));
|
||||
cut_assert_equal_int(0x94, res[3], cut_message("Wrong value length"));
|
||||
cut_assert_equal_memory(elongdata, sizeof(elongdata), res, osize, cut_message("Wrong encoded value"));
|
||||
free(res);
|
||||
}
|
||||
|
||||
void
|
||||
test_tlv_decode_short (void)
|
||||
test_tlv_decode_short(void)
|
||||
{
|
||||
uint8_t *res;
|
||||
uint16_t size;
|
||||
uint8_t type;
|
||||
|
||||
res = tlv_decode (eshortdata, &type, &size);
|
||||
cut_assert_equal_int (3, type, cut_message ("Wrong type"));
|
||||
cut_assert_equal_int (sizeof (shortdata), size, cut_message ("Wrong value length"));
|
||||
cut_assert_equal_memory (shortdata, sizeof (shortdata), res, size, cut_message ("Wrong decoded value"));
|
||||
free (res);
|
||||
res = tlv_decode(eshortdata, &type, &size);
|
||||
cut_assert_equal_int(3, type, cut_message("Wrong type"));
|
||||
cut_assert_equal_int(sizeof(shortdata), size, cut_message("Wrong value length"));
|
||||
cut_assert_equal_memory(shortdata, sizeof(shortdata), res, size, cut_message("Wrong decoded value"));
|
||||
free(res);
|
||||
}
|
||||
|
||||
void
|
||||
test_tlv_decode_long (void)
|
||||
test_tlv_decode_long(void)
|
||||
{
|
||||
uint8_t *res;
|
||||
uint16_t size;
|
||||
uint8_t type;
|
||||
|
||||
res = tlv_decode (elongdata, &type, &size);
|
||||
cut_assert_equal_int (7, type, cut_message ("Wrong type"));
|
||||
cut_assert_equal_int (sizeof (longdata), size, cut_message ("Wrong value length"));
|
||||
cut_assert_equal_memory (longdata, sizeof (longdata), res, size, cut_message ("Wrong decoded value"));
|
||||
free (res);
|
||||
res = tlv_decode(elongdata, &type, &size);
|
||||
cut_assert_equal_int(7, type, cut_message("Wrong type"));
|
||||
cut_assert_equal_int(sizeof(longdata), size, cut_message("Wrong value length"));
|
||||
cut_assert_equal_memory(longdata, sizeof(longdata), res, size, cut_message("Wrong decoded value"));
|
||||
free(res);
|
||||
}
|
||||
|
||||
void
|
||||
test_tlv_rfu (void)
|
||||
test_tlv_rfu(void)
|
||||
{
|
||||
uint8_t *data = malloc (0xffff);
|
||||
cut_assert_not_null (data, cut_message ("Out of memory"));
|
||||
uint8_t *data = malloc(0xffff);
|
||||
cut_assert_not_null(data, cut_message("Out of memory"));
|
||||
|
||||
uint8_t *res = tlv_encode (7, data, 0xffff, NULL);
|
||||
cut_assert_null (res, cut_message ("Size reserved for future use"));
|
||||
uint8_t *res = tlv_encode(7, data, 0xffff, NULL);
|
||||
cut_assert_null(res, cut_message("Size reserved for future use"));
|
||||
|
||||
free (data);
|
||||
free(data);
|
||||
}
|
||||
|
||||
void
|
||||
test_tlv_append (void)
|
||||
test_tlv_append(void)
|
||||
{
|
||||
const uint8_t a[] = { 0xde, 0xad, 0xbe, 0xef };
|
||||
const uint8_t b[] = { 0x42 };
|
||||
|
||||
uint8_t ndef_ab_ref[] = { 0x03, 0x04, 0xde, 0xad, 0xbe, 0xef, 0x03, 0x01, 0x42, 0xfe };
|
||||
|
||||
uint8_t *ndef_a = tlv_encode (3, a, 4, NULL);
|
||||
uint8_t *ndef_b = tlv_encode (3, b, 1, NULL);
|
||||
ndef_a = tlv_append (ndef_a, ndef_b);
|
||||
cut_assert_equal_memory (ndef_ab_ref, sizeof (ndef_ab_ref), ndef_a, sizeof (ndef_ab_ref), cut_message ("Wrong appended data"));
|
||||
uint8_t *ndef_a = tlv_encode(3, a, 4, NULL);
|
||||
uint8_t *ndef_b = tlv_encode(3, b, 1, NULL);
|
||||
ndef_a = tlv_append(ndef_a, ndef_b);
|
||||
cut_assert_equal_memory(ndef_ab_ref, sizeof(ndef_ab_ref), ndef_a, sizeof(ndef_ab_ref), cut_message("Wrong appended data"));
|
||||
|
||||
free (ndef_a);
|
||||
free (ndef_b);
|
||||
free(ndef_a);
|
||||
free(ndef_b);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue