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);