lsnfc is now able to detect some MIFARE Plus.
This commit is contained in:
parent
8231610d35
commit
2ed38019ac
171
src/lsnfc.c
171
src/lsnfc.c
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* NFC utils - lsnfc
|
* NFC utils - lsnfc
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009, Romuald Conty
|
* Copyright (C) 2009, 2010, 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 General Public License as published by the Free
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
@ -17,6 +17,19 @@
|
|||||||
* this program. If not, see <http://www.gnu.org/licenses/>
|
* this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This implementation was written based on information provided by the
|
||||||
|
* following documents:
|
||||||
|
*
|
||||||
|
* MIFARE Type Identification Procedure
|
||||||
|
* AN10833
|
||||||
|
* Rev. 3.1 — 07 July 2009
|
||||||
|
* Application note
|
||||||
|
*
|
||||||
|
* ISO14443 tags list
|
||||||
|
* http://www.libnfc.org/documentation/hardware/tags/iso14443
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -30,7 +43,69 @@ static byte_t abtFelica[5] = { 0x00, 0xff, 0xff, 0x00, 0x00 };
|
|||||||
|
|
||||||
#define ERR(x, ...) printf("ERROR: " x "\n", ## __VA_ARGS__ )
|
#define ERR(x, ...) printf("ERROR: " x "\n", ## __VA_ARGS__ )
|
||||||
|
|
||||||
#define MAX_DEVICE_COUNT 16
|
#define MAX_DEVICE_COUNT 16
|
||||||
|
#define MAX_ATS_LENGTH 32
|
||||||
|
|
||||||
|
struct iso14443a_tag {
|
||||||
|
uint8_t ATQA[2], SAK;
|
||||||
|
const char *name;
|
||||||
|
size_t ATS_length;
|
||||||
|
uint8_t ATS[MAX_ATS_LENGTH];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Theses values comes from http://www.libnfc.org/documentation/hardware/tags/iso14443
|
||||||
|
|
||||||
|
Manufacturer Product ATQA SAK ATS (called ATR for contact smartcards)
|
||||||
|
|
||||||
|
NXP MIFARE Mini 00 04 09
|
||||||
|
MIFARE Classic 1K 00 04 08
|
||||||
|
MIFARE Classic 4K 00 02 18
|
||||||
|
MIFARE Ultralight 00 44 00
|
||||||
|
MIFARE DESFire 03 44 20 06 75 77 81 02 80
|
||||||
|
MIFARE DESFire EV1 03 44 20 06 75 77 81 02 80
|
||||||
|
JCOP31 03 04 28 38 77 b1 4a 43 4f 50 33 31
|
||||||
|
JCOP31 v2.4.1 00 48 20 78 77 b1 02 4a 43 4f 50 76 32 34 31
|
||||||
|
JCOP41 v2.2 00 48 20 38 33 b1 4a 43 4f 50 34 31 56 32 32
|
||||||
|
JCOP41 v2.3.1 00 04 28 38 33 b1 4a 43 4f 50 34 31 56 32 33 31
|
||||||
|
Infineon MIFARE Classic 1K 00 04 88
|
||||||
|
Gemplus MPCOS 00 02 98
|
||||||
|
Innovision R&T Jewel 0C 00
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct iso14443a_tag iso14443a_tags[] = {
|
||||||
|
{ { 0x00, 0x44 }, 0x00, "NXP MIFARE UltraLight", 0, {} },
|
||||||
|
{ { 0x00, 0x44 }, 0x00, "NXP MIFARE UltraLight C", 0, {} },
|
||||||
|
{ { 0x00, 0x04 }, 0x09, "NXP MIFARE Mini", 0, {} },
|
||||||
|
{ { 0x00, 0x04 }, 0x08, "NXP MIFARE Classic 1k", 0, {} },
|
||||||
|
{ { 0x00, 0x02 }, 0x18, "NXP MIFARE Classic 4k", 0, {} },
|
||||||
|
|
||||||
|
{ { 0x00, 0x04 }, 0x08, "NXP MIFARE Plus 1k", 0, {} },
|
||||||
|
{ { 0x00, 0x04 }, 0x18, "NXP MIFARE Plus 4k", 0, {} },
|
||||||
|
{ { 0x00, 0x02 }, 0x08, "NXP MIFARE Plus 1k", 0, {} },
|
||||||
|
{ { 0x00, 0x02 }, 0x18, "NXP MIFARE Plus 4k", 0, {} },
|
||||||
|
{ { 0x00, 0x04 }, 0x10, "NXP MIFARE Plus 1k", 0, {} },
|
||||||
|
{ { 0x00, 0x04 }, 0x11, "NXP MIFARE Plus 4k", 0, {} },
|
||||||
|
{ { 0x00, 0x02 }, 0x10, "NXP MIFARE Plus 1k", 0, {} },
|
||||||
|
{ { 0x00, 0x02 }, 0x11, "NXP MIFARE Plus 4k", 0, {} },
|
||||||
|
{ { 0x00, 0x04 }, 0x20, "NXP MIFARE Plus 1k", 0, {} },
|
||||||
|
{ { 0x00, 0x04 }, 0x20, "NXP MIFARE Plus 4k", 0, {} },
|
||||||
|
{ { 0x00, 0x02 }, 0x20, "NXP MIFARE Plus 1k", 0, {} },
|
||||||
|
{ { 0x00, 0x02 }, 0x20, "NXP MIFARE Plus 4k", 0, {} },
|
||||||
|
|
||||||
|
{ { 0x00, 0x44 }, 0x20, "NXP MIFARE Plus 2k/4k", 0, { 0x75, 0x77, 0x80, 0x02, 0xc1, 0x05, 0x2f, 0x2f, 0x01, 0xbc, 0xd6 } },
|
||||||
|
|
||||||
|
{ { 0x00, 0x04 }, 0x88, "Infineon MIFARE Classic 1k", 0, {} },
|
||||||
|
{ { 0x00, 0x02 }, 0x38, "Nokia MIFARE Classic 4k (Emulated)", 0, {} },
|
||||||
|
{ { 0x03, 0x44 }, 0x20, "NXP MIFARE DESFire", 5, { 0x75, 0x77, 0x81, 0x02, 0x80 } },
|
||||||
|
{ { 0x03, 0x04 }, 0x28, "NXP JCOP31", 0, {} },
|
||||||
|
/* @todo handle ATS to be able to know which one is it. */
|
||||||
|
{ { 0x00, 0x48 }, 0x20, "NXP JCOP31 or JCOP41", 0, {} },
|
||||||
|
{ { 0x00, 0x04 }, 0x28, "NXP JCOP41", 0, {} },
|
||||||
|
{ { 0x00, 0x02 }, 0x98, "Gemplus MPCOS", 0, {} },
|
||||||
|
/* @note I'm not sure that Jewel can be detected using this modulation but I haven't Jewel tags to test. */
|
||||||
|
{ { 0x00, 0x02 }, 0x98, "Innovision R&T Jewel", 0, {} },
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
print_hex (byte_t * pbtData, size_t szDate)
|
print_hex (byte_t * pbtData, size_t szDate)
|
||||||
@ -93,82 +168,34 @@ main (int argc, const char *argv[])
|
|||||||
do {
|
do {
|
||||||
if (nfc_initiator_select_tag (pnd, NM_ISO14443A_106, NULL, 0, &nti)) {
|
if (nfc_initiator_select_tag (pnd, NM_ISO14443A_106, NULL, 0, &nti)) {
|
||||||
printf (" ISO14443A: ");
|
printf (" ISO14443A: ");
|
||||||
|
char * tag_name = NULL;
|
||||||
|
|
||||||
/*
|
for (size_t i = 0; i < sizeof (iso14443a_tags) / sizeof (struct iso14443a_tag); i++) {
|
||||||
Theses values comes from http://www.libnfc.org/documentation/hardware/tags/iso14443
|
if ((nti.nai.abtAtqa[0] == iso14443a_tags[i].ATQA[0]) &&
|
||||||
|
(nti.nai.abtAtqa[1] == iso14443a_tags[i].ATQA[1]) &&
|
||||||
|
(nti.nai.btSak == iso14443a_tags[i].SAK)) {
|
||||||
|
// printf("DBG: iso14443a_tags[i].ATS_length = %d , nti.nai.szAtsLen = %d", iso14443a_tags[i].ATS_length, nti.nai.szAtsLen);
|
||||||
|
if( iso14443a_tags[i].ATS_length == 0 ) {
|
||||||
|
tag_name = (iso14443a_tags[i].name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
Manufacturer Product ATQA SAK ATS (called ATR for contact smartcards)
|
if( iso14443a_tags[i].ATS_length == nti.nai.szAtsLen ) {
|
||||||
|
if ( memcmp( nti.nai.abtAts, iso14443a_tags[i].ATS, iso14443a_tags[i].ATS_length ) == 0 ) {
|
||||||
NXP MIFARE Mini 00 04 09
|
tag_name = (iso14443a_tags[i].name);
|
||||||
MIFARE Classic 1K 00 04 08
|
break;
|
||||||
MIFARE Classic 4K 00 02 18
|
}
|
||||||
MIFARE Ultralight 00 44 00
|
}
|
||||||
MIFARE DESFire 03 44 20 06 75 77 81 02 80
|
}
|
||||||
MIFARE DESFire EV1 03 44 20 06 75 77 81 02 80
|
}
|
||||||
JCOP31 03 04 28 38 77 b1 4a 43 4f 50 33 31
|
if( tag_name != NULL ) {
|
||||||
JCOP31 v2.4.1 00 48 20 78 77 b1 02 4a 43 4f 50 76 32 34 31
|
printf("%s (UID=", tag_name);
|
||||||
JCOP41 v2.2 00 48 20 38 33 b1 4a 43 4f 50 34 31 56 32 32
|
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
||||||
JCOP41 v2.3.1 00 04 28 38 33 b1 4a 43 4f 50 34 31 56 32 33 31
|
printf (")\n");
|
||||||
Infineon MIFARE Classic 1K 00 04 88
|
|
||||||
Gemplus MPCOS 00 02 98
|
|
||||||
Innovision R&T Jewel 0C 00
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((nti.nai.abtAtqa[0] == 0x00) && (nti.nai.abtAtqa[1] == 0x04) && (nti.nai.btSak == 0x09)) {
|
|
||||||
printf ("NXP MIFARE Mini (UID=");
|
|
||||||
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
|
||||||
printf (")\n");
|
|
||||||
} else if ((nti.nai.abtAtqa[0] == 0x00) && (nti.nai.abtAtqa[1] == 0x04) && (nti.nai.btSak == 0x08)) {
|
|
||||||
printf ("NXP MIFARE Classic 1K (UID=");
|
|
||||||
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
|
||||||
printf (")\n");
|
|
||||||
} else if ((nti.nai.abtAtqa[0] == 0x00) && (nti.nai.abtAtqa[1] == 0x02) && (nti.nai.btSak == 0x18)) {
|
|
||||||
printf ("NXP MIFARE Classic 4K (UID=");
|
|
||||||
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
|
||||||
printf (")\n");
|
|
||||||
} else if ((nti.nai.abtAtqa[0] == 0x00) && (nti.nai.abtAtqa[1] == 0x02) && (nti.nai.btSak == 0x38)) {
|
|
||||||
printf ("Nokia MIFARE Classic 4K - emulated - (UID=");
|
|
||||||
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
|
||||||
printf (")\n");
|
|
||||||
} else if ((nti.nai.abtAtqa[0] == 0x00) && (nti.nai.abtAtqa[1] == 0x44) && (nti.nai.btSak == 0x00)) {
|
|
||||||
printf ("NXP MIFARE Ultralight (UID=");
|
|
||||||
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
|
||||||
printf (")\n");
|
|
||||||
} else if ((nti.nai.abtAtqa[0] == 0x03) && (nti.nai.abtAtqa[1] == 0x44) && (nti.nai.btSak == 0x20)) {
|
|
||||||
printf ("NXP MIFARE DESFire (UID=");
|
|
||||||
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
|
||||||
printf (")\n");
|
|
||||||
} else if ((nti.nai.abtAtqa[0] == 0x03) && (nti.nai.abtAtqa[1] == 0x04) && (nti.nai.btSak == 0x28)) {
|
|
||||||
printf ("NXP JCOP31 (UID=");
|
|
||||||
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
|
||||||
printf (")\n");
|
|
||||||
} else if ((nti.nai.abtAtqa[0] == 0x00) && (nti.nai.abtAtqa[1] == 0x48) && (nti.nai.btSak == 0x20)) {
|
|
||||||
/* @todo handle ATS to be able to know which one is it. */
|
|
||||||
printf ("NXP JCOP31 or JCOP41 (UID=");
|
|
||||||
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
|
||||||
printf (")\n");
|
|
||||||
} else if ((nti.nai.abtAtqa[0] == 0x00) && (nti.nai.abtAtqa[1] == 0x04) && (nti.nai.btSak == 0x28)) {
|
|
||||||
printf ("NXP JCOP41 (UID=");
|
|
||||||
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
|
||||||
printf (")\n");
|
|
||||||
} else if ((nti.nai.abtAtqa[0] == 0x00) && (nti.nai.abtAtqa[1] == 0x04) && (nti.nai.btSak == 0x88)) {
|
|
||||||
printf ("Infineon MIFARE Classic 1K (UID=");
|
|
||||||
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
|
||||||
printf (")\n");
|
|
||||||
} else if ((nti.nai.abtAtqa[0] == 0x00) && (nti.nai.abtAtqa[1] == 0x02) && (nti.nai.btSak == 0x98)) {
|
|
||||||
printf ("Gemplus MPCOS (UID=");
|
|
||||||
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
|
||||||
printf (")\n");
|
|
||||||
} else if ((nti.nai.abtAtqa[0] == 0x0C) && (nti.nai.abtAtqa[1] == 0x00)) {
|
|
||||||
/* @note I'm not sure that Jewel can be detected using this modultation and I haven't Jewel tags to test. */
|
|
||||||
printf ("Innovision R&T Jewel (UID=");
|
|
||||||
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
|
||||||
printf (")\n");
|
|
||||||
} else {
|
} else {
|
||||||
printf ("Unknown ISO14443A tag type: ");
|
printf ("Unknown ISO14443A tag type: ");
|
||||||
printf ("ATQA (SENS_RES): ");
|
printf ("ATQA (SENS_RES): ");
|
||||||
print_hex (nti.nai.abtAtqa, 2);
|
print_hex (nti.nai.abtAtqa, 2);
|
||||||
printf (" == %02x%02d == ", nti.nai.abtAtqa[0], nti.nai.abtAtqa[1]);
|
|
||||||
printf (", UID (NFCID%c): ", (nti.nai.abtUid[0] == 0x08 ? '3' : '1'));
|
printf (", UID (NFCID%c): ", (nti.nai.abtUid[0] == 0x08 ? '3' : '1'));
|
||||||
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
print_hex (nti.nai.abtUid, nti.nai.szUidLen);
|
||||||
printf (", SAK (SEL_RES): ");
|
printf (", SAK (SEL_RES): ");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user