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