]> git.zerfleddert.de Git - proxmark3-svn/blob - client/reveng/model.c
CHG: 64?
[proxmark3-svn] / client / reveng / model.c
1 /* model.c
2 * Greg Cook, 26/Jul/2016
3 */
4
5 /* CRC RevEng: arbitrary-precision CRC calculator and algorithm finder
6 * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 Gregory Cook
7 *
8 * This file is part of CRC RevEng.
9 *
10 * CRC RevEng is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * CRC RevEng is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with CRC RevEng. If not, see <https://www.gnu.org/licenses/>.
22 */
23
24 /* 2016-02-22: split off preset.c
25 * 2012-03-03: single-line Williams model string conversion
26 * 2011-09-03: added mrev(), mnovel()
27 * 2011-01-17: fixed ANSI C warnings (except preset models)
28 * 2010-12-26: renamed CRC RevEng
29 * 2010-12-18: minor change to mtostr() output format
30 * 2010-12-15: added mcmp()
31 * 2010-12-14: finished mtostr()
32 * 2010-12-12: started models.c
33 */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <inttypes.h>
39 #include "reveng.h"
40
41 /* Private declarations */
42
43 static const poly_t pzero = PZERO;
44
45 /* Definitions */
46
47 void
48 mcpy(model_t *dest, const model_t *src) {
49 /* Copies the parameters of src to dest.
50 * dest must be an initialised model.
51 */
52 if(!dest || !src) return;
53 pcpy(&dest->spoly, src->spoly);
54 pcpy(&dest->init, src->init);
55 pcpy(&dest->xorout, src->xorout);
56 pcpy(&dest->check, src->check);
57 dest->flags = src->flags;
58 /* link to the name as it is static */
59 dest->name = src->name;
60 }
61
62 void
63 mfree(model_t *model) {
64 /* Frees the parameters of model. */
65 if(!model) return;
66 pfree(&model->spoly);
67 pfree(&model->init);
68 pfree(&model->xorout);
69 pfree(&model->check);
70 /* not name as it is static */
71 /* not model either, it might point to an array! */
72 }
73
74 int
75 mcmp(const model_t *a, const model_t *b) {
76 /* Compares a and b for identical effect, i.e. disregarding
77 * trailing zeroes in parameter polys.
78 * Intended for bsearch().
79 */
80 int result;
81 if(!a || !b) return(!b - !a);
82 if((result = psncmp(&a->spoly, &b->spoly))) return(result);
83 if((result = psncmp(&a->init, &b->init))) return(result);
84 if((a->flags & P_REFIN) && (~b->flags & P_REFIN)) return(1);
85 if((~a->flags & P_REFIN) && (b->flags & P_REFIN)) return(-1);
86 if((a->flags & P_REFOUT) && (~b->flags & P_REFOUT)) return(1);
87 if((~a->flags & P_REFOUT) && (b->flags & P_REFOUT)) return(-1);
88 return(psncmp(&a->xorout, &b->xorout));
89 }
90
91 char *
92 mtostr(const model_t *model) {
93 /* Returns a malloc()-ed string containing a Williams model
94 * record representing the input model.
95 * mcanon() should be called on the argument before printing.
96 */
97 size_t size;
98 char *polystr, *initstr, *xorotstr, *checkstr, strbuf[512], *string = NULL;
99
100 if(!model) return(NULL);
101 polystr = ptostr(model->spoly, P_RTJUST, 4);
102 initstr = ptostr(model->init, P_RTJUST, 4);
103 xorotstr = ptostr(model->xorout, P_RTJUST, 4);
104 checkstr = ptostr(model->check, P_RTJUST, 4);
105
106 sprintf(strbuf, "%lu", plen(model->spoly));
107 size =
108 70
109 + (model->name && *model->name ? 2 + strlen(model->name) : 6)
110 + strlen(strbuf)
111 + (polystr && *polystr ? strlen(polystr) : 6)
112 + (initstr && *initstr ? strlen(initstr) : 6)
113 + (model->flags & P_REFIN ? 4 : 5)
114 + (model->flags & P_REFOUT ? 4 : 5)
115 + (xorotstr && *xorotstr ? strlen(xorotstr) : 6)
116 + (checkstr && *checkstr ? strlen(checkstr) : 6);
117 if((string = malloc(size))) {
118 sprintf(strbuf, "\"%s\"", model->name);
119 sprintf(string,
120 "width=%" PRIu64 ""
121 "poly=0x%s "
122 "init=0x%s "
123 "refin=%s "
124 "refout=%s "
125 "xorout=0x%s "
126 "check=0x%s "
127 "name=%s",
128 plen(model->spoly),
129 polystr && *polystr ? polystr : "(none)",
130 initstr && *initstr ? initstr : "(none)",
131 (model->flags & P_REFIN) ? "true" : "false",
132 (model->flags & P_REFOUT) ? "true" : "false",
133 xorotstr && *xorotstr ? xorotstr : "(none)",
134 checkstr && *checkstr ? checkstr : "(none)",
135 (model->name && *model->name) ? strbuf : "(none)");
136 }
137 free(polystr);
138 free(initstr);
139 free(xorotstr);
140 free(checkstr);
141 if(!string)
142 uerror("cannot allocate memory for model description");
143 return(string);
144 }
145
146 void
147 mcanon(model_t *model) {
148 /* canonicalise a model */
149 unsigned long dlen;
150
151 if(!model) return;
152
153 /* extending on the right here. This preserves the functionality
154 * of a presumed working model.
155 */
156 psnorm(&model->spoly);
157 dlen = plen(model->spoly);
158 praloc(&model->init, dlen);
159 praloc(&model->xorout, dlen);
160
161 /* only calculate Check if missing. Relying on all functions
162 * changing parameters to call mnovel(). This is to ensure that
163 * the Check value stored in the preset table is printed when
164 * the model is dumped. If something goes wrong with the
165 * calculator then the discrepancy with the stored Check value
166 * might be noticed. Storing the Check value with each preset
167 * is highly preferred.
168 */
169 if(!plen(model->check))
170 mcheck(model);
171 }
172
173 void
174 mcheck(model_t *model) {
175 /* calculate a check for the model */
176 poly_t checkstr, check;
177
178 /* generate the check string with the correct bit order */
179 checkstr = strtop("313233343536373839", model->flags, 8);
180 check = pcrc(checkstr, model->spoly, model->init, pzero, model->flags);
181 if(model->flags & P_REFOUT)
182 prev(&check);
183 psum(&check, model->xorout, 0UL);
184 model->check = check;
185 pfree(&checkstr);
186 }
187
188 void
189 mrev(model_t *model) {
190 /* reverse the model to calculate reversed CRCs */
191 /* Here we invert RefIn and RefOut so that the user need only
192 * reverse the order of characters in the arguments, not the
193 * characters themselves. If RefOut=True, the mirror image of
194 * Init seen through RefOut becomes XorOut, and as RefOut
195 * becomes false, the XorOut value moved to Init stays upright.
196 * If RefOut=False, Init transfers to XorOut without reflection
197 * but the new Init must be reflected to present the same image,
198 * as RefOut becomes true.
199 */
200 poly_t temp;
201
202 prcp(&model->spoly);
203 if(model->flags & P_REFOUT)
204 prev(&model->init);
205 else
206 prev(&model->xorout);
207
208 /* exchange init and xorout */
209 temp = model->init;
210 model->init = model->xorout;
211 model->xorout = temp;
212
213 /* invert refin and refout */
214 model->flags ^= P_REFIN | P_REFOUT;
215
216 mnovel(model);
217 }
218
219 void
220 mnovel(model_t *model) {
221 /* remove name and check string from modified model */
222 model->name = NULL;
223 pfree(&model->check);
224 }
Impressum, Datenschutz