linux-integrity.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/10] ima-evm-utils
@ 2018-01-22 14:53 Mimi Zohar
  2018-01-22 14:53 ` [PATCH 01/10] ima-evm-utils: fix "ima_measurement" template fields length Mimi Zohar
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Mimi Zohar @ 2018-01-22 14:53 UTC (permalink / raw)
  To: linux-integrity
  Cc: Dmitry Kasatkin, Roberto Sassu, Bruno E . O . Meneguele,
	Mimi Zohar

Before upgrading to the new OpenSSL 1.1 API, let's clean up the code
a bit and add some missing functionality:
- option to specify the pcr sysfs location
- verify the measurement list using multiple keys
- verify the measurement list using multiple pcrs
- verify a measurement signature against the measurement list digest
- for completeness, extend "ima_verify" to verify the local security.ima hash

Mimi

Mimi Zohar (10):
  ima-evm-utils: fix "ima_measurement" template fields length
  ima-evm-utils: revert the change to use printf instead of log_info()
  ima-evm-utils: fix spelling error
  ima-evm-utils: remove the unnecessary display of the keyid
  ima-evm-utils: support verifying the measurement list using multiple
    keys
  ima-evm-utils: indicate measurement list signature verification
    failure
  ima-evm-utils: add support for specifying the pcr file location
  ima-evm-utils: verify the measurement list signature based on the list
    digest
  ima-evm-utils: verify IMA file hashes stored as xattrs
  ima-evm-utils: add support for validating multiple pcrs

 README          |   2 +-
 src/evmctl.c    |  94 ++++++++++++++++++++++++++++-----------
 src/imaevm.h    |   7 ++-
 src/libimaevm.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 4 files changed, 199 insertions(+), 39 deletions(-)

-- 
2.7.4

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

* [PATCH 01/10] ima-evm-utils: fix "ima_measurement" template fields length
  2018-01-22 14:53 [PATCH 00/10] ima-evm-utils Mimi Zohar
@ 2018-01-22 14:53 ` Mimi Zohar
  2018-01-22 14:53 ` [PATCH 02/10] ima-evm-utils: revert the change to use printf instead of log_info() Mimi Zohar
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Mimi Zohar @ 2018-01-22 14:53 UTC (permalink / raw)
  To: linux-integrity
  Cc: Dmitry Kasatkin, Roberto Sassu, Bruno E . O . Meneguele,
	Mimi Zohar

The template data field length is uint32_t, not uint8_t.

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

diff --git a/src/evmctl.c b/src/evmctl.c
index 313a0c5..a6c6e01 100644
--- a/src/evmctl.c
+++ b/src/evmctl.c
@@ -1342,7 +1342,7 @@ void ima_ng_show(struct template_entry *entry)
 	char *algo, *path;
 
 	/* get binary digest */
-	field_len = *(uint8_t *)fieldp;
+	field_len = *(uint32_t *)fieldp;
 	fieldp += sizeof(field_len);
 	total_len -= sizeof(field_len);
 
@@ -1356,7 +1356,7 @@ void ima_ng_show(struct template_entry *entry)
 	total_len -= field_len;
 
 	/* get path */
-	field_len = *(uint8_t *)fieldp;
+	field_len = *(uint32_t *)fieldp;
 	fieldp += sizeof(field_len);
 	total_len -= sizeof(field_len);
 
@@ -1368,7 +1368,7 @@ void ima_ng_show(struct template_entry *entry)
 
 	if (!strcmp(entry->name, "ima-sig")) {
 		/* get signature */
-		field_len = *(uint8_t *)fieldp;
+		field_len = *(uint32_t *)fieldp;
 		fieldp += sizeof(field_len);
 		total_len -= sizeof(field_len);
 
-- 
2.7.4

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

* [PATCH 02/10] ima-evm-utils: revert the change to use printf instead of log_info()
  2018-01-22 14:53 [PATCH 00/10] ima-evm-utils Mimi Zohar
  2018-01-22 14:53 ` [PATCH 01/10] ima-evm-utils: fix "ima_measurement" template fields length Mimi Zohar
@ 2018-01-22 14:53 ` Mimi Zohar
  2018-01-22 14:53 ` [PATCH 03/10] ima-evm-utils: fix spelling error Mimi Zohar
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Mimi Zohar @ 2018-01-22 14:53 UTC (permalink / raw)
  To: linux-integrity
  Cc: Dmitry Kasatkin, Roberto Sassu, Bruno E . O . Meneguele,
	Mimi Zohar

Using log_info() was commented out and replaced with printf.  Revert
this change and use log_info().

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

diff --git a/src/libimaevm.c b/src/libimaevm.c
index eedffb4..610b0b7 100644
--- a/src/libimaevm.c
+++ b/src/libimaevm.c
@@ -402,8 +402,7 @@ int verify_hash_v1(const unsigned char *hash, int size, unsigned char *sig, int
 		log_err("Verification failed: %d\n", err);
 		return -1;
 	} else {
-		/*log_info("Verification is OK\n");*/
-		printf("Verification is OK\n");
+		log_info("Verification is OK\n");
 	}
 
 	return 0;
