1 //**********************************************************************;
2 // Copyright (c) 2017, Intel Corporation
3 // All rights reserved.
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
8 // 1. Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
11 // 2. Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
15 // 3. Neither the name of Intel Corporation nor the names of its contributors
16 // may be used to endorse or promote products derived from this software without
17 // specific prior written permission.
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29 // THE POSSIBILITY OF SUCH DAMAGE.
30 //**********************************************************************;
34 #include <tss2/tss2_sys.h>
38 #include "tpm2_hash.h"
39 #include "tpm2_util.h"
41 bool tpm2_hash_compute_data(TSS2_SYS_CONTEXT *sapi_context, TPMI_ALG_HASH halg,
42 TPMI_RH_HIERARCHY hierarchy, BYTE *buffer, UINT16 length,
43 TPM2B_DIGEST *result, TPMT_TK_HASHCHECK *validation) {
45 FILE *mem = fmemopen(buffer, length, "rb");
47 LOG_ERR("Error converting buffer to memory stream: %s",
52 return tpm2_hash_file(sapi_context, halg, hierarchy, mem, result, validation);
55 bool tpm2_hash_file(TSS2_SYS_CONTEXT *sapi_context, TPMI_ALG_HASH halg,
56 TPMI_RH_HIERARCHY hierarchy, FILE *input, TPM2B_DIGEST *result,
57 TPMT_TK_HASHCHECK *validation) {
59 TPM2B_AUTH nullAuth = TPM2B_EMPTY_INIT;
60 TPMI_DH_OBJECT sequenceHandle;
62 TSS2L_SYS_AUTH_COMMAND cmdAuthArray = { 1, {{.sessionHandle = TPM2_RS_PW,
63 .nonce = TPM2B_EMPTY_INIT, .hmac = TPM2B_EMPTY_INIT,
64 .sessionAttributes = 0, }}};
65 unsigned long file_size = 0;
67 /* Suppress error reporting with NULL path */
68 bool res = files_get_file_size(input, &file_size, NULL);
70 /* If we can get the file size and its less than 1024, just do it in one hash invocation */
71 if (res && file_size <= TPM2_MAX_DIGEST_BUFFER) {
73 TPM2B_MAX_BUFFER buffer = { .size = file_size };
75 res = files_read_bytes(input, buffer.buffer, buffer.size);
77 LOG_ERR("Error reading input file!");
81 TSS2_RC rval = TSS2_RETRY_EXP(Tss2_Sys_Hash(sapi_context, NULL, &buffer, halg,
82 hierarchy, result, validation, NULL));
83 if (rval != TSS2_RC_SUCCESS) {
84 LOG_PERR(Tss2_Sys_Hash, rval);
92 * Size is either unkown because the FILE * is a fifo, or it's too big
93 * to do in a single hash call. Based on the size figure out the chunks
94 * to loop over, if possible. This way we can call Complete with data.
96 TSS2_RC rval = TSS2_RETRY_EXP(Tss2_Sys_HashSequenceStart(sapi_context, NULL, &nullAuth,
97 halg, &sequenceHandle, NULL));
98 if (rval != TPM2_RC_SUCCESS) {
99 LOG_PERR(Tss2_Sys_HashSequenceStart, rval);
103 /* If we know the file size, we decrement the amount read and terminate the loop
104 * when 1 block is left, else we go till feof.
106 size_t left = file_size;
107 bool use_left = !!res;
109 TPM2B_MAX_BUFFER data;
114 size_t bytes_read = fread(data.buffer, 1,
115 BUFFER_SIZE(typeof(data), buffer), input);
117 LOG_ERR("Error reading from input file");
121 data.size = bytes_read;
123 /* if data was read, update the sequence */
124 rval = TSS2_RETRY_EXP(Tss2_Sys_SequenceUpdate(sapi_context, sequenceHandle,
125 &cmdAuthArray, &data, NULL));
126 if (rval != TPM2_RC_SUCCESS) {
127 LOG_PERR(Tss2_Sys_SequenceUpdate, rval);
133 if (left <= TPM2_MAX_DIGEST_BUFFER) {
137 } else if (feof(input)) {
140 } /* end file read/hash update loop */
144 bool res = files_read_bytes(input, data.buffer, left);
146 LOG_ERR("Error reading from input file.");
153 rval = TSS2_RETRY_EXP(Tss2_Sys_SequenceComplete(sapi_context, sequenceHandle,
154 &cmdAuthArray, &data, hierarchy, result, validation,
156 if (rval != TSS2_RC_SUCCESS) {
157 LOG_PERR(Tss2_Sys_SequenceComplete, rval);