acst

Tracks changes and corruption in files using xattr-based checksums.
git clone https://noxz.tech/git/acst.git
Log | Files | Tags | LICENSE

commit: da2740b74db8497311ffa189ec8ef35f7765540d
parent: 9b533c9ba5cfd7b79fe5b63b1220b84202dec405
author: Chris Noxz <chris@noxz.tech>
date:   Sat, 2 Jul 2022 14:32:50 +0200
Replace the sha256 implementation with a similar to GNU coreutils

This gives better performance and reliability, as tests showed that some larger
files gave the wrong sha256 checksum with previous implementation.
Macst.c4+-
Msha256.c497+++++++++++++-------
Msha256.h116+++--
3 files changed, 374 insertions(+), 243 deletions(-)
diff --git a/acst.c b/acst.c
@@ -259,14 +259,14 @@ xa_compute(int fd, xa_t *xa)
 static void
 xa_hash(int fd, char *cs)
 {
-	SHA256_ctx      ctx;                    // SHA256 context
+	struct SHA256_ctx ctx;                  // SHA256 context
 	unsigned char   *hash,                  // hash buffer
 	                buf[BUFSZ];             // file content read buffer
 	size_t          len;                    // holder for read buffer length
 
 	SHA256_init(&ctx);
 	while ((len = read(fd, buf, BUFSZ)))
-		SHA256_update(&ctx, buf, len);
+		SHA256_update(buf, len, &ctx);
 
 	if (!(hash = calloc(1, SHA256_BYTES)))
 		error(ER_FATAL, STR_ERR_OOM);
diff --git a/sha256.c b/sha256.c
@@ -1,209 +1,344 @@
-/*
- * FIPS 180-2 SHA-224/256/384/512 implementation
- * Last update: 02/02/2007
- * Issue date:  04/30/2005
- *
- * Copyright (C) 2013, Con Kolivas <kernel@kolivas.org>
- * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
+/* sha256.c - Functions to compute SHA256 and SHA224 message digest of files or
+   memory blocks according to the NIST specification FIPS-180-2.
 
-#include <string.h>
-#include <stdint.h>
+   Copyright (C) 2005-2006, 2008-2022 Free Software Foundation, Inc.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   This file is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by David Madore, considerably copypasting from
+   Scott G. Miller's sha1.c
+
+   Minor changes by Chirs Noxz
+*/
 
+/* Specification. */
 #include "sha256.h"
 
-#define UNPACK32(x, str)                      \
-{                                             \
-    *((str) + 3) = (uint8_t) ((x)      );       \
-    *((str) + 2) = (uint8_t) ((x) >>  8);       \
-    *((str) + 1) = (uint8_t) ((x) >> 16);       \
-    *((str) + 0) = (uint8_t) ((x) >> 24);       \
-}
+#include <stdalign.h>
+#include <stdint.h>
+#include <string.h>
 
-#define PACK32(str, x)                        \
-{                                             \
-    *(x) =   ((uint32_t) *((str) + 3)      )    \
-           | ((uint32_t) *((str) + 2) <<  8)    \
-           | ((uint32_t) *((str) + 1) << 16)    \
-           | ((uint32_t) *((str) + 0) << 24);   \
-}
+#include <byteswap.h>
+#ifdef WORDS_BIGENDIAN
+# define SWAP(n) (n)
+#else
+# define SWAP(n) bswap_32 (n)
+#endif
 
-#define SHA256_SCR(i)                         \
-{                                             \
-    w[i] =  SHA256_F4(w[i -  2]) + w[i -  7]  \
-          + SHA256_F3(w[i - 15]) + w[i - 16]; \
-}
+/* This array contains the bytes used to pad the buffer to the next
+ * 64-byte boundary. */
+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
 
-uint32_t SHA256_h0[8] =
-            {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
-             0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
-
-uint32_t SHA256_k[64] =
-            {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
-             0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
-             0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
-             0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
-             0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
-             0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
-             0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
-             0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
-             0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
-             0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
-             0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
-             0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
-             0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
-             0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
-             0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
-             0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
-
-/* SHA-256 functions */
-
-void SHA256_transf(SHA256_ctx *ctx, const unsigned char *message,
-                   unsigned int block_nb)
+/*
+ * Takes a pointer to a 256 bit block of data (eight 32 bit ints) and
+ * initializes it to the start constants of the SHA256 algorithm. This
+ * must be called before using hash in the call to sha256_hash
+*/
+void
+SHA256_init (struct SHA256_ctx *ctx)
 {
-    uint32_t w[64];
-    uint32_t wv[8];
-    uint32_t t1, t2;
-    const unsigned char *sub_block;
-    int i;
-
-    int j;
-
-    for (i = 0; i < (int) block_nb; i++) {
-        sub_block = message + (i << 6);
-
-        for (j = 0; j < 16; j++) {
-            PACK32(&sub_block[j << 2], &w[j]);
-        }
-
-        for (j = 16; j < 64; j++) {
-            SHA256_SCR(j);
-        }
-
-        for (j = 0; j < 8; j++) {
-            wv[j] = ctx->h[j];
-        }
-
-        for (j = 0; j < 64; j++) {
-            t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
-                + SHA256_k[j] + w[j];
-            t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
-            wv[7] = wv[6];
-            wv[6] = wv[5];
-            wv[5] = wv[4];
-            wv[4] = wv[3] + t1;
-            wv[3] = wv[2];
-            wv[2] = wv[1];
-            wv[1] = wv[0];
-            wv[0] = t1 + t2;
-        }
-
-        for (j = 0; j < 8; j++) {
-            ctx->h[j] += wv[j];
-        }
-    }
+	ctx->state[0] = 0x6a09e667UL;
+	ctx->state[1] = 0xbb67ae85UL;
+	ctx->state[2] = 0x3c6ef372UL;
+	ctx->state[3] = 0xa54ff53aUL;
+	ctx->state[4] = 0x510e527fUL;
+	ctx->state[5] = 0x9b05688cUL;
+	ctx->state[6] = 0x1f83d9abUL;
+	ctx->state[7] = 0x5be0cd19UL;
+
+	ctx->total[0] = ctx->total[1] = 0;
+	ctx->buflen = 0;
 }
 
-void SHA256(const unsigned char *message, unsigned int len, unsigned char *digest)
+/* Copy the value from v into the memory location pointed to by *CP,
+ * If your architecture allows unaligned access, this is equivalent to
+ * (__typeof__ (v) *) cp = v */
+static void
+set_uint32 (char *cp, uint32_t v)
 {
-    SHA256_ctx ctx;
-
-    SHA256_init(&ctx);
-    SHA256_update(&ctx, message, len);
-    SHA256_final(&ctx, digest);
+	memcpy (cp, &v, sizeof v);
 }
 
-void SHA256_init(SHA256_ctx *ctx)
+/* Put result from CTX in first 32 bytes following RESBUF.
+ * The result must be in little endian byte order. */
+void *
+SHA256_read_ctx (const struct SHA256_ctx *ctx, void *resbuf)
 {
-    int i;
-    for (i = 0; i < 8; i++) {
-        ctx->h[i] = SHA256_h0[i];
-    }
+	int i;
+		char *r = resbuf;
 
-    ctx->len = 0;
-    ctx->tot_len = 0;
+	for (i = 0; i < 8; i++)
+		set_uint32 (r + i * sizeof ctx->state[0], SWAP (ctx->state[i]));
+
+	return resbuf;
 }
 
-void SHA256_update(SHA256_ctx *ctx, const unsigned char *message,
-                   unsigned int len)
+/* Process the remaining bytes in the internal buffer and the usual
+ * prolog according to the standard and write the result to RESBUF. */
+static void
+SHA256_conclude_ctx (struct SHA256_ctx *ctx)
 {
-    unsigned int block_nb;
-    unsigned int new_len, rem_len, tmp_len;
-    const unsigned char *shifted_message;
-
-    tmp_len = SHA256_BLOCK_SIZE - ctx->len;
-    rem_len = len < tmp_len ? len : tmp_len;
-
-    memcpy(&ctx->block[ctx->len], message, rem_len);
-
-    if (ctx->len + len < SHA256_BLOCK_SIZE) {
-        ctx->len += len;
-        return;
-    }
+	/* Take yet unprocessed bytes into account */
+	size_t bytes = ctx->buflen;
+	size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4;
 
-    new_len = len - rem_len;
-    block_nb = new_len / SHA256_BLOCK_SIZE;
+	/* Now count remaining bytes. */
+	ctx->total[0] += bytes;
+	if (ctx->total[0] < bytes)
+		++ctx->total[1];
 
-    shifted_message = message + rem_len;
+	/* Put the 64-bit file length in *bits* at the end of the buffer.
+	 * Use set_uint32 rather than a simple assignment, to avoid risk of
+	 * unaligned access. */
+	set_uint32 ((char *) &ctx->buffer[size - 2], SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)));
+	set_uint32 ((char *) &ctx->buffer[size - 1], SWAP (ctx->total[0] << 3));
 
-    SHA256_transf(ctx, ctx->block, 1);
-    SHA256_transf(ctx, shifted_message, block_nb);
+	memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 4 - bytes);
 
-    rem_len = new_len % SHA256_BLOCK_SIZE;
-
-    memcpy(ctx->block, &shifted_message[block_nb << 6],
-           rem_len);
-
-    ctx->len = rem_len;
-    ctx->tot_len += (block_nb + 1) << 6;
+	/* Process last bytes. */
+	SHA256_process_block (ctx->buffer, size * 4, ctx);
 }
 
