ssize_t mifare_application_write (MifareTag tag, Mad mad, const MadAid aid, const void *buf, size_t nbytes, const MifareClassicKey key, const MifareClassicKeyType key_type) { ssize_t res = 0; MifareClassicSectorNumber *sectors = mifare_application_find (mad, aid); MifareClassicSectorNumber *s = sectors; if (!sectors) return errno = EBADF, -1; while (*s && nbytes && (res >= 0)) { MifareClassicBlockNumber first_block = mifare_classic_sector_first_block (*s); MifareClassicBlockNumber last_block = mifare_classic_sector_last_block (*s); MifareClassicBlockNumber b = first_block; MifareClassicBlock block; if (mifare_classic_authenticate (tag, first_block, key, key_type) < 0) { res = -1; break; } while ((b < last_block) && nbytes) { size_t n = MIN (nbytes, 16); // Avoid overwriting existing data with uninitialized memory. if (n < 16) { if (mifare_classic_read (tag, b, &block) < 0) { res = -1; break; } } memcpy (&block, (uint8_t *)buf + res, n); if (mifare_classic_write (tag, b, block) < 0) { res = -1; break; } nbytes -= n; res += n; b++; } s++; } free (sectors); return res; }
int main(int argc, const char *argv[]) { nfc_device *pnd; //nfc_target nt; MifareTag *tags = NULL; int i,j,k; int nbrsect=0; MifareClassicBlock data; // Allocate only a pointer to nfc_context nfc_context *context; // Initialize libnfc and set the nfc_context nfc_init(&context); if (context == NULL) { printf("Unable to init libnfc\n"); exit(EXIT_FAILURE); } // Open, using the first available NFC device which can be in order of selection: // - default device specified using environment variable or // - first specified device in libnfc.conf (/etc/nfc) or // - first specified device in device-configuration directory (/etc/nfc/devices.d) or // - first auto-detected (if feature is not disabled in libnfc.conf) device pnd = nfc_open(context, NULL); if (pnd == NULL) { printf("ERROR: %s\n", "Unable to open NFC device."); exit(EXIT_FAILURE); } printf("NFC reader: %s opened\n", nfc_device_get_name(pnd)); tags = freefare_get_tags(pnd); if (!tags) { printf("no Mifare classic\n"); } else { for (i = 0; tags[i]; i++) { switch(freefare_get_tag_type(tags[i])) { case CLASSIC_1K: printf("%u : Mifare 1k (S50) : %s\n", i, freefare_get_tag_uid(tags[i])); nbrsect=16; break; case CLASSIC_4K: printf("%u : Mifare 4k (S70) : %s\n", i, freefare_get_tag_uid(tags[i])); nbrsect=40; break; default: printf("%u : other ISO14443A tag : %s\n", i, freefare_get_tag_uid(tags[i])); } } } if (!tags[0]) { printf("no tag found !\n"); nfc_close(pnd); nfc_exit(context); exit(EXIT_FAILURE); } printf ("Found %s\n", freefare_get_tag_friendly_name (tags[0])); /* MifareClassicBlockNumber dablock = 1; if(mifare_classic_connect(tags[0]) == OPERATION_OK) { printf("Connected !\n"); if(mifare_classic_authenticate(tags[0], dablock, keys[0], MFC_KEY_A) == OPERATION_OK) { printf("Authenticated !\n"); if(mifare_classic_get_data_block_permission (tags[0], dablock, MCAB_R|MCAB_W, MFC_KEY_A)) printf("i can READ block %d with key A\n", dablock); if(mifare_classic_get_trailer_block_permission (tags[0], ((dablock)/4)*4+3, MCAB_READ_KEYB, MFC_KEY_B)) printf("i can READ KEY A in trailer\n"); } } */ for(i=0; i<nbrsect; i++) { for(j=0; j < sizeof(keys)/sizeof(keys[0]); j++) { if((mifare_classic_connect(tags[0]) == OPERATION_OK) && (mifare_classic_authenticate( tags[0], mifare_classic_sector_last_block(i), keys[j], MFC_KEY_A) == OPERATION_OK)) { printf("sector %02d auth with A[%d]\n", i, j); for(k=mifare_classic_sector_first_block(i); k<=mifare_classic_sector_last_block(i); k++) { if(mifare_classic_read(tags[0], k, &data) == OPERATION_OK) { print_hex(data,16); } else { printf("read error\n"); } } mifare_classic_disconnect(tags[0]); break; } mifare_classic_disconnect(tags[0]); } printf("\n"); } printf("\n"); freefare_free_tags(tags); // Close NFC device nfc_close(pnd); // Release the context nfc_exit(context); exit(EXIT_SUCCESS); }
int main(int argc, const char *argv[]) { nfc_device *pnd; // nfc_target nt; // static mifare_param mp; int i, j; MifareTag *tags = NULL; int error = 0; MifareClassicBlock dablock; // MifareClassicBlock mydata = {0x00,0x00,0x00,0x42, 0xff,0xff,0xff,0xbd, 0x00,0x00,0x00,0x42, 0,0xff,0x00,0xff}; MifareClassicBlock my_trailer_block; MifareClassicKey my_key_A = { 0xff,0xff,0xff,0xff,0xff,0xff }; MifareClassicKey my_key_B = { 0xff,0xff,0xff,0xff,0xff,0xff }; // Allocate only a pointer to nfc_context nfc_context *context; // Initialize libnfc and set the nfc_context nfc_init(&context); if (context == NULL) { printf("Unable to init libnfc (malloc)\n"); exit(EXIT_FAILURE); } // Display libnfc version const char *acLibnfcVersion = nfc_version(); (void)argc; printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion); // Open, using the first available NFC device which can be in order of selection: // - default device specified using environment variable or // - first specified device in libnfc.conf (/etc/nfc) or // - first specified device in device-configuration directory (/etc/nfc/devices.d) or // - first auto-detected (if feature is not disabled in libnfc.conf) device pnd = nfc_open(context, NULL); if (pnd == NULL) { printf("ERROR: %s\n", "Unable to open NFC device."); exit(EXIT_FAILURE); } // Set opened NFC device to initiator mode if (nfc_initiator_init(pnd) < 0) { nfc_perror(pnd, "nfc_initiator_init"); exit(EXIT_FAILURE); } printf("NFC reader: %s opened\n", nfc_device_get_name(pnd)); // Poll for a ISO14443A (MIFARE) tag /* const nfc_modulation nmMifare = { .nmt = NMT_ISO14443A, .nbr = NBR_106, }; if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) > 0) { printf("The following (NFC) ISO14443A tag was found:\n"); printf(" ATQA (SENS_RES): "); print_hex(nt.nti.nai.abtAtqa, 2); printf(" UID (NFCID%c): ", (nt.nti.nai.abtUid[0] == 0x08 ? '3' : '1')); print_hex(nt.nti.nai.abtUid, nt.nti.nai.szUidLen); printf(" SAK (SEL_RES): "); print_hex(&nt.nti.nai.btSak, 1); if (nt.nti.nai.szAtsLen) { printf(" ATS (ATR): "); print_hex(nt.nti.nai.abtAts, nt.nti.nai.szAtsLen); } } */ tags = freefare_get_tags(pnd); if (!tags) { printf("no Mifare classic\n"); } else { for (i = 0; (!error) && tags[i]; i++) { if (freefare_get_tag_type(tags[i]) == CLASSIC_1K) printf("%u : Mifare 1k (S50)\n",i); if (freefare_get_tag_type(tags[i]) == CLASSIC_4K) printf("%u : Mifare 4k (S70)\n",i); } if(mifare_classic_connect(tags[0])==0) { printf("connected\n"); if(mifare_classic_authenticate(tags[0], 1,keys[0],MFC_KEY_B) == OPERATION_OK) { printf("Authenticated !\n"); if(mifare_classic_read (tags[0], 1, &dablock) == OPERATION_OK) { printf("Block readed\n"); for(j=0; j<16; j++) { printf("%02X ", dablock[j]); } printf("\n"); } else { printf("Auth error : %s\n", freefare_strerror(tags[0])); } if(mifare_classic_get_data_block_permission (tags[0], 1, MCAB_R, MFC_KEY_A)) printf("i can READ this block with B\n"); if(mifare_classic_get_data_block_permission (tags[0], 1, MCAB_W, MFC_KEY_A)) printf("i can WRITE this block with B\n"); if(mifare_classic_get_data_block_permission (tags[0], 1, MCAB_I, MFC_KEY_A)) printf("i can INC this block with B\n"); if(mifare_classic_get_data_block_permission (tags[0], 1, MCAB_D, MFC_KEY_A)) printf("i can DEC this block with B\n"); printf("---\n"); /* trailer = ((block) / 4) * 4 + 3; */ if(mifare_classic_get_trailer_block_permission (tags[0], 3, MCAB_READ_KEYA, MFC_KEY_A)) printf("i can READ KEY A in trailer\n"); if(mifare_classic_get_trailer_block_permission (tags[0], 3, MCAB_WRITE_KEYA, MFC_KEY_A)) printf("i can WRITE KEY A in trailer\n"); if(mifare_classic_get_trailer_block_permission (tags[0], 3, MCAB_READ_ACCESS_BITS, MFC_KEY_A)) printf("i can READ ACCESS BITS in trailer\n"); if(mifare_classic_get_trailer_block_permission (tags[0], 3, MCAB_WRITE_ACCESS_BITS, MFC_KEY_A)) printf("i can WRITE ACCESS BITS in trailer\n"); if(mifare_classic_get_trailer_block_permission (tags[0], 3, MCAB_READ_KEYB, MFC_KEY_A)) printf("i can READ KEYB in trailer\n"); if(mifare_classic_get_trailer_block_permission (tags[0], 3, MCAB_WRITE_KEYB, MFC_KEY_A)) printf("i can WRITE KEYB in trailer\n"); /* if(mifare_classic_write (tags[0], 1, mydata) == 0) { printf("write ok\n"); } */ if(mifare_classic_init_value (tags[0], 1, 0x42, 00) == 0) { printf("init value bloc ok\n"); } /* compose trailer block */ /* ab0 ab1 ab2 abt gpb */ /* abt = C_100 = 4 = 100 = c3c2c1 != datasheet c1c2c3*/ //mifare_classic_trailer_block (&my_trailer_block, my_key_A, C_000, C_011, C_000, C_100, 0x69, my_key_B); mifare_classic_trailer_block (&my_trailer_block, my_key_A, C_000, C_000, C_000, C_100, 0x69, my_key_B); for(j=0; j<16; j++) { printf("%02X ", my_trailer_block[j]); } printf("\n"); if(mifare_classic_write (tags[0], 3, my_trailer_block) == 0) { printf("trailer write ok\n"); } /* if(mifare_classic_decrement(tags[0], 1, 1) == OPERATION_OK) { printf("decrement ok\n"); } else { printf("Decrement error : %s\n", freefare_strerror(tags[0])); } if(mifare_classic_transfer (tags[0], 1) == OPERATION_OK) { printf("transfer ok\n"); } else { printf("Transfert error : %s\n", freefare_strerror(tags[0])); } if(mifare_classic_read(tags[0], 1, &dablock) == OPERATION_OK) { printf("Block readed\n"); for(j=0; j<16; j++) { printf("%02X ", dablock[j]); } printf("\n"); } else { printf("Read error : %s\n", freefare_strerror(tags[0])); } */ } else { printf("Erreur : %s\n", freefare_strerror(tags[0])); } mifare_classic_disconnect(tags[0]); } } /* for(i=0; i<1; i++) { for(j=0; j<8; j++) { memcpy(mp.mpa.abtKey, &keys[j*6], 6); res = nfc_initiator_mifare_cmd(pnd, MC_AUTH_B, 0, &mp); if(res) { printf("sector %u / key %u : yes\n", i, j); continue; } else { printf("sector %u / key %u : no\n", i, j); } } } */ /* // mifare parameters memcpy(mp.mpa.abtAuthUid,nt.nti.nai.abtUid,4); memcpy(mp.mpa.abtKey, &keys[0*6], 6); // block res = nfc_initiator_mifare_cmd(pnd, MC_AUTH_A, 0, &mp); if(res) { printf("Auth success\n"); } else { printf("Auth failed\n"); } for(i=0; i<4; i++) { res = nfc_initiator_mifare_cmd(pnd, MC_READ, i, &mp); if(res) { print_hex(mp.mpd.abtData,16); } else { printf("Read failed\n"); } } */ // Close NFC device nfc_close(pnd); // Release the context nfc_exit(context); exit(EXIT_SUCCESS); }
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")); }