[PATCH v2] ima-evm-utils: Improve ima_measurement matching on busy system with >1 banks

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When a system is very busy with IMA taking measurements into more than
one bank, then we often do not get the PCR 10 values of the sha1 bank
that represents the same log entry as the reading of the PCR value of
the sha256 bank. In other words, the reading of the PCR 10 value from
the sha1 bank may represent the PCR 10 state at the time of the
n-th entry in the log while the reading of the PCR 10 value from the
sha256 bank may represent the state at the time of a later-than-n entry.
The result currently is that the PCR measurements do not match and
on a busy system the tool may not easily report a successful match.

This patch fixes this issue by separating the TPM bank comparison for
each one of the banks being looked and using a bit mask for checking
which banks have already been matched. Once the mask has become 0
all PCR banks have been successfully matched.

A run on a busy system may result in the output as follows indicating
PCR bank matches at the n-th entry for the sha1 bank and at a later
entry, possibly n + 1 or n + 2 or so, for the sha256 bank. The
output is interleaved with a match of the sha1 bank against 'padded
matching'.

$ evmctl ima_measurement --ignore-violations /sys/kernel/security/ima/binary_runtime_measurements -v
sha1: PCRAgg  10: 381cc6139e2fbda76037ec0946089aeccaaa5374
sha1: TPM PCR-10: 381cc6139e2fbda76037ec0946089aeccaaa5374
sha1 PCR-10: succeed at entry 4918
sha1: PCRAgg  10: 381cc6139e2fbda76037ec0946089aeccaaa5374
sha1: TPM PCR-10: 381cc6139e2fbda76037ec0946089aeccaaa5374
sha1 PCR-10: succeed at entry 4918
[...]
sha256: PCRAgg  10: c21dcb7098b3d7627f7aaeddf8aff68a65209027274d82af52be2fd302193eb7
sha256: TPM PCR-10: c21dcb7098b3d7627f7aaeddf8aff68a65209027274d82af52be2fd302193eb7
sha256 PCR-10: succeed at entry 4922
Matched per TPM bank calculated digest(s).

Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxxxxx>
---
v1->v2:
 - Reporting entry number that resulted in a match when in verbose mode

---
 src/evmctl.c | 57 ++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 44 insertions(+), 13 deletions(-)

diff --git a/src/evmctl.c b/src/evmctl.c
index 1815f55..f18eaae 100644
--- a/src/evmctl.c
+++ b/src/evmctl.c
@@ -1594,10 +1594,15 @@ static struct tpm_bank_info *init_tpm_banks(int *num_banks)
 
 /*
  * Compare the calculated TPM PCR banks against the PCR values read.
+ * The banks_mask parameter allows to select which banks to consider.
+ * A banks_maks of 0x3 would consider banks 1 and 2, 0x2 would only
+ * consider the 2nd bank, ~0 would consider all banks.
+ *
  * On failure to match any TPM bank, fail comparison.
  */
 static int compare_tpm_banks(int num_banks, struct tpm_bank_info *bank,
-			     struct tpm_bank_info *tpm_bank)
+			     struct tpm_bank_info *tpm_bank,
+			     unsigned int banks_mask, unsigned long entry_num)
 {
 	int i, j;
 	int ret = 0;
@@ -1605,6 +1610,9 @@ static int compare_tpm_banks(int num_banks, struct tpm_bank_info *bank,
 	for (i = 0; i < num_banks; i++) {
 		if (!bank[i].supported || !tpm_bank[i].supported)
 			continue;
+		/* do we need to look at the n-th bank ? */
+		if ((banks_mask & (1 << i)) == 0)
+			continue;
 		for (j = 0; j < NUM_PCRS; j++) {
 			if (memcmp(bank[i].pcr[j], zero, bank[i].digest_size)
 			    == 0)
@@ -1625,8 +1633,8 @@ static int compare_tpm_banks(int num_banks, struct tpm_bank_info *bank,
 			log_dump(tpm_bank[i].pcr[j], tpm_bank[i].digest_size);
 
 			if (!ret)
-				log_info("%s PCR-%d: succeed\n",
-					 bank[i].algo_name, j);
+				log_info("%s PCR-%d: succeed at entry %lu\n",
+					 bank[i].algo_name, j, entry_num);
 			else
 				log_info("%s: PCRAgg %d does not match TPM PCR-%d\n",
 					 bank[i].algo_name, j, j);
@@ -1941,6 +1949,9 @@ static int ima_measurement(const char *file)
 	int num_banks = 0;
 	int tpmbanks = 1;
 	int first_record = 1;
+	unsigned int pseudo_padded_banks_mask, pseudo_banks_mask;
+	unsigned long entry_num = 0;
+	int c;
 
 	struct template_entry entry = { .template = 0 };
 	FILE *fp;
@@ -1974,7 +1985,12 @@ static int ima_measurement(const char *file)
 	if (read_tpm_banks(num_banks, tpm_banks) != 0)
 		tpmbanks = 0;
 
+	/* A mask where each bit represents the banks to check against */
+	pseudo_banks_mask = (1 << num_banks) - 1;
+	pseudo_padded_banks_mask = pseudo_banks_mask;
+
 	while (fread(&entry.header, sizeof(entry.header), 1, fp)) {
+		entry_num++;
 		if (entry.header.name_len > TCG_EVENT_NAME_LEN_MAX) {
 			log_err("%d ERROR: event name too long!\n",
 				entry.header.name_len);
@@ -2086,18 +2102,33 @@ static int ima_measurement(const char *file)
 		if (!tpmbanks)
 			continue;
 
-		/* The measurement list might contain too many entries,
-		 * compare the re-calculated TPM PCR values after each
-		 * extend.
-		 */
-		err = compare_tpm_banks(num_banks, pseudo_banks, tpm_banks);
-		if (!err)
+		for (c = 0; c < num_banks; c++) {
+			if ((pseudo_banks_mask & (1 << c)) == 0)
+				continue;
+			/* The measurement list might contain too many entries,
+			 * compare the re-calculated TPM PCR values after each
+			 * extend.
+			 */
+			err = compare_tpm_banks(num_banks, pseudo_banks,
+						tpm_banks, 1 << c, entry_num);
+			if (!err)
+				pseudo_banks_mask ^= (1 << c);
+		}
+		if (pseudo_banks_mask == 0)
 			break;
 
-		/* Compare against original SHA1 zero padded TPM PCR values */
-		err_padded = compare_tpm_banks(num_banks, pseudo_padded_banks,
-					       tpm_banks);
-		if (!err_padded)
+		for (c = 0; c < num_banks; c++) {
+			if ((pseudo_padded_banks_mask & (1 << c)) == 0)
+				continue;
+			/* Compare against original SHA1 zero padded TPM PCR values */
+			err_padded = compare_tpm_banks(num_banks,
+						       pseudo_padded_banks,
+						       tpm_banks,
+						       1 << c, entry_num);
+			if (!err_padded)
+				pseudo_padded_banks_mask ^= (1 << c);
+		}
+		if (pseudo_padded_banks_mask == 0)
 			break;
 	}
 
-- 
2.29.2




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux Kernel]     [Linux Kernel Hardening]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux