Skip to content

Fix swtpm UART read timeout to keep waiting until cumulative limit - #660

Merged
embhorn merged 1 commit into
wolfSSL:masterfrom
dgarske:swtpm_uart_timeout
Nov 2, 2026
Merged

embhorn merged 1 commit into
wolfSSL:masterfrom
dgarske:swtpm_uart_timeout

Conversation

@dgarske

@dgarske dgarske commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

The SWTPM UART transport configures the TTY with VMIN=0, VTIME=200, so read() returns 0 after 20 seconds with no data. Found on a NUCLEO-H563ZI running the wolftpm-examples STM32H5 fwTPM over the ST-LINK VCP, where RSA-2048 primary key generation takes longer than one period. Three related problems.

1. A per-read timeout was treated as EOF

SwTpmReceive() failed with TPM_RC_FAILURE on any zero-byte read, so a command slower than one VTIME period failed on the host even though the device completed it and WOLFTPM_SWTPM_UART_RX_TIMEOUT_SECS allowed longer. Because a primary key is derived from the NV seed, a given board then failed the same command every time.

2. A zero-byte read cannot distinguish a timeout from a hangup

A hung-up TTY also returns zero, immediately and indefinitely, so simply retrying a zero-byte read until the cumulative timeout spins on read() for the whole timeout once the device resets or the port is unplugged. SwTpmReceive() now waits with poll() and fails on POLLHUP/POLLERR, which means a zero-byte read can only follow a readable descriptor and is unambiguously EOF.

3. The cumulative timeout was not enforced at its stated value

The deadline was compared in whole seconds with <=, which allowed a further full read at the limit. It is now a monotonic millisecond deadline, equality counts as expiry, and each wait is capped at the time remaining.

WOLFTPM_SWTPM_UART_RX_TIMEOUT_SECS default is raised from 30 to 60 seconds. WOLFTPM_SWTPM_UART_VTIME is added, defaulting to the previous 200, so the per-read period is overridable. Socket transports are unchanged.

Testing

tests/swtpm_uart_unit_tests.c drives the receive path over a pseudo-terminal, with a forked child as the TPM: a response arriving many VTIME periods late, sustained silence, and peer closure, each checked for result code, elapsed time and CPU cost. The swtpm-uart CI job was compile-only and now runs it.

Configure sweep over --enable-swtpm=uart, the socket swtpm build and the default build.

Not re-tested on the NUCLEO-H563ZI since the receive path was rewritten around poll(). The earlier wrap/wrap_test, caps and examples/pqc runs on that board were against the previous implementation.

@dgarske dgarske assigned dgarske, embhorn and wolfSSL-Bot and unassigned dgarske Oct 30, 2026
@dgarske
dgarske requested a review from embhorn November 2, 2026 18:49

@embhorn embhorn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skoll Multi-Scan Review

Modes: review + review-security

Overall recommendation: REQUEST_CHANGES
Findings: 3 total — 3 posted, 0 skipped
3 finding(s) posted as inline comments (see file-level comments below)

Posted findings

  • [High] [review+review-security] Terminal hangup causes a busy retry loop on zero-byte UART read — src/tpm2_swtpm.c:225-230
  • [High] [review+review-security] Zero-byte retry can exceed the configured cumulative timeout — src/tpm2_swtpm.c:225-230
  • [Medium] [review] Add automated coverage for zero-byte UART reads — src/tpm2_swtpm.c:225-230

Review generated by Skoll

Comment thread src/tpm2_swtpm.c Resolved
Comment thread src/tpm2_swtpm.c Resolved
Comment thread src/tpm2_swtpm.c Resolved
@dgarske dgarske self-assigned this Nov 2, 2026
@dgarske
dgarske force-pushed the swtpm_uart_timeout branch from fb8a26b to 25ee20e Compare November 2, 2026 20:43
Copilot AI balanced review requested due to automatic review settings November 2, 2026 20:43
@dgarske dgarske removed their assignment Nov 2, 2026
@dgarske
dgarske requested a review from embhorn November 2, 2026 20:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The UART receive-timeout changes have no outstanding review issues blocking approval.

No open issues 🎉

What changed in this PR

Updates wolfTPM’s SWTPM UART transport to wait for slow TPM responses beyond a single serial-read timeout, while preserving socket transport behavior.

Changes:

  • Uses deadline-bounded polling for UART receives and raises the default cumulative timeout to 60 seconds.
  • Adds pseudo-terminal tests for delayed responses, silence, and hangups, and runs them in CI.
  • Documents the timeout settings and UART receive behavior.
File Description
tests/​swtpm_uart_unit_tests.c Adds hardware-free UART receive and CPU-use tests.
tests/​include.am Builds the UART tests with shortened timeouts.
src/​tpm2_swtpm.c Adds deadline-bounded polling and configurable read timing.
docs/​system-interfaces.md Documents timeout options and hangup handling.
configure.ac Adds a UART-specific build conditional.
.gitignore Ignores UART test binaries and logs.
.github/​workflows/​make-test-swtpm.yml Runs the UART tests in the existing CI configuration.

Review effort: Balanced

@embhorn
embhorn merged commit 96e7740 into wolfSSL:master Nov 2, 2026
244 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants