toybox/toys/lsb/md5sum.c
<<
>>
Prefs
   1/* md5sum.c - Calculate hashes md5, sha1, sha224, sha256, sha384, sha512.
   2 *
   3 * Copyright 2012, 2021 Rob Landley <rob@landley.net>
   4 *
   5 * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/md5sum.html
   6 * and http://www.ietf.org/rfc/rfc1321.txt
   7 * and http://www.ietf.org/rfc/rfc4634.txt
   8 *
   9 * They're combined this way to share infrastructure, and because md5sum is
  10 * a LSB standard command (but sha1sum and newer hashes are a good idea,
  11 * see http://valerieaurora.org/hash.html).
  12 *
  13 * We optionally use openssl (or equivalent) to access assembly optimized
  14 * versions of these functions, but provide a built-in version to reduce
  15 * required dependencies.
  16 *
  17 * coreutils supports --status but not -s, busybox supports -s but not --status
  18
  19USE_MD5SUM(NEWTOY(md5sum, "bc(check)s(status)[!bc]", TOYFLAG_USR|TOYFLAG_BIN))
  20USE_SHA1SUM(OLDTOY(sha1sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
  21USE_SHA224SUM(OLDTOY(sha224sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
  22USE_SHA256SUM(OLDTOY(sha256sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
  23USE_SHA384SUM(OLDTOY(sha384sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
  24USE_SHA512SUM(OLDTOY(sha512sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
  25
  26config MD5SUM
  27  bool "md5sum"
  28  default y
  29  help
  30    usage: ???sum [-bcs] [FILE]...
  31
  32    Calculate hash for each input file, reading from stdin if none, writing
  33    hexadecimal digits to stdout for each input file (md5=32 hex digits,
  34    sha1=40, sha224=56, sha256=64, sha384=96, sha512=128) followed by filename.
  35
  36    -b  Brief (hash only, no filename)
  37    -c  Check each line of each FILE is the same hash+filename we'd output
  38    -s  No output, exit status 0 if all hashes match, 1 otherwise
  39
  40config SHA1SUM
  41  bool "sha1sum"
  42  default y
  43  help
  44    See md5sum
  45
  46config SHA224SUM
  47  bool "sha224sum"
  48  default y
  49  help
  50    See md5sum
  51
  52config SHA256SUM
  53  bool "sha256sum"
  54  default y
  55  help
  56    See md5sum
  57
  58config SHA384SUM
  59  bool "sha384sum"
  60  default y
  61  help
  62    See md5sum
  63
  64config SHA512SUM
  65  bool "sha512sum"
  66  default y
  67  help
  68    See md5sum
  69*/
  70
  71#define FORCE_FLAGS
  72#define FOR_md5sum
  73#include "toys.h"
  74
  75#if CFG_TOYBOX_LIBCRYPTO
  76#include <openssl/md5.h>
  77#include <openssl/sha.h>
  78#else
  79typedef int SHA512_CTX;
  80#endif
  81
  82GLOBALS(
  83  int sawline;
  84  unsigned *rconsttable32;
  85  unsigned long long *rconsttable64; // for sha384,sha512
  86
  87  // Crypto variables blanked after summing
  88  unsigned long long count, overflow;
  89  union {
  90    char c[128]; // bytes, 1024 bits
  91    unsigned i32[16]; // 512 bits for md5,sha1,sha224,sha256
  92    unsigned long long i64[16]; // 1024 bits for sha384,sha512
  93  } state, buffer;
  94)
  95
  96// Round constants. Static table for when we haven't got floating point support
  97#if ! CFG_TOYBOX_FLOAT
  98static const unsigned md5nofloat[64] = {
  99  0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a,
 100  0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
 101  0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340,
 102  0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
 103  0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8,
 104  0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
 105  0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa,
 106  0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
 107  0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92,
 108  0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
 109  0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
 110};
 111#else
 112#define md5nofloat 0
 113#endif
 114static unsigned long long sha512nofloat[80] = {
 115  // we cannot calculate these 64-bit values using the readily
 116  // available floating point data types and math functions,
 117  // so we always use this lookup table (80 * 8 bytes)
 118  0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f,
 119  0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019,
 120  0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242,
 121  0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
 122  0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
 123  0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
 124  0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275,
 125  0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
 126  0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f,
 127  0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
 128  0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc,
 129  0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
 130  0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6,
 131  0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001,
 132  0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
 133  0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
 134  0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99,
 135  0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
 136  0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc,
 137  0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
 138  0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915,
 139  0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207,
 140  0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba,
 141  0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
 142  0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
 143  0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
 144  0x5fcb6fab3ad6faec, 0x6c44198c4a475817
 145};
 146// sha1 needs only 4 round constant values, so prefer precomputed
 147static const unsigned sha1rconsts[] = {
 148  0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6
 149};
 150
 151// bit rotations
 152#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
 153#define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits))))
 154#define ror64(value, bits) (((value) >> (bits)) | ((value) << (64 - (bits))))
 155
 156// Mix next 64 bytes of data into md5 hash
 157
 158static void md5_transform(void)
 159{
 160  unsigned x[4], *b = TT.buffer.i32;
 161  int i;
 162
 163  for (i = 0; i<4; i++) x[i] = TT.state.i32[i];
 164  for (i = 0; i<64; i++) {
 165    unsigned in, a, rot, temp;
 166
 167    a = (-i)&3;
 168    if (i<16) {
 169      in = i;
 170      rot = 7+(5*(i&3));
 171      temp = x[(a+1)&3];
 172      temp = (temp & x[(a+2)&3]) | ((~temp) & x[(a+3)&3]);
 173    } else if (i<32) {
 174      in = (1+(5*i))&15;
 175      temp = (i&3)+1;
 176      rot = temp*5;
 177      if (temp&2) rot--;
 178      temp = x[(a+3)&3];
 179      temp = (x[(a+1)&3] & temp) | (x[(a+2)&3] & ~temp);
 180    } else if (i<48) {
 181      in = (5+(3*(i&15)))&15;
 182      rot = i&3;
 183      rot = 4+(5*rot)+((rot+1)&6);
 184      temp = x[(a+1)&3] ^ x[(a+2)&3] ^ x[(a+3)&3];
 185    } else {
 186      in = (7*(i&15))&15;
 187      rot = (i&3)+1;
 188      rot = (5*rot)+(((rot+2)&2)>>1);
 189      temp = x[(a+2)&3] ^ (x[(a+1)&3] | ~x[(a+3)&3]);
 190    }
 191    temp += x[a] + SWAP_LE32(b[in]) + TT.rconsttable32[i];
 192    x[a] = x[(a+1)&3] + ((temp<<rot) | (temp>>(32-rot)));
 193  }
 194  for (i = 0; i<4; i++) TT.state.i32[i] += x[i];
 195}
 196
 197// Mix next 64 bytes of data into sha1 hash.
 198
 199static void sha1_transform(void)
 200{
 201  int i, j, k, count;
 202  unsigned *block = TT.buffer.i32, oldstate[5], *rot[5], *temp, work;
 203
 204  // Copy context->state.i32[] to working vars
 205  for (i = 0; i<5; i++) {
 206    oldstate[i] = TT.state.i32[i];
 207    rot[i] = TT.state.i32 + i;
 208  }
 209  if (IS_BIG_ENDIAN) for (i = 0; i<16; i++) block[i] = SWAP_LE32(block[i]);
 210
 211  // 4 rounds of 20 operations each.
 212  for (i = count = 0; i<4; i++) {
 213    for (j = 0; j<20; j++) {
 214      work = *rot[2] ^ *rot[3];
 215      if (!i) work = (work & *rot[1]) ^ *rot[3];
 216      else {
 217        if (i==2) work = ((*rot[1]|*rot[2])&*rot[3])|(*rot[1]&*rot[2]);
 218        else work ^= *rot[1];
 219      }
 220
 221      if (!i && j<16)
 222        work += block[count] = (ror(block[count],8)&0xFF00FF00)
 223                             | (rol(block[count],8)&0x00FF00FF);
 224      else
 225        work += block[count&15] = rol(block[(count+13)&15]
 226              ^ block[(count+8)&15] ^ block[(count+2)&15] ^ block[count&15], 1);
 227      *rot[4] += work + rol(*rot[0],5) + sha1rconsts[i];
 228      *rot[1] = rol(*rot[1],30);
 229
 230      // Rotate by one for next time.
 231      temp = rot[4];
 232      for (k = 4; k; k--) rot[k] = rot[k-1];
 233      *rot = temp;
 234      count++;
 235    }
 236  }
 237  // Add the previous values of state.i32[]
 238  for (i = 0; i<5; i++) TT.state.i32[i] += oldstate[i];
 239}
 240
 241static void sha2_32_transform(void)
 242{
 243  unsigned block[64], s0, s1, S0, S1, ch, maj, temp1, temp2, rot[8];
 244  int i;
 245
 246  for (i = 0; i<16; i++) block[i] = SWAP_BE32(TT.buffer.i32[i]);
 247
 248  // Extend the message schedule array beyond first 16 words
 249  for (i = 16; i<64; i++) {
 250    s0 = ror(block[i-15], 7) ^ ror(block[i-15], 18) ^ (block[i-15] >> 3);
 251    s1 = ror(block[i-2], 17) ^ ror(block[i-2], 19) ^ (block[i-2] >> 10);
 252    block[i] = block[i-16] + s0 + block[i-7] + s1;
 253  }
 254  // Copy context->state.i32[] to working vars
 255  for (i = 0; i<8; i++) rot[i] = TT.state.i32[i];
 256  // 64 rounds
 257  for (i = 0; i<64; i++) {
 258    S1 = ror(rot[4],6) ^ ror(rot[4],11) ^ ror(rot[4], 25);
 259    ch = (rot[4] & rot[5]) ^ ((~ rot[4]) & rot[6]);
 260    temp1 = rot[7] + S1 + ch + TT.rconsttable32[i] + block[i];
 261    S0 = ror(rot[0],2) ^ ror(rot[0],13) ^ ror(rot[0], 22);
 262    maj = (rot[0] & rot[1]) ^ (rot[0] & rot[2]) ^ (rot[1] & rot[2]);
 263    temp2 = S0 + maj;
 264    memmove(rot+1, rot, 28);
 265    rot[4] += temp1;
 266    rot[0] = temp1 + temp2;
 267  }
 268
 269  // Add the previous values of state.i32[]
 270  for (i = 0; i<8; i++) TT.state.i32[i] += rot[i];
 271}
 272
 273static void sha2_64_transform(void)
 274{
 275  unsigned long long block[80], s0, s1, S0, S1, ch, maj, temp1, temp2, rot[8];
 276  int i;
 277
 278  for (i=0; i<16; i++) block[i] = SWAP_BE64(TT.buffer.i64[i]);
 279
 280  // Extend the message schedule array beyond first 16 words
 281  for (i = 16; i<80; i++) {
 282    s0 = ror64(block[i-15], 1) ^ ror64(block[i-15], 8) ^ (block[i-15] >> 7);
 283    s1 = ror64(block[i-2], 19) ^ ror64(block[i-2], 61) ^ (block[i-2] >> 6);
 284    block[i] = block[i-16] + s0 + block[i-7] + s1;
 285  }
 286  // Copy context->state.i64[] to working vars
 287  for (i = 0; i<8; i++) rot[i] = TT.state.i64[i];
 288  // 80 rounds
 289  for (i = 0; i<80; i++) {
 290    S1 = ror64(rot[4],14) ^ ror64(rot[4],18) ^ ror64(rot[4], 41);
 291    ch = (rot[4] & rot[5]) ^ ((~ rot[4]) & rot[6]);
 292    temp1 = rot[7] + S1 + ch + TT.rconsttable64[i] + block[i];
 293    S0 = ror64(rot[0],28) ^ ror64(rot[0],34) ^ ror64(rot[0], 39);
 294    maj = (rot[0] & rot[1]) ^ (rot[0] & rot[2]) ^ (rot[1] & rot[2]);
 295    temp2 = S0 + maj;
 296    memmove(rot+1, rot, 56);
 297    rot[4] += temp1;
 298    rot[0] = temp1 + temp2;
 299  }
 300
 301  // Add the previous values of state.i64[]
 302  for (i=0; i<8; i++) TT.state.i64[i] += rot[i];
 303}
 304
 305// Fill the 64/128-byte (512/1024-bit) working buffer and call transform() when full.
 306
 307static void hash_update(char *data, unsigned int len, void (*transform)(void),
 308  int chunksize)
 309{
 310  unsigned int i, j;
 311
 312  j = TT.count & (chunksize - 1);
 313  if (TT.count+len<TT.count) TT.overflow++;
 314  TT.count += len;
 315
 316  for (;;) {
 317    // Grab next chunk of data, return if it's not enough to process a frame
 318    i = chunksize - j;
 319    if (i>len) i = len;
 320    memcpy(TT.buffer.c+j, data, i);
 321    if (j+i != chunksize) break;
 322
 323    // Process a frame
 324    transform();
 325    j=0;
 326    data += i;
 327    len -= i;
 328  }
 329}
 330
 331// Initialize array tersely
 332#define HASH_INIT(name, prefix) { name, (void *)prefix##_Init, \
 333  (void *)prefix##_Update, (void *)prefix##_Final, \
 334  prefix##_DIGEST_LENGTH, }
 335#define SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH
 336
 337// Call the assembly optimized library code when CFG_TOYBOX_LIBCRYPTO
 338static void do_lib_hash(int fd, char *name)
 339{
 340  // Largest context
 341  SHA512_CTX ctx;
 342  struct hash {
 343    char *name;
 344    int (*init)(void *);
 345    int (*update)(void *, void *, size_t);
 346    int (*final)(void *, void *);
 347    int digest_length;
 348  } algorithms[] = {
 349    USE_TOYBOX_LIBCRYPTO(
 350      USE_MD5SUM(HASH_INIT("md5sum", MD5),)
 351      USE_SHA1SUM(HASH_INIT("sha1sum", SHA1),)
 352      USE_SHA224SUM(HASH_INIT("sha224sum", SHA224),)
 353      USE_SHA256SUM(HASH_INIT("sha256sum", SHA256),)
 354      USE_SHA384SUM(HASH_INIT("sha384sum", SHA384),)
 355      USE_SHA512SUM(HASH_INIT("sha512sum", SHA512),)
 356    )
 357  }, * hash;
 358  int i;
 359
 360  // This should never NOT match, so no need to check
 361  for (i = 0; i<ARRAY_LEN(algorithms); i++)
 362    if (!strcmp(toys.which->name, algorithms[i].name)) break;
 363  hash = algorithms+i;
 364
 365  hash->init(&ctx);
 366  for (;;) {
 367      i = read(fd, toybuf, sizeof(toybuf));
 368      if (i<1) break;
 369      hash->update(&ctx, toybuf, i);
 370  }
 371  hash->final(toybuf+128, &ctx);
 372
 373  for (i = 0; i<hash->digest_length; i++)
 374    sprintf(toybuf+2*i, "%02x", toybuf[i+128]);
 375}
 376
 377static void do_builtin_hash(int fd, char *name)
 378{
 379  unsigned long long count[2];
 380  int i, chunksize, digestlen, method;
 381  volatile char *pp;
 382  void (*transform)(void);
 383  char buf;
 384
 385  // md5sum, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum
 386  method = stridx("us2581", toys.which->name[4]);
 387
 388  // select hash type
 389  transform = (void *[]){md5_transform, sha1_transform, sha2_32_transform,
 390    sha2_32_transform, sha2_64_transform, sha2_64_transform}[method];
 391  digestlen = (char []){16, 20, 28, 32, 48, 64}[method];
 392  chunksize = 64<<(method>=4);
 393  if (method<=1)
 394    memcpy(TT.state.i32, (unsigned []){0x67452301, 0xEFCDAB89, 0x98BADCFE,
 395      0x10325476, 0xC3D2E1F0}, 20);
 396  else if (method==2)
 397    memcpy(TT.state.i32, (unsigned []){0xc1059ed8, 0x367cd507, 0x3070dd17,
 398      0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4}, 32);
 399  else if (method==3)
 400    memcpy(TT.state.i32, (unsigned []){0x6a09e667, 0xbb67ae85, 0x3c6ef372,
 401      0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}, 32);
 402  else if (method==4)
 403    memcpy(TT.state.i64, (unsigned long long []){0xcbbb9d5dc1059ed8,
 404      0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939,
 405      0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7,
 406      0x47b5481dbefa4fa4}, 64);
 407  else memcpy(TT.state.i64, (unsigned long long []){0x6a09e667f3bcc908,
 408      0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
 409      0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b,
 410      0x5be0cd19137e2179}, 64);
 411
 412  TT.count = 0;
 413  for (;;) {
 414    i = read(fd, toybuf, sizeof(toybuf));
 415    if (i<1) break;
 416    hash_update(toybuf, i, transform, chunksize);
 417  }
 418
 419  // End the message by appending a "1" bit to the data, ending with the
 420  // message size (in bits, big endian), and adding enough zero bits in
 421  // between to pad to the end of the next frame.
 422  //
 423  // Since our input up to now has been in whole bytes, we can deal with
 424  // bytes here too. sha384 and 512 use 128 bit counter, so track overflow.
 425  buf = 0x80;
 426  count[0] = (TT.overflow<<3)+(TT.count>>61);
 427  count[1] = TT.count<<3; // convert to bits
 428  for (i = 0; i<2; i++)
 429    count[i] = !method ? SWAP_LE64(count[i]) : SWAP_BE64(count[i]);
 430  i = 8<<(method>=4);
 431  do {
 432    hash_update(&buf, 1, transform, chunksize);
 433    buf = 0;
 434  } while ((TT.count&(chunksize-1)) != chunksize-i);
 435  hash_update((void *)(count+(method<4)), i, transform, chunksize);
 436
 437  // write digest to toybuf
 438  if (method>=4) for (i=0; i<digestlen/8; i++)
 439    sprintf(toybuf+16*i, "%016llx", TT.state.i64[i]);
 440  else for (i=0; i<digestlen/4; i++)
 441    sprintf(toybuf+8*i, "%08x",
 442            !method ? bswap_32(TT.state.i32[i]) : TT.state.i32[i]);
 443  // Wipe variables. Cryptographer paranoia. Avoid "optimizing" out memset
 444  // by looping on a volatile pointer.
 445  i = sizeof(struct md5sum_data)-offsetof(struct md5sum_data, state.i64);
 446  for (pp = (void *)TT.state.i64; i; i--) *pp++ = 0;
 447  pp = toybuf+strlen(toybuf)+1;
 448  for (i = sizeof(toybuf)-(pp-toybuf); i; i--) *pp++ = 0;
 449}
 450
 451// Callback for loopfiles()
 452// Call builtin or lib hash function, then display output if necessary
 453static void do_hash(int fd, char *name)
 454{
 455  if (CFG_TOYBOX_LIBCRYPTO) do_lib_hash(fd, name);
 456  else do_builtin_hash(fd, name);
 457
 458  if (name) printf("%s  %s\n"+4*!!FLAG(b), toybuf, name);
 459}
 460
 461static void do_c_line(char *line)
 462{
 463  int space = 0, fail = 0, fd;
 464  char *name;
 465
 466  for (name = line; *name; name++) {
 467    if (isspace(*name)) {
 468      space++;
 469      *name = 0;
 470    } else if (space) break;
 471  }
 472  if (!space || !*line || !*name) return error_msg("bad line %s", line);
 473
 474  fd = !strcmp(name, "-") ? 0 : open(name, O_RDONLY);
 475
 476  TT.sawline = 1;
 477  if (fd==-1) {
 478    perror_msg_raw(name);
 479    *toybuf = 0;
 480  } else do_hash(fd, 0);
 481  if (strcasecmp(line, toybuf)) toys.exitval = fail = 1;
 482  if (!FLAG(s)) printf("%s: %s\n", name, fail ? "FAILED" : "OK");
 483  if (fd>0) close(fd);
 484}
 485
 486// Used instead of loopfiles_line to report error on files containing no hashes.
 487static void do_c_file(char *name)
 488{
 489  FILE *fp = !strcmp(name, "-") ? stdin : fopen(name, "r");
 490  char *line;
 491
 492  if (!fp) return perror_msg_raw(name);
 493
 494  TT.sawline = 0;
 495
 496  for (;;) {
 497    if (!(line = xgetline(fp))) break;
 498    do_c_line(line);
 499    free(line);
 500  }
 501  if (fp!=stdin) fclose(fp);
 502
 503  if (!TT.sawline) error_msg("%s: no lines", name);
 504}
 505
 506void md5sum_main(void)
 507{
 508  int i;
 509
 510  // Calculate table if we have floating point. Static version should drop
 511  // out at compile time when we don't need it.
 512  if (!CFG_TOYBOX_LIBCRYPTO) {
 513    if (*toys.which->name == 'm') { // MD5
 514      if (CFG_TOYBOX_FLOAT) {
 515        TT.rconsttable32 = xmalloc(64*4);
 516        for (i = 0; i<64; i++) TT.rconsttable32[i] = fabs(sin(i+1))*(1LL<<32);
 517      } else TT.rconsttable32 = md5nofloat;
 518    } else if (toys.which->name[3] == '2') { // sha224, sha256
 519      TT.rconsttable32 = xmalloc(64*4);
 520      for (i=0; i<64; i++) TT.rconsttable32[i] = sha512nofloat[i] >> 32;
 521    } else TT.rconsttable64 = sha512nofloat; // sha384, sha512
 522  }
 523
 524  if (FLAG(c)) for (i = 0; toys.optargs[i]; i++) do_c_file(toys.optargs[i]);
 525  else {
 526    if (FLAG(s)) error_exit("-s only with -c");
 527    loopfiles(toys.optargs, do_hash);
 528  }
 529}
 530