New API functions mad_application_read(), mad_application_write().

This commit is contained in:
Romain Tartiere 2010-07-03 10:04:06 +00:00
parent 9e5820b89e
commit dbd3682174
6 changed files with 200 additions and 2 deletions

2
NEWS
View file

@ -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().

View file

@ -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 \

View file

@ -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);

View file

@ -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.
.\" ____ _ _ .\" ____ _ _
.\" | _ \ ___| |_ _ _ _ __ _ __ __ ____ _| |_ _ ___ ___ .\" | _ \ ___| |_ _ _ _ __ _ __ __ ____ _| |_ _ ___ ___
.\" | |_) / _ \ __| | | | '__| '_ \ \ \ / / _` | | | | |/ _ \/ __| .\" | |_) / _ \ __| | | | '__| '_ \ \ \ / / _` | | | | |/ _ \/ __|

View file

@ -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;
}

View file

@ -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);