-void SHA256_final(SHA256_ctx *ctx, unsigned char *digest)
+void *
+SHA256_final (struct SHA256_ctx *ctx, void *resbuf)
 {
-    unsigned int block_nb;
-    unsigned int pm_len;
-    unsigned int len_b;
-
-    int i;
-
-    block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
-                     < (ctx->len % SHA256_BLOCK_SIZE)));
-
-    len_b = (ctx->tot_len + ctx->len) << 3;
-    pm_len = block_nb << 6;
-
-    memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
-    ctx->block[ctx->len] = 0x80;
-    UNPACK32(len_b, ctx->block + pm_len - 4);
+	SHA256_conclude_ctx (ctx);
+	return SHA256_read_ctx (ctx, resbuf);
+}
 
-    SHA256_transf(ctx, ctx->block, block_nb);
+void
+SHA256_update (const void *buffer, size_t len, struct SHA256_ctx *ctx)
+{
+	/* When we already have some bits in our internal buffer concatenate
+	 * both inputs first. */
+	if (ctx->buflen != 0)
+	{
+		size_t left_over = ctx->buflen;
+		size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+		memcpy (&((char *) ctx->buffer)[left_over], buffer, add);
+		ctx->buflen += add;
+
+		if (ctx->buflen > 64)
+		{
+			SHA256_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
+
+			ctx->buflen &= 63;
+			/* The regions in the following copy operation cannot overlap,
+			 * because ctx->buflen < 64 ≤ (left_over + add) & ~63. */
+			memcpy (ctx->buffer, &((char *) ctx->buffer)[(left_over + add) & ~63], ctx->buflen);
+		}
+
+		buffer = (const char *) buffer + add;
+		len -= add;
+	}
+
+	/* Process available complete blocks. */
+	if (len >= 64)
+	{
+#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned)
+# define UNALIGNED_P(p) ((uintptr_t) (p) % alignof (uint32_t) != 0)
+		if (UNALIGNED_P (buffer))
+			while (len > 64)
+			{
+				SHA256_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
+				buffer = (const char *) buffer + 64;
+				len -= 64;
+			}
+		else
+#endif
+		{
+			SHA256_process_block (buffer, len & ~63, ctx);
+			buffer = (const char *) buffer + (len & ~63);
+			len &= 63;
+		}
+	}
+
+	/* Move remaining bytes in internal buffer. */
+	if (len > 0)
+	{
+		size_t left_over = ctx->buflen;
+
+		memcpy (&((char *) ctx->buffer)[left_over], buffer, len);
+		left_over += len;
+		if (left_over >= 64)
+		{
+			SHA256_process_block (ctx->buffer, 64, ctx);
+			left_over -= 64;
+			/* The regions in the following copy operation cannot overlap,
+			 * because left_over ≤ 64. */
+			memcpy (ctx->buffer, &ctx->buffer[16], left_over);
+		}
+		ctx->buflen = left_over;
+	}
+}
 
