From e857919d341185669191b31751c305358dd6bfa9 Mon Sep 17 00:00:00 2001 From: "Furtner Thomas (IFAG CCS M CS AE)" Date: Thu, 20 Jul 2017 12:52:14 +0200 Subject: [PATCH] update --- README.txt | 333 ++++++ eltt2.c | 2932 +++++++++++++++++++++++++++------------------------- eltt2.h | 720 +++++++------ 3 files changed, 2235 insertions(+), 1750 deletions(-) create mode 100644 README.txt diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..242cf92 --- /dev/null +++ b/README.txt @@ -0,0 +1,333 @@ +-------------------------------------------------------------------------------- + Infineon Embedded Linux TPM Toolbox 2 (ELTT2) for TPM 2.0 v1.1 + Infineon Technologies AG + +All information in this document is Copyright (c) 2014, Infineon Technologies AG +All rights reserved. +-------------------------------------------------------------------------------- + +Contents: + +1. Welcome +1.1 Prerequisites +1.2 Contents of the package +1.3 Getting Started + +2. Usage of Embedded Linux TPM Toolbox 2 (ELTT2) +2.1 Generic Usage +2.2 Examples + +3. If you have questions + +4. Release Info + +5. FAQ + +================================================================================ + + + +1. Welcome + + Welcome to Embedded Linux TPM Toolbox 2 (ELTT2). + ELTT2 is a single-file executable program intended for testing, performing + diagnosis and basic state changes of the Infineon Technologies TPM 2.0. + + +1.1 Prerequisites + + To build and run ELTT2 you need GCC and a Linux system capable of hosting a + TPM 2.0. + + Tested PC Platforms (x86): + - Ubuntu (R) Linux 12.04 LTS - 64 bit (modified Kernel 3.15.4) + with Infineon TPM 2.0 SLB9665 Firmware 5.22 + + Tested Embedded Platforms (ARM): + - Android 6.0 "Marshmallow" - 64 bit (modified Kernel 3.18.0+) on HiKey + with Prototype Infineon I2C TPM 2.0 for Embedded Platforms + + ELTT2 may run on many other little-endian hardware and software + configurations capable of running Linux and hosting a TPM 2.0, but this has + not been tested. + + ELTT2 does not support machines with a big-endian CPU. + + +1.2 Contents of Package + + ELTT2 consists of the following files: + - eltt2.c + Contains all method implementations of ELTT2. + - eltt2.h + Contains all constant definitions, method and command byte declarations + for the operation of ELTT2. + - License.txt + Contains the license agreement for ELTT2. + - Makefile + Contains the command to compile ELTT2. + - README.txt + This file. + + +1.3 Getting Started + + In order to execute ELTT2, you need to compile it first: + 1. Switch to the directory with the ELTT2 source code + 2. Compile the source code by typing the following command: + make + + Due to hardware (and thus TPM) access restrictions for normal users, ELTT2 + requires root (aka superuser or administrator) privileges. They can be + obtained e.g. by using the 'sudo' command on Debian Linux derivates. + + +2. Usage of ELTT2 + + +2.1 Generic Usage + + ELTT2 is operated as follows: + + Call: ./eltt2 + + For example: ./eltt2 -g or ./eltt2 -gc + + For getting an overview of the possible commands, run ./eltt2 -h + + Some options require the TPM to be in a specific state. This state is shown + in brackets ("[]") behind each command line option in the list below: + + [u]: started + + To get the TPM into the required state, call ELTT2 with the corresponding + commands ("x" for a state means that whether this state is required or not + depends on the actual command or the command parameters sent eventually to + the TPM). + + + Command line options: Preconditions: + + -a : Hash Sequence SHA-1 [u] + + -A : Hash Sequence SHA-256 [u] + + -b : Enter your own TPM command [u] + + -c: Read Clock [u] + + -d : Shutdown [u] + + -e: PCR Extend SHA-1 [u] + + -E: PCR Extend SHA-256 [u] + + -g: Get fixed capability values [u] + + -v: Get variable capability values [u] + + -G : Get Random [u] + + -h: Help [-] + + -r : PCR Read SHA-1 [u] + + -R : PCR Read SHA-256 [u] + + -s : Hash SHA-1 [u] + + -S : Hash SHA-256 [u] + + -t : Self Test [u] + + -T: Get Test Result [u] + + -u : Startup [-] + + -z : PCR Reset [u] + + + Additional information: + + -a: + With the "-a" command you can hash given data with the SHA-1 hash algorithm. + This hash sequence sends 3 commands [start, update, complete] to the TPM and + allows to hash an arbitrary amount of data. + For example, use the following command to hash the byte sequence {0x41, + 0x62, 0x43, 0x64}: + ./eltt2 -a 41624364 + + -A: + With the "-A" command you can hash given data with the SHA-256 hash + algorithm. This hash sequence sends 3 commands [start, update, complete] to + the TPM and allows to hash an arbitrary amount of data. + For example, use the following command to hash the byte sequence {0x41, + 0x62, 0x43, 0x64}: + ./eltt2 -A 41624364 + + -b: + With the "-b" command you can enter your own TPM command bytes and read the + TPM response. + For example, use the following command to send a TPM2_Startup with startup + type CLEAR to the TPM: + ./eltt2 -b 80010000000C000001440000 + + -c: + With the "-c" command you can read the clock values of the TPM. + + -d: + With the "-d" command you can issue a TPM shutdown. It has 2 options: + ./eltt2 -d + or + ./eltt2 -d clear send a TPM2_Shutdown command with shutdown type CLEAR to + the TPM. + ./eltt2 -d state send a TPM2_Shutdown command with shutdown type STATE to + the TPM. + + -e: + With the "-e" command you can extend bytes in the selected PCR with SHA-1. + To do so, you have to enter the index of PCR in hexadecimal that you like to + extend and the digest you want to extend the selected PCR with. Note that + you can only extend PCRs with index 0 to 16 and PCR 23 and that the digest + must have a length of 20 bytes (will be padded with 0 if necessary). + The TPM then builds an SHA-1 hash over the PCR data in the selected PCR and + the digest you provided and writes the result back to the selected PCR. + For example, use the following command to extend PCR 23 (0x17) with the byte + sequence {0x41, 0x62, 0x43, 0x64, 0x00, ... (will be filled with 0x00)}: + ./eltt2 -e 17 41624364 + + -E: + With the "-E" command you can extend bytes in the selected PCR with SHA-256. + To do so, you have to enter the index of PCR in hexadecimal that you like to + extend and the digest you want to extend the selected PCR with. Note that + you can only extend PCRs with index 0 to 16 and PCR 23 and that the digest + must have a length of 32 bytes (will be padded with 0 if necessary). + The TPM then builds an SHA-256 hash over the PCR data in the selected PCR + and the digest you provided and writes the result back to the selected PCR. + For example, use the following command to extend PCR 23 (0x17) with the byte + sequence {0x41, 0x62, 0x43, 0x64, 0x00, ... (will be filled with 0x00)}: + ./eltt2 -E 17 41624364 + + -g: + With the "-g" command you can read the TPM's fixed properties. + + -v: + With the "-v" command you can read the TPM's variable properties. + + -G: + With the "-G" command you can get a given amount of random bytes. Note that + you can only request a maximum amount of 32 random bytes at once. + For example, use the following command to get 20 (0x14) random bytes: + ./eltt2 -G 14 + + -r: + With the "-r" command you can read data from a selected SHA-1 PCR. + For example, use the following command to read data from PCR 23 (0x17): + ./eltt2 -r 17 + + -R: + With the "-R" command you can read data from a selected SHA-256 PCR. + For example, use the following command to read data from PCR 23 (0x17): + ./eltt2 -R 17 + + -s: + With the "-s" command you can hash given data with the SHA-1 hash algorithm. + This command only allows a limited amount of data to be hashed (depending on + the TPM's maximum input buffer size). + For example, use the following command to hash the byte sequence {0x41, + 0x62, 0x43, 0x64}: + ./eltt2 -s 41624364 + + -S: + With the "-S" command you can hash given data with the SHA-256 hash + algorithm. This command only allows a limited amount of data to be hashed + (depending on the TPM input buffer size). + For example, use the following command to hash the byte sequence {0x41, + 0x62, 0x43, 0x64}: + ./eltt2 -S 41624364 + + -t: + With the "-t" command you can issue a TPM selftest. It has 3 options: + ./eltt2 -t + or + ./eltt2 -t not_full Perform a partial TPM2_Selftest to test previously + untested TPM capabilities. + ./eltt2 -t full Perform a full TPM2_Selftest to test all TPM + capabilities. + ./eltt2 -t incremental Perform a test of selected algorithms. + + -T: + With the "-T" command you can read the results of a previously run selftest. + + -u: + With the "-u" command you can issue a TPM startup command. It has 2 options: + ./eltt2 -u + or + ./eltt2 -u clear send a TPM2_Startup with startup type CLEAR to the TPM. + ./eltt2 -u state send a TPM2_Startup with startup type STATE to the TPM. + + -z: + With the "-z" command you can reset a selected PCR. Note that you can only + reset PCRs 16 and 23 and that the PCR is going to be reset in both banks + (SHA-1 and SHA-256). + For example, use the following command to reset PCR 23 (0x17): + ./eltt2 -z 17 + + +2.2 Examples: + + In order to work with the TPM, perform the following steps: + - Send the TPM2_Startup command: ./eltt2 -u + + + +3. If you have questions + + If you have any questions or problems, please read the section "FAQ and + Troubleshooting" in this document. + In case you still have questions, contact your local Infineon + Representative. + Further information is available at http://www.infineon.com/tpm. + + + +4. Release Info + + This is version 1.1. This version is a general release. + + + +5. FAQ and Troubleshooting + + If you encounter any error, please make sure that + - the TPM is properly connected. + - the TPM driver is loaded, i.e. check that "/dev/tpm0" exists. In case of + driver loading problems (e.g. shown by "Error opening device"), reboot + your system and try to load the driver again. + - ELTT2 has been started with root permissions. Please note that ELTT2 needs + root permissions for all commands. + - the TPM is started. (See section 2.2 in this document on how to do this.) + - Trousers do not run anymore. In some cases the Kernel starts Trousers by + booting. + Shut down Trousers by entering the following command: + sudo pkill tcsd + + The following list shows the most common errors and their solution: + + The ELTT2 response is "Error opening the device.": + - You need to load a TPM driver before you can work with ELTT2. + - You need to start ELTT2 with root permissions. + + The ELTT2 responds with error code 0x100. + - You need to send the TPM2_Startup command, or you did send it twice. In + case you have not sent it yet, do so with "./eltt2 -u". + + The TPM does not change any of the permanent flags shown by sending the "-g" + command , e.g. after a force clear. + - The TPM requires a reset in order to change any of the permanent flags. + Press the reset button or disconnect the TPM to do so. + + The value of a PCR does not change after sending PCR extend or reset. + - With the application permissions you cannot modify every PCR. For more + details, please refer to the description for the different PCR commands + in this file. diff --git a/eltt2.c b/eltt2.c index 892d1dd..62d9a4b 100644 --- a/eltt2.c +++ b/eltt2.c @@ -1,9 +1,9 @@ /** - * @brief Embedded Linux TPM Toolbox 2 (ELTT2) - * @details eltt2.c implements some basic methods to communicate with the Infineon TPM 2.0 without the TDDL lib. - * @file eltt2.c - * @date 2014/06/26 - * @copyright Copyright (c) 2014, Infineon Technologies AG\n + * @brief Embedded Linux TPM Toolbox 2 (ELTT2) + * @details eltt2.c implements some basic methods to communicate with the Infineon TPM 2.0 without the TDDL lib. + * @file eltt2.c + * @date 2014/06/26 + * @copyright Copyright (c) 2014 - 2017 Infineon Technologies AG ( www.infineon.com ).\n * All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following @@ -28,1474 +28,1632 @@ #include "eltt2.h" /** - * @brief Main entry point of the application. - * @details Handles the command line input and starts the communication with the TPM. - * @param [in] argc Counter for input parameters. - * @param [in] **argv Input parameters. - * @return One of the listed return codes, the TPM return code or the error code stored in the global errno system variable. - * @retval EXIT_SUCCESS In case of success. - * @retval ERR_BAD_CMD In case an invalid command line option. - * @retval value of errno In case of memory allocation error. - * @retval tpmtool_transmit All error codes from tpmtool_transmit. - * @retval return_error_handling All error codes from return_error_handling. - * @retval response_print All error codes from response_print. - * @retval create_hash_sequence All error codes from create_hash_sequence. - * @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray. - * @retval pcr_extend All error codes from pcr_extend. - * @retval get_random All error codes from get_random. - * @retval pcr_read All error codes from pcr_read. - * @retval create_hash All error codes from create_hash. - * @retval pcr_reset All error codes from pcr_reset. - * @date 2014/06/26 + * @brief Main entry point of the application. + * @details Handles the command line input and starts the communication with the TPM. + * @param [in] argc Counter for input parameters. + * @param [in] **argv Input parameters. + * @return One of the listed return codes, the TPM return code or the error code stored in the global errno system variable. + * @retval EXIT_SUCCESS In case of success. + * @retval ERR_BAD_CMD In case an invalid command line option. + * @retval value of errno In case of memory allocation error. + * @retval tpmtool_transmit All error codes from tpmtool_transmit. + * @retval return_error_handling All error codes from return_error_handling. + * @retval response_print All error codes from response_print. + * @retval create_hash_sequence All error codes from create_hash_sequence. + * @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray. + * @retval pcr_extend All error codes from pcr_extend. + * @retval get_random All error codes from get_random. + * @retval pcr_read All error codes from pcr_read. + * @retval create_hash All error codes from create_hash. + * @retval pcr_reset All error codes from pcr_reset. + * @date 2014/06/26 */ int main(int argc, char **argv) { - // ---------- Local declarations ---------- - int ret_val = EXIT_SUCCESS; // Return value. - uint8_t *tpm_response_buf = NULL; // Buffer for TPM response. - ssize_t tpm_response_buf_size = 0; // Size of tpm_response_buf. - int i = 0; // Command line parsing counter. - int option = 0; // Command line option. - uint8_t *input_bytes = NULL; // Custom command bytes for transmit in case of command line options -b and -E. - size_t input_bytes_size = 0; // Size of input_bytes. - int no_transmission = 0; // Flag to skip the transmission call, e.g. in case of command line option -h. - int tpm_error = 0; // Flag to indicate whether a TPM response has returned a TPM error code or not. - - // ---------- Program flow ---------- - printf("\n"); - do // Begin of DO WHILE(FALSE) for error handling. - { - // ---------- Allocate memory for buffer containing TPM response ---------- - tpm_response_buf_size = TPM_RESP_MAX_SIZE; - tpm_response_buf = malloc(tpm_response_buf_size); - MALLOC_ERROR_CHECK(tpm_response_buf); - memset(tpm_response_buf, 0xFF, tpm_response_buf_size); - - // ---------- Check for command line parameters ---------- - if (1 == argc) - { - fprintf(stderr, "ELTT needs an option. Use '-h' for displaying help.\n"); - ret_val = ERR_BAD_CMD; - break; - } - - // ---------- Command line parsing with getopt ---------- - opterr = 0; // Disable getopt error messages in case of unknown parameters; we want to use our own error messages. - - // Loop through parameters with getopt. - while (-1 != (option = getopt(argc, argv, "cgvhTa:A:b:d:e:E:G:r:R:s:S:t:u:z:"))) - { - switch (option) - { - case 'a': // TPM2_HashSequenceStart SHA-1 - case 'A': // TPM2_HashSequenceStart SHA-256 - ret_val = create_hash_sequence(optarg, option, tpm_response_buf, &tpm_response_buf_size); - break; - - case 'b': // Enter your own command bytes - // Allocate the input buffer for hexstr_to_bytearray and tpmtool_transmit. - input_bytes_size = strlen(optarg) / 2 + strlen(optarg) % 2; // 2 characters == 1 byte => size of input command bytes: length of input string / 2. - input_bytes = malloc(input_bytes_size); - MALLOC_ERROR_CHECK(input_bytes); - memset(input_bytes, 0xFF, input_bytes_size); - - // Convert the command line input to bytes. - ret_val = hexstr_to_bytearray(optarg, input_bytes, input_bytes_size); - RET_VAL_CHECK(ret_val); - - // Send bytes to TPM. - ret_val = tpmtool_transmit(input_bytes, input_bytes_size, tpm_response_buf, &tpm_response_buf_size); - break; - - case 'c': // TPM_CC_ReadClock - ret_val = tpmtool_transmit(tpm_cc_readclock, sizeof(tpm_cc_readclock), tpm_response_buf, &tpm_response_buf_size); - break; - - case 'd': // TPM_CC_Shutdown - if (0 == strcasecmp(optarg, "clear")) - { - ret_val = tpmtool_transmit(tpm_cc_shutdown_clear, sizeof(tpm_cc_shutdown_clear), tpm_response_buf, &tpm_response_buf_size); - } - else if (0 == strcasecmp(optarg, "state")) - { - ret_val = tpmtool_transmit(tpm_cc_shutdown_state, sizeof(tpm_cc_shutdown_state), tpm_response_buf, &tpm_response_buf_size); - } - else - { - ret_val = ERR_BAD_CMD; - fprintf(stderr, "Unknown option. Use '-h' for more information.\n"); - } - break; - - case 'e': // PCR_Extend SHA-1 - case 'E': // PCR_Extend SHA-256 - if (4 > argc) - { - ret_val = ERR_BAD_CMD; - fprintf(stderr, "The command '-%c' needs two arguments. Use '-h' for more information.\n", option); - - // Set the argument count to the next option for error handling. - optind += 2; - break; - } - - // Allocate the input buffer for pcr_extend and tpmtool_transmit. - if ('e' == option) - { - input_bytes_size = sizeof(tpm2_pcr_extend) + TPM_SHA1_DIGEST_SIZE; - } - else - { - input_bytes_size = sizeof(tpm2_pcr_extend) + TPM_SHA256_DIGEST_SIZE; - } - input_bytes = malloc(input_bytes_size); - MALLOC_ERROR_CHECK(input_bytes); - memset(input_bytes, 0, input_bytes_size); - - // Create PCR_Extend TPM request. - ret_val = pcr_extend(optarg, argv[optind], input_bytes, input_bytes_size, option); - - // Set the argument count to the next option for error handling. - optind++; - RET_VAL_CHECK(ret_val); - - // Send bytes to TPM. - ret_val = tpmtool_transmit(input_bytes, input_bytes_size, tpm_response_buf, &tpm_response_buf_size); - break; - - case 'g': // TPM_CC_GetCapability - ret_val = tpmtool_transmit(tpm2_getcapability_fixed, sizeof(tpm2_getcapability_fixed), tpm_response_buf, &tpm_response_buf_size); - break; - - case 'v': // TPM_CC_GetCapability - ret_val = tpmtool_transmit(tpm2_getcapability_var, sizeof(tpm2_getcapability_var), tpm_response_buf, &tpm_response_buf_size); - break; - - case 'G': // TPM_CC_GetRandom - // Allocate the input buffer for get_random and tpmtool_transmit. - input_bytes_size = (sizeof(tpm2_getrandom)); - input_bytes = malloc(input_bytes_size); - MALLOC_ERROR_CHECK(input_bytes); - memset(input_bytes, 0, input_bytes_size); - - // Create GetRandom TPM request. - ret_val = get_random(optarg, input_bytes); - RET_VAL_CHECK(ret_val); - - // Send bytes to TPM. - ret_val = tpmtool_transmit(input_bytes, input_bytes_size, tpm_response_buf, &tpm_response_buf_size); - break; - - case 'h': // Help - print_help(); - - // Set flag to skip any TPM transmission - no_transmission = 1; - break; - - case 'r': // PCR_Read SHA-1 - case 'R': // PCR_Read SHA-256 - // Allocate the input buffer for pcr_read and tpmtool_transmit. - input_bytes_size = sizeof(tpm2_pcr_read); - input_bytes = malloc(input_bytes_size); - MALLOC_ERROR_CHECK(input_bytes); - memset(input_bytes, 0, input_bytes_size); - - // Create PCR_Read TPM request. - ret_val = pcr_read(optarg, input_bytes, option); - RET_VAL_CHECK(ret_val); - - // Send bytes to TPM. - ret_val = tpmtool_transmit(input_bytes, input_bytes_size, tpm_response_buf, &tpm_response_buf_size); - break; - - case 's': // Hash SHA-1 - case 'S': // Hash SHA-256 - // Allocate the input buffer for create_hash and tpmtool_transmit. - input_bytes_size = strlen(optarg) / 2 + strlen(optarg) % 2 + sizeof(tpm2_hash); - input_bytes = malloc(input_bytes_size); - MALLOC_ERROR_CHECK(input_bytes); - memset(input_bytes, 0, input_bytes_size); - - // Create Hash TPM request. - ret_val = create_hash(optarg, option, input_bytes, input_bytes_size); - RET_VAL_CHECK(ret_val); - - // Send bytes to TPM. - ret_val = tpmtool_transmit(input_bytes, input_bytes_size, tpm_response_buf, &tpm_response_buf_size); - break; - - case 't': // TPM2_SelfTest - if (0 == strcasecmp(optarg, "not_full")) - { - ret_val = tpmtool_transmit(tpm2_self_test, sizeof(tpm2_self_test), tpm_response_buf, &tpm_response_buf_size); - } - else if (0 == strcasecmp(optarg, "full")) - { - ret_val = tpmtool_transmit(tpm2_self_test_full, sizeof(tpm2_self_test_full), tpm_response_buf, &tpm_response_buf_size); - } - else if (0 == strcasecmp(optarg, "incremental")) - { - ret_val = tpmtool_transmit(tpm2_self_test_incremental, sizeof(tpm2_self_test_incremental), tpm_response_buf, &tpm_response_buf_size); - } - else - { - ret_val = ERR_BAD_CMD; - fprintf(stderr, "Unknown option. Use '-h' for more information.\n"); - } - break; - - case 'T': // TPM_CC_GetTestResult - ret_val = tpmtool_transmit(tpm_cc_get_test_result, sizeof(tpm_cc_get_test_result), tpm_response_buf, &tpm_response_buf_size); - break; - - case 'u': // TPM2_Startup - if (0 == strcasecmp(optarg, "clear")) - { - ret_val = tpmtool_transmit(tpm2_startup_clear, sizeof(tpm2_startup_clear), tpm_response_buf, &tpm_response_buf_size); - } - else if (0 == strcasecmp(optarg, "state")) - { - ret_val = tpmtool_transmit(tpm2_startup_state, sizeof(tpm2_startup_state), tpm_response_buf, &tpm_response_buf_size); - } - else - { - ret_val = ERR_BAD_CMD; - fprintf(stderr, "Unknown option. Use '-h' for more information.\n"); - } - break; - - case 'z': // PCR_Reset - // Allocate the input buffer for pcr_reset and tpmtool_transmit - input_bytes_size = sizeof(tpm2_pcr_reset); - input_bytes = malloc(input_bytes_size); - MALLOC_ERROR_CHECK(input_bytes); - memset(input_bytes, 0, input_bytes_size); - - // Create PCR_Reset TPM request. - ret_val = pcr_reset(optarg, input_bytes); - RET_VAL_CHECK(ret_val); - - // Send bytes to TPM. - ret_val = tpmtool_transmit(input_bytes, input_bytes_size, tpm_response_buf, &tpm_response_buf_size); - break; - - default: - if ('a' == optopt || 'A' == optopt || 'b' == optopt || 'e' == optopt || 'E' == optopt || 'G' == optopt || - 'r' == optopt || 'R' == optopt || 's' == optopt || 'S' == optopt || 'z' == optopt) - { - // Error output if arguments are missing. - fprintf(stderr, "Option '-%c' requires additional arguments. Use '-h' for more information.\n", optopt); - ret_val = ERR_BAD_CMD; - } - else if ('d' == optopt) - { - // TPM shutdown default option without parameter (default is tpm_cc_shutdown_clear). - ret_val = tpmtool_transmit(tpm_cc_shutdown_clear, sizeof(tpm_cc_shutdown_clear), tpm_response_buf, &tpm_response_buf_size); - option='d'; // for response_print handler - } - else if ('t' == optopt) - { - // TPM shutdown default option without parameter (default is tpm2_self_test). - ret_val = tpmtool_transmit(tpm2_self_test, sizeof(tpm2_self_test), tpm_response_buf, &tpm_response_buf_size); - option='t'; // for response_print handler - } - else if ('u' == optopt) - { - // TPM startup default option without parameter (default is tpm2_startup_clear). - ret_val = tpmtool_transmit(tpm2_startup_clear, sizeof(tpm2_startup_clear), tpm_response_buf, &tpm_response_buf_size); - option='u'; // for response_print handler - } - else if (isprint(optopt)) - { - // Unknown parameter. - fprintf(stderr, "Unknown option '-%c'. Use '-h' for more information.\n", optopt); - ret_val = ERR_BAD_CMD; - } - else - { - // Non-printable character. - fprintf(stderr, "Invalid command line character. Use '-h' for more information.\n"); - ret_val = ERR_BAD_CMD; - } - break; - } // End of switch. - - // ---------- Output and error handling ---------- - // Check for transmission errors or skipped transmission. - if (EXIT_SUCCESS != ret_val || 1 == no_transmission) - { - // Exit command line parameter parsing loop. - break; - } - - // Transmission has been successful, now get TPM return code from TPM response. - ret_val = return_error_handling(tpm_response_buf); - if (EXIT_SUCCESS != ret_val) // Check for errors - { - // Set flag to indicate a TPM error. - tpm_error = 1; - - // Go out of command line parameter parsing loop. - break; - } - - // Print TPM response - ret_val = response_print(tpm_response_buf, tpm_response_buf_size, option); - RET_VAL_CHECK(ret_val); - - // Free memory for next command line option - MEMSET_FREE(input_bytes, input_bytes_size); - } // End of while (cmd line parameter parsing loop). - - // If no error has ocurred so far, handle remaining unknown parameters, if present. - RET_VAL_CHECK(ret_val); // If we do not check and break here in case of an error, we would override the previous error - for (i = optind; i < argc; i++) - { - ret_val = ERR_BAD_CMD; - fprintf(stderr, "Non-option argument '%s'. Use '-h' for more information.\n", argv[i]); - } - } while (0); // End of DO WHILE FALSE loop. - - // Check for non-TPM error. - if (EXIT_SUCCESS != ret_val && 1 != tpm_error) - { - fprintf(stderr, "Unexpected error: 0x%08X\n", ret_val); - } - - // Map TPM return value 0x100 (TPM_RC_INITIALIZE) to 0x101 (TPM_RC_FAILURE), since in case you - // run ELTT 2 in a python script only the lowest byte of the return code is actually being returned. - // But since the lowest byte of 0x100 is 0x00 (== TPM_RC_SUCCESS), python would not be able to - // distinguish between 0x000 and 0x100 as return code, therefore we need the mapping. - if (TPM_RC_INITIALIZE == ret_val) - { - ret_val = TPM_RC_FAILURE; - } - - // ---------- Cleanup ---------- - MEMSET_FREE(tpm_response_buf, tpm_response_buf_size); - MEMSET_FREE(input_bytes, input_bytes_size); - - printf("\n"); - return ret_val; + // ---------- Local declarations ---------- + int ret_val = EXIT_SUCCESS; // Return value. + uint8_t *tpm_response_buf = NULL; // Buffer for TPM response. + ssize_t tpm_response_buf_size = 0; // Size of tpm_response_buf. + int i = 0; // Command line parsing counter. + int option = 0; // Command line option. + uint8_t *input_bytes = NULL; // Custom command bytes for transmit in case of command line options -b and -E. + size_t input_bytes_size = 0; // Size of input_bytes. + int no_transmission = 0; // Flag to skip the transmission call, e.g. in case of command line option -h. + int tpm_error = 0; // Flag to indicate whether a TPM response has returned a TPM error code or not. + + // ---------- Program flow ---------- + printf("\n"); + do // Begin of DO WHILE(FALSE) for error handling. + { + // ---------- Allocate memory for buffer containing TPM response ---------- + tpm_response_buf_size = TPM_RESP_MAX_SIZE; + tpm_response_buf = malloc(tpm_response_buf_size); + MALLOC_ERROR_CHECK(tpm_response_buf); + memset(tpm_response_buf, 0xFF, tpm_response_buf_size); + + // ---------- Check for command line parameters ---------- + if (1 == argc) + { + fprintf(stderr, "ELTT needs an option. Use '-h' for displaying help.\n"); + ret_val = ERR_BAD_CMD; + break; + } + + // ---------- Command line parsing with getopt ---------- + opterr = 0; // Disable getopt error messages in case of unknown parameters; we want to use our own error messages. + + // Loop through parameters with getopt. + while (-1 != (option = getopt(argc, argv, "cgvhTa:A:b:d:e:E:G:r:R:s:S:t:u:z:"))) + { + switch (option) + { + case 'a': // TPM2_HashSequenceStart SHA-1 + case 'A': // TPM2_HashSequenceStart SHA-256 + ret_val = create_hash_sequence(optarg, option, tpm_response_buf, &tpm_response_buf_size); + break; + + case 'b': // Enter your own command bytes + // Allocate the input buffer for hexstr_to_bytearray and tpmtool_transmit. + input_bytes_size = strlen(optarg) / HEX_BYTE_STRING_LENGTH + strlen(optarg) % HEX_BYTE_STRING_LENGTH; // 2 characters == 1 byte => size of input command bytes: length of input string / 2. + input_bytes = malloc(input_bytes_size); + MALLOC_ERROR_CHECK(input_bytes); + memset(input_bytes, 0xFF, input_bytes_size); + + // Convert the command line input to bytes. + ret_val = hexstr_to_bytearray(optarg, input_bytes, input_bytes_size); + RET_VAL_CHECK(ret_val); + + // Send bytes to TPM. + ret_val = tpmtool_transmit(input_bytes, input_bytes_size, tpm_response_buf, &tpm_response_buf_size); + break; + + case 'c': // TPM_CC_ReadClock + ret_val = tpmtool_transmit(tpm_cc_readclock, sizeof(tpm_cc_readclock), tpm_response_buf, &tpm_response_buf_size); + break; + + case 'd': // TPM_CC_Shutdown + if (0 == strcasecmp(optarg, "clear")) + { + ret_val = tpmtool_transmit(tpm_cc_shutdown_clear, sizeof(tpm_cc_shutdown_clear), tpm_response_buf, &tpm_response_buf_size); + } + else if (0 == strcasecmp(optarg, "state")) + { + ret_val = tpmtool_transmit(tpm_cc_shutdown_state, sizeof(tpm_cc_shutdown_state), tpm_response_buf, &tpm_response_buf_size); + } + else + { + ret_val = ERR_BAD_CMD; + fprintf(stderr, "Unknown option. Use '-h' for more information.\n"); + } + break; + + case 'e': // PCR_Extend SHA-1 + case 'E': // PCR_Extend SHA-256 + if (4 > argc) + { + ret_val = ERR_BAD_CMD; + fprintf(stderr, "The command '-%c' needs two arguments. Use '-h' for more information.\n", option); + + // Set the argument count to the next option for error handling. + optind += 2; + break; + } + + // Allocate the input buffer for pcr_extend and tpmtool_transmit. + if ('e' == option) + { + input_bytes_size = sizeof(tpm2_pcr_extend) + TPM_SHA1_DIGEST_SIZE; + } + else + { + input_bytes_size = sizeof(tpm2_pcr_extend) + TPM_SHA256_DIGEST_SIZE; + } + input_bytes = malloc(input_bytes_size); + MALLOC_ERROR_CHECK(input_bytes); + memset(input_bytes, 0, input_bytes_size); + + // Create PCR_Extend TPM request. + ret_val = pcr_extend(optarg, argv[optind], input_bytes, input_bytes_size, option); + + // Set the argument count to the next option for error handling. + optind++; + RET_VAL_CHECK(ret_val); + + // Send bytes to TPM. + ret_val = tpmtool_transmit(input_bytes, input_bytes_size, tpm_response_buf, &tpm_response_buf_size); + break; + + case 'g': // TPM_CC_GetCapability + ret_val = tpmtool_transmit(tpm2_getcapability_fixed, sizeof(tpm2_getcapability_fixed), tpm_response_buf, &tpm_response_buf_size); + break; + + case 'v': // TPM_CC_GetCapability + ret_val = tpmtool_transmit(tpm2_getcapability_var, sizeof(tpm2_getcapability_var), tpm_response_buf, &tpm_response_buf_size); + break; + + case 'G': // TPM_CC_GetRandom + // Allocate the input buffer for get_random and tpmtool_transmit. + input_bytes_size = (sizeof(tpm2_getrandom)); + input_bytes = malloc(input_bytes_size); + MALLOC_ERROR_CHECK(input_bytes); + memset(input_bytes, 0, input_bytes_size); + + // Create GetRandom TPM request. + ret_val = get_random(optarg, input_bytes); + RET_VAL_CHECK(ret_val); + + // Send bytes to TPM. + ret_val = tpmtool_transmit(input_bytes, input_bytes_size, tpm_response_buf, &tpm_response_buf_size); + break; + + case 'h': // Help + print_help(); + + // Set flag to skip any TPM transmission + no_transmission = 1; + break; + + case 'r': // PCR_Read SHA-1 + case 'R': // PCR_Read SHA-256 + // Allocate the input buffer for pcr_read and tpmtool_transmit. + input_bytes_size = sizeof(tpm2_pcr_read); + input_bytes = malloc(input_bytes_size); + MALLOC_ERROR_CHECK(input_bytes); + memset(input_bytes, 0, input_bytes_size); + + // Create PCR_Read TPM request. + ret_val = pcr_read(optarg, input_bytes, option); + RET_VAL_CHECK(ret_val); + + // Send bytes to TPM. + ret_val = tpmtool_transmit(input_bytes, input_bytes_size, tpm_response_buf, &tpm_response_buf_size); + break; + + case 's': // Hash SHA-1 + case 'S': // Hash SHA-256 + // Allocate the input buffer for create_hash and tpmtool_transmit. + input_bytes_size = strlen(optarg) / HEX_BYTE_STRING_LENGTH + strlen(optarg) % HEX_BYTE_STRING_LENGTH + sizeof(tpm2_hash); + input_bytes = malloc(input_bytes_size); + MALLOC_ERROR_CHECK(input_bytes); + memset(input_bytes, 0, input_bytes_size); + + // Create Hash TPM request. + ret_val = create_hash(optarg, option, input_bytes, input_bytes_size); + RET_VAL_CHECK(ret_val); + + // Send bytes to TPM. + ret_val = tpmtool_transmit(input_bytes, input_bytes_size, tpm_response_buf, &tpm_response_buf_size); + break; + + case 't': // TPM2_SelfTest + if (0 == strcasecmp(optarg, "not_full")) + { + ret_val = tpmtool_transmit(tpm2_self_test, sizeof(tpm2_self_test), tpm_response_buf, &tpm_response_buf_size); + } + else if (0 == strcasecmp(optarg, "full")) + { + ret_val = tpmtool_transmit(tpm2_self_test_full, sizeof(tpm2_self_test_full), tpm_response_buf, &tpm_response_buf_size); + } + else if (0 == strcasecmp(optarg, "incremental")) + { + ret_val = tpmtool_transmit(tpm2_self_test_incremental, sizeof(tpm2_self_test_incremental), tpm_response_buf, &tpm_response_buf_size); + } + else + { + ret_val = ERR_BAD_CMD; + fprintf(stderr, "Unknown option. Use '-h' for more information.\n"); + } + break; + + case 'T': // TPM_CC_GetTestResult + ret_val = tpmtool_transmit(tpm_cc_get_test_result, sizeof(tpm_cc_get_test_result), tpm_response_buf, &tpm_response_buf_size); + break; + + case 'u': // TPM2_Startup + if (0 == strcasecmp(optarg, "clear")) + { + ret_val = tpmtool_transmit(tpm2_startup_clear, sizeof(tpm2_startup_clear), tpm_response_buf, &tpm_response_buf_size); + } + else if (0 == strcasecmp(optarg, "state")) + { + ret_val = tpmtool_transmit(tpm2_startup_state, sizeof(tpm2_startup_state), tpm_response_buf, &tpm_response_buf_size); + } + else + { + ret_val = ERR_BAD_CMD; + fprintf(stderr, "Unknown option. Use '-h' for more information.\n"); + } + break; + + case 'z': // PCR_Reset + // Allocate the input buffer for pcr_reset and tpmtool_transmit + input_bytes_size = sizeof(tpm2_pcr_reset); + input_bytes = malloc(input_bytes_size); + MALLOC_ERROR_CHECK(input_bytes); + memset(input_bytes, 0, input_bytes_size); + + // Create PCR_Reset TPM request. + ret_val = pcr_reset(optarg, input_bytes); + RET_VAL_CHECK(ret_val); + + // Send bytes to TPM. + ret_val = tpmtool_transmit(input_bytes, input_bytes_size, tpm_response_buf, &tpm_response_buf_size); + break; + + default: + if ('a' == optopt || 'A' == optopt || 'b' == optopt || 'e' == optopt || 'E' == optopt || 'G' == optopt || + 'r' == optopt || 'R' == optopt || 's' == optopt || 'S' == optopt || 'z' == optopt) + { + // Error output if arguments are missing. + fprintf(stderr, "Option '-%c' requires additional arguments. Use '-h' for more information.\n", optopt); + ret_val = ERR_BAD_CMD; + } + else if ('d' == optopt) + { + // TPM shutdown default option without parameter (default is tpm_cc_shutdown_clear). + ret_val = tpmtool_transmit(tpm_cc_shutdown_clear, sizeof(tpm_cc_shutdown_clear), tpm_response_buf, &tpm_response_buf_size); + option='d'; // for response_print handler + } + else if ('t' == optopt) + { + // TPM shutdown default option without parameter (default is tpm2_self_test). + ret_val = tpmtool_transmit(tpm2_self_test, sizeof(tpm2_self_test), tpm_response_buf, &tpm_response_buf_size); + option='t'; // for response_print handler + } + else if ('u' == optopt) + { + // TPM startup default option without parameter (default is tpm2_startup_clear). + ret_val = tpmtool_transmit(tpm2_startup_clear, sizeof(tpm2_startup_clear), tpm_response_buf, &tpm_response_buf_size); + option='u'; // for response_print handler + } + else if (isprint(optopt)) + { + // Unknown parameter. + fprintf(stderr, "Unknown option '-%c'. Use '-h' for more information.\n", optopt); + ret_val = ERR_BAD_CMD; + } + else + { + // Non-printable character. + fprintf(stderr, "Invalid command line character. Use '-h' for more information.\n"); + ret_val = ERR_BAD_CMD; + } + break; + } // End of switch. + + // ---------- Output and error handling ---------- + // Check for transmission errors or skipped transmission. + if (EXIT_SUCCESS != ret_val || 1 == no_transmission) + { + // Exit command line parameter parsing loop. + break; + } + + // Transmission has been successful, now get TPM return code from TPM response. + ret_val = return_error_handling(tpm_response_buf); + if (EXIT_SUCCESS != ret_val) // Check for errors + { + // Set flag to indicate a TPM error. + tpm_error = 1; + + // Go out of command line parameter parsing loop. + break; + } + + // Print TPM response + ret_val = response_print(tpm_response_buf, tpm_response_buf_size, option); + RET_VAL_CHECK(ret_val); + + // Free memory for next command line option + MEMSET_FREE(input_bytes, input_bytes_size); + } // End of while (command line parameter parsing loop). + + // If no error has occurred so far, handle remaining unknown parameters, if present. + RET_VAL_CHECK(ret_val); // If we do not check and break here in case of an error, we would override the previous error + for (i = optind; i < argc; i++) + { + ret_val = ERR_BAD_CMD; + fprintf(stderr, "Non-option argument '%s'. Use '-h' for more information.\n", argv[i]); + } + } while (0); // End of DO WHILE FALSE loop. + + // Check for non-TPM error. + if (EXIT_SUCCESS != ret_val && 1 != tpm_error) + { + fprintf(stderr, "Unexpected error: 0x%08X\n", ret_val); + } + + // Map TPM return value 0x100 (TPM_RC_INITIALIZE) to 0x101 (TPM_RC_FAILURE), since in case you + // run ELTT 2 in a python script only the lowest byte of the return code is actually being returned. + // But since the lowest byte of 0x100 is 0x00 (== TPM_RC_SUCCESS), python would not be able to + // distinguish between 0x000 and 0x100 as return code, therefore we need the mapping. + if (TPM_RC_INITIALIZE == ret_val) + { + ret_val = TPM_RC_FAILURE; + } + + // ---------- Cleanup ---------- + MEMSET_FREE(tpm_response_buf, tpm_response_buf_size); + MEMSET_FREE(input_bytes, input_bytes_size); + + printf("\n"); + return ret_val; } int tpmtool_transmit(const uint8_t *buf, ssize_t length, uint8_t *response, ssize_t *resp_length) { - // ---------- Transmit command given in buf to device with handle given in dev_tpm ---------- - int ret_val = EXIT_SUCCESS; // Return value. - int dev_tpm = -1; // TPM device handle. - ssize_t transmit_size = 0; // Amount of bytes sent to / received from the TPM. - - do - { - // Check input parameters. - NULL_POINTER_CHECK(buf); - NULL_POINTER_CHECK(response); - NULL_POINTER_CHECK(resp_length); - - // ---------- Open TPM device ---------- - dev_tpm = open("/dev/tpm0", O_RDWR); - if (-1 == dev_tpm) - { - ret_val = errno; - perror("Error opening the device"); - break; - } - - // Send request data to TPM. - transmit_size = write(dev_tpm, buf, length); - if (transmit_size == ERR_COMMUNICATION || length != transmit_size) - { - ret_val = errno; - perror("Error sending request to TPM"); - break; - } - - // Read the TPM response header. - transmit_size = read(dev_tpm, response, TPM_RESP_MAX_SIZE); - if (transmit_size == ERR_COMMUNICATION) - { - ret_val = errno; - perror("Error reading response from TPM"); - break; - } - - // Update response buffer length with value of data length returned by TPM. - *resp_length = transmit_size; - } while (0); - - // ---------- Close TPM device ---------- - if (-1 != dev_tpm) - { - // Close file handle. - close(dev_tpm); - - // Invalidate file handle. - dev_tpm = -1; - } - - return ret_val; + // ---------- Transmit command given in buf to device with handle given in dev_tpm ---------- + int ret_val = EXIT_SUCCESS; // Return value. + int dev_tpm = -1; // TPM device handle. + ssize_t transmit_size = 0; // Amount of bytes sent to / received from the TPM. + + do + { + // Check input parameters. + NULL_POINTER_CHECK(buf); + NULL_POINTER_CHECK(response); + NULL_POINTER_CHECK(resp_length); + + if (0 >= length) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'length' must be larger than 0."); + break; + } + if (TPM_REQ_MAX_SIZE < length) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'length' must be smaller than or equal to %u.", TPM_REQ_MAX_SIZE); + break; + } + if (TPM_CMD_HEADER_SIZE >= *resp_length) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter '*resp_length' must be at least %u.", TPM_CMD_HEADER_SIZE); + break; + } + if (TPM_RESP_MAX_SIZE < *resp_length) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter '*resp_length' must be smaller than or equal to %u.", TPM_RESP_MAX_SIZE); + break; + } + + memset(response, 0, *resp_length); + + // ---------- Open TPM device ---------- + dev_tpm = open("/dev/tpm0", O_RDWR); + if (-1 == dev_tpm) + { + ret_val = errno; + fprintf(stderr, "Error opening the device.\n"); + break; + } + + // Send request data to TPM. + transmit_size = write(dev_tpm, buf, length); + if (transmit_size == ERR_COMMUNICATION || length != transmit_size) + { + ret_val = errno; + fprintf(stderr, "Error sending request to TPM.\n"); + break; + } + + // Read the TPM response header. + transmit_size = read(dev_tpm, response, TPM_RESP_MAX_SIZE); + if (transmit_size == ERR_COMMUNICATION) + { + ret_val = errno; + fprintf(stderr, "Error reading response from TPM.\n"); + break; + } + + // Update response buffer length with value of data length returned by TPM. + *resp_length = transmit_size; + } while (0); + + // ---------- Close TPM device ---------- + if (-1 != dev_tpm) + { + // Close file handle. + close(dev_tpm); + + // Invalidate file handle. + dev_tpm = -1; + } + + return ret_val; } -int return_error_handling(uint8_t *response_buf) +static int return_error_handling(uint8_t *response_buf) { - int ret_val = EXIT_SUCCESS; // Return value. - uint32_t tpm_rc = 0; // Return code from TPM header. + int ret_val = EXIT_SUCCESS; // Return value. + uint64_t tpm_rc = 0; // Return code from TPM header. - do - { - NULL_POINTER_CHECK(response_buf); + do + { + NULL_POINTER_CHECK(response_buf); - ret_val = buf_to_uint64(response_buf, 6, sizeof(tpm_rc), (unsigned long long*)&tpm_rc); - RET_VAL_CHECK(ret_val); + ret_val = buf_to_uint64(response_buf, 6, sizeof(uint32_t), &tpm_rc, TPM_RESP_MAX_SIZE); // TPM Return code type is 32 bit unsigned int! + RET_VAL_CHECK(ret_val); - // Assign TPM return code to ret_val. - ret_val = tpm_rc; + // Assign TPM return code to ret_val. + ret_val = tpm_rc; - if (TPM_RC_SUCCESS != tpm_rc) - { - fprintf(stderr, "TPM Error 0x%08X: ", tpm_rc); - } + if (TPM_RC_SUCCESS != tpm_rc) + { + fprintf(stderr, "TPM Error 0x%.8llX: ", tpm_rc); + } - // Handle some known TPM return codes. - switch (tpm_rc) - { - case TPM_RC_SUCCESS: // 0x00 - break; + // Handle some known TPM return codes. + switch (tpm_rc) + { + case TPM_RC_SUCCESS: // 0x00 + break; - case TPM_RC_BAD_TAG: // 0x1E - fprintf(stderr, "The tag value sent to for a command is invalid.\n"); - break; + case TPM_RC_BAD_TAG: // 0x1E + fprintf(stderr, "The tag value sent to for a command is invalid.\n"); + break; - case TPM_RC_SIZE: // 0x95 - fprintf(stderr, "Structure is the wrong size.\n"); - break; + case TPM_RC_SIZE: // 0x95 + fprintf(stderr, "Structure is the wrong size.\n"); + break; - case TPM_RC_INITIALIZE: // 0x100 - fprintf(stderr, "TPM not initialized.\n"); - break; + case TPM_RC_INITIALIZE: // 0x100 + fprintf(stderr, "TPM not initialized.\n"); + break; - case TPM_RC_LOCALITY: // 0x907 - fprintf(stderr, "Bad locality.\n"); - break; + case TPM_RC_LOCALITY: // 0x907 + fprintf(stderr, "Bad locality.\n"); + break; - default: - fprintf(stderr, "See TPM Library Specification for more information.\n"); - break; - } - } while (0); + default: + fprintf(stderr, "See TPM Library Specification for more information.\n"); + break; + } + } while (0); - return ret_val; + return ret_val; } -int response_print(uint8_t *response_buf, size_t resp_size, int option) +static int response_print(uint8_t *response_buf, size_t resp_size, int option) { - int ret_val = EXIT_SUCCESS; // Return value. - - do - { - NULL_POINTER_CHECK(response_buf); - - switch (option) - { - case 'a': - case 'A': // Print the returned hash number. - ret_val = print_response_buf(response_buf, resp_size, PRINT_RESPONSE_HASH_WITHOUT_HEADER, PRINT_RESPONSE_HASH); - break; - case 'b': // Print the response value in hex. - case 'e': - case 'E': // Print the PCR extend response. - ret_val = print_response_buf(response_buf, resp_size, PRINT_RESPONSE_WITH_HEADER, PRINT_RESPONSE_HEADERBLOCKS); - break; - - case 'c': // Print the TPM clock values. - ret_val = print_clock_info(response_buf); - break; - - case 'd': // Print "Shutdown works as expected." - printf("Shutdown works as expected.\n"); - break; - - case 'g': // Print the fixed capability flags. - ret_val = print_capability_flags(response_buf, PT_FIXED_SELECTOR); - break; - - case 'v': // Print the variable capability flags. - ret_val = print_capability_flags(response_buf, PT_VAR_SELECTOR); - break; - - - case 'G': // Print the returned random value in hex. - printf("Random value:\n"); - ret_val = print_response_buf(response_buf, resp_size, PRINT_RESPONSE_WITHOUT_HEADER, PRINT_RESPONSE_HEX_BLOCK); - break; - - case 'r': - case 'R': // Print the response value in hex. - ret_val = print_response_buf(response_buf, resp_size, PRINT_RESPONSE_PCR_WITHOUT_HEADER, PRINT_RESPONSE_CLEAR); - break; - - case 's': - case 'S': // Print the returned hash number. - ret_val = print_response_buf(response_buf, resp_size, PRINT_RESPONSE_WITHOUT_HEADER, PRINT_RESPONSE_HASH); - break; - - case 't': // Print "Successfully tested. Works as expected." - printf("Successfully tested. Works as expected.\n"); - break; - - case 'T': // Print response value hex without the header. - printf("Test Result: "); - ret_val = print_response_buf(response_buf, resp_size, PRINT_RESPONSE_WITHOUT_HEADER, PRINT_RESPONSE_CLEAR); - break; - - case 'u': // Print "Startup works as expected." - printf("Startup works as expected.\n"); - break; - - default: // Print "Done." - printf("Done.\n"); - break; - } - printf("\n"); - } while (0); - - return ret_val; + int ret_val = EXIT_SUCCESS; // Return value. + + do + { + NULL_POINTER_CHECK(response_buf); + + if (0 >= resp_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'resp_size' must be larger than 0."); + break; + } + if (TPM_RESP_MAX_SIZE < resp_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'resp_size' must be smaller than or equal to %u.\n", TPM_RESP_MAX_SIZE); + break; + } + + switch (option) + { + case 'a': + case 'A': // Print the returned hash number. + ret_val = print_response_buf(response_buf, resp_size, PRINT_RESPONSE_HASH_WITHOUT_HEADER, PRINT_RESPONSE_HASH); + break; + case 'b': // Print the response value in hex. + case 'e': + case 'E': // Print the PCR extend response. + ret_val = print_response_buf(response_buf, resp_size, PRINT_RESPONSE_WITH_HEADER, PRINT_RESPONSE_HEADERBLOCKS); + break; + + case 'c': // Print the TPM clock values. + ret_val = print_clock_info(response_buf); + break; + + case 'd': // Print "Shutdown works as expected." + printf("Shutdown works as expected.\n"); + break; + + case 'g': // Print the fixed capability flags. + ret_val = print_capability_flags(response_buf, PT_FIXED_SELECTOR); + break; + + case 'v': // Print the variable capability flags. + ret_val = print_capability_flags(response_buf, PT_VAR_SELECTOR); + break; + + case 'G': // Print the returned random value in hex. + printf("Random value:\n"); + ret_val = print_response_buf(response_buf, resp_size, PRINT_RESPONSE_WITHOUT_HEADER, PRINT_RESPONSE_HEX_BLOCK); + break; + + case 'r': + case 'R': // Print the response value in hex. + ret_val = print_response_buf(response_buf, resp_size, PRINT_RESPONSE_PCR_WITHOUT_HEADER, PRINT_RESPONSE_CLEAR); + break; + + case 's': + case 'S': // Print the returned hash number. + ret_val = print_response_buf(response_buf, resp_size, PRINT_RESPONSE_WITHOUT_HEADER, PRINT_RESPONSE_HASH); + break; + + case 't': // Print "Successfully tested. Works as expected." + printf("Successfully tested. Works as expected.\n"); + break; + + case 'T': // Print response value hex without the header. + printf("Test Result: "); + ret_val = print_response_buf(response_buf, resp_size, PRINT_RESPONSE_WITHOUT_HEADER, PRINT_RESPONSE_CLEAR); + break; + + case 'u': // Print "Startup works as expected." + printf("Startup works as expected.\n"); + break; + + default: // Print "Done." + printf("Done.\n"); + break; + } + printf("\n"); + } while (0); + + return ret_val; } -int print_response_buf(uint8_t *response_buf, size_t resp_size, uint32_t offset, int format) +static int print_response_buf(uint8_t *response_buf, size_t resp_size, uint32_t offset, int format) { - int ret_val = EXIT_SUCCESS; // Return value. - uint32_t i = 0; // Loop variable. - unsigned long long data_size = 0; // Size of response data. - - do - { - NULL_POINTER_CHECK(response_buf); - - switch (format) - { - case PRINT_RESPONSE_CLEAR: - for (i = 0; i < resp_size - offset; i++) - { - printf("%02X ", response_buf[i + offset]); - } - break; - - case PRINT_RESPONSE_HEADERBLOCKS: - if (TPM_CMD_HEADER_SIZE > resp_size) - { - ret_val = EINVAL; - fprintf(stderr, "Response size is too small.\n"); - break; - } - - printf("TPM Response:\n"); - for (i = 0; i < resp_size - offset; i++) - { - printf("%02X ", response_buf[i + offset]); - if (i == 1) // Bytes 0 and 1 are TPM TAG. - { - printf(" TPM TAG\n"); - } - else if (i == 5) // Bytes 2 to 5 are the response length. - { - printf(" RESPONSE SIZE\n"); - } - else if (i == 9) // Last 4 bytes in header are the TPM return code. - { - printf(" RETURN CODE\n"); - if (i + 1 < resp_size - offset) - { - printf(" Command-specific response Data:\n"); - } - } - else if (i >= 10 && (i+1) % 10 == 0) // After all 10 header bytes have been printed, start new line after every 10 bytes of data. - { - printf("\n"); - } - } - break; - - case PRINT_RESPONSE_HEX_BLOCK: - for (i = 0; i < resp_size - offset; i++) - { - if (i % 16 == 0) - { - printf("\n0x%08X: ", i); - } - printf("0x%02X ", response_buf[i + offset]); - } - break; - - case PRINT_RESPONSE_HASH: - ret_val = buf_to_uint64(response_buf, offset - 2, 2, &data_size); // Data size always should be stored right before the actual data - if (data_size > resp_size - offset) - { - ret_val = EINVAL; - fprintf(stderr, "Invalid response data size.\n"); - break; - } - for (i = 0; i < data_size; i++) - { - if (i % 8 == 0) - { - printf("\n0x%08X: ", i); - } - printf("%02X ", response_buf[i + offset]); - } - break; - - default: - ret_val = EINVAL; - fprintf(stderr, "Unknown output format.\n"); - break; - } - } while (0); - - return ret_val; + int ret_val = EXIT_SUCCESS; // Return value. + uint32_t i = 0; // Loop variable. + uint64_t data_size = 0; // Size of response data. + + do + { + NULL_POINTER_CHECK(response_buf); + + if (0 >= resp_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'resp_size' must be larger than 0."); + break; + } + if (TPM_RESP_MAX_SIZE < resp_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'resp_size' must be smaller than or equal to %u.\n", TPM_RESP_MAX_SIZE); + break; + } + if (resp_size <= offset) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Offset %u cannot be equal or larger than input buffer size %u.\n", offset, resp_size); + break; + } + + switch (format) + { + case PRINT_RESPONSE_CLEAR: + for (i = 0; i < resp_size - offset; i++) + { + printf("%02X ", response_buf[i + offset]); + } + break; + + case PRINT_RESPONSE_HEADERBLOCKS: + if (TPM_CMD_HEADER_SIZE > resp_size) + { + ret_val = EINVAL; + fprintf(stderr, "Response size is too small.\n"); + break; + } + + printf("TPM Response:\n"); + for (i = 0; i < resp_size - offset; i++) + { + printf("%02X ", response_buf[i + offset]); + if (i == 1) // Bytes 0 and 1 are TPM TAG. + { + printf(" TPM TAG\n"); + } + else if (i == 5) // Bytes 2 to 5 are the response length. + { + printf(" RESPONSE SIZE\n"); + } + else if (i == 9) // Last 4 bytes in header are the TPM return code. + { + printf(" RETURN CODE\n"); + if (i + 1 < resp_size - offset) + { + printf(" Command-specific response Data:\n"); + } + } + else if (i >= TPM_CMD_HEADER_SIZE && (i+1) % 10 == 0) // After all header bytes have been printed, start new line after every 10 bytes of data. + { + printf("\n"); + } + } + break; + + case PRINT_RESPONSE_HEX_BLOCK: + for (i = 0; i < resp_size - offset; i++) + { + if (i % 16 == 0) + { + printf("\n0x%08X: ", i); + } + printf("0x%02X ", response_buf[i + offset]); + } + break; + + case PRINT_RESPONSE_HASH: + ret_val = buf_to_uint64(response_buf, offset - sizeof(uint16_t), sizeof(uint16_t), &data_size, resp_size); // Data size actually is only an uint16_t and should always be stored right before the actual data + if (data_size > resp_size - offset) + { + ret_val = EINVAL; + fprintf(stderr, "Invalid response data size.\n"); + break; + } + for (i = 0; i < data_size; i++) + { + if (i % 8 == 0) + { + printf("\n0x%08X: ", i); + } + printf("%02X ", response_buf[i + offset]); + } + break; + + default: + ret_val = EINVAL; + fprintf(stderr, "Unknown output format.\n"); + break; + } + } while (0); + + return ret_val; } -void print_help() +static void print_help() { - printf("'-a ': Hash Sequence SHA1\n"); - printf(" -> Data bytes: Enter a byte sequence like '0F56...' for {0x0f, 0x56, ...}\n"); - printf("'-A ': Hash Sequence SHA256\n"); - printf(" -> Data bytes: Enter a byte sequence like '0F56...' for {0x0f, 0x56, ...}\n"); - printf("'-b ': Enter your own TPM command\n"); - printf(" -> Command bytes: Enter your command bytes in hex like '0f56...' for {0x0f, 0x56, ...}\n"); - printf("'-c': Read Clock\n"); - printf("'-d ': Shutdown\n"); - printf(" -> Shutdown types: clear [default], state\n"); - printf("'-e ': PCR Extend SHA1\n"); - printf(" -> PCR index: Enter the PCR index in hex like '17' for 0x17\n"); - printf(" PCR digest: Enter the value to extend the PCR with in hex like '0f56...' for {0x0f, 0x56, ...}\n"); - printf("'-E ': PCR Extend SHA256\n"); - printf(" -> PCR index: Enter the PCR index in hex like '17' for 0x17\n"); - printf(" PCR digest: Enter the value to extend the PCR with in hex like '0f56...' for {0x0f, 0x56, ...}\n"); - printf("'-g': Get fixed capability values\n"); - printf("'-v': Get variable capability values\n"); - printf("'-G ': Get Random\n"); - printf(" -> Enter desired number of random bytes in hex like '32' for 0x32\n"); - printf("'-h': Help\n"); - printf("'-r ': PCR Read SHA1\n"); - printf(" -> PCR index: Enter PCR number in hex like '17' for 0x17\n"); - printf("'-R ': PCR Read SHA256\n"); - printf(" -> PCR index: Enter PCR number in hex like '17' for 0x17\n"); - printf("'-s ': Hash SHA1\n"); - printf(" -> Data bytes: Enter a byte sequence like '0F56...' for {0x0f, 0x56, ...}\n"); - printf("'-S ': Hash SHA256\n"); - printf(" -> Data bytes: Enter a byte sequence like '0F56...' for {0x0f, 0x56, ...}\n"); - printf("'-t ': SelfTest\n"); - printf(" -> Selftest type: not_full [default], full, incremental\n"); - printf("'-T': Get Test Result\n"); - printf("'-u ': Startup\n"); - printf(" -> Startup types: clear [default], state\n"); - printf("'-z ': PCR Reset\n"); - printf(" -> PCR index: Enter PCR number in hex like '17' for 0x17\n"); + printf("'-a ': Hash Sequence SHA-1\n"); + printf(" -> Data bytes: Enter a byte sequence like '0F56...' for {0x0f, 0x56, ...}\n"); + printf("'-A ': Hash Sequence SHA-256\n"); + printf(" -> Data bytes: Enter a byte sequence like '0F56...' for {0x0f, 0x56, ...}\n"); + printf("'-b ': Enter your own TPM command\n"); + printf(" -> Command bytes: Enter your command bytes in hex like '0f56...' for {0x0f, 0x56, ...}\n"); + printf("'-c': Read Clock\n"); + printf("'-d ': Shutdown\n"); + printf(" -> Shutdown types: clear [default], state\n"); + printf("'-e ': PCR Extend SHA-1\n"); + printf(" -> PCR index: Enter the PCR index in hex like '17' for 0x17\n"); + printf(" PCR digest: Enter the value to extend the PCR with in hex like '0f56...' for {0x0f, 0x56, ...}\n"); + printf("'-E ': PCR Extend SHA-256\n"); + printf(" -> PCR index: Enter the PCR index in hex like '17' for 0x17\n"); + printf(" PCR digest: Enter the value to extend the PCR with in hex like '0f56...' for {0x0f, 0x56, ...}\n"); + printf("'-g': Get fixed capability values\n"); + printf("'-v': Get variable capability values\n"); + printf("'-G ': Get Random\n"); + printf(" -> Enter desired number of random bytes in hex like '32' for 0x32\n"); + printf("'-h': Help\n"); + printf("'-r ': PCR Read SHA-1\n"); + printf(" -> PCR index: Enter PCR number in hex like '17' for 0x17\n"); + printf("'-R ': PCR Read SHA-256\n"); + printf(" -> PCR index: Enter PCR number in hex like '17' for 0x17\n"); + printf("'-s ': Hash SHA-1\n"); + printf(" -> Data bytes: Enter a byte sequence like '0F56...' for {0x0f, 0x56, ...}\n"); + printf("'-S ': Hash SHA-256\n"); + printf(" -> Data bytes: Enter a byte sequence like '0F56...' for {0x0f, 0x56, ...}\n"); + printf("'-t ': SelfTest\n"); + printf(" -> Selftest type: not_full [default], full, incremental\n"); + printf("'-T': Get Test Result\n"); + printf("'-u ': Startup\n"); + printf(" -> Startup types: clear [default], state\n"); + printf("'-z ': PCR Reset SHA-1 and SHA-256\n"); + printf(" -> PCR index: Enter PCR number in hex like '17' for 0x17\n"); } -int print_capability_flags(uint8_t *response_buf, uint8_t cap_selector) +static int print_capability_flags(uint8_t *response_buf, uint8_t cap_selector) { - int ret_val = EXIT_SUCCESS; // Return value. - unsigned long long propertyValue = 0; // Value of the read property. - unsigned long long i = 0, j = 0; // Position counter. - int tmp = 0; // Temporary buffer. - - if(cap_selector == PT_FIXED_SELECTOR) - { - do - { - NULL_POINTER_CHECK(response_buf); - - printf("\nTPM capability information of fixed properties:\n"); - printf("=========================================================\n"); - printf("TPM_PT_FAMILY_INDICATOR: %c%c%c%c\n", response_buf[23], response_buf[24], response_buf[25], response_buf[26]); - - ret_val = buf_to_uint64(response_buf, 31, 4, &propertyValue); - RET_VAL_CHECK(ret_val); - - printf("TPM_PT_LEVEL: %llu\n", propertyValue); - - ret_val = buf_to_uint64(response_buf, 39, 4, &propertyValue); - RET_VAL_CHECK(ret_val); - - printf("TPM_PT_REVISION: %llu\n", propertyValue); - - ret_val = buf_to_uint64(response_buf, 47, 4, &propertyValue); - RET_VAL_CHECK(ret_val); - - printf("TPM_PT_DAY_OF_YEAR: %llu\n", propertyValue); - - ret_val = buf_to_uint64(response_buf, 55, 4, &propertyValue); - RET_VAL_CHECK(ret_val); - - printf("TPM_PT_YEAR: %llu\n", propertyValue); - - printf("TPM_PT_MANUFACTURER: %c%c%c%c\n", response_buf[63], response_buf[64], response_buf[65], response_buf[66]); - - printf("TPM_PT_VENDOR_STRING: "); - printf("%c%c%c%c", response_buf[71], response_buf[72], response_buf[73], response_buf[74]); - printf("%c%c%c%c", response_buf[79], response_buf[80], response_buf[81], response_buf[82]); - printf("%c%c%c%c", response_buf[87], response_buf[88], response_buf[89], response_buf[90]); - printf("%c%c%c%c\n", response_buf[95], response_buf[96], response_buf[97], response_buf[98]); - - ret_val = buf_to_uint64(response_buf, 103, 4, &propertyValue); - RET_VAL_CHECK(ret_val); - - printf("TPM_PT_VENDOR_TPM_TYPE: %llu\n", propertyValue); - - ret_val = buf_to_uint64(response_buf, 111, 2, &propertyValue); - RET_VAL_CHECK(ret_val); - - printf("TPM_PT_FIRMWARE_VERSION: %llu", propertyValue); - ret_val = buf_to_uint64(response_buf, 113, 2, &propertyValue); - RET_VAL_CHECK(ret_val); - - printf(".%llu", propertyValue); - ret_val = buf_to_uint64(response_buf, 119, 2, &propertyValue); // Check for output version. - RET_VAL_CHECK(ret_val); - - if (2 <= propertyValue) // Print the new FIRMWARE_VERSION output. - { - ret_val = buf_to_uint64(response_buf, 120, 2, &propertyValue); - RET_VAL_CHECK(ret_val); - - printf(".%llu", propertyValue); - ret_val = buf_to_uint64(response_buf, 122, 1, &propertyValue); - RET_VAL_CHECK(ret_val); - - printf(".%llu\n", propertyValue); - - } - else // Print the old FIRMWARE_VERSION output. - { - ret_val = buf_to_uint64(response_buf, 119, 4, &propertyValue); - RET_VAL_CHECK(ret_val); - - printf(".%llu\n", propertyValue); - } - - - printf("\nTPM_PT_MEMORY:\n"); - printf("=========================================================\n"); - - ret_val = buf_to_uint64(response_buf, 207, 4, &propertyValue); - RET_VAL_CHECK(ret_val); - - i = 1; // bit 0 - tmp = ((propertyValue & i) == 0? 0:1); // Check bit 0 value. - printf("Shared RAM: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); - - i = i + i; // bit 1 - tmp = ((propertyValue & i) == 0? 0:1); // Check bit 1 value. - printf("Shared NV: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); - - i = i * 2; // bit 2 - tmp = ((propertyValue & i) == 0? 0:1); // Check bit 2 value. - printf("Object Copied To Ram: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); - //bit 31:3 = reserved - - printf("\nTPM_PT_PERMANENT:\n"); - printf("=========================================================\n"); - ret_val = buf_to_uint64(response_buf, 367, 4, &propertyValue); - RET_VAL_CHECK(ret_val); - - i = 1; // bit 0 - tmp = ((propertyValue & i) == 0? 0:1); // Check bit 0 value. - printf("Owner Auth Set: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); - - i = i + i; // bit 1 - tmp = ((propertyValue & i) == 0? 0:1); // Check bit 1 value. - printf("Endorsement Auth Set: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); - - i = i * 2; // bit 2 - tmp = ((propertyValue & i) == 0? 0:1); // Check bit 2 value. - printf("Lockout Auth Set: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); - - i = i * 2; // bit 3 - i = i * 2; // bit 4 - i = i * 2; // bit 5 - i = i * 2; // bit 6 - i = i * 2; // bit 7 - //bit 7:3 = reserved - - i = i * 2; // bit 8 - tmp = ((propertyValue & i) == 0? 0:1); // Check bit 8 value. - printf("Disable Clear: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); - - i = i * 2; // bit 9 - tmp = ((propertyValue & i) == 0? 0:1); // Check bit 9 value. - printf("In Lockout: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); - - i = i * 2; // bit 10 - tmp = ((propertyValue & i) == 0? 0:1); // Check bit 10 value. - printf("TPM Generated EPS: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); - //bit 31:11 = reserved - - } while (0); - } - else if (cap_selector == 2) - { - do - { - - NULL_POINTER_CHECK(response_buf); - - printf("\nTPM capability information of variable properties:\n"); - printf("\n\n"); - - ret_val = buf_to_uint64(response_buf, 31, 4, &propertyValue); - RET_VAL_CHECK(ret_val); - - printf("\nTPM_PT_STARTUP_CLEAR:\n"); - printf("=========================================================\n"); - - i = 1; // bit 0 - tmp = ((propertyValue & i) == 0? 0:1); // Check bit 0 value. - printf("Ph Enable: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); - - i = i + i; // bit 1 - tmp = ((propertyValue & i) == 0? 0:1); // Check bit 1 value. - printf("Sh Enable: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); - - i = i * 2; // bit 2 - tmp = ((propertyValue & i) == 0? 0:1); // Check bit 2 value. - printf("Eh Enable: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); - //bit 30:3 = reserved - for(j = 2; j < 31; j++) // go to bit 31. - { - i = i * 2; - } - tmp = ((propertyValue & i) == 0? 0:1); // Check bit 31 value. - printf("Orderly: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); - - } while (0); - } - - return ret_val; + int ret_val = EXIT_SUCCESS; // Return value. + uint64_t propertyValue = 0; // Value of the read property. + uint64_t i = 0, j = 0; // Position counter. + int tmp = 0; // Temporary buffer. + + do + { + NULL_POINTER_CHECK(response_buf); + + if(cap_selector == PT_FIXED_SELECTOR) + { + printf("\nTPM capability information of fixed properties:\n"); + printf("=========================================================\n"); + printf("TPM_PT_FAMILY_INDICATOR: %c%c%c%c\n", response_buf[23], response_buf[24], response_buf[25], response_buf[26]); + + ret_val = buf_to_uint64(response_buf, 31, 4, &propertyValue, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); + printf("TPM_PT_LEVEL: %llu\n", propertyValue); + + ret_val = buf_to_uint64(response_buf, 39, 4, &propertyValue, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); + printf("TPM_PT_REVISION: %llu\n", propertyValue); + + ret_val = buf_to_uint64(response_buf, 47, 4, &propertyValue, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); + printf("TPM_PT_DAY_OF_YEAR: %llu\n", propertyValue); + + ret_val = buf_to_uint64(response_buf, 55, 4, &propertyValue, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); + printf("TPM_PT_YEAR: %llu\n", propertyValue); + printf("TPM_PT_MANUFACTURER: %c%c%c%c\n", response_buf[63], response_buf[64], response_buf[65], response_buf[66]); + printf("TPM_PT_VENDOR_STRING: "); + printf("%c%c%c%c", response_buf[71], response_buf[72], response_buf[73], response_buf[74]); + printf("%c%c%c%c", response_buf[79], response_buf[80], response_buf[81], response_buf[82]); + printf("%c%c%c%c", response_buf[87], response_buf[88], response_buf[89], response_buf[90]); + printf("%c%c%c%c\n", response_buf[95], response_buf[96], response_buf[97], response_buf[98]); + + ret_val = buf_to_uint64(response_buf, 103, 4, &propertyValue, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); + printf("TPM_PT_VENDOR_TPM_TYPE: %llu\n", propertyValue); + + ret_val = buf_to_uint64(response_buf, 111, 2, &propertyValue, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); + printf("TPM_PT_FIRMWARE_VERSION: %llu", propertyValue); + + ret_val = buf_to_uint64(response_buf, 113, 2, &propertyValue, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); + printf(".%llu", propertyValue); + + ret_val = buf_to_uint64(response_buf, 119, 2, &propertyValue, TPM_RESP_MAX_SIZE); // Check for output version. + RET_VAL_CHECK(ret_val); + + if (2 <= propertyValue) // Print the new FIRMWARE_VERSION output. + { + ret_val = buf_to_uint64(response_buf, 120, 2, &propertyValue, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); + printf(".%llu", propertyValue); + + ret_val = buf_to_uint64(response_buf, 122, 1, &propertyValue, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); + printf(".%llu\n", propertyValue); + + } + else // Print the old FIRMWARE_VERSION output. + { + ret_val = buf_to_uint64(response_buf, 119, 4, &propertyValue, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); + printf(".%llu\n", propertyValue); + } + + printf("\nTPM_PT_MEMORY:\n"); + printf("=========================================================\n"); + + ret_val = buf_to_uint64(response_buf, 207, 4, &propertyValue, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); + + i = 1; // bit 0 + tmp = ((propertyValue & i) == 0? 0:1); // Check bit 0 value. + printf("Shared RAM: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); + + i = i + i; // bit 1 + tmp = ((propertyValue & i) == 0? 0:1); // Check bit 1 value. + printf("Shared NV: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); + + i = i * 2; // bit 2 + tmp = ((propertyValue & i) == 0? 0:1); // Check bit 2 value. + printf("Object Copied To Ram: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); + //bit 31:3 = reserved + + printf("\nTPM_PT_PERMANENT:\n"); + printf("=========================================================\n"); + + ret_val = buf_to_uint64(response_buf, 367, 4, &propertyValue, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); + + i = 1; // bit 0 + tmp = ((propertyValue & i) == 0? 0:1); // Check bit 0 value. + printf("Owner Auth Set: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); + + i = i + i; // bit 1 + tmp = ((propertyValue & i) == 0? 0:1); // Check bit 1 value. + printf("Sendorsement Auth Set: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); + + i = i * 2; // bit 2 + tmp = ((propertyValue & i) == 0? 0:1); // Check bit 2 value. + printf("Lockout Auth Set: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); + + i = i * 2; // bit 3 + i = i * 2; // bit 4 + i = i * 2; // bit 5 + i = i * 2; // bit 6 + i = i * 2; // bit 7 + //bit 7:3 = reserved + + i = i * 2; // bit 8 + tmp = ((propertyValue & i) == 0? 0:1); // Check bit 8 value. + printf("Disable Clear: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); + + i = i * 2; // bit 9 + tmp = ((propertyValue & i) == 0? 0:1); // Check bit 9 value. + printf("In Lockout: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); + + i = i * 2; // bit 10 + tmp = ((propertyValue & i) == 0? 0:1); // Check bit 10 value. + printf("TPM Generated EPS: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); + //bit 31:11 = reserved + + } + else if (cap_selector == 2) + { + NULL_POINTER_CHECK(response_buf); + + printf("\nTPM capability information of variable properties:\n"); + printf("\n\n"); + + ret_val = buf_to_uint64(response_buf, 31, 4, &propertyValue, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); + + printf("\nTPM_PT_STARTUP_CLEAR:\n"); + printf("=========================================================\n"); + + i = 1; // bit 0 + tmp = ((propertyValue & i) == 0? 0:1); // Check bit 0 value. + printf("Ph Enable: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); + + i = i + i; // bit 1 + tmp = ((propertyValue & i) == 0? 0:1); // Check bit 1 value. + printf("Sh Enable: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); + + i = i * 2; // bit 2 + tmp = ((propertyValue & i) == 0? 0:1); // Check bit 2 value. + printf("Eh Enable: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); + //bit 30:3 = reserved + for(j = 2; j < 31; j++) // go to bit 31. + { + i = i * 2; + } + tmp = ((propertyValue & i) == 0? 0:1); // Check bit 31 value. + printf("Orderly: %i %s", (tmp), ((tmp)? "SET\n" : "CLEAR\n")); + + } + } while (0); + + return ret_val; } -int print_clock_info(uint8_t *response_buf) +static int print_clock_info(uint8_t *response_buf) { - int ret_val = EXIT_SUCCESS; // Return value. - unsigned long long propertyValue = 0; // Value of the read property. - unsigned long long tmp_value = 0; // Helper variable for calculating actual values. - unsigned long long sec = 0; // Value for seconds. - unsigned long long tmp = 0; // buf_to_uint64 return value. + int ret_val = EXIT_SUCCESS; // Return value. + uint64_t propertyValue = 0; // Value of the read property. + uint64_t tmp_value = 0; // Helper variable for calculating actual values. + uint64_t sec = 0; // Value for seconds. + uint64_t tmp = 0; // buf_to_uint64 return value. - do - { - NULL_POINTER_CHECK(response_buf); + do + { + NULL_POINTER_CHECK(response_buf); - printf("\nClock info:\n"); - printf("=========================================================\n"); + printf("\nClock info:\n"); + printf("=========================================================\n"); - ret_val = buf_to_uint64(response_buf, 10, 8, &propertyValue); - RET_VAL_CHECK(ret_val); + ret_val = buf_to_uint64(response_buf, TPM_CMD_HEADER_SIZE, 8, &propertyValue, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); - printf("Time since the last TPM_Init:\n%llu ms = ", propertyValue); + printf("Time since the last TPM_Init:\n%llu ms = ", propertyValue); - sec = propertyValue / MILISECOND_TO_SECOND; - tmp_value = sec / YEAR_SECONDS; - printf("%llu y, ", tmp_value); + sec = propertyValue / MILISECOND_TO_SECOND; + tmp_value = sec / YEAR_SECONDS; + printf("%llu y, ", tmp_value); - tmp_value = (sec % YEAR_SECONDS) / DAY_SECONDS; - printf("%llu d, ", tmp_value); + tmp_value = (sec % YEAR_SECONDS) / DAY_SECONDS; + printf("%llu d, ", tmp_value); - tmp_value = ((sec % YEAR_SECONDS) % DAY_SECONDS) / HOUR_SECONDS; - printf("%llu h, ", tmp_value); + tmp_value = ((sec % YEAR_SECONDS) % DAY_SECONDS) / HOUR_SECONDS; + printf("%llu h, ", tmp_value); - tmp_value = (((sec % YEAR_SECONDS) % DAY_SECONDS) % HOUR_SECONDS) / MINUTE_SECONDS; - printf("%llu min, ", tmp_value); + tmp_value = (((sec % YEAR_SECONDS) % DAY_SECONDS) % HOUR_SECONDS) / MINUTE_SECONDS; + printf("%llu min, ", tmp_value); - tmp_value = (((sec % YEAR_SECONDS) % DAY_SECONDS) % HOUR_SECONDS) % MINUTE_SECONDS; - printf("%llu s, ", tmp_value); + tmp_value = (((sec % YEAR_SECONDS) % DAY_SECONDS) % HOUR_SECONDS) % MINUTE_SECONDS; + printf("%llu s, ", tmp_value); - tmp_value = propertyValue % MILISECOND_TO_SECOND; - printf("%llu ms\n\n", tmp_value); + tmp_value = propertyValue % MILISECOND_TO_SECOND; + printf("%llu ms\n\n", tmp_value); - ret_val = buf_to_uint64(response_buf, 18, 8, &propertyValue); - RET_VAL_CHECK(ret_val); + ret_val = buf_to_uint64(response_buf, 18, 8, &propertyValue, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); - printf("Time during which the TPM has been powered:\n%llu ms = ", propertyValue); + printf("Time during which the TPM has been powered:\n%llu ms = ", propertyValue); - sec = propertyValue / MILISECOND_TO_SECOND; - tmp_value = sec / YEAR_SECONDS; - printf("%llu y, ", tmp_value); + sec = propertyValue / MILISECOND_TO_SECOND; + tmp_value = sec / YEAR_SECONDS; + printf("%llu y, ", tmp_value); - tmp_value = (sec % YEAR_SECONDS) / DAY_SECONDS; - printf("%llu d, ", tmp_value); + tmp_value = (sec % YEAR_SECONDS) / DAY_SECONDS; + printf("%llu d, ", tmp_value); - tmp_value = ((sec % YEAR_SECONDS) % DAY_SECONDS) / HOUR_SECONDS; - printf("%llu h, ", tmp_value); + tmp_value = ((sec % YEAR_SECONDS) % DAY_SECONDS) / HOUR_SECONDS; + printf("%llu h, ", tmp_value); - tmp_value = (((sec % YEAR_SECONDS) % DAY_SECONDS) % HOUR_SECONDS) / MINUTE_SECONDS; - printf("%llu min, ", tmp_value); + tmp_value = (((sec % YEAR_SECONDS) % DAY_SECONDS) % HOUR_SECONDS) / MINUTE_SECONDS; + printf("%llu min, ", tmp_value); - tmp_value = (((sec % YEAR_SECONDS) % DAY_SECONDS) % HOUR_SECONDS) % MINUTE_SECONDS; - printf("%llu s, ", tmp_value); + tmp_value = (((sec % YEAR_SECONDS) % DAY_SECONDS) % HOUR_SECONDS) % MINUTE_SECONDS; + printf("%llu s, ", tmp_value); - tmp_value = propertyValue % MILISECOND_TO_SECOND; - printf("%llu ms\n\n", tmp_value); + tmp_value = propertyValue % MILISECOND_TO_SECOND; + printf("%llu ms\n\n", tmp_value); - ret_val = buf_to_uint64(response_buf, 26, 4, &tmp); - RET_VAL_CHECK(ret_val); + ret_val = buf_to_uint64(response_buf, 26, 4, &tmp, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); - printf("TPM Reset since the last TPM2_Clear: %llu\n", tmp); + printf("TPM Reset since the last TPM2_Clear: %llu\n", tmp); - ret_val = buf_to_uint64(response_buf, 30, 4, &tmp); - RET_VAL_CHECK(ret_val); + ret_val = buf_to_uint64(response_buf, 30, 4, &tmp, TPM_RESP_MAX_SIZE); + RET_VAL_CHECK(ret_val); - printf("Number of times that TPM2_Shutdown: %llu\n", tmp); + printf("Number of times that TPM2_Shutdown: %llu\n", tmp); - printf("Safe: %i = %s", response_buf[34], (response_buf[34]? "Yes\n" : "No\n")); - } while (0); + printf("Safe: %i = %s", response_buf[34], (response_buf[34]? "Yes\n" : "No\n")); + } while (0); - return ret_val; + return ret_val; } -int buf_to_uint64(uint8_t *input_buffer, uint32_t offset, uint8_t length, unsigned long long *output_value) +static int buf_to_uint64(uint8_t *input_buffer, uint32_t offset, uint32_t length, uint64_t *output_value, uint32_t input_buffer_size) { - int ret_val = EXIT_SUCCESS; // Return value. - uint32_t i = 0; // Loop variable. - unsigned long long tmp = 0; // Temporary variable for value calculation. - - do - { - NULL_POINTER_CHECK(input_buffer); - NULL_POINTER_CHECK(output_value); - - if (8 >= length) - { - for (i = 0; i < length; i++) - { - tmp = (tmp << 8) + input_buffer[offset + i]; - } - *output_value = tmp; - } - else - { - ret_val = EINVAL; - fprintf(stderr, "Bad parameter. Requested conversion amount of %i is to high. The maximum possible amount is 8 bytes.\n", length); - } - } while (0); - - return ret_val; + int ret_val = EXIT_SUCCESS; // Return value. + uint32_t i = 0; // Loop variable. + uint64_t tmp = 0; // Temporary variable for value calculation. + + do + { + NULL_POINTER_CHECK(input_buffer); + NULL_POINTER_CHECK(output_value); + + *output_value = 0; + + if (offset >= input_buffer_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'input_buffer_size' must be larger than %u.\n", offset); + break; + } + if (INT_MAX < input_buffer_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'input_buffer_size' must be smaller or equal to %u.\n", INT_MAX); + break; + } + if (0 >= length) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'length' must be larger than 0.\n"); + break; + } + if (length > input_buffer_size - offset) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'length' must be smaller or equal to %i.\n", input_buffer_size - offset); + break; + } + if (sizeof(uint64_t) < length) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Input buffer length remaining from offset must be smaller than %u.\n", sizeof(uint64_t)); + break; + } + + for (i = 0; i < length; i++) + { + tmp = (tmp << 8) + input_buffer[offset + i]; + } + *output_value = tmp; + } while (0); + + return ret_val; } -int hexstr_to_bytearray(char *byte_string, uint8_t *byte_values, size_t byte_values_size) +static int hexstr_to_bytearray(char *byte_string, uint8_t *byte_values, size_t byte_values_size) { - int ret_val = EXIT_SUCCESS; // Return value. - char hex_byte[3] = {0}; // Temporary buffer for input bytes. - char* invalidChars = NULL; // Pointer to target buffer where method stores invalid characters. - uint32_t i = 0; // Loop variable. - - do - { - NULL_POINTER_CHECK(byte_string); - NULL_POINTER_CHECK(byte_values); - - if (strlen(byte_string) / 2 + strlen(byte_string) % 2 > byte_values_size) - { - ret_val = EINVAL; - fprintf(stderr, "Input character string is too long for output buffer.\n"); - break; - } - - // Loop "bytewise" through string - for (i = 0; i < strlen(byte_string); i += 2) - { - // Split input string into "bytes" - if (1 == strlen(byte_string + i)) - { - // Assemble a single digit in the hex byte string. - hex_byte[0] = byte_string[i]; - hex_byte[1] = '\0'; - } - else - { - // Assemble a digit pair in the hex byte string. - hex_byte[0] = byte_string[i]; - hex_byte[1] = byte_string[i + 1]; - hex_byte[2] = '\0'; - } - - // Convert the hex string to an integer. - errno = 0; - byte_values[i / 2] = strtoul(hex_byte, &invalidChars, 16); - if (0 != errno) - { - ret_val = errno; - perror("Error parsing string"); - break; - } - if ('\0' != *invalidChars) - { - ret_val = EINVAL; - fprintf(stderr, "Invalid character(s) '%s' while trying to parse '%s' to a byte array.\n", invalidChars, byte_string); - break; - } - } - } while (0); - - return ret_val; + int ret_val = EXIT_SUCCESS; // Return value. + char hex_byte[3] = {0}; // Temporary buffer for input bytes. + char* invalidChars = NULL; // Pointer to target buffer where method stores invalid characters. + uint32_t i = 0; // Loop variable. + uint32_t unStrLen = 0; // Temporary store for byte string length. + + do + { + NULL_POINTER_CHECK(byte_string); + NULL_POINTER_CHECK(byte_values); + + if (0 >= byte_values_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'byte_values_size' must be larger than 0.\n"); + break; + } + if (INT_MAX < byte_values_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'byte_values_size' must be smaller or equal to %u.\n", INT_MAX); + break; + } + + memset(byte_values, 0, byte_values_size); + + unStrLen = strlen(byte_string); + if ((unStrLen / HEX_BYTE_STRING_LENGTH + unStrLen % HEX_BYTE_STRING_LENGTH) > (uint32_t)byte_values_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Input character string is too long for output buffer.\n"); + break; + } + + // Loop "byte-wise" through string + for (i = 0; i < unStrLen; i += HEX_BYTE_STRING_LENGTH) + { + // Split input string into "bytes" + if (1 == strlen(byte_string + i)) + { + // Assemble a single digit in the hex byte string. + hex_byte[0] = byte_string[i]; + hex_byte[1] = '\0'; + hex_byte[2] = '\0'; + } + else + { + // Assemble a digit pair in the hex byte string. + hex_byte[0] = byte_string[i]; + hex_byte[1] = byte_string[i + 1]; + hex_byte[2] = '\0'; + } + + // Convert the hex string to an integer. + errno = 0; + byte_values[i / HEX_BYTE_STRING_LENGTH] = (uint8_t)strtoul(hex_byte, &invalidChars, 16); + if (0 != errno) + { + ret_val = errno; + fprintf(stderr, "Error parsing string.\n"); + break; + } + if ('\0' != *invalidChars) + { + ret_val = EINVAL; + fprintf(stderr, "Invalid character(s) '%s' while trying to parse '%s' to a byte array.\n", invalidChars, byte_string); + break; + } + } + } while (0); + + return ret_val; } -int int_to_bytearray(uint64_t input, uint32_t input_size, uint8_t *output_byte) +static int int_to_bytearray(uint64_t input, uint32_t input_size, uint8_t *output_byte) { - int ret_val = EXIT_SUCCESS; // Return value. - uint32_t i; // For-while-loop counter. - - do - { - NULL_POINTER_CHECK(output_byte); - - for (i = 0; i < input_size; i++) - { - output_byte[i] = input >> ((input_size - 1 - i) * 8); - } - } while (0); - - return ret_val; + int ret_val = EXIT_SUCCESS; // Return value. + uint32_t i; // For-while-loop counter. + + do + { + NULL_POINTER_CHECK(output_byte); + if (0 >= input_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'input_size' must be larger than 0.\n"); + break; + } + if (sizeof(uint64_t) < input_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'input_size' must be smaller or equal to %u.\n", sizeof(uint64_t)); + break; + } + + for (i = 0; i < input_size; i++) + { + output_byte[i] = input >> ((input_size - 1 - i) * 8); + } + } while (0); + + return ret_val; } -int get_random(char *data_length_string, uint8_t *response_buf) +static int get_random(char *data_length_string, uint8_t *response_buf) { - int ret_val = EXIT_SUCCESS; // Return value. - uint8_t bytes_requested = 0; // Amount of random bytes requested by the user. - size_t byte_string_size = 0; // Size of user input. - - do - { - NULL_POINTER_CHECK(data_length_string); - NULL_POINTER_CHECK(response_buf); - - // Get length of command line input. - byte_string_size = strlen(data_length_string) / 2 + strlen(data_length_string) % 2; - if (1 != byte_string_size) - { - ret_val = ERR_BAD_CMD; - fprintf(stderr, "Bad option. Enter a single hex value (2 characters) without leading '0x'.\n"); - break; - } - - // Convert the command line input string for requested random data length to byte. - ret_val = hexstr_to_bytearray(data_length_string, &bytes_requested, 1); - RET_VAL_CHECK(ret_val); - if (32 < bytes_requested || 0 == bytes_requested) - { - ret_val = ERR_BAD_CMD; - fprintf(stderr, "Bad option. Enter a hex value between 0x01 and 0x20.\n"); - break; - } - - // Copy command bytes. - memcpy(response_buf, tpm2_getrandom, sizeof(tpm2_getrandom)); - - // Store amount of requested bytes at the correct byte index in the command byte stream. - response_buf[sizeof(tpm2_getrandom) - 1] = bytes_requested; - } while (0); - - return ret_val; + int ret_val = EXIT_SUCCESS; // Return value. + uint8_t bytes_requested = 0; // Amount of random bytes requested by the user. + size_t byte_string_size = 0; // Size of user input. + + do + { + NULL_POINTER_CHECK(data_length_string); + NULL_POINTER_CHECK(response_buf); + + // Get length of command line input. + byte_string_size = strlen(data_length_string) / HEX_BYTE_STRING_LENGTH + strlen(data_length_string) % HEX_BYTE_STRING_LENGTH; + if (1 != byte_string_size) + { + ret_val = ERR_BAD_CMD; + fprintf(stderr, "Bad option. Enter a single hex value (2 characters) without leading '0x'.\n"); + break; + } + + // Convert the command line input string for requested random data length to byte. + ret_val = hexstr_to_bytearray(data_length_string, &bytes_requested, 1); + RET_VAL_CHECK(ret_val); + if (32 < bytes_requested || 0 == bytes_requested) + { + ret_val = ERR_BAD_CMD; + fprintf(stderr, "Bad option. Enter a hex value between 0x01 and 0x20.\n"); + break; + } + + // Copy command bytes. + memcpy(response_buf, tpm2_getrandom, sizeof(tpm2_getrandom)); + + // Store amount of requested bytes at the correct byte index in the command byte stream. + response_buf[sizeof(tpm2_getrandom) - 1] = bytes_requested; + } while (0); + + return ret_val; } -int create_hash(char *data_string, char option, uint8_t *hash_cmd_buf, uint32_t hash_cmd_buf_size) +static int create_hash(char *data_string, char option, uint8_t *hash_cmd_buf, uint32_t hash_cmd_buf_size) { - int ret_val = EXIT_SUCCESS; // Return value. - uint32_t offset = 0; // Helper offset for generating command request. - uint16_t data_string_size = 0; // Size of user input data. - unsigned long max_data_size = 0; // Maximum supported size for input data. - const uint8_t *tpm_hash_alg = NULL; // Pointer to hash algorithm identifier. - - do - { - NULL_POINTER_CHECK(data_string); - NULL_POINTER_CHECK(hash_cmd_buf); - if ('s' != option && 'S' != option) - { - ret_val = EINVAL; - fprintf(stderr, "Bad parameter. Option argument must be 's' or 'S'.\n"); - break; - } - - // Check input string size. - data_string_size = strlen(data_string) / 2 + strlen(data_string) % 2; - max_data_size = TPM_REQ_MAX_SIZE - sizeof(tpm2_hash); - if (data_string_size > max_data_size) - { - ret_val = ERR_BAD_CMD; - fprintf(stderr, "Bad option. Maximum input data size is %lu byte (%lu characters).\n", max_data_size, max_data_size * 2); - break; - } - - // Copy basic command bytes. - memcpy(hash_cmd_buf, tpm2_hash, sizeof(tpm2_hash)); - - // Set hash algorithm, command and data sizes depending on user input option at the correct byte index in the command byte stream. - if ('s' == option) - { - tpm_hash_alg = sha1_alg; - printf("\nTPM2_Hash of '%s' with SHA-1:\n", data_string); - } - else - { - tpm_hash_alg = sha256_alg; - printf("\nTPM2_Hash of '%s' with SHA-256:\n", data_string); - } - - offset = 2; - ret_val = int_to_bytearray(sizeof(tpm2_hash) + data_string_size, sizeof(uint32_t), hash_cmd_buf + offset); - RET_VAL_CHECK(ret_val); - offset = 10; - ret_val = int_to_bytearray(data_string_size, sizeof(data_string_size), hash_cmd_buf + offset); - RET_VAL_CHECK(ret_val); - offset += sizeof(data_string_size); - - // Copy hash data to TPM request. - ret_val = hexstr_to_bytearray(data_string, hash_cmd_buf + offset, hash_cmd_buf_size - offset); - RET_VAL_CHECK(ret_val); - offset += data_string_size; - - // Set hash algorithm and hierarchy. - memcpy(hash_cmd_buf + offset, tpm_hash_alg, 2); - offset += 2; - memcpy(hash_cmd_buf + offset, tpm_cc_hash_hierarchy, sizeof(tpm_cc_hash_hierarchy)); - } while (0); - - return ret_val; + int ret_val = EXIT_SUCCESS; // Return value. + uint32_t offset = 0; // Helper offset for generating command request. + uint16_t data_string_size = 0; // Size of user input data. + const uint8_t *tpm_hash_alg = NULL; // Pointer to hash algorithm identifier. + + do + { + NULL_POINTER_CHECK(data_string); + NULL_POINTER_CHECK(hash_cmd_buf); + + if ('s' != option && 'S' != option) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Option argument must be 's' or 'S'.\n"); + break; + } + + if (TPM_REQ_MAX_SIZE < hash_cmd_buf_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'hash_cmd_buf_size' must be smaller or equal to %u.\n", TPM_REQ_MAX_SIZE); + break; + } + if (sizeof(tpm2_hash) > hash_cmd_buf_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'hash_cmd_buf_size' must be at least %u.\n", sizeof(tpm2_hash)); + break; + } + data_string_size = strlen(data_string) / HEX_BYTE_STRING_LENGTH + strlen(data_string) % HEX_BYTE_STRING_LENGTH; + if (0 == data_string_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. data_string is empty.\n"); + break; + } + if (hash_cmd_buf_size - sizeof(tpm2_hash) < data_string_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Input data size must be smaller or equal to %u.\n", hash_cmd_buf_size - sizeof(tpm2_hash)); + break; + } + + memset(hash_cmd_buf, 0, hash_cmd_buf_size); + + // Copy basic command bytes. + memcpy(hash_cmd_buf, tpm2_hash, sizeof(tpm2_hash)); + + // Set hash algorithm, command and data sizes depending on user input option at the correct byte index in the command byte stream. + if ('s' == option) + { + tpm_hash_alg = sha1_alg; + printf("\nTPM2_Hash of '%s' with SHA-1:\n", data_string); + } + else + { + tpm_hash_alg = sha256_alg; + printf("\nTPM2_Hash of '%s' with SHA-256:\n", data_string); + } + + offset = TPM_CMD_SIZE_OFFSET; + ret_val = int_to_bytearray(sizeof(tpm2_hash) + data_string_size, sizeof(uint32_t), hash_cmd_buf + offset); + RET_VAL_CHECK(ret_val); + offset = TPM_CMD_HEADER_SIZE; + ret_val = int_to_bytearray(data_string_size, sizeof(data_string_size), hash_cmd_buf + offset); + RET_VAL_CHECK(ret_val); + offset += sizeof(data_string_size); + + // Copy hash data to TPM request. + ret_val = hexstr_to_bytearray(data_string, hash_cmd_buf + offset, hash_cmd_buf_size - offset); + RET_VAL_CHECK(ret_val); + offset += data_string_size; + + // Set hash algorithm and hierarchy. + memcpy(hash_cmd_buf + offset, tpm_hash_alg, sizeof(sha1_alg)); + offset += sizeof(sha1_alg); + memcpy(hash_cmd_buf + offset, tpm_cc_hash_hierarchy, sizeof(tpm_cc_hash_hierarchy)); + } while (0); + + return ret_val; } -int create_hash_sequence(char *data_string, char option, uint8_t *tpm_response_buf, ssize_t *tpm_response_buf_size) +static int create_hash_sequence(char *data_string, char option, uint8_t *tpm_response_buf, ssize_t *tpm_response_buf_size) { - int ret_val = EXIT_SUCCESS; // Return value. - uint16_t data_string_bytes_size = 0; // Size of user input data string in bytes. - uint8_t *data_string_bytes = NULL; // Buffer for user input data string as bytes. - uint32_t update_request_size = 0; // Size of user input string. - uint16_t transfer_bytes = 0; // Amount of bytes to be transmitted to the TPM. - uint16_t remaining_bytes = 0; // Amount of bytes not yet transmitted to the TPM. - uint32_t offset = 0; // Helper offset for generating command request. - unsigned long long tpm_rc = TPM_RC_SUCCESS; // TPM return code. - uint8_t *update_request = NULL; // Buffer for update sequence command. - uint8_t sequence_handle[4]; // Buffer for tpmi response. - ssize_t original_response_buf_size = 0; // Backup of the original response buffer size - - do - { - NULL_POINTER_CHECK(tpm_response_buf); - NULL_POINTER_CHECK(data_string); - NULL_POINTER_CHECK(tpm_response_buf_size); - if ('a' != option && 'A' != option) - { - ret_val = EINVAL; - fprintf(stderr, "Bad parameter. Option argument must be 'a' or 'A'.\n"); - break; - } - original_response_buf_size = *tpm_response_buf_size; - - // Set hash algorithm depending on user input option at the correct byte index in the command byte stream. - if ('a' == option) - { - printf("\nTPM2_HashSequenceStart of '%s' with SHA-1:\n", data_string); - memcpy(tpm2_hash_sequence_start + 12, sha1_alg, sizeof(sha1_alg)); - } - else - { - printf("\nTPM2_HashSequenceStart of '%s' with SHA-256:\n", data_string); - memcpy(tpm2_hash_sequence_start + 12, sha256_alg, sizeof(sha256_alg)); - } - - // Send the TPM2_HashSequenceStart command to the TPM. - ret_val = tpmtool_transmit(tpm2_hash_sequence_start, sizeof(tpm2_hash_sequence_start), tpm_response_buf, tpm_response_buf_size); - RET_VAL_CHECK(ret_val); - - // Print the TPM response. - NULL_POINTER_CHECK(tpm_response_buf_size); - ret_val = print_response_buf(tpm_response_buf, (size_t)*tpm_response_buf_size, PRINT_RESPONSE_WITH_HEADER, PRINT_RESPONSE_HEADERBLOCKS); - RET_VAL_CHECK(ret_val); - - // Abort in case of TPM error. - ret_val = buf_to_uint64(tpm_response_buf, 6, 4, &tpm_rc); - RET_VAL_CHECK(ret_val); - if (TPM_RC_SUCCESS != tpm_rc) - { - break; - } - - // Get sequence handle from TPM response. - memcpy(sequence_handle, tpm_response_buf + 10, sizeof(sequence_handle)); - - // Calculate byte sizes of hash input string. - data_string_bytes_size = strlen(data_string) / 2 + strlen(data_string) % 2; - - // Allocate memory for conversion of hash input string. - data_string_bytes = malloc(data_string_bytes_size); - MALLOC_ERROR_CHECK(data_string_bytes); - memset(data_string_bytes, 0, data_string_bytes_size); - - // Convert hash input string to bytes. - ret_val = hexstr_to_bytearray(data_string, data_string_bytes, data_string_bytes_size); - RET_VAL_CHECK(ret_val); - - // If necessary split input bytes into multiple TPM2_SequenceUpdate commands - remaining_bytes = data_string_bytes_size; - while (remaining_bytes > 0) - { - // Calculate amount of bytes to be transmitted next - if (remaining_bytes <= TPM_REQ_MAX_SIZE - sizeof(tpm2_sequence_update)) - { - transfer_bytes = remaining_bytes; - } - else - { - transfer_bytes = TPM_REQ_MAX_SIZE - sizeof(tpm2_sequence_update); - } - update_request_size = transfer_bytes + sizeof(tpm2_sequence_update); - - // Compose the TPM2_SequenceUpdate command. - update_request = malloc(update_request_size); - MALLOC_ERROR_CHECK(update_request); - memset(update_request, 0, update_request_size); - memcpy(update_request, tpm2_sequence_update, sizeof(tpm2_sequence_update)); - offset = 2; - ret_val = int_to_bytearray(update_request_size, sizeof(update_request_size), update_request + offset); - RET_VAL_CHECK(ret_val); - offset = 10; - memcpy(update_request + offset, sequence_handle, sizeof(sequence_handle)); - offset = sizeof(tpm2_sequence_update) - sizeof(transfer_bytes); - ret_val = int_to_bytearray(transfer_bytes, sizeof(transfer_bytes), update_request + offset); - RET_VAL_CHECK(ret_val); - memcpy(update_request + sizeof(tpm2_sequence_update), data_string_bytes + data_string_bytes_size - remaining_bytes, transfer_bytes); - - // Send the TPM2_SequenceUpdate command to the TPM. - printf("\n\nTPM2_SequenceUpdate:\n"); - *tpm_response_buf_size = original_response_buf_size; - ret_val = tpmtool_transmit(update_request, update_request_size, tpm_response_buf, tpm_response_buf_size); - RET_VAL_CHECK(ret_val); - - // Free allocated memory - MEMSET_FREE(update_request, update_request_size); - - // Print the TPM response. - NULL_POINTER_CHECK(tpm_response_buf_size); - ret_val = print_response_buf(tpm_response_buf, (size_t)*tpm_response_buf_size, PRINT_RESPONSE_WITH_HEADER, PRINT_RESPONSE_HEADERBLOCKS); - RET_VAL_CHECK(ret_val); - - // Abort in case of TPM error. - ret_val = buf_to_uint64(tpm_response_buf, 6, 4, &tpm_rc); - RET_VAL_CHECK(ret_val); - if (TPM_RC_SUCCESS != tpm_rc) - { - break; - } - - remaining_bytes = remaining_bytes - transfer_bytes; - } - RET_VAL_CHECK(ret_val); - if (TPM_RC_SUCCESS != tpm_rc) - { - break; - } - - // Set the sequence handle in the TPM2_SequenceComplete command. - memcpy(tpm2_sequence_complete + 10, sequence_handle, sizeof(sequence_handle)); - - // Send the TPM2_SequenceComplete command to the TPM. - printf("\n\nTPM2_SequenceComplete:\n"); - *tpm_response_buf_size = original_response_buf_size; - ret_val = tpmtool_transmit(tpm2_sequence_complete, sizeof(tpm2_sequence_complete), tpm_response_buf, tpm_response_buf_size); - RET_VAL_CHECK(ret_val); + int ret_val = EXIT_SUCCESS; // Return value. + uint16_t data_string_bytes_size = 0; // Size of user input data string in bytes. + uint8_t *data_string_bytes = NULL; // Buffer for user input data string as bytes. + uint32_t update_request_size = 0; // Size of user input string. + uint16_t transfer_bytes = 0; // Amount of bytes to be transmitted to the TPM. + uint16_t remaining_bytes = 0; // Amount of bytes not yet transmitted to the TPM. + uint32_t offset = 0; // Helper offset for generating command request. + uint64_t tpm_rc = TPM_RC_SUCCESS; // TPM return code. + uint8_t *update_request = NULL; // Buffer for update sequence command. + uint8_t sequence_handle[4]; // Buffer for sequence handle. + ssize_t original_response_buf_size = 0; // Backup of the original response buffer size. + ssize_t minimum_response_buf_size = + TPM_CMD_HEADER_SIZE + sizeof(sequence_handle); // Minimum success response buffer size (TPM command header + sequence handle) + + do + { + NULL_POINTER_CHECK(tpm_response_buf); + NULL_POINTER_CHECK(data_string); + NULL_POINTER_CHECK(tpm_response_buf_size); + + memset(tpm_response_buf, 0, *tpm_response_buf_size); + memset(sequence_handle, 0, 4); - // Print the TPM response. - NULL_POINTER_CHECK(tpm_response_buf_size); - ret_val = print_response_buf(tpm_response_buf, (size_t)*tpm_response_buf_size, PRINT_RESPONSE_WITH_HEADER, PRINT_RESPONSE_HEADERBLOCKS); - printf("\n\nHash value extracted from TPM response:\n"); - } while (0); - - MEMSET_FREE(data_string_bytes, data_string_bytes_size); - MEMSET_FREE(update_request, update_request_size); - - return ret_val; + if (TPM_RESP_MAX_SIZE < *tpm_response_buf_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter '*tpm_response_buf_size' must be smaller or equal to %u.\n", TPM_RESP_MAX_SIZE); + break; + } + if (minimum_response_buf_size > *tpm_response_buf_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter '*tpm_response_buf_size' must be at least %u.\n", minimum_response_buf_size); + break; + } + + if ('a' != option && 'A' != option) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Option argument must be 'a' or 'A'.\n"); + break; + } + original_response_buf_size = *tpm_response_buf_size; + + // Set hash algorithm depending on user input option at the correct byte index in the command byte stream. + if ('a' == option) + { + printf("\nTPM2_HashSequenceStart of '%s' with SHA-1:\n", data_string); + memcpy(tpm2_hash_sequence_start + 12, sha1_alg, sizeof(sha1_alg)); + } + else + { + printf("\nTPM2_HashSequenceStart of '%s' with SHA-256:\n", data_string); + memcpy(tpm2_hash_sequence_start + 12, sha256_alg, sizeof(sha256_alg)); + } + + // Send the TPM2_HashSequenceStart command to the TPM. + ret_val = tpmtool_transmit(tpm2_hash_sequence_start, sizeof(tpm2_hash_sequence_start), tpm_response_buf, tpm_response_buf_size); + RET_VAL_CHECK(ret_val); + + // Print the TPM response. + NULL_POINTER_CHECK(tpm_response_buf_size); + ret_val = print_response_buf(tpm_response_buf, (size_t)*tpm_response_buf_size, PRINT_RESPONSE_WITH_HEADER, PRINT_RESPONSE_HEADERBLOCKS); + RET_VAL_CHECK(ret_val); + + // Abort in case of TPM error. + ret_val = buf_to_uint64(tpm_response_buf, 6, 4, &tpm_rc, *tpm_response_buf_size); + RET_VAL_CHECK(ret_val); + if (TPM_RC_SUCCESS != tpm_rc) + { + break; + } + + // Get sequence handle from TPM response. + memcpy(sequence_handle, tpm_response_buf + TPM_CMD_HEADER_SIZE, sizeof(sequence_handle)); + + // Calculate byte sizes of hash input string. + data_string_bytes_size = strlen(data_string) / HEX_BYTE_STRING_LENGTH + strlen(data_string) % HEX_BYTE_STRING_LENGTH; + + // Allocate memory for conversion of hash input string. + data_string_bytes = malloc(data_string_bytes_size); + MALLOC_ERROR_CHECK(data_string_bytes); + memset(data_string_bytes, 0, data_string_bytes_size); + + // Convert hash input string to bytes. + ret_val = hexstr_to_bytearray(data_string, data_string_bytes, data_string_bytes_size); + RET_VAL_CHECK(ret_val); + + // If necessary split input bytes into multiple TPM2_SequenceUpdate commands + remaining_bytes = data_string_bytes_size; + while (remaining_bytes > 0) + { + // Calculate amount of bytes to be transmitted next + if (remaining_bytes <= TPM_REQ_MAX_SIZE - sizeof(tpm2_sequence_update)) + { + transfer_bytes = remaining_bytes; + } + else + { + transfer_bytes = TPM_REQ_MAX_SIZE - sizeof(tpm2_sequence_update); + } + update_request_size = transfer_bytes + sizeof(tpm2_sequence_update); + + // Compose the TPM2_SequenceUpdate command. + update_request = malloc(update_request_size); + MALLOC_ERROR_CHECK(update_request); + memset(update_request, 0, update_request_size); + memcpy(update_request, tpm2_sequence_update, sizeof(tpm2_sequence_update)); + offset = TPM_CMD_SIZE_OFFSET; + ret_val = int_to_bytearray(update_request_size, sizeof(update_request_size), update_request + offset); + RET_VAL_CHECK(ret_val); + offset = TPM_CMD_HEADER_SIZE; + memcpy(update_request + offset, sequence_handle, sizeof(sequence_handle)); + offset = sizeof(tpm2_sequence_update) - sizeof(transfer_bytes); + ret_val = int_to_bytearray(transfer_bytes, sizeof(transfer_bytes), update_request + offset); + RET_VAL_CHECK(ret_val); + memcpy(update_request + sizeof(tpm2_sequence_update), data_string_bytes + data_string_bytes_size - remaining_bytes, transfer_bytes); + + // Send the TPM2_SequenceUpdate command to the TPM. + printf("\n\nTPM2_SequenceUpdate:\n"); + *tpm_response_buf_size = original_response_buf_size; + ret_val = tpmtool_transmit(update_request, update_request_size, tpm_response_buf, tpm_response_buf_size); + RET_VAL_CHECK(ret_val); + + // Free allocated memory + MEMSET_FREE(update_request, update_request_size); + + // Print the TPM response. + NULL_POINTER_CHECK(tpm_response_buf_size); + ret_val = print_response_buf(tpm_response_buf, (size_t)*tpm_response_buf_size, PRINT_RESPONSE_WITH_HEADER, PRINT_RESPONSE_HEADERBLOCKS); + RET_VAL_CHECK(ret_val); + + // Abort in case of TPM error. + ret_val = buf_to_uint64(tpm_response_buf, 6, 4, &tpm_rc, *tpm_response_buf_size); + RET_VAL_CHECK(ret_val); + if (TPM_RC_SUCCESS != tpm_rc) + { + break; + } + + remaining_bytes = remaining_bytes - transfer_bytes; + } + RET_VAL_CHECK(ret_val); + if (TPM_RC_SUCCESS != tpm_rc) + { + break; + } + + // Set the sequence handle in the TPM2_SequenceComplete command. + memcpy(tpm2_sequence_complete + TPM_CMD_HEADER_SIZE, sequence_handle, sizeof(sequence_handle)); + + // Send the TPM2_SequenceComplete command to the TPM. + printf("\n\nTPM2_SequenceComplete:\n"); + *tpm_response_buf_size = original_response_buf_size; + ret_val = tpmtool_transmit(tpm2_sequence_complete, sizeof(tpm2_sequence_complete), tpm_response_buf, tpm_response_buf_size); + RET_VAL_CHECK(ret_val); + + // Print the TPM response. + NULL_POINTER_CHECK(tpm_response_buf_size); + ret_val = print_response_buf(tpm_response_buf, (size_t)*tpm_response_buf_size, PRINT_RESPONSE_WITH_HEADER, PRINT_RESPONSE_HEADERBLOCKS); + printf("\n\nHash value extracted from TPM response:\n"); + } while (0); + + MEMSET_FREE(data_string_bytes, data_string_bytes_size); + MEMSET_FREE(update_request, update_request_size); + + return ret_val; } -int pcr_extend(char *pcr_index_str, char *pcr_digest_str, uint8_t *pcr_cmd_buf, size_t pcr_cmd_buf_size, char option) +static int pcr_extend(char *pcr_index_str, char *pcr_digest_str, uint8_t *pcr_cmd_buf, size_t pcr_cmd_buf_size, char option) { - int ret_val = EXIT_SUCCESS; // Return value. - uint8_t pcr_index = 0; // PCR index user input byte. - uint32_t pcr_digest_size = 0; // Sizeof PCR digest user input. - - do - { - NULL_POINTER_CHECK(pcr_index_str); - NULL_POINTER_CHECK(pcr_digest_str); - NULL_POINTER_CHECK(pcr_cmd_buf); - if ('e' != option && 'E' != option) - { - ret_val = EINVAL; - fprintf(stderr, "Bad parameter. Option argument must be 'e' or 'E'.\n"); - break; - } - - // Check and convert the command line input (PCR index) to bytes. - if (1 != strlen(pcr_index_str) / 2 + strlen(pcr_index_str) % 2) - { - ret_val = ERR_BAD_CMD; - fprintf(stderr, "Bad option. Enter a single hex value (2 characters) without leading '0x'.\n"); - break; - } - ret_val = hexstr_to_bytearray(pcr_index_str, &pcr_index, 1); - RET_VAL_CHECK(ret_val); - if (23 < pcr_index) - { - ret_val = ERR_BAD_CMD; - fprintf(stderr, "Bad option. Enter a hex value between 0x00 and 0x17 in hex without leading '0x'.\n"); - break; - } - - // Check the command line input (PCR digest). - pcr_digest_size = strlen(pcr_digest_str) / 2 + strlen(pcr_digest_str) % 2; - if ('e' == option && TPM_SHA1_DIGEST_SIZE < pcr_digest_size) - { - ret_val = ERR_BAD_CMD; - fprintf(stderr, "Bad option. Maximum SHA-1 PCR digest size is 20 byte (40 characters), but you entered %u byte.\n", pcr_digest_size); - break; - } - if ('E' == option && TPM_SHA256_DIGEST_SIZE < pcr_digest_size) - { - ret_val = ERR_BAD_CMD; - fprintf(stderr, "Bad option. Maximum SHA-256 PCR digest size is 32 byte (64 characters), but you entered %u byte.\n", pcr_digest_size); - break; - } - - // Copy basic command bytes. - memcpy(pcr_cmd_buf, tpm2_pcr_extend, sizeof(tpm2_pcr_extend)); - - // Store PCR index at the correct byte index in the command byte stream. - pcr_cmd_buf[13] = pcr_index; - - // Convert the PCR digest to bytes and store it at the correct byte index in the command byte stream. - ret_val = hexstr_to_bytearray(pcr_digest_str, pcr_cmd_buf + sizeof(tpm2_pcr_extend), pcr_cmd_buf_size - sizeof(tpm2_pcr_extend)); - RET_VAL_CHECK(ret_val); - - // Set hash algorithm and command length depending on user input option at the correct byte index in the command byte stream. - if ('e' == option) - { - pcr_cmd_buf[5] = sizeof(tpm2_pcr_extend) + TPM_SHA1_DIGEST_SIZE; - memcpy(pcr_cmd_buf + 31, sha1_alg, sizeof(sha1_alg)); - printf("Extend PCR %i (SHA-1) with digest { ", pcr_index); - } - else if ('E' == option) - { - pcr_cmd_buf[5] = sizeof(tpm2_pcr_extend) + TPM_SHA256_DIGEST_SIZE; - memcpy(pcr_cmd_buf + 31, sha256_alg, sizeof(sha256_alg)); - printf("Extend PCR %i (SHA-256) with digest { ", pcr_index); - } - print_response_buf(pcr_cmd_buf, pcr_cmd_buf_size, sizeof(tpm2_pcr_extend), PRINT_RESPONSE_CLEAR); - printf("}:\n"); - } while (0); - - return ret_val; + int ret_val = EXIT_SUCCESS; // Return value. + uint8_t pcr_index = 0; // PCR index user input byte. + uint32_t pcr_digest_size = 0; // Sizeof PCR digest user input. + + do + { + NULL_POINTER_CHECK(pcr_index_str); + NULL_POINTER_CHECK(pcr_digest_str); + NULL_POINTER_CHECK(pcr_cmd_buf); + + if (TPM_REQ_MAX_SIZE < pcr_cmd_buf_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'pcr_cmd_buf_size' size must be smaller or equal to %u.\n", TPM_REQ_MAX_SIZE); + break; + } + if (sizeof(tpm2_pcr_extend) > pcr_cmd_buf_size) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Value of parameter 'pcr_cmd_buf_size' must be at least %u.\n", sizeof(tpm2_pcr_extend)); + break; + } + + memset(pcr_cmd_buf, 0, pcr_cmd_buf_size); + + if ('e' != option && 'E' != option) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Option argument must be 'e' or 'E'.\n"); + break; + } + + // Check and convert the command line input (PCR index) to bytes. + if (1 != strlen(pcr_index_str) / HEX_BYTE_STRING_LENGTH + strlen(pcr_index_str) % HEX_BYTE_STRING_LENGTH) + { + ret_val = ERR_BAD_CMD; + fprintf(stderr, "Bad option. Enter a single hex value (2 characters) without leading '0x'.\n"); + break; + } + ret_val = hexstr_to_bytearray(pcr_index_str, &pcr_index, 1); + RET_VAL_CHECK(ret_val); + if (23 < pcr_index) + { + ret_val = ERR_BAD_CMD; + fprintf(stderr, "Bad option. Enter a hex value between 0x00 and 0x17 in hex without leading '0x'.\n"); + break; + } + + // Check the command line input (PCR digest). + pcr_digest_size = strlen(pcr_digest_str) / HEX_BYTE_STRING_LENGTH + strlen(pcr_digest_str) % HEX_BYTE_STRING_LENGTH; + if ('e' == option && TPM_SHA1_DIGEST_SIZE < pcr_digest_size) + { + ret_val = ERR_BAD_CMD; + fprintf(stderr, "Bad option. Maximum SHA-1 PCR digest size is 20 byte (40 characters), but you entered %u byte.\n", pcr_digest_size); + break; + } + if ('E' == option && TPM_SHA256_DIGEST_SIZE < pcr_digest_size) + { + ret_val = ERR_BAD_CMD; + fprintf(stderr, "Bad option. Maximum SHA-256 PCR digest size is 32 byte (64 characters), but you entered %u byte.\n", pcr_digest_size); + break; + } + + // Copy basic command bytes. + memcpy(pcr_cmd_buf, tpm2_pcr_extend, sizeof(tpm2_pcr_extend)); + + // Store PCR index at the correct byte index in the command byte stream. + pcr_cmd_buf[13] = pcr_index; + + // Convert the PCR digest to bytes and store it at the correct byte index in the command byte stream. + ret_val = hexstr_to_bytearray(pcr_digest_str, pcr_cmd_buf + sizeof(tpm2_pcr_extend), pcr_cmd_buf_size - sizeof(tpm2_pcr_extend)); + RET_VAL_CHECK(ret_val); + + // Set hash algorithm and command length depending on user input option at the correct byte index in the command byte stream. + if ('e' == option) + { + pcr_cmd_buf[5] = sizeof(tpm2_pcr_extend) + TPM_SHA1_DIGEST_SIZE; + memcpy(pcr_cmd_buf + 31, sha1_alg, sizeof(sha1_alg)); + printf("Extend PCR %i (SHA-1) with digest { ", pcr_index); + } + else if ('E' == option) + { + pcr_cmd_buf[5] = sizeof(tpm2_pcr_extend) + TPM_SHA256_DIGEST_SIZE; + memcpy(pcr_cmd_buf + 31, sha256_alg, sizeof(sha256_alg)); + printf("Extend PCR %i (SHA-256) with digest { ", pcr_index); + } + print_response_buf(pcr_cmd_buf, pcr_cmd_buf_size, sizeof(tpm2_pcr_extend), PRINT_RESPONSE_CLEAR); + printf("}:\n"); + } while (0); + + return ret_val; } -int pcr_read(char *pcr_index_str, uint8_t *pcr_cmd_buf, char option) +static int pcr_read(char *pcr_index_str, uint8_t *pcr_cmd_buf, char option) { - int ret_val = EXIT_SUCCESS; // Return value. - int pcr_byte_index = 0; // The location for pcr_select on pcr_cmd_buf. - uint8_t pcr_select = 0; // PCR index as mapped bit value. - uint8_t pcr_index = 0; // PCR user input byte. - - do - { - NULL_POINTER_CHECK(pcr_index_str); - NULL_POINTER_CHECK(pcr_cmd_buf); - if ('r' != option && 'R' != option) - { - ret_val = EINVAL; - fprintf(stderr, "Bad parameter. Option argument must be 'r' or 'R'.\n"); - break; - } - - // Convert the command line input to bytes. - if (1 != strlen(pcr_index_str) / 2 + strlen(pcr_index_str) % 2) - { - // Current implementation only supports selection of one PCR at a time. - ret_val = ERR_BAD_CMD; - fprintf(stderr, "Bad option. Enter a single hex value (2 characters) without leading '0x'.\n"); - break; - } - ret_val = hexstr_to_bytearray(pcr_index_str, &pcr_index, 1); - RET_VAL_CHECK(ret_val); - if (23 < pcr_index) - { - ret_val = ERR_BAD_CMD; - fprintf(stderr, "Bad option. Enter a hex value between 0x00 and 0x17 in hex without leading '0x'.\n"); - break; - } - - // Copy basic command bytes. - memcpy(pcr_cmd_buf, tpm2_pcr_read, sizeof(tpm2_pcr_read)); - - // Calculate the location of PCR index in command byte stream depends on the PCR index value: 0 for PCRs 0-7, 1 for PCRs 8-15 and 2 for PCRs 16-23. - pcr_byte_index = pcr_index / 8; - - // Set corresponding bit in PCR selection byte to 1: bit 0 for PCRs 0, 8 or 16, bit 1 for PCRs 1, 9 or 17, ... (etc.), and bit 7 for PCRs 7, 15 or 23. - // Note: This would allow to read multiple PCRs at once. For simplicity reasons, ELTT only supports reading one PCR at a time. - pcr_select = (1 << (pcr_index % 8)); - - // Store pcr_select at the correct byte index in the command byte stream. - pcr_cmd_buf[17 + pcr_byte_index] = pcr_select; - - // Set hash algorithm depending on user input option at the correct byte index in the command byte stream. - if ('r' == option) - { - memcpy(pcr_cmd_buf + 14, sha1_alg, sizeof(sha1_alg)); - printf("Read PCR %i (SHA-1):\n", pcr_index); - } - else if ('R' == option) - { - memcpy(pcr_cmd_buf + 14, sha256_alg, sizeof(sha256_alg)); - printf("Read PCR %i (SHA-256):\n", pcr_index); - } - } while (0); - - return ret_val; + int ret_val = EXIT_SUCCESS; // Return value. + int pcr_byte_index = 0; // The location for pcr_select on pcr_cmd_buf. + uint8_t pcr_select = 0; // PCR index as mapped bit value. + uint8_t pcr_index = 0; // PCR user input byte. + + do + { + NULL_POINTER_CHECK(pcr_index_str); + NULL_POINTER_CHECK(pcr_cmd_buf); + + memset(pcr_cmd_buf, 0, 20); + + if ('r' != option && 'R' != option) + { + ret_val = EINVAL; + fprintf(stderr, "Bad parameter. Option argument must be 'r' or 'R'.\n"); + break; + } + + // Convert the command line input to bytes. + if (1 != strlen(pcr_index_str) / HEX_BYTE_STRING_LENGTH + strlen(pcr_index_str) % HEX_BYTE_STRING_LENGTH) + { + // Current implementation only supports selection of one PCR at a time. + ret_val = ERR_BAD_CMD; + fprintf(stderr, "Bad option. Enter a single hex value (2 characters) without leading '0x'.\n"); + break; + } + ret_val = hexstr_to_bytearray(pcr_index_str, &pcr_index, 1); + RET_VAL_CHECK(ret_val); + if (23 < pcr_index) + { + ret_val = ERR_BAD_CMD; + fprintf(stderr, "Bad option. Enter a hex value between 0x00 and 0x17 in hex without leading '0x'.\n"); + break; + } + + // Copy basic command bytes. + memcpy(pcr_cmd_buf, tpm2_pcr_read, sizeof(tpm2_pcr_read)); + + // Calculate the location of PCR index in command byte stream depends on the PCR index value: 0 for PCRs 0-7, 1 for PCRs 8-15 and 2 for PCRs 16-23. + pcr_byte_index = pcr_index / 8; + + // Set corresponding bit in PCR selection byte to 1: bit 0 for PCRs 0, 8 or 16, bit 1 for PCRs 1, 9 or 17, ... (etc.), and bit 7 for PCRs 7, 15 or 23. + // Note: This would allow to read multiple PCRs at once. For simplicity reasons, ELTT only supports reading one PCR at a time. + pcr_select = (1 << (pcr_index % 8)); + + // Store pcr_select at the correct byte index in the command byte stream. + pcr_cmd_buf[17 + pcr_byte_index] = pcr_select; + + // Set hash algorithm depending on user input option at the correct byte index in the command byte stream. + if ('r' == option) + { + memcpy(pcr_cmd_buf + 14, sha1_alg, sizeof(sha1_alg)); + printf("Read PCR %i (SHA-1):\n", pcr_index); + } + else if ('R' == option) + { + memcpy(pcr_cmd_buf + 14, sha256_alg, sizeof(sha256_alg)); + printf("Read PCR %i (SHA-256):\n", pcr_index); + } + } while (0); + + return ret_val; } -int pcr_reset(char *pcr_index_str, uint8_t *pcr_cmd_buf) +static int pcr_reset(char *pcr_index_str, uint8_t *pcr_cmd_buf) { - int ret_val = EXIT_SUCCESS; // Return value. - uint8_t pcr_index = 0; // PCR user input byte. - - do - { - NULL_POINTER_CHECK(pcr_index_str); - NULL_POINTER_CHECK(pcr_cmd_buf); - - // Convert the command line input to bytes. - if (1 != strlen(pcr_index_str) / 2 + strlen(pcr_index_str) % 2) - { - ret_val = ERR_BAD_CMD; - fprintf(stderr, "Bad option. Enter a single hex value (2 characters) without leading '0x'.\n"); - break; - } - ret_val = hexstr_to_bytearray(pcr_index_str, &pcr_index, 1); - RET_VAL_CHECK(ret_val); - if (23 < pcr_index) - { - ret_val = ERR_BAD_CMD; - fprintf(stderr, "Bad option. Enter a hex value between 0x00 and 0x17 in hex without leading '0x'.\n"); - break; - } - - // Copy command bytes. - memcpy(pcr_cmd_buf, tpm2_pcr_reset, sizeof(tpm2_pcr_reset)); - - // Store pcr_index at the correct byte index in the command byte stream. - pcr_cmd_buf[13] = pcr_index; - - printf("Reset PCR %i:\n", pcr_index); - } while (0); - - return ret_val; + int ret_val = EXIT_SUCCESS; // Return value. + uint8_t pcr_index = 0; // PCR user input byte. + + do + { + NULL_POINTER_CHECK(pcr_index_str); + NULL_POINTER_CHECK(pcr_cmd_buf); + + memset(pcr_cmd_buf, 0, 27); + + // Convert the command line input to bytes. + if (1 != strlen(pcr_index_str) / HEX_BYTE_STRING_LENGTH + strlen(pcr_index_str) % HEX_BYTE_STRING_LENGTH) + { + ret_val = ERR_BAD_CMD; + fprintf(stderr, "Bad option. Enter a single hex value (2 characters) without leading '0x'.\n"); + break; + } + ret_val = hexstr_to_bytearray(pcr_index_str, &pcr_index, 1); + RET_VAL_CHECK(ret_val); + if (23 < pcr_index) + { + ret_val = ERR_BAD_CMD; + fprintf(stderr, "Bad option. Enter a hex value between 0x00 and 0x17 in hex without leading '0x'.\n"); + break; + } + + // Copy command bytes. + memcpy(pcr_cmd_buf, tpm2_pcr_reset, sizeof(tpm2_pcr_reset)); + + // Store pcr_index at the correct byte index in the command byte stream. + pcr_cmd_buf[13] = pcr_index; + + printf("Reset PCR %i (SHA-1 and SHA-256):\n", pcr_index); + } while (0); + + return ret_val; } diff --git a/eltt2.h b/eltt2.h index 097c8bf..e9ca42e 100644 --- a/eltt2.h +++ b/eltt2.h @@ -1,11 +1,11 @@ #ifndef _ELTT2_H_ #define _ELTT2_H_ /** - * @brief Infineon Embedded Linux TPM Toolbox 2 (ELTT2) for TPM 2.0 - * @details eltt2.h implements all TPM byte commands and the prototype declarations for eltt2.c. - * @file eltt2.h - * @date 2014/06/26 - * @copyright Copyright (c) 2014, Infineon Technologies AG\n + * @brief Infineon Embedded Linux TPM Toolbox 2 (ELTT2) for TPM 2.0 + * @details eltt2.h implements all TPM byte commands and the prototype declarations for eltt2.c. + * @file eltt2.h + * @date 2014/06/26 + * @copyright Copyright (c) 2014 - 2017 Infineon Technologies AG ( www.infineon.com ).\n * All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following @@ -28,18 +28,18 @@ */ // this is the main page for doxygen documentation. -/** @mainpage Infineon Embedded Linux TPM Toolbox 2 (ELTT2) for TPM 2.0 Documentation +/** @mainpage Infineon Embedded Linux TPM Toolbox 2 (ELTT2) for TPM 2.0 Documentation * - * @section Welcome + * @section Welcome * Welcome to Infineon TPM 2.0 Software-Tool "Embedded Linux TPM Toolbox 2 (ELTT2)".\n * \n - * @section Introduction + * @section Introduction * ELTT2 is a single file-executable program * intended for test, diagnosis and basic state changes of the Infineon * Technologies TPM 2.0.\n * \n - * @section Copyright - * Copyright (c) 2014, Infineon Technologies AG\n + * @section Copyright + * Copyright (c) 2014 - 2017 Infineon Technologies AG ( www.infineon.com ).\n * All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following @@ -71,47 +71,51 @@ #include //-------------"Defines"------------- -#define TPM_RESP_MAX_SIZE 4096 ///< This is the maximum possible TPM response size in bytes. -#define TPM_REQ_MAX_SIZE 1024 ///< This is the maximum possible TPM request size in bytes. TBD: Find out correct value. -#define ERR_COMMUNICATION -1 ///< Return error check for read and write to the TPM. -#define ERR_BAD_CMD -2 ///< Error code for a bad command line argument or option. -#define TPM_SHA1_DIGEST_SIZE 20 ///< For all SHA-1 operations the digest's size is always 20 bytes. -#define TPM_SHA256_DIGEST_SIZE 32 ///< For all SHA-256 operations the digest's size is always 32 bytes. -#define TPM_CMD_HEADER_SIZE 10 ///< The size of a standard TPM command header is 10 bytes. +#define TPM_RESP_MAX_SIZE 4096 ///< This is the maximum possible TPM response size in bytes. +#define TPM_REQ_MAX_SIZE 1024 ///< This is the maximum possible TPM request size in bytes. TBD: Find out correct value. +#define ERR_COMMUNICATION -1 ///< Return error check for read and write to the TPM. +#define ERR_BAD_CMD -2 ///< Error code for a bad command line argument or option. +#define TPM_SHA1_DIGEST_SIZE 20 ///< For all SHA-1 operations the digest's size is always 20 bytes. +#define TPM_SHA256_DIGEST_SIZE 32 ///< For all SHA-256 operations the digest's size is always 32 bytes. +#define TPM_CMD_HEADER_SIZE 10 ///< The size of a standard TPM command header is 10 bytes. +#define TPM_CMD_SIZE_OFFSET 2 ///< The offset of a TPM command's size value is 2 bytes. +#define HEX_BYTE_STRING_LENGTH 2 ///< A byte can be represented by two hexadecimal characters. +#ifndef INT_MAX +#define INT_MAX 0x7FFFFFF ///< The maximum value of a signed 32-bit integer. +#endif // TPM Return codes -#define TPM_RC_SUCCESS 0x00000000 ///< The response error code for TPM_SUCCESS. -#define TPM_RC_BAD_TAG 0x0000001E ///< The response error code for TPM_RC_BAD_TAG. -#define TPM_RC_SIZE 0x00000095 ///< The response error code for TPM_RC_SIZE. -#define TPM_RC_INITIALIZE 0x00000100 ///< The response error code for TPM_RC_INITIALIZE. -#define TPM_RC_FAILURE 0x00000101 ///< The response error code for TPM_RC_FAILURE. -#define TPM_RC_LOCALITY 0x00000907 ///< The response error code for TPM_RC_LOCALITY. -#define FU_FIRMWARE_VALID_FLAG 4 ///< If this flag is set, the firmware is valid. -#define FU_OWNER_FLAG 1 ///< If this flag is set, the owner is set. +#define TPM_RC_SUCCESS 0x00000000 ///< The response error code for TPM_SUCCESS. +#define TPM_RC_BAD_TAG 0x0000001E ///< The response error code for TPM_RC_BAD_TAG. +#define TPM_RC_SIZE 0x00000095 ///< The response error code for TPM_RC_SIZE. +#define TPM_RC_INITIALIZE 0x00000100 ///< The response error code for TPM_RC_INITIALIZE. +#define TPM_RC_FAILURE 0x00000101 ///< The response error code for TPM_RC_FAILURE. +#define TPM_RC_LOCALITY 0x00000907 ///< The response error code for TPM_RC_LOCALITY. +#define FU_FIRMWARE_VALID_FLAG 4 ///< If this flag is set, the firmware is valid. +#define FU_OWNER_FLAG 1 ///< If this flag is set, the owner is set. // print_response_buf options -#define PRINT_RESPONSE_CLEAR 1 ///< Prints response unformatted. -#define PRINT_RESPONSE_HEADERBLOCKS 2 ///< Prints response in commented blocks. -#define PRINT_RESPONSE_HEX_BLOCK 3 ///< Prints response in rows of 16 bytes and shows the line number. -#define PRINT_RESPONSE_HASH 4 ///< Prints response of Hash -#define PRINT_RESPONSE_WITHOUT_HEADER 12 ///< Prints the response buffer from byte 12. -#define PRINT_RESPONSE_HASH_WITHOUT_HEADER 16 ///< Prints the response buffer from byte 16. -#define PRINT_RESPONSE_WITH_HEADER 0 ///< Prints the response buffer from byte 0. -#define PRINT_RESPONSE_PCR_WITHOUT_HEADER 30 ///< Prints the pcr buffer from pcr_read. +#define PRINT_RESPONSE_CLEAR 1 ///< Prints response unformatted. +#define PRINT_RESPONSE_HEADERBLOCKS 2 ///< Prints response in commented blocks. +#define PRINT_RESPONSE_HEX_BLOCK 3 ///< Prints response in rows of 16 bytes and shows the line number. +#define PRINT_RESPONSE_HASH 4 ///< Prints response of Hash +#define PRINT_RESPONSE_WITHOUT_HEADER 12 ///< Prints the response buffer from byte 12. +#define PRINT_RESPONSE_HASH_WITHOUT_HEADER 16 ///< Prints the response buffer from byte 16. +#define PRINT_RESPONSE_WITH_HEADER 0 ///< Prints the response buffer from byte 0. +#define PRINT_RESPONSE_PCR_WITHOUT_HEADER 30 ///< Prints the pcr buffer from pcr_read. // time conversion -#define YEAR_SECONDS 31536000 ///< Number of seconds in one year -#define DAY_SECONDS 86400 ///< Number of seconds in one day -#define HOUR_SECONDS 3600 ///< Number of seconds in one hour -#define MINUTE_SECONDS 60 ///< Number of seconds in one minute -#define MILISECOND_TO_SECOND 1000 ///< Convertion from miliseconds to seconds +#define YEAR_SECONDS 31536000 ///< Number of seconds in one year +#define DAY_SECONDS 86400 ///< Number of seconds in one day +#define HOUR_SECONDS 3600 ///< Number of seconds in one hour +#define MINUTE_SECONDS 60 ///< Number of seconds in one minute +#define MILISECOND_TO_SECOND 1000 ///< Convertion from miliseconds to seconds // hash -#define STD_CC_HASH_SIZE 18 ///< Hash command size +#define STD_CC_HASH_SIZE 18 ///< Hash command size // TPM_PT constants #define PT_FIXED_SELECTOR 1 #define PT_VAR_SELECTOR 2 - //-------------"Macros"------------- // Null pointer check -#define NULL_POINTER_CHECK(x) if (NULL == x) { ret_val = EINVAL; fprintf(stderr, "Error: Invalid argument.\n"); break; } ///< Argument NULL check. +#define NULL_POINTER_CHECK(x) if (NULL == x) { ret_val = EINVAL; fprintf(stderr, "Error: Invalid argument.\n"); break; } ///< Argument NULL check. #define MALLOC_ERROR_CHECK(x) if (NULL == x) { ret_val = errno; fprintf(stderr, "Error (re)allocating memory.\n"); break; } ///< Malloc error check. #define MEMSET_FREE(x, y) if (NULL != x) { memset(x, 0, y); free(x); x = NULL; } ///< Sets memory to 0, frees memory and sets pointer to NULL. // Return value check @@ -119,423 +123,413 @@ //-------------"Methods"------------- /** - * @brief Convert (max.) 8 byte buffer to an unsigned long long integer. - * @param [in] *input_buffer Input buffer. Make sure that its size is at least as high as offset + length. - * @param [in] offset Start byte for conversion. - * @param [in] length Amount of bytes to be converted. - * @param [out] *output_value Return the converted unsigned long long integer. - * @return One of the listed return codes. - * @retval EINVAL In case of a NULL pointer or length is greater than 8. - * @retval EXIT_SUCCESS In case of success. - * @date 2014/06/26 + * @brief Convert (max.) 8 byte buffer to an unsigned 64-bit integer. + * @param [in] *input_buffer Input buffer. Make sure that its size is at least as high as offset + length. + * @param [in] offset Start byte for conversion. + * @param [in] length Amount of bytes to be converted. + * @param [out] *output_value Return the converted unsigned 64-bit integer. + * @param [in] input_buffer_size Size of input_buffer in bytes. + * @return One of the listed return codes. + * @retval EINVAL In case of a NULL pointer or length is greater than 8. + * @retval EXIT_SUCCESS In case of success. + * @date 2014/06/26 */ -int buf_to_uint64(uint8_t *input_buffer, uint32_t offset, uint8_t length, unsigned long long *output_value); +static int buf_to_uint64(uint8_t *input_buffer, uint32_t offset, uint32_t length, uint64_t *output_value, uint32_t input_buffer_size); /** - * @brief Convert a hexadecimal string representation of bytes like "0A1F" and returns an array containing the actual byte values as an array (e.g. { 0x0A, 0x1F }). - * @param [in] *byte_string Incoming bytes as string. - * @param [out] *byte_values Byte array representation of given input string. Must be allocated by caller with the length given in byte_values_size. - * @param [in] byte_values_size Size of byte_values array. - * @return One of the listed return codes. - * @retval EXIT_SUCCESS In case of success. - * @retval EINVAL In case of a NULL pointer. - * @retval value of errno In case parsing error. - * @date 2014/06/26 + * @brief Convert a hexadecimal string representation of bytes like "0A1F" and returns an array containing the actual byte values as an array (e.g. { 0x0A, 0x1F }). + * @param [in] *byte_string Incoming bytes as string. + * @param [out] *byte_values Byte array representation of given input string. Must be allocated by caller with the length given in byte_values_size. + * @param [in] byte_values_size Size of byte_values array. + * @return One of the listed return codes. + * @retval EXIT_SUCCESS In case of success. + * @retval EINVAL In case of a NULL pointer. + * @retval value of errno In case parsing error. + * @date 2014/06/26 */ -int hexstr_to_bytearray(char *byte_string, uint8_t *byte_values, size_t byte_values_size); +static int hexstr_to_bytearray(char *byte_string, uint8_t *byte_values, size_t byte_values_size); /** - * @brief Convert a number to a byte buffer. - * @param [in] input User input. - * @param [in] input_size Size of input data type in bytes. - * @param [out] *output_byte Return buffer for the converted integer. Must be allocated by the caller with at least a size of 'input_size'. - * @return One of the listed return codes. - * @retval EINVAL In case of a NULL pointer. - * @retval EXIT_SUCCESS In case of success. - * @date 2014/06/26 + * @brief Convert a number to a byte buffer. + * @param [in] input User input. + * @param [in] input_size Size of input data type in bytes. + * @param [out] *output_byte Return buffer for the converted integer. Must be allocated by the caller with at least a size of 'input_size'. + * @return One of the listed return codes. + * @retval EINVAL In case of a NULL pointer. + * @retval EXIT_SUCCESS In case of success. + * @date 2014/06/26 */ -int int_to_bytearray(uint64_t input, uint32_t input_size, uint8_t *output_byte); +static int int_to_bytearray(uint64_t input, uint32_t input_size, uint8_t *output_byte); /** - * @brief Create the PCR_Extend command. - * @param [in] *pcr_index_str User input string for PCR index. - * @param [in] *pcr_digest_str User input string of value to extend the selected PCR with. - * @param [out] *pcr_cmd_buf Return buffer for the complete command. Must be allocated by caller. - * @param [in] *pcr_cmd_buf_size Size of memory allocated at pcr_cmd_buf in bytes. - * @param [in] *option Set to 'e' for extending with SHA-1 and to 'E' for SHA-256. - * @return One of the listed return codes. - * @retval EINVAL In case of a NULL pointer or an invalid option. - * @retval EXIT_SUCCESS In case of success. - * @retval ERR_BAD_CMD In case of bad user input. - * @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray. - * @date 2014/06/26 + * @brief Create the PCR_Extend command. + * @param [in] *pcr_index_str User input string for PCR index. + * @param [in] *pcr_digest_str User input string of value to extend the selected PCR with. + * @param [out] *pcr_cmd_buf Return buffer for the complete command. Must be allocated by caller. + * @param [in] *pcr_cmd_buf_size Size of memory allocated at pcr_cmd_buf in bytes. + * @param [in] *option Set to 'e' for extending with SHA-1 and to 'E' for SHA-256. + * @return One of the listed return codes. + * @retval EINVAL In case of a NULL pointer or an invalid option. + * @retval EXIT_SUCCESS In case of success. + * @retval ERR_BAD_CMD In case of bad user input. + * @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray. + * @date 2014/06/26 */ -int pcr_extend(char *pcr_index_str, char *pcr_digest_str, uint8_t *pcr_cmd_buf, size_t pcr_cmd_buf_size, char option); +static int pcr_extend(char *pcr_index_str, char *pcr_digest_str, uint8_t *pcr_cmd_buf, size_t pcr_cmd_buf_size, char option); /** - * @brief Create the PCR_Read command. - * @param [in] *pcr_index_str User input string for PCR index. - * @param [out] *pcr_cmd_buf Return buffer for the complete command. - * @param [in] *option Set to 'r' for reading with SHA-1 and to 'R' for SHA-256. - * @return One of the listed return codes. - * @retval EINVAL In case of a NULL pointer or an invalid option. - * @retval EXIT_SUCCESS In case of success. - * @retval ERR_BAD_CMD In case of bad user input. - * @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray. - * @date 2014/06/26 + * @brief Create the PCR_Read command. + * @param [in] *pcr_index_str User input string for PCR index. + * @param [out] *pcr_cmd_buf Return buffer for the complete command. + * @param [in] *option Set to 'r' for reading with SHA-1 and to 'R' for SHA-256. + * @return One of the listed return codes. + * @retval EINVAL In case of a NULL pointer or an invalid option. + * @retval EXIT_SUCCESS In case of success. + * @retval ERR_BAD_CMD In case of bad user input. + * @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray. + * @date 2014/06/26 */ -int pcr_read(char *pcr_index_str, uint8_t *pcr_cmd_buf, char option); +static int pcr_read(char *pcr_index_str, uint8_t *pcr_cmd_buf, char option); /** - * @brief Create the PCR_Reset command. - * @param [in] *pcr_index_str User input string for PCR index. - * @param [out] *pcr_cmd_buf Return buffer for the complete command. - * @return One of the listed return codes. - * @retval EINVAL In case of a NULL pointer. - * @retval EXIT_SUCCESS In case of success. - * @retval ERR_BAD_CMD In case of bad user input. - * @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray. - * @date 2014/06/26 + * @brief Create the PCR_Reset command. + * @param [in] *pcr_index_str User input string for PCR index. + * @param [out] *pcr_cmd_buf Return buffer for the complete command. + * @return One of the listed return codes. + * @retval EINVAL In case of a NULL pointer. + * @retval EXIT_SUCCESS In case of success. + * @retval ERR_BAD_CMD In case of bad user input. + * @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray. + * @date 2014/06/26 */ -int pcr_reset(char *pcr_index_str, uint8_t *pcr_cmd_buf); +static int pcr_reset(char *pcr_index_str, uint8_t *pcr_cmd_buf); /** - * @brief Print the command line usage and switches. - * @date 2014/06/26 + * @brief Print the command line usage and switches. + * @date 2014/06/26 */ -void print_help(); +static void print_help(); /** - * @brief Print the response buffer in different formats. - * @param [in] *response_buf TPM response. - * @param [in] resp_size TPM response size. - * @param [in] offset Starting point for printing buffer. - * @param [in] format Select the output format. - * @return One of the listed return codes. - * @retval EINVAL In case of a NULL pointer or an unknown output format has been transfered. - * @retval EXIT_SUCCESS In case of success. - * @retval buf_to_uint64 All error codes from buf_to_uint64. - * @date 2014/06/26 + * @brief Print the response buffer in different formats. + * @param [in] *response_buf TPM response. + * @param [in] resp_size TPM response size. + * @param [in] offset Starting point for printing buffer. + * @param [in] format Select the output format. + * @return One of the listed return codes. + * @retval EINVAL In case of a NULL pointer or an unknown output format has been transfered. + * @retval EXIT_SUCCESS In case of success. + * @retval buf_to_uint64 All error codes from buf_to_uint64. + * @date 2014/06/26 */ -int print_response_buf(uint8_t *response_buf, size_t resp_size, uint32_t offset, int format); +static int print_response_buf(uint8_t *response_buf, size_t resp_size, uint32_t offset, int format); /** - * @brief Print a TPM response. - * @param [in] *response_buf TPM response. - * @param [in] resp_size TPM response size. - * @param [in] option Defines appearance of output. Can have the following values:\n - - PRINT_RESPONSE_CLEAR - - PRINT_RESPONSE_HEADERBLOCKS - - PRINT_RESPONSE_HEX_BLOCK - - PRINT_RESPONSE_WITHOUT_HEADER - - PRINT_RESPONSE_WITH_HEADER - * @return One of the listed return codes. - * @retval EINVAL In case of a NULL pointer. - * @retval EXIT_SUCCESS In case of success. - * @retval print_response_buf All error codes from print_response_buf. - * @retval print_clock_info All error codes from print_clock_info. - * @retval print_capability_flags All error codes from print_capability_flags. - * @date 2014/06/26 + * @brief Print a TPM response. + * @param [in] *response_buf TPM response. + * @param [in] resp_size TPM response size. + * @param [in] option Defines appearance of output. Can have the following values:\n + - PRINT_RESPONSE_CLEAR + - PRINT_RESPONSE_HEADERBLOCKS + - PRINT_RESPONSE_HEX_BLOCK + - PRINT_RESPONSE_WITHOUT_HEADER + - PRINT_RESPONSE_WITH_HEADER + * @return One of the listed return codes. + * @retval EINVAL In case of a NULL pointer. + * @retval EXIT_SUCCESS In case of success. + * @retval print_response_buf All error codes from print_response_buf. + * @retval print_clock_info All error codes from print_clock_info. + * @retval print_capability_flags All error codes from print_capability_flags. + * @date 2014/06/26 */ -int response_print(uint8_t *response_buf, size_t resp_size, int option); +static int response_print(uint8_t *response_buf, size_t resp_size, int option); /** - * @brief Check a TPM response for errors. - * @param [in] *response_buf TPM response. Must have at least a size of TPM_CMD_HEADER_SIZE bytes. - * @return Returns the TPM return code extracted from the given TPM response or one of the listed return codes. - * @retval EINVAL In case of a NULL pointer. - * @retval buf_to_uint64 All error codes from buf_to_uint64. - * @retval EXIT_SUCCESS In case of success. - * @date 2014/06/26 + * @brief Check a TPM response for errors. + * @param [in] *response_buf TPM response. Must have at least a size of TPM_CMD_HEADER_SIZE bytes. + * @return Returns the TPM return code extracted from the given TPM response or one of the listed return codes. + * @retval EINVAL In case of a NULL pointer. + * @retval buf_to_uint64 All error codes from buf_to_uint64. + * @retval EXIT_SUCCESS In case of success. + * @date 2014/06/26 */ -int return_error_handling(uint8_t *response_buf); +static int return_error_handling(uint8_t *response_buf); /** - * @brief Transmit TPM command to /dev/tpm0 and get the response. - * @param [in] *buf TPM request. - * @param [in] length TPM request length. - * @param [out] *response TPM response. - * @param [out] *resp_length TPM response length. - * @return One of the listed return codes or the error code stored in the global errno system variable. - * @retval EINVAL In case of a NULL pointer. - * @retval EXIT_SUCCESS In case of success. - * @date 2014/06/26 + * @brief Transmit TPM command to /dev/tpm0 and get the response. + * @param [in] *buf TPM request. + * @param [in] length TPM request length. + * @param [out] *response TPM response. + * @param [out] *resp_length TPM response length. + * @return One of the listed return codes or the error code stored in the global errno system variable. + * @retval EINVAL In case of a NULL pointer. + * @retval EXIT_SUCCESS In case of success. + * @date 2014/06/26 */ -int tpmtool_transmit(const uint8_t *buf, ssize_t length, uint8_t *response, ssize_t *resp_length); +static int tpmtool_transmit(const uint8_t *buf, ssize_t length, uint8_t *response, ssize_t *resp_length); /** - * @brief Print the capability flags. - * @param [in] *response_buf TPM response. - * @return One of the listed return codes. - * @retval EINVAL In case of a NULL pointer. - * @retval EXIT_SUCCESS In case of success. - * @retval buf_to_uint64 All error codes from buf_to_uint64. - * @date 2014/06/26 + * @brief Print the capability flags. + * @param [in] *response_buf TPM response. + * @param [in] cap_selector Type of capabilities to print. + * @return One of the listed return codes. + * @retval EINVAL In case of a NULL pointer. + * @retval EXIT_SUCCESS In case of success. + * @retval buf_to_uint64 All error codes from buf_to_uint64. + * @date 2014/06/26 */ -int print_capability_flags(uint8_t *response_buf, uint8_t cap_selector); +static int print_capability_flags(uint8_t *response_buf, uint8_t cap_selector); /** - * @brief Print the clock info. - * @param [in] *response_buf TPM response. - * @return One of the listed return codes. - * @retval EINVAL In case of a NULL pointer. - * @retval EXIT_SUCCESS In case of success. - * @retval buf_to_uint64 All error codes from buf_to_uint64. - * @date 2014/06/26 + * @brief Print the clock info. + * @param [in] *response_buf TPM response. + * @return One of the listed return codes. + * @retval EINVAL In case of a NULL pointer. + * @retval EXIT_SUCCESS In case of success. + * @retval buf_to_uint64 All error codes from buf_to_uint64. + * @date 2014/06/26 */ -int print_clock_info(uint8_t *response_buf); +static int print_clock_info(uint8_t *response_buf); /** - * @brief Create the get_random command. - * @param [in] *data_length_string User input string for random data length. - * @param [out] *response_buf Return buffer for the complete command. - * @return One of the listed return codes. - * @retval EINVAL In case of a NULL pointer. - * @retval EXIT_SUCCESS In case of success. - * @retval ERR_BAD_CMD In case of bad user input. - * @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray. - * @date 2014/06/26 + * @brief Create the get_random command. + * @param [in] *data_length_string User input string for random data length. + * @param [out] *response_buf Return buffer for the complete command. + * @return One of the listed return codes. + * @retval EINVAL In case of a NULL pointer. + * @retval EXIT_SUCCESS In case of success. + * @retval ERR_BAD_CMD In case of bad user input. + * @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray. + * @date 2014/06/26 */ -int get_random(char *data_length_string, uint8_t *response_buf); +static int get_random(char *data_length_string, uint8_t *response_buf); /** - * @brief Create the simple hash command. - * @param [in] *data_string User input string of data to be hashed. - * @param [in] option Set to 's' for hashing with SHA-1 and to 'S' for SHA-256. - * @param [out] *hash_cmd_buf Return buffer for the complete command. - * @param [in] hash_cmd_buf_size Return buffer size. - * @return One of the listed return codes. - * @retval EINVAL In case of a NULL pointer. - * @retval EXIT_SUCCESS In case of success. - * @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray. - * @retval int_to_bytearray All error codes from int_to_bytearray. - * @date 2014/06/26 + * @brief Create the simple hash command. + * @param [in] *data_string User input string of data to be hashed. + * @param [in] option Set to 's' for hashing with SHA-1 and to 'S' for SHA-256. + * @param [out] *hash_cmd_buf Return buffer for the complete command. + * @param [in] hash_cmd_buf_size Return buffer size. + * @return One of the listed return codes. + * @retval EINVAL In case of a NULL pointer. + * @retval EXIT_SUCCESS In case of success. + * @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray. + * @retval int_to_bytearray All error codes from int_to_bytearray. + * @date 2014/06/26 */ -int create_hash(char *data_string, char option, uint8_t *hash_cmd_buf, uint32_t hash_cmd_buf_size); +static int create_hash(char *data_string, char option, uint8_t *hash_cmd_buf, uint32_t hash_cmd_buf_size); /** - * @brief Create and transmit a sequence of TPM commands for hashing larger amounts of data. - * @param [in] *data_string User input string of data to be hashed. - * @param [in] option Set to 'a' for hashing with SHA-1 and to 'A' for SHA-256. - * @param [out] *tpm_response_buf TPM response. - * @param [out] *tpm_response_buf_size Size of tpm_response_buf. - * @return One of the listed return codes or the error code stored in the global errno system variable. - * @retval EINVAL In case of a NULL pointer. - * @retval EXIT_SUCCESS In case of success. - * @retval value of errno In case of memory allocation error. - * @retval buf_to_uint64 All error codes from buf_to_uint64. - * @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray. - * @retval int_to_bytearray All error codes from int_to_bytearray. - * @retval tpmtool_transmit All error codes from tpmtool_transmit. - * @retval print_response_buf All error codes from print_response_buf - * @date 2014/06/26 + * @brief Create and transmit a sequence of TPM commands for hashing larger amounts of data. + * @param [in] *data_string User input string of data to be hashed. + * @param [in] option Set to 'a' for hashing with SHA-1 and to 'A' for SHA-256. + * @param [out] *tpm_response_buf TPM response. + * @param [out] *tpm_response_buf_size Size of tpm_response_buf. + * @return One of the listed return codes or the error code stored in the global errno system variable. + * @retval EINVAL In case of a NULL pointer. + * @retval EXIT_SUCCESS In case of success. + * @retval value of errno In case of memory allocation error. + * @retval buf_to_uint64 All error codes from buf_to_uint64. + * @retval hexstr_to_bytearray All error codes from hexstr_to_bytearray. + * @retval int_to_bytearray All error codes from int_to_bytearray. + * @retval tpmtool_transmit All error codes from tpmtool_transmit. + * @retval print_response_buf All error codes from print_response_buf + * @date 2014/06/26 */ -int create_hash_sequence(char *data_string, char option, uint8_t *tpm_response_buf, ssize_t *tpm_response_buf_size); +static int create_hash_sequence(char *data_string, char option, uint8_t *tpm_response_buf, ssize_t *tpm_response_buf_size); //-------------"command bytes"------------- -static const uint8_t tpm2_startup_clear[] ={ - // TPM2_Startup(SU_CLEAR) - 0x80, 0x01, // TPM_ST_NO_SESSIONS - 0x00, 0x00, 0x00, 0x0C, // commandSize - 0x00, 0x00, 0x01, 0x44, // TPM_CC_Startup - 0x00, 0x00 // TPM_ST_CLEAR +static const uint8_t tpm2_startup_clear[] = { + 0x80, 0x01, // TPM_ST_NO_SESSIONS + 0x00, 0x00, 0x00, 0x0C, // commandSize + 0x00, 0x00, 0x01, 0x44, // TPM_CC_Startup + 0x00, 0x00 // TPM_ST_CLEAR }; -static const uint8_t tpm2_startup_state[] ={ - // TPM2_Startup(SU_STATE) - 0x80, 0x01, // TPM_ST_NO_SESSIONS - 0x00, 0x00, 0x00, 0x0C, // commandSize - 0x00, 0x00, 0x01, 0x44, // TPM_CC_Startup - 0x00, 0x01 // TPM_ST_STATE +static const uint8_t tpm2_startup_state[] = { + 0x80, 0x01, // TPM_ST_NO_SESSIONS + 0x00, 0x00, 0x00, 0x0C, // commandSize + 0x00, 0x00, 0x01, 0x44, // TPM_CC_Startup + 0x00, 0x01 // TPM_ST_STATE }; -static const uint8_t tpm_cc_shutdown_clear[] ={ - // TPM_CC_Shutdown(CLEAR) - 0x80, 0x01, // TPM_ST_NO_SESSIONS - 0x00, 0x00, 0x00, 0x0C, // commandSize - 0x00, 0x00, 0x01, 0x45, // TPM_CC_Shutdown - 0x00, 0x00 // TPM_SU_CLEAR +static const uint8_t tpm_cc_shutdown_clear[] = { + 0x80, 0x01, // TPM_ST_NO_SESSIONS + 0x00, 0x00, 0x00, 0x0C, // commandSize + 0x00, 0x00, 0x01, 0x45, // TPM_CC_Shutdown + 0x00, 0x00 // TPM_SU_CLEAR }; -static const uint8_t tpm_cc_shutdown_state[] ={ - // TPM_CC_Shutdown(STATE) - 0x80, 0x01, // TPM_ST_NO_SESSIONS - 0x00, 0x00, 0x00, 0x0C, // commandSize - 0x00, 0x00, 0x01, 0x45, // TPM_CC_Shutdown - 0x00, 0x01 // TPM_SU_STATE +static const uint8_t tpm_cc_shutdown_state[] = { + 0x80, 0x01, // TPM_ST_NO_SESSIONS + 0x00, 0x00, 0x00, 0x0C, // commandSize + 0x00, 0x00, 0x01, 0x45, // TPM_CC_Shutdown + 0x00, 0x01 // TPM_SU_STATE }; -static const uint8_t tpm2_self_test[] ={ - // TPM2_SelfTest(fullTest=No) - 0x80, 0x01, // TPM_ST_NO_SESSIONS - 0x00, 0x00, 0x00, 0x0B, // commandSize - 0x00, 0x00, 0x01, 0x43, // TPM_CC_SelfTest - 0x00 // fullTest=No +static const uint8_t tpm2_self_test[] = { + 0x80, 0x01, // TPM_ST_NO_SESSIONS + 0x00, 0x00, 0x00, 0x0B, // commandSize + 0x00, 0x00, 0x01, 0x43, // TPM_CC_SelfTest + 0x00 // fullTest=No }; -static const uint8_t tpm2_self_test_full[] ={ - // TPM2_SelfTest(fullTest=YES) - 0x80, 0x01, // TPM_ST_NO_SESSIONS - 0x00, 0x00, 0x00, 0x0B, // commandSize - 0x00, 0x00, 0x01, 0x43, // TPM_CC_SelfTest - 0x01 // fullTest=Yes +static const uint8_t tpm2_self_test_full[] = { + 0x80, 0x01, // TPM_ST_NO_SESSIONS + 0x00, 0x00, 0x00, 0x0B, // commandSize + 0x00, 0x00, 0x01, 0x43, // TPM_CC_SelfTest + 0x01 // fullTest=Yes }; -static const uint8_t tpm_cc_get_test_result[] ={ - // TPM_CC_GetTestResult - 0x80, 0x01, // TPM_ST_NO_SESSIONS - 0x00, 0x00, 0x00, 0x0A, // commandSize - 0x00, 0x00, 0x01, 0x7C // TPM_CC_GetTestResult +static const uint8_t tpm_cc_get_test_result[] = { + 0x80, 0x01, // TPM_ST_NO_SESSIONS + 0x00, 0x00, 0x00, 0x0A, // commandSize + 0x00, 0x00, 0x01, 0x7C // TPM_CC_GetTestResult }; -static const uint8_t tpm2_self_test_incremental[] ={ - // TPM_CC_IncrementalSelfTest - 0x80, 0x01, // TPM_ST_NO_SESSIONS - 0x00, 0x00, 0x00, 0x2A, // commandSize - 0x00, 0x00, 0x01, 0x42, // TPM_CC_IncrementalSelfTest - 0x00, 0x00, 0x00, 0x0E, // Count of Algorithm - 0x00, 0x01, 0x00, 0x04, // Algorithm two per line - 0x00, 0x05, 0x00, 0x06, - 0x00, 0x08, 0x00, 0x0A, - 0x00, 0x0B, 0x00, 0x14, - 0x00, 0x15, 0x00, 0x16, - 0x00, 0x17, 0x00, 0x22, - 0x00, 0x25, 0x00, 0x43 +static const uint8_t tpm2_self_test_incremental[] = { + 0x80, 0x01, // TPM_ST_NO_SESSIONS + 0x00, 0x00, 0x00, 0x2A, // commandSize + 0x00, 0x00, 0x01, 0x42, // TPM_CC_IncrementalSelfTest + 0x00, 0x00, 0x00, 0x0E, // Count of Algorithm + 0x00, 0x01, 0x00, 0x04, // Algorithm two per line + 0x00, 0x05, 0x00, 0x06, + 0x00, 0x08, 0x00, 0x0A, + 0x00, 0x0B, 0x00, 0x14, + 0x00, 0x15, 0x00, 0x16, + 0x00, 0x17, 0x00, 0x22, + 0x00, 0x25, 0x00, 0x43 }; -static const uint8_t tpm2_getrandom[] ={ - // TPM_CC_GetRandom - 0x80, 0x01, // TPM_ST_NO_SESSIONS - 0x00, 0x00, 0x00, 0x0C, // commandSize - 0x00, 0x00, 0x01, 0x7B, // TPM_CC_GetRandom - 0x00, 0x00 // bytesRequested (will be set later) +static const uint8_t tpm2_getrandom[] = { + 0x80, 0x01, // TPM_ST_NO_SESSIONS + 0x00, 0x00, 0x00, 0x0C, // commandSize + 0x00, 0x00, 0x01, 0x7B, // TPM_CC_GetRandom + 0x00, 0x00 // bytesRequested (will be set later) }; -static const uint8_t tpm_cc_readclock[] ={ - // TPM_CC_ReadClock - 0x80, 0x01, // TPM_ST_NO_SESSIONS - 0x00, 0x00, 0x00, 0x0A, // commandSize - 0x00, 0x00, 0x01, 0x81 // TPM_CC_ReadClock +static const uint8_t tpm_cc_readclock[] = { + 0x80, 0x01, // TPM_ST_NO_SESSIONS + 0x00, 0x00, 0x00, 0x0A, // commandSize + 0x00, 0x00, 0x01, 0x81 // TPM_CC_ReadClock }; static const uint8_t tpm2_getcapability_fixed[] ={ - // TPM2_GetCapability (TPM_CAP_TPM_PROPERTIES, -- ) - 0x80, 0x01, // TPM_ST_NO_SESSIONS - 0x00, 0x00, 0x00, 0x16, // commandSize - 0x00, 0x00, 0x01, 0x7A, // TPM_CC_GetCapability - 0x00, 0x00, 0x00, 0x06, // TPM_CAP_TPM_PROPERTIES (Property Type: TPM_PT) - 0x00, 0x00, 0x01, 0x00, // Property: TPM_PT_FAMILY_INDICATOR: PT_GROUP * 1 + 0 - 0x00, 0x00, 0x00, 0x2D // PropertyCount 2D (from 100 - 201) + 0x80, 0x01, // TPM_ST_NO_SESSIONS + 0x00, 0x00, 0x00, 0x16, // commandSize + 0x00, 0x00, 0x01, 0x7A, // TPM_CC_GetCapability + 0x00, 0x00, 0x00, 0x06, // TPM_CAP_TPM_PROPERTIES (Property Type: TPM_PT) + 0x00, 0x00, 0x01, 0x00, // Property: TPM_PT_FAMILY_INDICATOR: PT_GROUP * 1 + 0 + 0x00, 0x00, 0x00, 0x2D // PropertyCount 2D (from 100 - 201) }; static const uint8_t tpm2_getcapability_var[] ={ - // TPM2_GetCapability (TPM_CAP_TPM_PROPERTIES, -- ) - 0x80, 0x01, // TPM_ST_NO_SESSIONS - 0x00, 0x00, 0x00, 0x16, // commandSize - 0x00, 0x00, 0x01, 0x7A, // TPM_CC_GetCapability - 0x00, 0x00, 0x00, 0x06, // TPM_CAP_TPM_PROPERTIES (Property Type: TPM_PT) - 0x00, 0x00, 0x02, 0x00, // Property: TPM_PT_FAMILY_INDICATOR: PT_GROUP * 2 + 0 - 0x00, 0x00, 0x00, 0x2D // PropertyCount 2D (from 200 - 301) + 0x80, 0x01, // TPM_ST_NO_SESSIONS + 0x00, 0x00, 0x00, 0x16, // commandSize + 0x00, 0x00, 0x01, 0x7A, // TPM_CC_GetCapability + 0x00, 0x00, 0x00, 0x06, // TPM_CAP_TPM_PROPERTIES (Property Type: TPM_PT) + 0x00, 0x00, 0x02, 0x00, // Property: TPM_PT_FAMILY_INDICATOR: PT_GROUP * 2 + 0 + 0x00, 0x00, 0x00, 0x2D // PropertyCount 2D (from 200 - 301) }; // Hash -static const uint8_t tpm2_hash[] ={ - 0x80, 0x01, // TPM_ST_NO_SESSIONS - 0x00, 0x00, 0x00, 0x0e, // commandSize - 0x00, 0x00, 0x01, 0x7D, // TPM_CC_Hash - 0x00, 0x00, // size (will be set later) - // buffer (will be added later) - 0x00, 0x00, // hashAlg (will be added later) - 0x00, 0x00, 0x00, 0x00 // hierarchy of the ticket (TPM_RH_NULL; will be added later) +static const uint8_t tpm2_hash[] = { + 0x80, 0x01, // TPM_ST_NO_SESSIONS + 0x00, 0x00, 0x00, 0x0e, // commandSize + 0x00, 0x00, 0x01, 0x7D, // TPM_CC_Hash + 0x00, 0x00, // size (will be set later) + // buffer (will be added later) + 0x00, 0x00, // hashAlg (will be added later) + 0x00, 0x00, 0x00, 0x00 // hierarchy of the ticket (TPM_RH_NULL; will be added later) }; // HashSequence -static uint8_t tpm2_hash_sequence_start[] ={ - 0x80, 0x01, // TPM_ST_NO_SESSIONS - 0x00, 0x00, 0x00, 0x0e, // commandSize - 0x00, 0x00, 0x01, 0x86, // TPM_CC_HashSequenceStart - 0x00, 0x00, // authSize (NULL Password) - // null (indicate a NULL Password) - 0x00, 0x00 // hashAlg (will be set later) +static uint8_t tpm2_hash_sequence_start[] = { + 0x80, 0x01, // TPM_ST_NO_SESSIONS + 0x00, 0x00, 0x00, 0x0e, // commandSize + 0x00, 0x00, 0x01, 0x86, // TPM_CC_HashSequenceStart + 0x00, 0x00, // authSize (NULL Password) + // null (indicate a NULL Password) + 0x00, 0x00 // hashAlg (will be set later) }; -static uint8_t tpm2_sequence_update[] ={ - 0x80, 0x02, // TPM_ST_SESSIONS - 0x00, 0x00, 0x00, 0x00, // commandSize (will be set later) - 0x00, 0x00, 0x01, 0x5c, // TPM_CC_SequenceUpdate - 0x00, 0x00, 0x00, 0x00, // sequenceHandle (will be set later) - 0x00, 0x00, // authSize (NULL Password) - // null (indicate a NULL Password) - 0x00, 0x09, // authSize (password authorization session) - 0x40, 0x00, 0x00, 0x09, // TPM_RS_PW (indicate a password authorization session) - 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00 // size (will be set later) - // buffer (will be added later) +static uint8_t tpm2_sequence_update[] = { + 0x80, 0x02, // TPM_ST_SESSIONS + 0x00, 0x00, 0x00, 0x00, // commandSize (will be set later) + 0x00, 0x00, 0x01, 0x5c, // TPM_CC_SequenceUpdate + 0x00, 0x00, 0x00, 0x00, // sequenceHandle (will be set later) + 0x00, 0x00, // authSize (NULL Password) + // null (indicate a NULL Password) + 0x00, 0x09, // authSize (password authorization session) + 0x40, 0x00, 0x00, 0x09, // TPM_RS_PW (indicate a password authorization session) + 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00 // size (will be set later) + // buffer (will be added later) }; -static uint8_t tpm2_sequence_complete[] ={ - 0x80, 0x02, // TPM_ST_SESSIONS - 0x00, 0x00, 0x00, 0x21, // commandSize - 0x00, 0x00, 0x01, 0x3e, // TPM_CC_SequenceComplete - 0x00, 0x00, 0x00, 0x00, // sequenceHandle (will be set later) - 0x00, 0x00, // authSize (NULL Password) - // null (indicate a NULL Password) - 0x00, 0x09, // authSize (password authorization session) - 0x40, 0x00, 0x00, 0x09, // TPM_RS_PW (indicate a password authorization session) - 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, // size (NULL buffer) - // null (indicate an empty buffer buffer) - 0x40, 0x00, 0x00, 0x07 // hierarchy of the ticket (TPM_RH_NULL) +static uint8_t tpm2_sequence_complete[] = { + 0x80, 0x02, // TPM_ST_SESSIONS + 0x00, 0x00, 0x00, 0x21, // commandSize + 0x00, 0x00, 0x01, 0x3e, // TPM_CC_SequenceComplete + 0x00, 0x00, 0x00, 0x00, // sequenceHandle (will be set later) + 0x00, 0x00, // authSize (NULL Password) + // null (indicate a NULL Password) + 0x00, 0x09, // authSize (password authorization session) + 0x40, 0x00, 0x00, 0x09, // TPM_RS_PW (indicate a password authorization session) + 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, // size (NULL buffer) + // null (indicate an empty buffer buffer) + 0x40, 0x00, 0x00, 0x07 // hierarchy of the ticket (TPM_RH_NULL) }; -static const uint8_t sha1_alg[] ={ - 0x00, 0x04 // command for sha1 alg +static const uint8_t sha1_alg[] = { + 0x00, 0x04 // command for sha1 alg }; -static const uint8_t sha256_alg[] ={ - 0x00, 0x0B // command for sha256 alg +static const uint8_t sha256_alg[] = { + 0x00, 0x0B // command for sha256 alg }; -static const uint8_t tpm_cc_hash_hierarchy[] ={ - 0x40, 0x00, 0x00, 0x07 // hierarchy of the ticket (TPM_RH_NULL) +static const uint8_t tpm_cc_hash_hierarchy[] = { + 0x40, 0x00, 0x00, 0x07 // hierarchy of the ticket (TPM_RH_NULL) }; //PCR_Command -static const uint8_t tpm2_pcr_read[] ={ - 0x80, 0x01, // TPM_ST_NO_SESSIONS - 0x00, 0x00, 0x00, 0x14, // commandSize - 0x00, 0x00, 0x01, 0x7E, // TPM_CC_PCR_Read - 0x00, 0x00, 0x00, 0x01, // count (TPML_PCR_SELECTION) - 0x00, 0x00, // hash (TPMS_PCR_SELECTION; will be set later) - 0x03, // sizeofSelect (TPMS_PCR_SELECTION) - 0x00, 0x00, 0x00 // pcrSelect (TPMS_PCR_SELECTION) +static const uint8_t tpm2_pcr_read[] = { + 0x80, 0x01, // TPM_ST_NO_SESSIONS + 0x00, 0x00, 0x00, 0x14, // commandSize + 0x00, 0x00, 0x01, 0x7E, // TPM_CC_PCR_Read + 0x00, 0x00, 0x00, 0x01, // count (TPML_PCR_SELECTION) + 0x00, 0x00, // hash (TPMS_PCR_SELECTION; will be set later) + 0x03, // sizeofSelect (TPMS_PCR_SELECTION) + 0x00, 0x00, 0x00 // pcrSelect (TPMS_PCR_SELECTION) }; -static const uint8_t tpm2_pcr_extend[] ={ - 0x80, 0x02, // TPM_ST_SESSIONS - 0x00, 0x00, 0x00, 0x00, // commandSize (will be set later) - 0x00, 0x00, 0x01, 0x82, // TPM_CC_PCR_Extend - 0x00, 0x00, 0x00, 0x00, // {PCR_FIRST:PCR_LAST} (TPMI_DH_PCR) - 0x00, 0x00, // authSize (NULL Password) - // null (indicate a NULL Password) - 0x00, 0x09, // authSize (password authorization session) - 0x40, 0x00, 0x00, 0x09, // TPM_RS_PW (indicate a password authorization session) - 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, // count (TPML_DIGEST_VALUES) - 0x00, 0x00 // hashAlg (TPMT_HA; will be set later) - // digest (TPMT_HA; will be added later) +static const uint8_t tpm2_pcr_extend[] = { + 0x80, 0x02, // TPM_ST_SESSIONS + 0x00, 0x00, 0x00, 0x00, // commandSize (will be set later) + 0x00, 0x00, 0x01, 0x82, // TPM_CC_PCR_Extend + 0x00, 0x00, 0x00, 0x00, // {PCR_FIRST:PCR_LAST} (TPMI_DH_PCR) + 0x00, 0x00, // authSize (NULL Password) + // null (indicate a NULL Password) + 0x00, 0x09, // authSize (password authorization session) + 0x40, 0x00, 0x00, 0x09, // TPM_RS_PW (indicate a password authorization session) + 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, // count (TPML_DIGEST_VALUES) + 0x00, 0x00 // hashAlg (TPMT_HA; will be set later) + // digest (TPMT_HA; will be added later) }; -static const uint8_t tpm2_pcr_reset[] ={ - 0x80, 0x02, // TPM_ST_SESSIONS - 0x00, 0x00, 0x00, 0x1B, // commandSize - 0x00, 0x00, 0x01, 0x3D, // TPM_CC_PCR_Reset - 0x00, 0x00, 0x00, 0x00, // {PCR_FIRST:PCR_LAST} (TPMI_DH_PCR) - 0x00, 0x00, // authSize (NULL Password) - // null (indicate a NULL Password) - 0x00, 0x09, // authSize (password authorization session) - 0x40, 0x00, 0x00, 0x09, // TPM_RS_PW (indicate a password authorization session) - 0x00, 0x00, 0x01, 0x00, 0x00 +static const uint8_t tpm2_pcr_reset[] = { + 0x80, 0x02, // TPM_ST_SESSIONS + 0x00, 0x00, 0x00, 0x1B, // commandSize + 0x00, 0x00, 0x01, 0x3D, // TPM_CC_PCR_Reset + 0x00, 0x00, 0x00, 0x00, // {PCR_FIRST:PCR_LAST} (TPMI_DH_PCR) + 0x00, 0x00, // authSize (NULL Password) + // null (indicate a NULL Password) + 0x00, 0x09, // authSize (password authorization session) + 0x40, 0x00, 0x00, 0x09, // TPM_RS_PW (indicate a password authorization session) + 0x00, 0x00, 0x01, 0x00, 0x00 }; #endif /* _ELTT2_H_ */