1 #include <iostream>
2 #include <ostream>
3 #include <string>
4
5 std::ostream& operator<<(std::ostream& os, cc128_length_t value);
6
7 std::ostream& operator<<(std::ostream& os, cc128_length_t value) {
8 char buffer[128];
9 snprintf(buffer, sizeof(buffer), "{0x%" PRIx64 " %016" PRIx64 "}", (uint64_t)(value >> 64), (uint64_t)(value));
10 return os << buffer;
11 }
12
otype_suffix(uint32_t otype)13 static const char* otype_suffix(uint32_t otype) {
14 // Two separate switches since if the number of otype bits is the same
15 // we cannot have both of the case statements in one switch
16 switch (otype) {
17 case CC128_OTYPE_UNSEALED:
18 return " (CC128_OTYPE_UNSEALED)";
19 case CC128_OTYPE_SENTRY:
20 return " (CC128_OTYPE_SENTRY)";
21 case CC128_OTYPE_RESERVED2:
22 return " (CC128_OTYPE_RESERVED2)";
23 case CC128_OTYPE_RESERVED3:
24 return " (CC128_OTYPE_RESERVED3)";
25 default:
26 break;
27 }
28 switch (otype) {
29 case CC256_OTYPE_UNSEALED:
30 return " (CC256_OTYPE_UNSEALED)";
31 case CC256_OTYPE_SENTRY:
32 return " (CC256_OTYPE_SENTRY)";
33 case CC256_OTYPE_RESERVED2:
34 return " (CC256_OTYPE_RESERVED2)";
35 case CC256_OTYPE_RESERVED3:
36 return " (CC256_OTYPE_RESERVED3)";
37 default:
38 return "";
39 }
40 }
41
42 std::ostream& operator<<(std::ostream& os, const cap_register_t& value);
43
44 std::ostream& operator<<(std::ostream& os, const cap_register_t& value) {
45 char buffer[4096];
46 cc128_length_t top_full = value._cr_top;
47 snprintf(buffer, sizeof(buffer),
48 "\tPermissions: 0x%" PRIx32 "\n"
49 "\tUser Perms: 0x%" PRIx32 "\n"
50 "\tBase: 0x%016" PRIx64 "\n"
51 "\tOffset: 0x%016" PRIx64 "\n"
52 "\tLength: 0x%" PRIx64 "%016" PRIx64 " %s\n"
53 "\tTop: 0x%" PRIx64 "%016" PRIx64 " %s\n"
54 "\tSealed: %d\n"
55 "\tOType: 0x%" PRIx32 "%s\n",
56 value.cr_perms, value.cr_uperms, value.cr_base, (uint64_t)value.offset(), (uint64_t)(value.length() >> 64),
57 (uint64_t)value.length(), value.length() > UINT64_MAX ? " (greater than UINT64_MAX)" : "",
58 (uint64_t)(top_full >> 64), (uint64_t)top_full, top_full > UINT64_MAX ? " (greater than UINT64_MAX)" : "",
59 (int)cc128_is_cap_sealed(&value), value.cr_otype, otype_suffix(value.cr_otype));
60 os << "{\n" << buffer << "}";
61 return os;
62 }
63
64 #include "catch.hpp"
65
66 static bool failed = false;
67
check(T expected,T actual,const std::string & msg)68 template <typename T> static inline bool check(T expected, T actual, const std::string& msg) {
69 if (expected == actual)
70 return true;
71 std::cerr << "ERROR: " << msg << ": expected 0x" << std::hex << expected << " != 0x" << actual << "\n";
72 failed = true;
73 return false;
74 }
75
array_lengthof(T (&)[N])76 template <class T, std::size_t N> constexpr inline size_t array_lengthof(T (&)[N]) { return N; }
77
dump_cap_fields(const cap_register_t & result)78 static void dump_cap_fields(const cap_register_t& result) {
79 fprintf(stderr, "Permissions: 0x%" PRIx32 "\n", result.cr_perms); // TODO: decode perms
80 fprintf(stderr, "User Perms: 0x%" PRIx32 "\n", result.cr_uperms);
81 fprintf(stderr, "Base: 0x%016" PRIx64 "\n", result.cr_base);
82 fprintf(stderr, "Offset: 0x%016" PRIx64 "\n", (uint64_t)result.offset());
83 fprintf(stderr, "Cursor: 0x%016" PRIx64 "\n", result.address());
84 fprintf(stderr, "Length: 0x%" PRIx64 "%016" PRIx64 " %s\n", (uint64_t)(result.length() >> 64),
85 (uint64_t)result.length() , result.length() > UINT64_MAX ? " (greater than UINT64_MAX)" : "");
86 cc128_length_t top_full = result.top();
87 fprintf(stderr, "Top: 0x%" PRIx64 "%016" PRIx64 " %s\n", (uint64_t)(top_full >> 64), (uint64_t)top_full,
88 top_full > UINT64_MAX ? " (greater than UINT64_MAX)" : "");
89 fprintf(stderr, "Sealed: %d\n", (int)cc128_is_cap_sealed(&result));
90 fprintf(stderr, "OType: 0x%" PRIx32 "%s\n", result.cr_otype, otype_suffix(result.cr_otype));
91 fprintf(stderr, "\n");
92 }
93
decompress_representable(uint64_t pesbt_already_xored,uint64_t cursor)94 __attribute__((used)) static cap_register_t decompress_representable(uint64_t pesbt_already_xored, uint64_t cursor) {
95 cap_register_t result;
96 printf("Decompressing pesbt = %016" PRIx64 ", cursor = %016" PRIx64 "\n", pesbt_already_xored, cursor);
97 decompress_128cap_already_xored(pesbt_already_xored, cursor, &result);
98 dump_cap_fields(result);
99 // Check that the result is the same again when compressed
100 uint64_t new_pesbt_already_xored = compress_128cap_without_xor(&result);
101 CHECK(pesbt_already_xored == new_pesbt_already_xored);
102 CHECK(cursor == result.address());
103 return result;
104 }
105
make_max_perms_cap(uint64_t base,uint64_t offset,cc128_length_t length)106 inline cap_register_t make_max_perms_cap(uint64_t base, uint64_t offset, cc128_length_t length) {
107 cap_register_t creg;
108 memset(&creg, 0, sizeof(creg));
109 creg.cr_base = base;
110 creg._cr_cursor = base + offset;
111 creg._cr_top = base + length;
112 creg.cr_perms = CC128_PERMS_ALL;
113 creg.cr_uperms = CC128_UPERMS_ALL;
114 creg.cr_otype = CC128_OTYPE_UNSEALED;
115 creg.cr_ebt = CC128_RESET_EBT;
116 creg.cr_tag = true;
117 REQUIRE(cc128_is_representable_cap_exact(&creg));
118 return creg;
119 }
120
121 #define DO_STRINGIFY2(x) #x
122 #define DO_STRINGIFY1(x) DO_STRINGIFY2(x)
123 #define STRINGIFY(x) DO_STRINGIFY1(x)
124
125 #define CHECK_FIELD_RAW(value, expected) CHECK(value == expected)
126 #define CHECK_FIELD(cap, field, expected) CHECK((uint64_t)expected == cap.field())
127
128 enum {
129 #ifdef CC128_OLD_FORMAT
130 TESTING_OLD_FORMAT = 1
131 #else
132 TESTING_OLD_FORMAT = 0
133 #endif
134 };
135