-    for (i = 0 ; i < 8; i++) {
-        UNPACK32(ctx->h[i], &digest[i << 2]);
-    }
+/* --- Code below is the primary difference between sha1.c and SHA256.c --- */
+
+/* SHA256 round constants */
+#define K(I) SHA256_round_constants[I]
+static const uint32_t SHA256_round_constants[64] = {
+	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+	0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+	0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+	0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+	0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+	0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+	0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+	0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+	0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+	0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+	0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+	0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+	0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL,
+};
+
+/* Round functions. */
+#define F2(A,B,C) ( ( A & B ) | ( C & ( A | B ) ) )
+#define F1(E,F,G) ( G ^ ( E & ( F ^ G ) ) )
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+ * It is assumed that LEN % 64 == 0.
+ * Most of this code comes from GnuPG's cipher/sha1.c. */
+
+void
+SHA256_process_block (const void *buffer, size_t len, struct SHA256_ctx *ctx)
+{
+	const uint32_t *words = buffer;
+	size_t nwords = len / sizeof (uint32_t);
+	const uint32_t *endp = words + nwords;
+	uint32_t x[16];
+	uint32_t a = ctx->state[0];
+	uint32_t b = ctx->state[1];
+	uint32_t c = ctx->state[2];
+	uint32_t d = ctx->state[3];
+	uint32_t e = ctx->state[4];
+	uint32_t f = ctx->state[5];
+	uint32_t g = ctx->state[6];
+	uint32_t h = ctx->state[7];
+	uint32_t lolen = len;
+
+	/* First increment the byte count. FIPS PUB 180-2 specifies the possible
+	 * length of the file up to 2^64 bits. Here we only compute the
+	 * number of bytes. Do a double word increment. */
+	ctx->total[0] += lolen;
+	ctx->total[1] += (len >> 31 >> 1) + (ctx->total[0] < lolen);
+
+#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+#define S0(x) (rol(x,25)^rol(x,14)^(x>>3))
+#define S1(x) (rol(x,15)^rol(x,13)^(x>>10))
+#define SS0(x) (rol(x,30)^rol(x,19)^rol(x,10))
+#define SS1(x) (rol(x,26)^rol(x,21)^rol(x,7))
+
+#define M(I) ( tm =   S1(x[(I-2)&0x0f]) + x[(I-7)&0x0f] \
+                    + S0(x[(I-15)&0x0f]) + x[I&0x0f]    \
+               , x[I&0x0f] = tm )
+
+#define R(A,B,C,D,E,F,G,H,K,M)  do { t0 = SS0(A) + F2(A,B,C); \
+                                     t1 = H + SS1(E)  \
+                                      + F1(E,F,G)     \
+                                      + K             \
+                                      + M;            \
+                                     D += t1;  H = t0 + t1; \
+                               } while(0)
+
+	while (words < endp)
+	{
+		uint32_t tm;
+		uint32_t t0, t1;
+		int t;
+		/* FIXME: see sha1.c for a better implementation. */
+		for (t = 0; t < 16; t++) {
+			x[t] = SWAP (*words);
+			words++;
+		}
+
+		R( a, b, c, d, e, f, g, h, K( 0), x[ 0] );
+		R( h, a, b, c, d, e, f, g, K( 1), x[ 1] );
+		R( g, h, a, b, c, d, e, f, K( 2), x[ 2] );
+		R( f, g, h, a, b, c, d, e, K( 3), x[ 3] );
+		R( e, f, g, h, a, b, c, d, K( 4), x[ 4] );
+		R( d, e, f, g, h, a, b, c, K( 5), x[ 5] );
+		R( c, d, e, f, g, h, a, b, K( 6), x[ 6] );
+		R( b, c, d, e, f, g, h, a, K( 7), x[ 7] );
+		R( a, b, c, d, e, f, g, h, K( 8), x[ 8] );
+		R( h, a, b, c, d, e, f, g, K( 9), x[ 9] );
+		R( g, h, a, b, c, d, e, f, K(10), x[10] );
+		R( f, g, h, a, b, c, d, e, K(11), x[11] );
+		R( e, f, g, h, a, b, c, d, K(12), x[12] );
+		R( d, e, f, g, h, a, b, c, K(13), x[13] );
+		R( c, d, e, f, g, h, a, b, K(14), x[14] );
+		R( b, c, d, e, f, g, h, a, K(15), x[15] );
+		R( a, b, c, d, e, f, g, h, K(16), M(16) );
+		R( h, a, b, c, d, e, f, g, K(17), M(17) );
+		R( g, h, a, b, c, d, e, f, K(18), M(18) );
+		R( f, g, h, a, b, c, d, e, K(19), M(19) );
+		R( e, f, g, h, a, b, c, d, K(20), M(20) );
+		R( d, e, f, g, h, a, b, c, K(21), M(21) );
+		R( c, d, e, f, g, h, a, b, K(22), M(22) );
+		R( b, c, d, e, f, g, h, a, K(23), M(23) );
+		R( a, b, c, d, e, f, g, h, K(24), M(24) );
+		R( h, a, b, c, d, e, f, g, K(25), M(25) );
+		R( g, h, a, b, c, d, e, f, K(26), M(26) );
+		R( f, g, h, a, b, c, d, e, K(27), M(27) );
+		R( e, f, g, h, a, b, c, d, K(28), M(28) );
+		R( d, e, f, g, h, a, b, c, K(29), M(29) );
+		R( c, d, e, f, g, h, a, b, K(30), M(30) );
+		R( b, c, d, e, f, g, h, a, K(31), M(31) );
+		R( a, b, c, d, e, f, g, h, K(32), M(32) );
+		R( h, a, b, c, d, e, f, g, K(33), M(33) );
+		R( g, h, a, b, c, d, e, f, K(34), M(34) );
+		R( f, g, h, a, b, c, d, e, K(35), M(35) );
+		R( e, f, g, h, a, b, c, d, K(36), M(36) );
+		R( d, e, f, g, h, a, b, c, K(37), M(37) );
+		R( c, d, e, f, g, h, a, b, K(38), M(38) );
+		R( b, c, d, e, f, g, h, a, K(39), M(39) );
+		R( a, b, c, d, e, f, g, h, K(40), M(40) );
+		R( h, a, b, c, d, e, f, g, K(41), M(41) );
+		R( g, h, a, b, c, d, e, f, K(42), M(42) );
+		R( f, g, h, a, b, c, d, e, K(43), M(43) );
+		R( e, f, g, h, a, b, c, d, K(44), M(44) );
+		R( d, e, f, g, h, a, b, c, K(45), M(45) );
+		R( c, d, e, f, g, h, a, b, K(46), M(46) );
+		R( b, c, d, e, f, g, h, a, K(47), M(47) );
+		R( a, b, c, d, e, f, g, h, K(48), M(48) );
+		R( h, a, b, c, d, e, f, g, K(49), M(49) );
+		R( g, h, a, b, c, d, e, f, K(50), M(50) );
+		R( f, g, h, a, b, c, d, e, K(51), M(51) );
+		R( e, f, g, h, a, b, c, d, K(52), M(52) );
+		R( d, e, f, g, h, a, b, c, K(53), M(53) );
+		R( c, d, e, f, g, h, a, b, K(54), M(54) );
+		R( b, c, d, e, f, g, h, a, K(55), M(55) );
+		R( a, b, c, d, e, f, g, h, K(56), M(56) );
+		R( h, a, b, c, d, e, f, g, K(57), M(57) );
+		R( g, h, a, b, c, d, e, f, K(58), M(58) );
+		R( f, g, h, a, b, c, d, e, K(59), M(59) );
+		R( e, f, g, h, a, b, c, d, K(60), M(60) );
+		R( d, e, f, g, h, a, b, c, K(61), M(61) );
+		R( c, d, e, f, g, h, a, b, K(62), M(62) );
+		R( b, c, d, e, f, g, h, a, K(63), M(63) );
+
+		a = ctx->state[0] += a;
+		b = ctx->state[1] += b;
+		c = ctx->state[2] += c;
+		d = ctx->state[3] += d;
+		e = ctx->state[4] += e;
+		f = ctx->state[5] += f;
+		g = ctx->state[6] += g;
+		h = ctx->state[7] += h;
+	}
 }
