linux-integrity.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] ima-evm-utils: original "ima" template support
@ 2020-07-07  2:27 Mimi Zohar
  2020-07-07  2:27 ` [PATCH 1/3] ima-evm-utils: support the original "ima" template Mimi Zohar
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Mimi Zohar @ 2020-07-07  2:27 UTC (permalink / raw)
  To: linux-integrity; +Cc: Mimi Zohar, Petr Vorel, Bruno Meneguele

The IMA LTP and standalone tests supported verifying the the original
"ima" template format against the TPM PCRs, as well as verifying the 
"boot_aggregate" based on walking the TPM 1.2 event log and calculating
the TPM PCRs values.

Add this support to ima-evm-utils.

(Dependency on the misc-fixes patch set.)

Mimi

Mimi Zohar (3):
  ima-evm-utils: support the original "ima" template
  ima-evm-utils: read the TPM 1.2 binary_bios_measurements
  ima-evm-utils: mixed "ima" and other template formats not supported

 src/evmctl.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 168 insertions(+), 18 deletions(-)

-- 
2.7.5


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] ima-evm-utils: support the original "ima" template
  2020-07-07  2:27 [PATCH 0/3] ima-evm-utils: original "ima" template support Mimi Zohar
@ 2020-07-07  2:27 ` Mimi Zohar
  2020-07-07  2:27 ` [PATCH 2/3] ima-evm-utils: read the TPM 1.2 binary_bios_measurements Mimi Zohar
  2020-07-07  2:27 ` [PATCH 3/3] ima-evm-utils: mixed "ima" and other template formats not supported Mimi Zohar
  2 siblings, 0 replies; 4+ messages in thread
From: Mimi Zohar @ 2020-07-07  2:27 UTC (permalink / raw)
  To: linux-integrity; +Cc: Mimi Zohar, Petr Vorel, Bruno Meneguele

The original "ima" template digest included just a SHA1 file data hash
and a fixed 255 character pathname in the hash calculation.  Two main
differences exist between the "ima" template and other template formats.
The other template data formats are prefixed with the template data
length and each field is prefixed with the field length,

These differences simplify verifying the other template formats against
the TPM PCRs without necessarily understanding each and every template
field.

Support for the original "ima" templat formate is based on the original
LTP and IMA standalone versions.

Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
---
 src/evmctl.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 66 insertions(+), 13 deletions(-)

diff --git a/src/evmctl.c b/src/evmctl.c
index 9162de2a5aeb..b157c452839b 100644
--- a/src/evmctl.c
+++ b/src/evmctl.c
@@ -1424,18 +1424,22 @@ static int ima_verify_template_hash(struct template_entry *entry)
 
 	SHA1(entry->template, entry->template_len, digest);
 
-	if (memcmp(digest, entry->header.digest, sizeof(digest))) {
-		log_err("template hash error\n");
+	if (memcmp(digest, entry->header.digest, sizeof(digest)))
 		return 1;
-	}
 
 	return 0;
 }
 
 void ima_show(struct template_entry *entry)
 {
-	log_debug("ima, digest: ");
-	log_debug_dump(entry->header.digest, sizeof(entry->header.digest));
+	if (imaevm_params.verbose <= LOG_INFO)
+		return;
+
+	log_info("%d ", entry->header.pcr);
+	log_dump_n(entry->header.digest, sizeof(entry->header.digest));
+	log_info(" %s ", entry->name);
+	log_dump_n(entry->template, SHA_DIGEST_LENGTH);
+	log_info(" %s\n", entry->template + SHA_DIGEST_LENGTH);
 }
 
 /*
@@ -1826,6 +1830,7 @@ static int ima_measurement(const char *file)
 {
 	struct tpm_bank_info *pseudo_banks;
 	struct tpm_bank_info *tpm_banks;
+	int is_ima_template;
 	int num_banks = 0;
 
 	struct template_entry entry = { .template = 0 };
@@ -1851,16 +1856,31 @@ static int ima_measurement(const char *file)
 		init_public_keys("/etc/keys/x509_evm.der");
 
 	while (fread(&entry.header, sizeof(entry.header), 1, fp)) {
+		if (entry.header.name_len > TCG_EVENT_NAME_LEN_MAX) {
+			log_err("%d ERROR: event name too long!\n",
+				entry.header.name_len);
+		       fclose(fp);
+		       exit(1);
+		}
+
+		memset(entry.name, 0x00, sizeof(entry.name));
 		if (!fread(entry.name, entry.header.name_len, 1, fp)) {
 			log_err("Unable to read template name\n");
 			goto out;
 		}
 
-		entry.name[entry.header.name_len] = '\0';
+		is_ima_template = strcmp(entry.name, "ima") == 0 ? 1 : 0;
 
-		if (!fread(&entry.template_len, sizeof(entry.template_len), 1, fp)) {
-			log_err("Unable to read template length\n");
-			goto out;
+		/* The "ima" template data is not length prefixed.  Skip it. */
+		if (!is_ima_template) {
+			if (!fread(&entry.template_len,
+				   sizeof(entry.template_len), 1, fp)) {
+				log_err("Unable to read template length\n");
+				goto out;
+			}
+		} else {
+			entry.template_len = SHA_DIGEST_LENGTH +
+					     TCG_EVENT_NAME_LEN_MAX + 1;
 		}
 
 		if (entry.template_buf_len < entry.template_len) {
@@ -1869,9 +1889,42 @@ static int ima_measurement(const char *file)
 			entry.template = malloc(entry.template_len);
 		}
 