@@ -447,8 +446,7 @@ int verify_hash_v2(const unsigned char *hash, int size, unsigned char *sig, int
 		return -1;
 	}
 
-	/*log_info("Verification is OK\n");*/
-	printf("Verification is OK\n");
+	log_info("Verification is OK\n");
 
 	return 0;
 }
-- 
2.7.4

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

* [PATCH 03/10] ima-evm-utils: fix spelling error
  2018-01-22 14:53 [PATCH 00/10] ima-evm-utils Mimi Zohar
  2018-01-22 14:53 ` [PATCH 01/10] ima-evm-utils: fix "ima_measurement" template fields length Mimi Zohar
  2018-01-22 14:53 ` [PATCH 02/10] ima-evm-utils: revert the change to use printf instead of log_info() Mimi Zohar
@ 2018-01-22 14:53 ` Mimi Zohar
  2018-01-22 14:53 ` [PATCH 04/10] ima-evm-utils: remove the unnecessary display of the keyid Mimi Zohar
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Mimi Zohar @ 2018-01-22 14:53 UTC (permalink / raw)
  To: linux-integrity
  Cc: Dmitry Kasatkin, Roberto Sassu, Bruno E . O . Meneguele,
	Mimi Zohar

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

diff --git a/src/evmctl.c b/src/evmctl.c
index a6c6e01..746fc09 100644
--- a/src/evmctl.c
+++ b/src/evmctl.c
@@ -1310,7 +1310,7 @@ void ima_extend_pcr(uint8_t *pcr, uint8_t *digest, int length)
 	SHA1_Final(pcr, &ctx);
 }
 
-static int ima_verify_tamplate_hash(struct template_entry *entry)
+static int ima_verify_template_hash(struct template_entry *entry)
 {
 	uint8_t digest[SHA_DIGEST_LENGTH];
 
@@ -1446,7 +1446,7 @@ static int ima_measurement(const char *file)
 		}
 
 		if (validate)
-			ima_verify_tamplate_hash(&entry);
+			ima_verify_template_hash(&entry);
 
 		if (!strcmp(entry.name, "ima"))
 			ima_show(&entry);
-- 
2.7.4

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

* [PATCH 04/10] ima-evm-utils: remove the unnecessary display of the keyid
  2018-01-22 14:53 [PATCH 00/10] ima-evm-utils Mimi Zohar
                   ` (2 preceding siblings ...)
  2018-01-22 14:53 ` [PATCH 03/10] ima-evm-utils: fix spelling error Mimi Zohar
@ 2018-01-22 14:53 ` Mimi Zohar
  2018-01-22 14:54 ` [PATCH 05/10] ima-evm-utils: support verifying the measurement list using multiple keys Mimi Zohar
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Mimi Zohar @ 2018-01-22 14:53 UTC (permalink / raw)
  To: linux-integrity
  Cc: Dmitry Kasatkin, Roberto Sassu, Bruno E . O . Meneguele,
	Mimi Zohar

Callers of calc_keyid_v2() can display the keyid, when desired.

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
 src/libimaevm.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/libimaevm.c b/src/libimaevm.c
index 610b0b7..a92deed 100644
--- a/src/libimaevm.c
+++ b/src/libimaevm.c
@@ -606,8 +606,6 @@ void calc_keyid_v2(uint32_t *keyid, char *str, RSA *key)
 	log_debug_dump(keyid, 4);
 
 	sprintf(str, "%x", __be32_to_cpup(keyid));
-	log_info("keyid: %s\n", str);
-
 	free(pkey);
 }
 
-- 
2.7.4

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

* [PATCH 05/10] ima-evm-utils: support verifying the measurement list using multiple keys
  2018-01-22 14:53 [PATCH 00/10] ima-evm-utils Mimi Zohar
                   ` (3 preceding siblings ...)
  2018-01-22 14:53 ` [PATCH 04/10] ima-evm-utils: remove the unnecessary display of the keyid Mimi Zohar
@ 2018-01-22 14:54 ` Mimi Zohar
  2018-01-22 14:54 ` [PATCH 06/10] ima-evm-utils: indicate measurement list signature verification failure Mimi Zohar
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Mimi Zohar @ 2018-01-22 14:54 UTC (permalink / raw)
  To: linux-integrity
  Cc: Dmitry Kasatkin, Roberto Sassu, Bruno E . O . Meneguele,
	Mimi Zohar

On a running system, different software packages might be signed by
different parties.  Support verifying signatures in the measurement
list using multiple public keys(eg.  -k "key1, key2, ...").

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
 README          |  2 +-
 src/evmctl.c    |  4 +++
 src/imaevm.h    |  1 +
 src/libimaevm.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 4 files changed, 76 insertions(+), 6 deletions(-)

diff --git a/README b/README
index da828cf..1c4bc7a 100644
--- a/README
+++ b/README
@@ -31,7 +31,7 @@ COMMANDS
  ima_sign [--sigfile] [--key key] [--pass password] file
  ima_verify file
  ima_hash file
- ima_measurement file
+ ima_measurement [--key "key1, key2, ..."] file
  ima_fix [-t fdsxm] path
  sign_hash [--key key] [--pass password]
  hmac [--imahash | --imasig ] file
