1 /* SPDX-License-Identifier: BSD-2-Clause */
2
3 #include <stdarg.h>
4 #include <stdbool.h>
5 #include <stddef.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include <setjmp.h>
11 #include <cmocka.h>
12
13 #include "tss2_rc.h"
14
15 #define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0]))
16
17 #define TPM2_ERROR_TSS2_RC_LAYER_COUNT (TSS2_RC_LAYER_MASK >> TSS2_RC_LAYER_SHIFT)
18
19 #define assert_string_prefix(str, prefix) \
20 assert_memory_equal(str, prefix, strlen(prefix))
21
22 static void
test_layers(void ** state)23 test_layers(void **state)
24 {
25 (void) state;
26
27 static const char *known_layers[TPM2_ERROR_TSS2_RC_LAYER_COUNT] = {
28 "tpm:",
29 NULL,
30 NULL,
31 NULL,
32 NULL,
33 NULL,
34 "fapi:",
35 "esapi:",
36 "sys:",
37 "mu:",
38 "tcti:",
39 "rmt",
40 "rm",
41 "drvr",
42 };
43
44 UINT8 layer;
45 for (layer = 0; layer < TPM2_ERROR_TSS2_RC_LAYER_COUNT; layer++) {
46 TSS2_RC rc = TSS2_RC_LAYER(layer);
47
48 const char *got = Tss2_RC_Decode(rc);
49
50 char buf[256];
51 snprintf(buf, sizeof(buf), "%u:", layer);
52
53 const char *expected = known_layers[layer] ? known_layers[layer] : buf;
54 assert_string_prefix(got, expected);
55 }
56 }
57
58 static void
test_tpm_format_0_version2_0_error(void ** state)59 test_tpm_format_0_version2_0_error(void **state)
60 {
61 (void) state;
62
63 const char *m = Tss2_RC_Decode(TPM2_RC_SEQUENCE);
64 assert_string_equal(m, "tpm:error(2.0): improper use of a sequence"
65 " handle");
66 }
67
test_tpm_format_0_version2_0_warn(void ** state)68 static void test_tpm_format_0_version2_0_warn(void **state)
69 {
70 (void) state;
71
72 const char *m = Tss2_RC_Decode(TPM2_RC_REFERENCE_H0);
73 assert_string_equal(m,
74 "tpm:warn(2.0): the 1st handle in the handle area references a"
75 " transient object or session that is not loaded");
76 }
77
78 static void
test_tpm2_format_0_unknown(void ** state)79 test_tpm2_format_0_unknown(void **state)
80 {
81 (void) state;
82
83 const char *m = Tss2_RC_Decode(TPM2_RC_NOT_USED + 0x80);
84 assert_string_equal(m, "tpm:parameter(1):unknown error num: 0x3F");
85 }
86
87 static void
test_tpm_format_1_unk_handle(void ** state)88 test_tpm_format_1_unk_handle(void **state)
89 {
90 (void) state;
91
92 const char *m = Tss2_RC_Decode(TPM2_RC_HASH);
93 assert_string_equal(m,
94 "tpm:handle(unk):hash algorithm not supported or not appropriate");
95 }
96
97 static void
test_tpm_format_1_unk_parameter(void ** state)98 test_tpm_format_1_unk_parameter(void **state)
99 {
100 (void) state;
101
102 const char *m = Tss2_RC_Decode(TPM2_RC_HASH + TPM2_RC_P);
103 assert_string_equal(m,
104 "tpm:parameter(unk):hash algorithm not supported or not appropriate");
105 }
106
107 static void
test_tpm_format_1_unk_session(void ** state)108 test_tpm_format_1_unk_session(void **state)
109 {
110 (void) state;
111
112 const char *m = Tss2_RC_Decode(TPM2_RC_HASH + TPM2_RC_S);
113 assert_string_equal(m,
114 "tpm:session(unk):hash algorithm not supported or not appropriate");
115 }
116
117 static void
test_tpm_format_1_5_handle(void ** state)118 test_tpm_format_1_5_handle(void **state)
119 {
120 (void) state;
121
122 const char *m = Tss2_RC_Decode(TPM2_RC_HASH + TPM2_RC_5);
123 assert_string_equal(m,
124 "tpm:handle(5):hash algorithm not supported or not appropriate");
125 }
126
127 static void
test_tpm2_format_1_unknown(void ** state)128 test_tpm2_format_1_unknown(void **state)
129 {
130 (void) state;
131
132 const char *m = Tss2_RC_Decode(TPM2_RC_NOT_USED + 0x80);
133 assert_string_equal(m, "tpm:parameter(1):unknown error num: 0x3F");
134 }
135
136 static void
test_tpm2_format_1_success(void ** state)137 test_tpm2_format_1_success(void **state)
138 {
139 (void) state;
140
141 const char *m = Tss2_RC_Decode(TPM2_RC_SUCCESS);
142 assert_string_equal(m, "tpm:success");
143 }
144
145 static const char *
custom_err_handler(TSS2_RC rc)146 custom_err_handler(TSS2_RC rc)
147 {
148
149 static const char *err_map[] = { "error 1", "error 2", "error 3" };
150
151 if (rc - 1u >= ARRAY_LEN(err_map)) {
152 return NULL;
153 }
154
155 return err_map[rc - 1];
156 }
157
158 static void
test_custom_handler(void ** state)159 test_custom_handler(void **state)
160 {
161 (void) state;
162
163 /*
164 * Test registering a custom handler
165 */
166 TSS2_RC_HANDLER old = Tss2_RC_SetHandler(1, "cstm", custom_err_handler);
167 assert_null(old);
168
169 /*
170 * Test getting error strings
171 */
172 unsigned i;
173 for (i = 1; i < 4; i++) {
174 // Make a layer 1 error with an error number of i.
175 TSS2_RC rc = TSS2_RC_LAYER(1) | i;
176 char buf[256];
177 snprintf(buf, sizeof(buf), "cstm:error %u", i);
178
179 const char *e = Tss2_RC_Decode(rc);
180 assert_string_equal(e, buf);
181 }
182
183 TSS2_RC rc = TSS2_RC_LAYER(1) | 42;
184
185 /*
186 * Test an unknown error
187 */
188 const char *e = Tss2_RC_Decode(rc);
189 assert_string_equal(e, "cstm:0x2A");
190
191 /*
192 * Test clearing a handler
193 */
194 old = Tss2_RC_SetHandler(1, "cstm", NULL);
195 assert_ptr_equal(old, custom_err_handler);
196
197 /*
198 * Test an unknown layer
199 */
200 e = Tss2_RC_Decode(rc);
201 assert_string_equal(e, "1:0x2A");
202 }
203
204 static void
test_zero_length_name(void ** state)205 test_zero_length_name(void **state)
206 {
207 (void) state;
208
209 TSS2_RC_HANDLER old = Tss2_RC_SetHandler(TSS2_TPM_RC_LAYER, "",
210 custom_err_handler);
211 assert_non_null(old);
212
213 old = Tss2_RC_SetHandler(TSS2_TPM_RC_LAYER, "",
214 custom_err_handler);
215 assert_ptr_equal(old, custom_err_handler);
216 }
217
218 static void
test_over_length_name(void ** state)219 test_over_length_name(void **state)
220 {
221 (void) state;
222
223 TSS2_RC_HANDLER old = Tss2_RC_SetHandler(1, "way to long of name", custom_err_handler);
224 assert_null(old);
225
226 old = Tss2_RC_SetHandler(1, "way to long of name", custom_err_handler);
227 assert_ptr_equal(old, custom_err_handler);
228 }
229
230 static void
test_null_name(void ** state)231 test_null_name(void **state)
232 {
233 (void) state;
234
235 TSS2_RC_HANDLER old = Tss2_RC_SetHandler(1,
236 NULL, custom_err_handler);
237 assert_ptr_equal(old, custom_err_handler);
238
239 old = Tss2_RC_SetHandler(1,
240 NULL, custom_err_handler);
241 assert_ptr_equal(old, custom_err_handler);
242 }
243
244 static void
test_sys(void ** state)245 test_sys(void **state)
246 {
247 (void) state;
248
249 const char *e = Tss2_RC_Decode(TSS2_SYS_RC_ABI_MISMATCH);
250 assert_string_equal(e,
251 "sys:Passed in ABI version doesn't match called module's ABI version");
252 }
253
254 static void
test_esys(void ** state)255 test_esys(void **state)
256 {
257 (void) state;
258
259 const char *e = Tss2_RC_Decode(TSS2_ESYS_RC_BAD_VALUE);
260 assert_string_equal(e,
261 "esapi:A parameter has a bad value");
262 }
263
264 static void
test_mu(void ** state)265 test_mu(void **state)
266 {
267 (void) state;
268
269 const char *e = Tss2_RC_Decode(TSS2_MU_RC_BAD_REFERENCE);
270 assert_string_equal(e,
271 "mu:A pointer is NULL that isn't allowed to be NULL.");
272
273 }
274
275 static void
test_tcti(void ** state)276 test_tcti(void **state)
277 {
278 (void) state;
279
280 const char *e = Tss2_RC_Decode(TSS2_TCTI_RC_NO_CONNECTION);
281 assert_string_equal(e, "tcti:Fails to connect to next lower layer");
282 }
283
284 /* link required symbol, but tpm2_tool.c declares it AND main, which
285 * we have a main below for cmocka tests.
286 */
287 bool output_enabled = true;
288
289 int
main(int argc,char * argv[])290 main(int argc, char* argv[])
291 {
292 (void) argc;
293 (void) argv;
294
295 const struct CMUnitTest tests[] = {
296 /* Layer tests */
297 cmocka_unit_test(test_layers),
298 cmocka_unit_test(test_tpm_format_0_version2_0_error),
299 cmocka_unit_test(test_tpm_format_0_version2_0_warn),
300 cmocka_unit_test(test_tpm2_format_0_unknown),
301 cmocka_unit_test(test_tpm_format_1_unk_handle),
302 cmocka_unit_test(test_tpm_format_1_unk_parameter),
303 cmocka_unit_test(test_tpm_format_1_unk_session),
304 cmocka_unit_test(test_tpm_format_1_5_handle),
305 cmocka_unit_test(test_tpm2_format_1_unknown),
306 cmocka_unit_test(test_tpm2_format_1_success),
307 cmocka_unit_test(test_custom_handler),
308 cmocka_unit_test(test_zero_length_name),
309 cmocka_unit_test(test_over_length_name),
310 cmocka_unit_test(test_null_name),
311 cmocka_unit_test(test_sys),
312 cmocka_unit_test(test_esys),
313 cmocka_unit_test(test_mu),
314 cmocka_unit_test(test_tcti),
315 };
316
317 return cmocka_run_group_tests(tests, NULL, NULL);
318 }
319