mirror of https://github.com/wolfSSL/wolfssh.git
219 lines
7.5 KiB
YAML
219 lines
7.5 KiB
YAML
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 "client correctly rejected the untrusted server:"
|
|
cat 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
|