diff --git a/src/evmctl.c b/src/evmctl.c
index 746fc09..e0ed93d 100644
--- a/src/evmctl.c
+++ b/src/evmctl.c
@@ -1419,6 +1419,10 @@ static int ima_measurement(const char *file)
 		return -1;
 	}
 
+	/* Support multiple public keys */
+	if (params.keyfile)
+		init_public_keys(params.keyfile);
+
 	while (fread(&entry.header, sizeof(entry.header), 1, fp)) {
 		ima_extend_pcr(pcr, entry.header.digest, SHA_DIGEST_LENGTH);
 
diff --git a/src/imaevm.h b/src/imaevm.h
index e397743..ea6a7b1 100644
--- a/src/imaevm.h
+++ b/src/imaevm.h
@@ -205,5 +205,6 @@ int key2bin(RSA *key, unsigned char *pub);
 int sign_hash(const char *algo, const unsigned char *hash, int size, const char *keyfile, const char *keypass, unsigned char *sig);
 int verify_hash(const unsigned char *hash, int size, unsigned char *sig, int siglen);
 int ima_verify_signature(const char *file, unsigned char *sig, int siglen);
+void init_public_keys(const char *keyfiles);
 
 #endif
diff --git a/src/libimaevm.c b/src/libimaevm.c
index a92deed..0ad290a 100644
--- a/src/libimaevm.c
+++ b/src/libimaevm.c
@@ -408,6 +408,61 @@ int verify_hash_v1(const unsigned char *hash, int size, unsigned char *sig, int
 	return 0;
 }
 
+struct public_key_entry {
+	struct public_key_entry *next;
+	uint32_t keyid;
+	char name[9];
+	RSA *key;
+};
+static struct public_key_entry *public_keys = NULL;
+
+static RSA *find_keyid(uint32_t keyid)
+{
+	struct public_key_entry *entry;
+
+	for (entry = public_keys; entry != NULL; entry = entry->next) {
+		if (entry->keyid == keyid)
+			return entry->key;
+	}
+	return NULL;
+}
+
+void init_public_keys(const char *keyfiles)
+{
+	struct public_key_entry *entry;
+	char *tmp_keyfiles;
+	char *keyfile;
+	int i = 1;
+
+	tmp_keyfiles = strdup(keyfiles);
+
+	while ((keyfile = strsep(&tmp_keyfiles, ", \t")) != NULL) {
+		if (!keyfile)
+			break;
+		if ((*keyfile == '\0') || (*keyfile == ' ') ||
+		    (*keyfile == '\t'))
+			continue;
+
+		entry = malloc(sizeof(struct public_key_entry));
+		if (!entry) {
+			perror("malloc");
+			break;
+		}
+
+		entry->key = read_pub_key(keyfile, 1);
+		if (!entry->key) {
+			free(entry);
+			continue;
+		}
+
+		calc_keyid_v2(&entry->keyid, entry->name, entry->key);
+		sprintf(entry->name, "%x", __be32_to_cpup(&entry->keyid));
+		log_info("key %d: %s %s\n", i++, entry->name, keyfile);
+		entry->next = public_keys;
+		public_keys = entry;
+	}
+}
+
 int verify_hash_v2(const unsigned char *hash, int size, unsigned char *sig, int siglen, const char *keyfile)
 {
 	int err, len;
@@ -419,12 +474,22 @@ int verify_hash_v2(const unsigned char *hash, int size, unsigned char *sig, int
 	log_info("hash: ");
 	log_dump(hash, size);
 
-	key = read_pub_key(keyfile, 1);
-	if (!key)
-		return 1;
+	if (public_keys) {
+		key = find_keyid(hdr->keyid);
+		if (!key) {
+			log_err("Unknown keyid: %x\n",
+				__be32_to_cpup(&hdr->keyid));
+			return -1;
+		}
+	} else {
+		key = read_pub_key(keyfile, 1);
+		if (!key)
+			return 1;
+	}
 
-	err = RSA_public_decrypt(siglen - sizeof(*hdr), sig + sizeof(*hdr), out, key, RSA_PKCS1_PADDING);
-	RSA_free(key);
+
+	err = RSA_public_decrypt(siglen - sizeof(*hdr), sig + sizeof(*hdr),
+				 out, key, RSA_PKCS1_PADDING);
 	if (err < 0) {
 		log_err("RSA_public_decrypt() failed: %d\n", err);
 		return 1;
-- 
2.7.4

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

* [PATCH 06/10] ima-evm-utils: indicate measurement list signature verification failure
  2018-01-22 14:53 [PATCH 00/10] ima-evm-utils Mimi Zohar
                   ` (4 preceding siblings ...)
  2018-01-22 14:54 ` [PATCH 05/10] ima-evm-utils: support verifying the measurement list using multiple keys Mimi Zohar
@ 2018-01-22 14:54 ` Mimi Zohar
  2018-01-22 14:54 ` [PATCH 07/10] ima-evm-utils: add support for specifying the pcr file location Mimi Zohar
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Mimi Zohar @ 2018-01-22 14:54 UTC (permalink / raw)
  To: linux-integrity
  Cc: Dmitry Kasatkin, Roberto Sassu, Bruno E . O . Meneguele,
	Mimi Zohar

Walking the measurement list and calculating the PCR to compare
against the TPM is only the first step.  The next step is verifying
the file signatures contained in the measurement list.  This patch
differentiates between the two.

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

diff --git a/src/evmctl.c b/src/evmctl.c
index e0ed93d..f791a5b 100644
--- a/src/evmctl.c
+++ b/src/evmctl.c
@@ -1333,13 +1333,14 @@ void ima_show(struct template_entry *entry)
 	log_debug_dump(entry->header.digest, sizeof(entry->header.digest));
 }
 
-void ima_ng_show(struct template_entry *entry)
+int ima_ng_show(struct template_entry *entry)
 {
 	uint8_t *fieldp = entry->template;
 	uint32_t field_len;
 	int total_len = entry->template_len, digest_len, len, sig_len;
 	uint8_t *digest, *sig = NULL;
 	char *algo, *path;
+	int err = 0;
 
 	/* get binary digest */
 	field_len = *(uint32_t *)fieldp;
@@ -1392,12 +1393,13 @@ void ima_ng_show(struct template_entry *entry)
 	if (sig) {
 		log_info(" ");
 		log_dump(sig, sig_len);
-		ima_verify_signature(path, sig, sig_len);
+		err = ima_verify_signature(path, sig, sig_len);
 	} else
 		log_info("\n");
 
 	if (total_len)
 		log_err("Remain unprocessed data: %d\n", total_len);
+	return err;
 }
 
 static int ima_measurement(const char *file)
@@ -1407,6 +1409,7 @@ static int ima_measurement(const char *file)
 	struct template_entry entry = { .template = 0 };
 	FILE *fp;
 	int err = -1;
+	int verify_sig_failed = 0;
 
 	memset(fox, 0xff, SHA_DIGEST_LENGTH);
 
@@ -1452,10 +1455,12 @@ static int ima_measurement(const char *file)
 		if (validate)
 			ima_verify_template_hash(&entry);
 
-		if (!strcmp(entry.name, "ima"))
+		if (!strcmp(entry.name, "ima")) {
 			ima_show(&entry);
-		else
-			ima_ng_show(&entry);
+		} else {
+			if (ima_ng_show(&entry) != 0)
+				verify_sig_failed = 1;
+		}
 	}
 
 	tpm_pcr_read(10, pcr10, sizeof(pcr10));
@@ -1469,6 +1474,8 @@ static int ima_measurement(const char *file)
 	if (memcmp(pcr, pcr10, sizeof(pcr))) {
 		log_err("PCRAgg does not match PCR-10\n");
 		goto out;
+	} else if (verify_sig_failed == 1) {
+		log_err("PCRAgg matches PCR-10, but list contains unknown keys or invalid signatures\n");
 	}
 
 	err = 0;
-- 
2.7.4

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

* [PATCH 07/10] ima-evm-utils: add support for specifying the pcr file location
  2018-01-22 14:53 [PATCH 00/10] ima-evm-utils Mimi Zohar
                   ` (5 preceding siblings ...)
  2018-01-22 14:54 ` [PATCH 06/10] ima-evm-utils: indicate measurement list signature verification failure Mimi Zohar
@ 2018-01-22 14:54 ` Mimi Zohar
  2018-01-22 14:54 ` [PATCH 08/10] ima-evm-utils: verify the measurement list signature based on the list digest Mimi Zohar
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Mimi Zohar @ 2018-01-22 14:54 UTC (permalink / raw)
  To: linux-integrity
  Cc: Dmitry Kasatkin, Roberto Sassu, Bruno E . O . Meneguele,
	Mimi Zohar

The location of the PCRs differs from system to system.  This
patch defines a new "--pcrs <filename>" option.

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
 README       |  2 +-
 src/evmctl.c | 12 +++++++++++-
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/README b/README
index 1c4bc7a..f9706f8 100644
--- a/README
+++ b/README
@@ -31,7 +31,7 @@ COMMANDS
  ima_sign [--sigfile] [--key key] [--pass password] file
  ima_verify file
  ima_hash file
- ima_measurement [--key "key1, key2, ..."] file
+ ima_measurement [--key "key1, key2, ..."] [--pcrs <sysfs file>] file
  ima_fix [-t fdsxm] path
  sign_hash [--key key] [--pass password]
  hmac [--imahash | --imasig ] file
diff --git a/src/evmctl.c b/src/evmctl.c
index f791a5b..310ff4e 100644
--- a/src/evmctl.c
+++ b/src/evmctl.c
@@ -112,6 +112,7 @@ static char *generation_str;
 static char *caps_str;
 static char *ima_str;
 static char *selinux_str;
+static char *pcrs_sysfs;
 static char *search_type;
 static int recursive;
 static int msize;
@@ -1258,7 +1259,11 @@ static int tpm_pcr_read(int idx, uint8_t *pcr, int len)
 
 	sprintf(pcr_str, "PCR-%d", idx);
 
-	fp = fopen(pcrs, "r");
+
+	if (pcrs_sysfs)
+		fp = fopen(pcrs_sysfs, "r");
+	else
+		fp = fopen(pcrs, "r");
 	if (!fp) {
 		log_err("Unable to open %s\n", pcrs);
 		return -1;
@@ -1593,6 +1598,7 @@ static void usage(void)
 		"      --ima          use custom IMA signature for EVM\n"
 		"      --selinux      use custom Selinux label for EVM\n"
 		"      --caps         use custom Capabilities for EVM(unspecified: from FS, empty: do not use)\n"
+		"      --pcrs         specify local sysfs pcr file\n"
 		"  -v                 increase verbosity level\n"
 		"  -h, --help         display this help and exit\n"
 		"\n");
@@ -1644,6 +1650,7 @@ static struct option opts[] = {
 	{"ima", 1, 0, 135},
 	{"selinux", 1, 0, 136},
 	{"caps", 2, 0, 137},
+	{"pcrs", 1, 0, 138},
 	{}
 
 };
@@ -1792,6 +1799,9 @@ int main(int argc, char *argv[])
 			caps_str = optarg;
 			hmac_flags |= HMAC_FLAG_CAPS_SET;
 			break;
+		case 138:
+			pcrs_sysfs = optarg;
+			break;
 		case '?':
 			exit(1);
 			break;
-- 
2.7.4

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

* [PATCH 08/10] ima-evm-utils: verify the measurement list signature based on the list digest
  2018-01-22 14:53 [PATCH 00/10] ima-evm-utils Mimi Zohar
                   ` (6 preceding siblings ...)
  2018-01-22 14:54 ` [PATCH 07/10] ima-evm-utils: add support for specifying the pcr file location Mimi Zohar
@ 2018-01-22 14:54 ` Mimi Zohar
  2018-01-22 14:54 ` [PATCH 09/10] ima-evm-utils: verify IMA file hashes stored as xattrs Mimi Zohar
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Mimi Zohar @ 2018-01-22 14:54 UTC (permalink / raw)
  To: linux-integrity
  Cc: Dmitry Kasatkin, Roberto Sassu, Bruno E . O . Meneguele,
	Mimi Zohar

Instead of verifying file signatures included in the measurement list,
by calculating the local file hash, verify the file signature based on the
digest contained in the measurement list.

This patch defines a new option named "--list".

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
 README          |  2 +-
 src/evmctl.c    | 14 ++++++++++++--
 src/imaevm.h    |  2 +-
 src/libimaevm.c | 10 +++++++++-
 4 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/README b/README
index f9706f8..f60a9fd 100644
--- a/README
+++ b/README
@@ -31,7 +31,7 @@ COMMANDS
  ima_sign [--sigfile] [--key key] [--pass password] file
  ima_verify file
  ima_hash file
- ima_measurement [--key "key1, key2, ..."] [--pcrs <sysfs file>] file
+ ima_measurement [--key "key1, key2, ..."] [--pcrs <sysfs file>] [--list] file
  ima_fix [-t fdsxm] path
  sign_hash [--key key] [--pass password]
  hmac [--imahash | --imasig ] file
diff --git a/src/evmctl.c b/src/evmctl.c
index 310ff4e..5d1c6ea 100644
--- a/src/evmctl.c
+++ b/src/evmctl.c
@@ -114,6 +114,7 @@ static char *ima_str;
 static char *selinux_str;
 static char *pcrs_sysfs;
 static char *search_type;
+static int measurement_list;
 static int recursive;
 static int msize;
 static dev_t fs_dev;
@@ -793,7 +794,7 @@ static int verify_ima(const char *file)
 		}
 	}
 
