1

How can I make authenticate and read data from a MIFARE Classic card that is formatted with the MIFARE Application Directory structure? I'm using Android.

Michael Roland
  • 39,663
  • 10
  • 99
  • 206
Eagle_one
  • 426
  • 4
  • 15

1 Answers1

14

See NXP's application note on the MIFARE Application Directory. Typically, in order to read data from a MIFARE Classic card that makes use of the MAD, you would do something like the following:

  1. Authenticate to sector 0 (MAD sector) using key A A0 A1 A2 A3 A4 A5 (the public MAD read key).
  2. Read block 3.
  3. Based on the general purpose byte (byte 9 read from block 3), you can determine
    • if the card uses the MAD (bit 7 = 1),
    • if the card supports multiple applications (bit 6 = 1), and
    • the MAD version (bits 1-0).
  4. Read blocks 1 and 2, these blocks have the following format (where AIDx is the application ID assigned to sector number x):

            +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
       Byte |  0 |  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |  9 | 10 | 11 | 12 | 13 | 14 | 15 |
            +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
    Block 1 |CRC |INFO|  AID01  |  AID02  |  AID03  |  AID04  |  AID05  |  AID06  |  AID07  |
            +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
    Block 2 |  AID08  |  AID09  |  AID10  |  AID11  |  AID12  |  AID13  |  AID14  |  AID15  |
            +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
    
  5. Verify the CRC (block 1, byte 0).

  6. Browse through the AID list (as generated from the data of blocks 1 and 2) to find your application AIDs (and consequently to find the sectors that contain your application data).
  7. If MAD version 2 is used, authenticate to sector 16 and read blocks 0 (64), 1 (65), and 2 (66) in order to get the extended AID list. The format of these blocks is:

            +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
       Byte |  0 |  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |  9 | 10 | 11 | 12 | 13 | 14 | 15 |
            +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
    Block 0 |CRC |INFO|  AID17  |  AID18  |  AID19  |  AID20  |  AID21  |  AID22  |  AID23  |
            +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
    Block 1 |  AID24  |  AID25  |  AID26  |  AID27  |  AID28  |  AID29  |  AID30  |  AID31  |
            +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
    Block 2 |  AID32  |  AID33  |  AID34  |  AID35  |  AID36  |  AID37  |  AID38  |  AID39  |
            +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
    
  8. Authenticate to the sectors of your application (as discovered through the AID list) and read/write the data of your application.

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
Michael Roland
  • 39,663
  • 10
  • 99
  • 206
  • Hi Michael, thanks for your answer it helpt me a bit, I'm ok until I get to number (6) in your answer, the data that comes back from the readBlock() function is a byte[] so my questions are: - how can "Browse" through the AID list? Do you have any code example? – Eagle_one Oct 08 '15 at 12:58
  • @Eagle_one Did you read the [application note](http://www.nxp.com/documents/application_note/AN10787.pdf) that I linked in the post? Section 3.6, tables 9 and 10 show you the format of the AID list. – Michael Roland Oct 08 '15 at 15:36
  • Hi @MichaelRoland I did a program in Java (Android) that loops trough both sectors and their blocks, the thing is I get some strings normaly but others not, when I asked the card producer they said you should read those values as HEX not as string, and there where it stops, because I get back Byte arrays and if I read them as HEX they give me junk data example: – Eagle_one Oct 14 '15 at 09:53
  • {sector: 0, block: 0, Data BYTE: [-70, 65, -113, -120, -4, -120, 4, 0, -63, -123, 20, -103, 101, 16, 70, 18] and the value is: �A�����E�eF } – Eagle_one Oct 14 '15 at 09:55
  • And: {sector: 0, block: 1, Data BYTE: [-30, 0, 4, 0, -119, 81, -118, 81, -117, 81, -116, 81, -115, 81, 0, 0] and the value is: ������Q�Q�Q�Q�Q���� }, {sector: 0, block: 2, Data BYTE: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] and the value is: �������������������������������� }, – Eagle_one Oct 14 '15 at 09:55
  • And: {sector: 0, block: 3, Data BYTE: [0, 0, 0, 0, 0, 0, 120, 119, -120, -63, 0, 0, 0, 0, 0, 0] and the value is: ������������xw�������������� }, {sector: 1, block: 0, Data BYTE: [8, 81, 86, 73, 78, 84, 85, 83, 0, 72, 73, 68, 69, 78, 84, 73] and the value is: QVINTUS��HIDENTI } – Eagle_one Oct 14 '15 at 09:55