Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com --- nettle-meta.h | 12 +++++ sha2.h | 45 ++++++++++++++++-- sha384-meta.c | 3 ++ sha512-meta.c | 3 ++ sha512.c | 129 ++++++++++++++++++++++++++++++++++++-------------- 5 files changed, 152 insertions(+), 40 deletions(-)
diff --git a/nettle-meta.h b/nettle-meta.h index a28cecf5fe62..da9591287e79 100644 --- a/nettle-meta.h +++ b/nettle-meta.h @@ -155,6 +155,16 @@ struct nettle_bctx_hash (nettle_hash_block_digest_func *) name##_block_digest \ }
+#define _NETTLE_BLOCK_HASH_US(name, name_us, NAME) { \ + #name, \ + sizeof(struct name_us##_state), \ + NAME##_DIGEST_SIZE, \ + NAME##_BLOCK_SIZE, \ + (nettle_hash_block_init_func *) name_us##_block_init, \ + (nettle_hash_block_update_func *) name_us##_block_update, \ + (nettle_hash_block_digest_func *) name_us##_block_digest \ +} + /* null-terminated list of digests implemented by this version of nettle */ const struct nettle_hash * const * _NETTLE_ATTRIBUTE_PURE nettle_get_hashes (void); @@ -186,6 +196,8 @@ extern const struct nettle_bctx_hash nettle_bctx_ripemd160; extern const struct nettle_bctx_hash nettle_bctx_sha1; extern const struct nettle_bctx_hash nettle_bctx_sha224; extern const struct nettle_bctx_hash nettle_bctx_sha256; +extern const struct nettle_bctx_hash nettle_bctx_sha384; +extern const struct nettle_bctx_hash nettle_bctx_sha512;
struct nettle_aead { diff --git a/sha2.h b/sha2.h index 95640b5f4b7f..4f8f5c300822 100644 --- a/sha2.h +++ b/sha2.h @@ -53,9 +53,14 @@ extern "C" { #define sha256_block_digest nettle_sha256_block_digest #define sha384_init nettle_sha384_init #define sha384_digest nettle_sha384_digest +#define sha384_block_init nettle_sha384_block_init +#define sha384_block_digest nettle_sha384_block_digest #define sha512_init nettle_sha512_init #define sha512_update nettle_sha512_update #define sha512_digest nettle_sha512_digest +#define sha512_block_init nettle_sha512_block_init +#define sha512_block_update nettle_sha512_block_update +#define sha512_block_digest nettle_sha512_block_digest #define sha512_224_init nettle_sha512_224_init #define sha512_224_digest nettle_sha512_224_digest #define sha512_256_init nettle_sha512_256_init @@ -153,12 +158,16 @@ sha224_block_digest(struct sha256_state *state, /* Digest is kept internally as 8 64-bit words. */ #define _SHA512_DIGEST_LENGTH 8
-struct sha512_ctx +struct sha512_state { uint64_t state[_SHA512_DIGEST_LENGTH]; /* State variables */ uint64_t count_low, count_high; /* 128-bit block count */ - unsigned int index; /* index into buffer */ - uint8_t block[SHA512_BLOCK_SIZE]; /* SHA512 data buffer */ +}; + +struct sha512_ctx +{ + struct sha512_state state; + BLOCK_CTX(SHA512_BLOCK_SIZE); };
void @@ -174,12 +183,28 @@ sha512_digest(struct sha512_ctx *ctx, size_t length, uint8_t *digest);
+void +sha512_block_init(struct sha512_state *state, + struct block_ctx *bctx); + +void +sha512_block_update(struct sha512_state *state, + struct block_ctx *bctx, + size_t length, + const uint8_t *data); + +void +sha512_block_digest(struct sha512_state *state, + struct block_ctx *bctx, + size_t length, + uint8_t *digest);
/* SHA384, a truncated SHA512 with different initial state. */
#define SHA384_DIGEST_SIZE 48 #define SHA384_BLOCK_SIZE SHA512_BLOCK_SIZE #define sha384_ctx sha512_ctx +#define sha384_state sha512_state
void sha384_init(struct sha512_ctx *ctx); @@ -191,6 +216,18 @@ sha384_digest(struct sha512_ctx *ctx, size_t length, uint8_t *digest);
+void +sha384_block_init(struct sha512_state *state, + struct block_ctx *bctx); + +#define sha384_block_update sha512_block_update + +void +sha384_block_digest(struct sha512_state *state, + struct block_ctx *bctx, + size_t length, + uint8_t *digest); +
/* SHA512_224 and SHA512_256, two truncated versions of SHA512 with different initial states. */ @@ -222,7 +259,7 @@ void sha512_256_digest(struct sha512_256_ctx *ctx, size_t length, uint8_t *digest); - + #ifdef __cplusplus } #endif diff --git a/sha384-meta.c b/sha384-meta.c index 0eb561054a73..7c842f1b1b44 100644 --- a/sha384-meta.c +++ b/sha384-meta.c @@ -39,3 +39,6 @@
const struct nettle_hash nettle_sha384 = _NETTLE_HASH(sha384, SHA384); + +const struct nettle_bctx_hash nettle_bctx_sha384 += _NETTLE_BLOCK_HASH(sha384, SHA384); diff --git a/sha512-meta.c b/sha512-meta.c index d592c4bec6c7..c61812d5a8e1 100644 --- a/sha512-meta.c +++ b/sha512-meta.c @@ -39,3 +39,6 @@
const struct nettle_hash nettle_sha512 = _NETTLE_HASH(sha512, SHA512); + +const struct nettle_bctx_hash nettle_bctx_sha512 += _NETTLE_BLOCK_HASH(sha512, SHA512); diff --git a/sha512.c b/sha512.c index 6936cb501142..16d79a989955 100644 --- a/sha512.c +++ b/sha512.c @@ -116,7 +116,7 @@ K[80] = #define COMPRESS(ctx, data) (_nettle_sha512_compress((ctx)->state, (data), K))
void -sha512_init(struct sha512_ctx *ctx) +sha512_block_init(struct sha512_state *state, struct block_ctx *bctx) { /* Initial values, generated by the gp script { @@ -135,24 +135,40 @@ sha512_init(struct sha512_ctx *ctx) 0x1F83D9ABFB41BD6BULL,0x5BE0CD19137E2179ULL, };
- memcpy(ctx->state, H0, sizeof(H0)); + memcpy(state->state, H0, sizeof(H0));
/* Initialize bit count */ - ctx->count_low = ctx->count_high = 0; + state->count_low = state->count_high = 0;
/* Initialize buffer */ - ctx->index = 0; + bctx->index = 0; +} + +void +sha512_init(struct sha512_ctx *ctx) +{ + return sha512_block_init(&ctx->state, (struct block_ctx *)&ctx->block); }
void sha512_update(struct sha512_ctx *ctx, size_t length, const uint8_t *data) { - MD_UPDATE (ctx, length, data, COMPRESS, MD_INCR(ctx)); + MD_BLOCK_UPDATE (&ctx->state, &ctx->block, SHA512_BLOCK_SIZE, length, data, COMPRESS, MD_INCR(&ctx->state)); +} + +void +sha512_block_update(struct sha512_state *state, + struct block_ctx *bctx, + size_t length, + const uint8_t *data) +{ + MD_BLOCK_UPDATE(state, bctx, SHA512_BLOCK_SIZE, length, data, COMPRESS, MD_INCR(state)); }
static void -sha512_write_digest(struct sha512_ctx *ctx, +sha512_write_digest(struct sha512_state *state, + struct block_ctx *bctx, size_t length, uint8_t *digest) { @@ -164,29 +180,29 @@ sha512_write_digest(struct sha512_ctx *ctx,
assert(length <= SHA512_DIGEST_SIZE);
- MD_PAD(ctx, 16, COMPRESS); + MD_BLOCK_PAD(state, bctx, SHA512_BLOCK_SIZE, 16, COMPRESS);
/* There are 1024 = 2^10 bits in one block */ - high = (ctx->count_high << 10) | (ctx->count_low >> 54); - low = (ctx->count_low << 10) | (ctx->index << 3); + high = (state->count_high << 10) | (state->count_low >> 54); + low = (state->count_low << 10) | (bctx->index << 3);
/* This is slightly inefficient, as the numbers are converted to big-endian format, and will be converted back by the compression function. It's probably not worth the effort to fix this. */ - WRITE_UINT64(ctx->block + (SHA512_BLOCK_SIZE - 16), high); - WRITE_UINT64(ctx->block + (SHA512_BLOCK_SIZE - 8), low); - COMPRESS(ctx, ctx->block); + WRITE_UINT64(bctx->buffer + (SHA512_BLOCK_SIZE - 16), high); + WRITE_UINT64(bctx->buffer + (SHA512_BLOCK_SIZE - 8), low); + COMPRESS(state, bctx->buffer);
words = length / 8; leftover = length % 8;
for (i = 0; i < words; i++, digest += 8) - WRITE_UINT64(digest, ctx->state[i]); + WRITE_UINT64(digest, state->state[i]);
if (leftover) { /* Truncate to the right size */ - uint64_t word = ctx->state[i] >> (8*(8 - leftover)); + uint64_t word = state->state[i] >> (8*(8 - leftover));
do { digest[--leftover] = word & 0xff; @@ -202,13 +218,23 @@ sha512_digest(struct sha512_ctx *ctx, { assert(length <= SHA512_DIGEST_SIZE);
- sha512_write_digest(ctx, length, digest); + sha512_write_digest(&ctx->state, (struct block_ctx *)&ctx->block, length, digest); sha512_init(ctx); }
+void +sha512_block_digest(struct sha512_state *state, + struct block_ctx *bctx, + size_t length, + uint8_t *digest) +{ + sha512_write_digest(state, bctx, length, digest); + sha512_block_init(state, bctx); +} + /* sha384 variant. */ void -sha384_init(struct sha512_ctx *ctx) +sha384_block_init(struct sha512_state *state, struct block_ctx *bctx) { /* Initial values, generated by the gp script { @@ -227,13 +253,19 @@ sha384_init(struct sha512_ctx *ctx) 0xDB0C2E0D64F98FA7ULL, 0x47B5481DBEFA4FA4ULL, };
- memcpy(ctx->state, H0, sizeof(H0)); + memcpy(state->state, H0, sizeof(H0));
/* Initialize bit count */ - ctx->count_low = ctx->count_high = 0; + state->count_low = state->count_high = 0;
/* Initialize buffer */ - ctx->index = 0; + bctx->index = 0; +} + +void +sha384_init(struct sha512_ctx *ctx) +{ + return sha384_block_init(&ctx->state, (struct block_ctx *)&ctx->block); }
void @@ -243,14 +275,26 @@ sha384_digest(struct sha512_ctx *ctx, { assert(length <= SHA384_DIGEST_SIZE);
- sha512_write_digest(ctx, length, digest); + sha512_write_digest(&ctx->state, (struct block_ctx *)&ctx->block, length, digest); sha384_init(ctx); }
-/* sha-512/224 variant. */ void -sha512_224_init(struct sha512_224_ctx *ctx) +sha384_block_digest(struct sha512_state *state, + struct block_ctx *bctx, + size_t length, + uint8_t *digest) +{ + assert(length <= SHA384_DIGEST_SIZE); + + sha512_write_digest(state, bctx, length, digest); + sha384_block_init(state, bctx); +} + +/* sha-512/224 variant. */ +static void +sha512_224_block_init(struct sha512_state *state, struct block_ctx *bctx) { static const uint64_t H0[_SHA512_DIGEST_LENGTH] = { @@ -260,30 +304,37 @@ sha512_224_init(struct sha512_224_ctx *ctx) 0x3f9d85a86a1d36c8ULL, 0x1112e6ad91d692a1ULL, };
- memcpy(ctx->state, H0, sizeof(H0)); + memcpy(state->state, H0, sizeof(H0));
/* Initialize bit count */ - ctx->count_low = ctx->count_high = 0; + state->count_low = state->count_high = 0;
/* Initialize buffer */ - ctx->index = 0; + bctx->index = 0; +} + +void +sha512_224_init(struct sha512_ctx *ctx) +{ + return sha512_224_block_init(&ctx->state, (struct block_ctx *)&ctx->block); }
void sha512_224_digest(struct sha512_224_ctx *ctx, - size_t length, - uint8_t *digest) + size_t length, + uint8_t *digest) { assert(length <= SHA224_DIGEST_SIZE);
- sha512_write_digest(ctx, length, digest); + sha512_write_digest(&ctx->state, (struct block_ctx *)&ctx->block, length, digest); sha512_224_init(ctx); }
/* sha-512/256 variant. */ -void -sha512_256_init(struct sha512_256_ctx *ctx) +static void +sha512_256_block_init(struct sha512_state *state, + struct block_ctx *bctx) { static const uint64_t H0[_SHA512_DIGEST_LENGTH] = { @@ -293,22 +344,28 @@ sha512_256_init(struct sha512_256_ctx *ctx) 0x2b0199fc2c85b8aaULL, 0x0eb72ddc81c52ca2ULL, };
- memcpy(ctx->state, H0, sizeof(H0)); + memcpy(state->state, H0, sizeof(H0));
/* Initialize bit count */ - ctx->count_low = ctx->count_high = 0; + state->count_low = state->count_high = 0;
/* Initialize buffer */ - ctx->index = 0; + bctx->index = 0; +} + +void +sha512_256_init(struct sha512_256_ctx *ctx) +{ + sha512_256_block_init(&ctx->state, (struct block_ctx *)&ctx->block); }
void sha512_256_digest(struct sha512_256_ctx *ctx, - size_t length, - uint8_t *digest) + size_t length, + uint8_t *digest) { assert(length <= SHA256_DIGEST_SIZE);
- sha512_write_digest(ctx, length, digest); + sha512_write_digest(&ctx->state, (struct block_ctx *)&ctx->block, length, digest); sha512_256_init(ctx); }