amduat/src/near_core/hash/asl1.c
Carl Niklas Rydberg 87c8bcc799 Align HASH/ASL1 registry and codecs with spec constraints
- reject reserved HashId values across lookup/parse/encode paths
- add reserved-range registry table and remove 0x0000 from runtime list
- forbid SHA-256 impl overrides; add streaming hash API
- update tgk_store_mem test to use unsupported but non-reserved hash id
- document ASL store digest-length constraint in README
2025-12-22 00:21:16 +01:00

231 lines
5.7 KiB
C

#include "amduat/hash/asl1.h"
#include "sha256.h"
#include <stdlib.h>
#include <string.h>
static amduat_hash_asl1_desc_t g_hash_asl1_descs[] = {
{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}}};
typedef struct {
amduat_hash_id_t start;
amduat_hash_id_t end;
} amduat_hash_asl1_reserved_range_t;
static const amduat_hash_asl1_reserved_range_t
g_hash_asl1_reserved_ranges[] = {
{0x0000, 0x0000},
{0x0002, 0x0002},
{0x8001, 0x8001},
{0x8002, 0x80FF},
};
#ifdef AMDUAT_HASH_ASL1_ENABLE_SHA256_STUB
static bool amduat_hash_asl1_sha256_stub(void *ctx,
amduat_octets_t input,
uint8_t *out,
size_t out_len) {
size_t i;
(void)ctx;
(void)input;
if (out == NULL || out_len < 32) {
return false;
}
for (i = 0; i < 32; ++i) {
out[i] = 0;
}
return true;
}
#endif
amduat_octets_t amduat_hash_asl1_key(amduat_hash_id_t hash_id, uint8_t out[2]) {
out[0] = (uint8_t)(hash_id >> 8);
out[1] = (uint8_t)(hash_id & 0xff);
return amduat_octets(out, 2);
}
const amduat_hash_asl1_desc_t *amduat_hash_asl1_desc_lookup(
amduat_hash_id_t hash_id) {
size_t i;
if (amduat_hash_asl1_is_reserved(hash_id)) {
return NULL;
}
for (i = 0; i < sizeof(g_hash_asl1_descs) / sizeof(g_hash_asl1_descs[0]);
++i) {
if (g_hash_asl1_descs[i].hash_id == hash_id) {
return &g_hash_asl1_descs[i];
}
}
return NULL;
}
const amduat_hash_asl1_desc_t *amduat_hash_asl1_descs(size_t *out_len) {
if (out_len != NULL) {
*out_len = sizeof(g_hash_asl1_descs) / sizeof(g_hash_asl1_descs[0]);
}
return g_hash_asl1_descs;
}
bool amduat_hash_asl1_register_impl(amduat_hash_id_t hash_id,
amduat_hash_asl1_impl_t impl) {
size_t i;
if (amduat_hash_asl1_is_reserved(hash_id)) {
return false;
}
if (hash_id == AMDUAT_HASH_ASL1_ID_SHA256) {
return false;
}
for (i = 0; i < sizeof(g_hash_asl1_descs) / sizeof(g_hash_asl1_descs[0]);
++i) {
if (g_hash_asl1_descs[i].hash_id == hash_id) {
g_hash_asl1_descs[i].impl = impl;
return true;
}
}
return false;
}
bool amduat_hash_asl1_digest(amduat_hash_id_t hash_id,
amduat_octets_t input,
uint8_t *out,
size_t out_len) {
const amduat_hash_asl1_desc_t *desc;
if (out == NULL) {
return false;
}
desc = amduat_hash_asl1_desc_lookup(hash_id);
if (desc == NULL || desc->digest_len == 0) {
return false;
}
if (out_len < desc->digest_len) {
return false;
}
if (desc->impl.digest == NULL) {
return false;
}
return desc->impl.digest(desc->impl.ctx, input, out, desc->digest_len);
}
static bool amduat_hash_asl1_sha256_stream_update(void *ctx,
amduat_octets_t input) {
if (input.len != 0 && input.data == NULL) {
return false;
}
amduat_sha256_update((amduat_sha256_ctx_t *)ctx, input.data, input.len);
return true;
}
static bool amduat_hash_asl1_sha256_stream_final(void *ctx,
uint8_t *out,
size_t out_len) {
if (out == NULL || out_len < 32u) {
return false;
}
amduat_sha256_final((amduat_sha256_ctx_t *)ctx, out);
return true;
}
static void amduat_hash_asl1_sha256_stream_destroy(void *ctx) {
free(ctx);
}
bool amduat_hash_asl1_stream_init(amduat_hash_id_t hash_id,
amduat_hash_asl1_stream_t *out) {
amduat_sha256_ctx_t *ctx;
if (out == NULL) {
return false;
}
memset(out, 0, sizeof(*out));
if (amduat_hash_asl1_is_reserved(hash_id)) {
return false;
}
if (hash_id != AMDUAT_HASH_ASL1_ID_SHA256) {
return false;
}
ctx = (amduat_sha256_ctx_t *)malloc(sizeof(*ctx));
if (ctx == NULL) {
return false;
}
amduat_sha256_init(ctx);
out->hash_id = hash_id;
out->ctx = ctx;
out->update = amduat_hash_asl1_sha256_stream_update;
out->finalize = amduat_hash_asl1_sha256_stream_final;
out->destroy = amduat_hash_asl1_sha256_stream_destroy;
return true;
}
bool amduat_hash_asl1_stream_update(amduat_hash_asl1_stream_t *stream,
amduat_octets_t input) {
if (stream == NULL || stream->update == NULL) {
return false;
}
return stream->update(stream->ctx, input);
}
bool amduat_hash_asl1_stream_final(amduat_hash_asl1_stream_t *stream,
uint8_t *out,
size_t out_len) {
if (stream == NULL || stream->finalize == NULL) {
return false;
}
return stream->finalize(stream->ctx, out, out_len);
}
void amduat_hash_asl1_stream_destroy(amduat_hash_asl1_stream_t *stream) {
if (stream == NULL) {
return;
}
if (stream->destroy != NULL) {
stream->destroy(stream->ctx);
}
memset(stream, 0, sizeof(*stream));
}
bool amduat_hash_asl1_register_sha256_stub(void) {
#ifdef AMDUAT_HASH_ASL1_ENABLE_SHA256_STUB
amduat_hash_asl1_impl_t impl;
impl.digest = amduat_hash_asl1_sha256_stub;
impl.ctx = NULL;
return amduat_hash_asl1_register_impl(AMDUAT_HASH_ASL1_ID_SHA256, impl);
#else
return false;
#endif
}
bool amduat_hash_asl1_is_reserved(amduat_hash_id_t hash_id) {
size_t i;
for (i = 0; i < sizeof(g_hash_asl1_reserved_ranges) /
sizeof(g_hash_asl1_reserved_ranges[0]);
++i) {
if (hash_id >= g_hash_asl1_reserved_ranges[i].start &&
hash_id <= g_hash_asl1_reserved_ranges[i].end) {
return true;
}
}
return false;
}