aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2019-02-10 11:28:30 +0100
committerMattias Andrée <maandree@kth.se>2019-02-10 11:28:30 +0100
commitd84edd9500e6e22ba49c76dc93a7c0731755d008 (patch)
tree5238a0362e0f70ea44fa40906c86102d5a50a4eb
parentFix warnings (diff)
downloadlibsha2-d84edd9500e6e22ba49c76dc93a7c0731755d008.tar.gz
libsha2-d84edd9500e6e22ba49c76dc93a7c0731755d008.tar.bz2
libsha2-d84edd9500e6e22ba49c76dc93a7c0731755d008.tar.xz
Fix libsha2_digest + minor improvements
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--.gitignore12
-rw-r--r--Makefile11
-rw-r--r--algorithm_output_size.c1
-rw-r--r--common.h12
-rw-r--r--digest.c67
-rw-r--r--init.c3
-rw-r--r--libsha2.h14
-rw-r--r--libsha2_algorithm_output_size.34
-rw-r--r--marshal.c6
-rw-r--r--process.c96
-rw-r--r--test.c121
-rw-r--r--unmarshal.c11
-rw-r--r--update.c109
13 files changed, 299 insertions, 168 deletions
diff --git a/.gitignore b/.gitignore
index dcb3c86..49bee63 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,4 @@
-_/
-\#*\#
-.*
-!.git*
+*\#*
*~
*.bak
*.swp
@@ -11,10 +8,5 @@ _/
*.so
*.su
*.a
-*.gch
-*.info
-*.pdf
-*.ps
-*.dvi
-*.test
*.lo
+/test
diff --git a/Makefile b/Makefile
index 4f672f7..838e391 100644
--- a/Makefile
+++ b/Makefile
@@ -20,6 +20,7 @@ OBJ =\
digest.o\
init.o\
marshal.o\
+ process.o\
state_output_size.o\
sum_fd.o\
unhex.o\
@@ -43,7 +44,7 @@ MAN3 =\
libsha2_update.3
-all: libsha2.a libsha2.$(LIBEXT)
+all: libsha2.a libsha2.$(LIBEXT) test
$(OBJ): $(@:.o=.c) $(HDR)
$(OBJ:.o=.lo): $(@:.lo=.c) $(HDR)
@@ -53,14 +54,20 @@ $(OBJ:.o=.lo): $(@:.lo=.c) $(HDR)
.c.lo:
$(CC) -fPIC -c -o $@ $< $(CFLAGS)
+test: test.o libsha2.a
+ $(CC) -o $@ test.o libsha2.a $(LDFLAGS)
+
libsha2.$(LIBEXT): $(OBJ:.o=.lo)
$(CC) $(LIBFLAGS) -o $@ $(OBJ) $(LDFLAGS)
libsha2.a: $(OBJ)
-rm -f -- $@
- $(AR) rc $@ $?
+ $(AR) rc $@ $(OBJ)
$(AR) -s $@
+check: test
+ ./test
+
install:
mkdir -p -- "$(DESTDIR)$(PREFIX)/lib"
mkdir -p -- "$(DESTDIR)$(PREFIX)/include"
diff --git a/algorithm_output_size.c b/algorithm_output_size.c
index 2824b55..2593a15 100644
--- a/algorithm_output_size.c
+++ b/algorithm_output_size.c
@@ -1,5 +1,6 @@
/* See LICENSE file for copyright and license details. */
#include "common.h"
+#include <stdio.h>
/**
diff --git a/common.h b/common.h
index 746cf36..e6e15d5 100644
--- a/common.h
+++ b/common.h
@@ -7,3 +7,15 @@
#include <stddef.h>
#include <string.h>
#include <unistd.h>
+
+
+/**
+ * Process a chunk using SHA-2
+ *
+ * @param state The hashing state
+ * @param chunk The data to process
+ */
+#if defined(__GNUC__)
+__attribute__((__nonnull__, __nothrow__))
+#endif
+void libsha2_process(struct libsha2_state *restrict, const unsigned char *restrict);
diff --git a/digest.c b/digest.c
index bcd318f..c15e2fa 100644
--- a/digest.c
+++ b/digest.c
@@ -13,8 +13,7 @@
void
libsha2_digest(struct libsha2_state *restrict state, const char *restrict message, size_t msglen, char *output)
{
- char *appendix;
- size_t i, j, k, n;
+ size_t off, i, n;
if (msglen & ~(size_t)7) {
libsha2_update(state, message, msglen & ~(size_t)7);
@@ -22,40 +21,52 @@ libsha2_digest(struct libsha2_state *restrict state, const char *restrict messag
msglen &= (size_t)7;
}
- k = 8 * state->chunk_size;
- n = state->chunk_size + 8;
- n = (k + (n % k)) % k;
- n = n / 8 - 1;
-
- appendix = state->appendix;
+ off = (state->message_size / 8) % state->chunk_size;
if (msglen) {
- j = 7 - msglen;
- *appendix = *message;
- *appendix |= (char)(1 << j);
- *appendix &= (char)~((1 << j) - 1);
+ state->chunk[off] = *message;
+ state->chunk[off] |= (char)(1 << (7 - msglen));
+ state->chunk[off] &= (char)~((1 << (7 - msglen)) - 1);
+ state->message_size += msglen;
} else {
- *appendix = (char)128;
+ state->chunk[off] = 0x80;
}
+ off += 1;
- k = state->message_size + msglen;
- i = state->chunk_size / 8;
- appendix += n + i - 1;
- for (i = i < sizeof(size_t) ? i : sizeof(size_t); i--;)
- *(appendix - i) = (char)((k >> (i * 8)) & 255);
+ if (off > state->chunk_size - 8 * (1 + (state->algorithm > LIBSHA2_256))) {
+ memset(state->chunk + off, 0, state->chunk_size - off);
+ off = 0;
+ libsha2_process(state, state->chunk);
+ }
- n += state->chunk_size;
- libsha2_update(state, state->appendix, n);
+ memset(state->chunk + off, 0, state->chunk_size - 8 - off);
+ state->chunk[state->chunk_size - 8] = (char)(state->message_size >> 56);
+ state->chunk[state->chunk_size - 7] = (char)(state->message_size >> 48);
+ state->chunk[state->chunk_size - 6] = (char)(state->message_size >> 40);
+ state->chunk[state->chunk_size - 5] = (char)(state->message_size >> 32);
+ state->chunk[state->chunk_size - 4] = (char)(state->message_size >> 24);
+ state->chunk[state->chunk_size - 3] = (char)(state->message_size >> 16);
+ state->chunk[state->chunk_size - 2] = (char)(state->message_size >> 8);
+ state->chunk[state->chunk_size - 1] = (char)(state->message_size >> 0);
+ libsha2_process(state, state->chunk);
n = libsha2_algorithm_output_size(state->algorithm);
if (state->algorithm <= LIBSHA2_256) {
- for (i = 0; i < 8; i++)
- for (j = 0; j < (state->chunk_size / 16); j++)
- if (k = (i + 1) * (state->chunk_size / 16) - j - 1, k < n)
- output[k] = (char)((state->h.b32[i] >> (8 * j)) & 255);
+ for (i = 0, n /= 4; i < n; i++) {
+ output[4 * i + 0] = (char)(state->h.b32[i] >> 24);
+ output[4 * i + 1] = (char)(state->h.b32[i] >> 16);
+ output[4 * i + 2] = (char)(state->h.b32[i] >> 8);
+ output[4 * i + 3] = (char)(state->h.b32[i] >> 0);
+ }
} else {
- for (i = 0; i < 8; i++)
- for (j = 0; j < (state->chunk_size / 16); j++)
- if (k = (i + 1) * (state->chunk_size / 16) - j - 1, k < n)
- output[k] = (char)((state->h.b64[i] >> (8 * j)) & 255);
+ for (i = 0, n = (n + 7) / 8; i < n; i++) {
+ output[8 * i + 0] = (char)(state->h.b64[i] >> 56);
+ output[8 * i + 1] = (char)(state->h.b64[i] >> 48);
+ output[8 * i + 2] = (char)(state->h.b64[i] >> 40);
+ output[8 * i + 3] = (char)(state->h.b64[i] >> 32);
+ output[8 * i + 4] = (char)(state->h.b64[i] >> 24);
+ output[8 * i + 5] = (char)(state->h.b64[i] >> 16);
+ output[8 * i + 6] = (char)(state->h.b64[i] >> 8);
+ output[8 * i + 7] = (char)(state->h.b64[i] >> 0);
+ }
}
}
diff --git a/init.c b/init.c
index 34eadb7..1d7f80b 100644
--- a/init.c
+++ b/init.c
@@ -103,7 +103,8 @@ libsha2_init(struct libsha2_state *restrict state, enum libsha2_algorithm algori
case LIBSHA2_512_224: memcpy(state->h.b64, H_512_224, sizeof(H_512_224)); break;
case LIBSHA2_512_256: memcpy(state->h.b64, H_512_256, sizeof(H_512_256)); break;
default:
- return errno = EINVAL, -1;
+ errno = EINVAL;
+ return -1;
}
/* Set round constants, and chunk size. */
diff --git a/libsha2.h b/libsha2.h
index 801c6be..e410271 100644
--- a/libsha2.h
+++ b/libsha2.h
@@ -49,12 +49,6 @@ enum libsha2_algorithm {
* exposing two versions of each function: one to wipe data,
* and one not to wipe data to gain speed, now you can use use
* `explicit_bzero` (or `memset`) when you are done.
- *
- * This data structure is flat (it contains dynamic pointers)
- * and can be marshalled and unmarshalled naïvely, and does
- * not need destroyed; however, if you when to marshall it
- * using as little memory as possible, this are comments
- * about data that does not need to be mashalled
*/
struct libsha2_state {
/**
@@ -133,14 +127,6 @@ struct libsha2_state {
unsigned char chunk[128];
/**
- * Space for storing the last bits and
- * the padding
- *
- * Does not need to be marshalled
- */
- char appendix[256];
-
- /**
* The size of the chunks, in bytes
*/
size_t chunk_size;
diff --git a/libsha2_algorithm_output_size.3 b/libsha2_algorithm_output_size.3
index 49fd598..707c0d8 100644
--- a/libsha2_algorithm_output_size.3
+++ b/libsha2_algorithm_output_size.3
@@ -46,6 +46,8 @@ None.
.SH NOTES
None.
.SH BUGS
-None.
+Both GCC and Clang optimises out setting
+.I errno
+if using too high optimisation.
.SH SEE ALSO
.BR libsha2_state_output_size (3)
diff --git a/marshal.c b/marshal.c
index 8265c38..75a8749 100644
--- a/marshal.c
+++ b/marshal.c
@@ -47,11 +47,11 @@ libsha2_marshal(const struct libsha2_state *restrict state, char *restrict buf)
}
if (buf)
- memcpy(&buf[off], state->chunk, sizeof(state->chunk));
- off += sizeof(state->chunk);
- if (buf)
*(size_t *)&buf[off] = state->chunk_size;
off += sizeof(size_t);
+ if (buf)
+ memcpy(&buf[off], state->chunk, state->chunk_size);
+ off += state->chunk_size;
return off;
}
diff --git a/process.c b/process.c
new file mode 100644
index 0000000..52540e0
--- /dev/null
+++ b/process.c
@@ -0,0 +1,96 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+/**
+ * Unified implementation (what can unified without performance impact)
+ * of the chunk processing for all SHA-2 functions
+ *
+ * @param chunk The data to process
+ * @param A Wordsize-dependent constant, take a look at the code
+ * @param B Wordsize-dependent constant, take a look at the code
+ * @param C Wordsize-dependent constant, take a look at the code
+ * @param D Wordsize-dependent constant, take a look at the code
+ * @param E Wordsize-dependent constant, take a look at the code
+ * @param F Wordsize-dependent constant, take a look at the code
+ * @param G Wordsize-dependent constant, take a look at the code
+ * @param H Wordsize-dependent constant, take a look at the code
+ * @param I Wordsize-dependent constant, take a look at the code
+ * @param J Wordsize-dependent constant, take a look at the code
+ * @param K Wordsize-dependent constant, take a look at the code
+ * @param L Wordsize-dependent constant, take a look at the code
+ * @param WORD_T `__typeof()` on any wordsize-dependent variable, with exact size
+ * @param k Round constants
+ * @param w Words
+ * @param h Hash values
+ * @param work_h Space for temporary hash values
+ */
+#define SHA2_IMPLEMENTATION(chunk, A, B, C, D, E, F, G, H, I, J, K, L, WORD_T, k, w, h, work_h)\
+ memcpy(work_h, h, sizeof(work_h));\
+ \
+ memset(w, 0, 16 * sizeof(*(w)));\
+ for (i = 0; i < 16; i++)\
+ for (j = 0; j < sizeof(WORD_T); j++)\
+ w[i] |= ((WORD_T)(chunk[(i + 1) * sizeof(WORD_T) - j - 1])) << (j << 3);\
+ \
+ for (i = 16; i < sizeof(k) / sizeof(*(k)); i++) {\
+ w[i] = w[i - 16] + w[i - 7];\
+ w[i] += ROTR(w[i - 15], A) ^ ROTR(w[i - 15], B) ^ (w[i - 15] >> (C));\
+ w[i] += ROTR(w[i - 2], D) ^ ROTR(w[i - 2], E) ^ (w[i - 2] >> (F));\
+ }\
+ \
+ for (i = 0; i < sizeof(k) / sizeof(*(k)); i++) {\
+ s1 = work_h[6] ^ (work_h[4] & (work_h[5] ^ work_h[6]));\
+ s1 += work_h[7] + k[i] + w[i];\
+ s0 = (work_h[0] & work_h[1]) | (work_h[2] & (work_h[0] | work_h[1]));\
+ s1 += ROTR(work_h[4], G) ^ ROTR(work_h[4], H) ^ ROTR(work_h[4], I);\
+ s0 += ROTR(work_h[0], J) ^ ROTR(work_h[0], K) ^ ROTR(work_h[0], L);\
+ \
+ memmove(work_h + 1, work_h, 7 * sizeof(*(work_h)));\
+ work_h[4] += s1;\
+ work_h[0] = s1 + s0;\
+ }\
+ \
+ for (i = 0; i < 8; i++)\
+ h[i] += work_h[i]
+
+
+/**
+ * Process a chunk using SHA-2
+ *
+ * @param state The hashing state
+ * @param chunk The data to process
+ */
+void
+libsha2_process(struct libsha2_state *restrict state, const unsigned char *restrict chunk)
+{
+ if (state->algorithm <= LIBSHA2_256) {
+ uint32_t s0, s1;
+ size_t i, j;
+
+#if defined(__GNUC__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wmemset-elt-size"
+#endif
+#define ROTR(X, N) (((X) >> (N)) | ((X) << ((sizeof(uint32_t) * 8) - (N))))
+
+ SHA2_IMPLEMENTATION(chunk, 7, 18, 3, 17, 19, 10, 6, 11, 25, 2, 13, 22, uint32_t,
+ state->k.b32, state->w.b32, state->h.b32, state->work_h.b32);
+
+#undef ROTR
+#if defined(__GNUC__)
+# pragma GCC diagnostic pop
+#endif
+
+ } else {
+ uint64_t s0, s1;
+ size_t i, j;
+
+#define ROTR(X, N) (((X) >> (N)) | ((X) << ((sizeof(uint64_t) * 8) - (N))))
+
+ SHA2_IMPLEMENTATION(chunk, 1, 8, 7, 19, 61, 6, 14, 18, 41, 28, 34, 39, uint64_t,
+ state->k.b64, state->w.b64, state->h.b64, state->work_h.b64);
+
+#undef ROTR
+ }
+}
diff --git a/test.c b/test.c
new file mode 100644
index 0000000..9977af7
--- /dev/null
+++ b/test.c
@@ -0,0 +1,121 @@
+/* See LICENSE file for copyright and license details. */
+#include "libsha2.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define test(EXPR)\
+ do {\
+ if (EXPR)\
+ break;\
+ fprintf(stderr, "Failure at line %i: %s\n", __LINE__, #EXPR);\
+ exit(1);\
+ } while (0)
+
+#define test_str(HAVE, EXPECTED)\
+ do {\
+ if (!strcmp(HAVE, EXPECTED))\
+ break;\
+ fprintf(stderr, "Failure at line %i: expected \"%s\", got \"%s\"\n", __LINE__, EXPECTED, HAVE);\
+ exit(1);\
+ } while (0)
+
+
+int
+main(void)
+{
+ char buf[1024], str[1024];
+ struct libsha2_state s;
+
+ libsha2_behex_lower(buf, "", 0);
+ test_str(buf, "");
+
+ libsha2_behex_lower(buf, "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF", 16);
+ test_str(buf, "00112233445566778899aabbccddeeff");
+
+ libsha2_behex_lower(buf, "\x1E\x5A\xC0", 3);
+ test_str(buf, "1e5ac0");
+
+ libsha2_behex_upper(buf, "", 0);
+ test_str(buf, "");
+
+ libsha2_behex_upper(buf, "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF", 16);
+ test_str(buf, "00112233445566778899AABBCCDDEEFF");
+
+ libsha2_behex_upper(buf, "\x1E\x5A\xC0", 3);
+ test_str(buf, "1E5AC0");
+
+ libsha2_unhex(buf, "");
+ test(!memcmp(buf, "", 0));
+
+ libsha2_unhex(buf, "00112233445566778899AABBCCDDEEFF");
+ test(!memcmp(buf, "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF", 16));
+
+ libsha2_unhex(buf, "1E5AC0");
+ test(!memcmp(buf, "\x1E\x5A\xC0", 3));
+
+ libsha2_unhex(buf, "00112233445566778899aabbccddeeff");
+ test(!memcmp(buf, "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF", 16));
+
+ libsha2_unhex(buf, "1e5ac0");
+ test(!memcmp(buf, "\x1E\x5A\xC0", 3));
+
+ libsha2_unhex(buf, "AAbbCcdD");
+ test(!memcmp(buf, "\xAA\xBB\xCC\xDD", 4));
+
+ test(libsha2_algorithm_output_size(LIBSHA2_224) == 28);
+ test(libsha2_algorithm_output_size(LIBSHA2_256) == 32);
+ test(libsha2_algorithm_output_size(LIBSHA2_384) == 48);
+ test(libsha2_algorithm_output_size(LIBSHA2_512) == 64);
+ test(libsha2_algorithm_output_size(LIBSHA2_512_224) == 28);
+ test(libsha2_algorithm_output_size(LIBSHA2_512_256) == 32);
+ test(!errno);
+ test(libsha2_algorithm_output_size(~0) == 0); /* should test `errno == EINVAL`, optimising compiler breaks it */
+
+ errno = 0;
+ test(libsha2_init(&s, ~0) == -1 && errno == EINVAL);
+ errno = 0;
+
+ test(!libsha2_init(&s, LIBSHA2_224));
+ test(libsha2_state_output_size(&s) == 28);
+ libsha2_digest(&s, "", 0, buf);
+ libsha2_behex_lower(str, buf, libsha2_state_output_size(&s));
+ test_str(str, "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f");
+
+ test(!libsha2_init(&s, LIBSHA2_256));
+ test(libsha2_state_output_size(&s) == 32);
+ libsha2_digest(&s, "", 0, buf);
+ libsha2_behex_lower(str, buf, libsha2_state_output_size(&s));
+ test_str(str, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
+
+ test(!libsha2_init(&s, LIBSHA2_384));
+ test(libsha2_state_output_size(&s) == 48);
+ libsha2_digest(&s, "", 0, buf);
+ libsha2_behex_lower(str, buf, libsha2_state_output_size(&s));
+ test_str(str, "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b");
+
+ test(!libsha2_init(&s, LIBSHA2_512));
+ test(libsha2_state_output_size(&s) == 64);
+ libsha2_digest(&s, "", 0, buf);
+ libsha2_behex_lower(str, buf, libsha2_state_output_size(&s));
+ test_str(str, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e");
+
+ test(!libsha2_init(&s, LIBSHA2_512_224));
+ test(libsha2_state_output_size(&s) == 28);
+ libsha2_digest(&s, "", 0, buf);
+ libsha2_behex_lower(str, buf, libsha2_state_output_size(&s));
+ test_str(str, "6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4");
+
+ test(!libsha2_init(&s, LIBSHA2_512_256));
+ test(libsha2_state_output_size(&s) == 32);
+ libsha2_digest(&s, "", 0, buf);
+ libsha2_behex_lower(str, buf, libsha2_state_output_size(&s));
+ test_str(str, "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a");
+
+ test(!errno);
+
+ return 0;
+}
diff --git a/unmarshal.c b/unmarshal.c
index 13a97ff..315d556 100644
--- a/unmarshal.c
+++ b/unmarshal.c
@@ -67,14 +67,19 @@ libsha2_unmarshal(struct libsha2_state *restrict state, const char *restrict buf
return 0;
}
- if (bufsize - off < sizeof(state->chunk) + sizeof(size_t)) {
+ if (bufsize - off < sizeof(size_t)) {
errno = EINVAL;
return 0;
}
- memcpy(state->chunk, &buf[off], sizeof(state->chunk));
- off += sizeof(state->chunk);
state->chunk_size = *(const size_t *)&buf[off];
off += sizeof(size_t);
+ if (bufsize - off < state->chunk_size) {
+ errno = EINVAL;
+ return 0;
+ }
+ memcpy(state->chunk, &buf[off], state->chunk_size);
+ off += state->chunk_size;
+
return off;
}
diff --git a/update.c b/update.c
index 3263b62..b0eff29 100644
--- a/update.c
+++ b/update.c
@@ -3,105 +3,6 @@
/**
- * Unified implementation (what can unified without performance impact)
- * of the chunk processing for all SHA-2 functions
- *
- * @param A Wordsize-dependent constant, take a look at the code
- * @param B Wordsize-dependent constant, take a look at the code
- * @param C Wordsize-dependent constant, take a look at the code
- * @param D Wordsize-dependent constant, take a look at the code
- * @param E Wordsize-dependent constant, take a look at the code
- * @param F Wordsize-dependent constant, take a look at the code
- * @param G Wordsize-dependent constant, take a look at the code
- * @param H Wordsize-dependent constant, take a look at the code
- * @param I Wordsize-dependent constant, take a look at the code
- * @param J Wordsize-dependent constant, take a look at the code
- * @param K Wordsize-dependent constant, take a look at the code
- * @param L Wordsize-dependent constant, take a look at the code
- * @param WORD_T `__typeof()` on any wordsize-dependent variable, with exact size
- * @param k Round constants
- * @param w Words
- * @param h Hash values
- * @param work_h Space for temporary hash values
- */
-#define SHA2_IMPLEMENTATION(A, B, C, D, E, F, G, H, I, J, K, L, WORD_T, k, w, h, work_h)\
- memcpy(work_h, h, sizeof(work_h));\
- \
- memset(w, 0, 16 * sizeof(*(w)));\
- for (i = 0; i < 16; i++)\
- for (j = 0; j < sizeof(WORD_T); j++)\
- w[i] |= ((WORD_T)(state->chunk[(i + 1) * sizeof(WORD_T) - j - 1])) << (j << 3);\
- \
- for (i = 16; i < sizeof(k) / sizeof(*(k)); i++) {\
- w[i] = w[i - 16] + w[i - 7];\
- w[i] += ROTR(w[i - 15], A) ^ ROTR(w[i - 15], B) ^ (w[i - 15] >> (C));\
- w[i] += ROTR(w[i - 2], D) ^ ROTR(w[i - 2], E) ^ (w[i - 2] >> (F));\
- }\
- \
- for (i = 0; i < sizeof(k) / sizeof(*(k)); i++) {\
- s1 = (work_h[4] & work_h[5]) ^ (work_h[6] & ~(work_h[4]));\
- s1 += work_h[7] + k[i] + w[i];\
- s0 = (work_h[0] & work_h[1]) ^ (work_h[0] & work_h[2]) ^ (work_h[1] & work_h[2]);\
- s1 += ROTR(work_h[4], G) ^ ROTR(work_h[4], H) ^ ROTR(work_h[4], I);\
- s0 += ROTR(work_h[0], J) ^ ROTR(work_h[0], K) ^ ROTR(work_h[0], L);\
- \
- memmove(work_h + 1, work_h, 7 * sizeof(*(work_h)));\
- work_h[4] += s1;\
- work_h[0] = s1 + s0;\
- }\
- \
- for (i = 0; i < 8; i++)\
- h[i] += work_h[i]
-
-
-/**
- * Process a chunk using SHA-256
- *
- * @param state The hashing state
- */
-#if defined(__GNUC__)
-__attribute__((__nonnull__, __nothrow__))
-#endif
-static void
-process256(struct libsha2_state *restrict state)
-{
- uint32_t s0, s1;
- size_t i, j;
-#if defined(__GNUC__)
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wmemset-elt-size"
-#endif
-#define ROTR(X, N) (((X) >> (N)) | ((X) << ((sizeof(uint32_t) * 8) - (N))))
- SHA2_IMPLEMENTATION(7, 18, 3, 17, 19, 10, 6, 11, 25, 2, 13, 22, uint32_t,
- state->k.b32, state->w.b32, state->h.b32, state->work_h.b32);
-#undef ROTR
-#if defined(__GNUC__)
-# pragma GCC diagnostic pop
-#endif
-}
-
-
-/**
- * Process a chunk using SHA-512
- *
- * @param state The hashing state
- */
-#if defined(__GNUC__)
-__attribute__((__nonnull__, __nothrow__))
-#endif
-static void
-process512(struct libsha2_state *restrict state)
-{
- uint64_t s0, s1;
- size_t i, j;
-#define ROTR(X, N) (((X) >> (N)) | ((X) << ((sizeof(uint64_t) * 8) - (N))))
- SHA2_IMPLEMENTATION(1, 8, 7, 19, 61, 6, 14, 18, 41, 28, 34, 39, uint64_t,
- state->k.b64, state->w.b64, state->h.b64, state->work_h.b64);
-#undef ROTR
-}
-
-
-/**
* Absorb more of the message
*
* @param state The hashing state
@@ -109,7 +10,7 @@ process512(struct libsha2_state *restrict state)
* @param msglen The length of the message
*/
void
-libsha2_update(struct libsha2_state *restrict state, const char *restrict message, size_t msglen)
+libsha2_update(struct libsha2_state *restrict state, const char *restrict message, size_t msglen) /* TODO avoid coping */
{
size_t n, off, mlen;
@@ -121,12 +22,8 @@ libsha2_update(struct libsha2_state *restrict state, const char *restrict messag
n = state->chunk_size - off;
n = n < msglen ? n : msglen;
memcpy(state->chunk + off, message, n);
- if (off + n == state->chunk_size) {
- if (state->algorithm <= LIBSHA2_256)
- process256(state);
- else
- process512(state);
- }
+ if (off + n == state->chunk_size)
+ libsha2_process(state, state->chunk);
message += n, mlen += n, msglen -= n;
}