-
Notifications
You must be signed in to change notification settings - Fork 115
224 lines (203 loc) · 7.9 KB
/
Copy pathtpm-ssh.yml
File metadata and controls
224 lines (203 loc) · 7.9 KB
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
name: TPM SSH Test
on:
push:
branches: [ 'master', 'main', 'release/**' ]
pull_request:
branches: [ '*' ]
workflow_dispatch:
jobs:
test-tpm-ssh:
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
keytype: [ rsa, ecc ]
sim: [ ibmswtpm2, fwtpm ]
# raw: plain TPM host key (verified with OpenSSH).
# x509: TPM host key presented as an X.509 certificate, verified by the
# tpmcertserver/tpmcertclient example.
hostkey: [ raw, x509 ]
steps:
- uses: actions/checkout@v6
with:
path: wolfssh
- name: Clone wolfSSL
uses: actions/checkout@v6
with:
repository: wolfSSL/wolfssl
path: wolfssl
- name: Clone wolfTPM
uses: actions/checkout@v6
with:
repository: wolfSSL/wolftpm
path: wolftpm
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install -y libtool automake autoconf
sudo apt-get install -y build-essential git autoconf-archive \
libcmocka-dev libssl-dev uthash-dev libglib2.0-dev \
tpm2-tools openssh-client sshpass
- name: Build wolfSSL
run: |
cd wolfssl
./autogen.sh
# certgen/certreq/certext/cryptocb: generate the X.509 host certificate
# from the TPM key via the crypto callback.
EXTRA_CFLAGS="-DWC_RSA_NO_PADDING"
# The RSA x509v3-ssh-rsa host cert is SHA-1; modern wolfSSL otherwise
# rejects SHA-1 RSA signatures. Only needed for the RSA cells.
if [ "${{ matrix.keytype }}" = "rsa" ]; then
EXTRA_CFLAGS="$EXTRA_CFLAGS -DWC_SIG_MIN_HASH_TYPE=WC_HASH_TYPE_SHA"
fi
./configure --enable-wolftpm --enable-wolfssh --enable-keygen \
--enable-certgen --enable-certreq --enable-certext --enable-cryptocb \
CFLAGS="$EXTRA_CFLAGS"
make
sudo make install
sudo ldconfig
# The wolfTPM client library uses the SWTPM TCP transport (port 2321) for
# both simulators. The fwTPM build additionally produces fwtpm_server.
- name: Build wolfTPM (fwTPM)
if: matrix.sim == 'fwtpm'
run: |
cd wolftpm
./autogen.sh
./configure --enable-fwtpm --enable-swtpm
make
sudo make install
sudo ldconfig
- name: Start fwTPM simulator
if: matrix.sim == 'fwtpm'
run: |
cd wolftpm
./src/fwtpm/fwtpm_server &
echo "fwtpm_server started with PID: $!"
sleep 2
- name: Build wolfTPM (SWTPM)
if: matrix.sim == 'ibmswtpm2'
run: |
cd wolftpm
./autogen.sh
./configure --enable-swtpm
make
sudo make install
sudo ldconfig
- name: Start ibmswtpm2 simulator
if: matrix.sim == 'ibmswtpm2'
run: |
git clone https://github.com/kgoldman/ibmswtpm2
cd ibmswtpm2/src
make
./tpm_server &
echo "tpm_server started with PID: $!"
sleep 2
- name: Build wolfSSH
run: |
cd wolfssh
./autogen.sh
./configure --enable-tpm --enable-certs
make
sudo make install
sudo ldconfig
# Server host key resident in the TPM: the private key never enters RAM.
- name: Test TPM host key (${{ matrix.keytype }})
if: matrix.hostkey == 'raw'
run: |
cd wolftpm
./examples/keygen/keygen hostkey.bin -${{ matrix.keytype }} -t -eh
cd ../wolfssh
./examples/echoserver/echoserver -1 -p 22222 \
-G ../wolftpm/hostkey.bin &
echo "Echoserver (TPM ${{ matrix.keytype }} host key) PID: $!"
sleep 2
if [ "${{ matrix.keytype }}" = "ecc" ]; then
HKA=ecdsa-sha2-nistp256
else
HKA=rsa-sha2-256
fi
timeout 20 sshpass -p upthehill ssh -v -p 22222 \
-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
-o PreferredAuthentications=password -o PubkeyAuthentication=no \
-o HostKeyAlgorithms=$HKA \
jill@localhost exit > ssh_out.txt 2>&1 || true
echo "----- ssh output -----"
cat ssh_out.txt
grep -q "Authenticated to localhost" ssh_out.txt
# Server presents an X.509 host certificate whose private key lives in the
# TPM. The client verifies the certificate against it as the trusted CA and
# rejects a mismatched CA; the exchange hash is signed inside the TPM.
- name: Test TPM X.509 host certificate (${{ matrix.keytype }})
if: matrix.hostkey == 'x509'
run: |
cd wolfssh
./examples/tpmcertserver/tpmcertserver -k ${{ matrix.keytype }} \
-p 22223 > tpmcert_server.txt 2>&1 &
echo "tpmcertserver (X.509 ${{ matrix.keytype }}) PID: $!"
# RSA key generation inside the TPM can take longer than ECC.
for i in $(seq 1 40); do
if ss -ltn 2>/dev/null | grep -q ':22223'; then break; fi
sleep 1
done
./examples/tpmcertserver/tpmcertclient -A tpm-server-cert.der \
-p 22223 -h 127.0.0.1 > tpmcert_client.txt 2>&1
echo "----- server -----"; cat tpmcert_server.txt
echo "----- client -----"; cat tpmcert_client.txt
grep -q "verified server X.509 host certificate" tpmcert_client.txt
grep -q "Client connected and verified the TPM-backed host certificate" \
tpmcert_server.txt
# Negative test: a client that trusts an unrelated CA must reject the server.
- name: Test TPM X.509 host certificate rejects wrong CA (${{ matrix.keytype }})
if: matrix.hostkey == 'x509'
run: |
cd wolfssh
./examples/tpmcertserver/tpmcertserver -k ${{ matrix.keytype }} \
-p 22224 > tpmcert_server_neg.txt 2>&1 &
echo "tpmcertserver (X.509 neg ${{ matrix.keytype }}) PID: $!"
for i in $(seq 1 40); do
if ss -ltn 2>/dev/null | grep -q ':22224'; then break; fi
sleep 1
done
# keys/ca-cert-ecc.der is an unrelated CA; the self-signed host cert
# does not chain to it, so the client must refuse to connect.
if ./examples/tpmcertserver/tpmcertclient -A keys/ca-cert-ecc.der \
-p 22224 -h 127.0.0.1 > tpmcert_client_neg.txt 2>&1; then
echo "ERROR: client accepted a server with an untrusted CA"
cat tpmcert_client_neg.txt
exit 1
fi
echo "----- server -----"; cat tpmcert_server_neg.txt
echo "client correctly rejected the untrusted server:"
cat tpmcert_client_neg.txt
# Guard against a false pass: the server must have come up, and the
# client must have failed inside the SSH handshake (certificate
# rejection) rather than from a plain connection failure.
grep -q "Listening on port" tpmcert_server_neg.txt
grep -q "wolfSSH_connect failed" tpmcert_client_neg.txt
# Client public-key authentication with a TPM-resident key (RSA only).
- name: Test TPM client public-key auth
if: matrix.keytype == 'rsa' && matrix.hostkey == 'raw'
run: |
cd wolftpm
./examples/keygen/keygen keyblob.bin -rsa -t -pem -eh
ssh-keygen -f key.pem -i -m PKCS8 > ../wolfssh/key.ssh
cd ../wolfssh
./examples/echoserver/echoserver -1 -s key.ssh &
echo "Echoserver (authorized TPM client key) PID: $!"
sleep 2
timeout 20 ./examples/client/client -i ../wolftpm/keyblob.bin \
-u hansel -K ThisIsMyKeyAuth
- name: Archive test artifacts
if: always()
uses: actions/upload-artifact@v7
with:
name: test-artifacts-${{ matrix.keytype }}-${{ matrix.sim }}-${{ matrix.hostkey }}
if-no-files-found: ignore
path: |
wolftpm/hostkey.bin
wolfssh/ssh_out.txt
wolfssh/tpmcert_server.txt
wolfssh/tpmcert_client.txt
wolfssh/tpmcert_server_neg.txt
wolfssh/tpmcert_client_neg.txt