diff options
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | Makefile | 30 | ||||
-rw-r--r-- | hash-main.c | 50 | ||||
-rw-r--r-- | hmac-main.c | 31 | ||||
-rw-r--r-- | hmac-sha2.c | 99 | ||||
-rw-r--r-- | hmac-sha2.h | 51 | ||||
-rw-r--r-- | main.c | 70 | ||||
-rw-r--r-- | run-tests.c | 34 |
8 files changed, 289 insertions, 80 deletions
@@ -1,2 +1,4 @@ *.o -/sha256 +/hash-sha256 +/hmac-sha256 +/run-tests @@ -1,20 +1,32 @@ CFLAGS=-std=c11 -W -Wall -Wextra -pedantic -O3 -march=native -OBJS=sha2.o main.o tests.o -APP=sha256 +TEST_OBJS=sha2.o run-tests.o tests.o hmac-sha2.o +TEST_APP=run-tests +HASH_OBJS=sha2.o hash-main.o tests.o hmac-sha2.o +HASH_APP=hash-sha256 +HMAC_OBJS=sha2.o hmac-sha2.o hmac-main.o +HMAC_APP=hmac-sha256 .PHONY=all clean -all: $(APP) +all: $(TEST_APP) $(HMAC_APP) $(HASH_APP) -$(APP): $(OBJS) - $(CC) $(CFLAGS) -o $(APP) $(OBJS) +$(TEST_APP): $(TEST_OBJS) + $(CC) $(CFLAGS) -o $(TEST_APP) $(TEST_OBJS) + +$(HASH_APP): $(HASH_OBJS) + $(CC) $(CFLAGS) -o $(HASH_APP) $(HASH_OBJS) + +$(HMAC_APP): $(HMAC_OBJS) + $(CC) $(CFLAGS) -o $(HMAC_APP) $(HMAC_OBJS) %.o: %.c $(CC) $(CFLAGS) -c $< clean: - $(RM) $(OBJS) $(APP) + $(RM) $(TEST_OBJS) $(TEST_APP) \ + $(HASH_OBJS) $(HASH_APP) \ + $(HMAC_OBJS) $(HMAC_APP) -test: $(APP) - @# ./$(APP) '' 'foobar' - @./$(APP) +test: $(TEST_APP) + @# ./$(TEST_APP) '' 'foobar' + @./$(TEST_APP) diff --git a/hash-main.c b/hash-main.c new file mode 100644 index 0000000..61a6940 --- /dev/null +++ b/hash-main.c @@ -0,0 +1,50 @@ +#include <stdio.h> // printf() +#include <string.h> // strlen() +#include "sha2.h" + +static void print_hash(const uint8_t * const hash) { + for (size_t i = 0; i < SHA256_HASH_SIZE; i++) { + printf("%02x", hash[i]); + } +} + +static void print_row( + const char * const src, + const uint8_t * const hash +) { + printf("\"%s\",", src); + print_hash(hash); + printf("\n"); +} + +static uint8_t dst[SHA256_HASH_SIZE]; +static uint8_t buf[1 << 21]; + +int main(int argc, char *argv[]) { + // if command-line parameters are given, then treat them as a + // list of files: open each file, hash it, and and print the + // result instead of running the test vectors + + for (int i = 1; i < argc; i++) { + sha256_t ctx; + sha256_init(&ctx); + + FILE *fh = fopen(argv[i], "rb"); + if (!fh) { + fprintf(stderr, "fopen(\"%s\") failed", argv[i]); + return 1; + } + + size_t len = 0; + while ((len = fread(buf, 1, sizeof(buf), fh)) > 0) { + sha256_push(&ctx, buf, len); + } + + fclose(fh); + + sha256_fini(&ctx, dst); + print_row(argv[i], dst); + } + + return 0; +} diff --git a/hmac-main.c b/hmac-main.c new file mode 100644 index 0000000..ad65d65 --- /dev/null +++ b/hmac-main.c @@ -0,0 +1,31 @@ +#include <string.h> // strlen() +#include <stdio.h> // printf() +#include "hmac-sha2.h" + +static void print_hash(const uint8_t * const hash) { + for (size_t i = 0; i < SHA256_HASH_SIZE; i++) { + printf("%02x", hash[i]); + } +} + +int main(int argc, char *argv[]) { + // check args + if (argc < 2) { + fprintf(stderr, "Usage: %s [key] [message]\n", argv[0]); + return -1; + } + + // calculate hmac + uint8_t hash[SHA256_HASH_SIZE]; + hmac_sha256( + (uint8_t *) argv[1], strlen(argv[1]), + (uint8_t *) argv[2], strlen(argv[2]), + hash + ); + + // print hash + print_hash(hash); + printf("\n"); + + return 0; +} diff --git a/hmac-sha2.c b/hmac-sha2.c new file mode 100644 index 0000000..3c168d1 --- /dev/null +++ b/hmac-sha2.c @@ -0,0 +1,99 @@ +#include "hmac-sha2.h" +#include <stdbool.h> // bool +#include <string.h> // memcpy() + +#define SHA256_PAD(val) { \ + ctx->key[0] ^ (val), ctx->key[1] ^ (val), ctx->key[2] ^ (val), \ + ctx->key[3] ^ (val), ctx->key[4] ^ (val), ctx->key[5] ^ (val), \ + ctx->key[6] ^ (val), ctx->key[7] ^ (val), ctx->key[8] ^ (val), \ + ctx->key[9] ^ (val), ctx->key[10] ^ (val), ctx->key[11] ^ (val), \ + ctx->key[12] ^ (val), ctx->key[13] ^ (val), ctx->key[14] ^ (val), \ + ctx->key[15] ^ (val), ctx->key[16] ^ (val), ctx->key[17] ^ (val), \ + ctx->key[18] ^ (val), ctx->key[19] ^ (val), ctx->key[20] ^ (val), \ + ctx->key[21] ^ (val), ctx->key[22] ^ (val), ctx->key[23] ^ (val), \ + ctx->key[24] ^ (val), ctx->key[25] ^ (val), ctx->key[26] ^ (val), \ + ctx->key[27] ^ (val), ctx->key[28] ^ (val), ctx->key[29] ^ (val), \ + ctx->key[30] ^ (val), ctx->key[31] ^ (val), ctx->key[32] ^ (val), \ + ctx->key[33] ^ (val), ctx->key[34] ^ (val), ctx->key[35] ^ (val), \ + ctx->key[36] ^ (val), ctx->key[37] ^ (val), ctx->key[38] ^ (val), \ + ctx->key[39] ^ (val), ctx->key[40] ^ (val), ctx->key[41] ^ (val), \ + ctx->key[42] ^ (val), ctx->key[43] ^ (val), ctx->key[44] ^ (val), \ + ctx->key[45] ^ (val), ctx->key[46] ^ (val), ctx->key[47] ^ (val), \ + ctx->key[48] ^ (val), ctx->key[49] ^ (val), ctx->key[50] ^ (val), \ + ctx->key[51] ^ (val), ctx->key[52] ^ (val), ctx->key[53] ^ (val), \ + ctx->key[54] ^ (val), ctx->key[55] ^ (val), ctx->key[56] ^ (val), \ + ctx->key[57] ^ (val), ctx->key[58] ^ (val), ctx->key[59] ^ (val), \ + ctx->key[60] ^ (val), ctx->key[61] ^ (val), ctx->key[62] ^ (val), \ + ctx->key[63] ^ (val), \ +} + +void hmac_sha256_init( + hmac_sha256_t * const ctx, + const uint8_t * const key, + const size_t key_len +) { + memset(ctx->key, 0, 64); + if (key_len > 64) { + uint8_t hash[SHA256_HASH_SIZE]; + sha256(key, key_len, hash); + memcpy(ctx->key, hash, sizeof(hash)); + } else { + memcpy(ctx->key, key, key_len); + } + + sha256_init(&(ctx->ctx)); + const uint8_t ipad[64] = SHA256_PAD(0x36); + + sha256_push(&(ctx->ctx), ipad, sizeof(ipad)); +} + +void hmac_sha256_push( + hmac_sha256_t * const ctx, + const uint8_t * const buf, + const size_t buf_len +) { + sha256_push(&(ctx->ctx), buf, buf_len); +} + +void hmac_sha256_fini( + hmac_sha256_t * const ctx, + uint8_t * const out +) { + uint8_t hash[SHA256_HASH_SIZE]; + sha256_fini(&(ctx->ctx), hash); + + sha256_t out_ctx; + sha256_init(&out_ctx); + + const uint8_t opad[64] = SHA256_PAD(0x5c); + sha256_push(&out_ctx, opad, sizeof(opad)); + sha256_push(&out_ctx, hash, sizeof(hash)); + sha256_fini(&out_ctx, out); +} + +void hmac_sha256( + const uint8_t * const key, + const size_t key_len, + const uint8_t * const buf, + const size_t buf_len, + uint8_t * const out +) { + hmac_sha256_t ctx; + hmac_sha256_init(&ctx, key, key_len); + hmac_sha256_push(&ctx, buf, buf_len); + hmac_sha256_fini(&ctx, out); +} + +_Bool hmac_check( + const uint8_t * const a, + const uint8_t * const b, + const size_t len +) { + uint8_t r = 0; + + for (size_t i = 0; i < len; i++) { + r |= (a[i] ^ b[i]); + } + + return !r; +} diff --git a/hmac-sha2.h b/hmac-sha2.h new file mode 100644 index 0000000..46908d2 --- /dev/null +++ b/hmac-sha2.h @@ -0,0 +1,51 @@ +#ifndef HMAC_SHA2_H_ +#define HMAC_SHA2_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include <stdint.h> // uint8_t +#include "sha2.h" + +typedef struct { + uint8_t key[64]; + sha256_t ctx; +} hmac_sha256_t; + +void hmac_sha256_init( + hmac_sha256_t * const ctx, + const uint8_t * const key, + const size_t key_len +); + +void hmac_sha256_push( + hmac_sha256_t * const ctx, + const uint8_t * const buf, + const size_t buf_len +); + +void hmac_sha256_fini( + hmac_sha256_t * const ctx, + uint8_t * const out +); + +void hmac_sha256( + const uint8_t * const key, + const size_t key_len, + const uint8_t * const buf, + const size_t buf_len, + uint8_t * const out +); + +_Bool hmac_check( + const uint8_t * const a, + const uint8_t * const b, + const size_t len +); + +#ifdef __cplusplus +}; +#endif /* __cplusplus */ + +#endif /* HMAC_SHA2_H_ */ @@ -1,70 +0,0 @@ -#include <stdio.h> // printf() -#include <string.h> // strlen() -#include "sha2.h" -#include "tests.h" - -static void print_hash(const uint8_t * const hash) { - for (size_t i = 0; i < SHA256_HASH_SIZE; i++) { - printf("%02x", hash[i]); - } -} - -static void print_row( - const char * const src, - const uint8_t * const hash -) { - printf("\"%s\",", src); - print_hash(hash); - printf("\n"); -} - -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("sha%d,\"%s\",", algo, src); - print_hash(got_hash); - printf(","); - print_hash(expected_hash); - printf("\n"); -} - -static uint8_t dst[SHA256_HASH_SIZE]; -static uint8_t buf[1 << 21]; - -int main(int argc, char *argv[]) { - if (argc > 1) { - // if command-line parameters are given, then treat them as a - // list of files: open each file, hash it, and and print the - // result instead of running the test vectors - - for (int i = 1; i < argc; i++) { - sha256_t ctx; - sha256_init(&ctx); - - FILE *fh = fopen(argv[i], "rb"); - if (!fh) { - fprintf(stderr, "fopen(\"%s\") failed", argv[i]); - return 1; - } - - size_t len = 0; - while ((len = fread(buf, 1, sizeof(buf), fh)) > 0) { - sha256_push(&ctx, buf, len); - } - - fclose(fh); - - sha256_fini(&ctx, dst); - print_row(argv[i], dst); - } - } else { - // no command-line parameters given. run internal tests - printf("algo,input,result,expected\n"); - run_tests(on_test_fail); - } - - return 0; -} diff --git a/run-tests.c b/run-tests.c new file mode 100644 index 0000000..9ba120d --- /dev/null +++ b/run-tests.c @@ -0,0 +1,34 @@ +#include <stdio.h> // printf() +#include <string.h> // strlen() +#include "sha2.h" +#include "tests.h" + +static void print_hash(const uint8_t * const hash) { + for (size_t i = 0; i < SHA256_HASH_SIZE; i++) { + printf("%02x", hash[i]); + } +} + +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("sha%d,\"%s\",", algo, src); + print_hash(got_hash); + printf(","); + print_hash(expected_hash); + printf("\n"); +} + +int main(int argc, char *argv[]) { + (void) argc; + (void) argv; + + // run internal tests + printf("algo,input,result,expected\n"); + run_tests(on_test_fail); + + return 0; +} |