diff options
| author | Simon Tatham <anakin@pobox.com> | 2017-05-18 06:43:51 +0100 |
|---|---|---|
| committer | Simon Tatham <anakin@pobox.com> | 2017-05-18 06:43:51 +0100 |
| commit | ca59ebf60df4ef45a1e4d681980e29e3db853bba (patch) | |
| tree | 15651c55c8d273181f93dd72377b09623d50b6f1 | |
| parent | 7de9585efbbd148df26cd180900db69e11c36061 (diff) | |
| download | wix-on-linux-ca59ebf60df4ef45a1e4d681980e29e3db853bba.tar.gz wix-on-linux-ca59ebf60df4ef45a1e4d681980e29e3db853bba.tar.bz2 wix-on-linux-ca59ebf60df4ef45a1e4d681980e29e3db853bba.zip | |
Move MD5 out into its own file.
This begins a programme of code reorganisation at the end of which I'd
like to end up with something almost legible :-)
| -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 | } | ||
