aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--Makefile30
-rw-r--r--hash-main.c50
-rw-r--r--hmac-main.c31
-rw-r--r--hmac-sha2.c99
-rw-r--r--hmac-sha2.h51
-rw-r--r--main.c70
-rw-r--r--run-tests.c34
8 files changed, 289 insertions, 80 deletions
diff --git a/.gitignore b/.gitignore
index 5a3dbb3..bf6f583 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
*.o
-/sha256
+/hash-sha256
+/hmac-sha256
+/run-tests
diff --git a/Makefile b/Makefile
index 9558fc9..faa1541 100644
--- a/Makefile
+++ b/Makefile
@@ -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_ */
diff --git a/main.c b/main.c
deleted file mode 100644
index a5c14da..0000000
--- a/main.c
+++ /dev/null
@@ -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;
+}