diff --git a/sha256.h b/sha256.h
@@ -1,69 +1,65 @@
-/*
- * FIPS 180-2 SHA-224/256/384/512 implementation
- * Last update: 02/02/2007
- * Issue date:  04/30/2005
- *
- * Copyright (C) 2013, Con Kolivas <kernel@kolivas.org>
- * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
+/* Declarations of functions and data types used for SHA256 and SHA224 sum
+   library functions.
+   Copyright (C) 2005-2006, 2008-2022 Free Software Foundation, Inc.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   This file is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
 
-#include <stdint.h>
+#ifndef SHA256_H
+# define SHA256_H 1
 
-#ifndef SHA2_H
-#define SHA2_H
+# include <stdio.h>
+# include <stdint.h>
 
-#define SHA256_DIGEST_SIZE ( 256 / 8)
-#define SHA256_BLOCK_SIZE  ( 512 / 8)
+/* Structure to save state of computation between the single steps.  */
+struct SHA256_ctx
+{
+	uint32_t state[8];
+
+	uint32_t total[2];
+	size_t buflen;       /* ≥ 0, ≤ 128 */
+	uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */
+};
+
+/*
+  Takes a pointer to a 256 bit block of data (eight 32 bit ints) and
+  initializes it to the start constants of the SHA256 algorithm.  This
+  must be called before using hash in the call to sha256_hash
+*/
+extern void SHA256_init (struct SHA256_ctx *ctx);
 
