]> git.proxmox.com Git - swtpm.git/blob - tests/test_samples_create_tpmca
Move swtpm_localca sources from samples/ to src/
[swtpm.git] / tests / test_samples_create_tpmca
1 #!/usr/bin/env bash
2 #set -x
3
4 # For the license, see the LICENSE file in the root directory.
5
6 if [ "$(id -u)" -ne 0 ]; then
7 echo "Need to be root to run this test."
8 exit 77
9 fi
10
11 # tpmtool is not packaged everywhere ...
12 if [ -z "$(type -P tpmtool)" ]; then
13 echo "Could not find tpmtool in PATH"
14 exit 77
15 fi
16
17 ROOT=${abs_top_builddir:-$(dirname "$0")/..}
18 TESTDIR=${abs_top_testdir:=$(dirname "$0")}
19 SRCDIR=${abs_top_srcdir:-$(dirname "$0")/..}
20
21 PATH=$ROOT/src/swtpm:$PATH
22
23 source ${abs_top_builddir:-$(dirname "$0")/..}/tests/test_config
24
25 SWTPM_SETUP=${ROOT}/src/swtpm_setup/swtpm_setup
26 SWTPM_CREATE_TPMCA=${SRCDIR}/samples/swtpm-create-tpmca
27 SWTPM_LOCALCA=${ROOT}/src/swtpm_localca/swtpm_localca
28 SWTPM=${ROOT}/src/swtpm/swtpm
29 SWTPM_IOCTL=${ROOT}/src/swtpm_ioctl/swtpm_ioctl
30
31 SWTPM_INTERFACE=socket+socket
32 SWTPM_SERVER_NAME=localhost
33 SWTPM_SERVER_PORT=65434
34 SWTPM_CTRL_PORT=65435
35
36 TCSD_LISTEN_PORT=65436
37
38 SRK_PASSWORD=srk
39 OWNER_PASSWORD=owner
40
41 workdir=$(mktemp -d)
42
43 TCSD_CONF=${workdir}/tcsd.conf
44 TCSD_SYSTEM_PS_FILE=${workdir}/system_ps_file
45 TCSD_PIDFILE=${workdir}/tcsd.pid
46 SWTPM_LOCALCA_DIR="${workdir}/my localca"
47 SWTPM_LOCALCA_CONF="${workdir}/my localca/swtpm-localca.conf"
48
49 # Captured TCSD file when using a SRK_PASSWORD=srk
50 TCSD_FILE="AQEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAABLwEAAAAAAwAAAAAAAAAAAAAA
51 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
52 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
53 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
54 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
55 AAAAAAAAAAAAAAAAAAAAAAAAAQEAAAARAAAAAAEAAAABAAMAAQAAAAwAAAgAAAAAAgAAAAAAAAAA
56 AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
57 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
58 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
59 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
60 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
61
62 function cleanup()
63 {
64 if [ -n "${TCSD_PID}" ]; then
65 kill_quiet -15 ${TCSD_PID}
66 fi
67 if [ -n "${SWTPM_PID}" ]; then
68 kill_quiet -9 ${SWTPM_PID}
69 fi
70 if [ -n "${BASH_PID}" ]; then
71 kill_quiet -9 ${BASH_PID}
72 fi
73 rm -rf "${workdir}"
74 }
75
76 trap "cleanup" SIGTERM EXIT
77 source ${TESTDIR}/common
78
79 PATH=${ROOT}/src/swtpm_bios:${ROOT}/src/swtpm_cert:${PATH}
80
81 # run the test with the given owner and SRK passwords
82 # @param1: owner password; empty means to use well known password
83 # @param2: SRK password; empty means to use well known password
84 # @param3: vTPM is a TPM 2.0
85 function run_test() {
86 local owner_password="$1"
87 local srk_password="$2"
88 local vtpm_is_tpm2="$3"
89
90 local params certinfo regex regexs fil i skip
91
92 rm -rf "${workdir}"/*
93
94 cat <<_EOF_ > "${workdir}/swtpm_setup.conf"
95 create_certs_tool=${SWTPM_LOCALCA}
96 create_certs_tool_config=${workdir}/swtpm-localca.conf
97 create_certs_tool_options=/dev/null
98 _EOF_
99
100 params=""
101 if [ -n "${owner_password}" ]; then
102 params="${params} --ownerpass ${owner_password}"
103 else
104 params="${params} --owner-well-known"
105 fi
106 params="${params} --srkpass ${srk_password}"
107
108 # First setup the TPM and take ownership of it and set SRK password
109 $SWTPM_SETUP \
110 --runas root \
111 --tpm-state "${workdir}" \
112 --logfile "${workdir}/logfile" \
113 --config "${workdir}/swtpm_setup.conf" \
114 --tpm "${SWTPM_EXE} socket ${SWTPM_TEST_SECCOMP_OPT}" \
115 --take-ownership \
116 ${params} >/dev/null
117
118 if [ $? -ne 0 ]; then
119 echo "Error: Could not run $SWTPM_SETUP."
120 echo "Setup Logfile:"
121 cat ${workdir}/logfile
122 exit 1
123 fi
124
125 echo "Successfully took ownership of TPM and set owner and SRK passwords."
126
127 run_swtpm ${SWTPM_INTERFACE} \
128 --flags not-need-init \
129 --tpmstate "dir=${workdir}"
130
131 swtpm_open_cmddev ${SWTPM_INTERFACE} 100
132
133 # Startup the TPM
134 res="$(swtpm_cmd_tx "${SWTPM_INTERFACE}" '\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01')"
135 exp=' 00 c4 00 00 00 0a 00 00 00 00'
136 if [ "$res" != "$exp" ]; then
137 echo "Error: Did not get expected result from TPM_Startup(ST_Clear)"
138 echo "expected: $exp"
139 echo "received: $res"
140 exit 1
141 fi
142
143 echo "$TCSD_FILE" | base64 -d > "${TCSD_SYSTEM_PS_FILE}"
144
145 # Setup the TCSD config file and start TCSD with it
146 cat <<_EOF_ > "${TCSD_CONF}"
147 port = ${TCSD_LISTEN_PORT}
148 system_ps_file = ${TCSD_SYSTEM_PS_FILE}
149 _EOF_
150
151 # Due to recent changes in tcsd we have to try with TSS_USER=tss and TSS_USER=root
152 # Before the following worked:
153 # - tss:tss 0600 for TSS_USER=tss and TSS_GROUP=tss
154 # - root:tss 0640 for TSS_USER=root and TSS_GROUP=tss
155 # After the changes:
156 # - root:tss 0640 for TSS_USER=tss and TSS_GROUP=tss
157 while :; do
158 chown ${TSS_USER}:${TSS_GROUP} "${TCSD_CONF}"
159 if [ "${TSS_USER}" == "${TSS_GROUP}" ]; then
160 chmod 0600 "${TCSD_CONF}"
161 else
162 chmod 0640 "${TCSD_CONF}"
163 fi
164
165 bash -c "TCSD_USE_TCP_DEVICE=1 TCSD_TCP_DEVICE_PORT=${SWTPM_SERVER_PORT} tcsd -c "${TCSD_CONF}" -e -f &>/dev/null & echo \$! > "${TCSD_PIDFILE}"; wait" &
166 BASH_PID=$!
167
168 if wait_for_file "${TCSD_PIDFILE}" 3; then
169 echo "Error: Could not get TCSD's PID file"
170 exit 1
171 fi
172
173 # wait for PID to be written
174 sleep 0.5
175 TCSD_PID=$(cat "${TCSD_PIDFILE}")
176 kill_quiet -0 "${TCSD_PID}"
177 if [ $? -ne 0 ]; then
178 # Try again with root unless we already tried
179 if [ "$TSS_USER" != "root" ]; then
180 TSS_USER="root"
181 continue
182 fi
183 echo "Error: TCSD with pid ${TCSD_PID} must have terminated"
184 exit 1
185 fi
186 break
187 done
188
189 ${SWTPM_CREATE_TPMCA} \
190 --dir "${SWTPM_LOCALCA_DIR}" \
191 --srk-password "${srk_password}" \
192 --register \
193 --group "${TSS_GROUP}" \
194 --tss-tcsd-port "${TCSD_LISTEN_PORT}" \
195 --outfile "${SWTPM_LOCALCA_CONF}" &>/dev/null
196
197 if [ $? -ne 0 ]; then
198 echo "Error: Could not create TPM CA"
199 exit 1
200 fi
201
202 for fil in \
203 swtpm-localca-rootca-cert.pem \
204 swtpm-localca-rootca-privkey.pem \
205 swtpm-localca-tpmca-cert.pem \
206 swtpm-localca-tpmca-pubkey.pem; do
207 if [ ! -r "${SWTPM_LOCALCA_DIR}/${fil}" ]; then
208 echo "Error: TPM CA tool did not create file ${fil}."
209 exit 1
210 fi
211 done
212
213 params=""
214 if [ -n "${srk_password}" ]; then
215 params="^parentkey_password ="
216 fi
217
218 for regex in \
219 "^statedir = " \
220 "^signingkey = " \
221 "^issuercert = " \
222 "^certserial = " \
223 "^TSS_TCSD_HOSTNAME = " \
224 "^TSS_TCSD_PORT = " \
225 ${params}; do
226 if [ -n "${regex}" ] && \
227 [ -z "$(grep -E "${regex}" "${SWTPM_LOCALCA_CONF}")" ]; then
228 echo "Error: Could not find regex '${line}' in CA config file."
229 cat "${SWTPM_LOCALCA_CONF}"
230 exit 1
231 fi
232 done
233
234 params=""
235 if [ ${vtpm_is_tpm2} -ne 0 ]; then
236 params="--tpm2"
237 skip=0
238 else
239 skip=7 # header in cert
240 fi
241
242 # make sure we can actually sign with this new certificate
243 ${SWTPM_LOCALCA} \
244 --type ek \
245 --ek x=739192d8f1004283957a7b1568d610b41c637ccc114aadcac4908c20456468fa,y=59f63ac06f8011f6fdd1460c6bc8e3e0a2d090d4fc188c7e04870e06795ce8ae \
246 --dir "${workdir}" --vmid test \
247 ${params} \
248 --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 00 \
249 --tpm-model swtpm --tpm-version 20170101 --tpm-manufacturer IBM \
250 --configfile "${SWTPM_LOCALCA_CONF}" \
251 --optsfile /dev/null
252 if [ $? -ne 0 ]; then
253 echo "Error: The CA could not sign with the new certificate"
254 exit 1
255 fi
256 if [ ! -f "${workdir}/ek.cert" ]; then
257 echo "Error: The CA did not produce a certificate"
258 exit 1
259 fi
260 # cert was for example 541 bytes long
261 if [ $(get_filesize "${workdir}/ek.cert") -lt 500 ]; then
262 echo "Error: The certificate's size is dubious"
263 ls -l "${workdir}/ek.cert"
264 exit 1
265 fi
266
267 # Check the contents of the certificate
268 certinfo=$(dd "if=${workdir}/ek.cert" bs=1 "skip=$skip" status=none | \
269 "$CERTTOOL" -i --inder)
270 regexs=('^[[:space:]]+2.23.133.8.1$'
271 '^[[:space:]]+directoryName:.*(,)?2.23.133.2.3=.*'
272 '^[[:space:]]+directoryName:.*(,)?2.23.133.2.2=.*'
273 '^[[:space:]]+directoryName:.*(,)?2.23.133.2.1=.*'
274 '^[[:space:]]+Certificate Authority \(CA\): FALSE$'
275 '^[[:space:]]+Unknown extension 2.5.29.9 \(not critical\):$'
276 '^[[:space:]]+Hexdump: 3019301706056781050210310e300c0c03322e3002010002020092$')
277 if [ ${vtpm_is_tpm2} -ne 0 ]; then
278 # TPM 2.0; due to ecc: Key agreement
279 regexs+=('^[[:space:]]+Key agreement\.$'
280 '^[[:space:]]+Signature Algorithm: RSA-SHA256$')
281 else
282 regexs+=('^[[:space:]]+Key encipherment\.$'
283 '^[[:space:]]+Signature Algorithm: RSA-SHA1$')
284 fi
285
286 for ((i=0; i < ${#regexs}; i++)); do \
287 if [ -n "${regexs[$i]}" ] && \
288 [ -z "$(echo "${certinfo}" | grep -E "${regexs[$i]}")" ]; then
289 echo "Error: Could not match regex '${regexs[$i]}' with certificate info:"
290 echo "${certinfo}"
291 exit 1
292 fi
293 done
294
295 # Send SIGTERM to TCSD
296 kill_quiet -15 "${TCSD_PID}"
297
298 # Shut down TPM
299 run_swtpm_ioctl "${SWTPM_INTERFACE}" -s
300 if [ $? -ne 0 ]; then
301 echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM."
302 exit 1
303 fi
304
305 if wait_process_gone "${SWTPM_PID}" 4; then
306 echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore."
307 exit 1
308 fi
309
310 if wait_process_gone "${SWTPM_PID}" 4; then
311 echo "Error: tcsd should not be running anymore."
312 exit 1
313 fi
314 } # run_test
315
316 run_test "${OWNER_PASSWORD}" "${SRK_PASSWORD}" 1
317 echo "Test 1: OK"
318
319 run_test "${OWNER_PASSWORD}" "${SRK_PASSWORD}" 0
320 echo "Test 2: OK"
321
322 run_test "" "${SRK_PASSWORD}" 1
323 echo "Test 3: OK"
324
325 run_test "" "${SRK_PASSWORD}" 0
326 echo "Test 4: OK"
327
328 exit 0