]>
Commit | Line | Data |
---|---|---|
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 | } |