libnfc
1.4.2
|
00001 /*- 00002 * Public platform independent Near Field Communication (NFC) library examples 00003 * 00004 * Copyright (C) 2009, Roel Verdult 00005 * Copyright (C) 2010, Romuald Conty 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions are met: 00009 * 1) Redistributions of source code must retain the above copyright notice, 00010 * this list of conditions and the following disclaimer. 00011 * 2 )Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00016 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00017 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00018 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00019 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00020 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00021 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00023 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00024 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00025 * POSSIBILITY OF SUCH DAMAGE. 00026 * 00027 * Note that this license only applies on the examples, NFC library itself is under LGPL 00028 * 00029 */ 00030 00036 #ifdef HAVE_CONFIG_H 00037 # include "config.h" 00038 #endif // HAVE_CONFIG_H 00039 00040 #include <stdio.h> 00041 #include <stdlib.h> 00042 #include <stdint.h> 00043 #include <stddef.h> 00044 #include <stdbool.h> 00045 00046 #include <string.h> 00047 #include <ctype.h> 00048 00049 #include <nfc/nfc.h> 00050 #include <nfc/nfc-messages.h> 00051 00052 #include "mifare.h" 00053 00054 static nfc_device_t *pnd; 00055 static nfc_target_t nt; 00056 static mifare_param mp; 00057 static mifareul_tag mtDump; 00058 static uint32_t uiBlocks = 0xF; 00059 00060 static const nfc_modulation_t nmMifare = { 00061 .nmt = NMT_ISO14443A, 00062 .nbr = NBR_106, 00063 }; 00064 00065 static void 00066 print_success_or_failure (bool bFailure, uint32_t * uiCounter) 00067 { 00068 printf ("%c", (bFailure) ? 'x' : '.'); 00069 if (uiCounter) 00070 *uiCounter += (bFailure) ? 0 : 1; 00071 } 00072 00073 static bool 00074 read_card (void) 00075 { 00076 uint32_t page; 00077 bool bFailure = false; 00078 uint32_t uiReadedPages = 0; 00079 00080 printf ("Reading %d pages |", uiBlocks + 1); 00081 00082 for (page = 0; page <= uiBlocks; page += 4) { 00083 // Try to read out the data block 00084 if (nfc_initiator_mifare_cmd (pnd, MC_READ, page, &mp)) { 00085 memcpy (mtDump.amb[page / 4].mbd.abtData, mp.mpd.abtData, 16); 00086 } else { 00087 bFailure = true; 00088 break; 00089 } 00090 00091 print_success_or_failure (bFailure, &uiReadedPages); 00092 print_success_or_failure (bFailure, &uiReadedPages); 00093 print_success_or_failure (bFailure, &uiReadedPages); 00094 print_success_or_failure (bFailure, &uiReadedPages); 00095 } 00096 printf ("|\n"); 00097 printf ("Done, %d of %d pages readed.\n", uiReadedPages, uiBlocks + 1); 00098 fflush (stdout); 00099 00100 return (!bFailure); 00101 } 00102 00103 static bool 00104 write_card (void) 00105 { 00106 uint32_t uiBlock = 0; 00107 bool bFailure = false; 00108 uint32_t uiWritenPages = 0; 00109 uint32_t uiSkippedPages; 00110 00111 char buffer[BUFSIZ]; 00112 bool write_otp; 00113 bool write_lock; 00114 00115 printf ("Write OTP bytes ? [yN] "); 00116 if (!fgets (buffer, BUFSIZ, stdin)) { 00117 ERR ("Unable to read standard input."); 00118 } 00119 write_otp = ((buffer[0] == 'y') || (buffer[0] == 'Y')); 00120 printf ("Write Lock bytes ? [yN] "); 00121 if (!fgets (buffer, BUFSIZ, stdin)) { 00122 ERR ("Unable to read standard input."); 00123 } 00124 write_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y')); 00125 00126 printf ("Writing %d pages |", uiBlocks + 1); 00127 /* We need to skip 2 first pages. */ 00128 printf ("ss"); 00129 uiSkippedPages = 2; 00130 00131 for (int page = 0x2; page <= 0xF; page++) { 00132 if ((page==0x2) && (!write_lock)) { 00133 printf ("s"); 00134 uiSkippedPages++; 00135 continue; 00136 } 00137 if ((page==0x3) && (!write_otp)) { 00138 printf ("s"); 00139 uiSkippedPages++; 00140 continue; 00141 } 00142 // Show if the readout went well 00143 if (bFailure) { 00144 // When a failure occured we need to redo the anti-collision 00145 if (!nfc_initiator_select_passive_target (pnd, nmMifare, NULL, 0, &nt)) { 00146 ERR ("tag was removed"); 00147 return false; 00148 } 00149 bFailure = false; 00150 } 00151 // For the Mifare Ultralight, this write command can be used 00152 // in compatibility mode, which only actually writes the first 00153 // page (4 bytes). The Ultralight-specific Write command only 00154 // writes one page at a time. 00155 uiBlock = page / 4; 00156 memcpy (mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData + ((page % 4) * 4), 16); 00157 if (!nfc_initiator_mifare_cmd (pnd, MC_WRITE, page, &mp)) 00158 bFailure = true; 00159 00160 print_success_or_failure (bFailure, &uiWritenPages); 00161 } 00162 printf ("|\n"); 00163 printf ("Done, %d of %d pages written (%d pages skipped).\n", uiWritenPages, uiBlocks + 1, uiSkippedPages); 00164 00165 return true; 00166 } 00167 00168 int 00169 main (int argc, const char *argv[]) 00170 { 00171 bool bReadAction; 00172 FILE *pfDump; 00173 00174 if (argc < 3) { 00175 printf ("\n"); 00176 printf ("%s r|w <dump.mfd>\n", argv[0]); 00177 printf ("\n"); 00178 printf ("r|w - Perform read from or write to card\n"); 00179 printf ("<dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n"); 00180 printf ("\n"); 00181 return 1; 00182 } 00183 00184 DBG ("\nChecking arguments and settings\n"); 00185 00186 bReadAction = tolower ((int) ((unsigned char) *(argv[1])) == 'r'); 00187 00188 if (bReadAction) { 00189 memset (&mtDump, 0x00, sizeof (mtDump)); 00190 } else { 00191 pfDump = fopen (argv[2], "rb"); 00192 00193 if (pfDump == NULL) { 00194 ERR ("Could not open dump file: %s\n", argv[2]); 00195 return 1; 00196 } 00197 00198 if (fread (&mtDump, 1, sizeof (mtDump), pfDump) != sizeof (mtDump)) { 00199 ERR ("Could not read from dump file: %s\n", argv[2]); 00200 fclose (pfDump); 00201 return 1; 00202 } 00203 fclose (pfDump); 00204 } 00205 DBG ("Successfully opened the dump file\n"); 00206 00207 // Try to open the NFC device 00208 pnd = nfc_connect (NULL); 00209 if (pnd == NULL) { 00210 ERR ("Error connecting NFC device\n"); 00211 return 1; 00212 } 00213 00214 nfc_initiator_init (pnd); 00215 00216 // Drop the field for a while 00217 if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) { 00218 nfc_perror (pnd, "nfc_configure"); 00219 exit (EXIT_FAILURE); 00220 } 00221 // Let the device only try once to find a tag 00222 if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) { 00223 nfc_perror (pnd, "nfc_configure"); 00224 exit (EXIT_FAILURE); 00225 } 00226 if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) { 00227 nfc_perror (pnd, "nfc_configure"); 00228 exit (EXIT_FAILURE); 00229 } 00230 if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) { 00231 nfc_perror (pnd, "nfc_configure"); 00232 exit (EXIT_FAILURE); 00233 } 00234 // Enable field so more power consuming cards can power themselves up 00235 if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) { 00236 nfc_perror (pnd, "nfc_configure"); 00237 exit (EXIT_FAILURE); 00238 } 00239 00240 printf ("Connected to NFC device: %s\n", pnd->acName); 00241 00242 // Try to find a MIFARE Ultralight tag 00243 if (!nfc_initiator_select_passive_target (pnd, nmMifare, NULL, 0, &nt)) { 00244 ERR ("no tag was found\n"); 00245 nfc_disconnect (pnd); 00246 return 1; 00247 } 00248 // Test if we are dealing with a MIFARE compatible tag 00249 00250 if (nt.nti.nai.abtAtqa[1] != 0x44) { 00251 ERR ("tag is not a MIFARE Ultralight card\n"); 00252 nfc_disconnect (pnd); 00253 return EXIT_FAILURE; 00254 } 00255 // Get the info from the current tag 00256 printf ("Found MIFARE Ultralight card with UID: "); 00257 size_t szPos; 00258 for (szPos = 0; szPos < nt.nti.nai.szUidLen; szPos++) { 00259 printf ("%02x", nt.nti.nai.abtUid[szPos]); 00260 } 00261 printf("\n"); 00262 00263 if (bReadAction) { 00264 if (read_card ()) { 00265 printf ("Writing data to file: %s ... ", argv[2]); 00266 fflush (stdout); 00267 pfDump = fopen (argv[2], "wb"); 00268 if (pfDump == NULL) { 00269 printf ("Could not open file: %s\n", argv[2]); 00270 return EXIT_FAILURE; 00271 } 00272 if (fwrite (&mtDump, 1, sizeof (mtDump), pfDump) != sizeof (mtDump)) { 00273 printf ("Could not write to file: %s\n", argv[2]); 00274 return EXIT_FAILURE; 00275 } 00276 fclose (pfDump); 00277 printf ("Done.\n"); 00278 } 00279 } else { 00280 write_card (); 00281 } 00282 00283 nfc_disconnect (pnd); 00284 00285 return EXIT_SUCCESS; 00286 }