#include "amduat/fps.h" #include #include static const char k_amduat_fps_domain_sep[] = "CAS:OBJ\0"; static uint8_t amduat_fps_reverse_bits8(uint8_t value) { value = (uint8_t)(((value & 0xf0u) >> 4) | ((value & 0x0fu) << 4)); value = (uint8_t)(((value & 0xccu) >> 2) | ((value & 0x33u) << 2)); value = (uint8_t)(((value & 0xaau) >> 1) | ((value & 0x55u) << 1)); return value; } static bool amduat_fps_alloc_output(size_t len, amduat_octets_t *out) { uint8_t *buf; if (out == NULL) { return false; } *out = amduat_octets(NULL, 0u); if (len == 0u) { return true; } buf = (uint8_t *)malloc(len); if (buf == NULL) { return false; } *out = amduat_octets(buf, len); return true; } amduat_fps_error_t amduat_fps_slice(amduat_octets_t input, size_t offset, size_t length, amduat_octets_t *out) { if (out == NULL || (input.len != 0u && input.data == NULL)) { return AMDUAT_FPS_ERR_INVALID; } if (offset > input.len || length > input.len - offset) { return AMDUAT_FPS_ERR_SLICE_RANGE; } if (!amduat_fps_alloc_output(length, out)) { return AMDUAT_FPS_ERR_IO_FAILURE; } if (length != 0u) { memcpy((void *)out->data, input.data + offset, length); } return AMDUAT_FPS_OK; } amduat_fps_error_t amduat_fps_concat(const amduat_octets_t *inputs, size_t input_count, amduat_octets_t *out) { size_t total = 0u; size_t i; uint8_t *cursor; if (out == NULL) { return AMDUAT_FPS_ERR_INVALID; } if (input_count == 0u) { return AMDUAT_FPS_ERR_EMPTY_INPUTS; } if (inputs == NULL) { return AMDUAT_FPS_ERR_INVALID; } for (i = 0u; i < input_count; ++i) { if (inputs[i].len != 0u && inputs[i].data == NULL) { return AMDUAT_FPS_ERR_INVALID; } if (SIZE_MAX - total < inputs[i].len) { return AMDUAT_FPS_ERR_IO_FAILURE; } total += inputs[i].len; } if (!amduat_fps_alloc_output(total, out)) { return AMDUAT_FPS_ERR_IO_FAILURE; } cursor = (uint8_t *)out->data; for (i = 0u; i < input_count; ++i) { if (inputs[i].len != 0u) { memcpy(cursor, inputs[i].data, inputs[i].len); cursor += inputs[i].len; } } return AMDUAT_FPS_OK; } amduat_fps_error_t amduat_fps_reverse(amduat_octets_t input, amduat_fps_reverse_level_t level, amduat_octets_t *out) { size_t unit_size; size_t i; size_t unit_count; if (out == NULL || (input.len != 0u && input.data == NULL)) { return AMDUAT_FPS_ERR_INVALID; } if (level == AMDUAT_FPS_REVERSE_BITS) { if (!amduat_fps_alloc_output(input.len, out)) { return AMDUAT_FPS_ERR_IO_FAILURE; } for (i = 0u; i < input.len; ++i) { size_t dst = input.len - 1u - i; ((uint8_t *)out->data)[dst] = amduat_fps_reverse_bits8(input.data[i]); } return AMDUAT_FPS_OK; } if (level == AMDUAT_FPS_REVERSE_BYTES) { unit_size = 1u; } else if (level == AMDUAT_FPS_REVERSE_WORDS) { unit_size = 2u; } else if (level == AMDUAT_FPS_REVERSE_LONGS) { unit_size = 4u; } else { return AMDUAT_FPS_ERR_INVALID_LEVEL; } if (unit_size != 0u && input.len % unit_size != 0u) { return AMDUAT_FPS_ERR_REV_ALIGNMENT; } if (!amduat_fps_alloc_output(input.len, out)) { return AMDUAT_FPS_ERR_IO_FAILURE; } unit_count = unit_size == 0u ? 0u : input.len / unit_size; for (i = 0u; i < unit_count; ++i) { size_t src_offset = i * unit_size; size_t dst_offset = (unit_count - 1u - i) * unit_size; memcpy((uint8_t *)out->data + dst_offset, input.data + src_offset, unit_size); } return AMDUAT_FPS_OK; } amduat_fps_error_t amduat_fps_splice(amduat_octets_t a, size_t offset, amduat_octets_t b, amduat_octets_t *out) { size_t total; if (out == NULL || (a.len != 0u && a.data == NULL) || (b.len != 0u && b.data == NULL)) { return AMDUAT_FPS_ERR_INVALID; } if (offset > a.len) { return AMDUAT_FPS_ERR_SPLICE_RANGE; } if (SIZE_MAX - a.len < b.len) { return AMDUAT_FPS_ERR_IO_FAILURE; } total = a.len + b.len; if (!amduat_fps_alloc_output(total, out)) { return AMDUAT_FPS_ERR_IO_FAILURE; } if (offset != 0u) { memcpy((uint8_t *)out->data, a.data, offset); } if (b.len != 0u) { memcpy((uint8_t *)out->data + offset, b.data, b.len); } if (a.len > offset) { memcpy((uint8_t *)out->data + offset + b.len, a.data + offset, a.len - offset); } return AMDUAT_FPS_OK; } bool amduat_fps_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; amduat_octets_t domain_sep; uint8_t *digest; 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_fps_domain_sep, sizeof(k_amduat_fps_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; }