Introduce MAD application management functions.
This commit is contained in:
parent
0ae63092bd
commit
3cab1523eb
6 changed files with 225 additions and 4 deletions
|
@ -6,8 +6,8 @@ AM_LDFLAGS = @LIBNFC_LIBS@
|
|||
|
||||
lib_LTLIBRARIES = libfreefare.la
|
||||
|
||||
libfreefare_la_SOURCES = mifare_classic.c mad.c
|
||||
libfreefare_la_HEADERS = mifare_classic.h mad.h
|
||||
libfreefare_la_SOURCES = mifare_classic.c mad.c mifare_application.c
|
||||
libfreefare_la_HEADERS = mifare_classic.h mad.h mifare_application.h
|
||||
libfreefare_ladir = $(includedir)
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
|
|
170
mifare_application.c
Normal file
170
mifare_application.c
Normal file
|
@ -0,0 +1,170 @@
|
|||
/*-
|
||||
* Copyright (C) 2009, 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
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
* $Id: mad.c 81 2009-12-21 00:40:07Z romain.tartiere $
|
||||
*/
|
||||
|
||||
/*
|
||||
* This implementation was written based on information provided by the
|
||||
* following document:
|
||||
*
|
||||
* /dev/brain
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <mifare_application.h>
|
||||
|
||||
#define FIRST_SECTOR 1
|
||||
|
||||
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)
|
||||
{
|
||||
size_t result = 0;
|
||||
|
||||
MifareSectorNumber s_max = (mad_get_version (mad) == 1) ? 0x0f : 0x27;
|
||||
|
||||
/* Count application sectors */
|
||||
MadAid c_aid;
|
||||
for (MifareSectorNumber s = FIRST_SECTOR; s <= s_max; s++) {
|
||||
mad_get_aid (mad, s, &c_aid);
|
||||
if (0 == aidcmp (aid, c_aid)) {
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two application identifiers.
|
||||
*/
|
||||
inline int
|
||||
aidcmp (const MadAid left, const MadAid right)
|
||||
{
|
||||
return ((left.function_cluster_code - right.function_cluster_code) << 8) | (left.application_code - right.application_code);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Card publisher functions (MAD owner).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Allocates a new application into a MAD.
|
||||
*/
|
||||
MifareSectorNumber *
|
||||
mifare_application_alloc (Mad mad, MadAid aid, size_t size)
|
||||
{
|
||||
/*
|
||||
* Ensure the card does not already have the application registered.
|
||||
*/
|
||||
MifareSectorNumber *found;
|
||||
if ((found = mifare_application_find (mad, aid))) {
|
||||
free (found);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MifareSectorNumber *res = malloc (sizeof (*res) * (size+1));
|
||||
res[size] = 0;
|
||||
|
||||
/*
|
||||
* Ensure the remaining free space is suficient before destroying the MAD.
|
||||
*/
|
||||
MadAid free_aid = { 0x00, 0x00 };
|
||||
MifareSectorNumber *free_aids = mifare_application_find (mad, free_aid);
|
||||
if (!free_aids)
|
||||
return NULL;
|
||||
|
||||
|
||||
for (int c = 0; c < size; c++) {
|
||||
if (free_aids[c]) {
|
||||
res[c] = free_aids[c];
|
||||
} else {
|
||||
free (res);
|
||||
res = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free (free_aids);
|
||||
|
||||
if (res) {
|
||||
/* Update the MAD */
|
||||
for (int c = 0; c < size; c++)
|
||||
mad_set_aid (mad, res[c], aid);
|
||||
}
|
||||
|
||||
/* Return the list of allocated sectors */
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove an application from a MAD.
|
||||
*/
|
||||
void
|
||||
mifare_application_free (Mad mad, MadAid aid)
|
||||
{
|
||||
MifareSectorNumber *sectors = mifare_application_find (mad, aid);
|
||||
MifareSectorNumber *p = sectors;
|
||||
MadAid free_aid = { 0x00, 0x00 };
|
||||
while (*p) {
|
||||
mad_set_aid (mad, *p, free_aid);
|
||||
p++;
|
||||
}
|
||||
|
||||
free (sectors);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Application owner functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get all sector numbers of an application from the provided MAD.
|
||||
*/
|
||||
MifareSectorNumber *
|
||||
mifare_application_find (Mad mad, MadAid aid)
|
||||
{
|
||||
MifareSectorNumber *res = NULL;
|
||||
size_t res_count = count_aids (mad, aid);
|
||||
|
||||
if (res_count)
|
||||
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)) {
|
||||
res[w++] = r;
|
||||
}
|
||||
r++;
|
||||
}
|
||||
res[w] = 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
12
mifare_application.h
Normal file
12
mifare_application.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef __MAD_DATA_H__
|
||||
#define __MAD_DATA_H__
|
||||
|
||||
#include <mad.h>
|
||||
|
||||
MifareSectorNumber *mifare_application_alloc (Mad mad, MadAid aid, size_t size);
|
||||
void mifare_application_free (Mad mad, MadAid aid);
|
||||
|
||||
MifareSectorNumber *mifare_application_find (Mad mad, MadAid aid);
|
||||
|
||||
|
||||
#endif /* !__MAD_DATA_H__ */
|
|
@ -2,7 +2,7 @@ LMF_SRCDIR= ${.CURDIR}/..
|
|||
.PATH: ${LMF_SRCDIR}
|
||||
|
||||
#LMF_SRCS!= ${MAKE} -f ${LMF_SRCDIR}/Makefile -V SRCS
|
||||
LMF_SRCS= ../mifare_classic.c ../mad.c
|
||||
LMF_SRCS= ../mifare_classic.c ../mad.c ../mifare_application.c
|
||||
|
||||
TESTS= test_read_sector_0.c \
|
||||
test_authenticate.c \
|
||||
|
@ -10,7 +10,8 @@ TESTS= test_read_sector_0.c \
|
|||
test_access_bits.c \
|
||||
test_format.c \
|
||||
test_create_trailer_block.c \
|
||||
test_mad.c
|
||||
test_mad.c \
|
||||
test_mifare_application.c
|
||||
|
||||
SRCS= ${LMF_SRCS} \
|
||||
${TESTS} \
|
||||
|
|
|
@ -206,6 +206,7 @@ int read_open_memory2(struct archive *, void *, size_t, size_t);
|
|||
#include <nfc/nfc.h>
|
||||
#include <mifare_classic.h>
|
||||
#include <mad.h>
|
||||
#include <mifare_application.h>
|
||||
|
||||
int mifare_classic_test_setup (MifareClassicTag *tag);
|
||||
int mifare_classic_test_teardown (MifareClassicTag tag);
|
||||
|
|
37
test/test_mifare_application.c
Normal file
37
test/test_mifare_application.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include "test.h"
|
||||
|
||||
DEFINE_TEST(test_mifare_application)
|
||||
{
|
||||
do {
|
||||
|
||||
/* Card publisher part */
|
||||
|
||||
MadAid aid = { 0x22, 0x42 };
|
||||
Mad mad = mad_new (2);
|
||||
assert (NULL != mad);
|
||||
|
||||
MifareSectorNumber *s_alloc = mifare_application_alloc (mad, aid, 3);
|
||||
assert (NULL != s_alloc);
|
||||
|
||||
MifareSectorNumber *s_found = mifare_application_find (mad, aid);
|
||||
assert (NULL != s_found);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
assertEqualInt (s_alloc[i], s_found[i]);
|
||||
}
|
||||
|
||||
assertEqualInt (0, s_alloc[3]);
|
||||
assertEqualInt (0, s_found[3]);
|
||||
|
||||
mifare_application_free (mad, aid);
|
||||
|
||||
free (s_alloc);
|
||||
free (s_found);
|
||||
|
||||
s_found = mifare_application_find (mad, aid);
|
||||
assert (s_found == NULL);
|
||||
|
||||
mad_free (mad);
|
||||
|
||||
} while (0);
|
||||
}
|
Loading…
Reference in a new issue