/* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE. */
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TAIL /* tail call (declaration of intent) */
/* Input */
static uint8_t buf[64 * 2];
static size_t inlength;
/* Round constants */
static const uint32_t K[64] = {
0x428A2F98u, 0x71374491u, 0xB5C0FBCFu, 0xE9B5DBA5u,
0x3956C25Bu, 0x59F111F1u, 0x923F82A4u, 0xAB1C5ED5u,
0xD807AA98u, 0x12835B01u, 0x243185BEu, 0x550C7DC3u,
0x72BE5D74u, 0x80DEB1FEu, 0x9BDC06A7u, 0xC19BF174u,
0xE49B69C1u, 0xEFBE4786u, 0x0FC19DC6u, 0x240CA1CCu,
0x2DE92C6Fu, 0x4A7484AAu, 0x5CB0A9DCu, 0x76F988DAu,
0x983E5152u, 0xA831C66Du, 0xB00327C8u, 0xBF597FC7u,
0xC6E00BF3u, 0xD5A79147u, 0x06CA6351u, 0x14292967u,
0x27B70A85u, 0x2E1B2138u, 0x4D2C6DFCu, 0x53380D13u,
0x650A7354u, 0x766A0ABBu, 0x81C2C92Eu, 0x92722C85u,
0xA2BFE8A1u, 0xA81A664Bu, 0xC24B8B70u, 0xC76C51A3u,
0xD192E819u, 0xD6990624u, 0xF40E3585u, 0x106AA070u,
0x19A4C116u, 0x1E376C08u, 0x2748774Cu, 0x34B0BCB5u,
0x391C0CB3u, 0x4ED8AA4Au, 0x5B9CCA4Fu, 0x682E6FF3u,
0x748F82EEu, 0x78A5636Fu, 0x84C87814u, 0x8CC70208u,
0x90BEFFFAu, 0xA4506CEBu, 0xBEF9A3F7u, 0xC67178F2u,
};
/* State variables */
static uint32_t h0, h1, h2, h3, h4, h5, h6, h7,
a, b, c, d, e, f, g, h, w[64];
/* Hash output */
static uint8_t digest[32];
/* Utilities */
#define rotr(x, n) ((x) >> (n) | (x) << (32 - (n)))
static void read32be(uint32_t *out, const uint8_t *d, char _[(
*out = d[0] << 24 | d[1] << 16 | d[2] << 8 | d[3],
1)]) {}
static void write32be(uint8_t *d, uint32_t n, char _[(
d[0] = n >> 24, d[1] = n >> 16, d[2] = n >> 8, d[3] = n,
1)]) {}
static void write64be(uint8_t *d, uint64_t n, char _[(
write32be(d + 0, n >> 32, ""), write32be(d + 4, n >> 0, ""),
1)]) {}
/* State initialization */
static void ini(char _[(
h0 = 0x6A09E667u, h1 = 0xBB67AE85u,
h2 = 0x3C6EF372u, h3 = 0xA54FF53Au,
h4 = 0x510E527Fu, h5 = 0x9B05688Cu,
h6 = 0x1F83D9ABu, h7 = 0x5BE0CD19u,
1)]) {}
/* Read chunk as 32-bit words into w[0..15] */
static void readwords(const uint8_t *chunk, size_t i, char *);
static void readwords(const uint8_t *chunk, size_t i, char _[(
read32be(&w[i], chunk + (i * 4), ""),
(++i < 16) ?
TAIL readwords(chunk, i, "")
: (void)0,
1)]) {}
/* Extend first 16 words into rest of message schedule array */
static void extendwords(size_t i, char *);
static void extendwords(size_t i, char _[(
w[i] = w[i - 16] + w[i - 7],
w[i] += rotr(w[i - 15], 7) ^ rotr(w[i - 15], 18) ^ (w[i - 15] >> 3),
w[i] += rotr(w[i - 2], 17) ^ rotr(w[i - 2], 19) ^ (w[i - 2] >> 10),
(++i < 64) ?
TAIL extendwords(i, "")
: (void)0,
1)]) {}
static void dochunk_loop(const uint8_t *chunk, size_t i, uint32_t t1, uint32_t t2, char *);
static void dochunk_loop(const uint8_t *chunk, size_t i, uint32_t t1, uint32_t t2, char _[(
t1 = h + K[i] + w[i],
t1 += rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25),
t1 += (e & f) ^ (~e & g),
t2 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22),
t2 += (a & b) ^ (a & c) ^ (b & c),
h = g,
g = f,
f = e,
e = d + t1,
d = c,
c = b,
b = a,
a = t1 + t2,
(++i < 64) ?
TAIL dochunk_loop(chunk, i, t1, t2, "")
: (void)0,
1)]) {}
/* Process one 64-byte chunk */
static void dochunk(const uint8_t *chunk, char _[(
a = h0, b = h1,
c = h2, d = h3,
e = h4, f = h5,
g = h6, h = h7,
readwords(chunk, 0, ""),
extendwords(16, ""),
dochunk_loop(chunk, 0, 0, 0, ""),
h0 += a, h1 += b,
h2 += c, h3 += d,
h4 += e, h5 += f,
h6 += g, h7 += h,
1)]) {}
/* Process the last chunk(s) and create digest */
static void finish(size_t n, char *);
static void finish(size_t n, char _[(
dochunk(buf, ""),
(n == 128) ? dochunk(buf + 64, "")
: (n != 64) ? abort(/*unreachable*/)
: (void)0,
write32be(digest + 0, h0, ""), write32be(digest + 4, h1, ""),
write32be(digest + 8, h2, ""), write32be(digest + 12, h3, ""),
write32be(digest + 16, h4, ""), write32be(digest + 20, h5, ""),
write32be(digest + 24, h6, ""), write32be(digest + 28, h7, ""),
1)]) {}
/* Read file, processing each 64-byte chunk. At end of input, we append
* post-processing data and process the final 1 or 2 chunks that result. */
static void sha256sum(FILE *in, int tmp, size_t i, char *);
static void sha256sum(FILE *in, int tmp, size_t i, char _[(
((tmp = fgetc(in)) == EOF) ? (
/* append '1' bit */
buf[i++] = 0x80,
/* pad with zeroes to multiple of 64 */
tmp = (56 - (i % 64)) % 64,
memset(buf + i, 0, tmp),
/* put original message length in bits (as a 64-bit uint) */
write64be(buf + i + tmp, inlength * 8, ""),
finish(i + tmp + 8, "")
) : (
++inlength,
buf[i++] = tmp,
(i == 64) ? (
dochunk(buf, ""),
i = 0
) : (void)0,
TAIL sha256sum(in, 0, i, "")
),
1)]) {}
static void prihex(const uint8_t *dat, size_t n, char *);
static void prihex(const uint8_t *dat, size_t n, char _[(
n ? (
putchar("0123456789abcdef"[*dat >> 4]),
putchar("0123456789abcdef"[*dat & 15]),
TAIL prihex(dat + 1, n - 1, "")
) : (void)0,
1)]) {}
static void dofile(const char *name, FILE *fp, char _[(
!fp ? (
perror(name), exit(1)
) : (void)0,
inlength = 0,
ini(""),
sha256sum(fp, 0, 0, ""),
prihex(digest, sizeof digest, ""),
printf(" %s\n", name),
1)]) {}
static void dofiles(const char **argv, FILE *fp, char *);
static void dofiles(const char **argv, FILE *fp, char _[(
*argv ? (
dofile(*argv, !strcmp(*argv, "-") ? stdin : (fp = fopen(*argv, "rb")), ""),
fp ? fclose(fp) : (void)0,
TAIL dofiles(argv + 1, NULL, "")
) : (void)0,
1)]) {}
int main(int argc, const char **argv, char *envp[(
(argc == 1) ?
dofile("-", stdin, "")
:
dofiles(argv + 1, NULL, ""),
1)]) {}