-		if (!fread(entry.template, entry.template_len, 1, fp)) {
-			log_err("Unable to read template\n");
-			goto out;
+		if (!is_ima_template) {
+			if (!fread(entry.template, entry.template_len, 1, fp)) {
+				log_errno("Unable to read template\n");
+				goto out;
+			}
+		} else {
+			uint32_t field_len;
+			uint32_t len;
+
+			/*
+			 * The "ima" template data format is digest,
+			 * filename length, filename.
+			 */
+			if (!fread(entry.template, SHA_DIGEST_LENGTH, 1, fp)) {
+				log_errno("Unable to read file data hash\n");
+				goto out;
+			}
+
+			/*
+			 * Read the filename length, but it isn't included
+			 * in the template data hash calculation.
+			 */
+			len = fread(&field_len, sizeof(field_len), 1, fp);
+			if (field_len > TCG_EVENT_NAME_LEN_MAX)
+				log_err("file pathname is too long\n");
+
+			fread(entry.template + SHA_DIGEST_LENGTH,
+			      field_len, 1, fp);
+
+			/*
+			 * The template data is fixed sized, zero out
+			 * the remaining memory.
+			 */
+			len = SHA_DIGEST_LENGTH + field_len;
+			memset(entry.template + len, 0x00,
+			       entry.template_buf_len - len);
 		}
 
 		extend_tpm_banks(&entry, num_banks, pseudo_banks);
@@ -1879,7 +1932,7 @@ static int ima_measurement(const char *file)
 		if (verify)
 			ima_verify_template_hash(&entry);
 
-		if (!strcmp(entry.name, "ima"))
+		if (is_ima_template)
 			ima_show(&entry);
 		else
 			ima_ng_show(&entry);
-- 
2.7.5


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] ima-evm-utils: read the TPM 1.2 binary_bios_measurements
  2020-07-07  2:27 [PATCH 0/3] ima-evm-utils: original "ima" template support Mimi Zohar
  2020-07-07  2:27 ` [PATCH 1/3] ima-evm-utils: support the original "ima" template Mimi Zohar
@ 2020-07-07  2:27 ` Mimi Zohar
  2020-07-07  2:27 ` [PATCH 3/3] ima-evm-utils: mixed "ima" and other template formats not supported Mimi Zohar
  2 siblings, 0 replies; 4+ messages in thread
From: Mimi Zohar @ 2020-07-07  2:27 UTC (permalink / raw)
  To: linux-integrity; +Cc: Mimi Zohar, Petr Vorel, Bruno Meneguele

Instead of just calculating the "boot_aggregate" based on the current
TPM PCRs, the original LTP and standalone ima_boot_aggregate test walked
the TPM 1.2 event log, calculating the PCRs.

If the TPM 1.2 event log is provided as an option on the "evmctl
ima_boot_aggregate" command, read the event log, calculate the sha1
PCRs, and calculate the "boot_aggregate" based on these PCRs.

The code for walking the IMA measurement list is based on the LTP and
standalone ima_boot_aggregate tests.  Similar support for reading the
TPM 2.0 event log to calculate the PCRs requires the TPM 2.0 event log
to be exported or a TSS to read the event log.  Parsing the TPM 2.0
event log is not supported here.

Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
---
 src/evmctl.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 87 insertions(+), 5 deletions(-)

diff --git a/src/evmctl.c b/src/evmctl.c
index b157c452839b..9ee440f6a50a 100644
--- a/src/evmctl.c
+++ b/src/evmctl.c
@@ -1963,6 +1963,67 @@ static int cmd_ima_measurement(struct command *cmd)
 	return ima_measurement(file);
 }
 
+#define MAX_EVENT_DATA_SIZE 200000
+static int read_binary_bios_measurements(char *file, struct tpm_bank_info *bank)
+{
+	struct {
+		struct {
+			uint32_t pcr;
+			int type;
+			unsigned char digest[SHA_DIGEST_LENGTH];
+			uint32_t len;
+		} header;
+		unsigned char data[MAX_EVENT_DATA_SIZE];
+	} event;
+	FILE *fp;
+	SHA_CTX c;
+	int err = 0;
+	int i;
+
+	fp = fopen(file, "r");
+	if (!fp) {
+		log_errno("Failed to open TPM 1.2 event log.\n");
+		return 1;
+	}
+
+	if (imaevm_params.verbose > LOG_INFO)
+		log_info("Reading the TPM 1.2 event log %s.\n", file);
+
+	/* Extend the pseudo TPM PCRs with the event digest */
+	while (fread(&event, sizeof(event.header), 1, fp)) {
+		if (imaevm_params.verbose > LOG_INFO) {
+			log_info("%02u ", event.header.pcr);
+			log_dump(event.header.digest, SHA_DIGEST_LENGTH);
+		}
+		if (event.header.pcr > NUM_PCRS) {
+			log_err("Invalid PCR %d.\n", event.header.pcr);
+			err = 1;
+			break;
+		}
+		SHA1_Init(&c);
+		SHA1_Update(&c, bank->pcr[event.header.pcr], 20);
+		SHA1_Update(&c, event.header.digest, 20);
+		SHA1_Final(bank->pcr[event.header.pcr], &c);
+		if (event.header.len > MAX_EVENT_DATA_SIZE) {
+			log_err("Event data event too long.\n");
+			err = 1;
+			break;
+		}
+		fread(event.data, event.header.len, 1, fp);
+	}
+	fclose(fp);
+
+	if (imaevm_params.verbose <= LOG_INFO)
+		return err;
+
+	for (i = 0; i < NUM_PCRS; i++) {
+		log_info("PCR-%2.2x ", i);
+		log_dump(bank->pcr[i], SHA_DIGEST_LENGTH);
+
+	}
+	return err;
+}
+
 static void calc_bootaggr(struct tpm_bank_info *bank)
 {
 	EVP_MD_CTX *pctx;
@@ -2056,13 +2117,34 @@ static int cmd_ima_bootaggr(struct command *cmd)
 	char *bootaggr;
 	int num_banks = 0;
 	int offset = 0;
+	int err = 0;
 	int i;
 
-	tpm_banks = init_tpm_banks(&num_banks);
+	char *file = g_argv[optind++];
 
-	if (read_tpm_banks(num_banks, tpm_banks) != 0) {
-		log_info("Failed to read any TPM PCRs\n");
-		return -1;
+	/*
+	 * Instead of just reading the TPM 1.2 PCRs, walk the exported
+	 * TPM 1.2 SHA1 event log, calculating the PCRs.
+	 */
+	if (file) {
+		tpm_banks = init_tpm_banks(&num_banks);
+
+		/* TPM 1.2 only supports SHA1.*/
+		for (i = 1; i < num_banks; i++)
+			tpm_banks[i].supported = 0;
+
+		err = read_binary_bios_measurements(file, tpm_banks);
+		if (err) {
+			log_info("Failed reading the TPM 1.2 event log %s.\n",
+				 file);
+			return -1;
+		}
+	} else {
+		tpm_banks = init_tpm_banks(&num_banks);
+		if (read_tpm_banks(num_banks, tpm_banks) != 0) {
+			log_info("Failed to read any TPM PCRs\n");
+			return -1;
+		}
 	}
 
 	/*
@@ -2211,7 +2293,7 @@ struct command cmds[] = {
 	{"ima_setxattr", cmd_setxattr_ima, 0, "[--sigfile file]", "Set IMA signature from sigfile\n"},
 	{"ima_hash", cmd_hash_ima, 0, "file", "Make file content hash.\n"},
 	{"ima_measurement", cmd_ima_measurement, 0, "[--validate] [--verify] file", "Verify measurement list (experimental).\n"},
-	{"ima_boot_aggregate", cmd_ima_bootaggr, 0, "", "Calculate per TPM bank boot_aggregate digests\n"},
+	{"ima_boot_aggregate", cmd_ima_bootaggr, 0, "[file]", "Calculate per TPM bank boot_aggregate digests\n"},
 	{"ima_fix", cmd_ima_fix, 0, "[-t fdsxm] path", "Recursively fix IMA/EVM xattrs in fix mode.\n"},
 	{"ima_clear", cmd_ima_clear, 0, "[-t fdsxm] path", "Recursively remove IMA/EVM xattrs.\n"},
 	{"sign_hash", cmd_sign_hash, 0, "[--key key] [--pass [password]", "Sign hashes from shaXsum output.\n"},
-- 
2.7.5


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] ima-evm-utils: mixed "ima" and other template formats not supported
  2020-07-07  2:27 [PATCH 0/3] ima-evm-utils: original "ima" template support Mimi Zohar
  2020-07-07  2:27 ` [PATCH 1/3] ima-evm-utils: support the original "ima" template Mimi Zohar
  2020-07-07  2:27 ` [PATCH 2/3] ima-evm-utils: read the TPM 1.2 binary_bios_measurements Mimi Zohar
@ 2020-07-07  2:27 ` Mimi Zohar
  2 siblings, 0 replies; 4+ messages in thread
