Skip to content

Commit cd1a7b5

Browse files
add uart CI test
1 parent dc2caed commit cd1a7b5

File tree

3 files changed

+279
-2
lines changed

3 files changed

+279
-2
lines changed
Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
name: Test UART Communication with SWTPM
2+
3+
on:
4+
push:
5+
branches: [ 'master', 'main', 'release/**' ]
6+
pull_request:
7+
branches: [ 'master', 'main', 'release/**' ]
8+
workflow_dispatch:
9+
10+
jobs:
11+
test-uart-swtpm:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v4
17+
18+
- name: Install basic dependencies
19+
run: |
20+
sudo apt-get update
21+
sudo apt-get install -y \
22+
automake \
23+
autotools-dev \
24+
libtool \
25+
pkg-config \
26+
gcc \
27+
make \
28+
git \
29+
socat \
30+
strace \
31+
acl
32+
33+
- name: Install swtpm
34+
run: |
35+
sudo apt-get install -y swtpm swtpm-tools
36+
37+
- name: Setup wolfSSL
38+
uses: actions/checkout@v4
39+
with:
40+
repository: wolfssl/wolfssl
41+
path: wolfssl
42+
43+
- name: Build wolfSSL
44+
working-directory: ./wolfssl
45+
run: |
46+
./autogen.sh
47+
./configure --enable-wolftpm --prefix=${GITHUB_WORKSPACE}/wolfssl-install
48+
make -j$(nproc)
49+
make install
50+
51+
- name: Start swtpm in socket mode
52+
run: |
53+
mkdir -p /tmp/swtpm-state
54+
55+
# Start swtpm with socket backend (this works reliably in GitHub Actions)
56+
swtpm socket \
57+
--tpm2 \
58+
--tpmstate dir=/tmp/swtpm-state \
59+
--ctrl type=tcp,port=2322 \
60+
--server type=tcp,port=2321 \
61+
--flags not-need-init &
62+
SWTPM_PID=$!
63+
echo $SWTPM_PID > /tmp/swtpm.pid
64+
65+
# Give swtpm time to start
66+
sleep 3
67+
68+
# Verify swtpm is running and socket is accessible
69+
ps aux | grep swtpm | grep -v grep || exit 1
70+
timeout 2 bash -c 'until nc -z localhost 2321; do sleep 0.1; done' || exit 1
71+
72+
- name: Create UART bridge
73+
id: uart
74+
run: |
75+
# Create a PTY for wolfTPM to connect to as UART device
76+
# Use socat to create a PTY with proper permissions
77+
socat -d -d pty,raw,echo=0,link=/tmp/tpm-uart-client,perm=0666 pty,raw,echo=0,link=/tmp/tpm-uart-server,perm=0666 &
78+
SOCAT_PID=$!
79+
echo $SOCAT_PID > /tmp/socat.pid
80+
sleep 2
81+
82+
# Get the actual PTY device names
83+
CLIENT_PTY=$(readlink -f /tmp/tpm-uart-client)
84+
SERVER_PTY=$(readlink -f /tmp/tpm-uart-server)
85+
86+
echo "client_pty=$CLIENT_PTY" >> $GITHUB_OUTPUT
87+
echo "server_pty=$SERVER_PTY" >> $GITHUB_OUTPUT
88+
89+
echo "Client PTY (for wolfTPM): $CLIENT_PTY"
90+
echo "Server PTY (bridge endpoint): $SERVER_PTY"
91+
92+
# Verify PTYs exist
93+
ls -la $CLIENT_PTY $SERVER_PTY || exit 1
94+
95+
- name: Bridge socket to UART
96+
run: |
97+
SERVER_PTY="${{ steps.uart.outputs.server_pty }}"
98+
99+
# Ensure swtpm socket is ready before starting bridge
100+
echo "Waiting for swtpm socket to be ready..."
101+
timeout 5 bash -c 'until nc -z localhost 2321; do sleep 0.1; done' || {
102+
echo "ERROR: swtpm socket not ready!"
103+
exit 1
104+
}
105+
106+
# Bridge between swtpm socket (port 2321) and the server PTY
107+
# Use TCP-CONNECT to connect to swtpm and bridge to PTY
108+
# Add buffering and proper options for reliable data transfer
109+
echo "Starting bridge from PTY $SERVER_PTY to socket localhost:2321"
110+
# Use OPEN to open the existing PTY device directly
111+
# Add readbytes=0 to read all available data, and setsockopt to handle socket properly
112+
socat OPEN:$SERVER_PTY,raw,echo=0,readbytes=0 TCP:localhost:2321,keepalive,so-keepalive > /tmp/bridge.log 2>&1 &
113+
BRIDGE_PID=$!
114+
echo $BRIDGE_PID > /tmp/bridge.pid
115+
116+
sleep 2
117+
118+
# Verify bridge is running
119+
if ! ps -p $BRIDGE_PID > /dev/null 2>&1; then
120+
echo "ERROR: Bridge process died!"
121+
echo "Bridge log:"
122+
cat /tmp/bridge.log || true
123+
exit 1
124+
fi
125+
126+
# Also check if it shows up in ps
127+
if ! ps aux | grep "socat.*2321" | grep -v grep > /dev/null; then
128+
echo "WARNING: Bridge not found in ps, but PID file exists"
129+
echo "Checking bridge log:"
130+
cat /tmp/bridge.log || true
131+
fi
132+
133+
echo "Bridge is running (PID: $BRIDGE_PID), connecting PTY $SERVER_PTY to socket localhost:2321"
134+
135+
- name: Build wolfTPM with UART support
136+
env:
137+
CLIENT_PTY: ${{ steps.uart.outputs.client_pty }}
138+
run: |
139+
cd ${{ github.workspace }}
140+
./autogen.sh
141+
# Set UART device path via CPPFLAGS
142+
# TPM2_SWTPM_PORT is already set by configure, so we only need to set HOST
143+
# The quotes need to be passed through correctly to the C preprocessor
144+
echo "Building with UART device: $CLIENT_PTY"
145+
./configure \
146+
--enable-swtpm=uart \
147+
--enable-debug \
148+
--with-wolfcrypt=${GITHUB_WORKSPACE}/wolfssl-install \
149+
CPPFLAGS="-DTPM2_SWTPM_HOST=\"${CLIENT_PTY}\""
150+
make -j$(nproc)
151+
152+
# Verify the define by checking the compiled code
153+
echo "Verifying TPM2_SWTPM_HOST define..."
154+
strings src/.libs/libwolftpm.so 2>/dev/null | grep -E "(ttyS0|pts)" | head -5 || echo "Cannot verify from library"
155+
156+
- name: Verify UART setup
157+
env:
158+
CLIENT_PTY: ${{ steps.uart.outputs.client_pty }}
159+
SERVER_PTY: ${{ steps.uart.outputs.server_pty }}
160+
run: |
161+
echo "Verifying UART setup..."
162+
echo "Client PTY: $CLIENT_PTY"
163+
echo "Server PTY: $SERVER_PTY"
164+
165+
# Verify PTYs are still accessible
166+
[ -c "$CLIENT_PTY" ] || (echo "Client PTY not found!" && exit 1)
167+
[ -c "$SERVER_PTY" ] || (echo "Server PTY not found!" && exit 1)
168+
169+
# Verify swtpm is still running
170+
ps aux | grep swtpm | grep -v grep || (echo "swtpm not running!" && exit 1)
171+
172+
# Verify bridge is running
173+
ps aux | grep "socat.*2321" | grep -v grep || (echo "bridge not running!" && exit 1)
174+
175+
# Test socket connectivity to swtpm
176+
timeout 2 bash -c 'until nc -z localhost 2321; do sleep 0.1; done' || (echo "Cannot connect to swtpm socket!" && exit 1)
177+
178+
echo "UART setup verified successfully"
179+
180+
- name: Run UART communication test
181+
env:
182+
CLIENT_PTY: ${{ steps.uart.outputs.client_pty }}
183+
run: |
184+
cd ${{ github.workspace }}
185+
186+
# Build the caps example with the same CPPFLAGS to ensure TPM2_SWTPM_HOST is defined
187+
cd examples/wrap
188+
# Re-export the CPPFLAGS to ensure the example build uses them
189+
export CPPFLAGS="-DTPM2_SWTPM_HOST=\"${CLIENT_PTY}\""
190+
echo "Building caps with CPPFLAGS: $CPPFLAGS"
191+
make caps CPPFLAGS="$CPPFLAGS"
192+
193+
echo "Running UART communication test..."
194+
echo "Using UART device: $CLIENT_PTY"
195+
196+
# Verify bridge is still running
197+
echo "Checking bridge status..."
198+
if [ -f /tmp/bridge.pid ]; then
199+
BRIDGE_PID=$(cat /tmp/bridge.pid)
200+
if ps -p $BRIDGE_PID > /dev/null 2>&1; then
201+
echo "Bridge is running (PID: $BRIDGE_PID)"
202+
else
203+
echo "WARNING: Bridge PID file exists but process is not running"
204+
echo "Bridge log:"
205+
cat /tmp/bridge.log 2>/dev/null || echo "No bridge log found"
206+
fi
207+
else
208+
echo "WARNING: Bridge PID file not found"
209+
fi
210+
ps aux | grep "socat.*2321" | grep -v grep || echo "WARNING: Bridge process not found in ps"
211+
212+
# Test basic PTY connectivity
213+
echo "Testing PTY connectivity..."
214+
timeout 1 cat $CLIENT_PTY > /dev/null 2>&1 || echo "PTY read test (may timeout, that's ok)"
215+
216+
# Run the test with a timeout and capture all output
217+
# The test should connect to the PTY as if it were a UART device
218+
echo "Starting caps test..."
219+
set +e # Don't exit on error so we can capture output
220+
# Run with stderr to stdout to capture all output
221+
timeout 30 ./caps > /tmp/caps_output.log 2>&1
222+
CAPS_RC=$?
223+
set -e
224+
225+
# Also check if we can manually test the connection
226+
echo "Testing manual connection..."
227+
echo "test" | timeout 1 cat $CLIENT_PTY > /dev/null 2>&1 || echo "Manual PTY test (may timeout)"
228+
229+
if [ $CAPS_RC -ne 0 ]; then
230+
echo "Test failed with exit code $CAPS_RC"
231+
echo "=== Test output ==="
232+
cat /tmp/caps_output.log || true
233+
echo "=== Checking processes ==="
234+
echo "swtpm:"
235+
ps aux | grep swtpm | grep -v grep || echo "swtpm is not running"
236+
echo "bridge:"
237+
ps aux | grep "socat.*2321" | grep -v grep || echo "bridge is not running"
238+
echo "PTY pair:"
239+
ps aux | grep "socat.*pty" | grep -v grep || echo "PTY pair is not running"
240+
echo "PTY devices:"
241+
ls -la $CLIENT_PTY || echo "Client PTY not found"
242+
exit 1
243+
else
244+
echo "=== Test output ==="
245+
cat /tmp/caps_output.log || true
246+
fi
247+
248+
echo "UART communication test passed!"
249+
250+
- name: Cleanup
251+
if: always()
252+
run: |
253+
# Kill bridge
254+
if [ -f /tmp/bridge.pid ]; then
255+
kill $(cat /tmp/bridge.pid) 2>/dev/null || true
256+
fi
257+
258+
# Kill socat PTY pair
259+
if [ -f /tmp/socat.pid ]; then
260+
kill $(cat /tmp/socat.pid) 2>/dev/null || true
261+
fi
262+
263+
# Kill swtpm
264+
if [ -f /tmp/swtpm.pid ]; then
265+
kill $(cat /tmp/swtpm.pid) 2>/dev/null || true
266+
pkill -f "swtpm socket" 2>/dev/null || true
267+
fi
268+
269+
# Clean up PTY links
270+
rm -f /tmp/tpm-uart-server /tmp/tpm-uart-client

