218 lines
5.7 KiB
C
218 lines
5.7 KiB
C
#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;
|
|
}
|