255 changes: 121 additions & 134 deletions tools/tpm2_rc_decode.c
Expand Up @@ -25,95 +25,64 @@
// THE POSSIBILITY OF SUCH DAMAGE.
//**********************************************************************;

#include <getopt.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <sapi/tpm20.h>

#include "tpm2_options.h"
#include "log.h"
#include "rc-decode.h"
#include "tpm2_options.h"
#include "tpm2_tool.h"
#include "tpm2_util.h"

#define TPM_RC_MAX 0xffffffff

TPM_RC
str_to_tpm_rc (const char *rc_str)
{
static bool str_to_tpm_rc(const char *rc_str, TPM_RC *rc) {
uintmax_t rc_read = 0;
char *end_ptr = NULL;

rc_read = strtoumax (rc_str, &end_ptr, 0);
rc_read = strtoumax(rc_str, &end_ptr, 0);
if (rc_read > TPM_RC_MAX) {
LOG_ERR("invalid TPM_RC");
exit (1);
return false;
}

/* apply the TPM_RC_MAX mask to the possibly larger uintmax_t */
return rc_read & TPM_RC_MAX;
}
*rc = rc_read & TPM_RC_MAX;

int
process_cmdline (int argc,
char *argv[],
char *envp[])
{
int opt = -1;
const char *optstring = "hv";
static struct option long_options[] = {
{ "help", 0 , NULL, 'h' },
{ "version", 0, NULL, 'v' },
{ .name = NULL }
};
while ((opt = getopt_long (argc, argv, optstring, long_options, NULL)) != -1)
{
switch (opt)
{
case 'h':
execute_man (argv[0], envp);
exit (0);
case 'v':
showVersion (argv[0]);
exit (0);
case '?':
exit (1);
}
}
return optind;
return true;
}

/* Dump the hex, identifier and description for the format zero / VER1 error
* provided in TPM_RC parameter.
*/
int
print_tpm_rc_format_zero (TPM_RC rc)
{
static int print_tpm_rc_format_zero(TPM_RC rc) {
TPM_RC rc_tmp;
tpm2_rc_entry_t *entry;

rc_tmp = tpm2_rc_get_code_7bit (rc);
if (tpm2_rc_is_vendor_defined (rc)) {
rc_tmp = tpm2_rc_get_code_7bit(rc);
if (tpm2_rc_is_vendor_defined(rc)) {
LOG_ERR("vendor defined TPM_RCs are not supported");
return -1;
} else if (tpm2_rc_is_warning_code (rc)) {
entry = tpm2_get_warn_entry (rc_tmp);
} else if (tpm2_rc_is_warning_code(rc)) {
entry = tpm2_get_warn_entry(rc_tmp);
if (entry)
printf ("format 0 warning code\n hex: 0x%02x\n name: %s\n "
"description: %s\n",
rc_tmp, entry->name, entry->description);
tpm2_tool_output("format 0 warning code\n hex: 0x%02x\n name: %s\n "
"description: %s\n", rc_tmp, entry->name,
entry->description);
else
printf ("failed to decode TPM_RC warning: 0x%x\n", rc_tmp);
} else if (tpm2_rc_is_error_code (rc)) {
entry = tpm2_get_fmt0_entry (rc_tmp);
tpm2_tool_output("failed to decode TPM_RC warning: 0x%x\n", rc_tmp);
} else if (tpm2_rc_is_error_code(rc)) {
entry = tpm2_get_fmt0_entry(rc_tmp);
if (entry)
printf ("format 0 error code\n hex: 0x%02x\n name: %s\n "
"description: %s\n",
rc_tmp, entry->name, entry->description);
tpm2_tool_output("format 0 error code\n hex: 0x%02x\n name: %s\n "
"description: %s\n", rc_tmp, entry->name,
entry->description);
else
printf ("failed to decode TPM_RC error: 0x%02x\n", rc_tmp);
} else if (tpm2_rc_is_tpm12 (rc_tmp)) {
tpm2_tool_output("failed to decode TPM_RC error: 0x%02x\n", rc_tmp);
} else if (tpm2_rc_is_tpm12(rc_tmp)) {
LOG_ERR("version 1.2 TPM_RCs are not supported");
return -1;
} else {
Expand All @@ -126,50 +95,48 @@ print_tpm_rc_format_zero (TPM_RC rc)
/* Dump the hex, identifier and description for the format one / FMT1 error
* as well as the parameter, handle or session data.
*/
int
print_tpm_rc_format_one (TPM_RC rc)
{
static int print_tpm_rc_format_one(TPM_RC rc) {
TPM_RC rc_tmp;
tpm2_rc_entry_t *entry;

printf ("format 1 error code\n");
rc_tmp = tpm2_rc_get_code_6bit (rc);
printf (" hex: 0x%02x\n", rc_tmp);
tpm2_tool_output("format 1 error code\n");
rc_tmp = tpm2_rc_get_code_6bit(rc);
tpm2_tool_output(" hex: 0x%02x\n", rc_tmp);
/* decode error message */
entry = tpm2_get_fmt1_entry (rc_tmp);
entry = tpm2_get_fmt1_entry(rc_tmp);
if (!entry) {
printf ("Unknown TPM_RC\n");
tpm2_tool_output("Unknown TPM_RC\n");
return -1;
}
printf (" identifier: %s\n description: %s\n",
entry->name, entry->description);
tpm2_tool_output(" identifier: %s\n description: %s\n", entry->name,
entry->description);
/* decode parameter / handle / session number */
if (tpm2_rc_is_error_code_with_parameter (rc)) {
rc_tmp = tpm2_rc_get_parameter_number (rc);
entry = tpm2_get_parameter_entry (rc_tmp);
if (tpm2_rc_is_error_code_with_parameter(rc)) {
rc_tmp = tpm2_rc_get_parameter_number(rc);
entry = tpm2_get_parameter_entry(rc_tmp);
if (!entry) {
printf ("Unknown TPM_RC parameter number: 0x%03x\n", rc_tmp);
tpm2_tool_output("Unknown TPM_RC parameter number: 0x%03x\n", rc_tmp);
return -1;
}
printf ("parameter\n hex: 0x%03x\n identifier: %s\n "
tpm2_tool_output("parameter\n hex: 0x%03x\n identifier: %s\n "
"description: %s\n", rc_tmp, entry->name, entry->description);
} else if (tpm2_rc_is_error_code_with_handle (rc)) {
rc_tmp = tpm2_rc_get_handle_number (rc);
entry = tpm2_get_handle_entry (rc_tmp);
} else if (tpm2_rc_is_error_code_with_handle(rc)) {
rc_tmp = tpm2_rc_get_handle_number(rc);
entry = tpm2_get_handle_entry(rc_tmp);
if (!entry) {
printf ("Unkonwn TPM_RC handle number: 0x%03x\n", rc_tmp);
tpm2_tool_output("Unkonwn TPM_RC handle number: 0x%03x\n", rc_tmp);
return -1;
}
printf ("handle\n hex:0x%03x\n identifier: %s\n "
tpm2_tool_output("handle\n hex:0x%03x\n identifier: %s\n "
"description: %s\n", rc_tmp, entry->name, entry->description);
} else if (tpm2_rc_is_error_code_with_session (rc)) {
rc_tmp = tpm2_rc_get_session_number (rc);
entry = tpm2_get_session_entry (rc_tmp);
} else if (tpm2_rc_is_error_code_with_session(rc)) {
rc_tmp = tpm2_rc_get_session_number(rc);
entry = tpm2_get_session_entry(rc_tmp);
if (!entry) {
printf ("Unknown TPM_RC session number: 0x%03x\n", rc_tmp);
tpm2_tool_output("Unknown TPM_RC session number: 0x%03x\n", rc_tmp);
return -1;
}
printf ("session\n hex: 0x%03x\n identifier: %s\n "
tpm2_tool_output("session\n hex: 0x%03x\n identifier: %s\n "
"description: %s\n", rc_tmp, entry->name, entry->description);
}

Expand All @@ -178,23 +145,21 @@ print_tpm_rc_format_one (TPM_RC rc)
/* Dump the hex, identifier and description for the TSS defined layer
* indicator in the provided TPM_RC.
*/
int
print_tpm_rc_tss_layer (TPM_RC rc)
{
static int print_tpm_rc_tss_layer(TPM_RC rc) {
TPM_RC rc_tmp;
tpm2_rc_entry_t *entry;
int ret;

rc_tmp = tpm2_rc_get_layer (rc);
rc_tmp = tpm2_rc_get_layer(rc);
/* Currently no entry for 0x0 layer, assume it's directly from the TPM? */
printf ("error layer\n hex: 0x%x\n", rc_tmp);
entry = tpm2_get_layer_entry (rc_tmp);
tpm2_tool_output("error layer\n hex: 0x%x\n", rc_tmp);
entry = tpm2_get_layer_entry(rc_tmp);
if (entry) {
printf (" identifier: %s\n description: %s\n",
entry->name, entry->description);
tpm2_tool_output(" identifier: %s\n description: %s\n", entry->name,
entry->description);
ret = 0;
} else {
printf ("failed to decode TPM_RC layer: 0x%x\n", rc_tmp);
tpm2_tool_output("failed to decode TPM_RC layer: 0x%x\n", rc_tmp);
ret = -1;
}

Expand All @@ -203,21 +168,19 @@ print_tpm_rc_tss_layer (TPM_RC rc)
/* Dump the hex, identifier string and description for the TSS defined
* base error code in the provided TPM_RC.
*/
int
print_tpm_rc_tss_error_code (TPM_RC rc)
{
static int print_tpm_rc_tss_error_code(TPM_RC rc) {
TPM_RC rc_tmp;
tpm2_rc_entry_t *entry;
int ret;

entry = tpm2_get_tss_base_rc_entry (rc);
entry = tpm2_get_tss_base_rc_entry(rc);
if (entry) {
printf ("base error code\n identifier: %s\n description: %s\n",
tpm2_tool_output("base error code\n identifier: %s\n description: %s\n",
entry->name, entry->description);
ret = 0;
} else {
rc_tmp = tpm2_rc_get_tss_err_code (rc);
printf ("failed to decode TPM_RC error code: 0x%x\n", rc_tmp);
rc_tmp = tpm2_rc_get_tss_err_code(rc);
tpm2_tool_output("failed to decode TPM_RC error code: 0x%x\n", rc_tmp);
ret = -1;
}

Expand All @@ -226,13 +189,11 @@ print_tpm_rc_tss_error_code (TPM_RC rc)
/* Top level function to dump human readable data about TPM_RCs as defined
* in the TPM2 Part 2: Structures, Table 17..
*/
int
print_tpm_rc_tpm_error_code (TPM_RC rc)
{
if (tpm2_rc_is_format_zero (rc))
print_tpm_rc_format_zero (rc);
else if (tpm2_rc_is_format_one (rc))
print_tpm_rc_format_one (rc);
static int print_tpm_rc_tpm_error_code(TPM_RC rc) {
if (tpm2_rc_is_format_zero(rc))
print_tpm_rc_format_zero(rc);
else if (tpm2_rc_is_format_one(rc))
print_tpm_rc_format_one(rc);
else {
LOG_ERR("Unknown TPM_RC format");
return -1;
Expand All @@ -241,43 +202,69 @@ print_tpm_rc_tpm_error_code (TPM_RC rc)
}
/* Top level function to dump human readable data about TPM_RCs.
*/
int
print_tpm_rc (TPM_RC rc)
{
int ret;
TPM_RC rc_tmp;
bool print_tpm_rc(TPM_RC rc) {

/* Determine which layer in the stack produced the error */
rc_tmp = tpm2_rc_get_layer (rc);
ret = print_tpm_rc_tss_layer (rc);
TPM_RC rc_tmp = tpm2_rc_get_layer(rc);
int ret = print_tpm_rc_tss_layer(rc);
if (ret) {
return false;
}

switch (rc_tmp) {
case TSS2_SYS_ERROR_LEVEL:
case TSS2_TCTI_ERROR_LEVEL:
ret = print_tpm_rc_tss_error_code (rc);
break;
case TSS2_SYS_PART2_ERROR_LEVEL:
case TSS2_TPM_ERROR_LEVEL:
ret = print_tpm_rc_tpm_error_code (rc);
break;
default:
break;
case TSS2_SYS_ERROR_LEVEL:
case TSS2_TCTI_ERROR_LEVEL:
ret = print_tpm_rc_tss_error_code(rc);
break;
case TSS2_SYS_PART2_ERROR_LEVEL:
case TSS2_TPM_ERROR_LEVEL:
ret = print_tpm_rc_tpm_error_code(rc);
break;
default:
break;
}

return ret;
return ret == 0;
}

static char *rc_str;

static bool on_arg(int argc, char **argv) {

if (argc != 1) {
LOG_ERR("Expected 1 rc code, got: %d", argc);
}

rc_str = argv[0];

return true;
}

bool tpm2_tool_onstart(tpm2_options **opts) {

*opts = tpm2_options_new(NULL, 0, NULL,
NULL, on_arg);

return *opts != NULL;
}

int
main (int argc, char *argv[], char *envp[])
{
TPM_RC rc = 0;
int pos_ind = -1, ret = -1;
int tpm2_tool_onrun(TSS2_SYS_CONTEXT *sapi_context, tpm2_option_flags flags) {

UNUSED(flags);
UNUSED(sapi_context);

TPM_RC rc;

pos_ind = process_cmdline (argc, argv, envp);
if (pos_ind + 1 != argc) {
LOG_ERR ("No error code provided, try --help");
exit (1);
if (!rc_str) {
LOG_ERR("Expected a single rc value argument, got none.");
return 1;
}
rc = str_to_tpm_rc (argv[pos_ind]);
ret = print_tpm_rc (rc);
exit (ret);

bool result = str_to_tpm_rc(rc_str, &rc);
if (!result) {
return 1;
}

result = print_tpm_rc(rc);
return result != true;
}