diff --git a/sha.h b/sha.h index 5dbffd7ef9a761c4736f8493af4ec892128177b9..41afde4b6ac78b76efcba0e0bd1edd8b6d8487db 100644 --- a/sha.h +++ b/sha.h @@ -36,6 +36,8 @@ extern "C" { #define sha1_init nettle_sha1_init #define sha1_update nettle_sha1_update #define sha1_digest nettle_sha1_digest +#define sha224_init nettle_sha224_init +#define sha224_digest nettle_sha224_digest #define sha256_init nettle_sha256_init #define sha256_update nettle_sha256_update #define sha256_digest nettle_sha256_digest @@ -114,6 +116,24 @@ sha256_digest(struct sha256_ctx *ctx, void _nettle_sha256_compress(uint32_t *state, const uint8_t *data, const uint32_t *k); + +/* SHA224, a truncated SHA256 with different initial state. */ + +#define SHA224_DIGEST_SIZE 28 +#define SHA224_DATA_SIZE SHA256_DATA_SIZE +#define sha224_ctx sha256_ctx + +void +sha224_init(struct sha256_ctx *ctx); + +#define sha224_update nettle_sha256_update + +void +sha224_digest(struct sha256_ctx *ctx, + unsigned length, + uint8_t *digest); + + /* SHA512 */ #define SHA512_DIGEST_SIZE 64 @@ -149,9 +169,8 @@ sha512_digest(struct sha512_ctx *ctx, void _nettle_sha512_compress(uint64_t *state, const uint8_t *data, const uint64_t *k); -/* SHA384. */ -/* This is the same algorithm as SHA512, but with different initial - state and truncated output. */ + +/* SHA384, a truncated SHA512 with different initial state. */ #define SHA384_DIGEST_SIZE 48 #define SHA384_DATA_SIZE SHA512_DATA_SIZE diff --git a/sha256.c b/sha256.c index 9a3f1bb2cba48feefbb5dce09ad7013c3564a9eb..fa4f735b5979cde6a0a3e89733e893bb433a9c32 100644 --- a/sha256.c +++ b/sha256.c @@ -38,6 +38,7 @@ #include "sha.h" #include "macros.h" +#include "nettle-write.h" /* Generated by the shadata program. */ static const uint32_t @@ -172,42 +173,42 @@ sha256_digest(struct sha256_ctx *ctx, unsigned length, uint8_t *digest) { - unsigned i; - unsigned words; - unsigned leftover; - assert(length <= SHA256_DIGEST_SIZE); sha256_final(ctx); + _nettle_write_be32(length, digest, ctx->state); + sha256_init(ctx); +} + +/* sha224 variant. FIXME: Move to seperate file? */ + +void +sha224_init(struct sha256_ctx *ctx) +{ + /* Initial values. I's unclear how they are chosen. */ + static const uint32_t H0[_SHA256_DIGEST_LENGTH] = + { + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4, + }; + + memcpy(ctx->state, H0, sizeof(H0)); + + /* Initialize bit count */ + ctx->count_low = ctx->count_high = 0; - words = length / 4; - leftover = length % 4; + /* Initialize buffer */ + ctx->index = 0; +} - for (i = 0; i < words; i++, digest += 4) - WRITE_UINT32(digest, ctx->state[i]); +void +sha224_digest(struct sha256_ctx *ctx, + unsigned length, + uint8_t *digest) +{ + assert(length <= SHA224_DIGEST_SIZE); - if (leftover) - { - uint32_t word; - unsigned j = leftover; - - assert(i < _SHA256_DIGEST_LENGTH); - - word = ctx->state[i]; - - switch (leftover) - { - default: - abort(); - case 3: - digest[--j] = (word >> 8) & 0xff; - /* Fall through */ - case 2: - digest[--j] = (word >> 16) & 0xff; - /* Fall through */ - case 1: - digest[--j] = (word >> 24) & 0xff; - } - } - sha256_init(ctx); + sha256_final(ctx); + _nettle_write_be32(length, digest, ctx->state); + sha224_init(ctx); }