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