From: David Jacobson <djacobs7@xxxxxxxxxxxxxx> IMA can be configured to require signatures on policies before loading them. This test verifies that IMA correctly validates signatures, and rejects policies that lack signatures or have been signed by an unauthorized party (i.e. certificate is not on the appropriate keyring). This test requires root privileges in order to write to securityfs files. Signed-off-by: David Jacobson <djacobs7@xxxxxxxxxxxxxx> Changelog: * Placed policy_sig on list of tests * make sure key exists * shellcheck compliant * Update makefiles with tests instead of functions * removed begin * removed long opts * Notes file is updated in correct patch * restructure to use functions * reword usage * reworded patch title * Fixed changes in Notes * renamed key * Cut down on functions --- evmtest/Makefile.am | 6 +- evmtest/README | 1 + evmtest/evmtest | 1 + evmtest/files/Notes | 16 +++ evmtest/files/policies/signed_policy | 2 + evmtest/files/policies/unknown_signed_policy | 1 + evmtest/files/policies/unsigned_policy | 1 + evmtest/tests/policy_sig.sh | 110 +++++++++++++++++++ evmtest/unknown_privkey_ima.pem | 16 +++ 9 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 evmtest/files/policies/signed_policy create mode 100644 evmtest/files/policies/unknown_signed_policy create mode 100644 evmtest/files/policies/unsigned_policy create mode 100755 evmtest/tests/policy_sig.sh create mode 100644 evmtest/unknown_privkey_ima.pem diff --git a/evmtest/Makefile.am b/evmtest/Makefile.am index e74feaf..496a5de 100644 --- a/evmtest/Makefile.am +++ b/evmtest/Makefile.am @@ -14,9 +14,13 @@ evmtest.1: install: install -m 755 evmtest $(bindir) install -d $(datarootdir)/evmtest/files/ + install -d $(datarootdir)/evmtest/files/policies install -d $(datarootdir)/evmtest/tests/ - install -D $$(find ./files/ -not -type d) $(datarootdir)/evmtest/files/ + install -D \ + $$(find ./files/ -not -type d -not -path "./files/policies/*") \ + $(datarootdir)/evmtest/files/ install -D ./tests/* $(datarootdir)/evmtest/tests/ + install -D ./files/policies/* $(datarootdir)/evmtest/files/policies/ cp evmtest.1 $(datarootdir)/man/man1 mandb -q diff --git a/evmtest/README b/evmtest/README index 5a44070..480f426 100644 --- a/evmtest/README +++ b/evmtest/README @@ -38,6 +38,7 @@ TEST NAMES env_validate - verify kernel build example_test - example test + policy_sig - verify loading IMA policies Introduction diff --git a/evmtest/evmtest b/evmtest/evmtest index d579d03..9902e61 100755 --- a/evmtest/evmtest +++ b/evmtest/evmtest @@ -28,6 +28,7 @@ usage (){ # placement of a script in tests/ echo "[R] env_validate" echo "[ ] examples_test" + echo "[R] policy_sig" echo "" echo "Note: Tests may be run directly from the \"tests\" directory" diff --git a/evmtest/files/Notes b/evmtest/files/Notes index f20a272..8aa2670 100644 --- a/evmtest/files/Notes +++ b/evmtest/files/Notes @@ -3,3 +3,19 @@ This file contains a description of the contents of this directory. 1. common.sh This file contains useful functions and variables for evmtest scripts. + +2. load_policy.sh + +This is a script to load policies. The first time this is called, it will +replace the existing policy. Subsequent calls will append additional rules to +the existing policy. + +3. policies/ + +This is a directory that contains IMA policies with self explanatory names. + +4. unknown_privkey_ima.pem + +This file was generated such that its corresponding public key could be placed +on the IMA Trusted Keyring, however, it has not. Therefore, any policy (or file) +signed by this key cannot be verified, and is untrusted. diff --git a/evmtest/files/policies/signed_policy b/evmtest/files/policies/signed_policy new file mode 100644 index 0000000..87828f0 --- /dev/null +++ b/evmtest/files/policies/signed_policy @@ -0,0 +1,2 @@ +measure func=POLICY_CHECK +appraise func=POLICY_CHECK appraise_type=imasig diff --git a/evmtest/files/policies/unknown_signed_policy b/evmtest/files/policies/unknown_signed_policy new file mode 100644 index 0000000..1f8f8f4 --- /dev/null +++ b/evmtest/files/policies/unknown_signed_policy @@ -0,0 +1 @@ +audit func=POLICY_CHECK diff --git a/evmtest/files/policies/unsigned_policy b/evmtest/files/policies/unsigned_policy new file mode 100644 index 0000000..1f8f8f4 --- /dev/null +++ b/evmtest/files/policies/unsigned_policy @@ -0,0 +1 @@ +audit func=POLICY_CHECK diff --git a/evmtest/tests/policy_sig.sh b/evmtest/tests/policy_sig.sh new file mode 100755 index 0000000..174d111 --- /dev/null +++ b/evmtest/tests/policy_sig.sh @@ -0,0 +1,110 @@ +#!/bin/bash +TEST="policy_sig" +# Author: David Jacobson <davidj@xxxxxxxxxxxxx> + +ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )/.." +#shellcheck source=/usr/local/share/evmtest/files/common.sh +source "$ROOT"/files/common.sh + +VERBOSE=0 +POLICY_LOAD="$ROOT"/files/load_policy.sh +# This test validates that IMA measures and appraises policies. +usage() { + echo "" + echo "policy_sig -k <key> [-vh]" + echo "" + echo " This test first loads a policy requiring all subsequent" + echo " policies to be signed, and verifies that only signed policies" + echo " may then be loaded." + echo "" + echo " Loading policy rules requires root privilege. This test must be" + echo " executed as root." + echo "" + echo " -k The key for the certificate on the IMA keyring" + echo " -h Display this help message" + echo " -v Verbose logging" +} + +parse_args () { + TEMP=$(getopt -o 'k:hv' -n 'policy_sig' -- "$@") + eval set -- "$TEMP" + + while true ; do + case "$1" in + -h) usage; exit 0; shift;; + -k) IMA_KEY=$2; shift 2;; + -v) VERBOSE=1; shift;; + --) shift; break;; + *) echo "[*] Unrecognized option $1"; exit 1 ;; + esac + done + + if [ -z "$IMA_KEY" ]; then + usage + exit 1 + fi + + if [ ! -f "$IMA_KEY" ]; then + cleanup + fail "Missing key" + fi +} + +load_signed_policy () { + v_out "Signing policy with provided key..." + if ! evmctl ima_sign -f "$POLICY_PATH" -k "$IMA_KEY" &>> /dev/null; then + cleanup + fail "Failed to sign policy - check key file" + fi + + v_out "Loading policy..." + if ! "$POLICY_LOAD" signed_policy &>> /dev/null; then + cleanup + fail "Failed to write policy. " + fi + v_out "Loaded" +} + +load_unsigned_policy () { + v_out "Attempting to load unsigned policy..." + if "$POLICY_LOAD" unsigned_policy &>> /dev/null; then + cleanup + fail "Failed to reject unsigned policy" + fi + + v_out "IMA Blocked unsigned policy" +} + +load_unknown_key_policy () { + v_out "Signing policy with invalid key..." + evmctl ima_sign -f "$ROOT"/files/policies/unknown_signed_policy \ + -k "$ROOT"/files/unknown_privkey_ima.pem &>> /dev/null + + v_out "Attempting to load policy signed by invalid key..." + if "$POLICY_LOAD" unknown_signed_policy &>> /dev/null; then + cleanup + fail "Failed to reject policy signed by unknown key" + fi + + v_out "IMA blocked policy signed by unknown key" +} + +cleanup () { + v_out "Removing security.ima attribute from policies..." + setfattr -x security.ima "$ROOT"/files/policies/unsigned_policy &>> \ + /dev/null + setfattr -x security.ima "$ROOT"/files/policies/unknown_signed_policy \ + &>> /dev/null + v_out "Done" +} + +POLICY_PATH="$ROOT"/files/policies/signed_policy + +EVMTEST_require_root +echo "[*] Starting test: $TEST" +parse_args "$@" +load_signed_policy +load_unsigned_policy +load_unknown_key_policy +cleanup +passed diff --git a/evmtest/unknown_privkey_ima.pem b/evmtest/unknown_privkey_ima.pem new file mode 100644 index 0000000..dcc0e24 --- /dev/null +++ b/evmtest/unknown_privkey_ima.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMOnki6OKMHExpH1 +IWgUlPWWSbsDpW1lpqXMj0/ZWo9xU5W2xZC53TVArUGOImQ5PcMNkw1VcHhKbFKO +jYT0gEE0Sv+VbePiEnhUheFOWUxNNFE3DVQaOpBN0OzsUCSGX9RKIIwkIAwJkvWA +MHzR4ZPQGGM9hMJKhEvlTG4PP96LAgMBAAECgYBKVKVCrptpUhqmZNx2MCuPSbNl +KzNz5kRzhM2FZmvzRvicTj2siBA0JQgteZQzQ1PlgIi3bhg2ev/ANYwqUMFQWZv9 +zm5d4P7Zsdyle15MDTSrQIaroeb1nbfNvaB0L4D4Inv0p6ksyIFp7TR5MLVenC5k +bxfESVWVPDseiAFKUQJBAPQ/x3LmnT0RiMeX6quCGAON7DGpV5KFwL97luWO6vH+ +qZ2W1/J0UxTbruv7rA+tj3ZXpdNOxfmq+JStY0jrJV0CQQDNEUqomnA183rX0dv8 +MWyOPmX0Z9SMSTRvflNRW85Bzbosq68uLTq3qOBj+td9zUlopsLpJlfF0Vc+moff +uq0HAkEAi/Sz47oTZXfTqZL6TBZ6jibXrck8PeBYhyBZYebX55ymMn/J88sGBFCx +VdVbTYyFRSmKAqADv0FhuUf1OUZMnQJAOayjUsgcxw+zfP+I32UHIvppslOBc/Mi +zDi7Niab2+YAdo/StSoDWaQld/kUok0aWFSOfQRLq1c1MmZD0KiwAQJANY0LopqG +pxACc4/QawxtBoV1a8j5Zui8LZPRtKwjkA30Nq8fOufzMuBeJIlLap45uD1xC7St +bsPWG5+uz18e5w== +-----END PRIVATE KEY----- -- 2.20.1