#include "amduat/bytestore.h" #include #include static const char k_amduat_bytestore_domain_sep[] = "CAS:OBJ\0"; static bool amduat_bytestore_trim_trailing_slash(const char *input, size_t *out_len) { size_t len; if (input == NULL || out_len == NULL) { return false; } len = strlen(input); while (len > 1u && input[len - 1u] == '/') { len--; } *out_len = len; return true; } static bool amduat_bytestore_path_is_prefix(const char *parent, size_t parent_len, const char *child, size_t child_len) { if (parent_len == 0u || child_len == 0u) { return false; } if (child_len < parent_len) { return false; } if (memcmp(parent, child, parent_len) != 0) { return false; } if (child_len == parent_len) { return true; } return child[parent_len] == '/'; } void amduat_bytestore_init(amduat_bytestore_t *store, amduat_bytestore_config_t config, amduat_bytestore_ops_t ops, void *ctx) { if (store == NULL) { return; } store->config = config; store->ops = ops; store->ctx = ctx; } amduat_bytestore_error_t amduat_bytestore_put(amduat_bytestore_t *store, amduat_octets_t payload, amduat_reference_t *out_cid) { if (store == NULL || store->ops.put == NULL) { return AMDUAT_BYTESTORE_ERR_UNSUPPORTED; } return store->ops.put(store->ctx, payload, out_cid); } amduat_bytestore_error_t amduat_bytestore_put_stream( amduat_bytestore_t *store, amduat_bytestore_stream_t stream, amduat_reference_t *out_cid) { if (store == NULL || store->ops.put_stream == NULL) { return AMDUAT_BYTESTORE_ERR_UNSUPPORTED; } return store->ops.put_stream(store->ctx, stream, out_cid); } amduat_bytestore_error_t amduat_bytestore_import_cor( amduat_bytestore_t *store, amduat_octets_t envelope, amduat_reference_t *out_cid) { if (store == NULL || store->ops.import_cor == NULL) { return AMDUAT_BYTESTORE_ERR_UNSUPPORTED; } return store->ops.import_cor(store->ctx, envelope, out_cid); } amduat_bytestore_error_t amduat_bytestore_export_cor( amduat_bytestore_t *store, amduat_reference_t cid, amduat_octets_t *out_envelope) { if (store == NULL || store->ops.export_cor == NULL) { return AMDUAT_BYTESTORE_ERR_UNSUPPORTED; } return store->ops.export_cor(store->ctx, cid, out_envelope); } amduat_bytestore_error_t amduat_bytestore_get(amduat_bytestore_t *store, amduat_reference_t cid, amduat_octets_t *out_bytes) { if (store == NULL || store->ops.get == NULL) { return AMDUAT_BYTESTORE_ERR_UNSUPPORTED; } return store->ops.get(store->ctx, cid, out_bytes); } amduat_bytestore_error_t amduat_bytestore_stat( amduat_bytestore_t *store, amduat_reference_t cid, amduat_bytestore_stat_t *out_stat) { if (store == NULL || store->ops.stat == NULL) { return AMDUAT_BYTESTORE_ERR_UNSUPPORTED; } return store->ops.stat(store->ctx, cid, out_stat); } amduat_bytestore_error_t amduat_bytestore_assert_area_isolation( amduat_bytestore_t *store, const char *public_root, const char *secure_root) { size_t public_len; size_t secure_len; if (store != NULL && store->ops.assert_area_isolation != NULL) { return store->ops.assert_area_isolation(store->ctx, public_root, secure_root); } if (!amduat_bytestore_trim_trailing_slash(public_root, &public_len) || !amduat_bytestore_trim_trailing_slash(secure_root, &secure_len)) { return AMDUAT_BYTESTORE_ERR_INVALID; } if (public_len == 0u || secure_len == 0u) { return AMDUAT_BYTESTORE_ERR_INVALID; } if (public_len == secure_len && memcmp(public_root, secure_root, public_len) == 0) { return AMDUAT_BYTESTORE_ERR_AREA_VIOLATION; } if (amduat_bytestore_path_is_prefix(public_root, public_len, secure_root, secure_len)) { return AMDUAT_BYTESTORE_ERR_AREA_VIOLATION; } if (amduat_bytestore_path_is_prefix(secure_root, secure_len, public_root, public_len)) { return AMDUAT_BYTESTORE_ERR_AREA_VIOLATION; } return AMDUAT_BYTESTORE_OK; } bool amduat_bytestore_cid_for_payload(amduat_hash_id_t hash_id, amduat_octets_t payload, amduat_reference_t *out_cid) { const amduat_hash_asl1_desc_t *desc; uint8_t *digest; amduat_octets_t domain_sep; if (out_cid == NULL) { return false; } *out_cid = amduat_reference(0, amduat_octets(NULL, 0u)); desc = amduat_hash_asl1_desc_lookup(hash_id); if (desc == NULL || desc->digest_len == 0u) { return false; } digest = (uint8_t *)malloc(desc->digest_len); if (digest == NULL) { return false; } domain_sep = amduat_octets(k_amduat_bytestore_domain_sep, sizeof(k_amduat_bytestore_domain_sep) - 1u); if (!amduat_hash_asl1_digest_domain(hash_id, domain_sep, payload, digest, desc->digest_len)) { free(digest); return false; } *out_cid = amduat_reference(hash_id, amduat_octets(digest, desc->digest_len)); return true; } bool amduat_bytestore_cid_for_stream(amduat_hash_id_t hash_id, amduat_bytestore_stream_t stream, amduat_reference_t *out_cid) { amduat_hash_asl1_stream_t hasher; const amduat_hash_asl1_desc_t *desc; uint8_t *digest; amduat_octets_t domain_sep; amduat_octets_t chunk; int next_status; if (out_cid == NULL || stream.next == NULL) { return false; } *out_cid = amduat_reference(0, amduat_octets(NULL, 0u)); desc = amduat_hash_asl1_desc_lookup(hash_id); if (desc == NULL || desc->digest_len == 0u) { return false; } if (!amduat_hash_asl1_stream_init(hash_id, &hasher)) { return false; } domain_sep = amduat_octets(k_amduat_bytestore_domain_sep, sizeof(k_amduat_bytestore_domain_sep) - 1u); if (!amduat_hash_asl1_stream_update(&hasher, domain_sep)) { amduat_hash_asl1_stream_destroy(&hasher); return false; } while (true) { chunk = amduat_octets(NULL, 0u); next_status = stream.next(stream.ctx, &chunk); if (next_status == 0) { break; } if (next_status < 0) { amduat_hash_asl1_stream_destroy(&hasher); return false; } if (chunk.len != 0u && chunk.data == NULL) { amduat_hash_asl1_stream_destroy(&hasher); return false; } if (chunk.len != 0u && !amduat_hash_asl1_stream_update(&hasher, chunk)) { amduat_hash_asl1_stream_destroy(&hasher); return false; } } digest = (uint8_t *)malloc(desc->digest_len); if (digest == NULL) { amduat_hash_asl1_stream_destroy(&hasher); return false; } if (!amduat_hash_asl1_stream_final(&hasher, digest, desc->digest_len)) { free(digest); amduat_hash_asl1_stream_destroy(&hasher); return false; } amduat_hash_asl1_stream_destroy(&hasher); *out_cid = amduat_reference(hash_id, amduat_octets(digest, desc->digest_len)); return true; }