Made StoreConfig enforcement pluggable at the amduat_asl_store_t boundary by adding a validate_config hook to store ops. validate_config is now optional, get rejects refs whose hash_id doesn’t match the store config, and put verifies the returned Reference matches the configured hash_id. This uses the StoreConfig at the boundary without forcing every store to implement the hook.

This commit is contained in:
Carl Niklas Rydberg 2025-12-21 23:18:12 +01:00
parent 5443ad041c
commit a992e89766
3 changed files with 53 additions and 23 deletions

View file

@ -11,6 +11,7 @@
extern "C" { extern "C" {
#endif #endif
/* Zero-initialize before setting fields to keep future-compatibility. */
typedef struct { typedef struct {
amduat_asl_encoding_profile_id_t encoding_profile_id; amduat_asl_encoding_profile_id_t encoding_profile_id;
amduat_hash_id_t hash_id; amduat_hash_id_t hash_id;
@ -31,6 +32,9 @@ typedef struct {
amduat_asl_store_error_t (*get)(void *ctx, amduat_asl_store_error_t (*get)(void *ctx,
amduat_reference_t ref, amduat_reference_t ref,
amduat_artifact_t *out_artifact); amduat_artifact_t *out_artifact);
amduat_asl_store_error_t (*validate_config)(
void *ctx,
amduat_asl_store_config_t config);
} amduat_asl_store_ops_t; } amduat_asl_store_ops_t;
typedef struct { typedef struct {

View file

@ -489,6 +489,28 @@ static amduat_asl_store_error_t amduat_asl_store_fs_put_impl(
return AMDUAT_ASL_STORE_OK; return AMDUAT_ASL_STORE_OK;
} }
static amduat_asl_store_error_t amduat_asl_store_fs_validate_config(
void *ctx,
amduat_asl_store_config_t config) {
const amduat_hash_asl1_desc_t *hash_desc;
(void)ctx;
if (config.encoding_profile_id != AMDUAT_ENC_ASL1_CORE_V1) {
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
}
hash_desc = amduat_hash_asl1_desc_lookup(config.hash_id);
if (hash_desc == NULL || hash_desc->digest_len == 0 ||
hash_desc->impl.digest == NULL) {
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
}
if (hash_desc->digest_len < AMDUAT_ASL_STORE_FS_MIN_DIGEST_BYTES) {
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
}
return AMDUAT_ASL_STORE_OK;
}
static amduat_asl_store_error_t amduat_asl_store_fs_get_impl( static amduat_asl_store_error_t amduat_asl_store_fs_get_impl(
void *ctx, void *ctx,
amduat_reference_t ref, amduat_reference_t ref,
@ -671,7 +693,9 @@ bool amduat_asl_store_fs_init(amduat_asl_store_fs_t *fs,
amduat_asl_store_ops_t amduat_asl_store_fs_ops(void) { amduat_asl_store_ops_t amduat_asl_store_fs_ops(void) {
amduat_asl_store_ops_t ops; amduat_asl_store_ops_t ops;
memset(&ops, 0, sizeof(ops));
ops.put = amduat_asl_store_fs_put_impl; ops.put = amduat_asl_store_fs_put_impl;
ops.get = amduat_asl_store_fs_get_impl; ops.get = amduat_asl_store_fs_get_impl;
ops.validate_config = amduat_asl_store_fs_validate_config;
return ops; return ops;
} }

View file

@ -1,23 +1,11 @@
#include "amduat/asl/store.h" #include "amduat/asl/store.h"
#include "amduat/enc/asl1_core.h"
#include "amduat/hash/asl1.h"
static bool amduat_asl_store_config_supported( static amduat_asl_store_error_t amduat_asl_store_validate_config(
const amduat_asl_store_config_t *config) { amduat_asl_store_t *store) {
const amduat_hash_asl1_desc_t *hash_desc; if (store == NULL || store->ops.validate_config == NULL) {
return AMDUAT_ASL_STORE_OK;
if (config == NULL) {
return false;
} }
if (amduat_enc_asl1_core_desc_lookup(config->encoding_profile_id) == NULL) { return store->ops.validate_config(store->ctx, store->config);
return false;
}
hash_desc = amduat_hash_asl1_desc_lookup(config->hash_id);
if (hash_desc == NULL || hash_desc->digest_len == 0 ||
hash_desc->impl.digest == NULL) {
return false;
}
return true;
} }
void amduat_asl_store_init(amduat_asl_store_t *store, void amduat_asl_store_init(amduat_asl_store_t *store,
@ -35,26 +23,40 @@ void amduat_asl_store_init(amduat_asl_store_t *store,
amduat_asl_store_error_t amduat_asl_store_put(amduat_asl_store_t *store, amduat_asl_store_error_t amduat_asl_store_put(amduat_asl_store_t *store,
amduat_artifact_t artifact, amduat_artifact_t artifact,
amduat_reference_t *out_ref) { amduat_reference_t *out_ref) {
amduat_asl_store_error_t cfg_err;
amduat_asl_store_error_t store_err;
if (store == NULL || store->ops.put == NULL) { if (store == NULL || store->ops.put == NULL) {
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED; return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
} }
if (!amduat_asl_store_config_supported(&store->config)) { cfg_err = amduat_asl_store_validate_config(store);
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED; if (cfg_err != AMDUAT_ASL_STORE_OK) {
return cfg_err;
} }
return store->ops.put(store->ctx, artifact, out_ref); store_err = store->ops.put(store->ctx, artifact, out_ref);
if (store_err != AMDUAT_ASL_STORE_OK) {
return store_err;
}
if (out_ref != NULL && out_ref->hash_id != store->config.hash_id) {
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
}
return AMDUAT_ASL_STORE_OK;
} }
amduat_asl_store_error_t amduat_asl_store_get(amduat_asl_store_t *store, amduat_asl_store_error_t amduat_asl_store_get(amduat_asl_store_t *store,
amduat_reference_t ref, amduat_reference_t ref,
amduat_artifact_t *out_artifact) { amduat_artifact_t *out_artifact) {
amduat_asl_store_error_t cfg_err;
if (store == NULL || store->ops.get == NULL) { if (store == NULL || store->ops.get == NULL) {
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED; return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
} }
if (!amduat_asl_store_config_supported(&store->config)) {
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
}
if (ref.hash_id != store->config.hash_id) { if (ref.hash_id != store->config.hash_id) {
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED; return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
} }
cfg_err = amduat_asl_store_validate_config(store);
if (cfg_err != AMDUAT_ASL_STORE_OK) {
return cfg_err;
}
return store->ops.get(store->ctx, ref, out_artifact); return store->ops.get(store->ctx, ref, out_artifact);
} }