diff options
-rw-r--r-- | .gitignore | 12 | ||||
-rw-r--r-- | Makefile | 11 | ||||
-rw-r--r-- | algorithm_output_size.c | 1 | ||||
-rw-r--r-- | common.h | 12 | ||||
-rw-r--r-- | digest.c | 67 | ||||
-rw-r--r-- | init.c | 3 | ||||
-rw-r--r-- | libsha2.h | 14 | ||||
-rw-r--r-- | libsha2_algorithm_output_size.3 | 4 | ||||
-rw-r--r-- | marshal.c | 6 | ||||
-rw-r--r-- | process.c | 96 | ||||
-rw-r--r-- | test.c | 121 | ||||
-rw-r--r-- | unmarshal.c | 11 | ||||
-rw-r--r-- | update.c | 109 |
13 files changed, 299 insertions, 168 deletions
@@ -1,7 +1,4 @@ -_/ -\#*\# -.* -!.git* +*\#* *~ *.bak *.swp @@ -11,10 +8,5 @@ _/ *.so *.su *.a -*.gch -*.info -*.pdf -*.ps -*.dvi -*.test *.lo +/test @@ -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> /** @@ -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); @@ -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); + } } } @@ -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. */ @@ -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) @@ -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 + } +} @@ -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; } @@ -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; } |