diff --git a/CMakeLists.txt b/CMakeLists.txt index 5691f06..fa71db9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,7 @@ set(AMDUAT_ASL_SRCS set(AMDUAT_HASH_ASL1_SRCS src/near_core/hash/asl1.c + src/near_core/hash/sha256.c ) set(AMDUAT_ENC_SRCS diff --git a/src/near_core/hash/asl1.c b/src/near_core/hash/asl1.c index c1c0047..f14d3e5 100644 --- a/src/near_core/hash/asl1.c +++ b/src/near_core/hash/asl1.c @@ -1,8 +1,13 @@ #include "amduat/hash/asl1.h" +#include "sha256.h" + static amduat_hash_asl1_desc_t g_hash_asl1_descs[] = { {0x0000, NULL, 0, {NULL, NULL}}, - {AMDUAT_HASH_ASL1_ID_SHA256, "HASH-ASL1-256", 32, {NULL, NULL}}, + {AMDUAT_HASH_ASL1_ID_SHA256, + "HASH-ASL1-256", + 32, + {amduat_hash_asl1_sha256_digest, NULL}}, {0x0002, "HASH-ASL1-512", 64, {NULL, NULL}}, {0x8001, "HASH-ASL1-PQ1", 0, {NULL, NULL}}}; diff --git a/src/near_core/hash/sha256.c b/src/near_core/hash/sha256.c new file mode 100644 index 0000000..0712e05 --- /dev/null +++ b/src/near_core/hash/sha256.c @@ -0,0 +1,225 @@ +#include "sha256.h" + +#include + +typedef struct { + uint32_t state[8]; + uint64_t bitlen; + uint8_t buffer[64]; + size_t buffer_len; +} amduat_sha256_ctx_t; + +static uint32_t amduat_sha256_rotr(uint32_t v, uint32_t n) { + return (v >> n) | (v << (32u - n)); +} + +static uint32_t amduat_sha256_ch(uint32_t x, uint32_t y, uint32_t z) { + return (x & y) ^ (~x & z); +} + +static uint32_t amduat_sha256_maj(uint32_t x, uint32_t y, uint32_t z) { + return (x & y) ^ (x & z) ^ (y & z); +} + +static uint32_t amduat_sha256_big_sigma0(uint32_t x) { + return amduat_sha256_rotr(x, 2u) ^ amduat_sha256_rotr(x, 13u) ^ + amduat_sha256_rotr(x, 22u); +} + +static uint32_t amduat_sha256_big_sigma1(uint32_t x) { + return amduat_sha256_rotr(x, 6u) ^ amduat_sha256_rotr(x, 11u) ^ + amduat_sha256_rotr(x, 25u); +} + +static uint32_t amduat_sha256_small_sigma0(uint32_t x) { + return amduat_sha256_rotr(x, 7u) ^ amduat_sha256_rotr(x, 18u) ^ (x >> 3u); +} + +static uint32_t amduat_sha256_small_sigma1(uint32_t x) { + return amduat_sha256_rotr(x, 17u) ^ amduat_sha256_rotr(x, 19u) ^ (x >> 10u); +} + +static uint32_t amduat_sha256_load_be32(const uint8_t *data) { + return ((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) | + ((uint32_t)data[2] << 8) | (uint32_t)data[3]; +} + +static void amduat_sha256_store_be32(uint8_t *out, uint32_t v) { + out[0] = (uint8_t)(v >> 24); + out[1] = (uint8_t)(v >> 16); + out[2] = (uint8_t)(v >> 8); + out[3] = (uint8_t)(v); +} + +static void amduat_sha256_store_be64(uint8_t *out, uint64_t v) { + out[0] = (uint8_t)(v >> 56); + out[1] = (uint8_t)(v >> 48); + out[2] = (uint8_t)(v >> 40); + out[3] = (uint8_t)(v >> 32); + out[4] = (uint8_t)(v >> 24); + out[5] = (uint8_t)(v >> 16); + out[6] = (uint8_t)(v >> 8); + out[7] = (uint8_t)(v); +} + +static void amduat_sha256_transform(amduat_sha256_ctx_t *ctx, + const uint8_t block[64]) { + static const uint32_t k[64] = { + 0x428a2f98u, 0x71374491u, 0xb5c0fbcfu, 0xe9b5dba5u, 0x3956c25bu, + 0x59f111f1u, 0x923f82a4u, 0xab1c5ed5u, 0xd807aa98u, 0x12835b01u, + 0x243185beu, 0x550c7dc3u, 0x72be5d74u, 0x80deb1feu, 0x9bdc06a7u, + 0xc19bf174u, 0xe49b69c1u, 0xefbe4786u, 0x0fc19dc6u, 0x240ca1ccu, + 0x2de92c6fu, 0x4a7484aau, 0x5cb0a9dcu, 0x76f988dau, 0x983e5152u, + 0xa831c66du, 0xb00327c8u, 0xbf597fc7u, 0xc6e00bf3u, 0xd5a79147u, + 0x06ca6351u, 0x14292967u, 0x27b70a85u, 0x2e1b2138u, 0x4d2c6dfcu, + 0x53380d13u, 0x650a7354u, 0x766a0abbu, 0x81c2c92eu, 0x92722c85u, + 0xa2bfe8a1u, 0xa81a664bu, 0xc24b8b70u, 0xc76c51a3u, 0xd192e819u, + 0xd6990624u, 0xf40e3585u, 0x106aa070u, 0x19a4c116u, 0x1e376c08u, + 0x2748774cu, 0x34b0bcb5u, 0x391c0cb3u, 0x4ed8aa4au, 0x5b9cca4fu, + 0x682e6ff3u, 0x748f82eeu, 0x78a5636fu, 0x84c87814u, 0x8cc70208u, + 0x90befffau, 0xa4506cebu, 0xbef9a3f7u, 0xc67178f2u}; + uint32_t w[64]; + uint32_t a; + uint32_t b; + uint32_t c; + uint32_t d; + uint32_t e; + uint32_t f; + uint32_t g; + uint32_t h; + uint32_t t1; + uint32_t t2; + size_t i; + + for (i = 0; i < 16; ++i) { + w[i] = amduat_sha256_load_be32(block + (i * 4)); + } + for (i = 16; i < 64; ++i) { + w[i] = amduat_sha256_small_sigma1(w[i - 2]) + w[i - 7] + + amduat_sha256_small_sigma0(w[i - 15]) + w[i - 16]; + } + + a = ctx->state[0]; + b = ctx->state[1]; + c = ctx->state[2]; + d = ctx->state[3]; + e = ctx->state[4]; + f = ctx->state[5]; + g = ctx->state[6]; + h = ctx->state[7]; + + for (i = 0; i < 64; ++i) { + t1 = h + amduat_sha256_big_sigma1(e) + amduat_sha256_ch(e, f, g) + k[i] + + w[i]; + t2 = amduat_sha256_big_sigma0(a) + amduat_sha256_maj(a, b, c); + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + + ctx->state[0] += a; + ctx->state[1] += b; + ctx->state[2] += c; + ctx->state[3] += d; + ctx->state[4] += e; + ctx->state[5] += f; + ctx->state[6] += g; + ctx->state[7] += h; +} + +static void amduat_sha256_init(amduat_sha256_ctx_t *ctx) { + ctx->state[0] = 0x6a09e667u; + ctx->state[1] = 0xbb67ae85u; + ctx->state[2] = 0x3c6ef372u; + ctx->state[3] = 0xa54ff53au; + ctx->state[4] = 0x510e527fu; + ctx->state[5] = 0x9b05688cu; + ctx->state[6] = 0x1f83d9abu; + ctx->state[7] = 0x5be0cd19u; + ctx->bitlen = 0; + ctx->buffer_len = 0; +} + +static void amduat_sha256_update(amduat_sha256_ctx_t *ctx, + const uint8_t *data, + size_t len) { + size_t i; + + if (len == 0) { + return; + } + + ctx->bitlen += (uint64_t)len * 8u; + + i = 0; + if (ctx->buffer_len > 0) { + size_t to_copy = 64u - ctx->buffer_len; + if (to_copy > len) { + to_copy = len; + } + memcpy(ctx->buffer + ctx->buffer_len, data, to_copy); + ctx->buffer_len += to_copy; + i += to_copy; + + if (ctx->buffer_len == 64u) { + amduat_sha256_transform(ctx, ctx->buffer); + ctx->buffer_len = 0; + } + } + + for (; i + 64u <= len; i += 64u) { + amduat_sha256_transform(ctx, data + i); + } + + if (i < len) { + ctx->buffer_len = len - i; + memcpy(ctx->buffer, data + i, ctx->buffer_len); + } +} + +static void amduat_sha256_final(amduat_sha256_ctx_t *ctx, uint8_t out[32]) { + size_t i; + + i = ctx->buffer_len; + ctx->buffer[i++] = 0x80u; + + if (i > 56u) { + memset(ctx->buffer + i, 0, 64u - i); + amduat_sha256_transform(ctx, ctx->buffer); + i = 0; + } + + memset(ctx->buffer + i, 0, 56u - i); + amduat_sha256_store_be64(ctx->buffer + 56u, ctx->bitlen); + amduat_sha256_transform(ctx, ctx->buffer); + + for (i = 0; i < 8; ++i) { + amduat_sha256_store_be32(out + (i * 4u), ctx->state[i]); + } +} + +bool amduat_hash_asl1_sha256_digest(void *ctx, + amduat_octets_t input, + uint8_t *out, + size_t out_len) { + amduat_sha256_ctx_t sha_ctx; + + (void)ctx; + + if (out == NULL || out_len < 32u) { + return false; + } + if (input.len > 0 && input.data == NULL) { + return false; + } + + amduat_sha256_init(&sha_ctx); + amduat_sha256_update(&sha_ctx, input.data, input.len); + amduat_sha256_final(&sha_ctx, out); + return true; +} diff --git a/src/near_core/hash/sha256.h b/src/near_core/hash/sha256.h new file mode 100644 index 0000000..0a2f343 --- /dev/null +++ b/src/near_core/hash/sha256.h @@ -0,0 +1,15 @@ +#ifndef AMDUAT_HASH_SHA256_H +#define AMDUAT_HASH_SHA256_H + +#include "amduat/asl/core.h" + +#include +#include +#include + +bool amduat_hash_asl1_sha256_digest(void *ctx, + amduat_octets_t input, + uint8_t *out, + size_t out_len); + +#endif /* AMDUAT_HASH_SHA256_H */