Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 76 additions & 68 deletions .github/workflows/tpm-ssh.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,17 @@ jobs:
test-tpm-ssh:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
keytype: [ rsa, ecc ]
sim: [ ibmswtpm2, fwtpm ]

steps:
- uses: actions/checkout@v6
with:
path: wolfssh

# Clone dependencies
- name: Clone wolfSSL
uses: actions/checkout@v6
with:
Expand All @@ -29,48 +34,64 @@ jobs:
repository: wolfSSL/wolftpm
path: wolftpm

# Install dependencies
- 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
tpm2-tools openssh-client sshpass

# Clone, build, and start TPM Simulator
- name: Clone and Build TPM Simulator
- name: Build wolfSSL
run: |
git clone https://github.com/kgoldman/ibmswtpm2
cd ibmswtpm2/src
cd wolfssl
./autogen.sh
./configure --enable-wolftpm --enable-wolfssh --enable-keygen \
CFLAGS="-DWC_RSA_NO_PADDING"
make
./tpm_server &
sleep 2
cd ../..
sudo make install
sudo ldconfig

# Build and install wolfSSL
- name: Build wolfSSL
# 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 wolfssl
cd wolftpm
./autogen.sh
./configure --enable-wolftpm --enable-wolfssh
./configure --enable-fwtpm --enable-swtpm
make
sudo make install
sudo ldconfig
cd ..

# Build and install wolfTPM
- name: Build wolfTPM
- 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
cd ..

# Build wolfSSH
- 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
Expand All @@ -79,66 +100,53 @@ jobs:
make
sudo make install
sudo ldconfig
cd ..

# Test TPM SSH Default Password
- name: Test TPM SSH Default Password
# Server host key resident in the TPM: the private key never enters RAM.
- name: Test TPM host key (${{ matrix.keytype }})
run: |
# Generate key with default password
cd wolftpm
./examples/keygen/keygen keyblob1.bin -rsa -t -pem -eh
cp key.pem key1.pem # Save the key for first test

# Convert key to SSH format
ssh-keygen -f key1.pem -i -m PKCS8 > ../wolfssh/key1.ssh
cd ..

# Start echoserver and wait for it to be ready
cd wolfssh
./examples/echoserver/echoserver -1 -s key1.ssh &
echo "Echoserver started with PID: $!"
./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
cd ..

# Test client connection with default password
cd wolfssh
./examples/client/client -i ../wolftpm/keyblob1.bin -u hansel -K ThisIsMyKeyAuth
cd ..

# Test the TPM SSH Custom Password
- name: Test TPM SSH Custom Password
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

# Client public-key authentication with a TPM-resident key (RSA only).
- name: Test TPM client public-key auth
if: matrix.keytype == 'rsa'
run: |
# Test with custom password
cd wolftpm
./examples/keygen/keygen keyblob2.bin -rsa -t -pem -eh -auth=custompassword
cp key.pem key2.pem # Save the key for second test

# Convert key to SSH format
ssh-keygen -f key2.pem -i -m PKCS8 > ../wolfssh/key2.ssh
cd ..

# Start echoserver and wait for it to be ready
cd wolfssh
./examples/echoserver/echoserver -1 -s key2.ssh &
echo "Echoserver started with PID: $!"
./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
cd ..

# Test with custom password
cd wolfssh
./examples/client/client -i ../wolftpm/keyblob2.bin -u hansel -K custompassword
cd ..
./examples/client/client -i ../wolftpm/keyblob.bin -u hansel \
-K ThisIsMyKeyAuth

# Archive artifacts for debugging
- name: Archive test artifacts
if: always()
uses: actions/upload-artifact@v7
with:
name: test-artifacts
name: test-artifacts-${{ matrix.keytype }}-${{ matrix.sim }}
path: |
wolftpm/keyblob1.bin
wolftpm/keyblob2.bin
wolftpm/key1.pem
wolftpm/key2.pem
wolfssh/key1.ssh
wolfssh/key2.ssh
wolftpm/hostkey.bin
wolfssh/ssh_out.txt
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,40 @@ If you used a custom password for keygen you must specify the password you used:

$ ./examples/client/client -i ../wolfTPM/keyblob.bin -u hansel -K <custompassword>

TPM SERVER HOST KEY (ECDSA / RSA)
=================================

The server can also keep its own host key inside the TPM so the host private
key is never present in RAM. Build wolfSSL, wolfTPM, and wolfSSH the same way
as above (`--enable-tpm`). Both ECDSA and RSA host keys are supported.

Generate a host key blob under the endorsement hierarchy (ECC or RSA):

$ ./examples/keygen/keygen hostkey.bin -ecc -t -eh
$ ./examples/keygen/keygen hostkey.bin -rsa -t -eh

Start the echoserver with the TPM-resident host key using `-G`:

$ ./examples/echoserver/echoserver -G ../wolfTPM/hostkey.bin

The server loads the key blob into the TPM, registers it with
`wolfSSH_CTX_UseTpmHostKey()`, and advertises the matching host key algorithm
(`ecdsa-sha2-nistp256` or `rsa-sha2-256`). The exchange hash is signed by the
TPM; the host private key never leaves it. Any client that accepts the host
key can connect:

$ ssh -o HostKeyAlgorithms=ecdsa-sha2-nistp256 user@host
$ ssh -o HostKeyAlgorithms=rsa-sha2-256 user@host

To integrate this into your own server, provision the key once into the TPM,
load its handle at boot into a `WOLFTPM2_KEY`, and register it:

wolfSSH_CTX_UseTpmHostKey(ctx, &tpmDev, &tpmKey);

Note: RSA host keys are signed with `rsa-sha2-256`. The default echoserver key
auth produced by keygen is `ThisIsMyKeyAuth` (override with the `-G` example's
`ECHOSERVER_TPM_KEY_AUTH`).

WOLFSSH APPLICATIONS
====================

Expand Down
Loading
Loading