int mifare_classic_read_ndef(MifareTag tag, char * buffer, char *max_size) { int error = EXIT_SUCCESS; Mad mad; // NFCForum card has a MAD, load it. if (0 == mifare_classic_connect (tag)) { } else { return -2; } if ((mad = mad_read (tag))) { // Dump the NFCForum application using MAD information ssize_t len; if ((len = mifare_application_read (tag, mad, mad_nfcforum_aid, buffer, max_size, mifare_classic_nfcforum_public_key_a, MFC_KEY_A)) != -1) { uint8_t tlv_type; uint16_t tlv_data_len; uint8_t * tlv_data; uint8_t * pbuffer = buffer; uint8_t found = false; while (!found) { tlv_data = tlv_decode (pbuffer, &tlv_type, &tlv_data_len); switch (tlv_type) { case 0x00: printf ("NFC Forum application contains a \"NULL TLV\", Skipping...\n"); // According to [ANNFC1K4K], we skip this Tag to read further TLV blocks. pbuffer += tlv_record_length(pbuffer, NULL, NULL); if (pbuffer >= buffer + sizeof(buffer)) { error= -3; found = true; } break; case 0x03: printf ("NFC Forum application contains a \"NDEF Message TLV\".\n"); found = true; error = tlv_data_len; memcpy(buffer,tlv_data,tlv_data_len); break; case 0xFD: printf ("NFC Forum application contains a \"Proprietary TLV\", Skipping...\n"); // According to [ANNFC1K4K], we can skip this TLV to read further TLV blocks. pbuffer += tlv_record_length(pbuffer, NULL, NULL); if (pbuffer >= buffer + sizeof(buffer)) { error= -4; found = true; } break; case 0xFE: printf ("NFC Forum application contains a \"Terminator TLV\", no available data.\n"); error= -5; found = true; break; default: printf ("NFC Forum application contains an invalid TLV.\n"); error= -6; found = true; } } } else { printf ("No NFC Forum application.\n"); error= -7; } } else { printf ("No MAD detected.\n"); } vPortFree (mad); return error; }
void test_mifare_classic_mad (void) { MifareClassicKey key_a_transport = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; MifareClassicKey key_b_sector_00 = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; MifareClassicKey key_b_sector_10 = { 0x1a, 0x98, 0x2c, 0x7e, 0x45 ,0x9a }; MifareClassicBlock tb; Mad mad; int res; /* __ __ _ ___ _ * | \/ | /_\ | \__ _/ | * | |\/| |/ _ \| |) \ V / | * |_| |_/_/ \_\___/ \_/|_| */ mad = mad_new (1); cut_assert_not_null (mad, cut_message ("mad_new() failed")); // Prepare sector 0x00 for writing a MAD. res = mifare_classic_authenticate (tag, 0x00, key_a_transport, MFC_KEY_A); cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed")); mifare_classic_trailer_block (&tb, key_a_transport, 00, 00, 00, 06, 0x00, key_b_sector_00); res = mifare_classic_write (tag, 0x03, tb); cut_assert_equal_int (0, res, cut_message ("mifare_classic_write() failed")); // Write the empty MAD res = mad_write (tag, mad, key_b_sector_00, NULL); cut_assert_equal_int (0, res, cut_message ("mad_write() failed")); // Check the empty MAD MifareClassicBlock ref_01 = { 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; MifareClassicBlock ref_02 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; MifareClassicBlock data; res = mifare_classic_authenticate (tag, 0x01, mad_public_key_a, MFC_KEY_A); cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed")); res = mifare_classic_read (tag, 0x01, &data); cut_assert_equal_int (0, res, cut_message ("mad_read() failed")); cut_assert_equal_memory (ref_01, sizeof (ref_01), data, sizeof (data), cut_message ("Wrong data")); res = mifare_classic_read (tag, 0x02, &data); cut_assert_equal_int (0, res, cut_message ("mad_read() failed")); cut_assert_equal_memory (ref_02, sizeof (ref_02), data, sizeof (data), cut_message ("Wrong data")); Mad mad2 = mad_read (tag); cut_assert_not_null (mad2, cut_message ("mad_read() failed")); cut_assert_equal_memory (mad, sizeof (mad), mad2, sizeof (mad2), cut_message ("Wrong MAD")); const char application_data[] = "APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> " \ "APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> " \ "APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> " \ "APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> " \ "APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> " \ "APPLICATION DATA >> APPLICATION DATA >> APPLICATION DATA >> "; MadAid aid = { .function_cluster_code = 0x01, .application_code = 0x12 }; // Write some data in the application MifareClassicSectorNumber *sectors = mifare_application_alloc (mad, aid, sizeof (application_data)); cut_assert_not_null (sectors, cut_message ("mifare_application_alloc() failed")); free (sectors); res = mad_write (tag, mad, key_b_sector_00, NULL); cut_assert_equal_int (0, res, cut_message ("mad_write() failed")); ssize_t s = mifare_application_write (tag, mad, aid, &application_data, sizeof (application_data), key_a_transport, MFC_KEY_A); cut_assert_equal_int (sizeof (application_data), s, cut_message ("mifare_application_write() failed")); char read_buf[500]; // Read it again s = mifare_application_read (tag, mad, aid, read_buf, sizeof (application_data), key_a_transport, MFC_KEY_A); cut_assert_equal_int (sizeof (application_data), s, cut_message ("mifare_application_read() failed")); cut_assert_equal_memory (application_data, sizeof (application_data), read_buf, s, cut_message ("Wrong application data")); mad_free (mad); mad_free (mad2); // Revert to the transport configuration res = mifare_classic_authenticate (tag, 0x00, key_b_sector_00, MFC_KEY_B); cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed")); res = mifare_classic_format_sector (tag, 0x00); cut_assert_equal_int (0, res, cut_message ("mifare_classic_format_sector() failed")); /* __ __ _ ___ ___ * | \/ | /_\ | \__ _|_ ) * | |\/| |/ _ \| |) \ V // / * |_| |_/_/ \_\___/ \_//___| */ if (freefare_get_tag_type (tag) != CLASSIC_4K) { cut_omit ("MADv2 requires a MIFARE Classic 4K to be tested"); } mad = mad_new (2); cut_assert_not_null (mad, cut_message ("mad_new() failed")); // Prepare sector 0x00 for writing a MAD. res = mifare_classic_authenticate (tag, 0x00, key_a_transport, MFC_KEY_A); cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed")); mifare_classic_trailer_block (&tb, key_a_transport, 00, 00, 00, 06, 0x00, key_b_sector_00); res = mifare_classic_write (tag, 0x03, tb); cut_assert_equal_int (0, res, cut_message ("mifare_classic_write() failed")); // Prepare sector 0x10 for writing a MAD. res = mifare_classic_authenticate (tag, 0x40, key_a_transport, MFC_KEY_A); cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed")); mifare_classic_trailer_block (&tb, key_a_transport, 00, 00, 00, 06, 0x00, key_b_sector_10); res = mifare_classic_write (tag, 0x43, tb); cut_assert_equal_int (0, res, cut_message ("mifare_classic_write() failed")); // Write the empty MAD res = mad_write (tag, mad, key_b_sector_00, key_b_sector_10); cut_assert_equal_int (0, res, cut_message ("mad_write() failed")); // Check the empty MAD res = mifare_classic_authenticate (tag, 0x01, mad_public_key_a, MFC_KEY_A); cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed")); res = mifare_classic_read (tag, 0x01, &data); cut_assert_equal_int (0, res, cut_message ("mad_read() failed")); cut_assert_equal_memory (ref_01, sizeof (ref_01), data, sizeof (data), cut_message ("Wrong data")); res = mifare_classic_read (tag, 0x02, &data); cut_assert_equal_int (0, res, cut_message ("mad_read() failed")); cut_assert_equal_memory (ref_02, sizeof (ref_02), data, sizeof (data), cut_message ("Wrong data")); MifareClassicBlock ref_40 = { 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; MifareClassicBlock ref_41 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; MifareClassicBlock ref_42 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; res = mifare_classic_authenticate (tag, 0x40, mad_public_key_a, MFC_KEY_A); cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed")); res = mifare_classic_read (tag, 0x40, &data); cut_assert_equal_int (0, res, cut_message ("mad_read() failed")); cut_assert_equal_memory (ref_40, sizeof (ref_01), data, sizeof (data), cut_message ("Wrong data")); res = mifare_classic_read (tag, 0x41, &data); cut_assert_equal_int (0, res, cut_message ("mad_read() failed")); cut_assert_equal_memory (ref_41, sizeof (ref_02), data, sizeof (data), cut_message ("Wrong data")); res = mifare_classic_read (tag, 0x42, &data); cut_assert_equal_int (0, res, cut_message ("mad_read() failed")); cut_assert_equal_memory (ref_42, sizeof (ref_02), data, sizeof (data), cut_message ("Wrong data")); mad2 = mad_read (tag); cut_assert_not_null (mad2, cut_message ("mad_read() failed")); cut_assert_equal_memory (mad, sizeof (mad), mad2, sizeof (mad2), cut_message ("Wrong MAD")); // Write some data in the application sectors = mifare_application_alloc (mad, aid, sizeof (application_data)); cut_assert_not_null (sectors, cut_message ("mifare_application_alloc() failed")); free (sectors); res = mad_write (tag, mad, key_b_sector_00, key_b_sector_10); cut_assert_equal_int (0, res, cut_message ("mad_write() failed")); s = mifare_application_write (tag, mad, aid, &application_data, sizeof (application_data), key_a_transport, MFC_KEY_A); cut_assert_equal_int (sizeof (application_data), s, cut_message ("mifare_application_write() failed")); // Read it again s = mifare_application_read (tag, mad, aid, read_buf, sizeof (application_data), key_a_transport, MFC_KEY_A); cut_assert_equal_int (sizeof (application_data), s, cut_message ("mifare_application_read() failed")); cut_assert_equal_memory (application_data, sizeof (application_data), read_buf, s, cut_message ("Wrong application data")); mad_free (mad); mad_free (mad2); // Revert to the transport configuration res = mifare_classic_authenticate (tag, 0x00, key_b_sector_00, MFC_KEY_B); cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed")); res = mifare_classic_format_sector (tag, 0x00); cut_assert_equal_int (0, res, cut_message ("mifare_classic_format_sector() failed")); res = mifare_classic_authenticate (tag, 0x40, key_b_sector_10, MFC_KEY_B); cut_assert_equal_int (0, res, cut_message ("mifare_classic_authenticate() failed")); res = mifare_classic_format_sector (tag, 0x10); cut_assert_equal_int (0, res, cut_message ("mifare_classic_format_sector() failed")); }