]>
cvs.zerfleddert.de Git - proxmark3-svn/blob - client/cmdcrc.c
006804eebd710b42d381550a719a39b2ea8c64c1
   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 */ 
  26 #include "reveng/reveng.h" 
  33         PrintAndLog("%s",msg
); 
  37 int split(char *str
, char *arr
[MAX_ARGS
]){ 
  40         int maxWords 
= MAX_ARGS
; 
  44                 while(isspace(str
[beginIndex
])){ 
  47                 if(str
[beginIndex
] == '\0') 
  49                         endIndex 
= beginIndex
; 
  50                 while (str
[endIndex
] && !isspace(str
[endIndex
])){ 
  53                 int len 
= endIndex 
- beginIndex
; 
  54                 char *tmp 
= calloc(len 
+ 1, sizeof(char)); 
  55                 memcpy(tmp
, &str
[beginIndex
], len
); 
  57                 //PrintAndLog("DEBUG cnt: %d, %s",wordCnt-1, arr[wordCnt-1]); 
  58                 beginIndex 
= endIndex
; 
  59                 if (wordCnt 
== maxWords
) 
  65 int CmdCrc(const char *Cmd
) 
  67         char name
[] = {"reveng "}; 
  69         memcpy(Cmd2
, name
, 7); 
  70         memcpy(Cmd2 
+ 7, Cmd
, 50); 
  72         int argc 
= split(Cmd2
, argv
); 
  74         if (argc 
== 3 && memcmp(argv
[1],"-g",2)==0) { 
  75                 CmdrevengSearch(argv
[2]); 
  77                 reveng_main(argc
, argv
); 
  79         //PrintAndLog("DEBUG argc: %d, %s %s Cmd: %s",argc, argv[0], Cmd2, Cmd); 
  80         for(int i 
= 0; i 
< argc
; ++i
){ 
  87 //returns array of model names and the count of models returning 
  88 //  as well as a width array for the width of each model 
  89 int GetModels(char *Models
[], int *count
, uint8_t *width
){ 
  91         static model_t model 
= { 
  92                 PZERO
,          /* no CRC polynomial, user must specify */ 
  94                 P_BE
,           /* RefIn = false, RefOut = false, plus P_RTJUST setting in reveng.h */ 
  95                 PZERO
,          /* XorOut = 0 */ 
  96                 PZERO
,          /* check value unused */ 
  97                 NULL            
/* no model name */ 
 100         int ibperhx 
= 8;//, obperhx = 8; 
 101         int rflags 
= 0, uflags 
= 0; /* search and UI flags */ 
 102         poly_t apoly
, crc
, qpoly 
= PZERO
, *apolys 
= NULL
, *pptr 
= NULL
, *qptr 
= NULL
; 
 103         model_t pset 
= model
, *candmods
, *mptr
; 
 105         /* stdin must be binary */ 
 107                 _setmode(STDIN_FILENO
, _O_BINARY
); 
 112         int args 
= 0, psets
, pass
; 
 114         if (width
[0] == 0) { //reveng -D 
 117                         return uerr("no preset models available"); 
 119                 for(int mode 
= 0; mode 
< *count
; ++mode
) { 
 120                         mbynum(&model
, mode
); 
 122                         size_t size 
= (model
.name 
&& *model
.name
) ? strlen(model
.name
) : 6; 
 123                         char *tmp 
= calloc(size
+1, sizeof(char)); 
 125                                 return uerr("out of memory?"); 
 127                         memcpy(tmp
, model
.name
, size
); 
 129                         width
[mode
] = plen(model
.spoly
); 
 134                 if(~model
.flags 
& P_MULXN
) 
 135                         return uerr("cannot search for non-Williams compliant models"); 
 137                 praloc(&model
.spoly
, (unsigned long)width
[0]); 
 138                 praloc(&model
.init
, (unsigned long)width
[0]); 
 139                 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 */ 
 150                 /* not going to be sending additional args at this time (maybe future?) 
 152                 // allocate argument array  
 153                 args = argc - optind; 
 154                 if(!(apolys = malloc(args * sizeof(poly_t)))) 
 155                         return uerr("cannot allocate memory for argument list"); 
 157                 for(pptr = apolys; optind < argc; ++optind) { 
 158                         if(uflags & C_INFILE) 
 159                                 *pptr++ = rdpoly(argv[optind], model.flags, ibperhx); 
 161                                 *pptr++ = strtop(argv[optind], model.flags, ibperhx); 
 163                 // exit value of pptr is used hereafter!  
 167                 /* if endianness not specified, try 
 168                  * little-endian then big-endian. 
 169                  * NB: crossed-endian algorithms will not be 
 172                 /* scan against preset models */ 
 173                 if(~uflags 
& C_FORCE
) { 
 178                                 //PrintAndLog("psets: %d",psets); 
 180                                         mbynum(&pset
, --psets
); 
 182                                         /* skip if different width, or refin or refout don't match */ 
 183                                         if(plen(pset
.spoly
) != width
[0] || (model
.flags 
^ pset
.flags
) & (P_REFIN 
| P_REFOUT
)) 
 185                                         /* skip if the preset doesn't match specified parameters */ 
 186                                         if(rflags 
& R_HAVEP 
&& pcmp(&model
.spoly
, &pset
.spoly
)) 
 188                                         if(rflags 
& R_HAVEI 
&& psncmp(&model
.init
, &pset
.init
)) 
 190                                         if(rflags 
& R_HAVEX 
&& psncmp(&model
.xorout
, &pset
.xorout
)) 
 193                                         //for additional args (not used yet, maybe future?) 
 194                                         apoly 
= pclone(pset
.xorout
); 
 195                                         if(pset
.flags 
& P_REFOUT
) 
 198                                         for(qptr 
= apolys
; qptr 
< pptr
; ++qptr
) { 
 199                                                 crc 
= pcrc(*qptr
, pset
.spoly
, pset
.init
, apoly
, 0); 
 209                                                 /* the selected model solved all arguments */ 
 213                                                 size_t size 
= (pset
.name 
&& *pset
.name
) ? strlen(pset
.name
) : 6; 
 214                                                 //PrintAndLog("Size: %d, %s, count: %d",size,pset.name, Cnt); 
 215                                                 char *tmp 
= calloc(size
+1, sizeof(char)); 
 217                                                         PrintAndLog("out of memory?"); 
 220                                                 width
[Cnt
] = width
[0]; 
 221                                                 memcpy(tmp
, pset
.name
, size
); 
 229                                 /* toggle refIn/refOut and reflect arguments */ 
 230                                 if(~rflags 
& R_HAVERI
) { 
 231                                         model
.flags 
^= P_REFIN 
| P_REFOUT
; 
 232                                         for(qptr 
= apolys
; qptr 
< pptr
; ++qptr
) 
 233                                                 prevch(qptr
, ibperhx
); 
 235                         } while(~rflags 
& R_HAVERI 
&& ++pass 
< 2); 
 237                 //got everything now free the memory... 
 239                 if(uflags 
& C_RESULT
) { 
 240                         for(qptr 
= apolys
; qptr 
< pptr
; ++qptr
) 
 243                 if(!(model
.flags 
& P_REFIN
) != !(model
.flags 
& P_REFOUT
)) 
 244                         return uerr("cannot search for crossed-endian models"); 
 248                         mptr 
= candmods 
= reveng(&model
, qpoly
, rflags
, args
, apolys
); 
 249                         if(mptr 
&& plen(mptr
->spoly
)) 
 251                         while(mptr 
&& plen(mptr
->spoly
)) { 
 255                         if(~rflags 
& R_HAVERI
) { 
 256                                 model
.flags 
^= P_REFIN 
| P_REFOUT
; 
 257                                 for(qptr 
= apolys
; qptr 
< pptr
; ++qptr
) 
 258                                         prevch(qptr
, ibperhx
); 
 260                 } while(~rflags 
& R_HAVERI 
&& ++pass 
< 2); 
 261                 for(qptr 
= apolys
; qptr 
< pptr
; ++qptr
) 
 264                 if(~uflags 
& C_RESULT
) 
 265                         return uerr("no models found"); 
 271 //test call to GetModels 
 272 int CmdrevengTest(const char *Cmd
){ 
 275         uint8_t widtharr
[80] = {0}; 
 277         width 
= param_get8(Cmd
, 0); 
 278         //PrintAndLog("width: %d",width); 
 280                 return uerr("Width cannot exceed 89"); 
 283         int ans 
= GetModels(Models
, &count
, widtharr
); 
 286         PrintAndLog("Count: %d",count
); 
 287         for (int i 
= 0; i 
< count
; i
++){ 
 288                 PrintAndLog("Model %d: %s, width: %d",i
,Models
[i
], widtharr
[i
]); 
 295 //inModel = valid model name string - CRC-8 
 296 //inHexStr = input hex string to calculate crc on 
 297 //reverse = reverse calc option if true 
 298 //endian = {0 = calc default endian input and output, b = big endian input and output, B = big endian output, r = right justified 
 299 //          l = little endian input and output, L = little endian output only, t = left justified} 
 300 //result = calculated crc hex string 
 301 int RunModel(char *inModel
, char *inHexStr
, bool reverse
, char endian
, char *result
){ 
 303         static model_t model 
= { 
 304                 PZERO
,          // no CRC polynomial, user must specify 
 306                 P_BE
,             // RefIn = false, RefOut = false, plus P_RTJUST setting in reveng.h 
 308                 PZERO
,          // check value unused  
 309                 NULL              
// no model name  
 311         int ibperhx 
= 8, obperhx 
= 8; 
 312         int rflags 
= 0; // search flags  
 314         unsigned long width 
= 0UL; 
 319         // stdin must be binary 
 321                 _setmode(STDIN_FILENO
, _O_BINARY
); 
 326         if(!(c 
= mbynam(&model
, inModel
))) { 
 327                 fprintf(stderr
,"error: preset model '%s' not found.  Use reveng -D to list presets.\n", inModel
); 
 331                 return uerr("no preset models available"); 
 333         // must set width so that parameter to -ipx is not zeroed  
 334         width 
= plen(model
.spoly
); 
 335         rflags 
|= R_HAVEP 
| R_HAVEI 
| R_HAVERI 
| R_HAVERO 
| R_HAVEX
; 
 339                 case 'b': /* b  big-endian (RefIn = false, RefOut = false ) */ 
 340                         model
.flags 
&= ~P_REFIN
; 
 343                 case 'B': /* B  big-endian output (RefOut = false) */ 
 344                         model
.flags 
&= ~P_REFOUT
; 
 348                 case 'r': /* r  right-justified */ 
 349                         model
.flags 
|= P_RTJUST
; 
 351                 case 'l': /* l  little-endian input and output */ 
 352                         model
.flags 
|= P_REFIN
; 
 355                 case 'L': /* L  little-endian output */ 
 356                         model
.flags 
|= P_REFOUT
; 
 360                 case 't': /* t  left-justified */ 
 361                         model
.flags 
&= ~P_RTJUST
; 
 368                 // v  calculate reversed CRC 
 369                 /* Distinct from the -V switch as this causes 
 370                  * the arguments and output to be reversed as well. 
 376                  *   if(refout) prev(init); else prev(xorout); 
 377                  * but here the entire argument polynomial is 
 378                  * reflected, not just the characters, so RefIn 
 379                  * and RefOut are not inverted as with -V. 
 380                  * Consequently Init is the mirror image of the 
 381                  * one resulting from -V, and so we have: 
 383                 if(~model
.flags 
& P_REFOUT
) { 
 388                 // swap init and xorout 
 390                 model
.init 
= model
.xorout
; 
 391                 model
.xorout 
= apoly
; 
 396         /* if(plen(model.spoly) == 0) { 
 397          *      fprintf(stderr,"%s: no polynomial specified for -%c (add -w WIDTH -p POLY)\n", myname, mode); 
 398          *      exit(EXIT_FAILURE); 
 402         /* in the Williams model, xorout is applied after the refout stage. 
 403          * as refout is part of ptostr(), we reverse xorout here. 
 405         if(model
.flags 
& P_REFOUT
) 
 408         apoly 
= strtop(inHexStr
, model
.flags
, ibperhx
); 
 413         crc 
= pcrc(apoly
, model
.spoly
, model
.init
, model
.xorout
, model
.flags
); 
 418         string 
= ptostr(crc
, model
.flags
, obperhx
); 
 419         for (int i 
= 0; i 
< 50; i
++){ 
 420                 result
[i
] = string
[i
]; 
 421                 if (result
[i
]==0) break; 
 429 //test call to RunModel 
 430 int CmdrevengTestC(const char *Cmd
){ 
 432         char inModel
[30] = {0x00}; 
 433         char inHexStr
[30] = {0x00}; 
 437         dataLen 
= param_getstr(Cmd
, cmdp
++, inModel
); 
 438         if (dataLen 
< 4) return 0; 
 439         dataLen 
= param_getstr(Cmd
, cmdp
++, inHexStr
); 
 440         if (dataLen 
< 4) return 0; 
 441         bool reverse 
= (param_get8(Cmd
, cmdp
++)) ? true : false; 
 442         endian 
= param_getchar(Cmd
, cmdp
++);  
 444         //PrintAndLog("mod: %s, hex: %s, rev %d", inModel, inHexStr, reverse); 
 445         int ans 
= RunModel(inModel
, inHexStr
, reverse
, endian
, result
); 
 448         PrintAndLog("Result: %s",result
); 
 452 //returns a calloced string (needs to be freed) 
 453 char *SwapEndianStr(const char *inStr
, const size_t len
, const uint8_t blockSize
){ 
 454         char *tmp 
= calloc(len
+1, sizeof(char)); 
 455         for (uint8_t block
=0; block 
< (uint8_t)(len
/blockSize
); block
++){ 
 456                 for (size_t i 
= 0; i 
< blockSize
; i
+=2){ 
 457                         tmp
[i
+(blockSize
*block
)] = inStr
[(blockSize
-1-i
-1)+(blockSize
*block
)]; 
 458                         tmp
[i
+(blockSize
*block
)+1] = inStr
[(blockSize
-1-i
)+(blockSize
*block
)]; 
 464 // takes hex string in and searches for a matching result (hex string must include checksum) 
 465 int CmdrevengSearch(const char *Cmd
){ 
 466         char inHexStr
[50] = {0x00}; 
 467         int dataLen 
= param_getstr(Cmd
, 0, inHexStr
); 
 468         if (dataLen 
< 4) return 0; 
 474         uint8_t crcChars 
= 0; 
 477         int ans 
= GetModels(Models
, &count
, width
); 
 481         // try each model and get result 
 482         for (int i 
= 0; i 
< count
; i
++){ 
 487                 // round up to # of characters in this model's crc 
 488                 crcChars 
= ((width
[i
]+7)/8)*2;  
 489                 // can't test a model that has more crc digits than our data 
 490                 if (crcChars 
>= dataLen
)  
 492                 memset(result
, 0, 30); 
 493                 char *inCRC 
= calloc(crcChars
+1, sizeof(char)); 
 494                 memcpy(inCRC
, inHexStr
+(dataLen
-crcChars
), crcChars
); 
 496                 char *outHex 
= calloc(dataLen
-crcChars
+1, sizeof(char)); 
 497                 memcpy(outHex
, inHexStr
, dataLen
-crcChars
); 
 499                 //PrintAndLog("DEBUG: dataLen: %d, crcChars: %d, Model: %s, CRC: %s, width: %d, outHex: %s",dataLen, crcChars, Models[i], inCRC, width[i], outHex); 
 500                 ans 
= RunModel(Models
[i
], outHex
, false, 0, result
); 
 503                         if (memcmp(result
, inCRC
, crcChars
)==0){ 
 504                                 PrintAndLog("\nFound a match!\nModel: %s\nValue: %s\n",Models
[i
], result
); 
 505                                 //optional - stop searching if found... 
 509                                         char *swapEndian 
= SwapEndianStr(result
, crcChars
, crcChars
); 
 510                                         if (memcmp(swapEndian
, inCRC
, crcChars
)==0){ 
 511                                                 PrintAndLog("\nFound a match!\nModel: %s\nValue EndianSwapped: %s\n",Models
[i
], swapEndian
); 
 512                                                 //optional - stop searching if found... 
 521                         ans 
= RunModel(Models
[i
], outHex
, true, 0, revResult
); 
 524                                 if (memcmp(revResult
, inCRC
, crcChars
)==0){ 
 525                                         PrintAndLog("\nFound a match!\nModel Reversed: %s\nValue: %s\n",Models
[i
], revResult
); 
 526                                         //optional - stop searching if found... 
 530                                                 char *swapEndian 
= SwapEndianStr(revResult
, crcChars
, crcChars
); 
 531                                                 if (memcmp(swapEndian
, inCRC
, crcChars
)==0){ 
 532                                                         PrintAndLog("\nFound a match!\nModel Reversed: %s\nValue EndianSwapped: %s\n",Models
[i
], swapEndian
); 
 533                                                         //optional - stop searching if found... 
 545         if (!found
) PrintAndLog("\nNo matches found\n");