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