]>
git.zerfleddert.de Git - proxmark3-svn/blob - client/cmdcrc.c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2015 iceman <iceman at iuse.se>
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
7 //-----------------------------------------------------------------------------
8 // CRC Calculations from the software reveng commands
9 //-----------------------------------------------------------------------------
16 # define STDIN_FILENO 0
17 # endif /* STDIN_FILENO */
24 #include "reveng/reveng.h"
31 PrintAndLog("%s",msg
);
35 int split(char *str
, char *arr
[MAX_ARGS
]){
38 int maxWords
= MAX_ARGS
;
42 while(isspace(str
[beginIndex
])) {
45 if(str
[beginIndex
] == '\0') {
48 endIndex
= beginIndex
;
49 while (str
[endIndex
] && !isspace(str
[endIndex
])) {
52 int len
= endIndex
- beginIndex
;
53 char *tmp
= calloc(len
+ 1, sizeof(char));
54 memcpy(tmp
, &str
[beginIndex
], len
);
56 //PrintAndLog("cnt: %d, %s",wordCnt-1, arr[wordCnt-1]);
57 beginIndex
= endIndex
;
58 if (wordCnt
== maxWords
)
64 int CmdCrc(const char *Cmd
)
66 char name
[] = {"reveng "};
68 memcpy(Cmd2
, name
, 7);
69 memcpy(Cmd2
+ 7, Cmd
, 50);
71 int argc
= split(Cmd2
, argv
);
73 if (argc
== 3 && memcmp(argv
[1],"-g",2)==0) {
74 CmdrevengSearch(argv
[2]);
76 reveng_main(argc
, argv
);
78 //PrintAndLog("DEBUG argc: %d, %s %s Cmd: %s",argc, argv[0], Cmd2, Cmd);
79 for(int i
= 0; i
< argc
; ++i
) {
86 //returns array of model names and the count of models returning
87 // as well as a width array for the width of each model
88 int GetModels(char *Models
[], int *count
, uint8_t *width
){
90 static model_t model
= {
91 PZERO
, /* no CRC polynomial, user must specify */
93 P_BE
, /* RefIn = false, RefOut = false, plus P_RTJUST setting in reveng.h */
94 PZERO
, /* XorOut = 0 */
95 PZERO
, /* check value unused */
96 NULL
/* no model name */
99 int ibperhx
= 8;//, obperhx = 8;
100 int rflags
= 0, uflags
= 0; /* search and UI flags */
101 poly_t apoly
, crc
, qpoly
= PZERO
, *apolys
= NULL
, *pptr
= NULL
, *qptr
= NULL
;
102 model_t pset
= model
, *candmods
, *mptr
;
104 /* stdin must be binary */
106 _setmode(STDIN_FILENO
, _O_BINARY
);
111 int args
= 0, psets
, pass
;
113 if (width
[0] == 0) { //reveng -D
116 return uerr("no preset models available");
118 for(int mode
= 0; mode
< *count
; ++mode
) {
119 mbynum(&model
, mode
);
121 size_t size
= (model
.name
&& *model
.name
) ? strlen(model
.name
) : 6;
122 char *tmp
= calloc(size
+1, sizeof(char));
124 return uerr("out of memory?");
126 memcpy(tmp
, model
.name
, size
);
128 width
[mode
] = plen(model
.spoly
);
133 if(~model
.flags
& P_MULXN
)
134 return uerr("cannot search for non-Williams compliant models");
136 praloc(&model
.spoly
, (unsigned long)width
[0]);
137 praloc(&model
.init
, (unsigned long)width
[0]);
138 praloc(&model
.xorout
, (unsigned long)width
[0]);
140 if(!plen(model
.spoly
))
141 palloc(&model
.spoly
, (unsigned long)width
[0]);
143 width
[0] = (uint8_t)plen(model
.spoly
);
145 /* special case if qpoly is zero, search to end of range */
149 /* if endianness not specified, try
150 * little-endian then big-endian.
151 * NB: crossed-endian algorithms will not be
154 /* scan against preset models */
155 if (~uflags
& C_FORCE
) {
162 mbynum(&pset
, --psets
);
164 /* skip if different width, or refin or refout don't match */
165 if( plen(pset
.spoly
) != width
[0] || (model
.flags
^ pset
.flags
) & (P_REFIN
| P_REFOUT
))
167 /* skip if the preset doesn't match specified parameters */
168 if (rflags
& R_HAVEP
&& pcmp(&model
.spoly
, &pset
.spoly
))
170 if (rflags
& R_HAVEI
&& psncmp(&model
.init
, &pset
.init
))
172 if (rflags
& R_HAVEX
&& psncmp(&model
.xorout
, &pset
.xorout
))
175 //for additional args (not used yet, maybe future?)
176 apoly
= pclone(pset
.xorout
);
178 if (pset
.flags
& P_REFOUT
)
182 for (qptr
= apolys
; qptr
< pptr
; ++qptr
) {
183 crc
= pcrc(*qptr
, pset
.spoly
, pset
.init
, apoly
, 0);
194 /* the selected model solved all arguments */
197 size_t size
= (pset
.name
&& *pset
.name
) ? strlen(pset
.name
) : 6;
198 //PrintAndLog("Size: %d, %s, count: %d",size,pset.name, Cnt);
199 char *tmp
= calloc(size
+1, sizeof(char));
201 PrintAndLog("out of memory?");
204 width
[Cnt
] = width
[0];
205 memcpy(tmp
, pset
.name
, size
);
213 /* toggle refIn/refOut and reflect arguments */
214 if (~rflags
& R_HAVERI
) {
215 model
.flags
^= P_REFIN
| P_REFOUT
;
216 for (qptr
= apolys
; qptr
< pptr
; ++qptr
) {
217 prevch(qptr
, ibperhx
);
220 } while (~rflags
& R_HAVERI
&& ++pass
< 2);
222 //got everything now free the memory...
224 if (uflags
& C_RESULT
) {
225 for (qptr
= apolys
; qptr
< pptr
; ++qptr
) {
229 if (!(model
.flags
& P_REFIN
) != !(model
.flags
& P_REFOUT
))
230 return uerr("cannot search for crossed-endian models");
234 mptr
= candmods
= reveng(&model
, qpoly
, rflags
, args
, apolys
);
235 if (mptr
&& plen(mptr
->spoly
)) {
238 while (mptr
&& plen(mptr
->spoly
)) {
242 if (~rflags
& R_HAVERI
) {
243 model
.flags
^= P_REFIN
| P_REFOUT
;
244 for (qptr
= apolys
; qptr
< pptr
; ++qptr
) {
245 prevch(qptr
, ibperhx
);
248 } while (~rflags
& R_HAVERI
&& ++pass
< 2);
250 for (qptr
= apolys
; qptr
< pptr
; ++qptr
) {
254 if (~uflags
& C_RESULT
)
255 return uerr("no models found");
263 //inModel = valid model name string - CRC-8
264 //inHexStr = input hex string to calculate crc on
265 //reverse = reverse calc option if true
266 //endian = {0 = calc default endian input and output, b = big endian input and output, B = big endian output, r = right justified
267 // l = little endian input and output, L = little endian output only, t = left justified}
268 //result = calculated crc hex string
269 int RunModel(char *inModel
, char *inHexStr
, bool reverse
, char endian
, char *result
){
271 static model_t model
= {
272 PZERO
, // no CRC polynomial, user must specify
274 P_BE
, // RefIn = false, RefOut = false, plus P_RTJUST setting in reveng.h
276 PZERO
, // check value unused
277 NULL
// no model name
279 int ibperhx
= 8, obperhx
= 8;
280 int rflags
= 0; // search flags
286 // stdin must be binary
288 _setmode(STDIN_FILENO
, _O_BINARY
);
293 if (!(c
= mbynam(&model
, inModel
))) {
294 PrintAndLog("error: preset model '%s' not found. Use reveng -D to list presets.", inModel
);
298 return uerr("no preset models available");
300 rflags
|= R_HAVEP
| R_HAVEI
| R_HAVERI
| R_HAVERO
| R_HAVEX
;
304 case 'b': /* b big-endian (RefIn = false, RefOut = false ) */
305 model
.flags
&= ~P_REFIN
;
308 case 'B': /* B big-endian output (RefOut = false) */
309 model
.flags
&= ~P_REFOUT
;
313 case 'r': /* r right-justified */
314 model
.flags
|= P_RTJUST
;
316 case 'l': /* l little-endian input and output */
317 model
.flags
|= P_REFIN
;
320 case 'L': /* L little-endian output */
321 model
.flags
|= P_REFOUT
;
325 case 't': /* t left-justified */
326 model
.flags
&= ~P_RTJUST
;
329 /* canonicalise the model, so the one we dump is the one we
330 * calculate with (not with -s, spoly may be blank which will
331 * normalise to zero and clear init and xorout.)
337 // v calculate reversed CRC
338 /* Distinct from the -V switch as this causes
339 * the arguments and output to be reversed as well.
345 * if(refout) prev(init); else prev(xorout);
346 * but here the entire argument polynomial is
347 * reflected, not just the characters, so RefIn
348 * and RefOut are not inverted as with -V.
349 * Consequently Init is the mirror image of the
350 * one resulting from -V, and so we have:
352 if (~model
.flags
& P_REFOUT
) {
357 // swap init and xorout
359 model
.init
= model
.xorout
;
360 model
.xorout
= apoly
;
364 /* in the Williams model, xorout is applied after the refout stage.
365 * as refout is part of ptostr(), we reverse xorout here.
367 if (model
.flags
& P_REFOUT
)
370 apoly
= strtop(inHexStr
, model
.flags
, ibperhx
);
375 crc
= pcrc(apoly
, model
.spoly
, model
.init
, model
.xorout
, model
.flags
);
380 string
= ptostr(crc
, model
.flags
, obperhx
);
381 for (int i
= 0; i
< 50; i
++){
382 result
[i
] = string
[i
];
383 if (result
[i
]==0) break;
390 //returns a calloced string (needs to be freed)
391 char *SwapEndianStr(const char *inStr
, const size_t len
, const uint8_t blockSize
){
392 char *tmp
= calloc(len
+1, sizeof(char));
393 for (uint8_t block
=0; block
< (uint8_t)(len
/blockSize
); block
++){
394 for (size_t i
= 0; i
< blockSize
; i
+=2){
395 tmp
[i
+(blockSize
*block
)] = inStr
[(blockSize
-1-i
-1)+(blockSize
*block
)];
396 tmp
[i
+(blockSize
*block
)+1] = inStr
[(blockSize
-1-i
)+(blockSize
*block
)];
402 // takes hex string in and searches for a matching result (hex string must include checksum)
403 int CmdrevengSearch(const char *Cmd
){
404 char inHexStr
[50] = {0x00};
405 int dataLen
= param_getstr(Cmd
, 0, inHexStr
);
406 if (dataLen
< 4) return 0;
412 uint8_t crcChars
= 0;
415 int ans
= GetModels(Models
, &count
, width
);
419 // try each model and get result
420 for (int i
= 0; i
< count
; i
++){
425 // round up to # of characters in this model's crc
426 crcChars
= ((width
[i
]+7)/8)*2;
427 // can't test a model that has more crc digits than our data
428 if (crcChars
>= dataLen
)
430 memset(result
, 0, 30);
431 char *inCRC
= calloc(crcChars
+1, sizeof(char));
432 memcpy(inCRC
, inHexStr
+(dataLen
-crcChars
), crcChars
);
434 char *outHex
= calloc(dataLen
-crcChars
+1, sizeof(char));
435 memcpy(outHex
, inHexStr
, dataLen
-crcChars
);
437 //PrintAndLog("DEBUG: dataLen: %d, crcChars: %d, Model: %s, CRC: %s, width: %d, outHex: %s",dataLen, crcChars, Models[i], inCRC, width[i], outHex);
438 ans
= RunModel(Models
[i
], outHex
, false, 0, result
);
441 if (memcmp(result
, inCRC
, crcChars
)==0){
442 PrintAndLog("\nFound a possible match!\nModel: %s\nValue: %s\n",Models
[i
], result
);
443 //optional - stop searching if found...
447 char *swapEndian
= SwapEndianStr(result
, crcChars
, crcChars
);
448 if (memcmp(swapEndian
, inCRC
, crcChars
)==0){
449 PrintAndLog("\nFound a possible match!\nModel: %s\nValue EndianSwapped: %s\n",Models
[i
], swapEndian
);
450 //optional - stop searching if found...
459 ans
= RunModel(Models
[i
], outHex
, true, 0, revResult
);
462 if (memcmp(revResult
, inCRC
, crcChars
)==0){
463 PrintAndLog("\nFound a possible match!\nModel Reversed: %s\nValue: %s\n",Models
[i
], revResult
);
464 //optional - stop searching if found...
468 char *swapEndian
= SwapEndianStr(revResult
, crcChars
, crcChars
);
469 if (memcmp(swapEndian
, inCRC
, crcChars
)==0){
470 PrintAndLog("\nFound a possible match!\nModel Reversed: %s\nValue EndianSwapped: %s\n",Models
[i
], swapEndian
);
471 //optional - stop searching if found...
483 if (!found
) PrintAndLog("\nNo matches found\n");