1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <string.h>
4
+ #include <unistd.h>
5
+ #include <stdbool.h>
6
+ #include <inttypes.h>
7
+ #include "srix.h"
8
+
9
+
10
+ /**
11
+ * Print help message.
12
+ * @param executable name of executable
13
+ */
14
+ static void printUsage (const char * executable ) {
15
+ printf ("Usage: %s [-h] [-p] [-r file] [-w file] [-c] [-o]\n\n" , executable );
16
+ printf ("Options:\n" );
17
+ printf (" -h show this help message\n" );
18
+ printf (" -p print information about NFC tag\n" );
19
+ printf (" -r file read eeprom from a file, if not present read from NFC tag\n" );
20
+ printf (" -w file write eeprom to a file\n" );
21
+ printf (" -c write changes to NFC tag eeprom\n" );
22
+ printf (" -o reset SRIX4K OTP blocks\n" );
23
+ }
24
+
25
+
26
+ /**
27
+ * Initialize srix from NFC.
28
+ * @param srix struct to initialize
29
+ * @return boolean result
30
+ */
31
+ static bool readFromNfc (Srix * srix ) {
32
+ /* Get readers number */
33
+ size_t readersNumber = NfcGetReadersCount (srix );
34
+
35
+ /* Exit if no readers available */
36
+ if (readersNumber == 0 ) {
37
+ fprintf (stderr , "Unable to find an NFC reader\n" );
38
+ return false;
39
+ }
40
+
41
+ /* Print all readers */
42
+ printf ("Readers:\n" );
43
+ for (size_t i = 0 ; i < readersNumber ; i ++ ) {
44
+ printf ("[%" PRIu8 "] -> %s\n" , (uint8_t ) i , NfcGetDescription (srix , (int ) i ));
45
+ }
46
+
47
+ /* Reader selector */
48
+ uint8_t targetReader = 0 ;
49
+ if (readersNumber > 1 ) {
50
+ printf ("Found %zu readers available\n" , readersNumber );
51
+
52
+ /* Retry while input is out of range */
53
+ do {
54
+ printf ("Insert the target reader [0-%zu]: " , readersNumber - 1 );
55
+ /* While input is invalid, clean input and retry */
56
+ char buffer [8 ];
57
+ fgets (buffer , sizeof (buffer ), stdin );
58
+ targetReader = strtol (buffer , (void * ) 0 , 10 );
59
+ } while (targetReader >= readersNumber );
60
+ }
61
+
62
+ /* Init nfc */
63
+ if (!SrixNfcInit (srix , targetReader )) {
64
+ /* If result is null, print error */
65
+ fprintf (stderr , "Selected reader is invalid\n" );
66
+ return false;
67
+ }
68
+
69
+ return true;
70
+ }
71
+
72
+
73
+ /**
74
+ * Initialize srix from a file.
75
+ * @param srix struct to initialize
76
+ * @param filename name of file
77
+ * @return boolean result
78
+ */
79
+ static bool readFromFile (Srix * srix , char * filename ) {
80
+ FILE * eeprom = fopen (filename , "r" );
81
+ if (!eeprom ) {
82
+ fprintf (stderr , "Unable to read input file\n" );
83
+ return false;
84
+ }
85
+
86
+ // Read blocks
87
+ uint32_t blocks [SRIX4K_BLOCKS ];
88
+ for (int i = 0 ; i < SRIX4K_BLOCKS ; i ++ ) {
89
+ uint8_t buffer [SRIX_BLOCK_LENGTH ];
90
+ if (fread (buffer , sizeof (uint8_t ), SRIX_BLOCK_LENGTH , eeprom ) != SRIX_BLOCK_LENGTH ) {
91
+ fprintf (stderr , "Incorrect read value from input file\n" );
92
+ fclose (eeprom );
93
+ return false;
94
+ }
95
+
96
+ blocks [i ] = buffer [0 ] << 24 | buffer [1 ] << 16 | buffer [2 ] << 8 | buffer [3 ];
97
+ }
98
+
99
+ // Read UID
100
+ uint8_t uidBytes [SRIX_UID_LENGTH ];
101
+ if (fread (uidBytes , sizeof (uint8_t ), SRIX_UID_LENGTH , eeprom ) != SRIX_UID_LENGTH ) {
102
+ fprintf (stderr , "Incorrect read value from input file\n" );
103
+ fclose (eeprom );
104
+ return false;
105
+ }
106
+
107
+ uint64_t uid = (uint64_t ) uidBytes [7 ] << 56U | (uint64_t ) uidBytes [6 ] << 48U | (uint64_t ) uidBytes [5 ] << 40U |
108
+ (uint64_t ) uidBytes [4 ] << 32U | (uint64_t ) uidBytes [3 ] << 24U | (uint64_t ) uidBytes [2 ] << 16U |
109
+ (uint64_t ) uidBytes [1 ] << 8U | (uint64_t ) uidBytes [0 ];
110
+
111
+ /* Save data to SRIX struct */
112
+ SrixMemoryInit (srix , blocks , uid );
113
+ fclose (eeprom );
114
+ return true;
115
+ }
116
+
117
+
118
+ /**
119
+ * Save data to a file.
120
+ * @param srix struct to save
121
+ * @param filename name of file
122
+ * @return boolean result
123
+ */
124
+ static bool writeToFile (Srix * srix , char * filename ) {
125
+ FILE * outputFile = fopen (filename , "w" );
126
+ if (!outputFile ) {
127
+ fprintf (stderr , "Unable to open output file\n" );
128
+ return false;
129
+ }
130
+
131
+ // Write blocks
132
+ for (int i = 0 ; i < SRIX4K_BLOCKS ; i ++ ) {
133
+ uint32_t block = * SrixGetBlock (srix , i );
134
+ uint8_t buffer [SRIX_BLOCK_LENGTH ] = {block >> 24 , block >> 16 , block >> 8 , block };
135
+
136
+ if (fwrite (buffer , sizeof (uint8_t ), SRIX_BLOCK_LENGTH , outputFile ) != SRIX_BLOCK_LENGTH ) {
137
+ fprintf (stderr , "Incorrect written value to output file\n" );
138
+ fclose (outputFile );
139
+ return false;
140
+ }
141
+ }
142
+
143
+ // Write UID
144
+ uint64_t uid = SrixGetUid (srix );
145
+ uint8_t uidBytes [SRIX_UID_LENGTH ] = {uid , uid >> 8 , uid >> 16 , uid >> 24 , uid >> 32 ,
146
+ uid >> 40 , uid >> 48 , uid >> 56 };
147
+ if (fwrite (uidBytes , sizeof (uint8_t ), SRIX_UID_LENGTH , outputFile ) != SRIX_UID_LENGTH ) {
148
+ fprintf (stderr , "Incorrect written value to output file\n" );
149
+ fclose (outputFile );
150
+ return false;
151
+ }
152
+
153
+ fclose (outputFile );
154
+ return true;
155
+ }
156
+
157
+ int main (int argc , char * argv []) {
158
+ /* Check if there are arguments */
159
+ if (argc == 1 ) {
160
+ printUsage (argv [0 ]);
161
+ return EXIT_FAILURE ;
162
+ }
163
+
164
+ bool printInformation = false;
165
+ char * readFile = (void * ) 0 ;
166
+ char * writeFile = (void * ) 0 ;
167
+ bool writeTag = false;
168
+ bool resetOTP = false;
169
+
170
+ /* Parse input arguments */
171
+ int param ;
172
+ while ((param = getopt (argc , argv , "hpr:w:co" )) != -1 ) {
173
+ switch (param ) {
174
+ case 'h' :
175
+ printUsage (argv [0 ]);
176
+ return EXIT_SUCCESS ;
177
+ case 'p' :
178
+ printInformation = true;
179
+ break ;
180
+ case 'r' :
181
+ readFile = optarg ;
182
+ break ;
183
+ case 'w' :
184
+ writeFile = optarg ;
185
+ break ;
186
+ case 'c' :
187
+ writeTag = true;
188
+ break ;
189
+ case 'o' :
190
+ resetOTP = true;
191
+ break ;
192
+ default :
193
+ printUsage (argv [0 ]);
194
+ return EXIT_FAILURE ;
195
+ }
196
+ }
197
+
198
+ Srix * srix = SrixNew ();
199
+ if (srix == (void * ) 0 ) {
200
+ fprintf (stderr , "Unable to allocate memory for SRIX\n" );
201
+ return EXIT_FAILURE ;
202
+ }
203
+
204
+ /* Initialize NFC if read tag or write tag is enabled */
205
+ if (!readFile || writeTag ) {
206
+ if (!readFromNfc (srix )) {
207
+ return EXIT_FAILURE ;
208
+ }
209
+ }
210
+
211
+ /* Get data from file */
212
+ if (readFile ) {
213
+ if (!readFromFile (srix , readFile )) {
214
+ return EXIT_FAILURE ;
215
+ }
216
+ }
217
+
218
+ /* Print information in stdout */
219
+ if (printInformation ) {
220
+ printf ("UID: %lu\n\n" , SrixGetUid (srix ));
221
+
222
+ printf ("EEPROM:\n" );
223
+ for (int i = 0 ; i < SRIX4K_BLOCKS ; i ++ ) {
224
+ printf ("[%02X] -> %08X" , i , * SrixGetBlock (srix , i ));
225
+ }
226
+ }
227
+
228
+ /* Reset OTP blocks */
229
+ if (resetOTP ) {
230
+ /* If at least one OTP block is different than
231
+ * 0xFFFFFFFF, reset OTP.
232
+ * OTP Blocks: 0x00, 0x01, 0x02, 0x03, 0x04
233
+ */
234
+ bool toReset = false;
235
+ for (int i = 0x00 ; i <= 0x04 ; i ++ ) {
236
+ if (* SrixGetBlock (srix , i ) != 0xFFFFFFFF ) {
237
+ toReset = true;
238
+ }
239
+ }
240
+
241
+ if (toReset ) {
242
+ /* Decrease block 6 */
243
+ uint32_t block6old = * SrixGetBlock (srix , 0x06 );
244
+ uint32_t block6 =
245
+ (block6old << 24 ) | ((block6old & 0x0C ) << 8 ) | ((block6old & 0x30 ) >> 8 ) | (block6old >> 24 );
246
+
247
+ uint32_t toDecrease = 0x00200000 ;
248
+ if (block6 < toDecrease ) {
249
+ fprintf (stderr , "Unable to decrease block6 counter" );
250
+ return EXIT_FAILURE ;
251
+ } else {
252
+ /* If result will be higher than 0, subtract. */
253
+ block6 -= toDecrease ;
254
+ }
255
+
256
+ block6 = (block6 << 24 ) | ((block6 & 0x0C ) << 8 ) | ((block6 & 0x30 ) >> 8 ) | (block6 >> 24 );
257
+
258
+ SrixModifyBlock (srix , block6 , 0x06 );
259
+ SrixModifyBlock (srix , 0xFFFFFFFF , 0x00 );
260
+ SrixModifyBlock (srix , 0xFFFFFFFF , 0x01 );
261
+ SrixModifyBlock (srix , 0xFFFFFFFF , 0x02 );
262
+ SrixModifyBlock (srix , 0xFFFFFFFF , 0x03 );
263
+ SrixModifyBlock (srix , 0xFFFFFFFF , 0x04 );
264
+ }
265
+ }
266
+
267
+ /* Write result to file */
268
+ if (writeFile ) {
269
+ if (!writeToFile (srix , writeFile )) {
270
+ return EXIT_FAILURE ;
271
+ }
272
+ }
273
+
274
+ /* Write result to tag */
275
+ if (writeTag ) {
276
+ if (SrixWriteBlocks (srix ) != SRIX_SUCCESS ) {
277
+ fprintf (stderr , "Unable to write blocks to SRIX4K" );
278
+ }
279
+ }
280
+
281
+ /* Delete srix at the end */
282
+ SrixDelete (srix );
283
+
284
+ return EXIT_SUCCESS ;
285
+ }
0 commit comments