-	return ima_verify_signature(file, sig, len);
+	return ima_verify_signature(file, sig, len, NULL, 0);
 }
 
 static int cmd_verify_ima(struct command *cmd)
@@ -1398,7 +1399,11 @@ int ima_ng_show(struct template_entry *entry)
 	if (sig) {
 		log_info(" ");
 		log_dump(sig, sig_len);
-		err = ima_verify_signature(path, sig, sig_len);
+		if (measurement_list)
+			err = ima_verify_signature(path, sig, sig_len,
+						   digest, digest_len);
+		else
+			err = ima_verify_signature(path, sig, sig_len, NULL, 0);
 	} else
 		log_info("\n");
 
@@ -1599,6 +1604,7 @@ static void usage(void)
 		"      --selinux      use custom Selinux label for EVM\n"
 		"      --caps         use custom Capabilities for EVM(unspecified: from FS, empty: do not use)\n"
 		"      --pcrs         specify local sysfs pcr file\n"
+		"      --list         measurement list verification\n"
 		"  -v                 increase verbosity level\n"
 		"  -h, --help         display this help and exit\n"
 		"\n");
@@ -1651,6 +1657,7 @@ static struct option opts[] = {
 	{"selinux", 1, 0, 136},
 	{"caps", 2, 0, 137},
 	{"pcrs", 1, 0, 138},
+	{"list", 0, 0, 139},
 	{}
 
 };
@@ -1802,6 +1809,9 @@ int main(int argc, char *argv[])
 		case 138:
 			pcrs_sysfs = optarg;
 			break;
+		case 139:
+			measurement_list = 1;
+			break;
 		case '?':
 			exit(1);
 			break;
diff --git a/src/imaevm.h b/src/imaevm.h
index ea6a7b1..f5cee7d 100644
--- a/src/imaevm.h
+++ b/src/imaevm.h
@@ -204,7 +204,7 @@ int key2bin(RSA *key, unsigned char *pub);
 
 int sign_hash(const char *algo, const unsigned char *hash, int size, const char *keyfile, const char *keypass, unsigned char *sig);
 int verify_hash(const unsigned char *hash, int size, unsigned char *sig, int siglen);
-int ima_verify_signature(const char *file, unsigned char *sig, int siglen);
+int ima_verify_signature(const char *file, unsigned char *sig, int siglen, unsigned char *digest, int digestlen);
 void init_public_keys(const char *keyfiles);
 
 #endif
diff --git a/src/libimaevm.c b/src/libimaevm.c
index 0ad290a..247100f 100644
--- a/src/libimaevm.c
+++ b/src/libimaevm.c
@@ -580,7 +580,8 @@ int verify_hash(const unsigned char *hash, int size, unsigned char *sig, int sig
 	return verify_hash(hash, size, sig, siglen, key);
 }
 
-int ima_verify_signature(const char *file, unsigned char *sig, int siglen)
+int ima_verify_signature(const char *file, unsigned char *sig, int siglen,
+			 unsigned char *digest, int digestlen)
 {
 	unsigned char hash[64];
 	int hashlen, sig_hash_algo;
@@ -598,6 +599,13 @@ int ima_verify_signature(const char *file, unsigned char *sig, int siglen)
 	/* Use hash algorithm as retrieved from signature */
 	params.hash_algo = pkey_hash_algo[sig_hash_algo];
 
+	/*
+	 * Validate the signature based on the digest included in the
+	 * measurement list, not by calculating the local file digest.
+	 */
+	if (digestlen > 0)
+	    return verify_hash(digest, digestlen, sig + 1, siglen - 1);
+
 	hashlen = ima_calc_hash(file, hash);
 	if (hashlen <= 1)
 		return hashlen;
-- 
2.7.4

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

* [PATCH 09/10] ima-evm-utils: verify IMA file hashes stored as xattrs
  2018-01-22 14:53 [PATCH 00/10] ima-evm-utils Mimi Zohar
                   ` (7 preceding siblings ...)
  2018-01-22 14:54 ` [PATCH 08/10] ima-evm-utils: verify the measurement list signature based on the list digest Mimi Zohar
@ 2018-01-22 14:54 ` Mimi Zohar
  2018-01-22 14:54 ` [PATCH 10/10] ima-evm-utils: add support for validating multiple pcrs Mimi Zohar
  2018-01-28 19:01 ` [PATCH 00/10] ima-evm-utils Mimi Zohar
  10 siblings, 0 replies; 12+ messages in thread
From: Mimi Zohar @ 2018-01-22 14:54 UTC (permalink / raw)
  To: linux-integrity
  Cc: Dmitry Kasatkin, Roberto Sassu, Bruno E . O . Meneguele,
	Mimi Zohar

evmctl "ima_verify" verifies file signatures stored as xattrs on the
local filesystem.  This patch adds support for verifying the file hashes
stored as xattrs.

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
 src/evmctl.c    |  3 +++
 src/imaevm.h    |  1 +
 src/libimaevm.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 46 insertions(+)

diff --git a/src/evmctl.c b/src/evmctl.c
index 5d1c6ea..9142ed4 100644
--- a/src/evmctl.c
+++ b/src/evmctl.c
@@ -794,6 +794,9 @@ static int verify_ima(const char *file)
 		}
 	}
 
+	if (sig[0] == IMA_XATTR_DIGEST_NG || sig[0] == IMA_XATTR_DIGEST)
+		return ima_verify_hash(file, sig, len);
+
 	return ima_verify_signature(file, sig, len, NULL, 0);
 }
 
diff --git a/src/imaevm.h b/src/imaevm.h
index f5cee7d..d624571 100644
--- a/src/imaevm.h
+++ b/src/imaevm.h
@@ -205,6 +205,7 @@ int key2bin(RSA *key, unsigned char *pub);
 int sign_hash(const char *algo, const unsigned char *hash, int size, const char *keyfile, const char *keypass, unsigned char *sig);
 int verify_hash(const unsigned char *hash, int size, unsigned char *sig, int siglen);
 int ima_verify_signature(const char *file, unsigned char *sig, int siglen, unsigned char *digest, int digestlen);
+int ima_verify_hash(const char *file, unsigned char *digest, int digestlen);
 void init_public_keys(const char *keyfiles);
 
 #endif
diff --git a/src/libimaevm.c b/src/libimaevm.c
index 247100f..bc9c496 100644
--- a/src/libimaevm.c
+++ b/src/libimaevm.c
@@ -49,6 +49,7 @@
 #include <dirent.h>
 #include <string.h>
 #include <stdio.h>
+#include <linux/hash_info.h>
 
 #include <openssl/pem.h>
 #include <openssl/evp.h>
@@ -613,6 +614,47 @@ int ima_verify_signature(const char *file, unsigned char *sig, int siglen,
 	return verify_hash(hash, hashlen, sig + 1, siglen - 1);
 }
 
+int ima_verify_hash(const char *file, unsigned char *digest, int digestlen)
+{
+	unsigned char hash[64];
+	int hashlen, hash_algo = HASH_ALGO_SHA1;
+
+	if (digest[0] == IMA_XATTR_DIGEST_NG)
+		hash_algo = digest[1]; 
+
+	if (hash_algo < 0  || hash_algo > HASH_ALGO__LAST) {
+		log_err("Invalid signature\n");
+		return -1;
+	}
+
+	/* Use hash algorithm as retrieved from xattr */
+	params.hash_algo = pkey_hash_algo[hash_algo];
+
+	hashlen = ima_calc_hash(file, hash);
+	if (hashlen <= 1)
+		return hashlen;
+
+	if (digest[0] == IMA_XATTR_DIGEST_NG) {
+		if (hashlen != digestlen - 2 ||
+		    memcmp(digest + 2, hash, hashlen)) {
+			log_err("Hash ng verification failed\n");
+			return -1;
+		}
+		log_info("Hash verification is OK\n");
+		return 0;
+	} else if (digest[0] == IMA_XATTR_DIGEST) {
+		if (hashlen != digestlen - 1 ||
+		    memcmp(digest + 1, hash, hashlen)) {
+			log_err("Hash verification failed\n");
+			return -1;
+		}
+		log_info("Hash verification is OK\n");
+		return 0;
+	}
+	log_err("Unknown security.ima format\n");
+	return -1;
+}
+
 /*
  * Create binary key representation suitable for kernel
  */
-- 
2.7.4

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

* [PATCH 10/10] ima-evm-utils: add support for validating multiple pcrs
  2018-01-22 14:53 [PATCH 00/10] ima-evm-utils Mimi Zohar
                   ` (8 preceding siblings ...)
  2018-01-22 14:54 ` [PATCH 09/10] ima-evm-utils: verify IMA file hashes stored as xattrs Mimi Zohar
@ 2018-01-22 14:54 ` Mimi Zohar
  2018-01-28 19:01 ` [PATCH 00/10] ima-evm-utils Mimi Zohar
  10 siblings, 0 replies; 12+ messages in thread
From: Mimi Zohar @ 2018-01-22 14:54 UTC (permalink / raw)
  To: linux-integrity
  Cc: Dmitry Kasatkin, Roberto Sassu, Bruno E . O . Meneguele,
	Mimi Zohar

The IMA measurement list may contain records for different PCRs.  This
patch walks the measurement list, calculating a PCR aggregate value for
each PCR.

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
 src/evmctl.c | 44 +++++++++++++++++++++++++++-----------------
 src/imaevm.h |  3 +++
 2 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/src/evmctl.c b/src/evmctl.c
index 9142ed4..5029235 100644
--- a/src/evmctl.c
+++ b/src/evmctl.c
@@ -1417,13 +1417,16 @@ int ima_ng_show(struct template_entry *entry)
 
 static int ima_measurement(const char *file)
 {
-	uint8_t pcr[SHA_DIGEST_LENGTH] = {0,};
-	uint8_t pcr10[SHA_DIGEST_LENGTH];
+	uint8_t pcr[NUM_PCRS][SHA_DIGEST_LENGTH] = {{0}};
+	uint8_t hwpcr[SHA_DIGEST_LENGTH];
 	struct template_entry entry = { .template = 0 };
 	FILE *fp;
 	int err = -1;
-	int verify_sig_failed = 0;
+	bool verify_sig_failed[NUM_PCRS] = {0,};
+	bool verify_failed = false;
+	int i;
 
+	memset(zero, 0, SHA_DIGEST_LENGTH);
 	memset(fox, 0xff, SHA_DIGEST_LENGTH);
 
 	log_debug("Initial PCR value: ");
@@ -1440,7 +1443,8 @@ static int ima_measurement(const char *file)
 		init_public_keys(params.keyfile);
 
 	while (fread(&entry.header, sizeof(entry.header), 1, fp)) {
-		ima_extend_pcr(pcr, entry.header.digest, SHA_DIGEST_LENGTH);
+		ima_extend_pcr(pcr[entry.header.pcr], entry.header.digest,
+			       SHA_DIGEST_LENGTH);
 
 		if (!fread(entry.name, entry.header.name_len, 1, fp)) {
 			log_err("Unable to read template name\n");
@@ -1472,29 +1476,35 @@ static int ima_measurement(const char *file)
 			ima_show(&entry);
 		} else {
 			if (ima_ng_show(&entry) != 0)
-				verify_sig_failed = 1;
+				verify_sig_failed[entry.header.pcr] = true;
 		}
 	}
 
-	tpm_pcr_read(10, pcr10, sizeof(pcr10));
 
-	log_info("PCRAgg: ");
-	log_dump(pcr, sizeof(pcr));
+	for (i = 0; i < NUM_PCRS; i++) {
+		if (memcmp(pcr[i], zero, SHA_DIGEST_LENGTH) == 0)
+			continue;
+
+		log_info("PCRAgg %.2d: ", i);
+		log_dump(pcr[i], SHA_DIGEST_LENGTH);
 
-	log_info("PCR-10: ");
-	log_dump(pcr10, sizeof(pcr10));
+		tpm_pcr_read(i, hwpcr, sizeof(hwpcr));
+		log_info("HW PCR-%d: ", i);
+		log_dump(hwpcr, sizeof(hwpcr));
 
-	if (memcmp(pcr, pcr10, sizeof(pcr))) {
-		log_err("PCRAgg does not match PCR-10\n");
-		goto out;
-	} else if (verify_sig_failed == 1) {
-		log_err("PCRAgg matches PCR-10, but list contains unknown keys or invalid signatures\n");
+		if (memcmp(pcr[i], hwpcr, sizeof(SHA_DIGEST_LENGTH)) != 0) {
+			log_err("PCRAgg %d does not match HW PCR-%d\n", i, i);
+
+			verify_failed = true;
+		} else if (verify_sig_failed[i] == true) {
+			log_err("PCRAgg %d matches PCR-%d, but list contains unknown keys or invalid signatures\n", i, i);
+		}
 	}
 
-	err = 0;
+	if (!verify_failed)
+		err = 0;
 out:
 	fclose(fp);
-
 	return err;
 }
 
diff --git a/src/imaevm.h b/src/imaevm.h
index d624571..0507947 100644
--- a/src/imaevm.h
+++ b/src/imaevm.h
@@ -188,6 +188,9 @@ struct RSA_ASN1_template {
 	size_t size;
 };
 
+#define	NUM_PCRS 20
+#define DEFAULT_PCR 10
+
 extern const struct RSA_ASN1_template RSA_ASN1_templates[PKEY_HASH__LAST];
 extern struct libevm_params params;
 
-- 
2.7.4

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

* Re: [PATCH 00/10] ima-evm-utils
  2018-01-22 14:53 [PATCH 00/10] ima-evm-utils Mimi Zohar
                   ` (9 preceding siblings ...)
  2018-01-22 14:54 ` [PATCH 10/10] ima-evm-utils: add support for validating multiple pcrs Mimi Zohar
@ 2018-01-28 19:01 ` Mimi Zohar
  10 siblings, 0 replies; 12+ messages in thread
From: Mimi Zohar @ 2018-01-28 19:01 UTC (permalink / raw)
  To: linux-integrity
  Cc: Dmitry Kasatkin, Roberto Sassu, Bruno E . O . Meneguele,
	James Bottomley

On Mon, 2018-01-22 at 09:53 -0500, Mimi Zohar wrote:
> Before upgrading to the new OpenSSL 1.1 API, let's clean up the code
> a bit and add some missing functionality:
> - option to specify the pcr sysfs location
> - verify the measurement list using multiple keys
> - verify the measurement list using multiple pcrs
> - verify a measurement signature against the measurement list digest
> - for completeness, extend "ima_verify" to verify the local security.ima hash

With James' "ima-evm-utils: Add backward compatible support for
openssl 1.1" patch, which supports both OpenSSL 1.0 and 1.1, there is
no rush for including all these changes now.

For example instead of specifying the pcr sysfs location, a better
solution would be for the TPM device driver to export this
information.

The next branch contains the proposed changes for ima-evm-utils
version 1.1, which I'm hoping to release within the next day or so.

thanks,

Mimi

 

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

end of thread, other threads:[~2018-01-28 19:01 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-01-22 14:53 [PATCH 00/10] ima-evm-utils Mimi Zohar
2018-01-22 14:53 ` [PATCH 01/10] ima-evm-utils: fix "ima_measurement" template fields length Mimi Zohar
2018-01-22 14:53 ` [PATCH 02/10] ima-evm-utils: revert the change to use printf instead of log_info() Mimi Zohar
2018-01-22 14:53 ` [PATCH 03/10] ima-evm-utils: fix spelling error Mimi Zohar
2018-01-22 14:53 ` [PATCH 04/10] ima-evm-utils: remove the unnecessary display of the keyid Mimi Zohar
2018-01-22 14:54 ` [PATCH 05/10] ima-evm-utils: support verifying the measurement list using multiple keys Mimi Zohar
2018-01-22 14:54 ` [PATCH 06/10] ima-evm-utils: indicate measurement list signature verification failure Mimi Zohar
2018-01-22 14:54 ` [PATCH 07/10] ima-evm-utils: add support for specifying the pcr file location Mimi Zohar
2018-01-22 14:54 ` [PATCH 08/10] ima-evm-utils: verify the measurement list signature based on the list digest Mimi Zohar
2018-01-22 14:54 ` [PATCH 09/10] ima-evm-utils: verify IMA file hashes stored as xattrs Mimi Zohar
2018-01-22 14:54 ` [PATCH 10/10] ima-evm-utils: add support for validating multiple pcrs Mimi Zohar
2018-01-28 19:01 ` [PATCH 00/10] ima-evm-utils 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).