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