From: Mimi Zohar @ 2020-07-07  2:27 UTC (permalink / raw)
  To: linux-integrity; +Cc: Mimi Zohar, Petr Vorel, Bruno Meneguele

An IMA measurement list may not contain "ima" and other template
formats.  Fail verifying the ima_measurement test.

Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
---
 src/evmctl.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/src/evmctl.c b/src/evmctl.c
index 9ee440f6a50a..21809b3229e9 100644
--- a/src/evmctl.c
+++ b/src/evmctl.c
@@ -1830,8 +1830,9 @@ static int ima_measurement(const char *file)
 {
 	struct tpm_bank_info *pseudo_banks;
 	struct tpm_bank_info *tpm_banks;
-	int is_ima_template;
+	int is_ima_template, cur_template_fmt;
 	int num_banks = 0;
+	int first_record = 1;
 
 	struct template_entry entry = { .template = 0 };
 	FILE *fp;
@@ -1869,7 +1870,21 @@ static int ima_measurement(const char *file)
 			goto out;
 		}
 
-		is_ima_template = strcmp(entry.name, "ima") == 0 ? 1 : 0;
+	       /*
+		* The "ima" template format can not be mixed with other
+		* template formats records.
+		*/
+		if (!first_record) {
+			cur_template_fmt = strcmp(entry.name, "ima") == 0 ? 1 : 0;
+			if ((is_ima_template && !cur_template_fmt) ||
+			    (!is_ima_template && cur_template_fmt)) {
+				log_err("Mixed measurement list containing \"ima\" and other template formats not supported.\n");
+				goto out;
+			}
+		} else {
+			first_record = 0;
+			is_ima_template = strcmp(entry.name, "ima") == 0 ? 1 : 0;
+		}
 
 		/* The "ima" template data is not length prefixed.  Skip it. */
 		if (!is_ima_template) {
-- 
2.7.5


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-07-07  2:28 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-07  2:27 [PATCH 0/3] ima-evm-utils: original "ima" template support Mimi Zohar
2020-07-07  2:27 ` [PATCH 1/3] ima-evm-utils: support the original "ima" template Mimi Zohar
2020-07-07  2:27 ` [PATCH 2/3] ima-evm-utils: read the TPM 1.2 binary_bios_measurements Mimi Zohar
2020-07-07  2:27 ` [PATCH 3/3] ima-evm-utils: mixed "ima" and other template formats not supported Mimi Zohar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).