• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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