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(),
|
||||
mifare_classic_sector_first_block(), mifare_classic_sector_block_count()
|
||||
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_set_aid.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_free.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);
|
||||
bool mad_sector_reserved (MifareClassicSectorNumber sector);
|
||||
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);
|
||||
void mifare_application_free (Mad mad, MadAid aid);
|
||||
|
|
|
@ -34,7 +34,9 @@
|
|||
.Nm mad_set_card_publisher_sector ,
|
||||
.Nm mad_get_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"
|
||||
.\" _ _ _
|
||||
.\" | | (_) |__ _ __ __ _ _ __ _ _
|
||||
|
@ -72,6 +74,10 @@ Mifare card manipulation library (libfreefare, \-lfreefare)
|
|||
.Fn mad_set_aid "Mad mad" "MifareSectorNumber sector" "MadAid aid"
|
||||
.Ft void
|
||||
.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
|
||||
for the given
|
||||
.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_0X10_AIDS 23
|
||||
|
||||
#define MIN(a, b) ( (a < b) ? a : b )
|
||||
|
||||
struct mad_sector_0x00 {
|
||||
uint8_t crc;
|
||||
uint8_t info;
|
||||
|
@ -425,3 +427,101 @@ mad_free (Mad 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_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 (mad2);
|
||||
|
||||
|
@ -161,6 +191,22 @@ test_mifare_classic_mad (void)
|
|||
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);
|
||||
|
||||
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 (mad2);
|
||||
|
||||
|
|
Loading…
Reference in a new issue