From 95629acc2902541460698d1898175499500caecd Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Tue, 16 Jul 2019 21:04:10 -0400 Subject: add sha224 --- main.c | 5 ++-- sha256.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++------------ sha256.h | 11 ++++++++ tests.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++---------- tests.h | 11 ++++++-- 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 // 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 // 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 + +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_ */ -- cgit v1.2.3