From f15a0a5cf2b0d4cf8e3eb509dde0b2a0acf9d5ab Mon Sep 17 00:00:00 2001 From: lohhiiccc <96543753+lohhiiccc@users.noreply.github.com> Date: Thu, 30 Apr 2026 20:55:05 +0200 Subject: [PATCH] feat: sha256 --- include/digest_update.h | 20 ++++++ include/sha256.h | 2 + include/sha256_internal.h | 8 +++ src/Makefile.am | 2 + src/md5/md5_update.c | 19 +---- src/sha256/sha256.c | 20 ++++++ src/sha256/sha256_compress.c | 130 +++++++++++++++++++++++++++++++++++ src/sha256/sha256_final.c | 55 ++++++++++++++- src/sha256/sha256_init.c | 15 +++- src/sha256/sha256_update.c | 9 +-- 10 files changed, 252 insertions(+), 28 deletions(-) create mode 100644 include/digest_update.h create mode 100644 include/sha256_internal.h create mode 100644 src/sha256/sha256.c create mode 100644 src/sha256/sha256_compress.c diff --git a/include/digest_update.h b/include/digest_update.h new file mode 100644 index 0000000..b197b9d --- /dev/null +++ b/include/digest_update.h @@ -0,0 +1,20 @@ +#ifndef DIGEST_UPDATE_H +#define DIGEST_UPDATE_H + +#include +#include + +#define IMPL_DIGEST_UPDATE(algo, block_mask, compress_fn) \ +void \ +algo##_update(void *ctx, const uint8_t *data, size_t len) \ +{ \ + struct algo##_ctx *local_ctx = ctx; \ + for (size_t i = 0; i < len; ++i) { \ + local_ctx->buf[(local_ctx->count & (block_mask))] = data[i]; \ + ++local_ctx->count; \ + if (0 == (local_ctx->count & (block_mask))) \ + compress_fn(local_ctx, local_ctx->buf); \ + } \ +} + +#endif diff --git a/include/sha256.h b/include/sha256.h index 86b9f61..2c08e38 100644 --- a/include/sha256.h +++ b/include/sha256.h @@ -15,4 +15,6 @@ void sha256_init(void *ctx); void sha256_update(void *ctx, const uint8_t *data, size_t len); void sha256_final(void *ctx, uint8_t *out); +extern const uint32_t g_sha256_K[64]; + #endif diff --git a/include/sha256_internal.h b/include/sha256_internal.h new file mode 100644 index 0000000..a07fa81 --- /dev/null +++ b/include/sha256_internal.h @@ -0,0 +1,8 @@ +#ifndef SHA256_INTERNAL_H +#define SHA256_INTERNAL_H + +#include "sha256.h" + +void sha256_compress(struct sha256_ctx *ctx, const uint8_t block[64]); + +#endif diff --git a/src/Makefile.am b/src/Makefile.am index ca5ff1c..4babaa9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,7 +6,9 @@ libft_ssl_la_SOURCES = libft_ssl.c \ md5/md5_compress.c \ md5/md5_update.c \ md5/md5_final.c \ + sha256/sha256.c \ sha256/sha256_init.c \ + sha256/sha256_compress.c \ sha256/sha256_update.c \ sha256/sha256_final.c diff --git a/src/md5/md5_update.c b/src/md5/md5_update.c index d619798..fa345bd 100644 --- a/src/md5/md5_update.c +++ b/src/md5/md5_update.c @@ -1,19 +1,4 @@ -#include "md5.h" #include "md5_internal.h" -#include -#include +#include "digest_update.h" -void md5_update(void *ctx, const uint8_t *data, size_t len) -{ - struct md5_ctx *local_ctx = ctx; - - - for (size_t i = 0; i < len; ++i) - { - local_ctx->buf[(local_ctx->count & 63)] = data[i]; - ++local_ctx->count; - if (0 == (local_ctx->count & 63)) - md5_compress(local_ctx, local_ctx->buf); - } - -} +IMPL_DIGEST_UPDATE(md5, 63, md5_compress) diff --git a/src/sha256/sha256.c b/src/sha256/sha256.c new file mode 100644 index 0000000..8298db6 --- /dev/null +++ b/src/sha256/sha256.c @@ -0,0 +1,20 @@ +#include "sha256.h" + +const uint32_t g_sha256_K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, +}; diff --git a/src/sha256/sha256_compress.c b/src/sha256/sha256_compress.c new file mode 100644 index 0000000..7c3e4c7 --- /dev/null +++ b/src/sha256/sha256_compress.c @@ -0,0 +1,130 @@ +#include "sha256.h" +#include "sha256_internal.h" +#include + +/* Forward declarations */ +static uint32_t sha256_rotr(uint32_t x, uint32_t n); +static uint32_t sha256_ch(uint32_t e, uint32_t f, uint32_t g); +static uint32_t sha256_maj(uint32_t a, uint32_t b, uint32_t c); +static uint32_t sha256_Sigma0(uint32_t x); +static uint32_t sha256_Sigma1(uint32_t x); +static uint32_t sha256_sigma0(uint32_t x); +static uint32_t sha256_sigma1(uint32_t x); +static void sha256_decode(const uint8_t block[64], uint32_t w[16]); +static void sha256_schedule(uint32_t w[64], const uint8_t block[64]); +static void sha256_rounds(uint32_t state[8], const uint32_t w[64]); +/* ------------- */ + +void +sha256_compress(struct sha256_ctx *ctx, const uint8_t block[64]) +{ + uint32_t w[64]; + + sha256_schedule(w, block); + sha256_rounds(ctx->state, w); +} + +static void +sha256_schedule(uint32_t w[64], const uint8_t block[64]) +{ + sha256_decode(block, w); + + for (uint8_t i = 16; i < 64; ++i) + { + w[i] = sha256_sigma1(w[i - 2]); + w[i] += w[i - 7]; + w[i] += sha256_sigma0(w[i - 15]); + w[i] += w[i - 16]; + } +} + +static void +sha256_rounds(uint32_t state[8], const uint32_t w[64]) +{ + uint32_t a = state[0]; + uint32_t b = state[1]; + uint32_t c = state[2]; + uint32_t d = state[3]; + uint32_t e = state[4]; + uint32_t f = state[5]; + uint32_t g = state[6]; + uint32_t h = state[7]; + + for (uint8_t i = 0; i < 64; ++i) + { + uint32_t t1; + uint32_t t2; + + t1 = h + sha256_Sigma1(e) + sha256_ch(e, f, g) + g_sha256_K[i] + w[i]; + t2 = sha256_Sigma0(a) + sha256_maj(a, b, c); + + h = g; g = f; f = e; e = d + t1; + d = c; c = b; b = a; a = t1 + t2; + } + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; +} + +/* Decode 64 bytes into 16 x uint32_t words (big-endian) */ +static void +sha256_decode(const uint8_t block[64], uint32_t w[16]) +{ + for (uint8_t i = 0; i < 16; ++i) + { + const uint8_t i4 = i * 4; + + w[i] = (uint32_t)block[i4 + 0] << 24 + | (uint32_t)block[i4 + 1] << 16 + | (uint32_t)block[i4 + 2] << 8 + | (uint32_t)block[i4 + 3] << 0; + } +} + +static uint32_t +sha256_rotr(uint32_t x, uint32_t n) +{ + return (x >> n) | (x << (32u - n)); +} + +static uint32_t +sha256_ch(uint32_t e, uint32_t f, uint32_t g) +{ + return (e & f) ^ (~e & g); +} + +static uint32_t +sha256_maj(uint32_t a, uint32_t b, uint32_t c) +{ + return (a & b) ^ (a & c) ^ (b & c); +} + +static uint32_t +sha256_Sigma0(uint32_t x) +{ + return sha256_rotr(x, 2) ^ sha256_rotr(x, 13) ^ sha256_rotr(x, 22); +} + +static uint32_t +sha256_Sigma1(uint32_t x) +{ + return sha256_rotr(x, 6) ^ sha256_rotr(x, 11) ^ sha256_rotr(x, 25); +} + +static uint32_t +sha256_sigma0(uint32_t x) +{ + return sha256_rotr(x, 7) ^ sha256_rotr(x, 18) ^ (x >> 3); +} + +static uint32_t +sha256_sigma1(uint32_t x) +{ + return sha256_rotr(x, 17) ^ sha256_rotr(x, 19) ^ (x >> 10); +} diff --git a/src/sha256/sha256_final.c b/src/sha256/sha256_final.c index a51dc7c..342230b 100644 --- a/src/sha256/sha256_final.c +++ b/src/sha256/sha256_final.c @@ -1,6 +1,55 @@ -#include "compiler.h" -#include "sha256.h" +#include "sha256_internal.h" -void sha256_final(__unused void *ctx, __unused uint8_t *out) +/* Forward declarations */ +static void sha256_pad(struct sha256_ctx *ctx); +static inline void sha256_write_len(struct sha256_ctx *ctx, uint64_t bitlen); +static void sha256_encode(const struct sha256_ctx *ctx, uint8_t out[32]); +/* ---------------- */ + +void sha256_final(void *ctx, uint8_t *out) { + struct sha256_ctx *local_ctx = ctx; + + sha256_pad(local_ctx); + sha256_encode(local_ctx, out); +} + +static void +sha256_pad(struct sha256_ctx *ctx) +{ + uint64_t bitlen = ctx->count * 8; + + ctx->buf[ctx->count++ & 63] = 0x80; + if ((ctx->count & 63) > 56) + { + while ((ctx->count & 63) != 0) + ctx->buf[ctx->count++ & 63] = 0x00; + sha256_compress(ctx, ctx->buf); + } + while ((ctx->count & 63) < 56) + ctx->buf[ctx->count++ & 63] = 0x00; + sha256_write_len(ctx, bitlen); + sha256_compress(ctx, ctx->buf); +} + +static inline void +sha256_write_len(struct sha256_ctx *ctx, uint64_t bitlen) +{ + for (uint8_t i = 0; i < 8; ++i) + ctx->buf[56 + i] = (uint8_t)(bitlen >> (56 - 8 * i)); +} + +static void +sha256_encode(const struct sha256_ctx *ctx, uint8_t out[32]) +{ + for (uint8_t i = 0; i < 8; ++i) + { + const uint8_t i4 = i * 4; + uint32_t v = ctx->state[i]; + + out[i4 + 0] = (uint8_t)(v >> 24); + out[i4 + 1] = (uint8_t)(v >> 16); + out[i4 + 2] = (uint8_t)(v >> 8); + out[i4 + 3] = (uint8_t)(v >> 0); + } } diff --git a/src/sha256/sha256_init.c b/src/sha256/sha256_init.c index 6cd71ea..e59e2ae 100644 --- a/src/sha256/sha256_init.c +++ b/src/sha256/sha256_init.c @@ -1,6 +1,17 @@ -#include "compiler.h" #include "sha256.h" -void sha256_init(__unused void *ctx) +void sha256_init(void *ctx) { + struct sha256_ctx *local_ctx = ctx; + + local_ctx->state[0] = 0x6a09e667; + local_ctx->state[1] = 0xbb67ae85; + local_ctx->state[2] = 0x3c6ef372; + local_ctx->state[3] = 0xa54ff53a; + local_ctx->state[4] = 0x510e527f; + local_ctx->state[5] = 0x9b05688c; + local_ctx->state[6] = 0x1f83d9ab; + local_ctx->state[7] = 0x5be0cd19; + + local_ctx->count = 0; } diff --git a/src/sha256/sha256_update.c b/src/sha256/sha256_update.c index 7b1cc60..3860c5d 100644 --- a/src/sha256/sha256_update.c +++ b/src/sha256/sha256_update.c @@ -1,7 +1,4 @@ -#include "compiler.h" -#include "sha256.h" +#include "sha256_internal.h" +#include "digest_update.h" -void sha256_update(__unused void *ctx, __unused const uint8_t *data, - __unused size_t len) -{ -} +IMPL_DIGEST_UPDATE(sha256, 63, sha256_compress)