From 1963bb65e4d6aa07c5277e8923bb01e6fa8b2002 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 25 Oct 2010 13:48:01 +0000 Subject: [PATCH] nfc-anticol: Cascade based on SAK rather than CT, better for educational purpose --- examples/nfc-anticol.c | 87 ++++++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 29 deletions(-) diff --git a/examples/nfc-anticol.c b/examples/nfc-anticol.c index 766dedc..8ca3fd4 100644 --- a/examples/nfc-anticol.c +++ b/examples/nfc-anticol.c @@ -45,7 +45,7 @@ static byte_t abtRx[MAX_FRAME_LEN]; static size_t szRxBits; static size_t szRx; -static byte_t abtUid[10]; +static byte_t abtRawUid[12]; static byte_t abtAtqa[2]; static byte_t abtSak; static size_t szCL = 1;//Always start with Cascade Level 1 (CL1) @@ -59,6 +59,7 @@ byte_t abtSelectAll[2] = { 0x93, 0x20 }; byte_t abtSelectTag[9] = { 0x93, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; byte_t abtRats[4] = { 0xe0, 0x50, 0xbc, 0xa5 }; byte_t abtHalt[4] = { 0x50, 0x00, 0x57, 0xcd }; +#define CASCADE_BIT 0x04 static bool transmit_bits (const byte_t * pbtTx, const size_t szTxBits) @@ -194,61 +195,82 @@ main (int argc, char *argv[]) // Anti-collision transmit_bytes (abtSelectAll, 2); - // Test if we are dealing with a 4 bytes uid(CL1) - if (abtRx[0] != 0x88) { - // Save the UID - memcpy (abtUid, abtRx, 4); - } else { - // Save the first 3 bytes of UID - memcpy (abtUid, abtRx+1, 3); - szCL = 2;//or more + // Check answer + if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) { + printf("WARNING: BCC check failed!\n"); } + // Save the UID CL1 + memcpy (abtRawUid, abtRx, 4); + //Prepare and send CL1 Select-Command memcpy (abtSelectTag + 2, abtRx, 5); append_iso14443a_crc (abtSelectTag, 7); transmit_bytes (abtSelectTag, 9); abtSak = abtRx[0]; + // Test if we are dealing with a CL2 + if (abtSak & CASCADE_BIT) { + szCL = 2;//or more + // Check answer + if (abtRawUid[0] != 0x88) { + printf("WARNING: Cascade bit set but CT != 0x88!\n"); + } + } + if(szCL == 2) { // We have to do the anti-collision for cascade level 2 // Prepare CL2 commands abtSelectAll[0] = 0x95; - abtSelectTag[0] = 0x95; // Anti-collision transmit_bytes (abtSelectAll, 2); - if(abtRx[0] != 0x88) { - // Save the second part of UID - memcpy (abtUid + 3, abtRx, 4); - } else { - memcpy (abtUid + 3, abtRx + 1, 3); - szCL = 3; + // Check answer + if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) { + printf("WARNING: BCC check failed!\n"); } - - // Selection + + // Save UID CL2 + memcpy (abtRawUid + 4, abtRx, 4); + + // Selection + abtSelectTag[0] = 0x95; memcpy (abtSelectTag + 2, abtRx, 5); append_iso14443a_crc (abtSelectTag, 7); transmit_bytes (abtSelectTag, 9); abtSak = abtRx[0]; + // Test if we are dealing with a CL3 + if (abtSak & CASCADE_BIT) { + szCL = 3; + // Check answer + if (abtRawUid[0] != 0x88) { + printf("WARNING: Cascade bit set but CT != 0x88!\n"); + } + } + if ( szCL == 3) { - // Do last CL - - // Save the last part of UID - memcpy (abtUid + 6, abtRx, 4); + // We have to do the anti-collision for cascade level 3 // Prepare and send CL3 AC-Command abtSelectAll[0] = 0x97; transmit_bytes (abtSelectAll, 2); + // Check answer + if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) { + printf("WARNING: BCC check failed!\n"); + } + + // Save UID CL3 + memcpy (abtRawUid + 8, abtRx, 4); + // Prepare and send final Select-Command abtSelectTag[0] = 0x97; memcpy (abtSelectTag + 2, abtRx, 5); append_iso14443a_crc (abtSelectTag, 7); - transmit_bytes (abtSelectTag, 9); + transmit_bytes (abtSelectTag, 9); abtSak = abtRx[0]; } } @@ -261,12 +283,19 @@ main (int argc, char *argv[]) transmit_bytes (abtHalt, 4); printf ("\nFound tag with\n UID: "); - printf ("%02x%02x%02x%02x", abtUid[0], abtUid[1], abtUid[2], abtUid[3]); - if (szCL > 1) { - printf ("%02x%02x%02x", abtUid[4], abtUid[5], abtUid[6]); - if (szCL > 2) { - printf("%02x%02x%02x", abtUid[7], abtUid[8], abtUid[9]); - } + switch (szCL) { + case 1: + printf ("%02x%02x%02x%02x", abtRawUid[0], abtRawUid[1], abtRawUid[2], abtRawUid[3]); + break; + case 2: + printf ("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]); + printf ("%02x%02x%02x%02x", abtRawUid[4], abtRawUid[5], abtRawUid[6], abtRawUid[7]); + break; + case 3: + printf ("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]); + printf ("%02x%02x%02x", abtRawUid[5], abtRawUid[6], abtRawUid[7]); + printf ("%02x%02x%02x%02x", abtRawUid[8], abtRawUid[9], abtRawUid[10], abtRawUid[11]); + break; } printf("\n"); printf("ATQA: %02x%02x\n SAK: %02x\n", abtAtqa[1], abtAtqa[0], abtSak);