diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | fake-lib.c | 214 | ||||
-rw-r--r-- | fake-lib.h | 4 | ||||
-rw-r--r-- | fake-msi.c | 39 | ||||
-rw-r--r-- | md5.c | 271 |
5 files changed, 275 insertions, 255 deletions
diff --git a/Makefile.am b/Makefile.am index 56da99e..6fb2062 100644 --- a/Makefile.am +++ b/Makefile.am | |||
@@ -6,7 +6,7 @@ lib_LTLIBRARIES = libwinterop.so.la libmsi.so.la libpreload.la | |||
6 | 6 | ||
7 | libwinterop_so_la_SOURCES = fake-winterop.c fake-lib.c fake-lib.h | 7 | libwinterop_so_la_SOURCES = fake-winterop.c fake-lib.c fake-lib.h |
8 | 8 | ||
9 | libmsi_so_la_SOURCES = fake-msi.c fake-lib.c fake-lib.h | 9 | libmsi_so_la_SOURCES = fake-msi.c fake-lib.c fake-lib.h md5.c |
10 | 10 | ||
11 | libpreload_la_SOURCES = preload.c | 11 | libpreload_la_SOURCES = preload.c |
12 | libpreload_la_LDFLAGS = -ldl | 12 | libpreload_la_LDFLAGS = -ldl |
@@ -140,217 +140,3 @@ unsigned le(const unsigned char *buf, size_t len, size_t off, size_t nbytes) | |||
140 | } | 140 | } |
141 | return toret; | 141 | return toret; |
142 | } | 142 | } |
143 | |||
144 | /* ---------------------------------------------------------------------- | ||
145 | * Core MD5 algorithm: processes 16-word blocks into a message digest. | ||
146 | */ | ||
147 | |||
148 | typedef struct { | ||
149 | uint32_t h[4]; | ||
150 | } MD5_Core_State; | ||
151 | |||
152 | struct MD5Context { | ||
153 | MD5_Core_State core; | ||
154 | unsigned char block[64]; | ||
155 | int blkused; | ||
156 | uint32_t lenhi, lenlo; | ||
157 | }; | ||
158 | |||
159 | #define F(x,y,z) ( ((x) & (y)) | ((~(x)) & (z)) ) | ||
160 | #define G(x,y,z) ( ((x) & (z)) | ((~(z)) & (y)) ) | ||
161 | #define H(x,y,z) ( (x) ^ (y) ^ (z) ) | ||
162 | #define I(x,y,z) ( (y) ^ ( (x) | ~(z) ) ) | ||
163 | |||
164 | #define rol(x,y) ( ((x) << (y)) | (((uint32_t)x) >> (32-y)) ) | ||
165 | |||
166 | #define subround(f,w,x,y,z,k,s,ti) \ | ||
167 | w = x + rol(w + f(x,y,z) + block[k] + ti, s) | ||
168 | |||
169 | static void MD5_Core_Init(MD5_Core_State * s) | ||
170 | { | ||
171 | s->h[0] = 0x67452301; | ||
172 | s->h[1] = 0xefcdab89; | ||
173 | s->h[2] = 0x98badcfe; | ||
174 | s->h[3] = 0x10325476; | ||
175 | } | ||
176 | |||
177 | static void MD5_Block(MD5_Core_State * s, uint32_t * block) | ||
178 | { | ||
179 | uint32_t a, b, c, d; | ||
180 | |||
181 | a = s->h[0]; | ||
182 | b = s->h[1]; | ||
183 | c = s->h[2]; | ||
184 | d = s->h[3]; | ||
185 | |||
186 | subround(F, a, b, c, d, 0, 7, 0xd76aa478); | ||
187 | subround(F, d, a, b, c, 1, 12, 0xe8c7b756); | ||
188 | subround(F, c, d, a, b, 2, 17, 0x242070db); | ||
189 | subround(F, b, c, d, a, 3, 22, 0xc1bdceee); | ||
190 | subround(F, a, b, c, d, 4, 7, 0xf57c0faf); | ||
191 | subround(F, d, a, b, c, 5, 12, 0x4787c62a); | ||
192 | subround(F, c, d, a, b, 6, 17, 0xa8304613); | ||
193 | subround(F, b, c, d, a, 7, 22, 0xfd469501); | ||
194 | subround(F, a, b, c, d, 8, 7, 0x698098d8); | ||
195 | subround(F, d, a, b, c, 9, 12, 0x8b44f7af); | ||
196 | subround(F, c, d, a, b, 10, 17, 0xffff5bb1); | ||
197 | subround(F, b, c, d, a, 11, 22, 0x895cd7be); | ||
198 | subround(F, a, b, c, d, 12, 7, 0x6b901122); | ||
199 | subround(F, d, a, b, c, 13, 12, 0xfd987193); | ||
200 | subround(F, c, d, a, b, 14, 17, 0xa679438e); | ||
201 | subround(F, b, c, d, a, 15, 22, 0x49b40821); | ||
202 | subround(G, a, b, c, d, 1, 5, 0xf61e2562); | ||
203 | subround(G, d, a, b, c, 6, 9, 0xc040b340); | ||
204 | subround(G, c, d, a, b, 11, 14, 0x265e5a51); | ||
205 | subround(G, b, c, d, a, 0, 20, 0xe9b6c7aa); | ||
206 | subround(G, a, b, c, d, 5, 5, 0xd62f105d); | ||
207 | subround(G, d, a, b, c, 10, 9, 0x02441453); | ||
208 | subround(G, c, d, a, b, 15, 14, 0xd8a1e681); | ||
209 | subround(G, b, c, d, a, 4, 20, 0xe7d3fbc8); | ||
210 | subround(G, a, b, c, d, 9, 5, 0x21e1cde6); | ||
211 | subround(G, d, a, b, c, 14, 9, 0xc33707d6); | ||
212 | subround(G, c, d, a, b, 3, 14, 0xf4d50d87); | ||
213 | subround(G, b, c, d, a, 8, 20, 0x455a14ed); | ||
214 | subround(G, a, b, c, d, 13, 5, 0xa9e3e905); | ||
215 | subround(G, d, a, b, c, 2, 9, 0xfcefa3f8); | ||
216 | subround(G, c, d, a, b, 7, 14, 0x676f02d9); | ||
217 | subround(G, b, c, d, a, 12, 20, 0x8d2a4c8a); | ||
218 | subround(H, a, b, c, d, 5, 4, 0xfffa3942); | ||
219 | subround(H, d, a, b, c, 8, 11, 0x8771f681); | ||
220 | subround(H, c, d, a, b, 11, 16, 0x6d9d6122); | ||
221 | subround(H, b, c, d, a, 14, 23, 0xfde5380c); | ||
222 | subround(H, a, b, c, d, 1, 4, 0xa4beea44); | ||
223 | subround(H, d, a, b, c, 4, 11, 0x4bdecfa9); | ||
224 | subround(H, c, d, a, b, 7, 16, 0xf6bb4b60); | ||
225 | subround(H, b, c, d, a, 10, 23, 0xbebfbc70); | ||
226 | subround(H, a, b, c, d, 13, 4, 0x289b7ec6); | ||
227 | subround(H, d, a, b, c, 0, 11, 0xeaa127fa); | ||
228 | subround(H, c, d, a, b, 3, 16, 0xd4ef3085); | ||
229 | subround(H, b, c, d, a, 6, 23, 0x04881d05); | ||
230 | subround(H, a, b, c, d, 9, 4, 0xd9d4d039); | ||
231 | subround(H, d, a, b, c, 12, 11, 0xe6db99e5); | ||
232 | subround(H, c, d, a, b, 15, 16, 0x1fa27cf8); | ||
233 | subround(H, b, c, d, a, 2, 23, 0xc4ac5665); | ||
234 | subround(I, a, b, c, d, 0, 6, 0xf4292244); | ||
235 | subround(I, d, a, b, c, 7, 10, 0x432aff97); | ||
236 | subround(I, c, d, a, b, 14, 15, 0xab9423a7); | ||
237 | subround(I, b, c, d, a, 5, 21, 0xfc93a039); | ||
238 | subround(I, a, b, c, d, 12, 6, 0x655b59c3); | ||
239 | subround(I, d, a, b, c, 3, 10, 0x8f0ccc92); | ||
240 | subround(I, c, d, a, b, 10, 15, 0xffeff47d); | ||
241 | subround(I, b, c, d, a, 1, 21, 0x85845dd1); | ||
242 | subround(I, a, b, c, d, 8, 6, 0x6fa87e4f); | ||
243 | subround(I, d, a, b, c, 15, 10, 0xfe2ce6e0); | ||
244 | subround(I, c, d, a, b, 6, 15, 0xa3014314); | ||
245 | subround(I, b, c, d, a, 13, 21, 0x4e0811a1); | ||
246 | subround(I, a, b, c, d, 4, 6, 0xf7537e82); | ||
247 | subround(I, d, a, b, c, 11, 10, 0xbd3af235); | ||
248 | subround(I, c, d, a, b, 2, 15, 0x2ad7d2bb); | ||
249 | subround(I, b, c, d, a, 9, 21, 0xeb86d391); | ||
250 | |||
251 | s->h[0] += a; | ||
252 | s->h[1] += b; | ||
253 | s->h[2] += c; | ||
254 | s->h[3] += d; | ||
255 | } | ||
256 | |||
257 | /* ---------------------------------------------------------------------- | ||
258 | * Outer MD5 algorithm: take an arbitrary length byte string, | ||
259 | * convert it into 16-word blocks with the prescribed padding at | ||
260 | * the end, and pass those blocks to the core MD5 algorithm. | ||
261 | */ | ||
262 | |||
263 | #define BLKSIZE 64 | ||
264 | |||
265 | void MD5Init(struct MD5Context *s) | ||
266 | { | ||
267 | MD5_Core_Init(&s->core); | ||
268 | s->blkused = 0; | ||
269 | s->lenhi = s->lenlo = 0; | ||
270 | } | ||
271 | |||
272 | void MD5Update(struct MD5Context *s, unsigned char const *p, unsigned len) | ||
273 | { | ||
274 | unsigned char *q = (unsigned char *) p; | ||
275 | uint32_t wordblock[16]; | ||
276 | uint32_t lenw = len; | ||
277 | int i; | ||
278 | |||
279 | /* | ||
280 | * Update the length field. | ||
281 | */ | ||
282 | s->lenlo += lenw; | ||
283 | s->lenhi += (s->lenlo < lenw); | ||
284 | |||
285 | if (s->blkused + len < BLKSIZE) { | ||
286 | /* | ||
287 | * Trivial case: just add to the block. | ||
288 | */ | ||
289 | memcpy(s->block + s->blkused, q, len); | ||
290 | s->blkused += len; | ||
291 | } else { | ||
292 | /* | ||
293 | * We must complete and process at least one block. | ||
294 | */ | ||
295 | while (s->blkused + len >= BLKSIZE) { | ||
296 | memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused); | ||
297 | q += BLKSIZE - s->blkused; | ||
298 | len -= BLKSIZE - s->blkused; | ||
299 | /* Now process the block. Gather bytes little-endian into words */ | ||
300 | for (i = 0; i < 16; i++) { | ||
301 | wordblock[i] = | ||
302 | (((uint32_t) s->block[i * 4 + 3]) << 24) | | ||
303 | (((uint32_t) s->block[i * 4 + 2]) << 16) | | ||
304 | (((uint32_t) s->block[i * 4 + 1]) << 8) | | ||
305 | (((uint32_t) s->block[i * 4 + 0]) << 0); | ||
306 | } | ||
307 | MD5_Block(&s->core, wordblock); | ||
308 | s->blkused = 0; | ||
309 | } | ||
310 | memcpy(s->block, q, len); | ||
311 | s->blkused = len; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | void MD5Final(uint32_t output[4], struct MD5Context *s) | ||
316 | { | ||
317 | int i; | ||
318 | unsigned pad; | ||
319 | unsigned char c[64]; | ||
320 | uint32_t lenhi, lenlo; | ||
321 | |||
322 | if (s->blkused >= 56) | ||
323 | pad = 56 + 64 - s->blkused; | ||
324 | else | ||
325 | pad = 56 - s->blkused; | ||
326 | |||
327 | lenhi = (s->lenhi << 3) | (s->lenlo >> (32 - 3)); | ||
328 | lenlo = (s->lenlo << 3); | ||
329 | |||
330 | memset(c, 0, pad); | ||
331 | c[0] = 0x80; | ||
332 | MD5Update(s, c, pad); | ||
333 | |||
334 | c[7] = (lenhi >> 24) & 0xFF; | ||
335 | c[6] = (lenhi >> 16) & 0xFF; | ||
336 | c[5] = (lenhi >> 8) & 0xFF; | ||
337 | c[4] = (lenhi >> 0) & 0xFF; | ||
338 | c[3] = (lenlo >> 24) & 0xFF; | ||
339 | c[2] = (lenlo >> 16) & 0xFF; | ||
340 | c[1] = (lenlo >> 8) & 0xFF; | ||
341 | c[0] = (lenlo >> 0) & 0xFF; | ||
342 | |||
343 | MD5Update(s, c, 8); | ||
344 | |||
345 | for (i = 0; i < 4; i++) | ||
346 | output[i] = s->core.h[i]; | ||
347 | } | ||
348 | |||
349 | void MD5Simple(void const *p, unsigned len, uint32_t output[4]) | ||
350 | { | ||
351 | struct MD5Context s; | ||
352 | |||
353 | MD5Init(&s); | ||
354 | MD5Update(&s, (unsigned char const *)p, len); | ||
355 | MD5Final(output, &s); | ||
356 | } | ||
@@ -1,3 +1,6 @@ | |||
1 | #include <uchar.h> | ||
2 | #include <stdlib.h> | ||
3 | |||
1 | char *ascii(const char16_t *wstr, bool translate_slashes); | 4 | char *ascii(const char16_t *wstr, bool translate_slashes); |
2 | void system_argv(const char *cmd, ...); | 5 | void system_argv(const char *cmd, ...); |
3 | void system_argv_array(char **args); | 6 | void system_argv_array(char **args); |
@@ -6,7 +9,6 @@ void *smalloc(size_t size); | |||
6 | void *srealloc(void *ptr, size_t size); | 9 | void *srealloc(void *ptr, size_t size); |
7 | char *dupcat(const char *str, ...); | 10 | char *dupcat(const char *str, ...); |
8 | unsigned le(const unsigned char *buf, size_t len, size_t off, size_t nbytes); | 11 | unsigned le(const unsigned char *buf, size_t len, size_t off, size_t nbytes); |
9 | void MD5Simple(void const *p, unsigned len, uint32_t output[4]); | ||
10 | 12 | ||
11 | #define snew(type) ((type *)smalloc(sizeof(type))) | 13 | #define snew(type) ((type *)smalloc(sizeof(type))) |
12 | #define snewn(n,type) ((type *)smalloc((n)*sizeof(type))) | 14 | #define snewn(n,type) ((type *)smalloc((n)*sizeof(type))) |
@@ -199,45 +199,6 @@ uint32_t MsiGetFileVersionW(const char16_t *filename, | |||
199 | return toret; | 199 | return toret; |
200 | } | 200 | } |
201 | 201 | ||
202 | struct MsiHash { | ||
203 | uint32_t structure_size; | ||
204 | uint32_t hash_words[4]; | ||
205 | }; | ||
206 | |||
207 | uint32_t MsiGetFileHashW(const char16_t *filename, uint32_t options, | ||
208 | struct MsiHash *hash) | ||
209 | { | ||
210 | char *fname = ascii(filename, true); | ||
211 | int fd = -1; | ||
212 | void *mapv = MAP_FAILED; | ||
213 | uint32_t toret; | ||
214 | |||
215 | fd = open(fname, O_RDONLY); | ||
216 | if (fd < 0) | ||
217 | err(1, "%s: open", fname); | ||
218 | struct stat st; | ||
219 | if (fstat(fd, &st) < 0) | ||
220 | err(1, "%s: fstat", fname); | ||
221 | size_t fsize = st.st_size; | ||
222 | mapv = mmap(NULL, fsize, PROT_READ, MAP_PRIVATE, fd, 0); | ||
223 | if (mapv == MAP_FAILED) | ||
224 | err(1, "%s: mmap", fname); | ||
225 | |||
226 | MD5Simple(mapv, fsize, hash->hash_words); | ||
227 | warnx("MsiGetFileHash(%s) -> %08x:%08x:%08x:%08x", fname, | ||
228 | (unsigned)hash->hash_words[0], (unsigned)hash->hash_words[1], | ||
229 | (unsigned)hash->hash_words[2], (unsigned)hash->hash_words[3]); | ||
230 | toret = 0; | ||
231 | |||
232 | cleanup: | ||
233 | if (mapv != MAP_FAILED) | ||
234 | munmap(mapv, fsize); | ||
235 | if (fd != -1) | ||
236 | close(fd); | ||
237 | sfree(fname); | ||
238 | return toret; | ||
239 | } | ||
240 | |||
241 | typedef struct MsiTypePrefix { | 202 | typedef struct MsiTypePrefix { |
242 | enum { MAIN, VIEW, RECORD } type; | 203 | enum { MAIN, VIEW, RECORD } type; |
243 | } MsiTypePrefix; | 204 | } MsiTypePrefix; |
@@ -0,0 +1,271 @@ | |||
1 | /* | ||
2 | * Implement MsiGetFileHash(). | ||
3 | * | ||
4 | * Experimenting with a small test program on Windows calling the | ||
5 | * original version of that function suggests that the hash it | ||
6 | * implements is just MD5, only repackaged as an array of four | ||
7 | * little-endian 32-bit words instead of the usual 16 bytes. | ||
8 | */ | ||
9 | |||
10 | #include <stdio.h> | ||
11 | #include <stdint.h> | ||
12 | #include <string.h> | ||
13 | #include <stdbool.h> | ||
14 | |||
15 | #include <sys/types.h> | ||
16 | #include <sys/stat.h> | ||
17 | #include <fcntl.h> | ||
18 | #include <unistd.h> | ||
19 | |||
20 | #include <err.h> | ||
21 | |||
22 | #include "fake-lib.h" | ||
23 | |||
24 | /* ---------------------------------------------------------------------- | ||
25 | * Core MD5 algorithm: processes 16-word blocks into a message digest. | ||
26 | */ | ||
27 | |||
28 | typedef struct { | ||
29 | uint32_t h[4]; | ||
30 | } MD5_Core_State; | ||
31 | |||
32 | struct MD5Context { | ||
33 | MD5_Core_State core; | ||
34 | unsigned char block[64]; | ||
35 | int blkused; | ||
36 | uint64_t len; | ||
37 | }; | ||
38 | |||
39 | #define F(x,y,z) ( ((x) & (y)) | ((~(x)) & (z)) ) | ||
40 | #define G(x,y,z) ( ((x) & (z)) | ((~(z)) & (y)) ) | ||
41 | #define H(x,y,z) ( (x) ^ (y) ^ (z) ) | ||
42 | #define I(x,y,z) ( (y) ^ ( (x) | ~(z) ) ) | ||
43 | |||
44 | #define rol(x,y) ( ((x) << (y)) | (((uint32_t)x) >> (32-y)) ) | ||
45 | |||
46 | #define subround(f,w,x,y,z,k,s,ti) \ | ||
47 | w = x + rol(w + f(x,y,z) + block[k] + ti, s) | ||
48 | |||
49 | static void MD5_Core_Init(MD5_Core_State * s) | ||
50 | { | ||
51 | s->h[0] = 0x67452301; | ||
52 | s->h[1] = 0xefcdab89; | ||
53 | s->h[2] = 0x98badcfe; | ||
54 | s->h[3] = 0x10325476; | ||
55 | } | ||
56 | |||
57 | static void MD5_Block(MD5_Core_State * s, uint32_t * block) | ||
58 | { | ||
59 | uint32_t a, b, c, d; | ||
60 | |||
61 | a = s->h[0]; | ||
62 | b = s->h[1]; | ||
63 | c = s->h[2]; | ||
64 | d = s->h[3]; | ||
65 | |||
66 | subround(F, a, b, c, d, 0, 7, 0xd76aa478); | ||
67 | subround(F, d, a, b, c, 1, 12, 0xe8c7b756); | ||
68 | subround(F, c, d, a, b, 2, 17, 0x242070db); | ||
69 | subround(F, b, c, d, a, 3, 22, 0xc1bdceee); | ||
70 | subround(F, a, b, c, d, 4, 7, 0xf57c0faf); | ||
71 | subround(F, d, a, b, c, 5, 12, 0x4787c62a); | ||
72 | subround(F, c, d, a, b, 6, 17, 0xa8304613); | ||
73 | subround(F, b, c, d, a, 7, 22, 0xfd469501); | ||
74 | subround(F, a, b, c, d, 8, 7, 0x698098d8); | ||
75 | subround(F, d, a, b, c, 9, 12, 0x8b44f7af); | ||
76 | subround(F, c, d, a, b, 10, 17, 0xffff5bb1); | ||
77 | subround(F, b, c, d, a, 11, 22, 0x895cd7be); | ||
78 | subround(F, a, b, c, d, 12, 7, 0x6b901122); | ||
79 | subround(F, d, a, b, c, 13, 12, 0xfd987193); | ||
80 | subround(F, c, d, a, b, 14, 17, 0xa679438e); | ||
81 | subround(F, b, c, d, a, 15, 22, 0x49b40821); | ||
82 | subround(G, a, b, c, d, 1, 5, 0xf61e2562); | ||
83 | subround(G, d, a, b, c, 6, 9, 0xc040b340); | ||
84 | subround(G, c, d, a, b, 11, 14, 0x265e5a51); | ||
85 | subround(G, b, c, d, a, 0, 20, 0xe9b6c7aa); | ||
86 | subround(G, a, b, c, d, 5, 5, 0xd62f105d); | ||
87 | subround(G, d, a, b, c, 10, 9, 0x02441453); | ||
88 | subround(G, c, d, a, b, 15, 14, 0xd8a1e681); | ||
89 | subround(G, b, c, d, a, 4, 20, 0xe7d3fbc8); | ||
90 | subround(G, a, b, c, d, 9, 5, 0x21e1cde6); | ||
91 | subround(G, d, a, b, c, 14, 9, 0xc33707d6); | ||
92 | subround(G, c, d, a, b, 3, 14, 0xf4d50d87); | ||
93 | subround(G, b, c, d, a, 8, 20, 0x455a14ed); | ||
94 | subround(G, a, b, c, d, 13, 5, 0xa9e3e905); | ||
95 | subround(G, d, a, b, c, 2, 9, 0xfcefa3f8); | ||
96 | subround(G, c, d, a, b, 7, 14, 0x676f02d9); | ||
97 | subround(G, b, c, d, a, 12, 20, 0x8d2a4c8a); | ||
98 | subround(H, a, b, c, d, 5, 4, 0xfffa3942); | ||
99 | subround(H, d, a, b, c, 8, 11, 0x8771f681); | ||
100 | subround(H, c, d, a, b, 11, 16, 0x6d9d6122); | ||
101 | subround(H, b, c, d, a, 14, 23, 0xfde5380c); | ||
102 | subround(H, a, b, c, d, 1, 4, 0xa4beea44); | ||
103 | subround(H, d, a, b, c, 4, 11, 0x4bdecfa9); | ||
104 | subround(H, c, d, a, b, 7, 16, 0xf6bb4b60); | ||
105 | subround(H, b, c, d, a, 10, 23, 0xbebfbc70); | ||
106 | subround(H, a, b, c, d, 13, 4, 0x289b7ec6); | ||
107 | subround(H, d, a, b, c, 0, 11, 0xeaa127fa); | ||
108 | subround(H, c, d, a, b, 3, 16, 0xd4ef3085); | ||
109 | subround(H, b, c, d, a, 6, 23, 0x04881d05); | ||
110 | subround(H, a, b, c, d, 9, 4, 0xd9d4d039); | ||
111 | subround(H, d, a, b, c, 12, 11, 0xe6db99e5); | ||
112 | subround(H, c, d, a, b, 15, 16, 0x1fa27cf8); | ||
113 | subround(H, b, c, d, a, 2, 23, 0xc4ac5665); | ||
114 | subround(I, a, b, c, d, 0, 6, 0xf4292244); | ||
115 | subround(I, d, a, b, c, 7, 10, 0x432aff97); | ||
116 | subround(I, c, d, a, b, 14, 15, 0xab9423a7); | ||
117 | subround(I, b, c, d, a, 5, 21, 0xfc93a039); | ||
118 | subround(I, a, b, c, d, 12, 6, 0x655b59c3); | ||
119 | subround(I, d, a, b, c, 3, 10, 0x8f0ccc92); | ||
120 | subround(I, c, d, a, b, 10, 15, 0xffeff47d); | ||
121 | subround(I, b, c, d, a, 1, 21, 0x85845dd1); | ||
122 | subround(I, a, b, c, d, 8, 6, 0x6fa87e4f); | ||
123 | subround(I, d, a, b, c, 15, 10, 0xfe2ce6e0); | ||
124 | subround(I, c, d, a, b, 6, 15, 0xa3014314); | ||
125 | subround(I, b, c, d, a, 13, 21, 0x4e0811a1); | ||
126 | subround(I, a, b, c, d, 4, 6, 0xf7537e82); | ||
127 | subround(I, d, a, b, c, 11, 10, 0xbd3af235); | ||
128 | subround(I, c, d, a, b, 2, 15, 0x2ad7d2bb); | ||
129 | subround(I, b, c, d, a, 9, 21, 0xeb86d391); | ||
130 | |||
131 | s->h[0] += a; | ||
132 | s->h[1] += b; | ||
133 | s->h[2] += c; | ||
134 | s->h[3] += d; | ||
135 | } | ||
136 | |||
137 | /* ---------------------------------------------------------------------- | ||
138 | * Outer MD5 algorithm: take an arbitrary length byte string, | ||
139 | * convert it into 16-word blocks with the prescribed padding at | ||
140 | * the end, and pass those blocks to the core MD5 algorithm. | ||
141 | */ | ||
142 | |||
143 | #define BLKSIZE 64 | ||
144 | |||
145 | static void MD5Init(struct MD5Context *s) | ||
146 | { | ||
147 | MD5_Core_Init(&s->core); | ||
148 | s->blkused = 0; | ||
149 | s->len = 0; | ||
150 | } | ||
151 | |||
152 | static void MD5Update(struct MD5Context *s, unsigned char const *p, | ||
153 | unsigned len) | ||
154 | { | ||
155 | unsigned char *q = (unsigned char *) p; | ||
156 | uint32_t wordblock[16]; | ||
157 | int i; | ||
158 | |||
159 | /* | ||
160 | * Update the length field. | ||
161 | */ | ||
162 | s->len += len; | ||
163 | |||
164 | if (s->blkused + len < BLKSIZE) { | ||
165 | /* | ||
166 | * Trivial case: just add to the block. | ||
167 | */ | ||
168 | memcpy(s->block + s->blkused, q, len); | ||
169 | s->blkused += len; | ||
170 | } else { | ||
171 | /* | ||
172 | * We must complete and process at least one block. | ||
173 | */ | ||
174 | while (s->blkused + len >= BLKSIZE) { | ||
175 | memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused); | ||
176 | q += BLKSIZE - s->blkused; | ||
177 | len -= BLKSIZE - s->blkused; | ||
178 | /* Now process the block. Gather bytes little-endian into words */ | ||
179 | for (i = 0; i < 16; i++) { | ||
180 | wordblock[i] = | ||
181 | (((uint32_t) s->block[i * 4 + 3]) << 24) | | ||
182 | (((uint32_t) s->block[i * 4 + 2]) << 16) | | ||
183 | (((uint32_t) s->block[i * 4 + 1]) << 8) | | ||
184 | (((uint32_t) s->block[i * 4 + 0]) << 0); | ||
185 | } | ||
186 | MD5_Block(&s->core, wordblock); | ||
187 | s->blkused = 0; | ||
188 | } | ||
189 | memcpy(s->block, q, len); | ||
190 | s->blkused = len; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | static void MD5Final(uint32_t output[4], struct MD5Context *s) | ||
195 | { | ||
196 | int i; | ||
197 | unsigned pad; | ||
198 | unsigned char c[64]; | ||
199 | uint64_t len; | ||
200 | |||
201 | if (s->blkused >= 56) | ||
202 | pad = 56 + 64 - s->blkused; | ||
203 | else | ||
204 | pad = 56 - s->blkused; | ||
205 | |||
206 | len = s->len << 3; | ||
207 | |||
208 | memset(c, 0, pad); | ||
209 | c[0] = 0x80; | ||
210 | MD5Update(s, c, pad); | ||
211 | |||
212 | c[7] = (len >> (8*7)) & 0xFF; | ||
213 | c[6] = (len >> (8*6)) & 0xFF; | ||
214 | c[5] = (len >> (8*5)) & 0xFF; | ||
215 | c[4] = (len >> (8*4)) & 0xFF; | ||
216 | c[3] = (len >> (8*3)) & 0xFF; | ||
217 | c[2] = (len >> (8*2)) & 0xFF; | ||
218 | c[1] = (len >> (8*1)) & 0xFF; | ||
219 | c[0] = (len >> (8*0)) & 0xFF; | ||
220 | |||
221 | MD5Update(s, c, 8); | ||
222 | |||
223 | for (i = 0; i < 4; i++) | ||
224 | output[i] = s->core.h[i]; | ||
225 | } | ||
226 | |||
227 | struct MsiHash { | ||
228 | uint32_t structure_size; | ||
229 | uint32_t hash_words[4]; | ||
230 | }; | ||
231 | |||
232 | uint32_t MsiGetFileHashW(const char16_t *filename, uint32_t options, | ||
233 | struct MsiHash *hash) | ||
234 | { | ||
235 | char *fname = ascii(filename, true); | ||
236 | uint32_t toret; | ||
237 | char buffer[4096]; | ||
238 | int fd = -1, retd; | ||
239 | struct MD5Context ctx; | ||
240 | |||
241 | fd = open(fname, O_RDONLY); | ||
242 | if (fd < 0) { | ||
243 | /* Could do some better errno -> GetLastError translation here */ | ||
244 | warnx("MsiGetFileHash(%s) -> ERROR_OPEN_FAILED", fname); | ||
245 | toret = 110; | ||
246 | goto cleanup; | ||
247 | } | ||
248 | |||
249 | MD5Init(&ctx); | ||
250 | |||
251 | while ((retd = read(fd, buffer, sizeof(buffer)) > 0)) | ||
252 | MD5Update(&ctx, buffer, retd); | ||
253 | if (retd < 0) { | ||
254 | warnx("MsiGetFileHash(%s) -> ERROR_READ_FAULT", fname); | ||
255 | toret = 30; | ||
256 | goto cleanup; | ||
257 | } | ||
258 | |||
259 | MD5Final(hash->hash_words, &ctx); | ||
260 | |||
261 | warnx("MsiGetFileHash(%s) -> %08x:%08x:%08x:%08x", fname, | ||
262 | (unsigned)hash->hash_words[0], (unsigned)hash->hash_words[1], | ||
263 | (unsigned)hash->hash_words[2], (unsigned)hash->hash_words[3]); | ||
264 | toret = 0; | ||
265 | |||
266 | cleanup: | ||
267 | if (fd != -1) | ||
268 | close(fd); | ||
269 | sfree(fname); | ||
270 | return toret; | ||
271 | } | ||