#include "amduat/enc/asl_log.h" #include #include #include #include #include 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; }