amduat/tests/enc/test_asl_log.c

218 lines
5.7 KiB
C
Raw Permalink Normal View History

2026-01-17 12:51:32 +01:00
#include "amduat/enc/asl_log.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static bool octets_equal(amduat_octets_t a, amduat_octets_t b) {
if (a.len != b.len) {
return false;
}
if (a.len == 0) {
return true;
}
return memcmp(a.data, b.data, a.len) == 0;
}
static int test_round_trip(void) {
uint8_t payload_a[] = {0x01, 0x02, 0x03};
uint8_t payload_b[] = {0x10, 0x20};
amduat_asl_log_record_t records[2];
amduat_octets_t encoded;
amduat_asl_log_record_t *decoded = NULL;
size_t decoded_len = 0;
int exit_code = 1;
memset(records, 0, sizeof(records));
records[0].logseq = 1;
records[0].record_type = AMDUAT_ASL_LOG_RECORD_SEGMENT_SEAL;
records[0].payload = amduat_octets(payload_a, sizeof(payload_a));
records[1].logseq = 2;
records[1].record_type = AMDUAT_ASL_LOG_RECORD_TOMBSTONE;
records[1].payload = amduat_octets(payload_b, sizeof(payload_b));
if (!amduat_enc_asl_log_encode_v1(records, 2, &encoded)) {
fprintf(stderr, "encode failed\n");
return exit_code;
}
if (!amduat_enc_asl_log_decode_v1(encoded, &decoded, &decoded_len)) {
fprintf(stderr, "decode failed\n");
goto cleanup;
}
if (decoded_len != 2) {
fprintf(stderr, "decoded length mismatch\n");
goto cleanup_decoded;
}
if (decoded[0].logseq != records[0].logseq ||
decoded[1].logseq != records[1].logseq) {
fprintf(stderr, "decoded logseq mismatch\n");
goto cleanup_decoded;
}
if (decoded[0].record_type != records[0].record_type ||
decoded[1].record_type != records[1].record_type) {
fprintf(stderr, "decoded record type mismatch\n");
goto cleanup_decoded;
}
if (!octets_equal(decoded[0].payload, records[0].payload) ||
!octets_equal(decoded[1].payload, records[1].payload)) {
fprintf(stderr, "decoded payload mismatch\n");
goto cleanup_decoded;
}
exit_code = 0;
cleanup_decoded:
amduat_enc_asl_log_free(decoded, decoded_len);
cleanup:
free((void *)encoded.data);
return exit_code;
}
static int test_hash_chain_mutation(void) {
uint8_t payload_a[] = {0xaa, 0xbb, 0xcc};
amduat_asl_log_record_t record;
amduat_octets_t encoded;
amduat_asl_log_record_t *decoded = NULL;
size_t decoded_len = 0;
int exit_code = 1;
size_t payload_offset;
memset(&record, 0, sizeof(record));
record.logseq = 1;
record.record_type = AMDUAT_ASL_LOG_RECORD_SEGMENT_SEAL;
record.payload = amduat_octets(payload_a, sizeof(payload_a));
if (!amduat_enc_asl_log_encode_v1(&record, 1, &encoded)) {
fprintf(stderr, "encode failed\n");
return exit_code;
}
payload_offset = 24 + 8 + 4 + 4;
if (encoded.len <= payload_offset) {
fprintf(stderr, "encoded payload offset invalid\n");
goto cleanup;
}
((uint8_t *)encoded.data)[payload_offset] ^= 0xffu;
if (amduat_enc_asl_log_decode_v1(encoded, &decoded, &decoded_len)) {
fprintf(stderr, "decode unexpectedly succeeded\n");
amduat_enc_asl_log_free(decoded, decoded_len);
goto cleanup;
}
exit_code = 0;
cleanup:
free((void *)encoded.data);
return exit_code;
}
static int test_unknown_record_type(void) {
uint8_t payload_a[] = {0x11};
uint8_t payload_b[] = {0x22};
uint8_t payload_c[] = {0x33};
amduat_asl_log_record_t records[3];
amduat_octets_t encoded;
amduat_asl_log_record_t *decoded = NULL;
size_t decoded_len = 0;
int exit_code = 1;
memset(records, 0, sizeof(records));
records[0].logseq = 1;
records[0].record_type = AMDUAT_ASL_LOG_RECORD_SEGMENT_SEAL;
records[0].payload = amduat_octets(payload_a, sizeof(payload_a));
records[1].logseq = 2;
records[1].record_type = 0x99;
records[1].payload = amduat_octets(payload_b, sizeof(payload_b));
records[2].logseq = 3;
records[2].record_type = AMDUAT_ASL_LOG_RECORD_TOMBSTONE;
records[2].payload = amduat_octets(payload_c, sizeof(payload_c));
if (!amduat_enc_asl_log_encode_v1(records, 3, &encoded)) {
fprintf(stderr, "encode failed\n");
return exit_code;
}
if (!amduat_enc_asl_log_decode_v1(encoded, &decoded, &decoded_len)) {
fprintf(stderr, "decode failed\n");
goto cleanup;
}
if (decoded_len != 2) {
fprintf(stderr, "unknown record not skipped\n");
goto cleanup_decoded;
}
if (decoded[0].logseq != records[0].logseq ||
decoded[1].logseq != records[2].logseq) {
fprintf(stderr, "decoded logseq mismatch\n");
goto cleanup_decoded;
}
exit_code = 0;
cleanup_decoded:
amduat_enc_asl_log_free(decoded, decoded_len);
cleanup:
free((void *)encoded.data);
return exit_code;
}
static int test_truncated_payload(void) {
uint8_t payload_a[] = {0xaa, 0xbb, 0xcc, 0xdd};
amduat_asl_log_record_t record;
amduat_octets_t encoded;
amduat_asl_log_record_t *decoded = NULL;
size_t decoded_len = 0;
int exit_code = 1;
memset(&record, 0, sizeof(record));
record.logseq = 42;
record.record_type = AMDUAT_ASL_LOG_RECORD_TOMBSTONE;
record.payload = amduat_octets(payload_a, sizeof(payload_a));
if (!amduat_enc_asl_log_encode_v1(&record, 1, &encoded)) {
fprintf(stderr, "encode failed\n");
return exit_code;
}
if (encoded.len == 0) {
fprintf(stderr, "encoded length invalid\n");
goto cleanup;
}
if (amduat_enc_asl_log_decode_v1(
amduat_octets(encoded.data, encoded.len - 1),
&decoded,
&decoded_len)) {
fprintf(stderr, "decode unexpectedly succeeded\n");
amduat_enc_asl_log_free(decoded, decoded_len);
goto cleanup;
}
exit_code = 0;
cleanup:
free((void *)encoded.data);
return exit_code;
}
int main(void) {
if (test_round_trip() != 0) {
return 1;
}
if (test_hash_chain_mutation() != 0) {
return 1;
}
if (test_unknown_record_type() != 0) {
return 1;
}
if (test_truncated_payload() != 0) {
return 1;
}
return 0;
}