diff options
| -rw-r--r-- | fake-lib.c | 214 | ||||
| -rw-r--r-- | fake-lib.h | 1 | ||||
| -rw-r--r-- | fake-msi.c | 38 |
3 files changed, 253 insertions, 0 deletions
| @@ -140,3 +140,217 @@ 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 | } | ||
| @@ -6,6 +6,7 @@ void *smalloc(size_t size); | |||
| 6 | void *srealloc(void *ptr, size_t size); | 6 | void *srealloc(void *ptr, size_t size); |
| 7 | char *dupcat(const char *str, ...); | 7 | char *dupcat(const char *str, ...); |
| 8 | unsigned le(const unsigned char *buf, size_t len, size_t off, size_t nbytes); | 8 | 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]); | ||
| 9 | 10 | ||
| 10 | #define snew(type) ((type *)smalloc(sizeof(type))) | 11 | #define snew(type) ((type *)smalloc(sizeof(type))) |
| 11 | #define snewn(n,type) ((type *)smalloc((n)*sizeof(type))) | 12 | #define snewn(n,type) ((type *)smalloc((n)*sizeof(type))) |
| @@ -193,6 +193,44 @@ uint32_t MsiGetFileVersionW(const char16_t *filename, | |||
| 193 | sfree(fname); | 193 | sfree(fname); |
| 194 | return toret; | 194 | return toret; |
| 195 | } | 195 | } |
| 196 | |||
| 197 | struct MsiHash { | ||
| 198 | uint32_t structure_size; | ||
| 199 | uint32_t hash_words[4]; | ||
| 200 | }; | ||
| 201 | |||
| 202 | uint32_t MsiGetFileHashW(const char16_t *filename, uint32_t options, | ||
| 203 | struct MsiHash *hash) | ||
| 204 | { | ||
| 205 | char *fname = ascii(filename, true); | ||
| 206 | int fd = -1; | ||
| 207 | void *mapv = MAP_FAILED; | ||
| 208 | uint32_t toret; | ||
| 209 | |||
| 210 | fd = open(fname, O_RDONLY); | ||
| 211 | if (fd < 0) | ||
| 212 | err(1, "%s: open", fname); | ||
| 213 | struct stat st; | ||
| 214 | if (fstat(fd, &st) < 0) | ||
| 215 | err(1, "%s: fstat", fname); | ||
| 216 | size_t fsize = st.st_size; | ||
| 217 | mapv = mmap(NULL, fsize, PROT_READ, MAP_PRIVATE, fd, 0); | ||
| 218 | if (mapv == MAP_FAILED) | ||
| 219 | err(1, "%s: mmap", fname); | ||
| 220 | |||
| 221 | MD5Simple(mapv, fsize, hash->hash_words); | ||
| 222 | warnx("MsiGetFileHash(%s) -> %08x:%08x:%08x:%08x", fname, | ||
| 223 | (unsigned)hash->hash_words[0], (unsigned)hash->hash_words[1], | ||
| 224 | (unsigned)hash->hash_words[2], (unsigned)hash->hash_words[3]); | ||
| 225 | toret = 0; | ||
| 226 | |||
| 227 | cleanup: | ||
| 228 | if (mapv != MAP_FAILED) | ||
| 229 | munmap(mapv, fsize); | ||
| 230 | if (fd != -1) | ||
| 231 | close(fd); | ||
| 232 | sfree(fname); | ||
| 233 | return toret; | ||
| 196 | } | 234 | } |
| 197 | 235 | ||
| 198 | typedef struct MsiTypePrefix { | 236 | typedef struct MsiTypePrefix { |
