blob: 1c8d66c988f9d6dc7136e9abcb7b246260579d8e [file] [log] [blame]
/* SPDX-License-Identifier: BSD-2-Clause */
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <cmocka.h>
#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);
}