/* SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include #include #include #include "tss2_rc.h" #define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) #define TPM2_ERROR_TSS2_RC_LAYER_COUNT (TSS2_RC_LAYER_MASK >> TSS2_RC_LAYER_SHIFT) #define assert_string_prefix(str, prefix) \ assert_memory_equal(str, prefix, strlen(prefix)) static void test_layers(void **state) { (void) state; static const char *known_layers[TPM2_ERROR_TSS2_RC_LAYER_COUNT] = { "tpm:", NULL, NULL, NULL, NULL, NULL, "fapi:", "esapi:", "sys:", "mu:", "tcti:", "rmt", "rm", "drvr", }; UINT8 layer; for (layer = 0; layer < TPM2_ERROR_TSS2_RC_LAYER_COUNT; layer++) { TSS2_RC rc = TSS2_RC_LAYER(layer); const char *got = Tss2_RC_Decode(rc); char buf[256]; snprintf(buf, sizeof(buf), "%u:", layer); const char *expected = known_layers[layer] ? known_layers[layer] : buf; assert_string_prefix(got, expected); } } static void test_tpm_format_0_version2_0_error(void **state) { (void) state; const char *m = Tss2_RC_Decode(TPM2_RC_SEQUENCE); assert_string_equal(m, "tpm:error(2.0): improper use of a sequence" " handle"); } static void test_tpm_format_0_version2_0_warn(void **state) { (void) state; const char *m = Tss2_RC_Decode(TPM2_RC_REFERENCE_H0); assert_string_equal(m, "tpm:warn(2.0): the 1st handle in the handle area references a" " transient object or session that is not loaded"); } static void test_tpm2_format_0_unknown(void **state) { (void) state; const char *m = Tss2_RC_Decode(TPM2_RC_NOT_USED + 0x80); assert_string_equal(m, "tpm:parameter(1):unknown error num: 0x3F"); } static void test_tpm_format_1_unk_handle(void **state) { (void) state; const char *m = Tss2_RC_Decode(TPM2_RC_HASH); assert_string_equal(m, "tpm:handle(unk):hash algorithm not supported or not appropriate"); } static void test_tpm_format_1_unk_parameter(void **state) { (void) state; const char *m = Tss2_RC_Decode(TPM2_RC_HASH + TPM2_RC_P); assert_string_equal(m, "tpm:parameter(unk):hash algorithm not supported or not appropriate"); } static void test_tpm_format_1_unk_session(void **state) { (void) state; const char *m = Tss2_RC_Decode(TPM2_RC_HASH + TPM2_RC_S); assert_string_equal(m, "tpm:session(unk):hash algorithm not supported or not appropriate"); } static void test_tpm_format_1_5_handle(void **state) { (void) state; const char *m = Tss2_RC_Decode(TPM2_RC_HASH + TPM2_RC_5); assert_string_equal(m, "tpm:handle(5):hash algorithm not supported or not appropriate"); } static void test_tpm2_format_1_unknown(void **state) { (void) state; const char *m = Tss2_RC_Decode(TPM2_RC_NOT_USED + 0x80); assert_string_equal(m, "tpm:parameter(1):unknown error num: 0x3F"); } static void test_tpm2_format_1_success(void **state) { (void) state; const char *m = Tss2_RC_Decode(TPM2_RC_SUCCESS); assert_string_equal(m, "tpm:success"); } static const char * custom_err_handler(TSS2_RC rc) { static const char *err_map[] = { "error 1", "error 2", "error 3" }; if (rc - 1u >= ARRAY_LEN(err_map)) { return NULL; } return err_map[rc - 1]; } static void test_custom_handler(void **state) { (void) state; /* * Test registering a custom handler */ TSS2_RC_HANDLER old = Tss2_RC_SetHandler(1, "cstm", custom_err_handler); assert_null(old); /* * Test getting error strings */ unsigned i; for (i = 1; i < 4; i++) { // Make a layer 1 error with an error number of i. TSS2_RC rc = TSS2_RC_LAYER(1) | i; char buf[256]; snprintf(buf, sizeof(buf), "cstm:error %u", i); const char *e = Tss2_RC_Decode(rc); assert_string_equal(e, buf); } TSS2_RC rc = TSS2_RC_LAYER(1) | 42; /* * Test an unknown error */ const char *e = Tss2_RC_Decode(rc); assert_string_equal(e, "cstm:0x2A"); /* * Test clearing a handler */ old = Tss2_RC_SetHandler(1, "cstm", NULL); assert_ptr_equal(old, custom_err_handler); /* * Test an unknown layer */ e = Tss2_RC_Decode(rc); assert_string_equal(e, "1:0x2A"); } static void test_zero_length_name(void **state) { (void) state; TSS2_RC_HANDLER old = Tss2_RC_SetHandler(TSS2_TPM_RC_LAYER, "", custom_err_handler); assert_non_null(old); old = Tss2_RC_SetHandler(TSS2_TPM_RC_LAYER, "", custom_err_handler); assert_ptr_equal(old, custom_err_handler); } static void test_over_length_name(void **state) { (void) state; TSS2_RC_HANDLER old = Tss2_RC_SetHandler(1, "way to long of name", custom_err_handler); assert_null(old); old = Tss2_RC_SetHandler(1, "way to long of name", custom_err_handler); assert_ptr_equal(old, custom_err_handler); } static void test_null_name(void **state) { (void) state; TSS2_RC_HANDLER old = Tss2_RC_SetHandler(1, NULL, custom_err_handler); assert_ptr_equal(old, custom_err_handler); old = Tss2_RC_SetHandler(1, NULL, custom_err_handler); assert_ptr_equal(old, custom_err_handler); } static void test_sys(void **state) { (void) state; const char *e = Tss2_RC_Decode(TSS2_SYS_RC_ABI_MISMATCH); assert_string_equal(e, "sys:Passed in ABI version doesn't match called module's ABI version"); } static void test_esys(void **state) { (void) state; const char *e = Tss2_RC_Decode(TSS2_ESYS_RC_BAD_VALUE); assert_string_equal(e, "esapi:A parameter has a bad value"); } static void test_mu(void **state) { (void) state; const char *e = Tss2_RC_Decode(TSS2_MU_RC_BAD_REFERENCE); assert_string_equal(e, "mu:A pointer is NULL that isn't allowed to be NULL."); } static void test_tcti(void **state) { (void) state; const char *e = Tss2_RC_Decode(TSS2_TCTI_RC_NO_CONNECTION); assert_string_equal(e, "tcti:Fails to connect to next lower layer"); } /* link required symbol, but tpm2_tool.c declares it AND main, which * we have a main below for cmocka tests. */ bool output_enabled = true; int main(int argc, char* argv[]) { (void) argc; (void) argv; const struct CMUnitTest tests[] = { /* Layer tests */ cmocka_unit_test(test_layers), cmocka_unit_test(test_tpm_format_0_version2_0_error), cmocka_unit_test(test_tpm_format_0_version2_0_warn), cmocka_unit_test(test_tpm2_format_0_unknown), cmocka_unit_test(test_tpm_format_1_unk_handle), cmocka_unit_test(test_tpm_format_1_unk_parameter), cmocka_unit_test(test_tpm_format_1_unk_session), cmocka_unit_test(test_tpm_format_1_5_handle), cmocka_unit_test(test_tpm2_format_1_unknown), cmocka_unit_test(test_tpm2_format_1_success), cmocka_unit_test(test_custom_handler), cmocka_unit_test(test_zero_length_name), cmocka_unit_test(test_over_length_name), cmocka_unit_test(test_null_name), cmocka_unit_test(test_sys), cmocka_unit_test(test_esys), cmocka_unit_test(test_mu), cmocka_unit_test(test_tcti), }; return cmocka_run_group_tests(tests, NULL, NULL); }