Add TGK core edge types and TGK1 edge encoding/tests
This commit is contained in:
parent
d9e66ea60c
commit
1c5bae927e
|
|
@ -230,6 +230,16 @@ target_link_libraries(amduat_test_pel1_result
|
||||||
)
|
)
|
||||||
add_test(NAME pel1_result COMMAND amduat_test_pel1_result)
|
add_test(NAME pel1_result COMMAND amduat_test_pel1_result)
|
||||||
|
|
||||||
|
add_executable(amduat_test_tgk1_edge tests/enc/test_tgk1_edge.c)
|
||||||
|
target_include_directories(amduat_test_tgk1_edge
|
||||||
|
PRIVATE ${AMDUAT_INTERNAL_DIR}
|
||||||
|
PRIVATE ${AMDUAT_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
target_link_libraries(amduat_test_tgk1_edge
|
||||||
|
PRIVATE amduat_enc amduat_hash_asl1 amduat_asl amduat_util
|
||||||
|
)
|
||||||
|
add_test(NAME tgk1_edge COMMAND amduat_test_tgk1_edge)
|
||||||
|
|
||||||
add_executable(amduat_test_pel_program_dag_exec
|
add_executable(amduat_test_pel_program_dag_exec
|
||||||
tests/pel/test_pel_program_dag_exec.c)
|
tests/pel/test_pel_program_dag_exec.c)
|
||||||
target_include_directories(amduat_test_pel_program_dag_exec
|
target_include_directories(amduat_test_pel_program_dag_exec
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,25 @@
|
||||||
#ifndef AMDUAT_ENC_TGK1_EDGE_H
|
#ifndef AMDUAT_ENC_TGK1_EDGE_H
|
||||||
#define AMDUAT_ENC_TGK1_EDGE_H
|
#define AMDUAT_ENC_TGK1_EDGE_H
|
||||||
|
|
||||||
|
#include "amduat/tgk/core.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum { TGK1_EDGE_ENC_V1 = 0x0201u };
|
||||||
|
|
||||||
enum { TYPE_TAG_TGK1_EDGE_V1 = 0x00000201u };
|
enum { TYPE_TAG_TGK1_EDGE_V1 = 0x00000201u };
|
||||||
enum { AMDUAT_TYPE_TAG_TGK1_EDGE_V1 = TYPE_TAG_TGK1_EDGE_V1 };
|
enum { AMDUAT_TYPE_TAG_TGK1_EDGE_V1 = TYPE_TAG_TGK1_EDGE_V1 };
|
||||||
|
|
||||||
|
bool amduat_enc_tgk1_edge_encode_v1(const amduat_tgk_edge_body_t *edge,
|
||||||
|
amduat_octets_t *out_bytes);
|
||||||
|
bool amduat_enc_tgk1_edge_decode_v1(amduat_octets_t bytes,
|
||||||
|
amduat_tgk_edge_body_t *out_edge);
|
||||||
|
void amduat_enc_tgk1_edge_free(amduat_tgk_edge_body_t *edge);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
#ifndef AMDUAT_TGK_CORE_H
|
#ifndef AMDUAT_TGK_CORE_H
|
||||||
#define AMDUAT_TGK_CORE_H
|
#define AMDUAT_TGK_CORE_H
|
||||||
|
|
||||||
#include "amduat/enc/tgk1_edge.h"
|
#include "amduat/asl/core.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
@ -9,6 +13,24 @@ extern "C" {
|
||||||
|
|
||||||
/* Core TGK header re-exports encoding constants for convenience. */
|
/* Core TGK header re-exports encoding constants for convenience. */
|
||||||
|
|
||||||
|
typedef uint32_t amduat_tgk_edge_type_id_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
amduat_tgk_edge_type_id_t type;
|
||||||
|
amduat_reference_t *from;
|
||||||
|
size_t from_len;
|
||||||
|
amduat_reference_t *to;
|
||||||
|
size_t to_len;
|
||||||
|
amduat_reference_t payload;
|
||||||
|
} amduat_tgk_edge_body_t;
|
||||||
|
|
||||||
|
bool amduat_tgk_edge_body_has_endpoints(const amduat_tgk_edge_body_t *edge);
|
||||||
|
bool amduat_tgk_edge_body_eq(const amduat_tgk_edge_body_t *a,
|
||||||
|
const amduat_tgk_edge_body_t *b);
|
||||||
|
void amduat_tgk_edge_body_free(amduat_tgk_edge_body_t *edge);
|
||||||
|
|
||||||
|
#include "amduat/enc/tgk1_edge.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
#include "amduat/tgk/core.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static void amduat_reference_free(amduat_reference_t *ref) {
|
||||||
|
if (ref == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
free((void *)ref->digest.data);
|
||||||
|
ref->digest.data = NULL;
|
||||||
|
ref->digest.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_tgk_edge_body_has_endpoints(const amduat_tgk_edge_body_t *edge) {
|
||||||
|
if (edge == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return edge->from_len > 0 || edge->to_len > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_tgk_edge_body_eq(const amduat_tgk_edge_body_t *a,
|
||||||
|
const amduat_tgk_edge_body_t *b) {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (a == b) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (a == NULL || b == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (a->type != b->type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (a->from_len != b->from_len || a->to_len != b->to_len) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (a->from_len != 0 && (a->from == NULL || b->from == NULL)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (a->to_len != 0 && (a->to == NULL || b->to == NULL)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (i = 0; i < a->from_len; ++i) {
|
||||||
|
if (!amduat_reference_eq(a->from[i], b->from[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < a->to_len; ++i) {
|
||||||
|
if (!amduat_reference_eq(a->to[i], b->to[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return amduat_reference_eq(a->payload, b->payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
void amduat_tgk_edge_body_free(amduat_tgk_edge_body_t *edge) {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (edge == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (edge->from != NULL) {
|
||||||
|
for (i = 0; i < edge->from_len; ++i) {
|
||||||
|
amduat_reference_free(&edge->from[i]);
|
||||||
|
}
|
||||||
|
free(edge->from);
|
||||||
|
}
|
||||||
|
if (edge->to != NULL) {
|
||||||
|
for (i = 0; i < edge->to_len; ++i) {
|
||||||
|
amduat_reference_free(&edge->to[i]);
|
||||||
|
}
|
||||||
|
free(edge->to);
|
||||||
|
}
|
||||||
|
amduat_reference_free(&edge->payload);
|
||||||
|
|
||||||
|
edge->from = NULL;
|
||||||
|
edge->from_len = 0;
|
||||||
|
edge->to = NULL;
|
||||||
|
edge->to_len = 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,360 @@
|
||||||
|
#include "amduat/enc/tgk1_edge.h"
|
||||||
|
|
||||||
|
#include "amduat/enc/asl1_core_codec.h"
|
||||||
|
#include "amduat/hash/asl1.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const uint8_t *data;
|
||||||
|
size_t len;
|
||||||
|
size_t offset;
|
||||||
|
} amduat_cursor_t;
|
||||||
|
|
||||||
|
static void amduat_store_u16_be(uint8_t *out, uint16_t value) {
|
||||||
|
out[0] = (uint8_t)((value >> 8) & 0xffu);
|
||||||
|
out[1] = (uint8_t)(value & 0xffu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amduat_store_u32_be(uint8_t *out, uint32_t value) {
|
||||||
|
out[0] = (uint8_t)((value >> 24) & 0xffu);
|
||||||
|
out[1] = (uint8_t)((value >> 16) & 0xffu);
|
||||||
|
out[2] = (uint8_t)((value >> 8) & 0xffu);
|
||||||
|
out[3] = (uint8_t)(value & 0xffu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_read_u16(amduat_cursor_t *cur, uint16_t *out) {
|
||||||
|
const uint8_t *data;
|
||||||
|
if (cur->len - cur->offset < 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
data = cur->data + cur->offset;
|
||||||
|
*out = (uint16_t)((data[0] << 8) | data[1]);
|
||||||
|
cur->offset += 2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_read_u32(amduat_cursor_t *cur, uint32_t *out) {
|
||||||
|
const uint8_t *data;
|
||||||
|
if (cur->len - cur->offset < 4) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
data = cur->data + cur->offset;
|
||||||
|
*out = ((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) |
|
||||||
|
((uint32_t)data[2] << 8) | (uint32_t)data[3];
|
||||||
|
cur->offset += 4;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_add_size(size_t *acc, size_t add) {
|
||||||
|
if (*acc > SIZE_MAX - add) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*acc += add;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_reference_bytes_len(amduat_reference_t ref, size_t *out_len) {
|
||||||
|
const amduat_hash_asl1_desc_t *desc;
|
||||||
|
|
||||||
|
if (ref.digest.len != 0 && ref.digest.data == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc = amduat_hash_asl1_desc_lookup(ref.hash_id);
|
||||||
|
if (desc == NULL || desc->digest_len == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ref.digest.len != desc->digest_len) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_len = 2 + desc->digest_len;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_encoded_ref_len(amduat_reference_t ref, size_t *out_len) {
|
||||||
|
size_t ref_len;
|
||||||
|
|
||||||
|
if (!amduat_reference_bytes_len(ref, &ref_len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ref_len > UINT32_MAX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out_len = 4 + ref_len;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_write_encoded_ref(uint8_t *buffer,
|
||||||
|
size_t buffer_len,
|
||||||
|
size_t *offset,
|
||||||
|
amduat_reference_t ref) {
|
||||||
|
size_t ref_len;
|
||||||
|
|
||||||
|
if (!amduat_reference_bytes_len(ref, &ref_len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ref_len > UINT32_MAX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (buffer_len - *offset < 4 + ref_len) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
amduat_store_u32_be(buffer + *offset, (uint32_t)ref_len);
|
||||||
|
*offset += 4;
|
||||||
|
amduat_store_u16_be(buffer + *offset, ref.hash_id);
|
||||||
|
*offset += 2;
|
||||||
|
if (ref.digest.len != 0) {
|
||||||
|
memcpy(buffer + *offset, ref.digest.data, ref.digest.len);
|
||||||
|
*offset += ref.digest.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_read_encoded_ref(amduat_cursor_t *cur,
|
||||||
|
amduat_reference_t *out_ref) {
|
||||||
|
uint32_t ref_len_u32;
|
||||||
|
amduat_octets_t ref_bytes;
|
||||||
|
|
||||||
|
if (!amduat_read_u32(cur, &ref_len_u32)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ref_len_u32 < 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (cur->len - cur->offset < ref_len_u32) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ref_bytes = amduat_octets(cur->data + cur->offset, ref_len_u32);
|
||||||
|
if (!amduat_enc_asl1_core_decode_reference_v1(ref_bytes, out_ref)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cur->offset += ref_len_u32;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amduat_reference_free(amduat_reference_t *ref) {
|
||||||
|
if (ref == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
free((void *)ref->digest.data);
|
||||||
|
ref->digest.data = NULL;
|
||||||
|
ref->digest.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amduat_enc_tgk1_edge_free(amduat_tgk_edge_body_t *edge) {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (edge == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (edge->from != NULL) {
|
||||||
|
for (i = 0; i < edge->from_len; ++i) {
|
||||||
|
amduat_reference_free(&edge->from[i]);
|
||||||
|
}
|
||||||
|
free(edge->from);
|
||||||
|
}
|
||||||
|
if (edge->to != NULL) {
|
||||||
|
for (i = 0; i < edge->to_len; ++i) {
|
||||||
|
amduat_reference_free(&edge->to[i]);
|
||||||
|
}
|
||||||
|
free(edge->to);
|
||||||
|
}
|
||||||
|
amduat_reference_free(&edge->payload);
|
||||||
|
|
||||||
|
edge->from = NULL;
|
||||||
|
edge->from_len = 0;
|
||||||
|
edge->to = NULL;
|
||||||
|
edge->to_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_enc_tgk1_edge_encode_v1(const amduat_tgk_edge_body_t *edge,
|
||||||
|
amduat_octets_t *out_bytes) {
|
||||||
|
size_t total_len = 0;
|
||||||
|
size_t offset = 0;
|
||||||
|
uint8_t *buffer;
|
||||||
|
size_t i;
|
||||||
|
size_t enc_len;
|
||||||
|
|
||||||
|
if (edge == NULL || out_bytes == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_bytes->data = NULL;
|
||||||
|
out_bytes->len = 0;
|
||||||
|
|
||||||
|
if (edge->from_len == 0 && edge->to_len == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (edge->from_len > UINT32_MAX || edge->to_len > UINT32_MAX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (edge->from_len != 0 && edge->from == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (edge->to_len != 0 && edge->to == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_add_size(&total_len, 2 + 4 + 4)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (i = 0; i < edge->from_len; ++i) {
|
||||||
|
if (!amduat_encoded_ref_len(edge->from[i], &enc_len) ||
|
||||||
|
!amduat_add_size(&total_len, enc_len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!amduat_add_size(&total_len, 4)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (i = 0; i < edge->to_len; ++i) {
|
||||||
|
if (!amduat_encoded_ref_len(edge->to[i], &enc_len) ||
|
||||||
|
!amduat_add_size(&total_len, enc_len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!amduat_encoded_ref_len(edge->payload, &enc_len) ||
|
||||||
|
!amduat_add_size(&total_len, enc_len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = (uint8_t *)malloc(total_len);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
amduat_store_u16_be(buffer + offset, 1);
|
||||||
|
offset += 2;
|
||||||
|
amduat_store_u32_be(buffer + offset, edge->type);
|
||||||
|
offset += 4;
|
||||||
|
|
||||||
|
amduat_store_u32_be(buffer + offset, (uint32_t)edge->from_len);
|
||||||
|
offset += 4;
|
||||||
|
for (i = 0; i < edge->from_len; ++i) {
|
||||||
|
if (!amduat_write_encoded_ref(buffer, total_len, &offset,
|
||||||
|
edge->from[i])) {
|
||||||
|
free(buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
amduat_store_u32_be(buffer + offset, (uint32_t)edge->to_len);
|
||||||
|
offset += 4;
|
||||||
|
for (i = 0; i < edge->to_len; ++i) {
|
||||||
|
if (!amduat_write_encoded_ref(buffer, total_len, &offset, edge->to[i])) {
|
||||||
|
free(buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_write_encoded_ref(buffer, total_len, &offset, edge->payload)) {
|
||||||
|
free(buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_bytes->data = buffer;
|
||||||
|
out_bytes->len = total_len;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_enc_tgk1_edge_decode_v1(amduat_octets_t bytes,
|
||||||
|
amduat_tgk_edge_body_t *out_edge) {
|
||||||
|
amduat_cursor_t cur;
|
||||||
|
uint16_t edge_version;
|
||||||
|
uint32_t from_count;
|
||||||
|
uint32_t to_count;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (out_edge == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (bytes.len != 0 && bytes.data == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(out_edge, 0, sizeof(*out_edge));
|
||||||
|
|
||||||
|
cur.data = bytes.data;
|
||||||
|
cur.len = bytes.len;
|
||||||
|
cur.offset = 0;
|
||||||
|
|
||||||
|
if (!amduat_read_u16(&cur, &edge_version)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (edge_version != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_read_u32(&cur, &out_edge->type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_read_u32(&cur, &from_count)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (from_count != 0) {
|
||||||
|
if (from_count > SIZE_MAX / sizeof(amduat_reference_t)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out_edge->from = (amduat_reference_t *)calloc(from_count,
|
||||||
|
sizeof(amduat_reference_t));
|
||||||
|
if (out_edge->from == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out_edge->from_len = from_count;
|
||||||
|
|
||||||
|
for (i = 0; i < out_edge->from_len; ++i) {
|
||||||
|
if (!amduat_read_encoded_ref(&cur, &out_edge->from[i])) {
|
||||||
|
amduat_enc_tgk1_edge_free(out_edge);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_read_u32(&cur, &to_count)) {
|
||||||
|
amduat_enc_tgk1_edge_free(out_edge);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (to_count != 0) {
|
||||||
|
if (to_count > SIZE_MAX / sizeof(amduat_reference_t)) {
|
||||||
|
amduat_enc_tgk1_edge_free(out_edge);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out_edge->to =
|
||||||
|
(amduat_reference_t *)calloc(to_count, sizeof(amduat_reference_t));
|
||||||
|
if (out_edge->to == NULL) {
|
||||||
|
amduat_enc_tgk1_edge_free(out_edge);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out_edge->to_len = to_count;
|
||||||
|
|
||||||
|
for (i = 0; i < out_edge->to_len; ++i) {
|
||||||
|
if (!amduat_read_encoded_ref(&cur, &out_edge->to[i])) {
|
||||||
|
amduat_enc_tgk1_edge_free(out_edge);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_edge->from_len == 0 && out_edge->to_len == 0) {
|
||||||
|
amduat_enc_tgk1_edge_free(out_edge);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_read_encoded_ref(&cur, &out_edge->payload)) {
|
||||||
|
amduat_enc_tgk1_edge_free(out_edge);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur.offset != cur.len) {
|
||||||
|
amduat_enc_tgk1_edge_free(out_edge);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
194
tests/enc/test_tgk1_edge.c
Normal file
194
tests/enc/test_tgk1_edge.c
Normal file
|
|
@ -0,0 +1,194 @@
|
||||||
|
#include "amduat/enc/tgk1_edge.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static const uint8_t k_expected_edge_bytes[] = {
|
||||||
|
0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
|
||||||
|
0x00, 0x22, 0x00, 0x01, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||||
|
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||||
|
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||||
|
0x00, 0x00, 0x00, 0x22, 0x00, 0x01, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||||
|
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||||
|
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||||
|
0x11, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x01,
|
||||||
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||||
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||||
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x22,
|
||||||
|
0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||||
|
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||||
|
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t k_empty_edge_bytes[] = {
|
||||||
|
0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30,
|
||||||
|
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||||
|
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||||
|
0x30, 0x30, 0x30, 0x30,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void fill_digest(uint8_t *out, uint8_t value) {
|
||||||
|
memset(out, value, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
static amduat_reference_t make_ref(uint8_t value, uint8_t *storage) {
|
||||||
|
fill_digest(storage, value);
|
||||||
|
return amduat_reference(0x0001, amduat_octets(storage, 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool bytes_equal(amduat_octets_t bytes,
|
||||||
|
const uint8_t *expected,
|
||||||
|
size_t expected_len) {
|
||||||
|
if (bytes.len != expected_len) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (bytes.len == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return memcmp(bytes.data, expected, expected_len) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_edge_round_trip(void) {
|
||||||
|
amduat_tgk_edge_body_t edge;
|
||||||
|
amduat_reference_t from_refs[2];
|
||||||
|
amduat_reference_t to_refs[1];
|
||||||
|
amduat_octets_t encoded;
|
||||||
|
amduat_tgk_edge_body_t decoded;
|
||||||
|
uint8_t f0[32], f1[32], t0[32], p0[32];
|
||||||
|
int exit_code = 1;
|
||||||
|
|
||||||
|
memset(&edge, 0, sizeof(edge));
|
||||||
|
edge.type = 0x2a;
|
||||||
|
|
||||||
|
from_refs[0] = make_ref(0x10, f0);
|
||||||
|
from_refs[1] = make_ref(0x11, f1);
|
||||||
|
edge.from = from_refs;
|
||||||
|
edge.from_len = 2;
|
||||||
|
|
||||||
|
to_refs[0] = make_ref(0x20, t0);
|
||||||
|
edge.to = to_refs;
|
||||||
|
edge.to_len = 1;
|
||||||
|
|
||||||
|
edge.payload = make_ref(0x30, p0);
|
||||||
|
|
||||||
|
if (!amduat_enc_tgk1_edge_encode_v1(&edge, &encoded)) {
|
||||||
|
fprintf(stderr, "encode failed\n");
|
||||||
|
return exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bytes_equal(encoded, k_expected_edge_bytes,
|
||||||
|
sizeof(k_expected_edge_bytes))) {
|
||||||
|
fprintf(stderr, "encoded bytes mismatch\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_enc_tgk1_edge_decode_v1(encoded, &decoded)) {
|
||||||
|
fprintf(stderr, "decode failed\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decoded.type != edge.type || decoded.from_len != 2 ||
|
||||||
|
decoded.to_len != 1) {
|
||||||
|
fprintf(stderr, "decoded field mismatch\n");
|
||||||
|
goto cleanup_decoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_reference_eq(decoded.from[0], edge.from[0]) ||
|
||||||
|
!amduat_reference_eq(decoded.from[1], edge.from[1]) ||
|
||||||
|
!amduat_reference_eq(decoded.to[0], edge.to[0]) ||
|
||||||
|
!amduat_reference_eq(decoded.payload, edge.payload)) {
|
||||||
|
fprintf(stderr, "decoded references mismatch\n");
|
||||||
|
goto cleanup_decoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_code = 0;
|
||||||
|
|
||||||
|
cleanup_decoded:
|
||||||
|
amduat_enc_tgk1_edge_free(&decoded);
|
||||||
|
cleanup:
|
||||||
|
free((void *)encoded.data);
|
||||||
|
return exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_invalid_edge_version(void) {
|
||||||
|
uint8_t bad_bytes[sizeof(k_expected_edge_bytes)];
|
||||||
|
amduat_octets_t bytes;
|
||||||
|
amduat_tgk_edge_body_t decoded;
|
||||||
|
|
||||||
|
memcpy(bad_bytes, k_expected_edge_bytes, sizeof(k_expected_edge_bytes));
|
||||||
|
bad_bytes[1] = 0x02;
|
||||||
|
|
||||||
|
bytes = amduat_octets(bad_bytes, sizeof(bad_bytes));
|
||||||
|
if (amduat_enc_tgk1_edge_decode_v1(bytes, &decoded)) {
|
||||||
|
fprintf(stderr, "invalid edge version accepted\n");
|
||||||
|
amduat_enc_tgk1_edge_free(&decoded);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_empty_endpoints(void) {
|
||||||
|
amduat_tgk_edge_body_t edge;
|
||||||
|
amduat_octets_t encoded;
|
||||||
|
amduat_tgk_edge_body_t decoded;
|
||||||
|
uint8_t p0[32];
|
||||||
|
|
||||||
|
memset(&edge, 0, sizeof(edge));
|
||||||
|
edge.type = 0x2a;
|
||||||
|
edge.payload = make_ref(0x30, p0);
|
||||||
|
|
||||||
|
if (amduat_enc_tgk1_edge_encode_v1(&edge, &encoded)) {
|
||||||
|
fprintf(stderr, "encode accepted empty endpoints\n");
|
||||||
|
free((void *)encoded.data);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (amduat_enc_tgk1_edge_decode_v1(
|
||||||
|
amduat_octets(k_empty_edge_bytes, sizeof(k_empty_edge_bytes)),
|
||||||
|
&decoded)) {
|
||||||
|
fprintf(stderr, "decode accepted empty endpoints\n");
|
||||||
|
amduat_enc_tgk1_edge_free(&decoded);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_trailing_bytes(void) {
|
||||||
|
uint8_t bad_bytes[sizeof(k_expected_edge_bytes) + 1];
|
||||||
|
amduat_octets_t bytes;
|
||||||
|
amduat_tgk_edge_body_t decoded;
|
||||||
|
|
||||||
|
memcpy(bad_bytes, k_expected_edge_bytes, sizeof(k_expected_edge_bytes));
|
||||||
|
bad_bytes[sizeof(k_expected_edge_bytes)] = 0x00;
|
||||||
|
|
||||||
|
bytes = amduat_octets(bad_bytes, sizeof(bad_bytes));
|
||||||
|
if (amduat_enc_tgk1_edge_decode_v1(bytes, &decoded)) {
|
||||||
|
fprintf(stderr, "trailing bytes accepted\n");
|
||||||
|
amduat_enc_tgk1_edge_free(&decoded);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
if (test_edge_round_trip() != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (test_invalid_edge_version() != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (test_empty_endpoints() != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (test_trailing_bytes() != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue