aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2019-07-16 21:04:10 -0400
committerPaul Duncan <pabs@pablotron.org>2019-07-16 21:04:10 -0400
commit95629acc2902541460698d1898175499500caecd (patch)
treee5ed5bb6f888617cee6315c8248546fef22197fd
parentae8484372cbbf0bad041f3bd9b11c18d9cf37be7 (diff)
downloadsha2-95629acc2902541460698d1898175499500caecd.tar.bz2
sha2-95629acc2902541460698d1898175499500caecd.zip
add sha224
-rw-r--r--main.c5
-rw-r--r--sha256.c94
-rw-r--r--sha256.h11
-rw-r--r--tests.c86
-rw-r--r--tests.h11
5 files changed, 172 insertions, 35 deletions
diff --git a/main.c b/main.c
index 7c795ef..136a363 100644
--- a/main.c
+++ b/main.c
@@ -19,11 +19,12 @@ static void print_row(
}
static void on_test_fail(
+ const int algo,
const char * const src,
const uint8_t * const got_hash,
const uint8_t * const expected_hash
) {
- printf("\"%s\",", src);
+ printf("sha%d,\"%s\",", algo, src);
print_hash(got_hash);
printf(",");
print_hash(expected_hash);
@@ -61,7 +62,7 @@ int main(int argc, char *argv[]) {
}
} else {
// no command-line parameters given. run internal tests
- printf("input,result,expected\n");
+ printf("algo,input,result,expected\n");
run_tests(on_test_fail);
}
diff --git a/sha256.c b/sha256.c
index 1391466..a17cd3e 100644
--- a/sha256.c
+++ b/sha256.c
@@ -1,10 +1,18 @@
#include "sha256.h"
#include <string.h> // memcpy
-// initial hash values
+// extract bytes from uint32_t
+// (used in sha256_fini() and sha224_fini())
+#define WB(ctx, i) \
+ ((ctx)->h[i] >> 24) & 0xff, \
+ ((ctx)->h[i] >> 16) & 0xff, \
+ ((ctx)->h[i] >> 8) & 0xff, \
+ ((ctx)->h[i]) & 0xff
+
+// sha256 initial hash values
// (first 32 bits of the fractional parts of the square roots of the
// first 8 primes 2..19):
-static const uint32_t H[8] = {
+static const uint32_t SHA256_INIT[8] = {
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
};
@@ -38,7 +46,7 @@ rr(const uint32_t v, const size_t n) {
void sha256_init(sha256_t * const ctx) {
ctx->buf_len = 0;
ctx->num_bytes = 0;
- memcpy(ctx->h, H, sizeof(H));
+ memcpy(ctx->h, SHA256_INIT, sizeof(SHA256_INIT));
}
// WI: decode buffer data as 32-bit words (used for the first 16 words)
@@ -139,7 +147,7 @@ sha256_block(sha256_t * const ctx) {
// S0 := (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22)
// maj := (a and b) xor (a and c) xor (b and c)
// temp2 := S0 + maj
- //
+ //
// h := g
// g := f
// f := e
@@ -242,7 +250,7 @@ sha256_push_u64(
sha256_t * const ctx,
const uint64_t val
) {
- const uint8_t buf[8] = {
+ const uint8_t buf[8] = {
((val >> 56) & 0xff),
((val >> 48) & 0xff),
((val >> 40) & 0xff),
@@ -258,22 +266,16 @@ sha256_push_u64(
// end of stream padding
static const uint8_t PADDING[65] = {
- 128,
+ 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,
};
-#define WB(ctx, i) \
- ((ctx)->h[i] >> 24) & 0xff, \
- ((ctx)->h[i] >> 16) & 0xff, \
- ((ctx)->h[i] >> 8) & 0xff, \
- ((ctx)->h[i]) & 0xff
-
-void sha256_fini(
- sha256_t * const ctx,
- uint8_t * const out
+static void
+sha256_push_footer(
+ sha256_t * const ctx
) {
const uint64_t num_bytes = ctx->num_bytes;
const size_t pad_len = (65 - ((num_bytes + 1 + 8) % 64));
@@ -283,6 +285,14 @@ void sha256_fini(
// push length (in bits)
sha256_push_u64(ctx, num_bytes * 8);
+}
+
+void sha256_fini(
+ sha256_t * const ctx,
+ uint8_t * const out
+) {
+ // push footer
+ sha256_push_footer(ctx);
// extract hash
const uint8_t hash[32] = {
@@ -293,8 +303,6 @@ void sha256_fini(
memcpy(out, hash, sizeof(hash));
}
-#undef WB
-
void sha256(
const uint8_t * const src,
const size_t src_len,
@@ -305,3 +313,55 @@ void sha256(
sha256_push(&ctx, src, src_len);
sha256_fini(&ctx, dst);
}
+
+// sha224 initial hash values
+// (the second 32 bits of the fractional parts of the square roots of
+// the 9th through 16th primes 23..53)
+static const uint32_t SHA224_INIT[8] = {
+ 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
+ 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
+};
+
+void sha224_init(sha224_t * const ctx) {
+ ctx->ctx.buf_len = 0;
+ ctx->ctx.num_bytes = 0;
+ memcpy(ctx->ctx.h, SHA224_INIT, sizeof(SHA224_INIT));
+}
+
+void sha224_push(
+ sha224_t * const sha224_ctx,
+ const uint8_t * const src,
+ const size_t src_len
+) {
+ sha256_t * const ctx = (sha256_t * const) sha224_ctx;
+ sha256_push(ctx, src, src_len);
+}
+
+void sha224_fini(
+ sha224_t * const sha224_ctx,
+ uint8_t * const out
+) {
+ sha256_t * const ctx = (sha256_t * const) sha224_ctx;
+
+ // push footer
+ sha256_push_footer(ctx);
+
+ // 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),
+ };
+
+ memcpy(out, hash, sizeof(hash));
+}
+
+void sha224(
+ const uint8_t * const src,
+ const size_t src_len,
+ uint8_t * const dst
+) {
+ sha224_t ctx;
+ sha224_init(&ctx);
+ sha224_push(&ctx, src, src_len);
+ sha224_fini(&ctx, dst);
+}
diff --git a/sha256.h b/sha256.h
index e805293..01cf08b 100644
--- a/sha256.h
+++ b/sha256.h
@@ -20,4 +20,15 @@ void sha256_push(sha256_t * const, const uint8_t *, size_t);
void sha256_fini(sha256_t * const, uint8_t * const);
void sha256(const uint8_t * const, const size_t, uint8_t * const);
+#define SHA224_HASH_SIZE 28
+
+typedef struct {
+ sha256_t ctx;
+} sha224_t;
+
+void sha224_init(sha224_t * const);
+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);
+
#endif /* SHA2_H_ */
diff --git a/tests.c b/tests.c
index a71bd7b..a5bbae5 100644
--- a/tests.c
+++ b/tests.c
@@ -1,24 +1,25 @@
#include <string.h> // memcmp()
#include "sha256.h"
+#include "tests.h"
static const struct {
const char * const s;
- const uint8_t h[32];
-} TESTS[] = {{
+ const uint8_t h[SHA256_HASH_SIZE];
+} SHA256_TESTS[] = {{
.s = "",
.h = {
0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
- 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
+ 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
},
}, {
.s = "abc",
- .h = {
+ .h = {
0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
- 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,
+ 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,
},
}, {
.s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
@@ -26,25 +27,82 @@ static const struct {
0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
- 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,
+ 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,
},
}};
-#define NUM_TESTS (sizeof(TESTS) / sizeof(TESTS[0]))
+#define NUM_SHA256_TESTS (sizeof(SHA256_TESTS) / sizeof(SHA256_TESTS[0]))
-unsigned int run_tests(
- void (*on_fail)(const char * const, const uint8_t *, const uint8_t *)
-) {
+static unsigned int
+run_sha256_tests(test_fail_cb_t on_fail) {
+ unsigned int r = 0;
uint8_t hash[SHA256_HASH_SIZE];
+
+ for (size_t i = 0; i < NUM_SHA256_TESTS; i++) {
+ const char * const s = SHA256_TESTS[i].s;
+ sha256((const uint8_t *) s, strlen(s), hash);
+ if (memcmp(hash, SHA256_TESTS[i].h, sizeof(hash))) {
+ on_fail(256, s, hash, SHA256_TESTS[i].h);
+ r++;
+ }
+ }
+
+ return r;
+}
+
+static const struct {
+ const char * const s;
+ const uint8_t h[SHA224_HASH_SIZE];
+} SHA224_TESTS[] = {{
+ .s = "",
+ .h = {
+ 0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9,
+ 0x47, 0x61, 0x02, 0xbb, 0x28, 0x82, 0x34, 0xc4,
+ 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a,
+ 0xc5, 0xb3, 0xe4, 0x2f,
+ },
+}, {
+ .s = "abc",
+ .h = {
+ 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8, 0x22,
+ 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2, 0x55, 0xb3,
+ 0x2a, 0xad, 0xbc, 0xe4, 0xbd, 0xa0, 0xb3, 0xf7,
+ 0xe3, 0x6c, 0x9d, 0xa7,
+ },
+}, {
+ .s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ .h = {
+ 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76, 0xcc,
+ 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89, 0x01, 0x50,
+ 0xb0, 0xc6, 0x45, 0x5c, 0xb4, 0xf5, 0x8b, 0x19,
+ 0x52, 0x52, 0x25, 0x25,
+ },
+}};
+
+#define NUM_SHA224_TESTS (sizeof(SHA224_TESTS) / sizeof(SHA224_TESTS[0]))
+
+static unsigned int
+run_sha224_tests(test_fail_cb_t on_fail) {
unsigned int r = 0;
+ uint8_t hash[SHA224_HASH_SIZE];
- for (size_t i = 0; i < NUM_TESTS; i++) {
- sha256((const uint8_t *) TESTS[i].s, strlen(TESTS[i].s), hash);
- if (memcmp(hash, TESTS[i].h, sizeof(hash))) {
- on_fail(TESTS[i].s, hash, TESTS[i].h);
+ for (size_t i = 0; i < NUM_SHA224_TESTS; i++) {
+ const char * const s = SHA224_TESTS[i].s;
+ sha224((const uint8_t *) s, strlen(s), hash);
+ if (memcmp(hash, SHA224_TESTS[i].h, sizeof(hash))) {
+ on_fail(224, s, hash, SHA224_TESTS[i].h);
r++;
}
}
return r;
}
+
+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);
+
+ return r;
+}
diff --git a/tests.h b/tests.h
index 96b8357..339d565 100644
--- a/tests.h
+++ b/tests.h
@@ -1,8 +1,15 @@
#ifndef TESTS_H_
#define TESTS_H_
-unsigned int run_tests(
- void (*on_fail)(const char * const, const uint8_t *, const uint8_t *)
+#include <stdint.h>
+
+typedef void (*test_fail_cb_t)(
+ const int,
+ const char * const,
+ const uint8_t *,
+ const uint8_t *
);
+unsigned int run_tests(test_fail_cb_t);
+
#endif /* TESTS_H_ */