/* * 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; 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)) { result++; } } return result; }
/* * Allocates a new application into a MAD. */ MifareClassicSectorNumber * mifare_application_alloc (Mad mad, MadAid aid, size_t size) { uint8_t sector_map[40]; MifareClassicSectorNumber sector; MadAid sector_aid; MifareClassicSectorNumber *res = NULL; ssize_t s = size; /* * Ensure the card does not already have the application registered. */ MifareClassicSectorNumber *found; if ((found = mifare_application_find (mad, aid))) { free (found); return NULL; } for (size_t i = 0; i < sizeof (sector_map); i++) sector_map[i] = 0; /* * Try to minimize lost space and allocate as many large pages as possible * when the target is a Mifare Classic 4k. */ MadAid free_aid = { 0x00, 0x00 }; 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)) { sector_map[sector] = 1; s -= 15*16; } sector++; } } sector = FIRST_SECTOR; MifareClassicSectorNumber s_max = (mad_get_version (mad) == 1) ? 15 : 31; while ((s > 0) && (sector <= s_max)) { if (mad_sector_reserved (sector)) continue; mad_get_aid (mad, sector, §or_aid); if (0 == aidcmp (sector_aid, free_aid)) { sector_map[sector] = 1; s -= 3*16; } sector++; } /* * Ensure the remaining free space is suficient before destroying the MAD. */ if (s > 0) return NULL; int n = 0; for (size_t i = FIRST_SECTOR; i < sizeof (sector_map); i++) if (sector_map[i]) n++; if (!(res = malloc (sizeof (*res) * (n+1)))) return NULL; n = 0; for (size_t i = FIRST_SECTOR; i < sizeof (sector_map); i++) if (sector_map[i]) { res[n] = i; mad_set_aid (mad, i, aid); n++; } res[n] = 0; /* Return the list of allocated sectors */ return res; }
void test_mad (void) { int res; 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 (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, 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")); 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_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); } #define CRC_PRESET 0xc7 void test_mad_crc8_basic (void) { uint8_t crc; const uint8_t crc_value = 0x42; /* Check integrity */ crc = CRC_PRESET; nxp_crc(&crc, crc_value); uint8_t save = crc; 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")); }