src/tpm2_swtpm.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,14 @@
4747
#ifdef WOLFTPM_ZEPHYR
4848
#include <zephyr/posix/unistd.h>
4949
#include <zephyr/net/socket.h>
50+
#include <zephyr/posix/sys/select.h>
5051
#elif defined(HAVE_UNISTD_H)
5152
#include <unistd.h>
5253
#endif
54+
/* select() is used for TCP socket mode, not UART mode */
55+
#if !defined(WOLFTPM_ZEPHYR) && !defined(WOLFTPM_SWTPM_UART) && !defined(WOLFTPM_SWTPM_UARTNS550)
56+
#include <sys/select.h>
57+
#endif
5358
#include <errno.h>
5459
#include <string.h> /* necessary for memset */
5560
#include <stdio.h> /* standard in/out procedures */
@@ -583,7 +588,7 @@ int TPM2_SWTPM_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet)
583588

584589
#if !defined(WOLFTPM_SWTPM_UARTNS550)
585590
if (ctx->tcpCtx.fd < 0) {
586-
rc = SwTpmConnect(ctx, TPM2_SWTPM_HOST, XSTRINGIFY(TPM2_SWTPM_PORT));
591+
rc = SwTpmConnect(ctx, TPM2_SWTPM_HOST, TPM2_SWTPM_PORT);
587592
}
588593
#else
589594
if (ctx->tcpCtx.setup == 0) {

wolftpm/tpm2_types.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,9 +298,11 @@ typedef int64_t INT64;
298298

299299
/* Helper to convert macro to string */
300300
#ifndef XSTRINGIFY
301-
#define XSTRINGIFY(s) STRINGIFY(s)
301+
#ifndef STRINGIFY
302302
#define STRINGIFY(s) #s
303303
#endif
304+
#define XSTRINGIFY(s) STRINGIFY(s)
305+
#endif
304306

305307
/* ---------------------------------------------------------------------------*/
306308
/* TPM HARDWARE TYPE */

0 commit comments

Comments
 (0)