Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP3:Update
tpm2.0-tools
eventlog-support-pseudo-files.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File eventlog-support-pseudo-files.patch of Package tpm2.0-tools
From 7e6985fcf5f56245b6c860a623f42b43a2a13bd2 Mon Sep 17 00:00:00 2001 From: Trammell hudson <hudson@trmm.net> Date: Wed, 10 Jun 2020 12:07:51 +0200 Subject: [PATCH 01/11] tpm2_openssl: add tpm2_openssl_pcr_extend() to hash a new digest into a PCR Signed-off-by: Trammell hudson <hudson@trmm.net> --- lib/tpm2_openssl.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++ lib/tpm2_openssl.h | 16 +++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/lib/tpm2_openssl.c b/lib/tpm2_openssl.c index 6d29c0d4..2fad25d4 100644 --- a/lib/tpm2_openssl.c +++ b/lib/tpm2_openssl.c @@ -171,6 +171,55 @@ out: return result; } +bool tpm2_openssl_pcr_extend(TPMI_ALG_HASH halg, BYTE *pcr, + const BYTE *data, UINT16 length) { + + bool result = false; + + const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(halg); + if (!md) { + return false; + } + + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + if (!mdctx) { + LOG_ERR("%s", tpm2_openssl_get_err()); + return false; + } + + int rc = EVP_DigestInit_ex(mdctx, md, NULL); + if (!rc) { + LOG_ERR("%s", tpm2_openssl_get_err()); + goto out; + } + + // extend operation is pcr = HASH(pcr + data) + unsigned size = EVP_MD_size(md); + rc = EVP_DigestUpdate(mdctx, pcr, size); + if (!rc) { + LOG_ERR("%s", tpm2_openssl_get_err()); + goto out; + } + + rc = EVP_DigestUpdate(mdctx, data, length); + if (!rc) { + LOG_ERR("%s", tpm2_openssl_get_err()); + goto out; + } + + rc = EVP_DigestFinal_ex(mdctx, pcr, &size); + if (!rc) { + LOG_ERR("%s", tpm2_openssl_get_err()); + goto out; + } + + result = true; + +out: + EVP_MD_CTX_destroy(mdctx); + return result; +} + bool tpm2_openssl_hash_pcr_values(TPMI_ALG_HASH halg, TPML_DIGEST *digests, TPM2B_DIGEST *digest) { diff --git a/lib/tpm2_openssl.h b/lib/tpm2_openssl.h index c78540c5..864fbff6 100644 --- a/lib/tpm2_openssl.h +++ b/lib/tpm2_openssl.h @@ -118,6 +118,22 @@ bool tpm2_openssl_hash_pcr_values(TPMI_ALG_HASH halg, TPML_DIGEST *digests, bool tpm2_openssl_hash_pcr_banks(TPMI_ALG_HASH hashAlg, TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs, TPM2B_DIGEST *digest); +/** + * Extend a PCR with a new digest. + * @param halg + * The hashing algorithm to use. + * @param pcr + * A buffer with the current value of the PCR, will be updated in place. + * @param data + * The new digest to be added to the current PCR. + * @param length + * Length of the new data to be added to the digest. + * @return + * true on success, false on error. + */ +bool tpm2_openssl_pcr_extend(TPMI_ALG_HASH halg, BYTE *pcr, + const BYTE *data, UINT16 length); + /** * Obtains an OpenSSL EVP_CIPHER_CTX dealing with version * API changes in OSSL. -- 2.35.1 From 8e5e1ea8095443db7c0e61586ee22d913916249c Mon Sep 17 00:00:00 2001 From: William Roberts <william.c.roberts@intel.com> Date: Sat, 23 May 2020 15:22:05 -0500 Subject: [PATCH 02/11] tpm2_createak: add qualified name output Add the qualified name output of the AK. The qualified name of an object is the name hash alg of the qualified name of the parent and the name of the object. Thus the qualified name serves as a hash of the loaded object chain from the hiearchy seed to the object. To quote the spec: The Qualified Name (QN) of an object is the digest of all of the Names of all of the ancestor keys back to the Primary Seed at the root of the hierarchy. The QN of an object includes the Name of the object. The QN uses the Name hash of the current object to compute the QN for the object. Signed-off-by: William Roberts <william.c.roberts@intel.com> --- doc/CHANGELOG.md | 2 ++ lib/tpm2_openssl.c | 28 ++++++++++------------ lib/tpm2_openssl.h | 4 ++++ lib/tpm2_util.c | 56 +++++++++++++++++++++++++++++++++++++++++++ lib/tpm2_util.h | 27 +++++++++++++++++++++ tools/tpm2_createak.c | 56 +++++++++++++++++++++++++++++++++---------- 6 files changed, 144 insertions(+), 29 deletions(-) diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index 9b22ef68..1fb4471e 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -37,6 +37,8 @@ * Fix for loop declarations build error. + * tpm2\_createak: add qualified name output as -q. + ### 4.2 2020-04-08 * Fix various issues reported by static analysis tools. diff --git a/lib/tpm2_openssl.c b/lib/tpm2_openssl.c index 2fad25d4..0565b7e3 100644 --- a/lib/tpm2_openssl.c +++ b/lib/tpm2_openssl.c @@ -123,10 +123,6 @@ int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) { #endif -static inline const char *get_openssl_err(void) { - return ERR_error_string(ERR_get_error(), NULL); -} - bool tpm2_openssl_hash_compute_data(TPMI_ALG_HASH halg, BYTE *buffer, UINT16 length, TPM2B_DIGEST *digest) { @@ -139,26 +135,26 @@ bool tpm2_openssl_hash_compute_data(TPMI_ALG_HASH halg, BYTE *buffer, EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); if (!mdctx) { - LOG_ERR("%s", get_openssl_err()); + LOG_ERR("%s", tpm2_openssl_get_err()); return false; } int rc = EVP_DigestInit_ex(mdctx, md, NULL); if (!rc) { - LOG_ERR("%s", get_openssl_err()); + LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } rc = EVP_DigestUpdate(mdctx, buffer, length); if (!rc) { - LOG_ERR("%s", get_openssl_err()); + LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } unsigned size = EVP_MD_size(md); rc = EVP_DigestFinal_ex(mdctx, digest->buffer, &size); if (!rc) { - LOG_ERR("%s", get_openssl_err()); + LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } @@ -232,13 +228,13 @@ bool tpm2_openssl_hash_pcr_values(TPMI_ALG_HASH halg, TPML_DIGEST *digests, EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); if (!mdctx) { - LOG_ERR("%s", get_openssl_err()); + LOG_ERR("%s", tpm2_openssl_get_err()); return false; } int rc = EVP_DigestInit_ex(mdctx, md, NULL); if (!rc) { - LOG_ERR("%s", get_openssl_err()); + LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } @@ -248,7 +244,7 @@ bool tpm2_openssl_hash_pcr_values(TPMI_ALG_HASH halg, TPML_DIGEST *digests, TPM2B_DIGEST *b = &digests->digests[i]; rc = EVP_DigestUpdate(mdctx, b->buffer, b->size); if (!rc) { - LOG_ERR("%s", get_openssl_err()); + LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } } @@ -257,7 +253,7 @@ bool tpm2_openssl_hash_pcr_values(TPMI_ALG_HASH halg, TPML_DIGEST *digests, rc = EVP_DigestFinal_ex(mdctx, digest->buffer, &size); if (!rc) { - LOG_ERR("%s", get_openssl_err()); + LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } @@ -284,13 +280,13 @@ bool tpm2_openssl_hash_pcr_banks(TPMI_ALG_HASH hash_alg, EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); if (!mdctx) { - LOG_ERR("%s", get_openssl_err()); + LOG_ERR("%s", tpm2_openssl_get_err()); return false; } int rc = EVP_DigestInit_ex(mdctx, md, NULL); if (!rc) { - LOG_ERR("%s", get_openssl_err()); + LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } @@ -315,7 +311,7 @@ bool tpm2_openssl_hash_pcr_banks(TPMI_ALG_HASH hash_alg, TPM2B_DIGEST *b = &pcrs->pcr_values[vi].digests[di]; rc = EVP_DigestUpdate(mdctx, b->buffer, b->size); if (!rc) { - LOG_ERR("%s", get_openssl_err()); + LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } @@ -334,7 +330,7 @@ bool tpm2_openssl_hash_pcr_banks(TPMI_ALG_HASH hash_alg, unsigned size = EVP_MD_size(md); rc = EVP_DigestFinal_ex(mdctx, digest->buffer, &size); if (!rc) { - LOG_ERR("%s", get_openssl_err()); + LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } diff --git a/lib/tpm2_openssl.h b/lib/tpm2_openssl.h index 864fbff6..3df2dc26 100644 --- a/lib/tpm2_openssl.h +++ b/lib/tpm2_openssl.h @@ -40,6 +40,10 @@ int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); typedef unsigned char *(*digester)(const unsigned char *d, size_t n, unsigned char *md); +static inline const char *tpm2_openssl_get_err(void) { + return ERR_error_string(ERR_get_error(), NULL); +} + /** * Get an openssl hash algorithm ID from a tpm hashing algorithm ID. * @param algorithm diff --git a/lib/tpm2_util.c b/lib/tpm2_util.c index 69c9811b..4aa9c173 100644 --- a/lib/tpm2_util.c +++ b/lib/tpm2_util.c @@ -987,3 +987,59 @@ void tpm2_util_print_time(const TPMS_TIME_INFO *current_time) { tpm2_tool_output(" safe: %s\n", current_time->clockInfo.safe ? "yes" : "no"); } + +bool tpm2_calq_qname(TPM2B_NAME *pqname, + TPMI_ALG_HASH halg, TPM2B_NAME *name, TPM2B_NAME *qname) { + + // QNB ≔ HB (QNA || NAMEB) + bool result = false; + + const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(halg); + + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + if (!mdctx) { + LOG_ERR("%s", tpm2_openssl_get_err()); + return false; + } + + int rc = EVP_DigestInit_ex(mdctx, md, NULL); + if (!rc) { + LOG_ERR("%s", tpm2_openssl_get_err()); + goto out; + } + + size_t offset = sizeof(halg); + rc = EVP_DigestUpdate(mdctx, pqname->name, pqname->size); + if (!rc) { + LOG_ERR("%s", tpm2_openssl_get_err()); + goto out; + } + + rc = EVP_DigestUpdate(mdctx, name->name, name->size); + if (!rc) { + LOG_ERR("%s", tpm2_openssl_get_err()); + goto out; + } + + unsigned size = EVP_MD_size(md); + rc = EVP_DigestFinal_ex(mdctx, &qname->name[offset], &size); + if (!rc) { + LOG_ERR("%s", tpm2_openssl_get_err()); + goto out; + } + + /* hash sizes are not bigger than 16 bits, safe truncate */ + qname->size = (UINT16)size; + + /* put the hash alg on the front, since name already has it in marshalled + * proper form just use it. + */ + memcpy(qname->name, name->name, offset); + qname->size += offset; + + result = true; + +out: + EVP_MD_CTX_destroy(mdctx); + return result; +} diff --git a/lib/tpm2_util.h b/lib/tpm2_util.h index 53a63bfe..914f4a88 100644 --- a/lib/tpm2_util.h +++ b/lib/tpm2_util.h @@ -463,4 +463,31 @@ bool tpm2_util_get_label(const char *value, TPM2B_DATA *label); */ void tpm2_util_print_time(const TPMS_TIME_INFO *current_time); +/** + * Given the parent qualified name and the name of an object, computes + * that objects qualified name. + * + * The qualified name is defined as: + * QNB ≔ HB (QNA || NAMEB) + * + * Where: + * - QNB is the qualified name of the object. + * - HB is the name hash algorithm of the object. + * - QNA is the qualified name of the parent object. + * - NAMEB is the name of the object. + * + * @param pqname + * The parent qualified name. + * @param halg + * The name hash algorithm of the object. + * @param name + * The name of the object. + * @param qname + * The output qname, valid on success. + * @return + * True on success, false otherwise. + */ +bool tpm2_calq_qname(TPM2B_NAME *pqname, + TPMI_ALG_HASH halg, TPM2B_NAME *name, TPM2B_NAME *qname); + #endif /* STRING_BYTES_H */ diff --git a/tools/tpm2_createak.c b/tools/tpm2_createak.c index e450e9c3..b46e70f9 100644 --- a/tools/tpm2_createak.c +++ b/tools/tpm2_createak.c @@ -34,6 +34,7 @@ struct createak_context { const char *pub_file; const char *name_file; const char *priv_file; + const char *qname_file; } out; char *auth_str; } ak; @@ -235,9 +236,10 @@ static tool_rc create_ak(ESYS_CONTEXT *ectx) { LOG_INFO("Esys_PolicySecret success"); + TPM2B_CREATION_DATA *creation_data = NULL; rval = Esys_Create(ectx, ctx.ek.ek_ctx.tr_handle, sess_handle, ESYS_TR_NONE, ESYS_TR_NONE, &ctx.ak.in.in_sensitive, &in_public, &outside_info, - &creation_pcr, &out_private, &out_public, NULL, NULL, NULL); + &creation_pcr, &out_private, &out_public, &creation_data, NULL, NULL); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_Create, rval); goto out; @@ -304,10 +306,23 @@ static tool_rc create_ak(ESYS_CONTEXT *ectx) { goto out; } + /* generation qualified name */ + TPM2B_NAME *p_qname = &creation_data->creationData.parentQualifiedName; + TPM2B_NAME qname = { 0 }; + rc = tpm2_calq_qname(p_qname, + in_public.publicArea.nameAlg, key_name, &qname) ? + tool_rc_success : tool_rc_general_error; + if (rc != tool_rc_success) { + goto out; + } + /* Output in YAML format */ tpm2_tool_output("loaded-key:\n name: "); tpm2_util_print_tpm2b(key_name); tpm2_tool_output("\n"); + tpm2_tool_output(" qualified name: "); + tpm2_util_print_tpm2b(&qname); + tpm2_tool_output("\n"); // write name to ak.name file if (ctx.ak.out.name_file) { @@ -320,6 +335,16 @@ static tool_rc create_ak(ESYS_CONTEXT *ectx) { } } + if (ctx.ak.out.qname_file) { + result = files_save_bytes_to_file(ctx.ak.out.qname_file, qname.name, + qname.size); + if (!result) { + LOG_ERR("Failed to save AK qualified name into file \"%s\"", + ctx.ak.out.name_file); + goto nameout; + } + } + // If the AK isn't persisted we always save a context file of the // transient AK handle for future tool interactions. tmp_rc = files_save_tpm_context_to_path(ectx, loaded_sha1_key_handle, @@ -352,6 +377,7 @@ nameout: out: free(out_public); free(out_private); + Esys_Free(creation_data); out_session: tpm2_session_close(&session); @@ -413,6 +439,9 @@ static bool on_option(char key, char *value) { case 'r': ctx.ak.out.priv_file = value; break; + case 'q': + ctx.ak.out.qname_file = value; + break; } return true; @@ -421,20 +450,21 @@ static bool on_option(char key, char *value) { bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { - { "eh-auth", required_argument, NULL, 'P' }, - { "ak-auth", required_argument, NULL, 'p' }, - { "ek-context", required_argument, NULL, 'C' }, - { "ak-context", required_argument, NULL, 'c' }, - { "ak-name", required_argument, NULL, 'n' }, - { "key-algorithm", required_argument, NULL, 'G' }, - { "hash-algorithm", required_argument, NULL, 'g' }, - { "signing-algorithm",required_argument, NULL, 's' }, - { "format", required_argument, NULL, 'f' }, - { "public", required_argument, NULL, 'u' }, - { "private", required_argument, NULL, 'r'}, + { "eh-auth", required_argument, NULL, 'P' }, + { "ak-auth", required_argument, NULL, 'p' }, + { "ek-context", required_argument, NULL, 'C' }, + { "ak-context", required_argument, NULL, 'c' }, + { "ak-name", required_argument, NULL, 'n' }, + { "key-algorithm", required_argument, NULL, 'G' }, + { "hash-algorithm", required_argument, NULL, 'g' }, + { "signing-algorithm", required_argument, NULL, 's' }, + { "format", required_argument, NULL, 'f' }, + { "public", required_argument, NULL, 'u' }, + { "private", required_argument, NULL, 'r' }, + { "ak-qualified-name", required_argument, NULL, 'q' }, }; - *opts = tpm2_options_new("P:p:C:c:n:G:g:s:f:u:r:", ARRAY_LEN(topts), topts, + *opts = tpm2_options_new("P:p:C:c:n:G:g:s:f:u:r:q:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; -- 2.35.1 From c6d1ead5f7e164f5f7b6a8bc15a097403852311b Mon Sep 17 00:00:00 2001 From: Jonas Witschel <diabonas@gmx.de> Date: Thu, 16 Apr 2020 16:50:53 +0200 Subject: [PATCH 03/11] tools/misc/tpm2_eventlog: don't rely on the reported file size When using tpm2_eventlog directly on the sysfs file /sys/kernel/security/tpm0/binary_bios_measurements, an empty buffer is allocated because its file size is reported as 0. As we cannot know the correct buffer size in advance, allocate a buffer for the maximum amount of data and use the ability of file_read_bytes_from_file from the previous commit to determine the correct buffer size from a full file read. Fixes: GH-1975 Signed-off-by: Jonas Witschel <diabonas@gmx.de> --- tools/misc/tpm2_eventlog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/misc/tpm2_eventlog.c b/tools/misc/tpm2_eventlog.c index 565ddbfb..e56ca512 100644 --- a/tools/misc/tpm2_eventlog.c +++ b/tools/misc/tpm2_eventlog.c @@ -53,7 +53,8 @@ tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { return tool_rc_general_error; } - eventlog = calloc(1, size); + UINT16 size_tmp = UINT16_MAX; + eventlog = calloc(1, size_tmp); if (eventlog == NULL){ LOG_ERR("failed to allocate %lu bytes: %s", size, strerror(errno)); return tool_rc_general_error; @@ -63,7 +64,6 @@ tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { LOG_WARN("event log exceeds %" PRIu16 " and will be truncated", UINT16_MAX); } - UINT16 size_tmp = size; ret = files_load_bytes_from_path(filename, eventlog, &size_tmp); if (!ret) { free(eventlog); -- 2.35.1 From 6dacbb306c1b13d2447420e0ddc44cdefc6dd371 Mon Sep 17 00:00:00 2001 From: Imran Desai <imran.desai@intel.com> Date: Mon, 19 Oct 2020 12:51:20 -0700 Subject: [PATCH 04/11] tpm2_eventlog.c: Restructuring to keep it in line with coding guidelines Signed-off-by: Imran Desai <imran.desai@intel.com> --- tools/misc/tpm2_eventlog.c | 39 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/tools/misc/tpm2_eventlog.c b/tools/misc/tpm2_eventlog.c index e56ca512..c97279ec 100644 --- a/tools/misc/tpm2_eventlog.c +++ b/tools/misc/tpm2_eventlog.c @@ -40,43 +40,46 @@ tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); UNUSED(ectx); - bool ret = false; - UINT8 *eventlog; - unsigned long size = 0; - if (filename == NULL) { LOG_ERR("Missing required positional parameter, try -h / --help"); return tool_rc_option_error; } - ret = files_get_file_size_path(filename, &size); + + unsigned long size = 0; + bool ret = files_get_file_size_path(filename, &size); if (!ret) { return tool_rc_general_error; } + if (size > UINT16_MAX) { + LOG_WARN("event log exceeds %" PRIu16 " and will be truncated", + UINT16_MAX); + } + UINT16 size_tmp = UINT16_MAX; - eventlog = calloc(1, size_tmp); + UINT8 *eventlog = calloc(1, size_tmp); if (eventlog == NULL){ LOG_ERR("failed to allocate %lu bytes: %s", size, strerror(errno)); return tool_rc_general_error; } - if (size > UINT16_MAX) { - LOG_WARN("event log exceeds %" PRIu16 " and will be truncated", - UINT16_MAX); - } + tool_rc rc = tool_rc_success; ret = files_load_bytes_from_path(filename, eventlog, &size_tmp); if (!ret) { - free(eventlog); - return tool_rc_general_error; + rc = tool_rc_general_error; + goto out; } ret = yaml_eventlog(eventlog, size_tmp); - if (eventlog) - free(eventlog); - if (ret) { - return tool_rc_success; - } else { + if (!ret) { LOG_ERR("failed to parse tpm2 eventlog"); - return tool_rc_general_error; + rc = tool_rc_general_error; } + +out: + if (eventlog) { + free(eventlog); + } + + return rc; } -- 2.35.1 From a7eb3be12b5318887ce90b4adfbe7027bdd8bbc8 Mon Sep 17 00:00:00 2001 From: Imran Desai <imran.desai@intel.com> Date: Mon, 5 Apr 2021 13:31:14 -0700 Subject: [PATCH 05/11] tpm2_eventlog: Support logs longer than 64KB Fixes #2243 Signed-off-by: Imran Desai <imran.desai@intel.com> --- tools/misc/tpm2_eventlog.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tools/misc/tpm2_eventlog.c b/tools/misc/tpm2_eventlog.c index c97279ec..8f592916 100644 --- a/tools/misc/tpm2_eventlog.c +++ b/tools/misc/tpm2_eventlog.c @@ -45,32 +45,36 @@ tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { return tool_rc_option_error; } + /* Get file size */ unsigned long size = 0; bool ret = files_get_file_size_path(filename, &size); - if (!ret) { + if (!ret || !size) { return tool_rc_general_error; } - if (size > UINT16_MAX) { - LOG_WARN("event log exceeds %" PRIu16 " and will be truncated", - UINT16_MAX); - } - - UINT16 size_tmp = UINT16_MAX; - UINT8 *eventlog = calloc(1, size_tmp); + /* Allocate buffer to read file data */ + UINT8 *eventlog = calloc(1, size); if (eventlog == NULL){ LOG_ERR("failed to allocate %lu bytes: %s", size, strerror(errno)); return tool_rc_general_error; } + /* Load buffer with file data */ tool_rc rc = tool_rc_success; - ret = files_load_bytes_from_path(filename, eventlog, &size_tmp); + FILE *fileptr = fopen(filename, "rb"); + if (!fileptr) { + rc = tool_rc_general_error; + goto out; + } + + ret = files_read_bytes(fileptr, eventlog, size); if (!ret) { rc = tool_rc_general_error; goto out; } - ret = yaml_eventlog(eventlog, size_tmp); + /* Parse eventlog data */ + ret = yaml_eventlog(eventlog, size); if (!ret) { LOG_ERR("failed to parse tpm2 eventlog"); rc = tool_rc_general_error; -- 2.35.1 From 11d867a3a9c6cef455a85767586898bcfa590789 Mon Sep 17 00:00:00 2001 From: Imran Desai <imran.desai@intel.com> Date: Tue, 6 Apr 2021 08:28:03 -0700 Subject: [PATCH 06/11] tpm2_eventlog: Flush the eventlog stream data pointed by the fileptr. Signed-off-by: Imran Desai <imran.desai@intel.com> --- tools/misc/tpm2_eventlog.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/misc/tpm2_eventlog.c b/tools/misc/tpm2_eventlog.c index 8f592916..e9c9cf09 100644 --- a/tools/misc/tpm2_eventlog.c +++ b/tools/misc/tpm2_eventlog.c @@ -68,6 +68,7 @@ tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { } ret = files_read_bytes(fileptr, eventlog, size); + fclose(fileptr); if (!ret) { rc = tool_rc_general_error; goto out; -- 2.35.1 From 0d773f100c3e6b843a2d8155ccef7852d3d658e3 Mon Sep 17 00:00:00 2001 From: Alberto Planas <aplanas@suse.com> Date: Fri, 18 Jun 2021 15:54:22 +0200 Subject: [PATCH 07/11] tpm2_eventlog: read eventlog file in chunks The eventlog file lives is securityfs, that do not return the file size. The current implementation first try to do a "fseek(fp, 0, SEEK_END)" for this file, and this will always return 0. This generate an error, and tpm2_eventlog exit with: ERROR: Unable to run tpm2_eventlog This patch replace the reading logic, now reading in chunks of 16KB and reallocating the buffer if needed. Also introduces a new function in files.c ("files_read_bytes_chunk") that helps counting the total read size, that now is different from the ammount of allocated memory. Fixes #2775 Signed-off-by: Alberto Planas <aplanas@suse.com> --- lib/files.c | 9 ++++++++ lib/files.h | 15 +++++++++++++ tools/misc/tpm2_eventlog.c | 44 ++++++++++++++++++++------------------ 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/lib/files.c b/lib/files.c index 501f88d1..c0921636 100644 --- a/lib/files.c +++ b/lib/files.c @@ -568,6 +568,15 @@ bool files_read_bytes(FILE *out, UINT8 bytes[], size_t len) { return readx(out, bytes, len); } +bool files_read_bytes_chunk(FILE *out, UINT8 bytes[], size_t len, size_t *read_len) { + + BAIL_ON_NULL("FILE", out); + BAIL_ON_NULL("bytes", bytes); + size_t chunk_len = readx(out, bytes, len); + *read_len += chunk_len; + return (chunk_len == len); +} + bool files_write_bytes(FILE *out, uint8_t bytes[], size_t len) { BAIL_ON_NULL("FILE", out); diff --git a/lib/files.h b/lib/files.h index 97c93729..44f01fbe 100644 --- a/lib/files.h +++ b/lib/files.h @@ -481,6 +481,21 @@ bool files_read_64(FILE *out, UINT64 *data); */ bool files_read_bytes(FILE *out, UINT8 data[], size_t size); +/** + * Reads len bytes from a file and set the read length. + * @param out + * The file to read from. + * @param data + * The buffer to read into, only valid on a True return. + * @param size + * The number of bytes to read. + * @param read_size + * Total number of bytes read. + * @return + * True on success, False otherwise. + */ +bool files_read_bytes_chunk(FILE *out, UINT8 data[], size_t size, size_t *read_size); + /** * Converts a TPM2B_ATTEST to a TPMS_ATTEST using libmu. * @param quoted diff --git a/tools/misc/tpm2_eventlog.c b/tools/misc/tpm2_eventlog.c index e9c9cf09..f68ab859 100644 --- a/tools/misc/tpm2_eventlog.c +++ b/tools/misc/tpm2_eventlog.c @@ -12,6 +12,8 @@ #include "tpm2_eventlog_yaml.h" #include "tpm2_tool.h" +#define CHUNK_SIZE 16384 + static char *filename = NULL; static bool on_positional(int argc, char **argv) { @@ -45,37 +47,37 @@ tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { return tool_rc_option_error; } - /* Get file size */ - unsigned long size = 0; - bool ret = files_get_file_size_path(filename, &size); - if (!ret || !size) { + /* Read the file in chunks. Usually the file will reside in + securityfs, and those files do not have a public file size */ + tool_rc rc = tool_rc_success; + FILE *fileptr = fopen(filename, "rb"); + if (!fileptr) { return tool_rc_general_error; } - /* Allocate buffer to read file data */ - UINT8 *eventlog = calloc(1, size); + /* Reserve the buffer for the first chunk */ + UINT8 *eventlog = calloc(1, CHUNK_SIZE); if (eventlog == NULL){ - LOG_ERR("failed to allocate %lu bytes: %s", size, strerror(errno)); + LOG_ERR("failed to allocate %d bytes: %s", CHUNK_SIZE, strerror(errno)); return tool_rc_general_error; } - /* Load buffer with file data */ - tool_rc rc = tool_rc_success; - FILE *fileptr = fopen(filename, "rb"); - if (!fileptr) { - rc = tool_rc_general_error; - goto out; - } - - ret = files_read_bytes(fileptr, eventlog, size); + unsigned long size = 0; + bool is_file_read = false; + do { + is_file_read = files_read_bytes_chunk(fileptr, eventlog, CHUNK_SIZE, &size); + UINT8 *eventlog_tmp = realloc(eventlog, size + CHUNK_SIZE); + if (!eventlog_tmp){ + LOG_ERR("failed to allocate %lu bytes: %s", size + CHUNK_SIZE, strerror(errno)); + rc = tool_rc_general_error; + goto out; + } + eventlog = eventlog_tmp; + } while (is_file_read); fclose(fileptr); - if (!ret) { - rc = tool_rc_general_error; - goto out; - } /* Parse eventlog data */ - ret = yaml_eventlog(eventlog, size); + bool ret = yaml_eventlog(eventlog, size); if (!ret) { LOG_ERR("failed to parse tpm2 eventlog"); rc = tool_rc_general_error; -- 2.35.1 From 3d8457c11c8214bb3fa9a89b9baf1cc51bf5b8e5 Mon Sep 17 00:00:00 2001 From: Alberto Planas <aplanas@suse.com> Date: Thu, 29 Jul 2021 16:02:50 +0200 Subject: [PATCH 08/11] tpm2_eventlog: fix buffer offset when reading the event log The event log is read in chunks of CHUNK_SIZE blocks (16KB), always checking when the EOF is reached, so it is compatible with virtual files that lives in securityfs and we do not know the full size. The current code is not taking care of adjusting the offset when the next chunk is read. This patch add "size" to the base buffer where the event log is stored in memory. Fix #2778 Signed-off-by: Alberto Planas <aplanas@suse.com> --- tools/misc/tpm2_eventlog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/misc/tpm2_eventlog.c b/tools/misc/tpm2_eventlog.c index f68ab859..ffaf4c28 100644 --- a/tools/misc/tpm2_eventlog.c +++ b/tools/misc/tpm2_eventlog.c @@ -65,7 +65,7 @@ tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { unsigned long size = 0; bool is_file_read = false; do { - is_file_read = files_read_bytes_chunk(fileptr, eventlog, CHUNK_SIZE, &size); + is_file_read = files_read_bytes_chunk(fileptr, eventlog + size, CHUNK_SIZE, &size); UINT8 *eventlog_tmp = realloc(eventlog, size + CHUNK_SIZE); if (!eventlog_tmp){ LOG_ERR("failed to allocate %lu bytes: %s", size + CHUNK_SIZE, strerror(errno)); -- 2.35.1 From 75a0e240e9c15e939bb933a9233e3b1c5e3f3353 Mon Sep 17 00:00:00 2001 From: Jonas Witschel <diabonas@gmx.de> Date: Thu, 16 Apr 2020 16:42:19 +0200 Subject: [PATCH 09/11] lib/files: don't rely on the reported size in file_read_bytes_from_file The reported file size is not always correct, e.g. for sysfs files generated on the fly by the kernel when they are read, which appear as having size 0. Read as many bytes as we can until EOF is reached or the provided buffer is full. As a small sanity check, fail if the number of bytes read is smaller than the reported file size. This change leads to a problem with the current approach to wrapping fread in test_tpm2_auth_util: it unconditionally memcpy's the requested number of bytes regardless of whether there is actually enough mocked_file_data for that. This leads to a test failure when memory sanitation is enabled. Make sure not to copy unitialised memory by using strncpy instead of memcpy. Signed-off-by: Jonas Witschel <diabonas@gmx.de> --- lib/files.c | 126 +++++++++++++++++++++++++--------------------------- 1 file changed, 60 insertions(+), 66 deletions(-) diff --git a/lib/files.c b/lib/files.c index c0921636..62ff4989 100644 --- a/lib/files.c +++ b/lib/files.c @@ -33,6 +33,57 @@ static const UINT32 MAGIC = 0xBADCC0DE; } \ } while(0) +/** + * Writes size bytes to a file, continuing on EINTR short writes. + * @param f + * The file to write to. + * @param data + * The data to write. + * @param size + * The size, in bytes, of that data. + * @return + * True on success, False otherwise. + */ +static bool writex(FILE *f, UINT8 *data, size_t size) { + + size_t wrote = 0; + size_t index = 0; + do { + wrote = fwrite(&data[index], 1, size, f); + if (wrote != size) { + if (errno != EINTR) { + return false; + } + /* continue on EINTR */ + } + size -= wrote; + index += wrote; + } while (size > 0); + + return true; +} + +/** + * Reads size bytes from a file, continuing on EINTR short reads. + * @param f + * The file to read from. + * @param data + * The data buffer to read into. + * @param size + * The size of the buffer, which is also the amount of bytes to read. + * @return + * The number of bytes that have been read. + */ +static size_t readx(FILE *f, UINT8 *data, size_t size) { + + size_t bread = 0; + do { + bread += fread(&data[bread], 1, size-bread, f); + } while (bread < size && !feof(f) && errno == EINTR); + + return bread; +} + bool files_get_file_size(FILE *fp, unsigned long *file_size, const char *path) { long current = ftell(fp); @@ -95,16 +146,19 @@ bool file_read_bytes_from_file(FILE *f, UINT8 *buf, UINT16 *size, return false; } - result = files_read_bytes(f, buf, file_size); - if (!result) { + /* The reported file size is not always correct, e.g. for sysfs files + generated on the fly by the kernel when they are read, which appear as + having size 0. Read as many bytes as we can until EOF is reached or the + provided buffer is full. As a small sanity check, fail if the number of + bytes read is smaller than the reported file size. */ + *size = readx(f, buf, *size); + if (*size < file_size) { if (path) { LOG_ERR("Could not read data from file \"%s\"", path); } return false; } - *size = file_size; - return true; } @@ -464,66 +518,6 @@ bool files_get_file_size_path(const char *path, unsigned long *file_size) { return result; } -/** - * Writes size bytes to a file, continuing on EINTR short writes. - * @param f - * The file to write to. - * @param data - * The data to write. - * @param size - * The size, in bytes, of that data. - * @return - * True on success, False otherwise. - */ -static bool writex(FILE *f, UINT8 *data, size_t size) { - - size_t wrote = 0; - size_t index = 0; - do { - wrote = fwrite(&data[index], 1, size, f); - if (wrote != size) { - if (errno != EINTR) { - return false; - } - /* continue on EINTR */ - } - size -= wrote; - index += wrote; - } while (size > 0); - - return true; -} - -/** - * Reads size bytes from a file, continuing on EINTR short reads. - * @param f - * The file to read from. - * @param data - * The data buffer to read into. - * @param size - * The size of the buffer, which is also the amount of bytes to read. - * @return - * True on success, False otherwise. - */ -static bool readx(FILE *f, UINT8 *data, size_t size) { - - size_t bread = 0; - size_t index = 0; - do { - bread = fread(&data[index], 1, size, f); - if (bread != size) { - if (feof(f) || (errno != EINTR)) { - return false; - } - /* continue on EINTR */ - } - size -= bread; - index += bread; - } while (size > 0); - - return true; -} - #define BE_CONVERT(value, size) \ do { \ if (!tpm2_util_is_big_endian()) { \ @@ -542,7 +536,7 @@ static bool readx(FILE *f, UINT8 *data, size_t size) { bool files_read_##size(FILE *out, UINT##size *data) { \ BAIL_ON_NULL("FILE", out); \ BAIL_ON_NULL("data", data); \ - bool res = readx(out, (UINT8 *)data, sizeof(*data)); \ + bool res = (readx(out, (UINT8 *)data, sizeof(*data)) == sizeof(*data)); \ if (res) { \ BE_CONVERT(*data, size); \ } \ @@ -565,7 +559,7 @@ bool files_read_bytes(FILE *out, UINT8 bytes[], size_t len) { BAIL_ON_NULL("FILE", out); BAIL_ON_NULL("bytes", bytes); - return readx(out, bytes, len); + return (readx(out, bytes, len) == len); } bool files_read_bytes_chunk(FILE *out, UINT8 bytes[], size_t len, size_t *read_len) { -- 2.35.1 From 316a7f9607b2cabad78561867e1be1c139cd0b34 Mon Sep 17 00:00:00 2001 From: Imran Desai <imran.desai@intel.com> Date: Wed, 1 Sep 2021 13:29:17 -0700 Subject: [PATCH 10/11] tools/tpm2_eventlog.c: Fix resource leak when exiting with error Signed-off-by: Imran Desai <imran.desai@intel.com> --- tools/misc/tpm2_eventlog.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/misc/tpm2_eventlog.c b/tools/misc/tpm2_eventlog.c index ffaf4c28..8bdb3462 100644 --- a/tools/misc/tpm2_eventlog.c +++ b/tools/misc/tpm2_eventlog.c @@ -49,17 +49,18 @@ tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { /* Read the file in chunks. Usually the file will reside in securityfs, and those files do not have a public file size */ - tool_rc rc = tool_rc_success; FILE *fileptr = fopen(filename, "rb"); if (!fileptr) { return tool_rc_general_error; } /* Reserve the buffer for the first chunk */ + tool_rc rc = tool_rc_success; UINT8 *eventlog = calloc(1, CHUNK_SIZE); if (eventlog == NULL){ LOG_ERR("failed to allocate %d bytes: %s", CHUNK_SIZE, strerror(errno)); - return tool_rc_general_error; + rc = tool_rc_general_error; + goto out; } unsigned long size = 0; @@ -74,7 +75,6 @@ tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { } eventlog = eventlog_tmp; } while (is_file_read); - fclose(fileptr); /* Parse eventlog data */ bool ret = yaml_eventlog(eventlog, size); @@ -84,6 +84,10 @@ tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { } out: + if (fileptr) { + fclose(fileptr); + } + if (eventlog) { free(eventlog); } -- 2.35.1 From 14e2cb01a8d2aec9eda517264482b1e78a8b55f2 Mon Sep 17 00:00:00 2001 From: Claudia Meitinger <laicuda@gmx.net> Date: Thu, 22 Jul 2021 13:32:36 +0100 Subject: [PATCH 11/11] misc/tpm2_eventlog.c: fix build error on Raspberry Pi Signed-off-by: Claudia Meitinger <laicuda@gmx.net> --- tools/misc/tpm2_eventlog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/misc/tpm2_eventlog.c b/tools/misc/tpm2_eventlog.c index 8bdb3462..30ea928b 100644 --- a/tools/misc/tpm2_eventlog.c +++ b/tools/misc/tpm2_eventlog.c @@ -63,13 +63,13 @@ tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { goto out; } - unsigned long size = 0; + size_t size = 0; bool is_file_read = false; do { is_file_read = files_read_bytes_chunk(fileptr, eventlog + size, CHUNK_SIZE, &size); UINT8 *eventlog_tmp = realloc(eventlog, size + CHUNK_SIZE); if (!eventlog_tmp){ - LOG_ERR("failed to allocate %lu bytes: %s", size + CHUNK_SIZE, strerror(errno)); + LOG_ERR("failed to allocate %zu bytes: %s", size + CHUNK_SIZE, strerror(errno)); rc = tool_rc_general_error; goto out; } -- 2.35.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor