static bool parse_card() { e.logcount = 0; e.current_tran = 0; int32_t iBlock; bool bFailure = false; //printf("Reading out %d blocks\n", uiBlocks + 1); // Read the card from end to begin for (iBlock = uiBlocks; iBlock >= 0; iBlock--) { // Authenticate everytime we reach a trailer block if(is_debug) printf(" 0x%02x : ", iBlock); if (iBlock / 4 == DO_NOT_ACCESS) { if(is_debug) printf("!\n"); continue; } if (is_trailer_block(iBlock)) { if (bFailure) { // When a failure occured we need to redo the anti-collision if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { printf("!\nError: tag was removed\n"); return false; } bFailure = false; } fflush(stdout); // Try to authenticate for the current sector if (!authenticate(iBlock, false)) { printf("!\nError: authentication failed for block 0x%02x\n", iBlock); return false; } // Try to read out the trailer if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) { if(is_debug) print_hex(mp.mpd.abtData, 16); parserights(&e, uiBlocks / 4, mp.mpd.abtData); } else { printf("!\nfailed to read trailer block 0x%02x\n", iBlock); bFailure = true; } } else { // Make sure a earlier readout did not fail if (!bFailure) { // Try to read out the data block if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) { if(is_debug) print_hex(mp.mpd.abtData, 16); parseTag(&e, iBlock, mp.mpd.abtData); } else { printf("!\nError: unable to read block 0x%02x\n", iBlock); bFailure = true; } } } if ( bFailure ) return false; } fflush(stdout); return true; }
bool authenticate(uint32_t uiBlock) { mifare_cmd mc; uint32_t uiTrailerBlock; //! Set the authentication information (uid) memcpy(mp.mpa.abtAuthUid, nt.nti.nai.abtUid + nt.nti.nai.szUidLen - 4, 4); //! Should we use key A or B? mc = (bUseKeyA) ? MC_AUTH_A : MC_AUTH_B; //! Key file authentication. if (bUseKeyFile) { //! Locate the trailer (with the keys) used for this sector uiTrailerBlock = get_trailer_block(uiBlock); //! Extract the right key from dump file if (bUseKeyA) { memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyA, 6); } else { memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyB, 6); } //! Try to authenticate for the current sector if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) { return true; } } else { //! Try to guess the right key size_t key_index; for (key_index = 0; key_index < num_keys; key_index++) { memcpy(mp.mpa.abtKey, keys + (key_index * 6), 6); if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) { if (bUseKeyA) { memcpy(mtKeys.amb[uiBlock].mbt.abtKeyA, &mp.mpa.abtKey, 6); } else { memcpy(mtKeys.amb[uiBlock].mbt.abtKeyB, &mp.mpa.abtKey, 6); } return true; } nfc_initiator_select_passive_target(pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, NULL); } } return false; }
static bool authenticate(uint32_t uiBlock) { mifare_cmd mc; uint32_t uiTrailerBlock; // Set the authentication information (uid) memcpy(mp.mpa.abtAuthUid, nt.nti.nai.abtUid + nt.nti.nai.szUidLen - 4, 4); // Should we use key A or B? mc = (bUseKeyA) ? MC_AUTH_A : MC_AUTH_B; // Key file authentication. if (bUseKeyFile) { // Locate the trailer (with the keys) used for this sector uiTrailerBlock = get_trailer_block(uiBlock); // Extract the right key from dump file if (bUseKeyA) memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyA, 6); else memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyB, 6); // Try to authenticate for the current sector if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) return true; } // If formatting or not using key file, try to guess the right key if (bFormatCard || !bUseKeyFile) { for (size_t key_index = 0; key_index < num_keys; key_index++) { memcpy(mp.mpa.abtKey, keys + (key_index * 6), 6); if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) { if (bUseKeyA) memcpy(mtKeys.amb[uiBlock].mbt.abtKeyA, &mp.mpa.abtKey, 6); else memcpy(mtKeys.amb[uiBlock].mbt.abtKeyB, &mp.mpa.abtKey, 6); return true; } if (nfc_initiator_select_passive_target(pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, NULL) <= 0) { ERR("tag was removed"); return false; } } } return false; }
static bool write_card (void) { uint32_t uiBlock = 0; bool bFailure = false; uint32_t uiWritenPages = 0; uint32_t uiSkippedPages; char buffer[BUFSIZ]; bool write_otp; bool write_lock; printf ("Write OTP bytes ? [yN] "); fgets (buffer, BUFSIZ, stdin); write_otp = ((buffer[0] == 'y') || (buffer[0] == 'Y')); printf ("Write Lock bytes ? [yN] "); fgets (buffer, BUFSIZ, stdin); write_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y')); printf ("Writing %d pages |", uiBlocks + 1); /* We need to skip 2 first pages. */ printf ("ss"); uiSkippedPages = 2; for (int page = 0x2; page <= 0xF; page++) { if ((page==0x2) && (!write_lock)) { printf ("s"); uiSkippedPages++; continue; } if ((page==0x3) && (!write_otp)) { printf ("s"); uiSkippedPages++; continue; } // Show if the readout went well if (bFailure) { // When a failure occured we need to redo the anti-collision if (!nfc_initiator_select_passive_target (pnd, nmMifare, NULL, 0, &nt)) { ERR ("tag was removed"); return false; } bFailure = false; } // For the Mifare Ultralight, this write command can be used // in compatibility mode, which only actually writes the first // page (4 bytes). The Ultralight-specific Write command only // writes one page at a time. uiBlock = page / 4; memcpy (mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData + ((page % 4) * 4), 16); if (!nfc_initiator_mifare_cmd (pnd, MC_WRITE, page, &mp)) bFailure = true; print_success_or_failure (bFailure, &uiWritenPages); } printf ("|\n"); printf ("Done, %d of %d pages written (%d pages skipped).\n", uiWritenPages, uiBlocks + 1, uiSkippedPages); return true; }
static bool read_card (void) { uint32_t page; bool bFailure = false; uint32_t uiReadedPages = 0; printf ("Reading %d pages |", uiBlocks + 1); for (page = 0; page <= uiBlocks; page += 4) { // Try to read out the data block if (nfc_initiator_mifare_cmd (pnd, MC_READ, page, &mp)) { memcpy (mtDump.amb[page / 4].mbd.abtData, mp.mpd.abtData, 16); } else { bFailure = true; break; } print_success_or_failure (bFailure, &uiReadedPages); print_success_or_failure (bFailure, &uiReadedPages); print_success_or_failure (bFailure, &uiReadedPages); print_success_or_failure (bFailure, &uiReadedPages); } printf ("|\n"); printf ("Done, %d of %d pages readed.\n", uiReadedPages, uiBlocks + 1); fflush (stdout); return (!bFailure); }
static bool check_magic() { bool bFailure = false; int uid_data; for (uint32_t page = 0; page <= 1; page++) { // Show if the readout went well if (bFailure) { // When a failure occured we need to redo the anti-collision if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { ERR("tag was removed"); return false; } bFailure = false; } uid_data = 0x00000000; memcpy(mp.mpd.abtData, &uid_data, sizeof uid_data); memset(mp.mpd.abtData + 4, 0, 12); //Force the write without checking for errors - otherwise the writes to the sector 0 seem to complain nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp); } //Check that the ID is now set to 0x000000000000 if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) { //printf("%u", mp.mpd.abtData); bool result = true; for (int i = 0; i <= 7; i++) { if (mp.mpd.abtData[i] != 0x00) result = false; } if (result) { return true; } } //Initially check if we can unlock via the MF method if (unlock_card()) { return true; } else { return false; } }
static bool write_block(uint32_t uiBlock, uint8_t* data, bool isTypeA) { if(is_trailer_block(uiBlock)) return false; mifare_param mpw; mifare_cmd mc = MC_WRITE; memcpy(mpw.mpd.abtData, data, 16); if(!authenticate(uiBlock, isTypeA)) return false; if(!nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mpw)) return false; return true; }
bool write_card(ReaderTag rt,mifareul_tag * tag){ uint32_t uiBlock = 0; bool bFailure = false; uint32_t uiWritenPages = 0; uint32_t uiSkippedPages; char buffer[BUFSIZ]; bool write_otp=0; bool write_lock=0; uiSkippedPages = 2; for (int page = 0x2; page <= 30; page++) { if ((page == 0x2) && (!write_lock)) { printf("s"); uiSkippedPages++; continue; } if ((page == 0x3) && (!write_otp)) { printf("s"); uiSkippedPages++; continue; } // Show if the readout went well if (bFailure) { // When a failure occured we need to redo the anti-collision if (nfc_initiator_select_passive_target(rt.device, nmMifare, NULL, 0, &rt.nt) <= 0) { ERR("tag was removed"); return false; } bFailure = false; } // For the Mifare Ultralight, this write command can be used // in compatibility mode, which only actually writes the first // page (4 bytes). The Ultralight-specific Write command only // writes one page at a time. uiBlock = page / 4; memcpy(mp.mpd.abtData, tag->amb[uiBlock].mbd.abtData + ((page % 4) * 4), 16); if (!nfc_initiator_mifare_cmd(rt.device, MC_WRITE, page, &mp)) bFailure = true; print_success_or_failure(bFailure, &uiWritenPages); } printf("|\n"); printf("Done, %d of 16 pages written (%d pages skipped).\n", uiWritenPages, uiSkippedPages); return true; }
static bool authenticate(uint32_t uiBlock, bool isTypeA) { mifare_cmd mc; // Set the authentication information (uid) memcpy(mp.mpa.abtAuthUid, nt.nti.nai.abtUid + nt.nti.nai.szUidLen - 4, 4); // Should we use key A or B? mc = (isTypeA)?MC_AUTH_A:MC_AUTH_B; int uiSecs = (uiBlocks + 1) / 4; if(isTypeA) memcpy(mp.mpa.abtKey, keysA[uiSecs - uiBlock / 4 - 1], 6); else memcpy(mp.mpa.abtKey, keysB[uiSecs - uiBlock / 4 - 1], 6); if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) return true; nfc_initiator_select_passive_target(pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, NULL); return false; }
static bool read_card(void) { uint32_t page; bool bFailure = false; uint32_t uiFailedPages = 0; printf("Reading %d pages |", uiBlocks); for (page = 0; page < uiBlocks; page += 4) { // Try to read out the data block if (nfc_initiator_mifare_cmd(pnd, MC_READ, page, &mp)) { memcpy(mtDump.amb[page / 4].mbd.abtData, mp.mpd.abtData, uiBlocks - page < 4 ? (uiBlocks - page) * 4 : 16); } else { bFailure = true; } for (uint8_t i = 0; i < (uiBlocks - page < 4 ? uiBlocks - page : 4); i++) { print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages); } } printf("|\n"); printf("Done, %d of %d pages read (%d pages failed).\n", uiReadPages, uiBlocks, uiFailedPages); fflush(stdout); // copy EV1 secrets to dump data switch (iEV1Type) { case EV1_UL11: memcpy(mtDump.amb[4].mbc11.pwd, iPWD, 4); memcpy(mtDump.amb[4].mbc11.pack, iPACK, 2); break; case EV1_UL21: memcpy(mtDump.amb[9].mbc21a.pwd, iPWD, 4); memcpy(mtDump.amb[9].mbc21b.pack, iPACK, 2); break; case EV1_NONE: default: break; } return (!bFailure); }
bool mf_authenticate(size_t block, const uint8_t* key, mf_key_type_t key_type) { mifare_param mp; // Set the authentication information (uid) memcpy(mp.mpa.abtAuthUid, target.nti.nai.abtUid + target.nti.nai.szUidLen - 4, 4); // Select key for authentication mifare_cmd mc = (key_type == MF_KEY_A) ? MC_AUTH_A : MC_AUTH_B; // Set the key memcpy(mp.mpa.abtKey, key, 6); // Try to authenticate for the current sector if (nfc_initiator_mifare_cmd(device, mc, (uint8_t)block, &mp)) return true; // Do the hand shaking again if auth failed nfc_initiator_select_passive_target(device, mf_nfc_modulation, NULL, 0, &target); return false; }
bool read_card_ultralight(void) { uint32_t page; bool bFailure = false; uint32_t uiReadedPages = 0; #ifdef DEBUG_PRINTF fprintf(stderr,"Reading %d pages |", uiBlocks_ultralight + 1); #endif for (page = 0; page <= uiBlocks_ultralight; page += 4) { //! Try to read out the data block if (nfc_initiator_mifare_cmd(pnd, MC_READ, page, &mp)) { memcpy(mtDump.amb[page / 4].mbd.abtData, mp.mpd.abtData, 16); } else { bFailure = true; break; } print_success_or_failure(bFailure, &uiReadedPages); print_success_or_failure(bFailure, &uiReadedPages); print_success_or_failure(bFailure, &uiReadedPages); print_success_or_failure(bFailure, &uiReadedPages); } #ifdef DEBUG_PRINTF fprintf(stderr,"|\n"); fprintf(stderr,"Done : %d of %d pages readed.\n", uiReadedPages, uiBlocks_ultralight + 1); #endif fflush(stdout); if (bFailure) { sprintf(message_erreur,"Impossible d'accéder aux données de la carte !"); } return (!bFailure); }
bool write_card_ultralight(int argc, const char *argv[]) { uint32_t uiBlock = 0; bool bFailure = false; uint32_t uiWritenPages = 0; uint32_t uiSkippedPages = 0; bool write_otp; bool write_lock; bool write_uid; if (argc>3) // Mode EXPERT ! { write_otp = ((argv[3][0] == 'y') || (argv[3][0] == 'Y')); write_lock = ((argv[4][0] == 'y') || (argv[4][0] == 'Y')); write_uid = ((argv[5][0] == 'y') || (argv[5][0] == 'Y')); } else { write_otp = true; write_lock = true; write_uid = false; } #ifdef DEBUG_PRINTF fprintf(stderr,"Writing %d pages |", uiBlocks_ultralight + 1); #endif /* We may need to skip 2 first pages. */ if (!write_uid) { fprintf(stderr,"ss"); uiSkippedPages = 2; } int page; for (page = uiSkippedPages; page <= 0xF; page++) { if ((page == 0x2) && (!write_lock)) { #ifdef DEBUG_PRINTF fprintf(stderr,"s"); #endif uiSkippedPages++; continue; } if ((page == 0x3) && (!write_otp)) { #ifdef DEBUG_PRINTF fprintf(stderr,"s"); #endif uiSkippedPages++; continue; } //! Show if the readout went well if (bFailure) { //! When a failure occured we need to redo the anti-collision if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { sprintf(message_erreur,"Tag was removed !"); return false; } bFailure = false; } //! For the Mifare Ultralight, this write command can be used //! in compatibility mode, which only actually writes the first //! page (4 bytes). The Ultralight-specific Write command only //! writes one page at a time. uiBlock = page / 4; memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData + ((page % 4) * 4), 16); if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp)) bFailure = true; print_success_or_failure(bFailure, &uiWritenPages); } #ifdef DEBUG_PRINTF fprintf(stderr,"|\n"); fprintf(stderr,"Done, %d of %d pages written (%d pages skipped).\n", uiWritenPages, uiBlocks_ultralight + 1, uiSkippedPages); #endif return true; }
bool write_card(int write_block_zero) { uint32_t uiBlock; bool bFailure = false; uint32_t uiWriteBlocks = 0; if (write_block_zero) { if (!unlock_card()) { return false; } } #ifdef DEBUG_PRINTF fprintf(stderr,"Writing %d blocks |", uiBlocks + 1); #endif //! Write the card from begin to end; for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) { //! Authenticate everytime we reach the first sector of a new block if (is_first_block(uiBlock)) { if (bFailure) { //! When a failure occured we need to redo the anti-collision if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { #ifdef DEBUG_PRINTF fprintf(stderr,"!\nError: tag was removed\n"); #endif sprintf(message_erreur,"Error: tag was removed !"); return false; } bFailure = false; } fflush(stdout); //! Try to authenticate for the current sector if (!write_block_zero && !authenticate(uiBlock)) { #ifdef DEBUG_PRINTF fprintf(stderr,"!\nError: authentication failed for block %02x\n", uiBlock); #endif sprintf(message_erreur,"Error: authentication failed for block %02x !", uiBlock); return false; } } if (is_trailer_block(uiBlock)) { //! Copy the keys over from our key dump and store the retrieved access bits memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbt.abtKeyA, 6); memcpy(mp.mpd.abtData + 6, mtDump.amb[uiBlock].mbt.abtAccessBits, 4); memcpy(mp.mpd.abtData + 10, mtDump.amb[uiBlock].mbt.abtKeyB, 6); //! Try to write the trailer if (nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp) == false) { #ifdef DEBUG_PRINTF fprintf(stderr,"failed to write trailer block %d \n", uiBlock); #endif bFailure = true; } } else { //! The first block 0x00 is read only, skip this if (uiBlock == 0 && ! write_block_zero && ! magic2) continue; //! Make sure a earlier write did not fail if (!bFailure) { //! Try to write the data block memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, 16); //! do not write a block 0 with incorrect BCC - card will be made invalid! if (uiBlock == 0) { if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) { #ifdef DEBUG_PRINTF fprintf(stderr,"!\nError: incorrect BCC in MFD file!\n"); fprintf(stderr,"Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]); #endif sprintf(message_erreur,"Error: incorrect BCC in MFD file! "); return false; } } if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) { bFailure = true; } } } //! Show if the write went well for each block print_success_or_failure(bFailure, &uiWriteBlocks); if ((! bTolerateFailures) && bFailure) { return false; } } #ifdef DEBUG_PRINTF fprintf(stderr,"|\n"); fprintf(stderr,"Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1); #endif fflush(stdout); return true; }
bool read_card(int read_unlocked) { int32_t iBlock; bool bFailure = false; uint32_t uiReadBlocks = 0; if (read_unlocked) { if (!unlock_card()) { return false; } } #ifdef DEBUG_PRINTF fprintf(stderr,"Reading out %d blocks |\n", uiBlocks + 1); #endif //! Read the card from end to begin for (iBlock = uiBlocks; iBlock >= 0; iBlock--) { //! Authenticate everytime we reach a trailer block if (is_trailer_block(iBlock)) { if (bFailure) { //! When a failure occured we need to redo the anti-collision if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { #ifdef DEBUG_PRINTF fprintf(stderr,"!\nError: tag was removed\n"); #endif sprintf(message_erreur,"Error: tag was removed !"); return false; } bFailure = false; } fflush(stdout); //! Try to authenticate for the current sector if (!read_unlocked && !authenticate(iBlock)) { #ifdef DEBUG_PRINTF fprintf(stderr,"!\nError: authentication failed for block 0x%02x\n", iBlock); #endif sprintf(message_erreur,"Error: authentication failed for block 0x%02x !", iBlock); return false; } //! Try to read out the trailer if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) { if (read_unlocked) { memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16); } else { //! Copy the keys over from our key dump and store the retrieved access bits memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, 6); memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpd.abtData + 6, 4); memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, 6); } } else { #ifdef DEBUG_PRINTF fprintf(stderr,"!\nfailed to read trailer block 0x%02x\n", iBlock); #endif bFailure = true; } } else { //! Make sure a earlier readout did not fail if (!bFailure) { //! Try to read out the data block if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) { memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16); } else { #ifdef DEBUG_PRINTF fprintf(stderr,"!\nError: unable to read block 0x%02x\n", iBlock); #endif bFailure = true; } } } //! Show if the readout went well for each block print_success_or_failure(bFailure, &uiReadBlocks); if ((! bTolerateFailures) && bFailure) { return false; } } #ifdef DEBUG_PRINTF fprintf(stderr,"|\n"); fprintf(stderr,"Done : %d of %d blocks read.\n", uiReadBlocks, uiBlocks + 1); #endif fflush(stdout); return true; }
bool mf_read_tag_internal(mf_tag_t* tag, const mf_tag_t* keys, mf_key_type_t key_type) { mifare_param mp; static mf_tag_t buffer_tag; clear_tag(&buffer_tag); int error = 0; printf("Reading: ["); fflush(stdout); // Read the card from end to begin for (int block_it = (int)block_count(size) - 1; block_it >= 0; --block_it) { size_t block = (size_t)block_it; // Authenticate everytime we reach a trailer block if (is_trailer_block(block)) { // Try to authenticate for the current sector uint8_t* key = key_from_tag(keys, key_type, block); if (!mf_authenticate(block, key, key_type)) { // Progress indication and error report printf("0x%02zx", block_to_sector(block)); if (block != 3) printf("."); fflush(stdout); block_it -= (int)sector_size(block) - 1; // Skip the rest of the sector blocks error = 1; } else { // Try to read the trailer (only to *read* the access bits) if (nfc_initiator_mifare_cmd(device, MC_READ, (uint8_t)block, &mp)) { // Copy the keys over to our tag buffer key_to_tag(&buffer_tag, keys->amb[block].mbt.abtKeyA, MF_KEY_A, block); key_to_tag(&buffer_tag, keys->amb[block].mbt.abtKeyB, MF_KEY_B, block); // Store the retrieved access bits in the tag buffer memcpy(buffer_tag.amb[block].mbt.abtAccessBits, mp.mpd.abtData + 6, 4); } else { printf ("\nUnable to read trailer block: 0x%02zx.\n", block); return false; } printf("."); fflush(stdout); // Progress indicator } } else { // I.e. not a sector trailer // Try to read out the block if (!nfc_initiator_mifare_cmd(device, MC_READ, (uint8_t)block, &mp)) { printf("\nUnable to read block: 0x%02zx.\n", block); return false; } memcpy(buffer_tag.amb[block].mbd.abtData, mp.mpd.abtData, 0x10); } } // Terminate progress indicator if (error) printf("] Auth errors in indicated sectors.\n"); else printf("] Success!\n"); // Success! Copy the data // todo: Or return static ptr? memcpy(tag, &buffer_tag, MF_4K); return true; }
bool mf_write_tag_internal(const mf_tag_t* tag, const mf_tag_t* keys, mf_key_type_t key_type) { mifare_param mp; int error = 0; printf("Writing %s tag [", sprint_size(size)); fflush(stdout); // Process each sector in turn for (int header_block_it = sector_header_iterator(0); header_block_it != -1; header_block_it = sector_header_iterator(size)) { size_t header_block = (size_t)header_block_it; // Authenticate uint8_t* key = key_from_tag(keys, key_type, header_block); if (key_type != MF_KEY_UNLOCKED) { if (!mf_authenticate(header_block, key, key_type)) { // Progress indication and error report if (header_block != 0) printf("."); printf("0x%02zx", block_to_sector(header_block)); fflush(stdout); error = 1; continue; // Skip the rest of the sector blocks } } // Write the sectors blocks for (size_t block = header_block, trailer = block_to_trailer(header_block); block < trailer; ++block) { // First block on tag is read only - skip it unless unlocked if (block == 0 && key_type != MF_KEY_UNLOCKED) continue; // Try to write the data block memcpy (mp.mpd.abtData, tag->amb[block].mbd.abtData, 0x10); // do not write a block 0 with incorrect BCC - card will be made invalid! if (block == 0) { if((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00) { printf ("\nError: incorrect BCC in MFD file!\n"); // ADD DATA return false; } } // Write the data block if (!nfc_initiator_mifare_cmd(device, MC_WRITE, (uint8_t)block, &mp)) { printf("\nUnable to write block: 0x%02zx.\n", block); return false; } } // Auth ok and sector read ok, finish up by reading trailer size_t trailer_block = block_to_trailer(header_block); memcpy (mp.mpd.abtData, tag->amb[trailer_block].mbt.abtKeyA, 6); memcpy (mp.mpd.abtData + 6, tag->amb[trailer_block].mbt.abtAccessBits, 4); memcpy (mp.mpd.abtData + 10, tag->amb[trailer_block].mbt.abtKeyB, 6); // Try to write the trailer if (!nfc_initiator_mifare_cmd(device, MC_WRITE, (uint8_t)trailer_block, &mp)) { printf("\nUnable to write block: 0x%02zx.\n", trailer_block); return false; } printf("."); fflush(stdout); // Progress indicator } // Terminate progress indicator if (error) printf("] Auth errors in indicated sectors.\n"); else printf("] Success!\n"); return true; }
static bool write_card(bool write_otp, bool write_lock, bool write_uid) { uint32_t uiBlock = 0; bool bFailure = false; uint32_t uiWritenPages = 0; uint32_t uiSkippedPages = 0; char buffer[BUFSIZ]; if (!write_otp) { printf("Write OTP bytes ? [yN] "); if (!fgets(buffer, BUFSIZ, stdin)) { ERR("Unable to read standard input."); } write_otp = ((buffer[0] == 'y') || (buffer[0] == 'Y')); } if (!write_lock) { printf("Write Lock bytes ? [yN] "); if (!fgets(buffer, BUFSIZ, stdin)) { ERR("Unable to read standard input."); } write_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y')); } if (!write_uid) { printf("Write UID bytes (only for special writeable UID cards) ? [yN] "); if (!fgets(buffer, BUFSIZ, stdin)) { ERR("Unable to read standard input."); } write_uid = ((buffer[0] == 'y') || (buffer[0] == 'Y')); } printf("Writing %d pages |", uiBlocks + 1); /* We may need to skip 2 first pages. */ if (!write_uid) { printf("ss"); uiSkippedPages = 2; } else { if (!check_magic()) { printf("\nUnable to unlock card - are you sure the card is magic?\n"); bFailure = false; return false; } } for (uint32_t page = uiSkippedPages; page <= ((uiBlocks / 4) * 4); page++) { if ((page == 0x2) && (!write_lock)) { printf("s"); uiSkippedPages++; continue; } if ((page == 0x3) && (!write_otp)) { printf("s"); uiSkippedPages++; continue; } // Show if the readout went well if (bFailure) { // When a failure occured we need to redo the anti-collision if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) { ERR("tag was removed"); return false; } bFailure = false; } // For the Mifare Ultralight, this write command can be used // in compatibility mode, which only actually writes the first // page (4 bytes). The Ultralight-specific Write command only // writes one page at a time. uiBlock = page / 4; memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData + ((page % 4) * 4), 4); memset(mp.mpd.abtData + 4, 0, 12); if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp)) bFailure = true; print_success_or_failure(bFailure, &uiWritenPages); } printf("|\n"); printf("Done, %d of %d pages written (%d pages skipped).\n", uiWritenPages, uiBlocks + 1, uiSkippedPages); return true; }