]> git.zerfleddert.de Git - proxmark3-svn/blob - client/reveng/model.c
eead6377055fe8092f07315afd80a3c35ae554ee
[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 "reveng.h"
39
40 /* Private declarations */
41
42 static const poly_t pzero = PZERO;
43
44 /* Definitions */
45
46 void
47 mcpy(model_t *dest, const model_t *src) {
48 /* Copies the parameters of src to dest.
49 * dest must be an initialised model.
50 */
51 if(!dest || !src) return;
52 pcpy(&dest->spoly, src->spoly);
53 pcpy(&dest->init, src->init);
54 pcpy(&dest->xorout, src->xorout);
55 pcpy(&dest->check, src->check);
56 dest->flags = src->flags;
57 /* link to the name as it is static */
58 dest->name = src->name;
59 }
60
61 void
62 mfree(model_t *model) {
63 /* Frees the parameters of model. */
64 if(!model) return;
65 pfree(&model->spoly);
66 pfree(&model->init);
67 pfree(&model->xorout);
68 pfree(&model->check);
69 /* not name as it is static */
70 /* not model either, it might point to an array! */
71 }
72
73 int
74 mcmp(const model_t *a, const model_t *b) {
75 /* Compares a and b for identical effect, i.e. disregarding
76 * trailing zeroes in parameter polys.
77 * Intended for bsearch().
78 */
79 int result;
80 if(!a || !b) return(!b - !a);
81 if((result = psncmp(&a->spoly, &b->spoly))) return(result);
82 if((result = psncmp(&a->init, &b->init))) return(result);
83 if((a->flags & P_REFIN) && (~b->flags & P_REFIN)) return(1);
84 if((~a->flags & P_REFIN) && (b->flags & P_REFIN)) return(-1);
85 if((a->flags & P_REFOUT) && (~b->flags & P_REFOUT)) return(1);
86 if((~a->flags & P_REFOUT) && (b->flags & P_REFOUT)) return(-1);
87 return(psncmp(&a->xorout, &b->xorout));
88 }
89
90 char *
91 mtostr(const model_t *model) {
92 /* Returns a malloc()-ed string containing a Williams model
93 * record representing the input model.
94 * mcanon() should be called on the argument before printing.
95 */
96 size_t size;
97 char *polystr, *initstr, *xorotstr, *checkstr, strbuf[512], *string = NULL;
98
99 if(!model) return(NULL);
100 polystr = ptostr(model->spoly, P_RTJUST, 4);
101 initstr = ptostr(model->init, P_RTJUST, 4);
102 xorotstr = ptostr(model->xorout, P_RTJUST, 4);
103 checkstr = ptostr(model->check, P_RTJUST, 4);
104
105 sprintf(strbuf, "%lu", plen(model->spoly));
106 size =
107 70
108 + (model->name && *model->name ? 2 + strlen(model->name) : 6)
109 + strlen(strbuf)
110 + (polystr && *polystr ? strlen(polystr) : 6)
111 + (initstr && *initstr ? strlen(initstr) : 6)
112 + (model->flags & P_REFIN ? 4 : 5)
113 + (model->flags & P_REFOUT ? 4 : 5)
114 + (xorotstr && *xorotstr ? strlen(xorotstr) : 6)
115 + (checkstr && *checkstr ? strlen(checkstr) : 6);
116 if((string = malloc(size))) {
117 sprintf(strbuf, "\"%s\"", model->name);
118 sprintf(string,
119 "width=%lu "
120 "poly=0x%s "
121 "init=0x%s "
122 "refin=%s "
123 "refout=%s "
124 "xorout=0x%s "
125 "check=0x%s "
126 "name=%s",
127 plen(model->spoly),
128 polystr && *polystr ? polystr : "(none)",
129 initstr && *initstr ? initstr : "(none)",
130 (model->flags & P_REFIN) ? "true" : "false",
131 (model->flags & P_REFOUT) ? "true" : "false",
132 xorotstr && *xorotstr ? xorotstr : "(none)",
133 checkstr && *checkstr ? checkstr : "(none)",
134 (model->name && *model->name) ? strbuf : "(none)");
135 }
136 free(polystr);
137 free(initstr);
138 free(xorotstr);
139 free(checkstr);
140 if(!string)
141 uerror("cannot allocate memory for model description");
142 return(string);
143 }
144
145 void
146 mcanon(model_t *model) {
147 /* canonicalise a model */
148 unsigned long dlen;
149
150 if(!model) return;
151
152 /* extending on the right here. This preserves the functionality
153 * of a presumed working model.
154 */
155 psnorm(&model->spoly);
156 dlen = plen(model->spoly);
157 praloc(&model->init, dlen);
158 praloc(&model->xorout, dlen);
159
160 /* only calculate Check if missing. Relying on all functions
161 * changing parameters to call mnovel(). This is to ensure that
162 * the Check value stored in the preset table is printed when
163 * the model is dumped. If something goes wrong with the
164 * calculator then the discrepancy with the stored Check value
165 * might be noticed. Storing the Check value with each preset
166 * is highly preferred.
167 */
168 if(!plen(model->check))
169 mcheck(model);
170 }
171
172 void
173 mcheck(model_t *model) {
174 /* calculate a check for the model */
175 poly_t checkstr, check;
176
177 /* generate the check string with the correct bit order */
178 checkstr = strtop("313233343536373839", model->flags, 8);
179 check = pcrc(checkstr, model->spoly, model->init, pzero, model->flags);
180 if(model->flags & P_REFOUT)
181 prev(&check);
182 psum(&check, model->xorout, 0UL);
183 model->check = check;
184 pfree(&checkstr);
185 }
186
187 void
188 mrev(model_t *model) {
189 /* reverse the model to calculate reversed CRCs */
190 /* Here we invert RefIn and RefOut so that the user need only
191 * reverse the order of characters in the arguments, not the
192 * characters themselves. If RefOut=True, the mirror image of
193 * Init seen through RefOut becomes XorOut, and as RefOut
194 * becomes false, the XorOut value moved to Init stays upright.
195 * If RefOut=False, Init transfers to XorOut without reflection
196 * but the new Init must be reflected to present the same image,
197 * as RefOut becomes true.
198 */
199 poly_t temp;
200
201 prcp(&model->spoly);
202 if(model->flags & P_REFOUT)
203 prev(&model->init);
204 else
205 prev(&model->xorout);
206
207 /* exchange init and xorout */
208 temp = model->init;
209 model->init = model->xorout;
210 model->xorout = temp;
211
212 /* invert refin and refout */
213 model->flags ^= P_REFIN | P_REFOUT;
214
215 mnovel(model);
216 }
217
218 void
219 mnovel(model_t *model) {
220 /* remove name and check string from modified model */
221 model->name = NULL;
222 pfree(&model->check);
223 }
Impressum, Datenschutz