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