forked from tpm2-software/tpm2-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tpm2_rc_decode.c: Add utility to decode TPM_RC error codes.
Basic usage is extremely simple and documented in the -h/--help option. It expects a single 32bit TPM_RC as a positional parameter. This number is parsed using the convenience functions in the rc-decode.h header. This tool then generates human readable output describing each component of the TPM_RC. This requires a few lookups in the tables from rc-decode.c, accessed using the helper functions. The algorithm is roughly: Extract the TSS layer / level indicator if TCTI | SAPI error print layer data to stdout lookup string mapping for the error code print error code data to stdout else if PART2 | TPM error if error code is in format zero if error code is vendor defined return error else if error code is a warning lookup string mapping for warning code print warning code data to stdout else if error code is an error lookup string mapping for error code print error code data to stdout else if error code is a TPM 1.2 format print error: 1.2 TPM_RCs aren't supported return error else print error: unknown TPM_RC format return error endif else if error code is in format one lookup string mapping for the error code print error code data to stdout if error code has parameter data lookup string mapping for parameter code print parameter code data to stdout else if error code has handle data lookup string mapping for handle code print handle code data to stdout else if error code has session data lookup string mapping for session code print session code data to stdout endif endif endif The output format for data is very simple. Each component of the TPM_RC is preceded by a line identifying the component. Data about the layer producing the error is preceded by: 'error layer' followed by a new line. The data in the field is then decoded and the hex value, a string representation of the identifier and then a string describing the error. These 3 items are printed each on their own line and indented 2 spaces. An example makes this more clear: TSS2_SYS_PART2_RC_LEVEL + TSS2_SYS_PART2_RC_LEVEL = 0x90100 $ src/tpm2_rc_decode 0x90100 error layer hex: 0x90000 identifier: TSS2_SYS_PART2_RC_LEVEL description: Error from the SAPI duplicating TPM error check format 0 error code hex: 0x00 name: TPM_RC_INITIALIZE description: TPM not initialized TPM_FMT1 + TPM_RC_P + TPM_RC_MFG + TPM_RC_3 = 0x3c8 error layer hex: 0x0 identifier: TSS2_TPM_ERROR_LEVEL description: Error produced by the TPM format 1 error code hex: 0x08 identifier: TPM_RC_MGF description: mask generation function not supported parameter hex: 0x300 identifier: TPM_RC_3 description: (null) Signed-off-by: Philip Tricca <[email protected]>
- Loading branch information
Showing
4 changed files
with
299 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
Unreleased | ||
Added | ||
* tpm2_rc_decode tool: Decode TPM_RC error codes. | ||
|
||
2015-10-19 Gang Wei <[email protected]> | ||
* 1.0 release | ||
* 29 tools included |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,291 @@ | ||
//**********************************************************************; | ||
// Copyright (c) 2016, Intel Corporation | ||
// All rights reserved. | ||
// | ||
// Redistribution and use in source and binary forms, with or without | ||
// modification, are permitted provided that the following conditions are met: | ||
// | ||
// 1. Redistributions of source code must retain the above copyright notice, | ||
// this list of conditions and the following disclaimer. | ||
// | ||
// 2. Redistributions in binary form must reproduce the above copyright notice, | ||
// this list of conditions and the following disclaimer in the documentation | ||
// and/or other materials provided with the distribution. | ||
// | ||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||
// 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 "common.h" | ||
#include "rc-decode.h" | ||
|
||
#define TPM_RC_MAX 0xffffffff | ||
|
||
void | ||
showHelp (const char *name) | ||
{ | ||
printf ("%s [--version|--help] TPM_RC\n" | ||
"-h, --help\t\tDisplay help message\n" | ||
"-v, --version\t\tDisplay version info\n" | ||
"\nExample:\n" | ||
"Decode hex TPM return code: %s 0xffffffff\n", name, name); | ||
} | ||
|
||
TPM_RC | ||
str_to_tpm_rc (const char *rc_str) | ||
{ | ||
uintmax_t rc_read = 0; | ||
char *end_ptr = NULL; | ||
|
||
rc_read = strtoumax (rc_str, &end_ptr, 0); | ||
if (rc_read > TPM_RC_MAX) { | ||
fprintf (stderr, "invalid TPM_RC\n"); | ||
exit (1); | ||
} | ||
/* apply the TPM_RC_MAX mask to the possibly larger uintmax_t */ | ||
return rc_read & TPM_RC_MAX; | ||
} | ||
|
||
int | ||
process_cmdline (int argc, | ||
char *argv[]) | ||
{ | ||
int opt = -1; | ||
const char *optstring = "hr"; | ||
static struct option long_options[] = { | ||
{ "help", 0 , NULL, 'h' }, | ||
{ "version", 0, NULL, 'r' }, | ||
{ 0 } | ||
}; | ||
while ((opt = getopt_long (argc, argv, optstring, long_options, NULL)) != -1) | ||
{ | ||
switch (opt) | ||
{ | ||
case 'h': | ||
showHelp (argv[0]); | ||
exit (0); | ||
case 'r': | ||
showVersion (argv[0]); | ||
exit (0); | ||
case '?': | ||
exit (1); | ||
} | ||
} | ||
return optind; | ||
} | ||
|
||
/* 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) | ||
{ | ||
TPM_RC rc_tmp; | ||
tpm2_rc_entry_t *entry; | ||
|
||
rc_tmp = tpm2_rc_get_code_7bit (rc); | ||
if (tpm2_rc_is_vendor_defined (rc)) { | ||
fprintf (stderr, "vendor defined TPM_RCs are not supported\n"); | ||
return -1; | ||
} 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); | ||
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); | ||
if (entry) | ||
printf ("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)) { | ||
fprintf (stderr, "version 1.2 TPM_RCs are not supproted\n"); | ||
return -1; | ||
} else { | ||
fprintf (stderr, "Unknown TPM_RC format\n"); | ||
return -1; | ||
} | ||
/* decode warning / error code */ | ||
return 0; | ||
} | ||
/* 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) | ||
{ | ||
TPM_RC rc_tmp; | ||
tpm2_rc_entry_t *entry; | ||
int ret; | ||
|
||
printf ("format 1 error code\n"); | ||
rc_tmp = tpm2_rc_get_code_6bit (rc); | ||
printf (" hex: 0x%02x\n", rc_tmp); | ||
/* decode error message */ | ||
entry = tpm2_get_fmt1_entry (rc_tmp); | ||
if (!entry) { | ||
printf ("Unknown TPM_RC\n"); | ||
return -1; | ||
} | ||
printf (" 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 (!entry) { | ||
printf ("Unknown TPM_RC parameter number: 0x%03x\n", rc_tmp); | ||
return -1; | ||
} | ||
printf ("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); | ||
if (!entry) { | ||
printf ("Unkonwn TPM_RC handle number: 0x%03x\n", rc_tmp); | ||
return -1; | ||
} | ||
printf ("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); | ||
if (!entry) { | ||
printf ("Unknown TPM_RC session number: 0x%03x\n", rc_tmp); | ||
return -1; | ||
} | ||
printf ("session\n hex: 0x%03x\n identifier: %s\n " | ||
"description: %s\n", rc_tmp, entry->name, entry->description); | ||
} | ||
|
||
return 0; | ||
} | ||
/* 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) | ||
{ | ||
TPM_RC rc_tmp; | ||
tpm2_rc_entry_t *entry; | ||
int ret; | ||
|
||
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); | ||
if (entry) { | ||
printf (" 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); | ||
ret = -1; | ||
} | ||
|
||
return ret; | ||
} | ||
/* 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) | ||
{ | ||
TPM_RC rc_tmp; | ||
tpm2_rc_entry_t *entry; | ||
int ret; | ||
|
||
entry = tpm2_get_tss_base_rc_entry (rc); | ||
if (entry) { | ||
printf ("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); | ||
ret = -1; | ||
} | ||
|
||
return ret; | ||
} | ||
/* 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); | ||
else { | ||
fprintf (stderr, "Unknown TPM_RC format\n"); | ||
return -1; | ||
} | ||
} | ||
/* Top level function to dump human readable data about TPM_RCs. | ||
*/ | ||
int | ||
print_tpm_rc (TPM_RC rc) | ||
{ | ||
int ret; | ||
TPM_RC rc_tmp; | ||
|
||
/* determin which layer in the stack produced the error */ | ||
rc_tmp = tpm2_rc_get_layer (rc); | ||
ret = print_tpm_rc_tss_layer (rc); | ||
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; | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
int | ||
main (int argc, char *argv[]) | ||
{ | ||
TPM_RC rc = 0; | ||
int pos_ind = -1, ret = -1; | ||
|
||
pos_ind = process_cmdline (argc, argv); | ||
if (pos_ind + 1 != argc) { | ||
printf ("No error code provided, try --help\n"); | ||
exit (1); | ||
} | ||
rc = str_to_tpm_rc (argv[pos_ind]); | ||
ret = print_tpm_rc (rc); | ||
exit (ret); | ||
} |