1#!/bin/sh 2# SPDX-License-Identifier: GPL-2.0-or-later 3# Copyright (c) 2020 Microsoft Corporation 4# Copyright (c) 2020-2021 Petr Vorel <pvorel@suse.cz> 5# Author: Lachlan Sneff <t-josne@linux.microsoft.com> 6# 7# Verify that keys are measured correctly based on policy. 8 9TST_NEEDS_CMDS="cmp cut grep sed" 10TST_CNT=2 11TST_NEEDS_DEVICE=1 12TST_SETUP=setup 13TST_CLEANUP=cleanup 14 15. ima_setup.sh 16 17FUNC_KEYCHECK='func=KEY_CHECK' 18REQUIRED_POLICY="^measure.*$FUNC_KEYCHECK" 19 20setup() 21{ 22 require_ima_policy_content "$REQUIRED_POLICY" '-E' > $TST_TMPDIR/policy.txt 23 require_valid_policy_template 24} 25 26cleanup() 27{ 28 tst_is_num $KEYRING_ID && keyctl clear $KEYRING_ID 29} 30 31 32require_valid_policy_template() 33{ 34 while read line; do 35 if echo $line | grep -q 'template=' && ! echo $line | grep -q 'template=ima-buf'; then 36 tst_brk TCONF "only template=ima-buf can be specified for KEY_CHECK" 37 fi 38 done < $TST_TMPDIR/policy.txt 39} 40 41check_keys_policy() 42{ 43 local pattern="$1" 44 45 if ! grep -E "$pattern" $TST_TMPDIR/policy.txt; then 46 tst_res TCONF "IMA policy must specify $pattern, $FUNC_KEYCHECK" 47 return 1 48 fi 49 return 0 50} 51 52# Based on https://lkml.org/lkml/2019/12/13/564. 53# (450d0fd51564 - "IMA: Call workqueue functions to measure queued keys") 54test1() 55{ 56 local keycheck_lines i keyrings templates 57 local pattern='keyrings=[^[:space:]]+' 58 local test_file="file.txt" tmp_file="file2.txt" 59 60 tst_res TINFO "verify key measurement for keyrings and templates specified in IMA policy" 61 62 check_keys_policy "$pattern" > $tmp_file || return 63 keycheck_lines=$(cat $tmp_file) 64 keyrings=$(for i in $keycheck_lines; do echo "$i" | grep "keyrings" | \ 65 sed "s/\./\\\./g" | cut -d'=' -f2; done | sed ':a;N;$!ba;s/\n/|/g') 66 if [ -z "$keyrings" ]; then 67 tst_res TCONF "IMA policy has a keyring key-value specifier, but no specified keyrings" 68 return 69 fi 70 71 templates=$(for i in $keycheck_lines; do echo "$i" | grep "template" | \ 72 cut -d'=' -f2; done | sed ':a;N;$!ba;s/\n/|/g') 73 74 tst_res TINFO "keyrings: '$keyrings'" 75 tst_res TINFO "templates: '$templates'" 76 77 grep -E "($templates).*($keyrings)" $ASCII_MEASUREMENTS | while read line 78 do 79 local digest expected_digest algorithm 80 81 digest=$(echo "$line" | cut -d' ' -f4 | cut -d':' -f2) 82 algorithm=$(echo "$line" | cut -d' ' -f4 | cut -d':' -f1) 83 keyring=$(echo "$line" | cut -d' ' -f5) 84 85 echo "$line" | cut -d' ' -f6 | tst_hexdump -d > $test_file 86 87 if ! expected_digest="$(compute_digest $algorithm $test_file)"; then 88 tst_res TCONF "cannot compute digest for $algorithm" 89 return 90 fi 91 92 if [ "$digest" != "$expected_digest" ]; then 93 tst_res TFAIL "incorrect digest was found for $keyring keyring" 94 return 95 fi 96 done 97 98 tst_res TPASS "specified keyrings were measured correctly" 99} 100 101# Create a new keyring, import a certificate into it, and verify 102# that the certificate is measured correctly by IMA. 103test2() 104{ 105 tst_require_cmds keyctl openssl 106 107 require_evmctl "1.3.2" 108 109 local cert_file="$TST_DATAROOT/x509_ima.der" 110 local keyring_name="key_import_test" 111 local pattern="keyrings=[^[:space:]]*$keyring_name" 112 local temp_file="file.txt" 113 114 tst_res TINFO "verify measurement of certificate imported into a keyring" 115 116 check_keys_policy "$pattern" >/dev/null || return 117 118 KEYRING_ID=$(keyctl newring $keyring_name @s) || \ 119 tst_brk TBROK "unable to create a new keyring" 120 121 if ! tst_is_num $KEYRING_ID; then 122 tst_brk TBROK "unable to parse the new keyring id ('$KEYRING_ID')" 123 fi 124 125 evmctl import $cert_file $KEYRING_ID > /dev/null || \ 126 tst_brk TBROK "unable to import a certificate into $keyring_name keyring" 127 128 grep $keyring_name $ASCII_MEASUREMENTS | tail -n1 | cut -d' ' -f6 | \ 129 tst_hexdump -d > $temp_file 130 131 if [ ! -s $temp_file ]; then 132 tst_res TFAIL "keyring $keyring_name not found in $ASCII_MEASUREMENTS" 133 return 134 fi 135 136 if ! openssl x509 -in $temp_file -inform der > /dev/null; then 137 tst_res TFAIL "logged certificate is not a valid x509 certificate" 138 return 139 fi 140 141 if cmp -s $temp_file $cert_file; then 142 tst_res TPASS "logged certificate matches the original" 143 else 144 tst_res TFAIL "logged certificate does not match original" 145 fi 146} 147 148tst_run 149