aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2019-07-17 01:13:12 -0400
committerPaul Duncan <pabs@pablotron.org>2019-07-17 01:13:12 -0400
commit9b9d4f7a7d22f1a0c2b1d53a1f7cd6bc67a34010 (patch)
tree28452875fd430ea7f79db4656802270ab1605125
parent84d33c240c163ef161673ffbdc51c4ef2e43db7b (diff)
downloadsha2-9b9d4f7a7d22f1a0c2b1d53a1f7cd6bc67a34010.tar.bz2
sha2-9b9d4f7a7d22f1a0c2b1d53a1f7cd6bc67a34010.zip
add sha{384,512}
-rw-r--r--sha2.c383
-rw-r--r--sha2.h28
-rw-r--r--tests.c71
3 files changed, 457 insertions, 25 deletions
diff --git a/sha2.c b/sha2.c
index 84667a8..fc08d38 100644
--- a/sha2.c
+++ b/sha2.c
@@ -1,9 +1,9 @@
#include "sha2.h"
-#include <string.h> // memcpy
+#include <string.h> // memcpy()
// extract bytes from uint32_t
// (used in sha256_fini() and sha224_fini())
-#define WB(ctx, i) \
+#define E4(ctx, i) \
((ctx)->h[i] >> 24) & 0xff, \
((ctx)->h[i] >> 16) & 0xff, \
((ctx)->h[i] >> 8) & 0xff, \
@@ -17,10 +17,10 @@ static const uint32_t SHA256_INIT[8] = {
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
};
-// round constants
+// sha256 round constants
// (first 32 bits of the fractional parts of the cube roots of the first
// 64 primes 2..311):
-static const uint32_t K[64] = {
+static const uint32_t K256[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
@@ -36,13 +36,28 @@ static const uint32_t K[64] = {
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
};
-// rotate right
+// rotate right (uint32_t)
// (src: https://blog.regehr.org/archives/1063)
static inline uint32_t
-rr(const uint32_t v, const size_t n) {
+rr32(const uint32_t v, const size_t n) {
return (v << (32 - n)) | (v >> n);
}
+#if 0
+#define rr32(v, n) (((v) << (32 - (n))) | ((v) >> (n)))
+#endif /* 0 */
+
+// rotate right (uint64_t)
+// (src: https://blog.regehr.org/archives/1063)
+static inline uint64_t
+rr64(const uint64_t v, const size_t n) {
+ return (v << (64 - n)) | (v >> n);
+}
+
+#if 0
+#define rr64(v, n) (((v) << (64 - (n))) | ((v) >> (n)))
+#endif /* 0 */
+
void sha256_init(sha256_t * const ctx) {
ctx->buf_len = 0;
ctx->num_bytes = 0;
@@ -63,17 +78,17 @@ void sha256_init(sha256_t * const ctx) {
w7 = w[(i) - 7], \
w15 = w[(i) - 15], \
w16 = w[(i) - 16], \
- s0 = rr(w15, 7) ^ rr(w15, 18) ^ (w15 >> 3), \
- s1 = rr(w2, 17) ^ rr(w2, 19) ^ (w2 >> 10); \
+ s0 = rr32(w15, 7) ^ rr32(w15, 18) ^ (w15 >> 3), \
+ s1 = rr32(w2, 17) ^ rr32(w2, 19) ^ (w2 >> 10); \
w[i] = w16 + s0 + w7 + s1; \
} while (0)
// WC: compress word
#define WC(i) do { \
- const uint32_t s1 = rr(hs[4], 6) ^ rr(hs[4], 11) ^ rr(hs[4], 25), \
+ const uint32_t s1 = rr32(hs[4], 6) ^ rr32(hs[4], 11) ^ rr32(hs[4], 25), \
ch = (hs[4] & hs[5]) ^ ((~(hs[4])) & hs[6]), \
- t0 = hs[7] + s1 + ch + K[i] + w[i], \
- s0 = rr(hs[0], 2) ^ rr(hs[0], 13) ^ rr(hs[0], 22), \
+ t0 = hs[7] + s1 + ch + K256[i] + w[i], \
+ s0 = rr32(hs[0], 2) ^ rr32(hs[0], 13) ^ rr32(hs[0], 22), \
mj = (hs[0] & hs[1]) ^ (hs[0] & hs[2]) ^ (hs[1] & hs[2]), \
t1 = s0 + mj; \
\
@@ -109,8 +124,8 @@ sha256_block(sha256_t * const ctx) {
// w7 = w[i - 7],
// w15 = w[i - 15],
// w16 = w[i - 16],
- // s0 = rr(w15, 7) ^ rr(w15, 18) ^ (w15 >> 3),
- // s1 = rr(w2, 17) ^ rr(w2, 19) ^ (w2 >> 10);
+ // s0 = rr32(w15, 7) ^ rr32(w15, 18) ^ (w15 >> 3),
+ // s1 = rr32(w2, 17) ^ rr32(w2, 19) ^ (w2 >> 10);
// w[i] = w16 + s0 + w7 + s1;
// }
//
@@ -158,10 +173,10 @@ sha256_block(sha256_t * const ctx) {
// a := temp1 + temp2
//
// for (size_t i = 0; i < 64; i++) {
- // const uint32_t s1 = rr(hs[4], 6) ^ rr(hs[4], 11) ^ rr(hs[4], 25),
+ // const uint32_t s1 = rr32(hs[4], 6) ^ rr32(hs[4], 11) ^ rr32(hs[4], 25),
// ch = (hs[4] & hs[5]) ^ ((~(hs[4])) & hs[6]),
- // t0 = hs[7] + s1 + ch + K[i] + w[i],
- // s0 = rr(hs[0], 2) ^ rr(hs[0], 13) ^ rr(hs[0], 22),
+ // t0 = hs[7] + s1 + ch + K256[i] + w[i],
+ // s0 = rr32(hs[0], 2) ^ rr32(hs[0], 13) ^ rr32(hs[0], 22),
// mj = (hs[0] & hs[1]) ^ (hs[0] & hs[2]) ^ (hs[1] & hs[2]),
// t1 = s0 + mj;
@@ -208,8 +223,6 @@ sha256_block(sha256_t * const ctx) {
#undef WE
#undef WC
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-
void sha256_push(
sha256_t * const ctx,
const uint8_t * const src,
@@ -264,8 +277,8 @@ sha256_push_u64(
sha256_push(ctx, buf, sizeof(buf));
}
-// end of stream padding
-static const uint8_t PADDING[65] = {
+// sha256 end of stream padding
+static const uint8_t SHA256_PADDING[65] = {
128,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -281,7 +294,7 @@ sha256_push_footer(
const size_t pad_len = (65 - ((num_bytes + 1 + 8) % 64));
// push padding
- sha256_push(ctx, PADDING, pad_len);
+ sha256_push(ctx, SHA256_PADDING, pad_len);
// push length (in bits)
sha256_push_u64(ctx, num_bytes * 8);
@@ -296,8 +309,8 @@ void sha256_fini(
// extract hash
const uint8_t hash[32] = {
- WB(ctx, 0), WB(ctx, 1), WB(ctx, 2), WB(ctx, 3),
- WB(ctx, 4), WB(ctx, 5), WB(ctx, 6), WB(ctx, 7),
+ E4(ctx, 0), E4(ctx, 1), E4(ctx, 2), E4(ctx, 3),
+ E4(ctx, 4), E4(ctx, 5), E4(ctx, 6), E4(ctx, 7),
};
memcpy(out, hash, sizeof(hash));
@@ -348,8 +361,8 @@ void sha224_fini(
// extract hash
const uint8_t hash[28] = {
- WB(ctx, 0), WB(ctx, 1), WB(ctx, 2), WB(ctx, 3),
- WB(ctx, 4), WB(ctx, 5), WB(ctx, 6),
+ E4(ctx, 0), E4(ctx, 1), E4(ctx, 2), E4(ctx, 3),
+ E4(ctx, 4), E4(ctx, 5), E4(ctx, 6),
};
memcpy(out, hash, sizeof(hash));
@@ -365,3 +378,323 @@ void sha224(
sha224_push(&ctx, src, src_len);
sha224_fini(&ctx, dst);
}
+
+// extract bytes from uint64_t
+// (used in sha512_fini() and sha384_fini())
+#define E8(ctx, i) \
+ ((ctx)->h[i] >> 56) & 0xff, \
+ ((ctx)->h[i] >> 48) & 0xff, \
+ ((ctx)->h[i] >> 40) & 0xff, \
+ ((ctx)->h[i] >> 32) & 0xff, \
+ ((ctx)->h[i] >> 24) & 0xff, \
+ ((ctx)->h[i] >> 16) & 0xff, \
+ ((ctx)->h[i] >> 8) & 0xff, \
+ ((ctx)->h[i]) & 0xff
+
+// sha512 initial hash values
+// (first 64 bits of the fractional parts of the square roots of the
+// first 8 primes 2..19):
+static const uint64_t SHA512_INIT[8] = {
+ 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b,
+ 0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f,
+ 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
+};
+
+// sha512 round constants
+// (first 64 bits of the fractional parts of the cube roots of the first
+// 80 primes [2..409]):
+static const uint64_t K512[80] = {
+ 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f,
+ 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019,
+ 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242,
+ 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
+ 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
+ 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
+ 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275,
+ 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
+ 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f,
+ 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
+ 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc,
+ 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
+ 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6,
+ 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001,
+ 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
+ 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
+ 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99,
+ 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
+ 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc,
+ 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
+ 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915,
+ 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207,
+ 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba,
+ 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
+ 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
+ 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
+ 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
+};
+
+void sha512_init(sha512_t * const ctx) {
+ ctx->buf_len = 0;
+ ctx->num_bytes = 0;
+ memcpy(ctx->h, SHA512_INIT, sizeof(SHA512_INIT));
+}
+
+// WI64: decode buffer data as 64-bit words (used for the first 16 words)
+#define WI64(i) ( \
+ (((uint64_t) ctx->buf[8 * (i) + 0]) << 56) | \
+ (((uint64_t) ctx->buf[8 * (i) + 1]) << 48) | \
+ (((uint64_t) ctx->buf[8 * (i) + 2]) << 40) | \
+ (((uint64_t) ctx->buf[8 * (i) + 3]) << 32) | \
+ (((uint64_t) ctx->buf[8 * (i) + 4]) << 24) | \
+ (((uint64_t) ctx->buf[8 * (i) + 5]) << 16) | \
+ (((uint64_t) ctx->buf[8 * (i) + 6]) << 8) | \
+ ((uint64_t) ctx->buf[8 * (i) + 7]) \
+)
+
+// WE64: expand first 16 buffer words into remaining 64 words
+#define WE64(i) do { \
+ const uint64_t w2 = w[(i) - 2], \
+ w7 = w[(i) - 7], \
+ w15 = w[(i) - 15], \
+ w16 = w[(i) - 16], \
+ s0 = rr64(w15, 1) ^ rr64(w15, 8) ^ (w15 >> 7), \
+ s1 = rr64(w2, 19) ^ rr64(w2, 61) ^ (w2 >> 6); \
+ w[i] = w16 + s0 + w7 + s1; \
+} while (0)
+
+// WC: compress word
+#define WC64(i) do { \
+ const uint64_t s1 = rr64(hs[4], 14) ^ rr64(hs[4], 18) ^ rr64(hs[4], 41), \
+ ch = (hs[4] & hs[5]) ^ ((~(hs[4])) & hs[6]), \
+ t0 = hs[7] + s1 + ch + K512[i] + w[i], \
+ s0 = rr64(hs[0], 28) ^ rr64(hs[0], 34) ^ rr64(hs[0], 39), \
+ mj = (hs[0] & hs[1]) ^ (hs[0] & hs[2]) ^ (hs[1] & hs[2]), \
+ t1 = s0 + mj; \
+\
+ hs[7] = hs[6]; \
+ hs[6] = hs[5]; \
+ hs[5] = hs[4]; \
+ hs[4] = hs[3] + t0; \
+ hs[3] = hs[2]; \
+ hs[2] = hs[1]; \
+ hs[1] = hs[0]; \
+ hs[0] = t0 + t1; \
+} while (0)
+
+static void
+sha512_block(sha512_t * const ctx) {
+ // init first 16 words from buffer
+ uint64_t w[80] = {
+ WI64(0), WI64(1), WI64(2), WI64(3),
+ WI64(4), WI64(5), WI64(6), WI64(7),
+ WI64(8), WI64(9), WI64(10), WI64(11),
+ WI64(12), WI64(13), WI64(14), WI64(15),
+ 0,
+ };
+
+ // Extend the first 16 words into the remaining 64 words w[16..80] of
+ // the message schedule array
+ for (size_t i = 16; i < 80; i++) {
+ WE64(i);
+ }
+
+ // Initialize working variables to current hash value
+ uint64_t hs[8] = {
+ ctx->h[0], ctx->h[1], ctx->h[2], ctx->h[3],
+ ctx->h[4], ctx->h[5], ctx->h[6], ctx->h[7],
+ };
+
+ // Compression function main loop
+ //
+ // partially unrolled:
+ for (size_t i = 0; i < 80; i += 16) {
+ WC64(i + 0); WC64(i + 1); WC64(i + 2); WC64(i + 3);
+ WC64(i + 4); WC64(i + 5); WC64(i + 6); WC64(i + 7);
+ WC64(i + 8); WC64(i + 9); WC64(i + 10); WC64(i + 11);
+ WC64(i + 12); WC64(i + 13); WC64(i + 14); WC64(i + 15);
+ }
+
+ // Add the compressed chunk to the current hash value
+ ctx->h[0] += hs[0];
+ ctx->h[1] += hs[1];
+ ctx->h[2] += hs[2];
+ ctx->h[3] += hs[3];
+ ctx->h[4] += hs[4];
+ ctx->h[5] += hs[5];
+ ctx->h[6] += hs[6];
+ ctx->h[7] += hs[7];
+}
+
+#undef WI64
+#undef WE64
+#undef WC64
+
+void sha512_push(
+ sha512_t * const ctx,
+ const uint8_t * const src,
+ const size_t src_len
+) {
+ const size_t buf_left = 128 - ctx->buf_len;
+
+ if (src_len >= buf_left) {
+ // fill remaining buffer
+ memcpy(ctx->buf + ctx->buf_len, src, buf_left);
+ sha512_block(ctx);
+ ctx->buf_len = 0;
+
+ const size_t new_src_len = src_len - buf_left;
+ const size_t num_blocks = new_src_len / 128;
+
+ // process chunks
+ for (size_t i = 0; i < num_blocks; i++) {
+ memcpy(ctx->buf, src + buf_left + (128 * i), 128);
+ sha512_block(ctx);
+ }
+
+ // copy remaining bytes to buffer
+ const size_t new_buf_len = (new_src_len - 128 * num_blocks);
+ memcpy(ctx->buf, src + buf_left + (128 * num_blocks), new_buf_len);
+ ctx->buf_len = new_buf_len;
+ } else {
+ memcpy(ctx->buf + ctx->buf_len, src, src_len);
+ ctx->buf_len += src_len;
+ }
+
+ // update byte count
+ ctx->num_bytes += src_len;
+}
+
+static void
+sha512_push_u128(
+ sha512_t * const ctx,
+ const uint64_t hi,
+ const uint64_t lo
+) {
+ const uint8_t buf[16] = {
+ ((hi >> 56) & 0xff),
+ ((hi >> 48) & 0xff),
+ ((hi >> 40) & 0xff),
+ ((hi >> 32) & 0xff),
+ ((hi >> 24) & 0xff),
+ ((hi >> 16) & 0xff),
+ ((hi >> 8) & 0xff),
+ ((hi) & 0xff),
+ ((lo >> 56) & 0xff),
+ ((lo >> 48) & 0xff),
+ ((lo >> 40) & 0xff),
+ ((lo >> 32) & 0xff),
+ ((lo >> 24) & 0xff),
+ ((lo >> 16) & 0xff),
+ ((lo >> 8) & 0xff),
+ ((lo) & 0xff),
+ };
+
+ sha512_push(ctx, buf, sizeof(buf));
+}
+
+// sha512 end of stream padding
+static const uint8_t SHA512_PADDING[129] = {
+ 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static void
+sha512_push_footer(
+ sha512_t * const ctx
+) {
+ const uint64_t num_bytes = ctx->num_bytes;
+ const size_t pad_len = (129 - ((num_bytes + 1 + 16) % 128));
+
+ // push padding
+ sha512_push(ctx, SHA512_PADDING, pad_len);
+
+ // push length (in bits)
+ sha512_push_u128(ctx, 0, num_bytes * 8);
+}
+
+void sha512_fini(
+ sha512_t * const ctx,
+ uint8_t * const out
+) {
+ // push footer
+ sha512_push_footer(ctx);
+
+ // extract hash
+ const uint8_t hash[64] = {
+ E8(ctx, 0), E8(ctx, 1), E8(ctx, 2), E8(ctx, 3),
+ E8(ctx, 4), E8(ctx, 5), E8(ctx, 6), E8(ctx, 7),
+ };
+
+ memcpy(out, hash, sizeof(hash));
+}
+
+void sha512(
+ const uint8_t * const src,
+ const size_t src_len,
+ uint8_t * const dst
+) {
+ sha512_t ctx;
+ sha512_init(&ctx);
+ sha512_push(&ctx, src, src_len);
+ sha512_fini(&ctx, dst);
+}
+
+// sha384 initial hash values
+// (the second 64 bits of the fractional parts of the square roots of
+// the 9th through 16th primes 23..53)
+static const uint64_t SHA384_INIT[8] = {
+ 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17,
+ 0x152fecd8f70e5939, 0x67332667ffc00b31, 0x8eb44a8768581511,
+ 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4
+};
+
+void sha384_init(sha384_t * const ctx) {
+ ctx->ctx.buf_len = 0;
+ ctx->ctx.num_bytes = 0;
+ memcpy(ctx->ctx.h, SHA384_INIT, sizeof(SHA384_INIT));
+}
+
+void sha384_push(
+ sha384_t * const sha384_ctx,
+ const uint8_t * const src,
+ const size_t src_len
+) {
+ sha512_t * const ctx = (sha512_t * const) sha384_ctx;
+ sha512_push(ctx, src, src_len);
+}
+
+void sha384_fini(
+ sha384_t * const sha384_ctx,
+ uint8_t * const out
+) {
+ sha512_t * const ctx = (sha512_t * const) sha384_ctx;
+
+ // push footer
+ sha512_push_footer(ctx);
+
+ // extract hash
+ const uint8_t hash[56] = {
+ E8(ctx, 0), E8(ctx, 1), E8(ctx, 2), E8(ctx, 3),
+ E8(ctx, 4), E8(ctx, 5), E8(ctx, 6),
+ };
+
+ memcpy(out, hash, sizeof(hash));
+}
+
+void sha384(
+ const uint8_t * const src,
+ const size_t src_len,
+ uint8_t * const dst
+) {
+ sha384_t ctx;
+ sha384_init(&ctx);
+ sha384_push(&ctx, src, src_len);
+ sha384_fini(&ctx, dst);
+}
diff --git a/sha2.h b/sha2.h
index 01cf08b..704fb2f 100644
--- a/sha2.h
+++ b/sha2.h
@@ -31,4 +31,32 @@ void sha224_push(sha224_t * const, const uint8_t *, size_t);
void sha224_fini(sha224_t * const, uint8_t * const);
void sha224(const uint8_t * const, const size_t, uint8_t * const);
+
+#define SHA512_HASH_SIZE 64
+
+typedef struct {
+ uint8_t buf[128];
+ size_t buf_len;
+
+ uint64_t h[8];
+
+ uint64_t num_bytes;
+} sha512_t;
+
+void sha512_init(sha512_t * const);
+void sha512_push(sha512_t * const, const uint8_t *, size_t);
+void sha512_fini(sha512_t * const, uint8_t * const);
+void sha512(const uint8_t * const, const size_t, uint8_t * const);
+
+#define SHA384_HASH_SIZE 48
+
+typedef struct {
+ sha512_t ctx;
+} sha384_t;
+
+void sha384_init(sha384_t * const);
+void sha384_push(sha384_t * const, const uint8_t *, size_t);
+void sha384_fini(sha384_t * const, uint8_t * const);
+void sha384(const uint8_t * const, const size_t, uint8_t * const);
+
#endif /* SHA2_H_ */
diff --git a/tests.c b/tests.c
index f0396ca..a308c00 100644
--- a/tests.c
+++ b/tests.c
@@ -81,14 +81,85 @@ static const struct {
},
}};
+static const struct {
+ const char * const s;
+ const uint8_t h[SHA512_HASH_SIZE];
+} SHA512_TESTS[] = {{
+ .s = "",
+ .h = {
+ 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 0xf1, 0x54, 0x28,
+ 0x50, 0xd6, 0x6d, 0x80, 0x07, 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57,
+ 0x15, 0xdc, 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, 0x47,
+ 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, 0xff, 0x83, 0x18, 0xd2,
+ 0x87, 0x7e, 0xec, 0x2f, 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a,
+ 0x81, 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e,
+ },
+}, {
+ .s = "abc",
+ .h = {
+ 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73,
+ 0x49, 0xae, 0x20, 0x41, 0x31, 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9,
+ 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 0x21,
+ 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23,
+ 0xa3, 0xfe, 0xeb, 0xbd, 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8,
+ 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f,
+ },
+}, {
+ .s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ .h = {
+ 0x20, 0x4a, 0x8f, 0xc6, 0xdd, 0xa8, 0x2f, 0x0a, 0x0c, 0xed, 0x7b,
+ 0xeb, 0x8e, 0x08, 0xa4, 0x16, 0x57, 0xc1, 0x6e, 0xf4, 0x68, 0xb2,
+ 0x28, 0xa8, 0x27, 0x9b, 0xe3, 0x31, 0xa7, 0x03, 0xc3, 0x35, 0x96,
+ 0xfd, 0x15, 0xc1, 0x3b, 0x1b, 0x07, 0xf9, 0xaa, 0x1d, 0x3b, 0xea,
+ 0x57, 0x78, 0x9c, 0xa0, 0x31, 0xad, 0x85, 0xc7, 0xa7, 0x1d, 0xd7,
+ 0x03, 0x54, 0xec, 0x63, 0x12, 0x38, 0xca, 0x34, 0x45,
+ },
+}};
+
+static const struct {
+ const char * const s;
+ const uint8_t h[SHA384_HASH_SIZE];
+} SHA384_TESTS[] = {{
+ .s = "",
+ .h = {
+ 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32,
+ 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe,
+ 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, 0x27,
+ 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1,
+ 0x48, 0x98, 0xb9, 0x5b,
+ },
+}, {
+ .s = "abc",
+ .h = {
+ 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, 0xb5, 0xa0, 0x3d,
+ 0x69, 0x9a, 0xc6, 0x50, 0x07, 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde,
+ 0xd1, 0x63, 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, 0x80,
+ 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, 0x58, 0xba, 0xec, 0xa1,
+ 0x34, 0xc8, 0x25, 0xa7,
+ },
+}, {
+ .s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ .h = {
+ 0x33, 0x91, 0xfd, 0xdd, 0xfc, 0x8d, 0xc7, 0x39, 0x37, 0x07, 0xa6,
+ 0x5b, 0x1b, 0x47, 0x09, 0x39, 0x7c, 0xf8, 0xb1, 0xd1, 0x62, 0xaf,
+ 0x05, 0xab, 0xfe, 0x8f, 0x45, 0x0d, 0xe5, 0xf3, 0x6b, 0xc6, 0xb0,
+ 0x45, 0x5a, 0x85, 0x20, 0xbc, 0x4e, 0x6f, 0x5f, 0xe9, 0x5b, 0x1f,
+ 0xe3, 0xc8, 0x45, 0x2b,
+ },
+}};
+
DEF_TEST_FUNC(256)
DEF_TEST_FUNC(224)
+DEF_TEST_FUNC(512)
+DEF_TEST_FUNC(384)
unsigned int run_tests(test_fail_cb_t on_fail) {
unsigned int r = 0;
r += run_sha256_tests(on_fail);
r += run_sha224_tests(on_fail);
+ r += run_sha512_tests(on_fail);
+ r += run_sha384_tests(on_fail);
return r;
}