wok-next diff syslinux/stuff/iso2exe/iso2exe.c @ rev 17591
syslinux/isohybrib.exe: add --md5, --undo
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Tue Feb 10 08:53:27 2015 +0100 (2015-02-10) |
parents | 054f70cb9bec |
children | 24b07aa2fafd |
line diff
1.1 --- a/syslinux/stuff/iso2exe/iso2exe.c Thu Jan 01 22:09:19 2015 +0100 1.2 +++ b/syslinux/stuff/iso2exe/iso2exe.c Tue Feb 10 08:53:27 2015 +0100 1.3 @@ -9,9 +9,11 @@ 1.4 #ifdef WIN32 1.5 #include <windows.h> 1.6 #endif 1.7 +typedef unsigned char uint8_t; 1.8 +typedef unsigned long uint32_t; 1.9 #include "iso2exe.h" 1.10 1.11 -static int fd, forced, status = 1; 1.12 +static int fd, forced, uninstall, status = 1; 1.13 static char tazlitoinfo[0x8000U - BOOTISOSZ]; 1.14 #define buffer tazlitoinfo 1.15 #define BUFFERSZ 2048 1.16 @@ -27,6 +29,217 @@ 1.17 } 1.18 } 1.19 1.20 +static int domd5 = 0; 1.21 +#define ALIGN1 1.22 + 1.23 +typedef struct { 1.24 + uint32_t l; 1.25 + uint32_t h; 1.26 +} uint64_t; 1.27 +static uint8_t wbuffer[64]; /* always correctly aligned for uint64_t */ 1.28 +static uint64_t total64; /* must be directly before hash[] */ 1.29 +static uint32_t hash[8]; /* 4 elements for md5, 5 for sha1, 8 for sha256 */ 1.30 + 1.31 +//#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) 1.32 +static uint32_t rotl32(uint32_t x, unsigned n) 1.33 +{ 1.34 + return (x << n) | (x >> (32 - n)); 1.35 +} 1.36 + 1.37 +static void md5_process_block64(void); 1.38 + 1.39 +/* Feed data through a temporary buffer. 1.40 + * The internal buffer remembers previous data until it has 64 1.41 + * bytes worth to pass on. 1.42 + */ 1.43 +static void common64_hash(const void *buffer, size_t len) 1.44 +{ 1.45 + unsigned bufpos = total64.l & 63; 1.46 + 1.47 + total64.l += len; if (total64.l < len) total64.h++; 1.48 + 1.49 + while (1) { 1.50 + unsigned remaining = 64 - bufpos; 1.51 + if (remaining > len) 1.52 + remaining = len; 1.53 + /* Copy data into aligned buffer */ 1.54 + memcpy(wbuffer + bufpos, buffer, remaining); 1.55 + len -= remaining; 1.56 + buffer = (const char *)buffer + remaining; 1.57 + bufpos += remaining; 1.58 + /* clever way to do "if (bufpos != 64) break; ... ; bufpos = 0;" */ 1.59 + bufpos -= 64; 1.60 + if (bufpos != 0) 1.61 + break; 1.62 + /* Buffer is filled up, process it */ 1.63 + md5_process_block64(); 1.64 + /*bufpos = 0; - already is */ 1.65 + } 1.66 +} 1.67 + 1.68 +/* Process the remaining bytes in the buffer */ 1.69 +static void common64_end(void) 1.70 +{ 1.71 + unsigned bufpos = total64.l & 63; 1.72 + /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ 1.73 + wbuffer[bufpos++] = 0x80; 1.74 + 1.75 + /* This loop iterates either once or twice, no more, no less */ 1.76 + while (1) { 1.77 + unsigned remaining = 64 - bufpos; 1.78 + memset(wbuffer + bufpos, 0, remaining); 1.79 + /* Do we have enough space for the length count? */ 1.80 + if (remaining >= 8) { 1.81 + /* Store the 64-bit counter of bits in the buffer */ 1.82 + //uint64_t t = total64 << 3; 1.83 + uint32_t *t = (uint32_t *) (&wbuffer[64 - 8]); 1.84 + /* wbuffer is suitably aligned for this */ 1.85 + //*(uint64_t *) (&wbuffer[64 - 8]) = t; 1.86 + t[0] = total64.l << 3; 1.87 + t[1] = (total64.h << 3) | (total64.l >> 29); 1.88 + } 1.89 + md5_process_block64(); 1.90 + if (remaining >= 8) 1.91 + break; 1.92 + bufpos = 0; 1.93 + } 1.94 +} 1.95 + 1.96 +/* These are the four functions used in the four steps of the MD5 algorithm 1.97 + * and defined in the RFC 1321. The first function is a little bit optimized 1.98 + * (as found in Colin Plumbs public domain implementation). 1.99 + * #define FF(b, c, d) ((b & c) | (~b & d)) 1.100 + */ 1.101 +#undef FF 1.102 +#undef FG 1.103 +#undef FH 1.104 +#undef FI 1.105 +#define FF(b, c, d) (d ^ (b & (c ^ d))) 1.106 +#define FG(b, c, d) FF(d, b, c) 1.107 +#define FH(b, c, d) (b ^ c ^ d) 1.108 +#define FI(b, c, d) (c ^ (b | ~d)) 1.109 + 1.110 +/* Hash a single block, 64 bytes long and 4-byte aligned */ 1.111 +static void md5_process_block64(void) 1.112 +{ 1.113 + uint32_t *words = (void*) wbuffer; 1.114 + uint32_t A = hash[0]; 1.115 + uint32_t B = hash[1]; 1.116 + uint32_t C = hash[2]; 1.117 + uint32_t D = hash[3]; 1.118 + 1.119 + const uint32_t *pc; 1.120 + const char *pp; 1.121 + const char *ps; 1.122 + int i; 1.123 + uint32_t temp; 1.124 + 1.125 + 1.126 + pc = C_array; 1.127 + pp = P_array; 1.128 + ps = S_array - 4; 1.129 + 1.130 + for (i = 0; i < 64; i++) { 1.131 + if ((i & 0x0f) == 0) 1.132 + ps += 4; 1.133 + temp = A; 1.134 + switch (i >> 4) { 1.135 + case 0: 1.136 + temp += FF(B, C, D); 1.137 + break; 1.138 + case 1: 1.139 + temp += FG(B, C, D); 1.140 + break; 1.141 + case 2: 1.142 + temp += FH(B, C, D); 1.143 + break; 1.144 + case 3: 1.145 + temp += FI(B, C, D); 1.146 + } 1.147 + temp += words[(int) (*pp++)] + *pc++; 1.148 + temp = rotl32(temp, ps[i & 3]); 1.149 + temp += B; 1.150 + A = D; 1.151 + D = C; 1.152 + C = B; 1.153 + B = temp; 1.154 + } 1.155 + /* Add checksum to the starting values */ 1.156 + hash[0] += A; 1.157 + hash[1] += B; 1.158 + hash[2] += C; 1.159 + hash[3] += D; 1.160 + 1.161 +} 1.162 +#undef FF 1.163 +#undef FG 1.164 +#undef FH 1.165 +#undef FI 1.166 + 1.167 +/* Initialize structure containing state of computation. 1.168 + * (RFC 1321, 3.3: Step 3) 1.169 + */ 1.170 +static void md5_begin(void) 1.171 +{ 1.172 + hash[0] = 0x67452301; 1.173 + hash[1] = 0xefcdab89; 1.174 + hash[2] = 0x98badcfe; 1.175 + hash[3] = 0x10325476; 1.176 + total64.l = total64.h = 0; 1.177 +} 1.178 + 1.179 +/* Used also for sha1 and sha256 */ 1.180 +#define md5_hash common64_hash 1.181 + 1.182 +/* Process the remaining bytes in the buffer and put result from CTX 1.183 + * in first 16 bytes following RESBUF. The result is always in little 1.184 + * endian byte order, so that a byte-wise output yields to the wanted 1.185 + * ASCII representation of the message digest. 1.186 + */ 1.187 +#define md5_end common64_end 1.188 + 1.189 +static void md5sum(void) 1.190 +{ 1.191 + unsigned long sectors = 0; 1.192 + int count; 1.193 + 1.194 + lseek(fd, 32768UL, SEEK_SET); 1.195 + 1.196 + md5_begin(); 1.197 + while ((count = read(fd, buffer, BUFFERSZ)) > 0) { 1.198 + if (sectors == 0) 1.199 + sectors = LONG(buffer + 80); 1.200 + md5_hash(buffer, count); 1.201 + if (--sectors == 0) 1.202 + break; 1.203 + } 1.204 + 1.205 + if (count < 0) 1.206 + return; 1.207 + 1.208 + md5_end(); 1.209 + 1.210 + lseek(fd, 32752UL, SEEK_SET); 1.211 + write(fd, hash, 16); 1.212 + memcpy(bootiso + BOOTISOSZ - 16, hash, 16); 1.213 +} 1.214 + 1.215 +static unsigned chksum(unsigned start, unsigned stop) 1.216 +{ 1.217 + unsigned i, n = 0; 1.218 + 1.219 + lseek(fd, 0UL /* (unsigned long) (start / BUFFERSZ) */, SEEK_SET); 1.220 + while (1) { 1.221 + if (read(fd, buffer, BUFFERSZ) != BUFFERSZ) 1.222 + return 0; 1.223 + for (i = start % BUFFERSZ; i < BUFFERSZ; i += 2, start += 2) { 1.224 + if (start >= stop) 1.225 + return - n; 1.226 + n += WORD(buffer + i); 1.227 + } 1.228 + } 1.229 +} 1.230 + 1.231 static unsigned install(char *filename) 1.232 { 1.233 #define heads 64 1.234 @@ -50,6 +263,23 @@ 1.235 if (fd == -1) 1.236 return OPENERR; 1.237 1.238 + if (uninstall) { 1.239 + struct { char check[sizeof(tazlitoinfo) - BUFFERSZ - 1024]; }; 1.240 + readsector(0UL); 1.241 + n = BUFFERSZ; 1.242 + if (WORD(buffer) == 23117) { 1.243 + readsector((unsigned long) buffer[69]); 1.244 + n = 0; 1.245 + } 1.246 + lseek(fd, 0UL, SEEK_SET); 1.247 + for (i = 0; i < 32; i++, n = BUFFERSZ) { 1.248 + write(fd, buffer + n, 1024); 1.249 + } 1.250 + close(fd); 1.251 + status = 0; 1.252 + return UNINSTALLMSG; 1.253 + } 1.254 + 1.255 if (forced == 0) { 1.256 status = 2; 1.257 /* Install hybridiso boot sector */ 1.258 @@ -105,18 +335,22 @@ 1.259 write(fd, tazlitoinfo, sizeof(tazlitoinfo)); 1.260 write(fd, bootiso + n, BOOTISOSZ - n); /* COM + rootfs + EXE/DOS */ 1.261 1.262 - /* Compute the checksum */ 1.263 - lseek(fd, 0UL, SEEK_SET); 1.264 - for (i = 66, n = 0, j = 0; j < 16; j++, i = 0) { 1.265 - if (read(fd, buffer, BUFFERSZ) != BUFFERSZ) 1.266 - goto nochksum; 1.267 - for (; i < BUFFERSZ; i += 2) 1.268 - n += WORD(buffer + i); 1.269 + if (domd5) { 1.270 + puts(bootiso + MD5MSG); 1.271 + md5sum(); 1.272 } 1.273 - WORD(bootiso + 64) = -n; 1.274 - lseek(fd, 0UL, SEEK_SET); 1.275 - write(fd, bootiso, 512); 1.276 -nochksum: 1.277 + 1.278 + /* Compute the boot checksums */ 1.279 + if ((WORD(bootiso + 64) = chksum(66, 32768)) != 0) { 1.280 + if (domd5) { 1.281 + lseek(fd, 0UL, SEEK_SET); 1.282 + write(fd, bootiso, 512); 1.283 + n = WORD(bootiso + 2) - 512*(WORD(bootiso + 4) - 1); 1.284 + WORD(bootiso + 18) = chksum(0, n) - 1; 1.285 + } 1.286 + lseek(fd, 0UL, SEEK_SET); 1.287 + write(fd, bootiso, 512); 1.288 + } 1.289 close(fd); 1.290 status = 0; 1.291 return SUCCESSMSG; 1.292 @@ -124,7 +358,16 @@ 1.293 1.294 int main(int argc, char *argv[]) 1.295 { 1.296 - forced = (argc > 2); 1.297 + int i; 1.298 + for (i = 2; i < argc; i++) { 1.299 + char *s = argv[i]; 1.300 + while ((unsigned)(*s - '-') <= ('/' - '-')) s++; 1.301 + switch (*s | 0x20) { 1.302 + case 'f' : forced++; break; 1.303 + case 'm' : domd5++; break; 1.304 + case 'u' : uninstall++; break; 1.305 + } 1.306 + } 1.307 puts(bootiso + install(argv[1])); 1.308 if (status > 1) 1.309 puts(bootiso + FORCEMSG);