toybox/toys/other/sha3sum.c
<<
>>
Prefs
   1/* sha3sum.c - Keccak-f[1600] permutation, sponge construction
   2 *
   3 * Copyright 2014 David Leon Gil <coruus@gmail.com>
   4 *
   5 * https://keccak.team/files/Keccak-reference-3.0.pdf
   6 * https://csrc.nist.gov/publications/detail/fips/202/final
   7 * https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf
   8
   9// Depends on FLAG(b) being 4
  10USE_SHA3SUM(NEWTOY(sha3sum, "bSa#<128>512=224", TOYFLAG_USR|TOYFLAG_BIN))
  11
  12config SHA3SUM
  13  bool "sha3sum"
  14  default y
  15  help
  16    usage: sha3sum [-S] [-a BITS] [FILE...]
  17
  18    Hash function du jour.
  19
  20    -a  Produce a hash BITS long (default 224)
  21    -b  Brief (hash only, no filename)
  22    -S  Use SHAKE termination byte instead of SHA3 (ask FIPS why)
  23*/
  24
  25#define FOR_sha3sum
  26#include "toys.h"
  27
  28GLOBALS(
  29  long a;
  30  unsigned long long rc[24];
  31)
  32
  33static const char rho[] =
  34  {1,3,6,10,15,21,28,36,45,55,2,14,27,41,56,8,25,43,62,18,39,61,20,44};
  35static const char pi[] =
  36  {10,7,11,17,18,3,5,16,8,21,24,4,15,23,19,13,12,2,20,14,22,9,6,1};
  37static const char rcpack[] =
  38  {0x33,0x07,0xdd,0x16,0x38,0x1b,0x7b,0x2b,0xad,0x6a,0xce,0x4c,0x29,0xfe,0x31,
  39   0x68,0x9d,0xb0,0x8f,0x2f,0x0a};
  40
  41static void keccak(unsigned long long *a)
  42{
  43  unsigned long long b[5] = {0}, t;
  44  int i, x, y;
  45
  46  for (i = 0; i < 24; i++) {
  47    for (x = 0; x<5; x++) for (b[x] = 0, y = 0; y<25; y += 5) b[x] ^= a[x+y];
  48    for (x = 0; x<5; x++) for (y = 0; y<25; y += 5) {
  49      t = b[(x+1)%5];
  50      a[y+x] ^= b[(x+4)%5]^(t<<1|t>>63);
  51    }
  52    for (t = a[1], x = 0; x<24; x++) {
  53      *b = a[pi[x]];
  54      a[pi[x]] = (t<<rho[x])|(t>>(64-rho[x]));
  55      t = *b;
  56    }
  57    for (y = 0; y<25; y += 5) {
  58      for (x = 0; x<5; x++) b[x] = a[y + x];
  59      for (x = 0; x<5; x++) a[y + x] = b[x]^((~b[(x+1)%5])&b[(x+2)%5]);
  60    }
  61    *a ^= TT.rc[i];
  62  }
  63}
  64
  65static void do_sha3sum(int fd, char *name)
  66{
  67  int span, ii, len, rate = 200-TT.a/4;
  68  char *ss = toybuf, buf[200];
  69
  70  memset(buf, 0, sizeof(buf));
  71  for (len = 0;; ss += rate) {
  72    if ((span = len-(ss-toybuf))<rate) {
  73      memcpy(toybuf, ss, span);
  74      len = span += readall(fd, (ss = toybuf)+span, sizeof(toybuf)-span);
  75    }
  76    if (span>rate) span = rate;
  77    for (ii = 0; ii<span; ii++) buf[ii] ^= ss[ii];
  78    if (rate!=span) {
  79      buf[span] ^= FLAG(S) ? 0x1f : 0x06;
  80      buf[rate-1] ^= 0x80;
  81    }
  82    keccak((void *)buf);
  83    if (span<rate) break;
  84  }
  85
  86  for (ii = 0; ii<TT.a/8; ) {
  87    printf("%02x", buf[ii%rate]);
  88    if (!(++ii%rate)) keccak((void *)buf);
  89  }
  90  memset(buf, 0, sizeof(buf));
  91
  92  // Depends on FLAG(b) being 4
  93  xprintf("  %s\n"+FLAG(b), name);
  94}
  95
  96// TODO test 224 256 384 512, and shake 128 256
  97void sha3sum_main(void)
  98{
  99  int i, j, k;
 100  char *s;
 101
 102  // Decompress RC table
 103  for (s = (void *)rcpack, i = 127; i; s += 3) for (i>>=1,k = j = 0; k<24; k++)
 104    if (1&(s[k>>3]>>(7-(k&7)))) TT.rc[k] |= 1ULL<<i;
 105
 106  loopfiles(toys.optargs, do_sha3sum);
 107}
 108