]> git.zerfleddert.de Git - proxmark3-svn/blob - client/cmdcrc.c
reveng RunModel - add endian switches
[proxmark3-svn] / client / cmdcrc.c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2015 iceman <iceman at iuse.se>
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //-----------------------------------------------------------------------------
8 // CRC Calculations from the software reveng commands
9 //-----------------------------------------------------------------------------
10
11 #include <stdlib.h>
12 #ifdef _WIN32
13 # include <io.h>
14 # include <fcntl.h>
15 # ifndef STDIN_FILENO
16 # define STDIN_FILENO 0
17 # endif /* STDIN_FILENO */
18 #endif /* _WIN32 */
19
20 #include <stdio.h>
21 #include <string.h>
22 //#include <stdlib.h>
23 //#include <ctype.h>
24 #include "cmdmain.h"
25 #include "cmdcrc.h"
26 #include "reveng/reveng.h"
27 #include "ui.h"
28 #include "util.h"
29
30 #define MAX_ARGS 20
31
32 int uerr(char *msg){
33 PrintAndLog("%s",msg);
34 return 0;
35 }
36
37 int split(char *str, char *arr[MAX_ARGS]){
38 int beginIndex = 0;
39 int endIndex;
40 int maxWords = MAX_ARGS;
41 int wordCnt = 0;
42
43 while(1){
44 while(isspace(str[beginIndex])){
45 ++beginIndex;
46 }
47 if(str[beginIndex] == '\0')
48 break;
49 endIndex = beginIndex;
50 while (str[endIndex] && !isspace(str[endIndex])){
51 ++endIndex;
52 }
53 int len = endIndex - beginIndex;
54 char *tmp = calloc(len + 1, sizeof(char));
55 memcpy(tmp, &str[beginIndex], len);
56 arr[wordCnt++] = tmp;
57 //PrintAndLog("cnt: %d, %s",wordCnt-1, arr[wordCnt-1]);
58 beginIndex = endIndex;
59 if (wordCnt == maxWords)
60 break;
61 }
62 return wordCnt;
63 }
64
65 int CmdCrc(const char *Cmd)
66 {
67 char name[] = {"reveng "};
68 char Cmd2[50 + 7];
69 memcpy(Cmd2, name, 7);
70 memcpy(Cmd2 + 7, Cmd, 50);
71 char *argv[MAX_ARGS];
72 int argc = split(Cmd2, argv);
73 //PrintAndLog("argc: %d, %s %s Cmd: %s",argc, argv[0], Cmd2, Cmd);
74 reveng_main(argc, argv);
75 for(int i = 0; i < argc; ++i){
76 //puts(arr[i]);
77 free(argv[i]);
78 }
79
80 return 0;
81 }
82
83 int GetModels(char *Models[], int *count, uint32_t *width){
84 /* default values */
85 static model_t model = {
86 PZERO, /* no CRC polynomial, user must specify */
87 PZERO, /* Init = 0 */
88 P_BE, /* RefIn = false, RefOut = false, plus P_RTJUST setting in reveng.h */
89 PZERO, /* XorOut = 0 */
90 PZERO, /* check value unused */
91 NULL /* no model name */
92 };
93 int ibperhx = 8;//, obperhx = 8;
94 int rflags = 0, uflags = 0; /* search and UI flags */
95
96 //unsigned long width = 0UL;
97 //int c, mode = 0, args, psets, pass;
98 poly_t apoly, crc, qpoly = PZERO, *apolys = NULL, *pptr = NULL, *qptr = NULL;
99 model_t pset = model, *candmods, *mptr;
100 //char *string;
101
102 //myname = argv[0];
103
104 /* stdin must be binary */
105 #ifdef _WIN32
106 _setmode(STDIN_FILENO, _O_BINARY);
107 #endif /* _WIN32 */
108
109 SETBMP();
110
111 //pos=0;
112 //optind=1;
113
114 int args = 0, psets, pass;
115 int Cnt = 0;
116 if (*width == 0) { //reveng -D
117 *count = mcount();
118 //PrintAndLog("Count: %d",*count);
119 if(!*count)
120 return uerr("no preset models available");
121
122 for(int mode = 0; mode < *count; ++mode) {
123 mbynum(&model, mode);
124 mcanon(&model);
125 size_t size = (model.name && *model.name) ? strlen(model.name) : 6;
126 //PrintAndLog("Size: %d, %s",size,model.name);
127 char *tmp = calloc(size+1, sizeof(char));
128 if (tmp==NULL)
129 return uerr("out of memory?");
130
131 memcpy(tmp, model.name, size);
132 Models[mode] = tmp;
133 //ufound(&model);
134 }
135 } else { //reveng -s
136
137 if(~model.flags & P_MULXN)
138 return uerr("cannot search for non-Williams compliant models");
139
140 praloc(&model.spoly, *width);
141 praloc(&model.init, *width);
142 praloc(&model.xorout, *width);
143 if(!plen(model.spoly))
144 palloc(&model.spoly, *width);
145 else
146 *width = plen(model.spoly);
147
148 /* special case if qpoly is zero, search to end of range */
149 if(!ptst(qpoly))
150 rflags &= ~R_HAVEQ;
151
152
153 /* not going to be sending additional args
154
155 // allocate argument array
156 args = argc - optind;
157 if(!(apolys = malloc(args * sizeof(poly_t))))
158 return uerr("cannot allocate memory for argument list");
159
160 for(pptr = apolys; optind < argc; ++optind) {
161 if(uflags & C_INFILE)
162 *pptr++ = rdpoly(argv[optind], model.flags, ibperhx);
163 else
164 *pptr++ = strtop(argv[optind], model.flags, ibperhx);
165 }
166 // exit value of pptr is used hereafter!
167
168 */
169
170 /* if endianness not specified, try
171 * little-endian then big-endian.
172 * NB: crossed-endian algorithms will not be
173 * searched.
174 */
175 /* scan against preset models */
176 if(~uflags & C_FORCE) {
177 pass = 0;
178 Cnt = 0;
179 do {
180 psets = mcount();
181 //PrintAndLog("psets: %d",psets);
182 while(psets) {
183 mbynum(&pset, --psets);
184
185 /* skip if different width, or refin or refout don't match */
186 if(plen(pset.spoly) != *width || (model.flags ^ pset.flags) & (P_REFIN | P_REFOUT))
187 continue;
188 /* skip if the preset doesn't match specified parameters */
189 if(rflags & R_HAVEP && pcmp(&model.spoly, &pset.spoly))
190 continue;
191 if(rflags & R_HAVEI && psncmp(&model.init, &pset.init))
192 continue;
193 if(rflags & R_HAVEX && psncmp(&model.xorout, &pset.xorout))
194 continue;
195
196 apoly = pclone(pset.xorout);
197 if(pset.flags & P_REFOUT)
198 prev(&apoly);
199 for(qptr = apolys; qptr < pptr; ++qptr) {
200 crc = pcrc(*qptr, pset.spoly, pset.init, apoly, 0);
201 if(ptst(crc)) {
202 pfree(&crc);
203 break;
204 } else
205 pfree(&crc);
206 }
207 pfree(&apoly);
208 if(qptr == pptr) {
209 /* the selected model solved all arguments */
210 mcanon(&pset);
211
212 size_t size = (pset.name && *pset.name) ? strlen(pset.name) : 6;
213 //PrintAndLog("Size: %d, %s, count: %d",size,pset.name, Cnt);
214 char *tmp = calloc(size+1, sizeof(char));
215 if (tmp==NULL){
216 PrintAndLog("out of memory?");
217 return 0;
218 }
219 memcpy(tmp, pset.name, size);
220 Models[Cnt++] = tmp;
221 *count = Cnt;
222 //ufound(&pset);
223 uflags |= C_RESULT;
224 }
225 }
226 mfree(&pset);
227
228 /* toggle refIn/refOut and reflect arguments */
229 if(~rflags & R_HAVERI) {
230 model.flags ^= P_REFIN | P_REFOUT;
231 for(qptr = apolys; qptr < pptr; ++qptr)
232 prevch(qptr, ibperhx);
233 }
234 } while(~rflags & R_HAVERI && ++pass < 2);
235 }
236 if(uflags & C_RESULT) {
237 for(qptr = apolys; qptr < pptr; ++qptr)
238 pfree(qptr);
239 return 1;
240 //exit(EXIT_SUCCESS);
241 }
242 if(!(model.flags & P_REFIN) != !(model.flags & P_REFOUT))
243 return uerr("cannot search for crossed-endian models");
244 pass = 0;
245 do {
246 mptr = candmods = reveng(&model, qpoly, rflags, args, apolys);
247 if(mptr && plen(mptr->spoly))
248 uflags |= C_RESULT;
249 while(mptr && plen(mptr->spoly)) {
250 /* results were printed by the callback
251 * string = mtostr(mptr);
252 * puts(string);
253 * free(string);
254 */
255 mfree(mptr++);
256 }
257 free(candmods);
258 if(~rflags & R_HAVERI) {
259 model.flags ^= P_REFIN | P_REFOUT;
260 for(qptr = apolys; qptr < pptr; ++qptr)
261 prevch(qptr, ibperhx);
262 }
263 } while(~rflags & R_HAVERI && ++pass < 2);
264 for(qptr = apolys; qptr < pptr; ++qptr)
265 pfree(qptr);
266 free(apolys);
267 if(~uflags & C_RESULT)
268 return uerr("no models found");
269
270
271 }
272 //PrintAndLog("DONE");
273 return 1;
274 }
275
276 //test call to GetModels
277 int CmdrevengTest(const char *Cmd){
278 char *Models[80];
279 int count = 0;
280 uint32_t width = 0;
281 width = param_get8(Cmd, 0);
282 //PrintAndLog("width: %d",width);
283 if (width > 89)
284 return uerr("Width cannot exceed 89");
285
286 int ans = GetModels(Models, &count, &width);
287 if (!ans) return 0;
288
289 PrintAndLog("Count: %d",count);
290 for (int i = 0; i < count; i++){
291 PrintAndLog("Model %d: %s",i,Models[i]);
292 free(Models[i]);
293 }
294 return 1;
295 }
296
297 //-c || -v
298 //inModel = valid model name string - CRC-8
299 //inHexStr = input hex string to calculate crc on
300 //reverse = reverse calc option if true
301 //endian = {0 = calc default endian input and output, b = big endian input and output, B = big endian output, r = right justified
302 // l = little endian input and output, L = little endian output only, t = left justified}
303 //result = calculated crc hex string
304 int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *result){
305 /* default values */
306 static model_t model = {
307 PZERO, // no CRC polynomial, user must specify
308 PZERO, // Init = 0
309 P_BE, // RefIn = false, RefOut = false, plus P_RTJUST setting in reveng.h
310 PZERO, // XorOut = 0
311 PZERO, // check value unused
312 NULL // no model name
313 };
314 int ibperhx = 8, obperhx = 8;
315 int rflags = 0; // search flags
316 int c;
317 unsigned long width = 0UL;
318 poly_t apoly, crc;
319
320 char *string;
321
322 // stdin must be binary
323 #ifdef _WIN32
324 _setmode(STDIN_FILENO, _O_BINARY);
325 #endif /* _WIN32 */
326
327 SETBMP();
328 //set model
329 if(!(c = mbynam(&model, inModel))) {
330 fprintf(stderr,"error: preset model '%s' not found. Use reveng -D to list presets.\n", inModel);
331 return 0;
332 }
333 if(c < 0)
334 return uerr("no preset models available");
335
336 // must set width so that parameter to -ipx is not zeroed
337 width = plen(model.spoly);
338 rflags |= R_HAVEP | R_HAVEI | R_HAVERI | R_HAVERO | R_HAVEX;
339
340 //set flags
341 switch (endian) {
342 case 'b': /* b big-endian (RefIn = false, RefOut = false ) */
343 model.flags &= ~P_REFIN;
344 rflags |= R_HAVERI;
345 /* fall through: */
346 case 'B': /* B big-endian output (RefOut = false) */
347 model.flags &= ~P_REFOUT;
348 rflags |= R_HAVERO;
349 mnovel(&model);
350 /* fall through: */
351 case 'r': /* r right-justified */
352 model.flags |= P_RTJUST;
353 break;
354 case 'l': /* l little-endian input and output */
355 model.flags |= P_REFIN;
356 rflags |= R_HAVERI;
357 /* fall through: */
358 case 'L': /* L little-endian output */
359 model.flags |= P_REFOUT;
360 rflags |= R_HAVERO;
361 mnovel(&model);
362 /* fall through: */
363 case 't': /* t left-justified */
364 model.flags &= ~P_RTJUST;
365 break;
366 }
367
368 mcanon(&model);
369
370 if (reverse) {
371 // v calculate reversed CRC
372 /* Distinct from the -V switch as this causes
373 * the arguments and output to be reversed as well.
374 */
375 // reciprocate Poly
376 prcp(&model.spoly);
377
378 /* mrev() does:
379 * if(refout) prev(init); else prev(xorout);
380 * but here the entire argument polynomial is
381 * reflected, not just the characters, so RefIn
382 * and RefOut are not inverted as with -V.
383 * Consequently Init is the mirror image of the
384 * one resulting from -V, and so we have:
385 */
386 if(~model.flags & P_REFOUT) {
387 prev(&model.init);
388 prev(&model.xorout);
389 }
390
391 // swap init and xorout
392 apoly = model.init;
393 model.init = model.xorout;
394 model.xorout = apoly;
395 }
396 // c calculate CRC
397
398 // validate inputs
399 /* if(plen(model.spoly) == 0) {
400 * fprintf(stderr,"%s: no polynomial specified for -%c (add -w WIDTH -p POLY)\n", myname, mode);
401 * exit(EXIT_FAILURE);
402 * }
403 */
404
405 /* in the Williams model, xorout is applied after the refout stage.
406 * as refout is part of ptostr(), we reverse xorout here.
407 */
408 if(model.flags & P_REFOUT)
409 prev(&model.xorout);
410
411 apoly = strtop(inHexStr, model.flags, ibperhx);
412
413 if(reverse)
414 prev(&apoly);
415
416 crc = pcrc(apoly, model.spoly, model.init, model.xorout, model.flags);
417
418 if(reverse)
419 prev(&crc);
420
421 string = ptostr(crc, model.flags, obperhx);
422 for (int i = 0; i < 50; i++){
423 result[i] = string[i];
424 if (result[i]==0) break;
425 }
426 free(string);
427 pfree(&crc);
428 pfree(&apoly);
429 return 1;
430 }
431
432 //test call to RunModel
433 int CmdrevengTestC(const char *Cmd){
434 int cmdp = 0;
435 char inModel[30] = {0x00};
436 char inHexStr[30] = {0x00};
437 char result[30];
438 int dataLen;
439 char endian = 0;
440 dataLen = param_getstr(Cmd, cmdp++, inModel);
441 if (dataLen < 4) return 0;
442 dataLen = param_getstr(Cmd, cmdp++, inHexStr);
443 if (dataLen < 4) return 0;
444 bool reverse = (param_get8(Cmd, cmdp++)) ? true : false;
445 endian = param_getchar(Cmd, cmdp++);
446
447 //PrintAndLog("mod: %s, hex: %s, rev %d", inModel, inHexStr, reverse);
448 int ans = RunModel(inModel, inHexStr, reverse, endian, result);
449 if (!ans) return 0;
450
451 PrintAndLog("Result: %s",result);
452 return 1;
453 }
Impressum, Datenschutz