libnfc 1.8.0
nfc-jewel.c
Go to the documentation of this file.
1/*-
2 * Free/Libre Near Field Communication (NFC) library
3 *
4 * Libnfc historical contributors:
5 * Copyright (C) 2009 Roel Verdult
6 * Copyright (C) 2009-2013 Romuald Conty
7 * Copyright (C) 2010-2012 Romain Tartière
8 * Copyright (C) 2010-2013 Philippe Teuwen
9 * Copyright (C) 2012-2013 Ludovic Rousseau
10 * See AUTHORS file for a more comprehensive list of contributors.
11 * Additional contributors of this file:
12 * Copyright (C) 2014 Pim 't Hart
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are met:
16 * 1) Redistributions of source code must retain the above copyright notice,
17 * this list of conditions and the following disclaimer.
18 * 2 )Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *
34 * Note that this license only applies on the examples, NFC library itself is under LGPL
35 *
36 */
37
43#ifdef HAVE_CONFIG_H
44# include "config.h"
45#endif // HAVE_CONFIG_H
46
47#include <stdio.h>
48#include <stdlib.h>
49#include <stdint.h>
50#include <stddef.h>
51#include <stdbool.h>
52
53#include <string.h>
54#include <ctype.h>
55
56#include <nfc/nfc.h>
57
58#include "nfc-utils.h"
59#include "jewel.h"
60
61static nfc_device *pnd;
62static nfc_target nt;
63static jewel_req req;
64static jewel_res res;
65static jewel_tag ttDump;
66static uint32_t uiBlocks = 0x0E;
67static uint32_t uiBytesPerBlock = 0x08;
68
69static const nfc_modulation nmJewel = {
70 .nmt = NMT_JEWEL,
71 .nbr = NBR_106,
72};
73
74static void
75print_success_or_failure(bool bFailure, uint32_t *uiCounter)
76{
77 printf("%c", (bFailure) ? 'x' : '.');
78 if (uiCounter)
79 *uiCounter += (bFailure) ? 0 : 1;
80}
81
82static bool
83read_card(void)
84{
85 uint32_t block;
86 uint32_t byte;
87 bool bFailure = false;
88 uint32_t uiReadBlocks = 0;
89
90 printf("Reading %d blocks |", uiBlocks + 1);
91
92 for (block = 0; block <= uiBlocks; block++) {
93 for (byte = 0; byte < uiBytesPerBlock; byte++) {
94
95 // Try to read the byte
96 req.read.btCmd = TC_READ;
97 req.read.btAdd = (block << 3) + byte;
98 if (nfc_initiator_jewel_cmd(pnd, req, &res)) {
99 ttDump.ttd.abtData[(block << 3) + byte] = res.read.btDat;
100 } else {
101 bFailure = true;
102 break;
103 }
104 }
105
106 print_success_or_failure(bFailure, &uiReadBlocks);
107 fflush(stdout);
108 }
109 printf("|\n");
110 printf("Done, %d of %d blocks read.\n", uiReadBlocks, uiBlocks + 1);
111
112 return (!bFailure);
113}
114
115static bool
116write_card(void)
117{
118 uint32_t block;
119 uint32_t byte;
120 bool bFailure = false;
121 uint32_t uiWrittenBlocks = 0;
122 uint32_t uiSkippedBlocks = 0;
123 uint32_t uiPartialBlocks = 0;
124
125 char buffer[BUFSIZ];
126 bool write_otp;
127 bool write_lock;
128
129 printf("Write Lock bytes ? [yN] ");
130 if (!fgets(buffer, BUFSIZ, stdin)) {
131 ERR("Unable to read standard input.");
132 }
133 write_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
134
135 printf("Write OTP bytes ? [yN] ");
136 if (!fgets(buffer, BUFSIZ, stdin)) {
137 ERR("Unable to read standard input.");
138 }
139 write_otp = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
140
141 printf("Writing %d pages |", uiBlocks + 1);
142
143 // Skip block 0 - as far as I know there are no Jewel tags with block 0 writeable
144 printf("s");
145 uiSkippedBlocks++;
146
147 for (block = uiSkippedBlocks; block <= uiBlocks; block++) {
148 // Skip block 0x0D - it is reserved for internal use and can't be written
149 if (block == 0x0D) {
150 printf("s");
151 uiSkippedBlocks++;
152 continue;
153 }
154 // Skip block 0X0E if lock-bits and OTP shouldn't be written
155 if ((block == 0x0E) && (!write_lock) && (!write_otp)) {
156 printf("s");
157 uiSkippedBlocks++;
158 continue;
159 }
160 // Write block 0x0E partially if lock-bits or OTP shouldn't be written
161 if ((block == 0x0E) && (!write_lock || !write_otp)) {
162 printf("p");
163 uiPartialBlocks++;
164 }
165
166 for (byte = 0; byte < uiBytesPerBlock; byte++) {
167 if ((block == 0x0E) && (byte == 0 || byte == 1) && (!write_lock)) {
168 continue;
169 }
170 if ((block == 0x0E) && (byte > 1) && (!write_otp)) {
171 continue;
172 }
173
174 // Show if the readout went well
175 if (bFailure) {
176 // When a failure occured we need to redo the anti-collision
177 if (nfc_initiator_select_passive_target(pnd, nmJewel, NULL, 0, &nt) <= 0) {
178 ERR("tag was removed");
179 return false;
180 }
181 bFailure = false;
182 }
183
184 req.writee.btCmd = TC_WRITEE;
185 req.writee.btAdd = (block << 3) + byte;
186 req.writee.btDat = ttDump.ttd.abtData[(block << 3) + byte];
187 if (!nfc_initiator_jewel_cmd(pnd, req, &res)) {
188 bFailure = true;
189 }
190 }
191 print_success_or_failure(bFailure, &uiWrittenBlocks);
192 fflush(stdout);
193 }
194 printf("|\n");
195 printf("Done, %d of %d blocks written (%d blocks partial, %d blocks skipped).\n", uiWrittenBlocks, uiBlocks + 1, uiPartialBlocks, uiSkippedBlocks);
196
197 return true;
198}
199
200int
201main(int argc, const char *argv[])
202{
203 bool bReadAction;
204 FILE *pfDump;
205
206 if (argc < 3) {
207 printf("\n");
208 printf("%s r|w <dump.jwd>\n", argv[0]);
209 printf("\n");
210 printf("r|w - Perform read from or write to card\n");
211 printf("<dump.jwd> - JeWel Dump (JWD) used to write (card to JWD) or (JWD to card)\n");
212 printf("\n");
213 exit(EXIT_FAILURE);
214 }
215
216 DBG("\nChecking arguments and settings\n");
217
218 bReadAction = tolower((int)((unsigned char) * (argv[1])) == 'r');
219
220 if (bReadAction) {
221 memset(&ttDump, 0x00, sizeof(ttDump));
222 } else {
223 pfDump = fopen(argv[2], "rb");
224
225 if (pfDump == NULL) {
226 ERR("Could not open dump file: %s\n", argv[2]);
227 exit(EXIT_FAILURE);
228 }
229
230 if (fread(&ttDump, 1, sizeof(ttDump), pfDump) != sizeof(ttDump)) {
231 ERR("Could not read from dump file: %s\n", argv[2]);
232 fclose(pfDump);
233 exit(EXIT_FAILURE);
234 }
235 fclose(pfDump);
236 }
237 DBG("Successfully opened the dump file\n");
238
239 nfc_context *context;
240 nfc_init(&context);
241 if (context == NULL) {
242 ERR("Unable to init libnfc (malloc)");
243 exit(EXIT_FAILURE);
244 }
245
246 // Try to open the NFC device
247 pnd = nfc_open(context, NULL);
248 if (pnd == NULL) {
249 ERR("Error opening NFC device");
250 nfc_exit(context);
251 exit(EXIT_FAILURE);
252 }
253
254 if (nfc_initiator_init(pnd) < 0) {
255 nfc_perror(pnd, "nfc_initiator_init");
256 nfc_close(pnd);
257 nfc_exit(context);
258 exit(EXIT_FAILURE);
259 }
260
261 // Let the device only try once to find a tag
263 nfc_perror(pnd, "nfc_device_set_property_bool");
264 nfc_close(pnd);
265 nfc_exit(context);
266 exit(EXIT_FAILURE);
267 }
268
269 printf("NFC device: %s opened\n", nfc_device_get_name(pnd));
270
271 // Try to find a Jewel tag
272 if (nfc_initiator_select_passive_target(pnd, nmJewel, NULL, 0, &nt) <= 0) {
273 ERR("no tag was found\n");
274 nfc_close(pnd);
275 nfc_exit(context);
276 exit(EXIT_FAILURE);
277 }
278
279 // Get the info from the current tag
280 printf("Found Jewel card with UID: ");
281 size_t szPos;
282 for (szPos = 0; szPos < 4; szPos++) {
283 printf("%02x", nt.nti.nji.btId[szPos]);
284 }
285 printf("\n");
286
287 if (bReadAction) {
288 if (read_card()) {
289 printf("Writing data to file: %s ... ", argv[2]);
290 fflush(stdout);
291 pfDump = fopen(argv[2], "wb");
292 if (pfDump == NULL) {
293 printf("Could not open file: %s\n", argv[2]);
294 nfc_close(pnd);
295 nfc_exit(context);
296 exit(EXIT_FAILURE);
297 }
298 if (fwrite(&ttDump, 1, sizeof(ttDump), pfDump) != sizeof(ttDump)) {
299 printf("Could not write to file: %s\n", argv[2]);
300 fclose(pfDump);
301 nfc_close(pnd);
302 nfc_exit(context);
303 exit(EXIT_FAILURE);
304 }
305 fclose(pfDump);
306 printf("Done.\n");
307 }
308 } else {
309 write_card();
310 }
311
312 nfc_close(pnd);
313 nfc_exit(context);
314 exit(EXIT_SUCCESS);
315}
const char * nfc_device_get_name(nfc_device *pnd)
Returns the device name.
Definition: nfc.c:1209
void nfc_close(nfc_device *pnd)
Close from a NFC device.
Definition: nfc.c:339
nfc_device * nfc_open(nfc_context *context, const nfc_connstring connstring)
Open a NFC device.
Definition: nfc.c:277
void nfc_perror(const nfc_device *pnd, const char *pcString)
Display the last error occured on a nfc_device.
Definition: nfc.c:1183
int nfc_initiator_init(nfc_device *pnd)
Initialize NFC device as initiator (reader)
Definition: nfc.c:493
int nfc_initiator_select_passive_target(nfc_device *pnd, const nfc_modulation nm, const uint8_t *pbtInitData, const size_t szInitData, nfc_target *pnt)
Select a passive or emulated tag.
Definition: nfc.c:562
void nfc_exit(nfc_context *context)
Deinitialize libnfc. Should be called after closing all open devices and before your application term...
Definition: nfc.c:248
void nfc_init(nfc_context **context)
Initialize libnfc. This function must be called before calling any other libnfc function.
Definition: nfc.c:231
int nfc_device_set_property_bool(nfc_device *pnd, const nfc_property property, const bool bEnable)
Set a device's boolean-property value.
Definition: nfc.c:466
bool nfc_initiator_jewel_cmd(nfc_device *pnd, const jewel_req req, jewel_res *pres)
Execute a Jewel Topaz Command.
Definition: jewel.c:56
provide samples structs and functions to manipulate Jewel Topaz tags using libnfc
@ NP_INFINITE_SELECT
Definition: nfc-types.h:115
Provide some examples shared functions like print, parity calculation, options parsing.
#define ERR(...)
Print a error message.
Definition: nfc-utils.h:85
#define DBG(...)
Print a message of standard output only in DEBUG mode.
Definition: nfc-utils.h:59
libnfc interface
NFC library context Struct which contains internal options, references, pointers, etc....
Definition: nfc-internal.h:175
NFC device information.
Definition: nfc-internal.h:190
NFC modulation structure.
Definition: nfc-types.h:342
NFC target structure.
Definition: nfc-types.h:351