203 lines
5.7 KiB
C
203 lines
5.7 KiB
C
|
|
#include "amduat/fps.h"
|
||
|
|
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
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;
|
||
|
|
}
|