wok diff syslinux/stuff/extra/md5sum.c @ rev 12210
syslinux: add md5sum.c32
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Sat Mar 31 14:27:35 2012 +0200 (2012-03-31) |
parents | |
children | 7219c33850c6 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/syslinux/stuff/extra/md5sum.c Sat Mar 31 14:27:35 2012 +0200 1.3 @@ -0,0 +1,363 @@ 1.4 +/* vi: set sw=4 ts=4: */ 1.5 +/* 1.6 + * Based on busybox code 1.7 + * 1.8 + * Utility routines. 1.9 + * 1.10 + * Copyright (C) 2010 Denys Vlasenko 1.11 + * 1.12 + * Licensed under GPLv2 or later, see file LICENSE in this source tree. 1.13 + */ 1.14 + 1.15 +#include <stdio.h> 1.16 +#include <stdlib.h> 1.17 +#include <string.h> 1.18 +#include <unistd.h> 1.19 +#include <fcntl.h> 1.20 +#include <console.h> 1.21 +#include <com32.h> 1.22 + 1.23 +#define ALIGN1 1.24 +const char bb_hexdigits_upcase[] ALIGN1 = "0123456789ABCDEF"; 1.25 + 1.26 +/* Emit a string of hex representation of bytes */ 1.27 +char* bin2hex(char *p, const char *cp, int count) 1.28 +{ 1.29 + while (count) { 1.30 + unsigned char c = *cp++; 1.31 + /* put lowercase hex digits */ 1.32 + *p++ = 0x20 | bb_hexdigits_upcase[c >> 4]; 1.33 + *p++ = 0x20 | bb_hexdigits_upcase[c & 0xf]; 1.34 + count--; 1.35 + } 1.36 + return p; 1.37 +} 1.38 + 1.39 +//#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) 1.40 +static uint32_t rotl32(uint32_t x, unsigned n) 1.41 +{ 1.42 + return (x << n) | (x >> (32 - n)); 1.43 +} 1.44 + 1.45 +typedef struct md5_ctx_t { 1.46 + uint8_t wbuffer[64]; /* always correctly aligned for uint64_t */ 1.47 + uint64_t total64; /* must be directly before hash[] */ 1.48 + uint32_t hash[8]; /* 4 elements for md5, 5 for sha1, 8 for sha256 */ 1.49 +} md5_ctx_t; 1.50 + 1.51 +static void md5_process_block64(md5_ctx_t *ctx); 1.52 + 1.53 +/* Feed data through a temporary buffer. 1.54 + * The internal buffer remembers previous data until it has 64 1.55 + * bytes worth to pass on. 1.56 + */ 1.57 +static void common64_hash(md5_ctx_t *ctx, const void *buffer, size_t len) 1.58 +{ 1.59 + unsigned bufpos = ctx->total64 & 63; 1.60 + 1.61 + ctx->total64 += len; 1.62 + 1.63 + while (1) { 1.64 + unsigned remaining = 64 - bufpos; 1.65 + if (remaining > len) 1.66 + remaining = len; 1.67 + /* Copy data into aligned buffer */ 1.68 + memcpy(ctx->wbuffer + bufpos, buffer, remaining); 1.69 + len -= remaining; 1.70 + buffer = (const char *)buffer + remaining; 1.71 + bufpos += remaining; 1.72 + /* clever way to do "if (bufpos != 64) break; ... ; bufpos = 0;" */ 1.73 + bufpos -= 64; 1.74 + if (bufpos != 0) 1.75 + break; 1.76 + /* Buffer is filled up, process it */ 1.77 + md5_process_block64(ctx); 1.78 + /*bufpos = 0; - already is */ 1.79 + } 1.80 +} 1.81 + 1.82 +/* Process the remaining bytes in the buffer */ 1.83 +static void common64_end(md5_ctx_t *ctx) 1.84 +{ 1.85 + unsigned bufpos = ctx->total64 & 63; 1.86 + /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ 1.87 + ctx->wbuffer[bufpos++] = 0x80; 1.88 + 1.89 + /* This loop iterates either once or twice, no more, no less */ 1.90 + while (1) { 1.91 + unsigned remaining = 64 - bufpos; 1.92 + memset(ctx->wbuffer + bufpos, 0, remaining); 1.93 + /* Do we have enough space for the length count? */ 1.94 + if (remaining >= 8) { 1.95 + /* Store the 64-bit counter of bits in the buffer */ 1.96 + uint64_t t = ctx->total64 << 3; 1.97 + /* wbuffer is suitably aligned for this */ 1.98 + *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t; 1.99 + } 1.100 + md5_process_block64(ctx); 1.101 + if (remaining >= 8) 1.102 + break; 1.103 + bufpos = 0; 1.104 + } 1.105 +} 1.106 + 1.107 + 1.108 +/* 1.109 + * Compute MD5 checksum of strings according to the 1.110 + * definition of MD5 in RFC 1321 from April 1992. 1.111 + * 1.112 + * Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. 1.113 + * 1.114 + * Copyright (C) 1995-1999 Free Software Foundation, Inc. 1.115 + * Copyright (C) 2001 Manuel Novoa III 1.116 + * Copyright (C) 2003 Glenn L. McGrath 1.117 + * Copyright (C) 2003 Erik Andersen 1.118 + * 1.119 + * Licensed under GPLv2 or later, see file LICENSE in this source tree. 1.120 + */ 1.121 + 1.122 +/* These are the four functions used in the four steps of the MD5 algorithm 1.123 + * and defined in the RFC 1321. The first function is a little bit optimized 1.124 + * (as found in Colin Plumbs public domain implementation). 1.125 + * #define FF(b, c, d) ((b & c) | (~b & d)) 1.126 + */ 1.127 +#undef FF 1.128 +#undef FG 1.129 +#undef FH 1.130 +#undef FI 1.131 +#define FF(b, c, d) (d ^ (b & (c ^ d))) 1.132 +#define FG(b, c, d) FF(d, b, c) 1.133 +#define FH(b, c, d) (b ^ c ^ d) 1.134 +#define FI(b, c, d) (c ^ (b | ~d)) 1.135 + 1.136 +/* Hash a single block, 64 bytes long and 4-byte aligned */ 1.137 +static void md5_process_block64(md5_ctx_t *ctx) 1.138 +{ 1.139 + /* Before we start, one word to the strange constants. 1.140 + They are defined in RFC 1321 as 1.141 + T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64 1.142 + */ 1.143 + static const uint32_t C_array[] = { 1.144 + /* round 1 */ 1.145 + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 1.146 + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 1.147 + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 1.148 + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 1.149 + /* round 2 */ 1.150 + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 1.151 + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 1.152 + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 1.153 + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 1.154 + /* round 3 */ 1.155 + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 1.156 + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 1.157 + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, 1.158 + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 1.159 + /* round 4 */ 1.160 + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 1.161 + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 1.162 + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 1.163 + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 1.164 + }; 1.165 + static const char P_array[] ALIGN1 = { 1.166 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */ 1.167 + 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */ 1.168 + 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */ 1.169 + 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ 1.170 + }; 1.171 + uint32_t *words = (void*) ctx->wbuffer; 1.172 + uint32_t A = ctx->hash[0]; 1.173 + uint32_t B = ctx->hash[1]; 1.174 + uint32_t C = ctx->hash[2]; 1.175 + uint32_t D = ctx->hash[3]; 1.176 + 1.177 + static const char S_array[] ALIGN1 = { 1.178 + 7, 12, 17, 22, 1.179 + 5, 9, 14, 20, 1.180 + 4, 11, 16, 23, 1.181 + 6, 10, 15, 21 1.182 + }; 1.183 + const uint32_t *pc; 1.184 + const char *pp; 1.185 + const char *ps; 1.186 + int i; 1.187 + uint32_t temp; 1.188 + 1.189 + 1.190 + pc = C_array; 1.191 + pp = P_array; 1.192 + ps = S_array - 4; 1.193 + 1.194 + for (i = 0; i < 64; i++) { 1.195 + if ((i & 0x0f) == 0) 1.196 + ps += 4; 1.197 + temp = A; 1.198 + switch (i >> 4) { 1.199 + case 0: 1.200 + temp += FF(B, C, D); 1.201 + break; 1.202 + case 1: 1.203 + temp += FG(B, C, D); 1.204 + break; 1.205 + case 2: 1.206 + temp += FH(B, C, D); 1.207 + break; 1.208 + case 3: 1.209 + temp += FI(B, C, D); 1.210 + } 1.211 + temp += words[(int) (*pp++)] + *pc++; 1.212 + temp = rotl32(temp, ps[i & 3]); 1.213 + temp += B; 1.214 + A = D; 1.215 + D = C; 1.216 + C = B; 1.217 + B = temp; 1.218 + } 1.219 + /* Add checksum to the starting values */ 1.220 + ctx->hash[0] += A; 1.221 + ctx->hash[1] += B; 1.222 + ctx->hash[2] += C; 1.223 + ctx->hash[3] += D; 1.224 + 1.225 +} 1.226 +#undef FF 1.227 +#undef FG 1.228 +#undef FH 1.229 +#undef FI 1.230 + 1.231 +/* Initialize structure containing state of computation. 1.232 + * (RFC 1321, 3.3: Step 3) 1.233 + */ 1.234 +void md5_begin(md5_ctx_t *ctx) 1.235 +{ 1.236 + ctx->hash[0] = 0x67452301; 1.237 + ctx->hash[1] = 0xefcdab89; 1.238 + ctx->hash[2] = 0x98badcfe; 1.239 + ctx->hash[3] = 0x10325476; 1.240 + ctx->total64 = 0; 1.241 +} 1.242 + 1.243 +/* Used also for sha1 and sha256 */ 1.244 +void md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) 1.245 +{ 1.246 + common64_hash(ctx, buffer, len); 1.247 +} 1.248 + 1.249 +/* Process the remaining bytes in the buffer and put result from CTX 1.250 + * in first 16 bytes following RESBUF. The result is always in little 1.251 + * endian byte order, so that a byte-wise output yields to the wanted 1.252 + * ASCII representation of the message digest. 1.253 + */ 1.254 +void md5_end(md5_ctx_t *ctx, void *resbuf) 1.255 +{ 1.256 + /* MD5 stores total in LE, need to swap on BE arches: */ 1.257 + common64_end(ctx); 1.258 + 1.259 + /* The MD5 result is in little endian byte order */ 1.260 + memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * 4); 1.261 +} 1.262 + 1.263 +/* 1.264 + * Copyright (C) 2003 Glenn L. McGrath 1.265 + * Copyright (C) 2003-2004 Erik Andersen 1.266 + * 1.267 + * Licensed under GPLv2 or later, see file LICENSE in this source tree. 1.268 + */ 1.269 + 1.270 +/* This might be useful elsewhere */ 1.271 +static unsigned char *hash_bin_to_hex(unsigned char *hash_value, 1.272 + unsigned hash_length) 1.273 +{ 1.274 + static char hex_value[16*2+1]; 1.275 + bin2hex(hex_value, (char*)hash_value, hash_length); 1.276 + return (unsigned char *)hex_value; 1.277 +} 1.278 + 1.279 +static uint8_t *hash_file(const char *filename) 1.280 +{ 1.281 + int src_fd, count; 1.282 + md5_ctx_t context; 1.283 + uint8_t *hash_value, in_buf[4096]; 1.284 + 1.285 + src_fd = open(filename, O_RDONLY); 1.286 + if (src_fd < 0) { 1.287 + return NULL; 1.288 + } 1.289 + 1.290 + md5_begin(&context); 1.291 + while ((count = read(src_fd, in_buf, 4096)) > 0) { 1.292 + md5_hash(&context, in_buf, count); 1.293 + } 1.294 + hash_value = NULL; 1.295 + if (count == 0) { 1.296 + md5_end(&context, in_buf); 1.297 + hash_value = hash_bin_to_hex(in_buf, 16); 1.298 + } 1.299 + 1.300 + close(src_fd); 1.301 + 1.302 + return hash_value; 1.303 +} 1.304 + 1.305 +static int valid_name(char *name) 1.306 +{ 1.307 + int dots, suffix; 1.308 + for (dots = 0, suffix = 0; *name; name++) { 1.309 + if (dots) suffix++; 1.310 + if (*name == '.') dots++; 1.311 + } 1.312 + return dots < 2 && suffix <= 3; 1.313 +} 1.314 + 1.315 +int main(int argc, char **argv) 1.316 +{ 1.317 + int return_value = EXIT_SUCCESS; 1.318 + 1.319 + (void) argc; 1.320 + /* -c implied */ 1.321 + openconsole(&dev_rawcon_r, &dev_stdcon_w); 1.322 + 1.323 + do { 1.324 + FILE *fp; 1.325 + char *line, buffer[256]; 1.326 + fp = fopen(*argv,"r"); 1.327 + 1.328 + while ((line = fgets(buffer,256,fp)) != NULL) { 1.329 + uint8_t *hash_value; 1.330 + char *filename_ptr, *status; 1.331 + int len = strlen(line); 1.332 +#define BLANK " " 1.333 + 1.334 + if (line[0] < '0') 1.335 + continue; 1.336 + if (line[len-1] == '\n') 1.337 + line[len-1] = 0; 1.338 + filename_ptr = strstr(line, " "); 1.339 + /* handle format for binary checksums */ 1.340 + if (filename_ptr == NULL) { 1.341 + filename_ptr = strstr(line, " *"); 1.342 + } 1.343 + if (filename_ptr == NULL) { 1.344 + return_value = EXIT_FAILURE; 1.345 + continue; 1.346 + } 1.347 + *filename_ptr = '\0'; 1.348 + *++filename_ptr = '/'; 1.349 + 1.350 + status = "SKIPPED" BLANK; 1.351 + if (valid_name(filename_ptr)) { 1.352 + hash_value = hash_file(filename_ptr); 1.353 + status = "OK" BLANK; 1.354 + if (hash_value == NULL || strcmp((char*)hash_value, line)) { 1.355 + return_value = EXIT_FAILURE; 1.356 + status = "FAILED" BLANK "\n"; 1.357 + } 1.358 + } 1.359 + printf("\r%s: %s", filename_ptr, status); 1.360 + } 1.361 + fclose(fp); 1.362 + } while (*++argv); 1.363 + printf("\r" BLANK "\r"); 1.364 + 1.365 + return return_value; 1.366 +}