amduat/src/near_core/hash/sha256.c

219 lines
5.8 KiB
C
Raw Normal View History

#include "sha256.h"
#include <string.h>
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;
}
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;
}
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);
}
}
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;
}