summaryrefslogtreecommitdiff
path: root/lib/sha512.c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-01-20 10:55:18 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-01-20 10:55:18 +0000
commit70e9163c9c18e995515598085cb824e554eb7ae7 (patch)
treea42dc8b2a6c031354bf31472de888bfc8a060132 /lib/sha512.c
parentcbf5993c43f49281173f185863577d86bfac6eae (diff)
downloadcoreutils-tarball-master.tar.gz
Diffstat (limited to 'lib/sha512.c')
-rw-r--r--lib/sha512.c306
1 files changed, 169 insertions, 137 deletions
diff --git a/lib/sha512.c b/lib/sha512.c
index e24c6f5..5494dcb 100644
--- a/lib/sha512.c
+++ b/lib/sha512.c
@@ -1,12 +1,12 @@
/* sha512.c - Functions to compute SHA512 and SHA384 message digest of files or
memory blocks according to the NIST specification FIPS-180-2.
- Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2005-2006, 2008-2016 Free Software Foundation, Inc.
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -14,8 +14,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Written by David Madore, considerably copypasting from
Scott G. Miller's sha1.c
@@ -23,9 +22,14 @@
#include <config.h>
+#if HAVE_OPENSSL_SHA512
+# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE
+#endif
#include "sha512.h"
-#include <stddef.h>
+#include <stdalign.h>
+#include <stdint.h>
+#include <stdlib.h>
#include <string.h>
#if USE_UNLOCKED_IO
@@ -36,21 +40,22 @@
# define SWAP(n) (n)
#else
# define SWAP(n) \
- u64or (u64or (u64or (u64shl (n, 56), \
- u64shl (u64and (n, u64lo (0x0000ff00)), 40)), \
- u64or (u64shl (u64and (n, u64lo (0x00ff0000)), 24), \
- u64shl (u64and (n, u64lo (0xff000000)), 8))), \
- u64or (u64or (u64and (u64shr (n, 8), u64lo (0xff000000)), \
- u64and (u64shr (n, 24), u64lo (0x00ff0000))), \
- u64or (u64and (u64shr (n, 40), u64lo (0x0000ff00)), \
- u64shr (n, 56))))
+ u64or (u64or (u64or (u64shl (n, 56), \
+ u64shl (u64and (n, u64lo (0x0000ff00)), 40)), \
+ u64or (u64shl (u64and (n, u64lo (0x00ff0000)), 24), \
+ u64shl (u64and (n, u64lo (0xff000000)), 8))), \
+ u64or (u64or (u64and (u64shr (n, 8), u64lo (0xff000000)), \
+ u64and (u64shr (n, 24), u64lo (0x00ff0000))), \
+ u64or (u64and (u64shr (n, 40), u64lo (0x0000ff00)), \
+ u64shr (n, 56))))
#endif
-#define BLOCKSIZE 4096
+#define BLOCKSIZE 32768
#if BLOCKSIZE % 128 != 0
# error "invalid BLOCKSIZE"
#endif
+#if ! HAVE_OPENSSL_SHA512
/* This array contains the bytes used to pad the buffer to the next
128-byte boundary. */
static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ... */ };
@@ -58,7 +63,7 @@ static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ... */ };
/*
Takes a pointer to a 512 bit block of data (eight 64 bit ints) and
- intializes it to the start constants of the SHA512 algorithm. This
+ initializes it to the start constants of the SHA512 algorithm. This
must be called before using hash in the call to sha512_hash
*/
void
@@ -93,18 +98,25 @@ sha384_init_ctx (struct sha512_ctx *ctx)
ctx->buflen = 0;
}
-/* Put result from CTX in first 64 bytes following RESBUF. The result
- must be in little endian byte order.
+/* 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_uint64 (char *cp, u64 v)
+{
+ memcpy (cp, &v, sizeof v);
+}
- IMPORTANT: On some systems it is required that RESBUF is correctly
- aligned for a 64-bit value. */
+/* Put result from CTX in first 64 bytes following RESBUF.
+ The result must be in little endian byte order. */
void *
sha512_read_ctx (const struct sha512_ctx *ctx, void *resbuf)
{
int i;
+ char *r = resbuf;
for (i = 0; i < 8; i++)
- ((u64 *) resbuf)[i] = SWAP (ctx->state[i]);
+ set_uint64 (r + i * sizeof ctx->state[0], SWAP (ctx->state[i]));
return resbuf;
}
@@ -113,18 +125,16 @@ void *
sha384_read_ctx (const struct sha512_ctx *ctx, void *resbuf)
{
int i;
+ char *r = resbuf;
for (i = 0; i < 6; i++)
- ((u64 *) resbuf)[i] = SWAP (ctx->state[i]);
+ set_uint64 (r + i * sizeof ctx->state[0], SWAP (ctx->state[i]));
return resbuf;
}
/* Process the remaining bytes in the internal buffer and the usual
- prolog according to the standard and write the result to RESBUF.
-
- IMPORTANT: On some systems it is required that RESBUF is correctly
- aligned for a 64-bit value. */
+ prolog according to the standard and write the result to RESBUF. */
static void
sha512_conclude_ctx (struct sha512_ctx *ctx)
{
@@ -137,10 +147,14 @@ sha512_conclude_ctx (struct sha512_ctx *ctx)
if (u64lt (ctx->total[0], u64lo (bytes)))
ctx->total[1] = u64plus (ctx->total[1], u64lo (1));
- /* Put the 64-bit file length in *bits* at the end of the buffer. */
- ctx->buffer[size - 2] = SWAP (u64or (u64shl (ctx->total[1], 3),
- u64shr (ctx->total[0], 61)));
- ctx->buffer[size - 1] = SWAP (u64shl (ctx->total[0], 3));
+ /* Put the 128-bit file length in *bits* at the end of the buffer.
+ Use set_uint64 rather than a simple assignment, to avoid risk of
+ unaligned access. */
+ set_uint64 ((char *) &ctx->buffer[size - 2],
+ SWAP (u64or (u64shl (ctx->total[1], 3),
+ u64shr (ctx->total[0], 61))));
+ set_uint64 ((char *) &ctx->buffer[size - 1],
+ SWAP (u64shl (ctx->total[0], 3)));
memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 8 - bytes);
@@ -161,6 +175,7 @@ sha384_finish_ctx (struct sha512_ctx *ctx, void *resbuf)
sha512_conclude_ctx (ctx);
return sha384_read_ctx (ctx, resbuf);
}
+#endif
/* Compute SHA512 message digest for bytes read from STREAM. The
resulting message digest number will be written into the 64 bytes
@@ -169,9 +184,12 @@ int
sha512_stream (FILE *stream, void *resblock)
{
struct sha512_ctx ctx;
- char buffer[BLOCKSIZE + 72];
size_t sum;
+ char *buffer = malloc (BLOCKSIZE + 72);
+ if (!buffer)
+ return 1;
+
/* Initialize the computation context. */
sha512_init_ctx (&ctx);
@@ -179,40 +197,43 @@ sha512_stream (FILE *stream, void *resblock)
while (1)
{
/* We read the file in blocks of BLOCKSIZE bytes. One call of the
- computation function processes the whole buffer so that with the
- next round of the loop another block can be read. */
+ computation function processes the whole buffer so that with the
+ next round of the loop another block can be read. */
size_t n;
sum = 0;
/* Read block. Take care for partial reads. */
while (1)
- {
- n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
-
- sum += n;
-
- if (sum == BLOCKSIZE)
- break;
-
- if (n == 0)
- {
- /* Check for the error flag IFF N == 0, so that we don't
- exit the loop after a partial read due to e.g., EAGAIN
- or EWOULDBLOCK. */
- if (ferror (stream))
- return 1;
- goto process_partial_block;
- }
-
- /* We've read at least one byte, so ignore errors. But always
- check for EOF, since feof may be true even though N > 0.
- Otherwise, we could end up calling fread after EOF. */
- if (feof (stream))
- goto process_partial_block;
- }
+ {
+ n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+ sum += n;
+
+ if (sum == BLOCKSIZE)
+ break;
+
+ if (n == 0)
+ {
+ /* Check for the error flag IFF N == 0, so that we don't
+ exit the loop after a partial read due to e.g., EAGAIN
+ or EWOULDBLOCK. */
+ if (ferror (stream))
+ {
+ free (buffer);
+ return 1;
+ }
+ goto process_partial_block;
+ }
+
+ /* We've read at least one byte, so ignore errors. But always
+ check for EOF, since feof may be true even though N > 0.
+ Otherwise, we could end up calling fread after EOF. */
+ if (feof (stream))
+ goto process_partial_block;
+ }
/* Process buffer with BLOCKSIZE bytes. Note that
- BLOCKSIZE % 128 == 0
+ BLOCKSIZE % 128 == 0
*/
sha512_process_block (buffer, BLOCKSIZE, &ctx);
}
@@ -225,6 +246,7 @@ sha512_stream (FILE *stream, void *resblock)
/* Construct result in desired memory. */
sha512_finish_ctx (&ctx, resblock);
+ free (buffer);
return 0;
}
@@ -233,9 +255,12 @@ int
sha384_stream (FILE *stream, void *resblock)
{
struct sha512_ctx ctx;
- char buffer[BLOCKSIZE + 72];
size_t sum;
+ char *buffer = malloc (BLOCKSIZE + 72);
+ if (!buffer)
+ return 1;
+
/* Initialize the computation context. */
sha384_init_ctx (&ctx);
@@ -243,40 +268,43 @@ sha384_stream (FILE *stream, void *resblock)
while (1)
{
/* We read the file in blocks of BLOCKSIZE bytes. One call of the
- computation function processes the whole buffer so that with the
- next round of the loop another block can be read. */
+ computation function processes the whole buffer so that with the
+ next round of the loop another block can be read. */
size_t n;
sum = 0;
/* Read block. Take care for partial reads. */
while (1)
- {
- n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
-
- sum += n;
-
- if (sum == BLOCKSIZE)
- break;
-
- if (n == 0)
- {
- /* Check for the error flag IFF N == 0, so that we don't
- exit the loop after a partial read due to e.g., EAGAIN
- or EWOULDBLOCK. */
- if (ferror (stream))
- return 1;
- goto process_partial_block;
- }
-
- /* We've read at least one byte, so ignore errors. But always
- check for EOF, since feof may be true even though N > 0.
- Otherwise, we could end up calling fread after EOF. */
- if (feof (stream))
- goto process_partial_block;
- }
+ {
+ n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+ sum += n;
+
+ if (sum == BLOCKSIZE)
+ break;
+
+ if (n == 0)
+ {
+ /* Check for the error flag IFF N == 0, so that we don't
+ exit the loop after a partial read due to e.g., EAGAIN
+ or EWOULDBLOCK. */
+ if (ferror (stream))
+ {
+ free (buffer);
+ return 1;
+ }
+ goto process_partial_block;
+ }
+
+ /* We've read at least one byte, so ignore errors. But always
+ check for EOF, since feof may be true even though N > 0.
+ Otherwise, we could end up calling fread after EOF. */
+ if (feof (stream))
+ goto process_partial_block;
+ }
/* Process buffer with BLOCKSIZE bytes. Note that
- BLOCKSIZE % 128 == 0
+ BLOCKSIZE % 128 == 0
*/
sha512_process_block (buffer, BLOCKSIZE, &ctx);
}
@@ -289,9 +317,11 @@ sha384_stream (FILE *stream, void *resblock)
/* Construct result in desired memory. */
sha384_finish_ctx (&ctx, resblock);
+ free (buffer);
return 0;
}
+#if ! HAVE_OPENSSL_SHA512
/* Compute SHA512 message digest for LEN bytes beginning at BUFFER. The
result is always in little endian byte order, so that a byte-wise
output yields to the wanted ASCII representation of the message
@@ -340,15 +370,15 @@ sha512_process_bytes (const void *buffer, size_t len, struct sha512_ctx *ctx)
ctx->buflen += add;
if (ctx->buflen > 128)
- {
- sha512_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
+ {
+ sha512_process_block (ctx->buffer, ctx->buflen & ~127, ctx);
- ctx->buflen &= 127;
- /* The regions in the following copy operation cannot overlap. */
- memcpy (ctx->buffer,
- &((char *) ctx->buffer)[(left_over + add) & ~127],
- ctx->buflen);
- }
+ ctx->buflen &= 127;
+ /* The regions in the following copy operation cannot overlap. */
+ memcpy (ctx->buffer,
+ &((char *) ctx->buffer)[(left_over + add) & ~127],
+ ctx->buflen);
+ }
buffer = (const char *) buffer + add;
len -= add;
@@ -358,22 +388,21 @@ sha512_process_bytes (const void *buffer, size_t len, struct sha512_ctx *ctx)
if (len >= 128)
{
#if !_STRING_ARCH_unaligned
-# define alignof(type) offsetof (struct { char c; type x; }, x)
-# define UNALIGNED_P(p) (((size_t) p) % alignof (u64) != 0)
+# define UNALIGNED_P(p) ((uintptr_t) (p) % alignof (u64) != 0)
if (UNALIGNED_P (buffer))
- while (len > 128)
- {
- sha512_process_block (memcpy (ctx->buffer, buffer, 128), 128, ctx);
- buffer = (const char *) buffer + 128;
- len -= 128;
- }
+ while (len > 128)
+ {
+ sha512_process_block (memcpy (ctx->buffer, buffer, 128), 128, ctx);
+ buffer = (const char *) buffer + 128;
+ len -= 128;
+ }
else
#endif
- {
- sha512_process_block (buffer, len & ~127, ctx);
- buffer = (const char *) buffer + (len & ~127);
- len &= 127;
- }
+ {
+ sha512_process_block (buffer, len & ~127, ctx);
+ buffer = (const char *) buffer + (len & ~127);
+ len &= 127;
+ }
}
/* Move remaining bytes in internal buffer. */
@@ -384,11 +413,11 @@ sha512_process_bytes (const void *buffer, size_t len, struct sha512_ctx *ctx)
memcpy (&((char *) ctx->buffer)[left_over], buffer, len);
left_over += len;
if (left_over >= 128)
- {
- sha512_process_block (ctx->buffer, 128, ctx);
- left_over -= 128;
- memcpy (ctx->buffer, &ctx->buffer[16], left_over);
- }
+ {
+ sha512_process_block (ctx->buffer, 128, ctx);
+ left_over -= 128;
+ memcpy (ctx->buffer, &ctx->buffer[16], left_over);
+ }
ctx->buflen = left_over;
}
}
@@ -462,35 +491,37 @@ sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx)
u64 f = ctx->state[5];
u64 g = ctx->state[6];
u64 h = ctx->state[7];
+ u64 lolen = u64size (len);
/* First increment the byte count. FIPS PUB 180-2 specifies the possible
length of the file up to 2^128 bits. Here we only compute the
number of bytes. Do a double word increment. */
- ctx->total[0] = u64plus (ctx->total[0], u64lo (len));
- if (u64lt (ctx->total[0], u64lo (len)))
- ctx->total[1] = u64plus (ctx->total[1], u64lo (1));
+ ctx->total[0] = u64plus (ctx->total[0], lolen);
+ ctx->total[1] = u64plus (ctx->total[1],
+ u64plus (u64size (len >> 31 >> 31 >> 2),
+ u64lo (u64lt (ctx->total[0], lolen))));
#define S0(x) u64xor (u64rol(x, 63), u64xor (u64rol (x, 56), u64shr (x, 7)))
#define S1(x) u64xor (u64rol (x, 45), u64xor (u64rol (x, 3), u64shr (x, 6)))
#define SS0(x) u64xor (u64rol (x, 36), u64xor (u64rol (x, 30), u64rol (x, 25)))
#define SS1(x) u64xor (u64rol(x, 50), u64xor (u64rol (x, 46), u64rol (x, 23)))
-#define M(I) (x[(I) & 15] \
- = u64plus (x[(I) & 15], \
- u64plus (S1 (x[((I) - 2) & 15]), \
- u64plus (x[((I) - 7) & 15], \
- S0 (x[((I) - 15) & 15])))))
-
-#define R(A, B, C, D, E, F, G, H, K, M) \
- do \
- { \
- u64 t0 = u64plus (SS0 (A), F2 (A, B, C)); \
- u64 t1 = \
- u64plus (H, u64plus (SS1 (E), \
- u64plus (F1 (E, F, G), u64plus (K, M)))); \
- D = u64plus (D, t1); \
- H = u64plus (t0, t1); \
- } \
+#define M(I) (x[(I) & 15] \
+ = u64plus (x[(I) & 15], \
+ u64plus (S1 (x[((I) - 2) & 15]), \
+ u64plus (x[((I) - 7) & 15], \
+ S0 (x[((I) - 15) & 15])))))
+
+#define R(A, B, C, D, E, F, G, H, K, M) \
+ do \
+ { \
+ u64 t0 = u64plus (SS0 (A), F2 (A, B, C)); \
+ u64 t1 = \
+ u64plus (H, u64plus (SS1 (E), \
+ u64plus (F1 (E, F, G), u64plus (K, M)))); \
+ D = u64plus (D, t1); \
+ H = u64plus (t0, t1); \
+ } \
while (0)
while (words < endp)
@@ -498,10 +529,10 @@ sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx)
int t;
/* FIXME: see sha1.c for a better implementation. */
for (t = 0; t < 16; t++)
- {
- x[t] = SWAP (*words);
- words++;
- }
+ {
+ 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] );
@@ -594,3 +625,4 @@ sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx)
h = ctx->state[7] = u64plus (ctx->state[7], h);
}
}
+#endif