File: security.sh

package info (click to toggle)
ndctl 82-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,460 kB
  • sloc: ansic: 42,027; sh: 3,974; makefile: 28
file content (265 lines) | stat: -rwxr-xr-x 5,726 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
#!/bin/bash -Ex
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2018-2020 Intel Corporation. All rights reserved.

rc=77
dev=""
id=""
keypath="/etc/ndctl/keys"
masterkey="nvdimm-master"
masterpath="$keypath/$masterkey.blob"
backup_key=0
backup_handle=0

. $(dirname $0)/common

trap 'err $LINENO' ERR

setup()
{
	$NDCTL disable-region -b "$TEST_BUS" all
}

setup_keys()
{
	if [ ! -d "$keypath" ]; then
		mkdir -p "$keypath"
	fi

	if [ -f "$masterpath" ]; then
		mv "$masterpath" "$masterpath.bak"
		backup_key=1
	fi
	if [ -f "$keypath/tpm.handle" ]; then
		mv "$keypath/tpm.handle" "$keypath/tpm.handle.bak"
		backup_handle=1
	fi

	# Make sure there is a session and a user keyring linked into it
	keyctl new_session
	keyctl link @u @s
	dd if=/dev/urandom bs=1 count=32 2>/dev/null | keyctl padd user "$masterkey" @u
	keyctl pipe "$(keyctl search @u user $masterkey)" > "$masterpath"
}

test_cleanup()
{
	if keyctl search @u encrypted nvdimm:"$id"; then
		keyctl unlink "$(keyctl search @u encrypted nvdimm:"$id")"
	fi

	if keyctl search @u user "$masterkey"; then
		keyctl unlink "$(keyctl search @u user "$masterkey")"
	fi

	if [ -f "$keypath"/nvdimm_"$id"_"$(hostname)".blob ]; then
		rm -f "$keypath"/nvdimm_"$id"_"$(hostname)".blob
	fi
}

post_cleanup()
{
	if [ -f $masterpath ]; then
		rm -f "$masterpath"
	fi
	if [ "$backup_key" -eq 1 ]; then
		mv "$masterpath.bak" "$masterpath"
	fi
	if [ "$backup_handle" -eq 1 ]; then
		mv "$keypath/tpm.handle.bak" "$keypath/tpm.handle"
	fi
}

get_frozen_state()
{
	$NDCTL list -i -b "$TEST_BUS" -d "$dev" | jq -r .[].dimms[0].security_frozen
}

get_security_state()
{
	$NDCTL list -i -b "$TEST_BUS" -d "$dev" | jq -r .[].dimms[0].security
}

setup_passphrase()
{
	$NDCTL setup-passphrase "$dev" -k user:"$masterkey"
	sstate="$(get_security_state)"
	if [ "$sstate" != "unlocked" ]; then
		echo "Incorrect security state: $sstate expected: unlocked"
		err "$LINENO"
	fi
}

remove_passphrase()
{
	$NDCTL remove-passphrase "$dev"
	sstate="$(get_security_state)"
	if [ "$sstate" != "disabled" ]; then
		echo "Incorrect security state: $sstate expected: disabled"
		err "$LINENO"
	fi
}

erase_security()
{
	$NDCTL sanitize-dimm -c "$dev"
	sstate="$(get_security_state)"
	if [ "$sstate" != "disabled" ]; then
		echo "Incorrect security state: $sstate expected: disabled"
		err "$LINENO"
	fi
}

update_security()
{
	$NDCTL update-passphrase "$dev"
	sstate="$(get_security_state)"
	if [ "$sstate" != "unlocked" ]; then
		echo "Incorrect security state: $sstate expected: unlocked"
		err "$LINENO"
	fi
}

freeze_security()
{
	$NDCTL freeze-security "$dev"
}

test_1_security_setup_and_remove()
{
	setup_passphrase
	remove_passphrase
}

test_2_security_setup_and_update()
{
	setup_passphrase
	update_security
	remove_passphrase
}

test_3_security_setup_and_erase()
{
	setup_passphrase
	erase_security
}

test_4_security_unlock()
{
	setup_passphrase
	lock_dimm
	$NDCTL enable-dimm "$dev"
	sstate="$(get_security_state)"
	if [ "$sstate" != "unlocked" ]; then
		echo "Incorrect security state: $sstate expected: unlocked"
		err "$LINENO"
	fi
	$NDCTL disable-region -b "$TEST_BUS" all
	remove_passphrase
}

# This should always be the last nvdimm security test.
# with security frozen, nfit_test must be removed and is no longer usable
test_5_security_freeze()
{
	setup_passphrase
	freeze_security
	sstate="$(get_security_state)"
	fstate="$(get_frozen_state)"
	if [ "$fstate" != "true" ]; then
		echo "Incorrect security state: expected: frozen"
		err "$LINENO"
	fi
	$NDCTL remove-passphrase "$dev" && { echo "remove succeed after frozen"; }
	sstate2="$(get_security_state)"
	if [ "$sstate" != "$sstate2" ]; then
		echo "Incorrect security state: $sstate2 expected: $sstate"
		err "$LINENO"
	fi
}

test_6_load_keys()
{
	if keyctl search @u encrypted nvdimm:"$id"; then
		keyctl unlink "$(keyctl search @u encrypted nvdimm:"$id")"
	fi

	if keyctl search @u user "$masterkey"; then
		keyctl unlink "$(keyctl search @u user "$masterkey")"
	fi

	$NDCTL load-keys

	if keyctl search @u user "$masterkey"; then
		echo "master key loaded"
	else
		echo "master key failed to loaded"
		err "$LINENO"
	fi

	if keyctl search @u encrypted nvdimm:"$id"; then
		echo "dimm key loaded"
	else
		echo "dimm key failed to load"
		err "$LINENO"
	fi
}

if [ "$1" = "nfit" ]; then
	. $(dirname $0)/nfit-security
	TEST_BUS="$NFIT_TEST_BUS0"
	check_min_kver "5.0" || do_skip "may lack security handling"
	KMOD_TEST="nfit_test"
elif [ "$1" = "cxl" ]; then
	. $(dirname $0)/cxl-security
	TEST_BUS="$CXL_TEST_BUS"
	check_min_kver "6.2" || do_skip "may lack security handling"
	KMOD_TEST="cxl_test"
else
	do_skip "Missing input parameters"
fi

check_prereq "keyctl"
check_prereq "jq"

uid="$(keyctl show | grep -Eo "_uid.[0-9]+" | head -1 | cut -d. -f2-)"
if [ "$uid" -ne 0 ]; then
	do_skip "run as root or with a sudo login shell for test to work"
fi

modprobe "$KMOD_TEST"
$CXL list
setup
rc=1
detect
test_cleanup
setup_keys
echo "Test 1, security setup and remove"
test_1_security_setup_and_remove
echo "Test 2, security setup, update, and remove"
test_2_security_setup_and_update
echo "Test 3, security setup and erase"
test_3_security_setup_and_erase
echo "Test 4, unlock dimm"
test_4_security_unlock

# Freeze should always be the last nvdimm security test because it locks
# security state and require nfit_test module unload. However, this does
# not impact any key management testing via libkeyctl.
echo "Test 5, freeze security"
test_5_security_freeze

# Load-keys is independent of actual nvdimm security and is part of key
# mangement testing.
echo "Test 6, test load-keys"
test_6_load_keys

test_cleanup
post_cleanup
if [ "$1" = "nfit" ]; then
	_cleanup
elif [ "$1" = "cxl" ]; then
	_cxl_cleanup
fi

exit 0