Add MAD CRC support.
This commit is contained in:
parent
54f4a84ead
commit
8a9d90210a
4 changed files with 372 additions and 12 deletions
|
@ -10,5 +10,7 @@ libfreefare_la_SOURCES = mifare_classic.c mad.c mifare_application.c
|
||||||
libfreefare_la_HEADERS = freefare.h
|
libfreefare_la_HEADERS = freefare.h
|
||||||
libfreefare_ladir = $(includedir)
|
libfreefare_ladir = $(includedir)
|
||||||
|
|
||||||
|
EXTRA_DIST = freefare_internal.h
|
||||||
|
|
||||||
pkgconfigdir = $(libdir)/pkgconfig
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
pkgconfig_DATA = libfreefare.pc
|
pkgconfig_DATA = libfreefare.pc
|
||||||
|
|
30
freefare_internal.h
Normal file
30
freefare_internal.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010, 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$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FREEFARE_INTERNAL_H__
|
||||||
|
#define __FREEFARE_INTERNAL_H__
|
||||||
|
|
||||||
|
struct mad_sector_0x00;
|
||||||
|
struct mad_sector_0x10;
|
||||||
|
|
||||||
|
void crc8 (uint8_t *crc, const uint8_t value);
|
||||||
|
uint8_t sector_0x00_crc8 (Mad mad);
|
||||||
|
uint8_t sector_0x10_crc8 (Mad mad);
|
||||||
|
|
||||||
|
#endif /* !__FREEFARE_INTERNAL_H__ */
|
98
mad.c
98
mad.c
|
@ -1,5 +1,5 @@
|
||||||
/*-
|
/*-
|
||||||
* Copyright (C) 2009, Romain Tartiere, Romuald Conty.
|
* Copyright (C) 2009, 2010, Romain Tartiere, Romuald Conty.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* 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
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -27,22 +27,40 @@
|
||||||
*/
|
*/
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <freefare.h>
|
#include <freefare.h>
|
||||||
|
|
||||||
|
#include "mad.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX The documentation says the preset is 0xE3, but the various card dumps
|
||||||
|
* and the documentation example MAD CRC can be verified only with a CRC
|
||||||
|
* preset of 0x67.
|
||||||
|
*
|
||||||
|
* This is still under investigation:
|
||||||
|
* http://www.libnfc.org/community/post/667/
|
||||||
|
* http://discussion.forum.nokia.com/forum/showthread.php?t=181702#14
|
||||||
|
*/
|
||||||
|
#define CRC_PRESET 0x67
|
||||||
|
|
||||||
|
#define SECTOR_0X00_AIDS 15
|
||||||
|
#define SECTOR_0X10_AIDS 23
|
||||||
|
|
||||||
struct mad_sector_0x00 {
|
struct mad_sector_0x00 {
|
||||||
uint8_t crc;
|
uint8_t crc;
|
||||||
uint8_t info;
|
uint8_t info;
|
||||||
MadAid aids[15];
|
MadAid aids[SECTOR_0X00_AIDS];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mad_sector_0x10 {
|
struct mad_sector_0x10 {
|
||||||
uint8_t crc;
|
uint8_t crc;
|
||||||
uint8_t info;
|
uint8_t info;
|
||||||
MadAid aids[23];
|
MadAid aids[SECTOR_0X10_AIDS];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mad {
|
struct mad {
|
||||||
|
@ -74,6 +92,57 @@ mad_new (uint8_t version)
|
||||||
return mad;
|
return mad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute CRC.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
crc8 (uint8_t *crc, const uint8_t value)
|
||||||
|
{
|
||||||
|
/* x^8 + x^4 + x^3 + x^2 + 1 => 0x11d */
|
||||||
|
const uint8_t poly = 0x1d;
|
||||||
|
|
||||||
|
for (int current_bit = 7; current_bit >= 0; current_bit--) {
|
||||||
|
int bit_out = (*crc) & 0x80;
|
||||||
|
*crc = ((*crc) << 1) | (( value >> (current_bit)) & 0x01);
|
||||||
|
|
||||||
|
if (bit_out)
|
||||||
|
*crc ^= poly;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
sector_0x00_crc8 (Mad mad)
|
||||||
|
{
|
||||||
|
uint8_t crc = CRC_PRESET;
|
||||||
|
|
||||||
|
crc8 (&crc, mad->sector_0x00.info);
|
||||||
|
|
||||||
|
for (int n = 0; n < SECTOR_0X00_AIDS; n++) {
|
||||||
|
crc8 (&crc, mad->sector_0x00.aids[n].application_code);
|
||||||
|
crc8 (&crc, mad->sector_0x00.aids[n].function_cluster_code);
|
||||||
|
}
|
||||||
|
crc8 (&crc, 0x00);
|
||||||
|
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
sector_0x10_crc8 (Mad mad)
|
||||||
|
{
|
||||||
|
uint8_t crc = CRC_PRESET;
|
||||||
|
|
||||||
|
crc8 (&crc, mad->sector_0x10.info);
|
||||||
|
|
||||||
|
for (int n = 0; n < SECTOR_0X10_AIDS; n++) {
|
||||||
|
crc8 (&crc, mad->sector_0x10.aids[n].application_code);
|
||||||
|
crc8 (&crc, mad->sector_0x10.aids[n].function_cluster_code);
|
||||||
|
}
|
||||||
|
crc8 (&crc, 0x00);
|
||||||
|
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read a MAD from the provided MIFARE tag.
|
* Read a MAD from the provided MIFARE tag.
|
||||||
*/
|
*/
|
||||||
|
@ -125,6 +194,11 @@ mad_read (MifareClassicTag tag)
|
||||||
goto error;
|
goto error;
|
||||||
memcpy (&(mad->sector_0x00) + sizeof (data), data, sizeof (data));
|
memcpy (&(mad->sector_0x00) + sizeof (data), data, sizeof (data));
|
||||||
|
|
||||||
|
uint8_t crc = mad->sector_0x00.crc;
|
||||||
|
uint8_t computed_crc = sector_0x00_crc8 (mad);
|
||||||
|
if (crc != computed_crc)
|
||||||
|
goto error;
|
||||||
|
|
||||||
/* Read MAD data at 0x10 (MAD2) */
|
/* Read MAD data at 0x10 (MAD2) */
|
||||||
if (mad->version == 2) {
|
if (mad->version == 2) {
|
||||||
|
|
||||||
|
@ -144,12 +218,12 @@ mad_read (MifareClassicTag tag)
|
||||||
if (mifare_classic_read (tag, 0x42, &data) < 0)
|
if (mifare_classic_read (tag, 0x42, &data) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
memcpy (&(mad->sector_0x10) + sizeof (data) * 2, data, sizeof (data));
|
memcpy (&(mad->sector_0x10) + sizeof (data) * 2, data, sizeof (data));
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
crc = mad->sector_0x10.crc;
|
||||||
* FIXME 3.7 CRC calculation states ``This code (CRC) should be checked
|
computed_crc = sector_0x10_crc8 (mad);
|
||||||
* whenever the MAD is read in order to ensure data integrity''.
|
if (crc != computed_crc)
|
||||||
*/
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
return mad;
|
return mad;
|
||||||
|
|
||||||
|
@ -164,10 +238,6 @@ error:
|
||||||
int
|
int
|
||||||
mad_write (MifareClassicTag tag, Mad mad, MifareClassicKey key_b_sector_00, MifareClassicKey key_b_sector_10)
|
mad_write (MifareClassicTag tag, Mad mad, MifareClassicKey key_b_sector_00, MifareClassicKey key_b_sector_10)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* FIXME Since the CRC SHOULD be checked, it SHOULD be written, right?
|
|
||||||
*/
|
|
||||||
|
|
||||||
MifareClassicBlock data;
|
MifareClassicBlock data;
|
||||||
|
|
||||||
if (mifare_classic_authenticate (tag, 0x00, key_b_sector_00, MFC_KEY_B) < 0)
|
if (mifare_classic_authenticate (tag, 0x00, key_b_sector_00, MFC_KEY_B) < 0)
|
||||||
|
@ -211,6 +281,8 @@ mad_write (MifareClassicTag tag, Mad mad, MifareClassicKey key_b_sector_00, Mifa
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mad->sector_0x10.crc = sector_0x10_crc8 (mad);
|
||||||
|
|
||||||
memcpy (data, &(mad->sector_0x10), sizeof (data));
|
memcpy (data, &(mad->sector_0x10), sizeof (data));
|
||||||
if (mifare_classic_write (tag, 0x40, data) < 0) return -1;
|
if (mifare_classic_write (tag, 0x40, data) < 0) return -1;
|
||||||
memcpy (data, &(mad->sector_0x10) + sizeof (data), sizeof (data));
|
memcpy (data, &(mad->sector_0x10) + sizeof (data), sizeof (data));
|
||||||
|
@ -223,6 +295,8 @@ mad_write (MifareClassicTag tag, Mad mad, MifareClassicKey key_b_sector_00, Mifa
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mad->sector_0x00.crc = sector_0x00_crc8 (mad);
|
||||||
|
|
||||||
if (mifare_classic_authenticate (tag, 0x00, key_b_sector_00, MFC_KEY_B) < 0) return -1;
|
if (mifare_classic_authenticate (tag, 0x00, key_b_sector_00, MFC_KEY_B) < 0) return -1;
|
||||||
memcpy (data, &(mad->sector_0x00), sizeof (data));
|
memcpy (data, &(mad->sector_0x00), sizeof (data));
|
||||||
if (mifare_classic_write (tag, 0x01, data) < 0) return -1;
|
if (mifare_classic_write (tag, 0x01, data) < 0) return -1;
|
||||||
|
|
254
test/test_mad.c
254
test/test_mad.c
|
@ -1,5 +1,7 @@
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
|
#include "../freefare_internal.h"
|
||||||
|
|
||||||
DEFINE_TEST(test_mad)
|
DEFINE_TEST(test_mad)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
@ -49,3 +51,255 @@ DEFINE_TEST(test_mad)
|
||||||
} while (0);
|
} while (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CRC_PRESET 0x67
|
||||||
|
|
||||||
|
DEFINE_TEST(test_mad_crc8_basic)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
uint8_t crc;
|
||||||
|
const uint8_t crc_value = 0x42;
|
||||||
|
|
||||||
|
/* Insert data */
|
||||||
|
crc = 0x00;
|
||||||
|
crc8(&crc, crc_value);
|
||||||
|
assertEqualInt (crc, crc_value);
|
||||||
|
|
||||||
|
/* Insert data with leading zeros */
|
||||||
|
crc = 0x00;
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, crc_value);
|
||||||
|
assertEqualInt (crc, crc_value);
|
||||||
|
|
||||||
|
/* Check integrity */
|
||||||
|
crc = CRC_PRESET;
|
||||||
|
crc8(&crc, crc_value);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
uint8_t save = crc;
|
||||||
|
|
||||||
|
crc = CRC_PRESET;
|
||||||
|
crc8(&crc, crc_value);
|
||||||
|
crc8(&crc, save);
|
||||||
|
assertEqualInt (crc, 0x00);
|
||||||
|
|
||||||
|
} while (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following MAD values where extracted from documentation.
|
||||||
|
*/
|
||||||
|
DEFINE_TEST(test_mad_crc8_doc_example)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
/* Preset */
|
||||||
|
uint8_t crc = CRC_PRESET;
|
||||||
|
|
||||||
|
/* Block 1 -- 0x01 - 0x07 */
|
||||||
|
crc8(&crc, 0x01);
|
||||||
|
crc8(&crc, 0x01);
|
||||||
|
crc8(&crc, 0x08);
|
||||||
|
crc8(&crc, 0x01);
|
||||||
|
crc8(&crc, 0x08);
|
||||||
|
crc8(&crc, 0x01);
|
||||||
|
crc8(&crc, 0x08);
|
||||||
|
|
||||||
|
/* Block 2 -- 0x08 - 0x0f */
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x04);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
|
||||||
|
/* Block 3 -- 0x00 - 0x07 */
|
||||||
|
crc8(&crc, 0x03);
|
||||||
|
crc8(&crc, 0x10);
|
||||||
|
crc8(&crc, 0x03);
|
||||||
|
crc8(&crc, 0x10);
|
||||||
|
crc8(&crc, 0x02);
|
||||||
|
crc8(&crc, 0x10);
|
||||||
|
crc8(&crc, 0x02);
|
||||||
|
crc8(&crc, 0x10);
|
||||||
|
|
||||||
|
/* Block 3 -- 0x08 - 0x0f */
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x11);
|
||||||
|
crc8(&crc, 0x30);
|
||||||
|
|
||||||
|
/* Append zeros of augmented message */
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
|
||||||
|
assertEqualInt (crc, 0x89);
|
||||||
|
|
||||||
|
} while (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following MAD values where extracted from a MIFARE dump.
|
||||||
|
*/
|
||||||
|
DEFINE_TEST(test_mad_crc8_real_example_1)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
/* Preset */
|
||||||
|
uint8_t crc = CRC_PRESET;
|
||||||
|
|
||||||
|
/* Block 1 -- 0x01 - 0x07 */
|
||||||
|
crc8(&crc, 0x01);
|
||||||
|
crc8(&crc, 0x03);
|
||||||
|
crc8(&crc, 0xe1);
|
||||||
|
crc8(&crc, 0x03);
|
||||||
|
crc8(&crc, 0xe1);
|
||||||
|
crc8(&crc, 0x03);
|
||||||
|
crc8(&crc, 0xe1);
|
||||||
|
|
||||||
|
/* Block 2 -- 0x08 - 0x0f */
|
||||||
|
crc8(&crc, 0x03);
|
||||||
|
crc8(&crc, 0xe1);
|
||||||
|
crc8(&crc, 0x03);
|
||||||
|
crc8(&crc, 0xe1);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
|
||||||
|
/* Block 3 -- 0x00 - 0x07 */
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
|
||||||
|
/* Block 3 -- 0x08 - 0x0f */
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
|
||||||
|
/* Append zeros of augmented message */
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
|
||||||
|
assertEqualInt (crc, 0xc4);
|
||||||
|
|
||||||
|
} while (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following MAD values where extracted from a MIFARE dump.
|
||||||
|
*/
|
||||||
|
DEFINE_TEST(test_mad_crc8_real_example_2)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
/* Preset */
|
||||||
|
uint8_t crc = CRC_PRESET;
|
||||||
|
|
||||||
|
/* Block 1 -- 0x01 - 0x07 */
|
||||||
|
crc8(&crc, 0x01);
|
||||||
|
crc8(&crc, 0x03);
|
||||||
|
crc8(&crc, 0xe1);
|
||||||
|
crc8(&crc, 0x03);
|
||||||
|
crc8(&crc, 0xe1);
|
||||||
|
crc8(&crc, 0x03);
|
||||||
|
crc8(&crc, 0xe1);
|
||||||
|
|
||||||
|
/* Block 2 -- 0x08 - 0x0f */
|
||||||
|
crc8(&crc, 0x03);
|
||||||
|
crc8(&crc, 0xe1);
|
||||||
|
crc8(&crc, 0x03);
|
||||||
|
crc8(&crc, 0xe1);
|
||||||
|
crc8(&crc, 0x03);
|
||||||
|
crc8(&crc, 0xe1);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
|
||||||
|
/* Block 3 -- 0x00 - 0x07 */
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
|
||||||
|
/* Block 3 -- 0x08 - 0x0f */
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
|
||||||
|
/* Append zeros of augmented message */
|
||||||
|
crc8(&crc, 0x00);
|
||||||
|
|
||||||
|
assertEqualInt (crc, 0xab);
|
||||||
|
|
||||||
|
} while (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_TEST (test_mad_sector_0x00_crc8)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
do {
|
||||||
|
Mad mad = mad_new (1);
|
||||||
|
assert (mad != NULL);
|
||||||
|
|
||||||
|
if (mad) {
|
||||||
|
res = mad_set_card_publisher_sector (mad, 0x01);
|
||||||
|
|
||||||
|
/* Block 1 */
|
||||||
|
MadAid aid1 = { 0x08, 0x01 };
|
||||||
|
mad_set_aid (mad, 1, aid1);
|
||||||
|
mad_set_aid (mad, 2, aid1);
|
||||||
|
mad_set_aid (mad, 3, aid1);
|
||||||
|
|
||||||
|
/* Block 2 */
|
||||||
|
MadAid empty_aid = { 0x00, 0x00 };
|
||||||
|
mad_set_aid (mad, 4, empty_aid);
|
||||||
|
mad_set_aid (mad, 5, empty_aid);
|
||||||
|
mad_set_aid (mad, 6, empty_aid);
|
||||||
|
MadAid aid2 = { 0x00, 0x04 };
|
||||||
|
mad_set_aid (mad, 7, aid2);
|
||||||
|
|
||||||
|
/* Block 3 */
|
||||||
|
MadAid aid3 = { 0x10, 0x03 };
|
||||||
|
mad_set_aid (mad, 8, aid3);
|
||||||
|
mad_set_aid (mad, 9, aid3);
|
||||||
|
MadAid aid4 = { 0x10, 0x02 };
|
||||||
|
mad_set_aid (mad, 10, aid4);
|
||||||
|
mad_set_aid (mad, 11, aid4);
|
||||||
|
|
||||||
|
mad_set_aid (mad, 12, empty_aid);
|
||||||
|
mad_set_aid (mad, 13, empty_aid);
|
||||||
|
mad_set_aid (mad, 14, empty_aid);
|
||||||
|
MadAid aid5 = { 0x30, 0x11 };
|
||||||
|
mad_set_aid (mad, 15, aid5);
|
||||||
|
|
||||||
|
res = sector_0x00_crc8 (mad);
|
||||||
|
assertEqualInt(0x89, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
mad_free (mad);
|
||||||
|
|
||||||
|
} while (0);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue