diff mbox series

[v2,1/2] IMA: Add a test to verify measurment of keys

Message ID 20200612143842.3993-2-t-josne@linux.microsoft.com
State Superseded
Headers show
Series IMA: Key Measurement + Certificate Measurement Tests | expand

Commit Message

Lachlan Sneff June 12, 2020, 2:38 p.m. UTC
Add a testcase that verifies that the IMA subsystem has correctly
measured keys added to keyrings specified in the IMA policy file.

Additionally, add support for handling a new IMA template descriptor,
namely ima-buf[1], in the IMA measurement tests.

[1]: https://www.kernel.org/doc/html/latest/security/IMA-templates.html#use

Signed-off-by: Lachlan Sneff <t-josne@linux.microsoft.com>
---
 runtest/ima                                   |  1 +
 .../integrity/ima/datafiles/keycheck.policy   |  1 +
 .../security/integrity/ima/tests/ima_keys.sh  | 65 +++++++++++++++++++
 .../integrity/ima/tests/ima_measurements.sh   | 36 +---------
 .../integrity/ima/tests/ima_policy.sh         |  1 -
 .../security/integrity/ima/tests/ima_setup.sh | 35 ++++++++++
 6 files changed, 103 insertions(+), 36 deletions(-)
 create mode 100644 testcases/kernel/security/integrity/ima/datafiles/keycheck.policy
 create mode 100755 testcases/kernel/security/integrity/ima/tests/ima_keys.sh

Comments

Petr Vorel June 16, 2020, 3:31 p.m. UTC | #1
Hi Lachlan,

Reviewed-by: Petr Vorel <pvorel@suse.cz>

..
> +++ b/testcases/kernel/security/integrity/ima/datafiles/keycheck.policy
> @@ -0,0 +1 @@
> +measure func=KEY_CHECK keyrings=.ima|.evm|.builtin_trusted_keys|.blacklist template=ima-buf
Thanks for this!
You don't use it, but that's ok, I'll add that policy handling myself after
merging. I have some notes about documentation / setup for both commits.

It would be nice to mention CONFIG_IMA_READ_POLICY=y in
testcases/kernel/security/integrity/ima/README.md as it's required.
That trivial thing I could do myself, but it'd help to add more info for setup
needed (and it's always preferred to do the setup, if possible, but for some
tests e.g. EVM testing in evm_overlay.sh it must be during the installation).

> diff --git a/testcases/kernel/security/integrity/ima/tests/ima_keys.sh b/testcases/kernel/security/integrity/ima/tests/ima_keys.sh
> new file mode 100755
> index 000000000..f9c60a6fc
> --- /dev/null
> +++ b/testcases/kernel/security/integrity/ima/tests/ima_keys.sh
> @@ -0,0 +1,65 @@
> +#!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# Copyright (c) 2020 Microsoft Corporation
> +# Author: Lachlan Sneff <t-josne@linux.microsoft.com>
Reviewed-by: Petr Vorel <pvorel@suse.cz>
> +#
> +# Verify that keys are measured correctly based on policy.
> +
> +TST_NEEDS_CMDS="awk cut xxd"
nit: actually sed was meant to be added in this commit (I reported in previous
one).

Kind regards,
Petr
Petr Vorel June 19, 2020, 8:56 a.m. UTC | #2
Hi Lachlan,

...
> +	keycheck_line=$(grep "func=KEY_CHECK" $IMA_POLICY)
> +	if [ -z "$keycheck_line" ]; then
> +		tst_brk TCONF "ima policy does not specify \"func=KEY_CHECK\""
> +	fi
> +
> +	if echo "$keycheck_line" | grep -q "*keyrings*"; then
I guess "*keyrings*" as grep parameter is wrong. * for regexp should be .*
If you meant to grep for keyrings, it should be:
if ! echo "$keycheck_line" | grep -q "keyrings"; then
	tst_brk TCONF "ima policy does not specify a keyrings to check"
fi

Few more changes (mostly nits), is that ok for you?

Kind regards,
Petr

diff --git testcases/kernel/security/integrity/ima/README.md testcases/kernel/security/integrity/ima/README.md
index 16a1f48c3..66d0f5308 100644
--- testcases/kernel/security/integrity/ima/README.md
+++ testcases/kernel/security/integrity/ima/README.md
@@ -16,6 +16,24 @@ CONFIG_INTEGRITY=y
 CONFIG_IMA=y
 ```
 
+IMA Key Import tests
+~~~~~~~~~~~~~~~~~~~~
+
+`ima_keys.sh` requires a x509 public key, by default in `/etc/keys/x509_ima.der`.
+The key must be signed by the private key you generate. Follow these instructions:
+https://manpages.ubuntu.com/manpages/disco/man1/evmctl.1.html#generate%20trusted%20keys.
+
+The test cannot be set-up automatically because the kernel must be built
+with one of the keys you generate.
+
+As well as what's required for the IMA tests, the following are also required
+in the kernel configuration:
+```
+CONFIG_IMA_READ_POLICY=y
+CONFIG_SYSTEM_TRUSTED_KEYRING=y
+CONFIG_SYSTEM_TRUSTED_KEYS="/etc/keys/ima-local-ca.pem"
+```
+
 EVM tests
 ---------
 
diff --git testcases/kernel/security/integrity/ima/tests/ima_keys.sh testcases/kernel/security/integrity/ima/tests/ima_keys.sh
index 2b5324dbf..398ee141c 100755
--- testcases/kernel/security/integrity/ima/tests/ima_keys.sh
+++ testcases/kernel/security/integrity/ima/tests/ima_keys.sh
@@ -5,17 +5,18 @@
 #
 # Verify that keys are measured correctly based on policy.
 
-TST_NEEDS_CMDS="grep mktemp cut sed tr"
+TST_NEEDS_CMDS="cut grep sed tr xxd"
 TST_CNT=1
 TST_NEEDS_DEVICE=1
 
 . ima_setup.sh
 
-# Based on https://lkml.org/lkml/2019/12/13/564.
+# Based on https://lkml.org/lkml/2019/12/13/564
 # (450d0fd51564 - "IMA: Call workqueue functions to measure queued keys")
 test1()
 {
-	local keyrings keycheck_line templates test_file=$(mktemp)
+	local err keycheck_line keyrings line templates
+	local test_file="file.txt"
 
 	tst_res TINFO "verifying key measurement for keyrings and templates specified in IMA policy file"
 
@@ -28,7 +29,7 @@ test1()
 		tst_brk TCONF "ima policy does not specify \"func=KEY_CHECK\""
 	fi
 
-	if echo "$keycheck_line" | grep -q "*keyrings*"; then
+	if ! echo "$keycheck_line" | grep -q "keyrings"; then
 		tst_brk TCONF "ima policy does not specify a keyrings to check"
 	fi
 
@@ -41,12 +42,12 @@ test1()
 	templates=$(echo "$keycheck_line" | tr " " "\n" | grep "template" | \
 		cut -d'=' -f2)
 
-	grep -E "($templates)*($keyrings)" $ASCII_MEASUREMENTS | while read line
+	grep -E "($templates)*$keyrings" $ASCII_MEASUREMENTS | while read line
 	do
-		local digest expected_digest algorithm
+		local algorithm digest expected_digest keyring
 
-		digest=$(echo "$line" | cut -d' ' -f4 | cut -d':' -f2)
 		algorithm=$(echo "$line" | cut -d' ' -f4 | cut -d':' -f1)
+		digest=$(echo "$line" | cut -d' ' -f4 | cut -d':' -f2)
 		keyring=$(echo "$line" | cut -d' ' -f5)
 
 		echo "$line" | cut -d' ' -f6 | xxd -r -p > $test_file
@@ -56,12 +57,12 @@ test1()
 
 		if [ "$digest" != "$expected_digest" ]; then
 			tst_res TFAIL "incorrect digest was found for the ($keyring) keyring"
+			err=1
 		fi
 	done
 
-	rm $test_file
-
-	tst_res TPASS "specified keyrings were measured correctly"
+	[ -z "$err" ] && \
+		tst_res TPASS "specified keyrings were measured correctly"
 }
 
 tst_run
diff mbox series

Patch

diff --git a/runtest/ima b/runtest/ima
index f3ea88cf0..309d47420 100644
--- a/runtest/ima
+++ b/runtest/ima
@@ -3,4 +3,5 @@  ima_measurements ima_measurements.sh
 ima_policy ima_policy.sh
 ima_tpm ima_tpm.sh
 ima_violations ima_violations.sh
+ima_keys ima_keys.sh
 evm_overlay evm_overlay.sh
diff --git a/testcases/kernel/security/integrity/ima/datafiles/keycheck.policy b/testcases/kernel/security/integrity/ima/datafiles/keycheck.policy
new file mode 100644
index 000000000..3f1934a3d
--- /dev/null
+++ b/testcases/kernel/security/integrity/ima/datafiles/keycheck.policy
@@ -0,0 +1 @@ 
+measure func=KEY_CHECK keyrings=.ima|.evm|.builtin_trusted_keys|.blacklist template=ima-buf
diff --git a/testcases/kernel/security/integrity/ima/tests/ima_keys.sh b/testcases/kernel/security/integrity/ima/tests/ima_keys.sh
new file mode 100755
index 000000000..f9c60a6fc
--- /dev/null
+++ b/testcases/kernel/security/integrity/ima/tests/ima_keys.sh
@@ -0,0 +1,65 @@ 
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2020 Microsoft Corporation
+# Author: Lachlan Sneff <t-josne@linux.microsoft.com>
+#
+# Verify that keys are measured correctly based on policy.
+
+TST_NEEDS_CMDS="awk cut xxd"
+TST_CNT=1
+TST_NEEDS_DEVICE=1
+
+. ima_setup.sh
+
+# Based on https://lkml.org/lkml/2019/12/13/564.
+# (450d0fd51564 - "IMA: Call workqueue functions to measure queued keys")
+test1()
+{
+	local keyrings keycheck_line templates test_file="$PWD/test.txt"
+
+	tst_res TINFO "verifying key measurement for keyrings and templates specified in IMA policy file"
+
+	[ -f $IMA_POLICY ] || tst_brk TCONF "missing $IMA_POLICY"
+
+	[ -r $IMA_POLICY ] || tst_brk TCONF "cannot read IMA policy (CONFIG_IMA_READ_POLICY=y required)"
+
+	keycheck_line=$(grep "func=KEY_CHECK" $IMA_POLICY)
+	if [ -z "$keycheck_line" ]; then
+		tst_brk TCONF "ima policy does not specify \"func=KEY_CHECK\""
+	fi
+
+	if echo "$keycheck_line" | grep -q "*keyrings*"; then
+		tst_brk TCONF "ima policy does not specify a keyrings to check"
+	fi
+
+	keyrings=$(echo "$keycheck_line" | tr " " "\n" | grep "keyrings" | \
+		sed "s/\./\\\./g" | cut -d'=' -f2)
+	if [ -z "$keyrings" ]; then
+		tst_brk TCONF "ima policy has a keyring key-value specifier, but no specified keyrings"
+	fi
+
+	templates=$(echo "$keycheck_line" | tr " " "\n" | grep "template" | \
+		cut -d'=' -f2)
+
+	grep -E "($templates)*($keyrings)" $ASCII_MEASUREMENTS | while read line
+	do
+		local digest expected_digest algorithm
+
+		digest=$(echo "$line" | cut -d' ' -f4 | cut -d':' -f2)
+		algorithm=$(echo "$line" | cut -d' ' -f4 | cut -d':' -f1)
+		keyring=$(echo "$line" | cut -d' ' -f5)
+
+		echo "$line" | cut -d' ' -f6 | xxd -r -p > $test_file
+
+		expected_digest="$(compute_digest $algorithm $test_file)" || \
+			tst_brk TCONF "cannot compute digest for $algorithm"
+
+		if [ "$digest" != "$expected_digest" ]; then
+			tst_res TFAIL "incorrect digest was found for the ($keyring) keyring"
+		fi
+	done
+
+	tst_res TPASS "specified keyrings were measured correctly"
+}
+
+tst_run
diff --git a/testcases/kernel/security/integrity/ima/tests/ima_measurements.sh b/testcases/kernel/security/integrity/ima/tests/ima_measurements.sh
index 54237d688..04d8e6353 100755
--- a/testcases/kernel/security/integrity/ima/tests/ima_measurements.sh
+++ b/testcases/kernel/security/integrity/ima/tests/ima_measurements.sh
@@ -28,7 +28,7 @@  setup()
 	# parse digest index
 	# https://www.kernel.org/doc/html/latest/security/IMA-templates.html#use
 	case "$template" in
-	ima|ima-ng|ima-sig) DIGEST_INDEX=4 ;;
+	ima|ima-ng|ima-sig|ima-buf) DIGEST_INDEX=4 ;;
 	*)
 		# using ima_template_fmt kernel parameter
 		local IFS="|"
@@ -46,40 +46,6 @@  setup()
 		"Cannot find digest index (template: '$template')"
 }
 
-# TODO: find support for rmd128 rmd256 rmd320 wp256 wp384 tgr128 tgr160
-compute_digest()
-{
-	local algorithm="$1"
-	local file="$2"
-	local digest
-
-	digest="$(${algorithm}sum $file 2>/dev/null | cut -f1 -d ' ')"
-	if [ -n "$digest" ]; then
-		echo "$digest"
-		return 0
-	fi
-
-	digest="$(openssl $algorithm $file 2>/dev/null | cut -f2 -d ' ')"
-	if [ -n "$digest" ]; then
-		echo "$digest"
-		return 0
-	fi
-
-	# uncommon ciphers
-	local arg="$algorithm"
-	case "$algorithm" in
-	tgr192) arg="tiger" ;;
-	wp512) arg="whirlpool" ;;
-	esac
-
-	digest="$(rdigest --$arg $file 2>/dev/null | cut -f1 -d ' ')"
-	if [ -n "$digest" ]; then
-		echo "$digest"
-		return 0
-	fi
-	return 1
-}
-
 ima_check()
 {
 	local delimiter=':'
diff --git a/testcases/kernel/security/integrity/ima/tests/ima_policy.sh b/testcases/kernel/security/integrity/ima/tests/ima_policy.sh
index 6286277b4..244cf081d 100755
--- a/testcases/kernel/security/integrity/ima/tests/ima_policy.sh
+++ b/testcases/kernel/security/integrity/ima/tests/ima_policy.sh
@@ -23,7 +23,6 @@  check_policy_writable()
 
 setup()
 {
-	IMA_POLICY="$IMA_DIR/policy"
 	check_policy_writable
 
 	VALID_POLICY="$TST_DATAROOT/measure.policy"
diff --git a/testcases/kernel/security/integrity/ima/tests/ima_setup.sh b/testcases/kernel/security/integrity/ima/tests/ima_setup.sh
index 58a12eda3..8ae477c1c 100644
--- a/testcases/kernel/security/integrity/ima/tests/ima_setup.sh
+++ b/testcases/kernel/security/integrity/ima/tests/ima_setup.sh
@@ -20,6 +20,40 @@  SYSFS="/sys"
 UMOUNT=
 TST_FS_TYPE="ext3"
 
+# TODO: find support for rmd128 rmd256 rmd320 wp256 wp384 tgr128 tgr160
+compute_digest()
+{
+	local algorithm="$1"
+	local file="$2"
+	local digest
+
+	digest="$(${algorithm}sum $file 2>/dev/null | cut -f1 -d ' ')"
+	if [ -n "$digest" ]; then
+		echo "$digest"
+		return 0
+	fi
+
+	digest="$(openssl $algorithm $file 2>/dev/null | cut -f2 -d ' ')"
+	if [ -n "$digest" ]; then
+		echo "$digest"
+		return 0
+	fi
+
+	# uncommon ciphers
+	local arg="$algorithm"
+	case "$algorithm" in
+	tgr192) arg="tiger" ;;
+	wp512) arg="whirlpool" ;;
+	esac
+
+	digest="$(rdigest --$arg $file 2>/dev/null | cut -f1 -d ' ')"
+	if [ -n "$digest" ]; then
+		echo "$digest"
+		return 0
+	fi
+	return 1
+}
+
 check_ima_policy()
 {
 	local policy="$1"
@@ -85,6 +119,7 @@  ima_setup()
 	[ -d "$IMA_DIR" ] || tst_brk TCONF "IMA not enabled in kernel"
 	ASCII_MEASUREMENTS="$IMA_DIR/ascii_runtime_measurements"
 	BINARY_MEASUREMENTS="$IMA_DIR/binary_runtime_measurements"
+	IMA_POLICY="$IMA_DIR/policy"
 
 	print_ima_config