New API functions mad_application_read(), mad_application_write().
This commit is contained in:
parent
9e5820b89e
commit
dbd3682174
6 changed files with 200 additions and 2 deletions
2
NEWS
2
NEWS
|
@ -10,4 +10,4 @@ Changes between 0.1.0 and x.x.x [xx XXX xxxx]
|
||||||
*) New API functions mifare_classic_block_sector(),
|
*) New API functions mifare_classic_block_sector(),
|
||||||
mifare_classic_sector_first_block(), mifare_classic_sector_block_count()
|
mifare_classic_sector_first_block(), mifare_classic_sector_block_count()
|
||||||
and mifare_classic_sector_last_block().
|
and mifare_classic_sector_last_block().
|
||||||
|
*) New API functions mad_application_read(), mad_application_write().
|
||||||
|
|
|
@ -57,6 +57,8 @@ linkedman = \
|
||||||
mad.3 mad_get_aid.3 \
|
mad.3 mad_get_aid.3 \
|
||||||
mad.3 mad_set_aid.3 \
|
mad.3 mad_set_aid.3 \
|
||||||
mad.3 mad_free.3 \
|
mad.3 mad_free.3 \
|
||||||
|
mad.3 mad_application_read.3 \
|
||||||
|
mad.3 mad_application_write.3 \
|
||||||
mifare_application.3 mifare_application_alloc.3 \
|
mifare_application.3 mifare_application_alloc.3 \
|
||||||
mifare_application.3 mifare_application_free.3 \
|
mifare_application.3 mifare_application_free.3 \
|
||||||
mifare_application.3 mifare_application_find.3 \
|
mifare_application.3 mifare_application_find.3 \
|
||||||
|
|
|
@ -144,6 +144,8 @@ int mad_get_aid (Mad mad, MifareClassicSectorNumber sector, MadAid *aid);
|
||||||
int mad_set_aid (Mad mad, MifareClassicSectorNumber sector, MadAid aid);
|
int mad_set_aid (Mad mad, MifareClassicSectorNumber sector, MadAid aid);
|
||||||
bool mad_sector_reserved (MifareClassicSectorNumber sector);
|
bool mad_sector_reserved (MifareClassicSectorNumber sector);
|
||||||
void mad_free (Mad mad);
|
void mad_free (Mad mad);
|
||||||
|
ssize_t mad_application_read (MifareTag tag, Mad mad, MadAid aid, void *buf, size_t nbytes, MifareClassicKey key, MifareClassicKeyType key_type);
|
||||||
|
ssize_t mad_application_write (MifareTag tag, Mad mad, MadAid aid, const void *buf, size_t nbytes, MifareClassicKey key, MifareClassicKeyType key_type);
|
||||||
|
|
||||||
MifareClassicSectorNumber *mifare_application_alloc (Mad mad, MadAid aid, size_t size);
|
MifareClassicSectorNumber *mifare_application_alloc (Mad mad, MadAid aid, size_t size);
|
||||||
void mifare_application_free (Mad mad, MadAid aid);
|
void mifare_application_free (Mad mad, MadAid aid);
|
||||||
|
|
|
@ -34,7 +34,9 @@
|
||||||
.Nm mad_set_card_publisher_sector ,
|
.Nm mad_set_card_publisher_sector ,
|
||||||
.Nm mad_get_aid ,
|
.Nm mad_get_aid ,
|
||||||
.Nm mad_set_aid ,
|
.Nm mad_set_aid ,
|
||||||
.Nm mad_free
|
.Nm mad_free ,
|
||||||
|
.Nm mad_application_read ,
|
||||||
|
.Nm mad_application_write
|
||||||
.Nd "Mifare Application Directory (MAD) Manipulation Functions"
|
.Nd "Mifare Application Directory (MAD) Manipulation Functions"
|
||||||
.\" _ _ _
|
.\" _ _ _
|
||||||
.\" | | (_) |__ _ __ __ _ _ __ _ _
|
.\" | | (_) |__ _ __ __ _ _ __ _ _
|
||||||
|
@ -72,6 +74,10 @@ Mifare card manipulation library (libfreefare, \-lfreefare)
|
||||||
.Fn mad_set_aid "Mad mad" "MifareSectorNumber sector" "MadAid aid"
|
.Fn mad_set_aid "Mad mad" "MifareSectorNumber sector" "MadAid aid"
|
||||||
.Ft void
|
.Ft void
|
||||||
.Fn mad_free "Mad mad"
|
.Fn mad_free "Mad mad"
|
||||||
|
.Ft ssize_t
|
||||||
|
.Fn mad_application_read "MifareTag tag" "Mad mad" "MadAid aid" "void *buf" "size_t nbytes" "MifareClassicKey key" "MifareClassicKeyType key_type"
|
||||||
|
.Ft ssize_t
|
||||||
|
.Fn mad_application_write "MifareTag tag" "Mad mad" "MadAid aid" "const void *buf" size_t nbytes" "MifareClassicKey key" "MifareClassicKeyType key_type"
|
||||||
.\" ____ _ _ _
|
.\" ____ _ _ _
|
||||||
.\" | _ \ ___ ___ ___ _ __(_)_ __ | |_(_) ___ _ __
|
.\" | _ \ ___ ___ ___ _ __(_)_ __ | |_(_) ___ _ __
|
||||||
.\" | | | |/ _ \/ __|/ __| '__| | '_ \| __| |/ _ \| '_ \
|
.\" | | | |/ _ \/ __|/ __| '__| | '_ \| __| |/ _ \| '_ \
|
||||||
|
@ -141,6 +147,48 @@ functions. These functions fill-in or read the Application Identifier,
|
||||||
.Vt aid
|
.Vt aid
|
||||||
for the given
|
for the given
|
||||||
.Vt sector .
|
.Vt sector .
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn mad_application_read
|
||||||
|
reads at most
|
||||||
|
.Vt nbytes
|
||||||
|
of the application identified by
|
||||||
|
.Vt aid
|
||||||
|
in the
|
||||||
|
.Vt mad
|
||||||
|
on the
|
||||||
|
.Vt tag
|
||||||
|
and copy them into
|
||||||
|
.Vt buf.
|
||||||
|
The function returns the amount of data it copied, or -1 on error.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn mad_application_write
|
||||||
|
functions writes at most
|
||||||
|
.Vt nbytes
|
||||||
|
of
|
||||||
|
.Vt buf
|
||||||
|
in the application identified by
|
||||||
|
.Vt aid
|
||||||
|
on the
|
||||||
|
.Vt mad
|
||||||
|
of the
|
||||||
|
.Vt tag
|
||||||
|
and returns the quantity of data written, or -1 on error.
|
||||||
|
.\" ___ _ _ _ _ _
|
||||||
|
.\" |_ _|_ __ ___ _ __ | | ___ _ __ ___ ___ _ __ | |_ __ _| |_(_) ___ _ __ _ __ ___ | |_ ___ ___
|
||||||
|
.\" | || '_ ` _ \| '_ \| |/ _ \ '_ ` _ \ / _ \ '_ \| __/ _` | __| |/ _ \| '_ \ | '_ \ / _ \| __/ _ \/ __|
|
||||||
|
.\" | || | | | | | |_) | | __/ | | | | | __/ | | | || (_| | |_| | (_) | | | | | | | | (_) | || __/\__ \
|
||||||
|
.\" |___|_| |_| |_| .__/|_|\___|_| |_| |_|\___|_| |_|\__\__,_|\__|_|\___/|_| |_| |_| |_|\___/ \__\___||___/
|
||||||
|
.\" |_|
|
||||||
|
.Sh IMPLEMENTATION NOTES
|
||||||
|
The
|
||||||
|
.Vt nbytes
|
||||||
|
argument of
|
||||||
|
.Fn mad_application_read
|
||||||
|
and
|
||||||
|
.Fn mad_application_write
|
||||||
|
does not need to be aligned on blocks not sectors.
|
||||||
.\" ____ _ _
|
.\" ____ _ _
|
||||||
.\" | _ \ ___| |_ _ _ _ __ _ __ __ ____ _| |_ _ ___ ___
|
.\" | _ \ ___| |_ _ _ _ __ _ __ __ ____ _| |_ _ ___ ___
|
||||||
.\" | |_) / _ \ __| | | | '__| '_ \ \ \ / / _` | | | | |/ _ \/ __|
|
.\" | |_) / _ \ __| | | | '__| '_ \ \ \ / / _` | | | | |/ _ \/ __|
|
||||||
|
|
|
@ -46,6 +46,8 @@
|
||||||
#define SECTOR_0X00_AIDS 15
|
#define SECTOR_0X00_AIDS 15
|
||||||
#define SECTOR_0X10_AIDS 23
|
#define SECTOR_0X10_AIDS 23
|
||||||
|
|
||||||
|
#define MIN(a, b) ( (a < b) ? a : b )
|
||||||
|
|
||||||
struct mad_sector_0x00 {
|
struct mad_sector_0x00 {
|
||||||
uint8_t crc;
|
uint8_t crc;
|
||||||
uint8_t info;
|
uint8_t info;
|
||||||
|
@ -425,3 +427,101 @@ mad_free (Mad mad)
|
||||||
{
|
{
|
||||||
free (mad);
|
free (mad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
mad_application_read (MifareTag tag, Mad mad, MadAid aid, void *buf, size_t nbytes, MifareClassicKey key, MifareClassicKeyType key_type)
|
||||||
|
{
|
||||||
|
ssize_t res = 0;
|
||||||
|
|
||||||
|
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 b = first_block;
|
||||||
|
MifareClassicBlock block;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (mifare_classic_read (tag, b, &block) < 0) {
|
||||||
|
res = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memcpy ((uint8_t *)buf + res, &block, n);
|
||||||
|
|
||||||
|
nbytes -= n;
|
||||||
|
res += n;
|
||||||
|
|
||||||
|
b++;
|
||||||
|
}
|
||||||
|
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
free (sectors);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
mad_application_write (MifareTag tag, Mad mad, MadAid aid, const void *buf, size_t nbytes, MifareClassicKey key, MifareClassicKeyType key_type)
|
||||||
|
{
|
||||||
|
ssize_t res = 0;
|
||||||
|
|
||||||
|
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 b = first_block;
|
||||||
|
MifareClassicBlock block;
|
||||||
|
|
||||||
|
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);
|
||||||
|
// Avoid overwriting existing data with uninitialized memory.
|
||||||
|
if (n < 16) {
|
||||||
|
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) {
|
||||||
|
res = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nbytes -= n;
|
||||||
|
res += n;
|
||||||
|
|
||||||
|
b++;
|
||||||
|
}
|
||||||
|
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
free (sectors);
|
||||||
|
return res;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -78,6 +78,36 @@ test_mifare_classic_mad (void)
|
||||||
cut_assert_not_null (mad2, cut_message ("mad_read() failed"));
|
cut_assert_not_null (mad2, cut_message ("mad_read() failed"));
|
||||||
cut_assert_equal_memory (mad, sizeof (mad), mad2, sizeof (mad2), cut_message ("Wrong MAD"));
|
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 >> ";
|
||||||
|
|
||||||
|
MadAid aid = {
|
||||||
|
.function_cluster_code = 0x01,
|
||||||
|
.application_code = 0x12
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
res = mad_write (tag, mad, key_b_sector_00, NULL);
|
||||||
|
cut_assert_equal_int (0, res, cut_message ("mad_write() failed"));
|
||||||
|
|
||||||
|
ssize_t s = mad_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 ("mad_application_write() failed"));
|
||||||
|
|
||||||
|
char read_buf[500];
|
||||||
|
|
||||||
|
// Read it again
|
||||||
|
s = mad_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 ("mad_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 (mad);
|
||||||
mad_free (mad2);
|
mad_free (mad2);
|
||||||
|
|
||||||
|
@ -161,6 +191,22 @@ test_mifare_classic_mad (void)
|
||||||
cut_assert_not_null (mad2, cut_message ("mad_read() failed"));
|
cut_assert_not_null (mad2, cut_message ("mad_read() failed"));
|
||||||
cut_assert_equal_memory (mad, sizeof (mad), mad2, sizeof (mad2), cut_message ("Wrong MAD"));
|
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);
|
||||||
|
|
||||||
|
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 = mad_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 ("mad_application_write() failed"));
|
||||||
|
|
||||||
|
// Read it again
|
||||||
|
s = mad_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 ("mad_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 (mad);
|
||||||
mad_free (mad2);
|
mad_free (mad2);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue