| Index: git/include/tpm_tspi.h |
| =================================================================== |
| --- git.orig/include/tpm_tspi.h |
| +++ git/include/tpm_tspi.h |
| @@ -117,6 +117,10 @@ TSS_RESULT tpmPcrRead(TSS_HTPM a_hTpm, U |
| UINT32 *a_PcrSize, BYTE **a_PcrValue); |
| TSS_RESULT pcrcompositeSetPcrValue(TSS_HPCRS a_hPcrs, UINT32 a_Idx, |
| UINT32 a_PcrSize, BYTE *a_PcrValue); |
| +TSS_RESULT tpmPcrExtend(TSS_HTPM a_hTpm, UINT32 a_Idx, |
| + UINT32 a_DataSize, BYTE *a_Data, |
| + TSS_PCR_EVENT *a_Event, |
| + UINT32 *a_PcrSize, BYTE **a_PcrValue); |
| #ifdef TSS_LIB_IS_12 |
| TSS_RESULT unloadVersionInfo(UINT64 *offset, BYTE *blob, TPM_CAP_VERSION_INFO *v); |
| TSS_RESULT pcrcompositeSetPcrLocality(TSS_HPCRS a_hPcrs, UINT32 localityValue); |
| Index: git/lib/tpm_tspi.c |
| =================================================================== |
| --- git.orig/lib/tpm_tspi.c |
| +++ git/lib/tpm_tspi.c |
| @@ -594,6 +594,20 @@ pcrcompositeSetPcrValue(TSS_HPCRS a_hPcr |
| return result; |
| } |
| |
| +TSS_RESULT |
| +tpmPcrExtend(TSS_HTPM a_hTpm, UINT32 a_Idx, |
| + UINT32 a_DataSize, BYTE *a_Data, |
| + TSS_PCR_EVENT *a_Event, |
| + UINT32 *a_PcrSize, BYTE **a_PcrValue) |
| +{ |
| + TSS_RESULT result = |
| + Tspi_TPM_PcrExtend(a_hTpm, a_Idx, a_DataSize, a_Data, a_Event, |
| + a_PcrSize, a_PcrValue); |
| + tspiResult("Tspi_TPM_PcrExtend", result); |
| + |
| + return result; |
| +} |
| + |
| #ifdef TSS_LIB_IS_12 |
| /* |
| * These getPasswd functions will wrap calls to the other functions and check to see if the TSS |
| Index: git/src/cmds/Makefile.am |
| =================================================================== |
| --- git.orig/src/cmds/Makefile.am |
| +++ git/src/cmds/Makefile.am |
| @@ -22,6 +22,7 @@ |
| # |
| |
| bin_PROGRAMS = tpm_sealdata \ |
| + tpm_extendpcr \ |
| tpm_unsealdata |
| |
| if TSS_LIB_IS_12 |
| @@ -33,4 +34,5 @@ endif |
| LDADD = $(top_builddir)/lib/libtpm_tspi.la -ltspi $(top_builddir)/lib/libtpm_unseal.la -ltpm_unseal -lcrypto @INTLLIBS@ |
| |
| tpm_sealdata_SOURCES = tpm_sealdata.c |
| +tpm_extendpcr_SOURCES = tpm_extendpcr.c |
| tpm_unsealdata_SOURCES = tpm_unsealdata.c |
| Index: git/src/cmds/tpm_extendpcr.c |
| =================================================================== |
| --- /dev/null |
| +++ git/src/cmds/tpm_extendpcr.c |
| @@ -0,0 +1,181 @@ |
| +/* |
| + * The Initial Developer of the Original Code is International |
| + * Business Machines Corporation. Portions created by IBM |
| + * Corporation are Copyright (C) 2005, 2006 International Business |
| + * Machines Corporation. All Rights Reserved. |
| + * |
| + * This program is free software; you can redistribute it and/or modify |
| + * it under the terms of the Common Public License as published by |
| + * IBM Corporation; either version 1 of the License, or (at your option) |
| + * any later version. |
| + * |
| + * This program is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + * Common Public License for more details. |
| + * |
| + * You should have received a copy of the Common Public License |
| + * along with this program; if not, a copy can be viewed at |
| + * http://www.opensource.org/licenses/cpl1.0.php. |
| + */ |
| +#include <openssl/evp.h> |
| +#include <openssl/sha.h> |
| +#include <limits.h> |
| +#include "tpm_tspi.h" |
| +#include "tpm_utils.h" |
| +#include "tpm_seal.h" |
| + |
| +// #define TPM_EXTENDPCR_DEBUG |
| + |
| +static void help(const char *aCmd) |
| +{ |
| + logCmdHelp(aCmd); |
| + logCmdOption("-i, --infile FILE", |
| + _ |
| + ("Filename containing data to extend PCRs with. Default is STDIN.")); |
| + logCmdOption("-p, --pcr NUMBER", |
| + _("PCR to extend.")); |
| + |
| +} |
| + |
| +static char in_filename[PATH_MAX] = ""; |
| +static TSS_HPCRS hPcrs = NULL_HPCRS; |
| +static TSS_HTPM hTpm; |
| +static UINT32 selectedPcrs[24]; |
| +static UINT32 selectedPcrsLen = 0; |
| +TSS_HCONTEXT hContext = 0; |
| + |
| +static int parse(const int aOpt, const char *aArg) |
| +{ |
| + int rc = -1; |
| + |
| + switch (aOpt) { |
| + case 'i': |
| + if (aArg) { |
| + strncpy(in_filename, aArg, PATH_MAX); |
| + rc = 0; |
| + } |
| + break; |
| + case 'p': |
| + if (aArg) { |
| + selectedPcrs[selectedPcrsLen++] = atoi(aArg); |
| + rc = 0; |
| + } |
| + break; |
| + default: |
| + break; |
| + } |
| + return rc; |
| + |
| +} |
| + |
| +int main(int argc, char **argv) |
| +{ |
| + |
| + int iRc = -1; |
| + struct option opts[] = { |
| + {"infile", required_argument, NULL, 'i'}, |
| + {"pcr", required_argument, NULL, 'p'}, |
| + }; |
| + unsigned char line[EVP_MD_block_size(EVP_sha1()) * 16]; |
| + int lineLen; |
| + UINT32 i; |
| + |
| + BIO *bin = NULL; |
| + |
| + initIntlSys(); |
| + |
| + if (genericOptHandler(argc, argv, "i:p:", opts, |
| + sizeof(opts) / sizeof(struct option), parse, |
| + help) != 0) |
| + goto out; |
| + |
| + if (contextCreate(&hContext) != TSS_SUCCESS) |
| + goto out; |
| + |
| + if (contextConnect(hContext) != TSS_SUCCESS) |
| + goto out_close; |
| + |
| + if (contextGetTpm(hContext, &hTpm) != TSS_SUCCESS) |
| + goto out_close; |
| + |
| + /* Create a BIO for the input file */ |
| + if ((bin = BIO_new(BIO_s_file())) == NULL) { |
| + logError(_("Unable to open input BIO\n")); |
| + goto out_close; |
| + } |
| + |
| + /* Assign the input file to the BIO */ |
| + if (strlen(in_filename) == 0) |
| + BIO_set_fp(bin, stdin, BIO_NOCLOSE); |
| + else if (!BIO_read_filename(bin, in_filename)) { |
| + logError(_("Unable to open input file: %s\n"), |
| + in_filename); |
| + goto out_close; |
| + } |
| + |
| + /* Create the PCRs object. If any PCRs above 15 are selected, this will need to be |
| + * a 1.2 TSS/TPM */ |
| + if (selectedPcrsLen) { |
| + TSS_FLAG initFlag = 0; |
| + UINT32 pcrSize; |
| + BYTE *pcrValue; |
| + |
| + for (i = 0; i < selectedPcrsLen; i++) { |
| + if (selectedPcrs[i] > 15) { |
| +#ifdef TSS_LIB_IS_12 |
| + initFlag |= TSS_PCRS_STRUCT_INFO_LONG; |
| +#else |
| + logError(_("This version of %s was compiled for a v1.1 TSS, which " |
| + "can only seal\n data to PCRs 0-15. PCR %u is out of range" |
| + "\n"), argv[0], selectedPcrs[i]); |
| + goto out_close; |
| +#endif |
| + } |
| + } |
| + |
| + unsigned char msg[EVP_MAX_MD_SIZE]; |
| + unsigned int msglen; |
| + EVP_MD_CTX ctx; |
| + EVP_DigestInit(&ctx, EVP_sha1()); |
| + while ((lineLen = BIO_read(bin, line, sizeof(line))) > 0) |
| + EVP_DigestUpdate(&ctx, line, lineLen); |
| + EVP_DigestFinal(&ctx, msg, &msglen); |
| + |
| + if (contextCreateObject(hContext, TSS_OBJECT_TYPE_PCRS, initFlag, |
| + &hPcrs) != TSS_SUCCESS) |
| + goto out_close; |
| + |
| + for (i = 0; i < selectedPcrsLen; i++) { |
| +#ifdef TPM_EXTENDPCR_DEBUG |
| + if (tpmPcrRead(hTpm, selectedPcrs[i], &pcrSize, &pcrValue) != TSS_SUCCESS) |
| + goto out_close; |
| + |
| + unsigned int j; |
| + for (j = 0; j < pcrSize; j++) |
| + printf("%02X ", pcrValue[j]); |
| + printf("\n"); |
| +#endif |
| + |
| + if (tpmPcrExtend(hTpm, selectedPcrs[i], msglen, msg, NULL, &pcrSize, &pcrValue) != TSS_SUCCESS) |
| + goto out_close; |
| + |
| +#ifdef TPM_EXTENDPCR_DEBUG |
| + for (j = 0; j < pcrSize; j++) |
| + printf("%02X ", pcrValue[j]); |
| + printf("\n"); |
| +#endif |
| + } |
| + } |
| + |
| + iRc = 0; |
| + logSuccess(argv[0]); |
| + |
| +out_close: |
| + contextClose(hContext); |
| + |
| +out: |
| + if (bin) |
| + BIO_free(bin); |
| + return iRc; |
| +} |