commit bb9fdf70159b23a9335e93fc7ee3717e53e58c1e
parent 4325939f19827b660d38857434eb254e4e9653c4
Author: MikoĊaj Lenczewski <mikolaj@lenczewski.org>
Date: Wed, 16 Sep 2026 14:57:12 +0100
Add sha224 and sha512/224 implementations
Diffstat:
10 files changed, 207 insertions(+), 10 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,5 +1,4 @@
bin/
-test/
**/.*.swp
imgui.ini
diff --git a/build.sh b/build.sh
@@ -5,11 +5,11 @@ set -ex
CC="${CC:-clang}"
FLAGS="-std=c11 -O0 -g3 -Wall -Wextra -Wno-unused-parameter -Wno-format"
-mkdir -p bin test
+mkdir -p bin
-for src in test-*.c; do
- cc -o test/$(basename -s .c $src) $src $FLAGS
+for src in test/*.c; do
+ $CC -o bin/$(basename -s .c $src) $src $FLAGS -I.
done
-cc -o bin/tls_client tls_client.c $FLAGS
-cc -o bin/tls_server tls_server.c $FLAGS
+$CC -o bin/tls_client tls_client.c $FLAGS
+$CC -o bin/tls_server tls_server.c $FLAGS
diff --git a/sha.c b/sha.c
@@ -193,7 +193,48 @@ sha256(void const *buf, size_t len, unsigned char digest[static SHA256_DIGEST_SI
memcpy(digest, ctx.digest, SHA256_DIGEST_SIZE);
}
-// sha 512
+// sha224
+// ===========================================================================
+
+void
+sha224_init(struct sha256_ctx *ctx)
+{
+ memset(ctx, 0, sizeof *ctx);
+
+ ctx->digest[0] = 0xc1059ed8;
+ ctx->digest[1] = 0x367cd507;
+ ctx->digest[2] = 0x3070dd17;
+ ctx->digest[3] = 0xf70e5939;
+ ctx->digest[4] = 0xffc00b31;
+ ctx->digest[5] = 0x68581511;
+ ctx->digest[6] = 0x64f98fa7;
+ ctx->digest[7] = 0xbefa4fa4;
+}
+
+void
+sha224_push(struct sha256_ctx *ctx, void const *buf, size_t len)
+{
+ sha256_push(ctx, buf, len);
+}
+
+void
+sha224_dgst(struct sha256_ctx *ctx)
+{
+ sha256_dgst(ctx);
+}
+
+void
+sha224(void const *buf, size_t len, unsigned char digest[static SHA224_DIGEST_SIZE])
+{
+ struct sha256_ctx ctx;
+ sha224_init(&ctx);
+ sha224_push(&ctx, buf, len);
+ sha224_dgst(&ctx);
+
+ memcpy(digest, ctx.digest, SHA224_DIGEST_SIZE);
+}
+
+// sha512
// ===========================================================================
void
@@ -343,12 +384,14 @@ sha512(void const *buf, size_t len, unsigned char digest[static SHA512_DIGEST_SI
memcpy(digest, ctx.digest, SHA512_DIGEST_SIZE);
}
-// sha 384
+// sha384
// ===========================================================================
void
sha384_init(struct sha512_ctx *ctx)
{
+ memset(ctx, 0, sizeof *ctx);
+
ctx->digest[0] = 0xcbbb9d5dc1059ed8;
ctx->digest[1] = 0x629a292a367cd507;
ctx->digest[2] = 0x9159015a3070dd17;
@@ -382,12 +425,55 @@ sha384(void const *buf, size_t len, unsigned char digest[static SHA384_DIGEST_SI
memcpy(digest, ctx.digest, SHA384_DIGEST_SIZE);
}
+// sha512/224
+// ===========================================================================
+
+void
+sha512_224_init(struct sha512_ctx *ctx)
+{
+ memset(ctx, 0, sizeof *ctx);
+
+ ctx->digest[0] = 0x8c3d37c819544da2;
+ ctx->digest[1] = 0x73e1996689dcd4d6;
+ ctx->digest[2] = 0x1dfab7ae32ff9c82;
+ ctx->digest[3] = 0x679dd514582f9fcf;
+ ctx->digest[4] = 0x0f6d2b697bd44da8;
+ ctx->digest[5] = 0x77e36f7304c48942;
+ ctx->digest[6] = 0x3f9d85a86a1d36c8;
+ ctx->digest[7] = 0x1112e6ad91d692a1;
+}
+
+void
+sha512_224_push(struct sha512_ctx *ctx, void const *buf, size_t len)
+{
+ sha512_push(ctx, buf, len);
+}
+
+void
+sha512_224_dgst(struct sha512_ctx *ctx)
+{
+ sha512_dgst(ctx);
+}
+
+void
+sha512_224(void const *buf, size_t len, unsigned char digest[static SHA512_224_DIGEST_SIZE])
+{
+ struct sha512_ctx ctx;
+ sha512_224_init(&ctx);
+ sha512_224_push(&ctx, buf, len);
+ sha512_224_dgst(&ctx);
+
+ memcpy(digest, ctx.digest, SHA512_224_DIGEST_SIZE);
+}
+
// sha512/256
// ===========================================================================
void
sha512_256_init(struct sha512_ctx *ctx)
{
+ memset(ctx, 0, sizeof *ctx);
+
ctx->digest[0] = 0x22312194fc2bf72c;
ctx->digest[1] = 0x9f555fa3c84c64c2;
ctx->digest[2] = 0x2393b86b6f53b151;
diff --git a/sha.h b/sha.h
@@ -43,6 +43,11 @@ struct sha256_ctx {
size_t ctr;
};
+// sha224 re-usees the sha256 definitions
+#define SHA224_DIGEST_BITS 224
+#define SHA224_DIGEST_WORDS (SHA224_DIGEST_BITS / SHA256_WORD_BITS)
+#define SHA224_DIGEST_SIZE (SHA224_DIGEST_BITS / CHAR_BIT)
+
typedef uint64_t sha512_word_t;
#define SHA512_WORD_BITS 64
@@ -73,6 +78,11 @@ struct sha512_ctx {
#define SHA384_DIGEST_WORDS (SHA384_DIGEST_BITS / SHA512_WORD_BITS)
#define SHA384_DIGEST_SIZE (SHA384_DIGEST_BITS / CHAR_BIT)
+// sha512/224 re-uses the sha512 definitions
+#define SHA512_224_DIGEST_BITS 224
+#define SHA512_224_DIGEST_WORDS (SHA512_224_DIGEST_BITS / SHA512_WORD_BITS)
+#define SHA512_224_DIGEST_SIZE (SHA512_224_DIGEST_BITS / CHAR_BIT)
+
// sha512/256 re-uses the sha512 definitions
#define SHA512_256_DIGEST_BITS 256
#define SHA512_256_DIGEST_WORDS (SHA512_256_DIGEST_BITS / SHA512_WORD_BITS)
@@ -116,7 +126,22 @@ sha256_dgst(struct sha256_ctx *ctx);
void
sha256(void const *buf, size_t len, unsigned char digest[static SHA256_DIGEST_SIZE]);
-// sha 512
+// sha224
+// ===========================================================================
+
+void
+sha224_init(struct sha256_ctx *ctx);
+
+void
+sha224_push(struct sha256_ctx *ctx, void const *buf, size_t len);
+
+void
+sha224_dgst(struct sha256_ctx *ctx);
+
+void
+sha224(void const *buf, size_t len, unsigned char digest[static SHA224_DIGEST_SIZE]);
+
+// sha512
// ===========================================================================
void
@@ -131,7 +156,7 @@ sha512_dgst(struct sha512_ctx *ctx);
void
sha512(void const *buf, size_t len, unsigned char digest[static SHA512_DIGEST_SIZE]);
-// sha 384
+// sha384
// ===========================================================================
void
@@ -146,6 +171,21 @@ sha384_dgst(struct sha512_ctx *ctx);
void
sha384(void const *buf, size_t len, unsigned char digest[static SHA384_DIGEST_SIZE]);
+// sha512/224
+// ===========================================================================
+
+void
+sha512_224_init(struct sha512_ctx *ctx);
+
+void
+sha512_224_push(struct sha512_ctx *ctx, void const *buf, size_t len);
+
+void
+sha512_224_dgst(struct sha512_ctx *ctx);
+
+void
+sha512_224(void const *buf, size_t len, unsigned char digest[static SHA512_224_DIGEST_SIZE]);
+
// sha512/256
// ===========================================================================
diff --git a/test/test-sha224.c b/test/test-sha224.c
@@ -0,0 +1,36 @@
+#include "sha.h"
+#include <stdio.h>
+
+int
+main(void)
+{
+ char msg[] = "abc";
+
+ uint8_t dgst[SHA224_DIGEST_SIZE];
+ sha224(msg, strlen(msg), dgst);
+
+ uint8_t expected[SHA224_DIGEST_SIZE] = {
+ 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,
+ };
+
+ printf("msg: \"%.*s\" (%lu bytes)\n", sizeof msg, msg, strlen(msg));
+
+ printf("dgst: ");
+ for (size_t i = 0; i < sizeof dgst; i++) {
+ printf("%.2x", dgst[i]);
+ }
+ printf("\n");
+
+ printf("exp.: ");
+ for (size_t i = 0; i < sizeof expected; i++) {
+ printf("%.2x", expected[i]);
+ }
+ printf("\n");
+
+ return memcmp(expected, dgst, SHA224_DIGEST_SIZE);
+}
+
+#include "sha.c"
diff --git a/test-sha256.c b/test/test-sha256.c
diff --git a/test-sha384.c b/test/test-sha384.c
diff --git a/test/test-sha512-224.c b/test/test-sha512-224.c
@@ -0,0 +1,36 @@
+#include "sha.h"
+#include <stdio.h>
+
+int
+main(void)
+{
+ char msg[] = "abc";
+
+ uint8_t dgst[SHA512_224_DIGEST_SIZE];
+ sha512_224(msg, strlen(msg), dgst);
+
+ uint8_t expected[SHA512_224_DIGEST_SIZE] = {
+ 0x46, 0x34, 0x27, 0x0f, 0x70, 0x7b, 0x6a, 0x54,
+ 0xda, 0xae, 0x75, 0x30, 0x46, 0x08, 0x42, 0xe2,
+ 0x0e, 0x37, 0xed, 0x26, 0x5c, 0xee, 0xe9, 0xa4,
+ 0x3e, 0x89, 0x24, 0xaa,
+ };
+
+ printf("msg: \"%.*s\" (%lu bytes)\n", sizeof msg, msg, strlen(msg));
+
+ printf("dgst: ");
+ for (size_t i = 0; i < sizeof dgst; i++) {
+ printf("%.2x", dgst[i]);
+ }
+ printf("\n");
+
+ printf("exp.: ");
+ for (size_t i = 0; i < sizeof expected; i++) {
+ printf("%.2x", expected[i]);
+ }
+ printf("\n");
+
+ return memcmp(expected, dgst, SHA512_224_DIGEST_SIZE);
+}
+
+#include "sha.c"
diff --git a/test-sha512-256.c b/test/test-sha512-256.c
diff --git a/test-sha512.c b/test/test-sha512.c