-#define SHFR(x, n)    (x >> n)
-#define ROTR(x, n)   ((x >> n) | (x << ((sizeof(x) << 3) - n)))
-#define CH(x, y, z)  ((x & y) ^ (~x & z))
-#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is necessary that LEN is a multiple of 64!!! */
+extern void SHA256_process_block (const void *buffer, size_t len, struct SHA256_ctx *ctx);
 
-#define SHA256_F1(x) (ROTR(x,  2) ^ ROTR(x, 13) ^ ROTR(x, 22))
-#define SHA256_F2(x) (ROTR(x,  6) ^ ROTR(x, 11) ^ ROTR(x, 25))
-#define SHA256_F3(x) (ROTR(x,  7) ^ ROTR(x, 18) ^ SHFR(x,  3))
-#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is NOT required that LEN is a multiple of 64.  */
+extern void SHA256_update (const void *buffer, size_t len, struct SHA256_ctx *ctx);
 
-typedef struct {
-    unsigned int tot_len;
-    unsigned int len;
-    unsigned char block[2 * SHA256_BLOCK_SIZE];
-    uint32_t h[8];
-} SHA256_ctx;
+/* Process the remaining bytes in the buffer and put result from CTX
+   in first 32 (28) bytes following RESBUF.  The result is always in little
+   endian byte order, so that a byte-wise output yields to the wanted
+   ASCII representation of the message digest.  */
+extern void *SHA256_final (struct SHA256_ctx *ctx, void *restrict resbuf);
 
-extern uint32_t SHA256_k[64];
 
-void SHA256_init(SHA256_ctx * ctx);
-void SHA256_update(SHA256_ctx *ctx, const unsigned char *message,
-                   unsigned int len);
-void SHA256_final(SHA256_ctx *ctx, unsigned char *digest);
-void SHA256(const unsigned char *message, unsigned int len,
-            unsigned char *digest);
+/* Put result from CTX in first 32 (28) bytes following RESBUF.  The result is
+   always in little endian byte order, so that a byte-wise output yields
+   to the wanted ASCII representation of the message digest.  */
+extern void *SHA256_read_ctx (const struct SHA256_ctx *ctx, void *restrict resbuf);
 
-#endif /* !SHA2_H */
+#endif