aboutsummaryrefslogtreecommitdiffstats
path: root/libkeccak_generalised_sum_fd.c
diff options
context:
space:
mode:
Diffstat (limited to 'libkeccak_generalised_sum_fd.c')
-rw-r--r--libkeccak_generalised_sum_fd.c37
1 files changed, 32 insertions, 5 deletions
diff --git a/libkeccak_generalised_sum_fd.c b/libkeccak_generalised_sum_fd.c
index bc81451..78890b4 100644
--- a/libkeccak_generalised_sum_fd.c
+++ b/libkeccak_generalised_sum_fd.c
@@ -19,11 +19,16 @@ libkeccak_generalised_sum_fd(int fd, struct libkeccak_state *restrict state, con
const char *restrict suffix, void *restrict hashsum)
{
ssize_t got;
+ size_t offset;
#ifndef _WIN32
struct stat attr;
#endif
size_t blksize = 4096;
- void *restrict chunk;
+ unsigned char *restrict chunk;
+ size_t chunksize = libkeccak_zerocopy_chunksize(state);
+ size_t extrasize = (strlen(suffix) + 2 + 7) >> 3;
+ size_t extrachunks = (extrasize + (chunksize - 1)) / chunksize;
+ size_t chunks, chunkmod;
if (libkeccak_state_initialise(state, spec) < 0)
return -1;
@@ -34,6 +39,16 @@ libkeccak_generalised_sum_fd(int fd, struct libkeccak_state *restrict state, con
blksize = (size_t)attr.st_blksize;
#endif
+ chunks = blksize / chunksize;
+ chunkmod = blksize % chunksize;
+ if (chunkmod) {
+ blksize -= chunkmod;
+ blksize += chunksize;
+ chunks += 1;
+ }
+ if (chunks < extrachunks + 1)
+ blksize = (extrachunks + 1) * chunksize;
+
#if ALLOCA_LIMIT > 0
if (blksize > (size_t)ALLOCA_LIMIT)
blksize = (size_t)ALLOCA_LIMIT;
@@ -53,8 +68,9 @@ libkeccak_generalised_sum_fd(int fd, struct libkeccak_state *restrict state, con
return -1;
#endif
+ offset = 0;
for (;;) {
- got = read(fd, chunk, blksize);
+ got = read(fd, &chunk[offset], blksize - offset);
if (got <= 0) {
if (!got)
break;
@@ -62,11 +78,22 @@ libkeccak_generalised_sum_fd(int fd, struct libkeccak_state *restrict state, con
continue;
goto fail;
}
- if (libkeccak_fast_update(state, chunk, (size_t)got) < 0)
- goto fail;
+ offset += (size_t)got;
+ if (offset == blksize) {
+ libkeccak_zerocopy_update(state, chunk, blksize);
+ offset = 0;
+ }
+ }
+
+ if (extrasize > blksize - offset) {
+ chunkmod = offset % chunksize;
+ libkeccak_zerocopy_update(state, chunk, offset - chunkmod);
+ __builtin_memcpy(chunk, &chunk[offset - chunkmod], chunkmod * sizeof(char));
+ offset = chunkmod;
}
- return libkeccak_fast_digest(state, NULL, 0, 0, suffix, hashsum);
+ libkeccak_zerocopy_digest(state, chunk, offset, 0, suffix, hashsum);
+ return 0;
fail:
#if ALLOCA_LIMIT <= 0