[PATCH 1/2] Make SHA-512 use the new _gcry_md_block_write helper
Jussi Kivilinna
jussi.kivilinna at iki.fi
Thu Sep 19 12:09:57 CEST 2013
* cipher/hash-common.c (_gcry_md_block_write): Check that hd->buf is
large enough.
* cipher/hash-common.h (MD_BLOCK_MAX_BLOCKSIZE, MD_NBLOCKS_TYPE): New
macros.
(gcry_md_block_ctx_t): Use above macros for 'nblocks' and 'buf'.
* cipher/sha512.c (SHA512_STATE): New struct.
(SHA512_CONTEXT): Add 'bctx' and 'state'.
(sha512_init, sha384_init): Initialize 'bctx'.
(__transform, _gcry_sha512_transform_armv7_neon): Use SHA512_STATE for
'hd'.
(transform): For now, do not return burn stack.
(sha512_write): Remove.
(sha512_final): Use _gcry_md_block_write and bctx.
(_gcry_digest_spec_sha512, _gcry_digest_spec_sha384): Use
_gcry_md_block_write.
--
Patch changes 'nblocks' counter to 64-bits when SHA-512 is enabled. This does
not cause problems with other algorithms; they are already casting 'nblocks'
to u32 variable in their finalization functions. Also move 'buf' member to
head of 'gcry_md_block_ctx_t' to ensure proper alignment; this is because some
algorithms cast buffer pointer to (u64*) in final endian conversion.
Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
cipher/hash-common.c | 5 +
cipher/hash-common.h | 17 ++++-
cipher/sha512.c | 179 ++++++++++++++++++++++----------------------------
3 files changed, 97 insertions(+), 104 deletions(-)
diff --git a/cipher/hash-common.c b/cipher/hash-common.c
index a823a66..1a6e8e9 100644
--- a/cipher/hash-common.c
+++ b/cipher/hash-common.c
@@ -102,7 +102,10 @@ _gcry_md_block_write (void *context, const void *inbuf_arg, size_t inlen)
const unsigned char *inbuf = inbuf_arg;
gcry_md_block_ctx_t *hd = context;
- if ( hd->buf == NULL || hd->bwrite == NULL)
+ if (sizeof(hd->buf) < hd->blocksize)
+ BUG();
+
+ if (hd->buf == NULL || hd->bwrite == NULL)
return;
if (hd->count == hd->blocksize) /* Flush the buffer. */
diff --git a/cipher/hash-common.h b/cipher/hash-common.h
index 1d1d4ec..4dd5441 100644
--- a/cipher/hash-common.h
+++ b/cipher/hash-common.h
@@ -20,6 +20,8 @@
#ifndef GCRY_HASH_COMMON_H
#define GCRY_HASH_COMMON_H
+#include "types.h"
+
const char * _gcry_hash_selftest_check_one
/**/ (int algo,
@@ -29,11 +31,20 @@ const char * _gcry_hash_selftest_check_one
/* Type for the md_write helper function. */
typedef void (*_gcry_md_block_write_t) (void *c, const unsigned char *buf);
+#if defined(HAVE_U64_TYPEDEF) && defined(USE_SHA512)
+/* SHA-512 needs u64 and larger buffer. */
+# define MD_BLOCK_MAX_BLOCKSIZE 128
+# define MD_NBLOCKS_TYPE u64
+#else
+# define MD_BLOCK_MAX_BLOCKSIZE 64
+# define MD_NBLOCKS_TYPE u32
+#endif
+
typedef struct gcry_md_block_ctx
{
- u32 nblocks;
- int count;
- byte buf[64];
+ byte buf[MD_BLOCK_MAX_BLOCKSIZE];
+ MD_NBLOCKS_TYPE nblocks;
+ int count;
size_t blocksize;
_gcry_md_block_write_t bwrite;
size_t stack_burn;
diff --git a/cipher/sha512.c b/cipher/sha512.c
index fee3e71..ed63ae6 100644
--- a/cipher/sha512.c
+++ b/cipher/sha512.c
@@ -67,18 +67,25 @@
typedef struct
{
u64 h0, h1, h2, h3, h4, h5, h6, h7;
- u64 nblocks;
- byte buf[128];
- int count;
+} SHA512_STATE;
+
+typedef struct
+{
+ gcry_md_block_ctx_t bctx;
+ SHA512_STATE state;
#ifdef USE_ARM_NEON_ASM
int use_neon;
#endif
} SHA512_CONTEXT;
static void
+transform (void *context, const unsigned char *data);
+
+static void
sha512_init (void *context)
{
- SHA512_CONTEXT *hd = context;
+ SHA512_CONTEXT *ctx = context;
+ SHA512_STATE *hd = &ctx->state;
hd->h0 = U64_C(0x6a09e667f3bcc908);
hd->h1 = U64_C(0xbb67ae8584caa73b);
@@ -89,17 +96,22 @@ sha512_init (void *context)
hd->h6 = U64_C(0x1f83d9abfb41bd6b);
hd->h7 = U64_C(0x5be0cd19137e2179);
- hd->nblocks = 0;
- hd->count = 0;
+ ctx->bctx.nblocks = 0;
+ ctx->bctx.count = 0;
+ ctx->bctx.blocksize = 128;
+ ctx->bctx.bwrite = transform;
+ ctx->bctx.stack_burn = 256;
+
#ifdef USE_ARM_NEON_ASM
- hd->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0;
+ ctx->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0;
#endif
}
static void
sha384_init (void *context)
{
- SHA512_CONTEXT *hd = context;
+ SHA512_CONTEXT *ctx = context;
+ SHA512_STATE *hd = &ctx->state;
hd->h0 = U64_C(0xcbbb9d5dc1059ed8);
hd->h1 = U64_C(0x629a292a367cd507);
@@ -110,10 +122,14 @@ sha384_init (void *context)
hd->h6 = U64_C(0xdb0c2e0d64f98fa7);
hd->h7 = U64_C(0x47b5481dbefa4fa4);
- hd->nblocks = 0;
- hd->count = 0;
+ ctx->bctx.nblocks = 0;
+ ctx->bctx.count = 0;
+ ctx->bctx.blocksize = 128;
+ ctx->bctx.bwrite = transform;
+ ctx->bctx.stack_burn = 256;
+
#ifdef USE_ARM_NEON_ASM
- hd->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0;
+ ctx->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0;
#endif
}
@@ -196,7 +212,7 @@ static const u64 k[] =
* Transform the message W which consists of 16 64-bit-words
*/
static void
-__transform (SHA512_CONTEXT *hd, const unsigned char *data)
+__transform (SHA512_STATE *hd, const unsigned char *data)
{
u64 a, b, c, d, e, f, g, h;
u64 w[16];
@@ -477,71 +493,33 @@ __transform (SHA512_CONTEXT *hd, const unsigned char *data)
#ifdef USE_ARM_NEON_ASM
-void _gcry_sha512_transform_armv7_neon (SHA512_CONTEXT *hd,
+void _gcry_sha512_transform_armv7_neon (SHA512_STATE *hd,
const unsigned char *data,
const u64 k[]);
#endif
-static unsigned int
-transform (SHA512_CONTEXT *hd, const unsigned char *data)
+static void
+transform (void *context, const unsigned char *data)
{
+ SHA512_CONTEXT *ctx = context;
+
#ifdef USE_ARM_NEON_ASM
if (hd->use_neon)
{
- _gcry_sha512_transform_armv7_neon(hd, data, k);
+ _gcry_sha512_transform_armv7_neon(&ctx->state, data, k);
+ /* TODO: return burn stack to md_block_write */
/* return stack burn depth */
- return (sizeof(void *) * 3);
+ return /*(sizeof(void *) * 3)*/;
}
#endif
- __transform (hd, data);
+ __transform (&ctx->state, data);
+ /* TODO: return burn stack to md_block_write */
/* return stack burn depth */
- return 256;
-}
-
-
-/* Update the message digest with the contents
- * of INBUF with length INLEN.
- */
-static void
-sha512_write (void *context, const void *inbuf_arg, size_t inlen)
-{
- const unsigned char *inbuf = inbuf_arg;
- SHA512_CONTEXT *hd = context;
- unsigned int stack_burn_depth = 0;
-
- if (hd->count == 128)
- { /* flush the buffer */
- stack_burn_depth = transform (hd, hd->buf);
- _gcry_burn_stack (stack_burn_depth);
- hd->count = 0;
- hd->nblocks++;
- }
- if (!inbuf)
- return;
- if (hd->count)
- {
- for (; inlen && hd->count < 128; inlen--)
- hd->buf[hd->count++] = *inbuf++;
- sha512_write (context, NULL, 0);
- if (!inlen)
- return;
- }
-
- while (inlen >= 128)
- {
- stack_burn_depth = transform (hd, inbuf);
- hd->count = 0;
- hd->nblocks++;
- inlen -= 128;
- inbuf += 128;
- }
- _gcry_burn_stack (stack_burn_depth);
- for (; inlen && hd->count < 128; inlen--)
- hd->buf[hd->count++] = *inbuf++;
+ return /*256*/;
}
@@ -561,15 +539,15 @@ sha512_final (void *context)
u64 t, msb, lsb;
byte *p;
- sha512_write (context, NULL, 0); /* flush */ ;
+ _gcry_md_block_write (context, NULL, 0); /* flush */ ;
- t = hd->nblocks;
+ t = hd->bctx.nblocks;
/* multiply by 128 to make a byte count */
lsb = t << 7;
msb = t >> 57;
/* add the count */
t = lsb;
- if ((lsb += hd->count) < t)
+ if ((lsb += hd->bctx.count) < t)
msb++;
/* multiply by 8 to make a bit count */
t = lsb;
@@ -577,49 +555,50 @@ sha512_final (void *context)
msb <<= 3;
msb |= t >> 61;
- if (hd->count < 112)
+ if (hd->bctx.count < 112)
{ /* enough room */
- hd->buf[hd->count++] = 0x80; /* pad */
- while (hd->count < 112)
- hd->buf[hd->count++] = 0; /* pad */
+ hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */
+ while (hd->bctx.count < 112)
+ hd->bctx.buf[hd->bctx.count++] = 0; /* pad */
}
else
{ /* need one extra block */
- hd->buf[hd->count++] = 0x80; /* pad character */
- while (hd->count < 128)
- hd->buf[hd->count++] = 0;
- sha512_write (context, NULL, 0); /* flush */ ;
- memset (hd->buf, 0, 112); /* fill next block with zeroes */
+ hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */
+ while (hd->bctx.count < 128)
+ hd->bctx.buf[hd->bctx.count++] = 0;
+ _gcry_md_block_write (context, NULL, 0); /* flush */ ;
+ memset (hd->bctx.buf, 0, 112); /* fill next block with zeroes */
}
/* append the 128 bit count */
- hd->buf[112] = msb >> 56;
- hd->buf[113] = msb >> 48;
- hd->buf[114] = msb >> 40;
- hd->buf[115] = msb >> 32;
- hd->buf[116] = msb >> 24;
- hd->buf[117] = msb >> 16;
- hd->buf[118] = msb >> 8;
- hd->buf[119] = msb;
-
- hd->buf[120] = lsb >> 56;
- hd->buf[121] = lsb >> 48;
- hd->buf[122] = lsb >> 40;
- hd->buf[123] = lsb >> 32;
- hd->buf[124] = lsb >> 24;
- hd->buf[125] = lsb >> 16;
- hd->buf[126] = lsb >> 8;
- hd->buf[127] = lsb;
- stack_burn_depth = transform (hd, hd->buf);
+ hd->bctx.buf[112] = msb >> 56;
+ hd->bctx.buf[113] = msb >> 48;
+ hd->bctx.buf[114] = msb >> 40;
+ hd->bctx.buf[115] = msb >> 32;
+ hd->bctx.buf[116] = msb >> 24;
+ hd->bctx.buf[117] = msb >> 16;
+ hd->bctx.buf[118] = msb >> 8;
+ hd->bctx.buf[119] = msb;
+
+ hd->bctx.buf[120] = lsb >> 56;
+ hd->bctx.buf[121] = lsb >> 48;
+ hd->bctx.buf[122] = lsb >> 40;
+ hd->bctx.buf[123] = lsb >> 32;
+ hd->bctx.buf[124] = lsb >> 24;
+ hd->bctx.buf[125] = lsb >> 16;
+ hd->bctx.buf[126] = lsb >> 8;
+ hd->bctx.buf[127] = lsb;
+ transform (hd, hd->bctx.buf);
+ stack_burn_depth = hd->bctx.stack_burn;
_gcry_burn_stack (stack_burn_depth);
- p = hd->buf;
+ p = hd->bctx.buf;
#ifdef WORDS_BIGENDIAN
-#define X(a) do { *(u64*)p = hd->h##a ; p += 8; } while (0)
+#define X(a) do { *(u64*)p = hd->state.h##a ; p += 8; } while (0)
#else /* little endian */
-#define X(a) do { *p++ = hd->h##a >> 56; *p++ = hd->h##a >> 48; \
- *p++ = hd->h##a >> 40; *p++ = hd->h##a >> 32; \
- *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \
- *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while (0)
+#define X(a) do { *p++ = hd->state.h##a >> 56; *p++ = hd->state.h##a >> 48; \
+ *p++ = hd->state.h##a >> 40; *p++ = hd->state.h##a >> 32; \
+ *p++ = hd->state.h##a >> 24; *p++ = hd->state.h##a >> 16; \
+ *p++ = hd->state.h##a >> 8; *p++ = hd->state.h##a; } while(0)
#endif
X (0);
X (1);
@@ -638,7 +617,7 @@ static byte *
sha512_read (void *context)
{
SHA512_CONTEXT *hd = (SHA512_CONTEXT *) context;
- return hd->buf;
+ return hd->bctx.buf;
}
@@ -797,7 +776,7 @@ static gcry_md_oid_spec_t oid_spec_sha512[] =
gcry_md_spec_t _gcry_digest_spec_sha512 =
{
"SHA512", sha512_asn, DIM (sha512_asn), oid_spec_sha512, 64,
- sha512_init, sha512_write, sha512_final, sha512_read,
+ sha512_init, _gcry_md_block_write, sha512_final, sha512_read,
sizeof (SHA512_CONTEXT),
};
md_extra_spec_t _gcry_digest_extraspec_sha512 =
@@ -825,7 +804,7 @@ static gcry_md_oid_spec_t oid_spec_sha384[] =
gcry_md_spec_t _gcry_digest_spec_sha384 =
{
"SHA384", sha384_asn, DIM (sha384_asn), oid_spec_sha384, 48,
- sha384_init, sha512_write, sha512_final, sha512_read,
+ sha384_init, _gcry_md_block_write, sha512_final, sha512_read,
sizeof (SHA512_CONTEXT),
};
md_extra_spec_t _gcry_digest_extraspec_sha384 =
More information about the Gcrypt-devel
mailing list